mirror of https://github.com/BOINC/boinc.git
372 lines
8.8 KiB
C++
372 lines
8.8 KiB
C++
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
// 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <setjmp.h>
|
|
|
|
#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 <jpeglib.h>
|
|
}
|
|
#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;i<PANEL_MAX_LINES;i++) {
|
|
memset(&(text[i][0]),0,256);
|
|
}
|
|
}
|
|
|
|
void MOVING_TEXT_PANEL::init(
|
|
float* p, float* s, COLOR& c, double d, double ch, double lw, double ls, double m
|
|
) {
|
|
memcpy(pos, p, sizeof(pos));
|
|
memcpy(base_pos, p, sizeof(base_pos));
|
|
memcpy(size, s, sizeof(size));
|
|
color = c;
|
|
theta = 0;
|
|
dtheta = d;
|
|
char_height = ch;
|
|
line_width = lw;
|
|
line_spacing = ls;
|
|
margin = m;
|
|
memset(text, 0, sizeof(text));
|
|
}
|
|
|
|
// draw a rectangle of the given color in the XY plane
|
|
// and draw the given test in it
|
|
//
|
|
void MOVING_TEXT_PANEL::draw() {
|
|
COLOR side_color = color;
|
|
GLfloat pos0[3], pos1[3], pos2[3], pos3[3];
|
|
memcpy(pos0, pos, sizeof(pos0));
|
|
memcpy(pos1, pos, sizeof(pos0));
|
|
pos1[0] += size[0];
|
|
memcpy(pos2, pos1, sizeof(pos0));
|
|
pos2[1] += size[1];
|
|
memcpy(pos3, pos2, sizeof(pos0));
|
|
pos3[0] -= size[0];
|
|
mode_unshaded();
|
|
glColor4fv(&color.r);
|
|
glBegin(GL_QUADS);
|
|
glVertex3fv(pos0);
|
|
glVertex3fv(pos1);
|
|
glVertex3fv(pos2);
|
|
glVertex3fv(pos3);
|
|
|
|
// draw flanges
|
|
//
|
|
side_color.r /= 2;
|
|
side_color.g /= 2;
|
|
side_color.b /= 2;
|
|
glColor4fv(&side_color.r);
|
|
GLfloat posa0[3], posa1[3], posa2[3], posa3[3];
|
|
memcpy(posa0, pos0, sizeof(pos0));
|
|
memcpy(posa1, pos1, sizeof(pos0));
|
|
memcpy(posa2, pos2, sizeof(pos0));
|
|
memcpy(posa3, pos3, sizeof(pos0));
|
|
posa0[2] -= .2;
|
|
posa1[2] -= .2;
|
|
posa2[2] -= .2;
|
|
posa3[2] -= .2;
|
|
glVertex3fv(pos0);
|
|
glVertex3fv(pos1);
|
|
glVertex3fv(posa1);
|
|
glVertex3fv(posa0);
|
|
glVertex3fv(pos1);
|
|
glVertex3fv(pos2);
|
|
glVertex3fv(posa2);
|
|
glVertex3fv(posa1);
|
|
glVertex3fv(pos2);
|
|
glVertex3fv(pos3);
|
|
glVertex3fv(posa3);
|
|
glVertex3fv(posa2);
|
|
glVertex3fv(pos3);
|
|
glVertex3fv(pos0);
|
|
glVertex3fv(posa0);
|
|
glVertex3fv(posa3);
|
|
glEnd();
|
|
|
|
pos3[0] += margin;
|
|
pos3[1] -= (margin+char_height);
|
|
pos3[2] += 0.01;
|
|
glColor3f(1, 1, 1);
|
|
for (int i=0; i<PANEL_MAX_LINES; i++) {
|
|
if (strlen(text[i])) {
|
|
draw_text(pos3, char_height, line_width, line_spacing, text[i]);
|
|
}
|
|
pos3[1] -= line_spacing;
|
|
}
|
|
}
|
|
|
|
void MOVING_TEXT_PANEL::set_text(int lineno, const char* str) {
|
|
char buf[8192];
|
|
strcpy(buf, str);
|
|
char* p = buf;
|
|
char* q = strchr(p, '\n');
|
|
while (p) {
|
|
if (q) *q = 0;
|
|
strlcpy(text[lineno++], p, 256);
|
|
if (!q) break;
|
|
p = q+1;
|
|
q = strchr(p, '\n');
|
|
}
|
|
}
|
|
|
|
void MOVING_TEXT_PANEL::move(double dt) {
|
|
pos[0] = base_pos[0] + sin(theta);
|
|
pos[1] = base_pos[1];
|
|
pos[2] = base_pos[2] + cos(theta);
|
|
theta += dtheta*dt;
|
|
}
|
|
|
|
void MOVING_TEXT_PANEL::get_pos(int lineno, float* p) {
|
|
memcpy(p, pos, sizeof(pos));
|
|
p[0] += margin;
|
|
p[1] += (size[1] - margin - lineno*line_spacing);
|
|
}
|
|
|
|
static int compare_tp(const void* p1, const void* p2) {
|
|
const MOVING_TEXT_PANEL* tp1=(const MOVING_TEXT_PANEL*)p1, *tp2 = (const MOVING_TEXT_PANEL*)p2;
|
|
if (tp1->pos[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);
|
|
}
|
|
|