/* * NodeText.cpp * * Copyright (C) 1999 Stephen F. White * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file "COPYING" for details); if * not, write to the Free Software Foundation, Inc., 675 Mass Ave, * Cambridge, MA 02139, USA. */ #include #include "stdafx.h" #include "NodeText.h" #include "Proto.h" #include "FieldValue.h" #include "MFString.h" #include "SFNode.h" #include "MFFloat.h" #include "SFFloat.h" #include "SFString.h" #include "SFBool.h" #include "Scene.h" #include "NodeFontStyle.h" #include "FontInfo.h" #include "Util.h" ProtoText::ProtoText(Scene *scene) : Proto(scene, "Text") { string.set( addExposedField(MFSTRING, "string", new MFString())); fontStyle.set( addExposedField(SFNODE, "fontStyle", new SFNode(NULL), NODE_FONT_STYLE)); length.set( addExposedField(MFFLOAT, "length", new MFFloat(), new SFFloat(0.0f))); maxExtent.set( addExposedField(SFFLOAT, "maxExtent", new SFFloat(0.0f), new SFFloat(0.0f))); } Node * ProtoText::create(Scene *scene) { return new NodeText(scene, this); } NodeText::NodeText(Scene *scene, Proto *def) : Node(scene, def) { } #ifdef HAVE_LIBGLUT #include "GL/glut.h" // yet another ugly textnode implementation 8-( void NodeText::draw() { MFString *mfstring = string(); NodeFontStyle *fontStyle = (NodeFontStyle *) ((SFNode *) getField(fontStyle_Index(),true))->getValue(); float fsize = 1; if (fontStyle) fsize = fontStyle->size()->getValue(); GLfloat diff_color[4]; GLfloat em_color[4]; glGetMaterialfv(GL_FRONT, GL_DIFFUSE, diff_color); glGetMaterialfv(GL_FRONT, GL_EMISSION, em_color); GLfloat color[4]; for (int i = 0; i < 3; i++) { color[i] = em_color[i]; if (_scene->getNumLights() != 0) color[i] += diff_color[i]; if (color[i] > 1) color[i] = 1 ; } color[3] = diff_color[3]; glPushAttrib(GL_ENABLE_BIT); glDisable(GL_LIGHTING); glDisable(GL_BLEND); Util::myGlColor4f(color[0], color[1], color[2], color[3]); glEnable(GL_LINE_SMOOTH); for (int j = 0; j < mfstring->getSize(); j++) { const char *str = mfstring->getValue(j); int n = strlen(str); glPushMatrix(); glTranslatef(0, -j * fsize, 0); const float GLUT_STROKE_ROMAN_SIZE = 119.05; float scale = 1/GLUT_STROKE_ROMAN_SIZE; glScalef(scale * fsize, scale * fsize, 1.0); for (int i = 0; i < n; i++) glutStrokeCharacter(GLUT_STROKE_ROMAN, str[i]); glPopMatrix(); } glLineWidth(1.0); glPopAttrib(); } #else void NodeText::draw() { MFString *mfstring = string(); NodeFontStyle *fontStyle = (NodeFontStyle *) ((SFNode *) getField(fontStyle_Index(),true))->getValue(); // const float *length = ((MFFloat *) getField(length_Index()))->getValue(); // float maxExtent = ((SFFloat *) getField(maxExtent_Index()))->getValue(); FontInfo *font = NULL; bool fhorizontal = true; bool bleftToRight = true; float fsize = 1.0f; float fspacing = 1.0f; bool btopToBottom = true; if (fontStyle) { MFString *ffamily = fontStyle->family(); fhorizontal = fontStyle->horizontal()->getValue(); // MFString *justify = fontStyle->justify(); // const char *language = fontStyle->language()->getValue(); bleftToRight = fontStyle->leftToRight()->getValue(); fsize = fontStyle->size()->getValue(); fspacing = fontStyle->spacing()->getValue(); const char *sstyle = fontStyle->style()->getValue(); btopToBottom = fontStyle->topToBottom()->getValue(); for (int i = 0; i < ffamily->getSize(); i++) { font = _scene->LoadGLFont(ffamily->getValue(i), sstyle); if (font) break; } } else { font = _scene->LoadGLFont("SERIF", "PLAIN"); } if (!font) return; // couldn't find the font glPushMatrix(); glPushAttrib(GL_TEXTURE_BIT); glScalef(fsize, fsize, 1.0f); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); #ifndef _WIN32 glRasterPos4i(0, 0, 0, 0); #endif glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); float sPlane[4] = {1.0, 0.0, 0.0, 0.0}; float tPlane[4] = {0.0, 1.0, 0.0, 0.0}; float ySpacing = btopToBottom ? - fspacing : fspacing; for (int j = 0; j < mfstring->getSize(); j++) { const char *str = mfstring->getValue(j); int n = strlen(str); if (fhorizontal) { sPlane[3] = 0.0f; glPushMatrix(); for (int i = 0; i < n; i++) { if (bleftToRight) { glTexGenfv(GL_S, GL_OBJECT_PLANE, sPlane); glTexGenfv(GL_T, GL_OBJECT_PLANE, tPlane); glCallList(font->displayListBase + str[i]); sPlane[3] += font->kernX[str[i]]; } else { glTranslatef(-font->kernX[str[i]], 0.0f, 0.0f); sPlane[3] -= font->kernX[str[i]]; glTexGenfv(GL_S, GL_OBJECT_PLANE, sPlane); glTexGenfv(GL_T, GL_OBJECT_PLANE, tPlane); glPushMatrix(); glCallList(font->displayListBase + str[i]); glPopMatrix(); } } glPopMatrix(); glTranslatef(0.0f, ySpacing, 0.0f); tPlane[3] += ySpacing; } else { tPlane[3] = 0.0f; if (!bleftToRight) { glTranslatef(-fspacing * 0.5f, 0.0f, 0.0f); sPlane[3] += -fspacing * 0.5f; } glPushMatrix(); for (int i = 0; i < n; i++) { if (btopToBottom) { float y = -font->kernY[str[i]]; if (y == 0.0) y = -1.0f; // FIXME: default advance? glTranslatef(0.0f, y, 0.0f); tPlane[3] += y; glPushMatrix(); glTexGenfv(GL_S, GL_OBJECT_PLANE, sPlane); glTexGenfv(GL_T, GL_OBJECT_PLANE, tPlane); glCallList(font->displayListBase + str[i]); glPopMatrix(); } else { glPushMatrix(); glTexGenfv(GL_S, GL_OBJECT_PLANE, sPlane); glTexGenfv(GL_T, GL_OBJECT_PLANE, tPlane); glCallList(font->displayListBase + str[i]); glPopMatrix(); float y = font->kernY[str[i]]; if (y == 0.0) y = 1.0f; // FIXME: default advance? glTranslatef(0.0f, y, 0.0f); tPlane[3] += y; } } glPopMatrix(); if (bleftToRight) { glTranslatef(fspacing * 0.5f, 0.0f, 0.0f); sPlane[3] += fspacing * 0.5f; } } } glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); glPopAttrib(); glPopMatrix(); } #endif