// This file is part of BOINC. // http://boinc.berkeley.edu // Copyright (C) 2008 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License // as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // BOINC is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . // The part of BOINC's graphics utilities that uses GLUT char-drawing #if defined(_WIN32) && !defined(__STDWX_H__) && !defined(_BOINC_WIN_) && !defined(_AFX_STDAFX_H_) #include "boinc_win.h" #else #include "config.h" #endif #include #include #include #include #include #ifdef _WIN32 #ifdef __cplusplus extern "C" { #include "jpeglib.h" } #else #include "jpeglib.h" #endif #include "bmplib.h" #include "tgalib.h" #endif #ifndef _WIN32 #ifdef __APPLE__ #undef HAVE_STDLIB_H /* Avoid compiler warning (redefined in jconfig,h) */ #endif extern "C"{ #include } #endif #include "boinc_gl.h" #include "boinc_glut.h" #include "filesys.h" #include "str_util.h" #include "str_replace.h" #include "gutil.h" #define STROKE_SCALE 120 // GLUT stroke characters are about 120 units high GLfloat text_width(const char* text) { GLfloat sum = 0; for (const char* p = text; *p; p++) { sum += glutStrokeWidth(GLUT_STROKE_ROMAN, *p); } return sum/STROKE_SCALE; } static void draw_text_line_aux(const char *text) { for (const char* p = text; *p; p++) { glutStrokeCharacter(GLUT_STROKE_ROMAN, *p); } } static void draw_text_start(GLfloat* pos, GLfloat char_height, GLfloat line_width) { glLineWidth(line_width); glPushMatrix(); glTranslatef(pos[0], pos[1], pos[2]); glRasterPos3d(pos[0],pos[1],pos[2]); float w = char_height/STROKE_SCALE; glScalef(w, w, w); } static void draw_text_end() { glPopMatrix(); } // draw a line of text in the XY plane at the given starting position, // character height, and line width. void draw_text_simple(const char* text, float line_width, float char_height) { glLineWidth(line_width); float w = char_height/STROKE_SCALE; glScalef(w, w, w); draw_text_line_aux(text); } void draw_text_line( GLfloat* _pos, GLfloat char_height, GLfloat line_width, const char *text, int justify ) { GLfloat pos[3]; GLfloat w; memcpy(pos, _pos, sizeof(pos)); switch(justify) { case TEXT_LEFT: break; case TEXT_CENTER: w = text_width(text); pos[0] -= w/2; break; case TEXT_RIGHT: w = text_width(text); pos[0] -= w; break; } draw_text_start(pos, char_height, line_width); draw_text_line_aux(text); draw_text_end(); } // draw rotated text void draw_rotated_text( GLfloat* pos, GLfloat height, GLfloat width, GLfloat /*spacing*/, const char *text, GLfloat rotation, GLfloat* rotation_vector) { draw_text_start(pos, height, width); glRotatef(rotation,rotation_vector[0],rotation_vector[1],rotation_vector[2]); draw_text_line_aux(text); draw_text_end(); } // draw multiple lines of text // void draw_text( GLfloat* _pos, GLfloat char_height, GLfloat line_width, GLfloat line_spacing, const char* text ) { char* q, *p; char buf[4096]; GLfloat pos[3]; memcpy(pos, _pos, sizeof(pos)); strlcpy(buf, text, 4096); p = buf; while (*p) { q = strchr(p, '\n'); if (q) *q = 0; draw_text_start(pos, char_height, line_width); draw_text_line_aux(p); draw_text_end(); pos[1] -= line_spacing; if (!q) break; p = q+1; } } void draw_text_new_3d( GLfloat* _pos, GLfloat /*char_height*/, GLfloat /*line_width*/, GLfloat line_spacing, const char* text ) { char* q, *p; char buf[4096]; GLfloat pos[3]; memcpy(pos, _pos, sizeof(pos)); strlcpy(buf, text, 4096); p = buf; glPushMatrix(); glTranslatef(pos[0], pos[1], pos[2]); while (*p) { q = strchr(p, '\n'); if (q) *q = 0; glRasterPos3d(pos[0],pos[1],pos[2]); print_text(p); pos[1] -= line_spacing; if (!q) break; p = q+1; } glPopMatrix(); } void draw_text_new( GLfloat* _pos, GLfloat /*char_height*/, GLfloat /*line_width*/, GLfloat line_spacing, const char* text ) { char *q, *p; char buf[4096]; GLfloat pos[3]; memcpy(pos,_pos,sizeof(pos)); strlcpy(buf, text, 4096); p=buf; int viewport[4]; get_viewport(viewport); while(*p) { q = strchr(p, '\n'); if (q) *q = 0; glRasterPos3d(pos[0],pos[1],pos[2]); print_text(p); pos[1] -= line_spacing; if (!q) break; p = q+1; } } void draw_text_right( GLfloat* _pos, GLfloat char_height, GLfloat line_width, GLfloat line_spacing, const char* text ) { char *q, *p; char buf[4096]; GLfloat pos[3]; memcpy(pos,_pos,sizeof(pos)); float orig = pos[0]; strlcpy(buf, text, 4096); p=buf; float w; while (*p) { q = strchr(p, '\n'); if (q) *q = 0; w = text_width(p)/66.5f; pos[0] -= w; draw_text_start(pos, char_height, line_width); draw_text_line_aux(p); draw_text_end(); pos[1] -= line_spacing; pos[0]=orig; if (!q) break; p = q+1; } } MOVING_TEXT_PANEL::MOVING_TEXT_PANEL() : theta(0), dtheta(0), color(0), char_height(0), line_width(0), line_spacing(0), margin(0) { int i; for (i=0;i<3;i++) { base_pos[i]=size[i]=0; } for (i=0;ipos[2] > tp2->pos[2]) return 1; if (tp2->pos[2] > tp1->pos[2]) return -1; return 0; } void MOVING_TEXT_PANEL::sort(MOVING_TEXT_PANEL* tp, int n) { qsort(tp, n, sizeof(MOVING_TEXT_PANEL), compare_tp); }