// 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);
}