SoTextLabel.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2009 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # ifdef FC_OS_WIN32
00028 # include <windows.h>
00029 # endif
00030 # ifdef FC_OS_MACOSX
00031 # include <OpenGL/gl.h>
00032 # else
00033 # include <GL/gl.h>
00034 # endif
00035 # include <cfloat>
00036 # include <algorithm>
00037 # include <QFontMetrics>
00038 # include <QGLWidget>
00039 # include <QPainter>
00040 # include <QPen>
00041 # include <Inventor/actions/SoGLRenderAction.h>
00042 # include <Inventor/bundles/SoMaterialBundle.h>
00043 # include <Inventor/elements/SoLazyElement.h>
00044 # include <Inventor/nodes/SoSurroundScale.h>
00045 # include <Inventor/misc/SoState.h>
00046 #endif
00047 
00048 #include <Inventor/draggers/SoTranslate2Dragger.h>
00049 #include <Inventor/elements/SoFontNameElement.h>
00050 #include <Inventor/elements/SoFontSizeElement.h>
00051 #include <Inventor/elements/SoCullElement.h>
00052 #include <Inventor/elements/SoModelMatrixElement.h>
00053 #include <Inventor/elements/SoProjectionMatrixElement.h>
00054 #include <Inventor/elements/SoViewingMatrixElement.h>
00055 #include <Inventor/elements/SoViewVolumeElement.h>
00056 #include <Inventor/elements/SoViewportRegionElement.h>
00057 #include <Inventor/elements/SoGLTextureEnabledElement.h>
00058 #include <Inventor/elements/SoGLTexture3EnabledElement.h>
00059 
00060 #include "SoTextLabel.h"
00061 #include "SoFCInteractiveElement.h"
00062 #include "BitmapFactory.h"
00063 
00064 using namespace Gui;
00065 
00092 SO_NODE_SOURCE(SoTextLabel);
00093 
00094 void SoTextLabel::initClass()
00095 {
00096     SO_NODE_INIT_CLASS(SoTextLabel, SoText2, "Text2");
00097 }
00098 
00099 SoTextLabel::SoTextLabel()
00100 {
00101     SO_NODE_CONSTRUCTOR(SoTextLabel);
00102     SO_NODE_ADD_FIELD(backgroundColor, (SbVec3f(1.0f,1.0f,1.0f)));
00103     SO_NODE_ADD_FIELD(background, (TRUE));
00104     SO_NODE_ADD_FIELD(frameSize, (10.0f));
00105 }
00106 
00110 void SoTextLabel::GLRender(SoGLRenderAction *action)
00111 {
00112     if (!this->shouldGLRender(action)) return;
00113 
00114     // only draw text without background
00115     if (!this->background.getValue()) {
00116         inherited::GLRender(action);
00117         return;
00118     }
00119 
00120     SoState * state = action->getState();
00121 
00122     state->push();
00123     SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
00124 
00125     SbBox3f box;
00126     SbVec3f center;
00127     this->computeBBox(action, box, center);
00128 
00129     if (!SoCullElement::cullTest(state, box, TRUE)) {
00130         SoMaterialBundle mb(action);
00131         mb.sendFirst();
00132         const SbMatrix & mat = SoModelMatrixElement::get(state);
00133         //const SbViewVolume & vv = SoViewVolumeElement::get(state);
00134         const SbMatrix & projmatrix = (mat * SoViewingMatrixElement::get(state) *
00135                                        SoProjectionMatrixElement::get(state));
00136         const SbViewportRegion & vp = SoViewportRegionElement::get(state);
00137         SbVec2s vpsize = vp.getViewportSizePixels();
00138 
00139         // font stuff
00140         //float space = this->spacing.getValue();
00141         //float fontsize = SoFontSizeElement::get(state);
00142         SbName fontname = SoFontNameElement::get(state);
00143         int lines = this->string.getNum();
00144 
00145         // get left bottom corner of the label
00146         SbVec3f nilpoint(0.0f, 0.0f, 0.0f);
00147         projmatrix.multVecMatrix(nilpoint, nilpoint);
00148         nilpoint[0] = (nilpoint[0] + 1.0f) * 0.5f * vpsize[0];
00149         nilpoint[1] = (nilpoint[1] + 1.0f) * 0.5f * vpsize[1];
00150 
00151 #if 1
00152         // Unfortunately, the size of the label is stored in the pimpl class of
00153         // SoText2 which cannot be accessed directly. However, there is a trick
00154         // to get the required information: set model, viewing and projection
00155         // matrix to the identity matrix and also view volume to some default
00156         // values. SoText2::computeBBox() then calls SoText2P::getQuad which
00157         // returns the sizes in form of the bounding box. These values can be
00158         // reverse-engineered to get width and height.
00159         state->push();
00160         SoModelMatrixElement::set(state,this,SbMatrix::identity());
00161         SoViewingMatrixElement::set(state,this,SbMatrix::identity());
00162         SoProjectionMatrixElement::set(state,this,SbMatrix::identity());
00163         SbViewVolume vv;
00164         vv.ortho(-1,1,-1,1,-1,1);
00165         SoViewVolumeElement::set(state,this,vv);
00166 
00167         SbBox3f box;
00168         SbVec3f center;
00169         this->computeBBox(action, box, center);
00170         state->pop();
00171 
00172         float xmin,ymin,zmin,xmax,ymax,zmax;
00173         box.getBounds(xmin,ymin,zmin,xmax,ymax,zmax);
00174         SbVec3f v0(xmin,ymax,zmax);
00175         SbVec3f v1(xmax,ymax,zmax);
00176         SbVec3f v2(xmax,ymin,zmax);
00177         SbVec3f v3(xmin,ymin,zmax);
00178         vv.projectToScreen(v0,v0);
00179         vv.projectToScreen(v1,v1);
00180         vv.projectToScreen(v2,v2);
00181         vv.projectToScreen(v3,v3);
00182 
00183         float width,height;
00184         width  = (v1[0]-v0[0])*vpsize[0];
00185         height = (v1[1]-v3[1])*vpsize[1];
00186         switch (this->justification.getValue()) {
00187         case SoText2::RIGHT:
00188             nilpoint[0] -= width;
00189             break;
00190         case SoText2::CENTER:
00191             nilpoint[0] -= 0.5f*width;
00192             break;
00193         default:
00194             break;
00195         }
00196 
00197         if (lines > 1) {
00198             nilpoint[1] -= (float(lines-1)/(float)lines*height);
00199         }
00200 #else
00201         // Unfortunately, the required size (in pixels) is stored in a non-accessible way
00202         // in the subclass SoText2. Thus, we try to get a satisfactory solution with Qt 
00203         // methods.
00204         // The font name is of the form "family:style". If 'style' is given it can be
00205         // 'Bold', 'Italic' or 'Bold Italic'.
00206         QFont font;
00207         QString fn = QString::fromAscii(fontname.getString());
00208         int pos = fn.indexOf(QLatin1Char(':'));
00209         if (pos > -1) {
00210             if (fn.indexOf(QLatin1String("Bold"),pos,Qt::CaseInsensitive) > pos)
00211                 font.setBold(true);
00212             if (fn.indexOf(QLatin1String("Italic"),pos,Qt::CaseInsensitive) > pos)
00213                 font.setItalic(true);
00214             fn = fn.left(pos);
00215         }
00216         font.setFamily(fn);
00217         font.setPixelSize((int)fontsize);
00218         QFontMetrics fm(font);
00219 
00220         float width = 0.0f;
00221         float height = 0.75f*fontsize*lines + (lines-1)*space;//fm.height();
00222         float hh=0;
00223         for (int i = 0; i < lines; i++) {
00224             SbString str = this->string[i];
00225             float w = fm.width(QLatin1String(this->string[i].getString()));
00226             width = std::max<float>(width, w);
00227             hh = fm.height();
00228         }
00229 
00230         if (lines > 1) {
00231             nilpoint[1] -= ((lines-1)*fontsize*0.75f+space);
00232         }
00233 #endif
00234 
00235         SbVec3f toppoint = nilpoint;
00236         toppoint[0] += width;
00237         toppoint[1] += height;
00238 
00239         // Set new state.
00240         glMatrixMode(GL_MODELVIEW);
00241         glPushMatrix();
00242         glLoadIdentity();
00243         glMatrixMode(GL_PROJECTION);
00244         glPushMatrix();
00245         glLoadIdentity();
00246         glOrtho(0, vpsize[0], 0, vpsize[1], -1.0f, 1.0f);
00247         glPixelStorei(GL_UNPACK_ALIGNMENT,1);
00248 
00249         state->push();
00250 
00251         // disable textures for all units
00252         SoGLTextureEnabledElement::set(state, this, FALSE);
00253         SoGLTexture3EnabledElement::set(state, this, FALSE);
00254 
00255         glPushAttrib(GL_ENABLE_BIT | GL_PIXEL_MODE_BIT | GL_COLOR_BUFFER_BIT);
00256         glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
00257 
00258         // color and frame size
00259         SbColor color = this->backgroundColor.getValue();
00260         float fs = this->frameSize.getValue();
00261 
00262         // draw background
00263         glColor3f(color[0], color[1], color[2]);
00264         glBegin(GL_QUADS);
00265         glVertex3f(nilpoint[0]-fs,nilpoint[1]-fs,0.0f);
00266         glVertex3f(toppoint[0]+fs,nilpoint[1]-fs,0.0f);
00267         glVertex3f(toppoint[0]+fs,toppoint[1]+fs,0.0f);
00268         glVertex3f(nilpoint[0]-fs,toppoint[1]+fs,0.0f);
00269         glEnd();
00270 
00271         // pop old state
00272         glPopClientAttrib();
00273         glPopAttrib();
00274         state->pop();
00275           
00276         glPixelStorei(GL_UNPACK_ALIGNMENT,4);
00277         // Pop old GL matrix state.
00278         glMatrixMode(GL_PROJECTION);
00279         glPopMatrix();
00280         glMatrixMode(GL_MODELVIEW);
00281         glPopMatrix();
00282     }
00283 
00284     state->pop();
00285 
00286     inherited::GLRender(action);
00287 }
00288 
00289 // ------------------------------------------------------
00290 
00291 SO_NODE_SOURCE(SoStringLabel);
00292 
00293 void SoStringLabel::initClass()
00294 {
00295     SO_NODE_INIT_CLASS(SoStringLabel, SoNode, "Node");
00296 }
00297 
00298 SoStringLabel::SoStringLabel()
00299 {
00300     SO_NODE_CONSTRUCTOR(SoStringLabel);
00301     SO_NODE_ADD_FIELD(string, (""));
00302     SO_NODE_ADD_FIELD(textColor, (SbVec3f(1.0f,1.0f,1.0f)));
00303     SO_NODE_ADD_FIELD(name, ("Helvetica"));
00304     SO_NODE_ADD_FIELD(size, (12));
00305 }
00306 
00310 void SoStringLabel::GLRender(SoGLRenderAction *action)
00311 {
00312     QGLWidget* window;
00313     SoState * state = action->getState();
00314     state->push();
00315     SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
00316     SoGLWidgetElement::get(state, window);
00317     if (!window) {
00318         state->pop();
00319         return;
00320     }
00321 
00322     // Enter in 2D screen mode
00323     glMatrixMode(GL_PROJECTION);
00324     glPushMatrix();
00325     glLoadIdentity();
00326     glOrtho(-1,1,-1,1,-1,1);
00327     glMatrixMode(GL_MODELVIEW);
00328     glPushMatrix();
00329     glLoadIdentity();
00330     glPushAttrib(GL_ENABLE_BIT);
00331     glDisable(GL_DEPTH_TEST);
00332     glDisable(GL_LIGHTING);
00333     glDisable(GL_TEXTURE_2D);
00334     glEnable(GL_BLEND);
00335 
00336     QFont font;
00337     font.setStyleStrategy(QFont::NoAntialias);
00338     font.setFamily(QLatin1String(this->name.getValue()));
00339     font.setPixelSize(this->size.getValue());
00340 
00341     glBlendFunc(GL_ONE,GL_SRC_ALPHA);
00342 
00343     /* Background Box */
00344     //glColor4f(1,0.1f,0.1f,1);
00345     //int ln =4;
00346     //float ls = font.pixelSize()*1.5f;
00347     //float bh = -1 + 2.0*(ls*(ln+.25))/float(window->height());
00348 
00349     //glBegin(GL_QUADS);
00350     //glVertex2f(-1.f,bh);   glVertex2f(-1.f,-1.f);
00351     //glVertex2f( 1.f,-1.f); glVertex2f( 1.f,bh);
00352     //glEnd();
00353 
00354     //float middleCol=window->width()*0.40;
00355     //float rightCol=window->width()*0.85;
00356     //float startPos = window->height()-(5+ls*(ln));
00357 
00358     // text color
00359     SbColor color = this->textColor.getValue();
00360     glColor4f(color[0], color[1], color[2],1);
00361     //window->renderText(20,20/*startPos+ 1*ls*/,QLatin1String(this->string[0].getString()),font);
00362     const SbMatrix & mat = SoModelMatrixElement::get(state);
00363     const SbMatrix & projmatrix = (mat * SoViewingMatrixElement::get(state) *
00364                                    SoProjectionMatrixElement::get(state));
00365     SbVec3f nil(0.0f, 0.0f, 0.0f);
00366     projmatrix.multVecMatrix(nil, nil);
00367     QStringList list;
00368     for (int i=0; i<this->string.getNum(); i++)
00369         list << QLatin1String(this->string[i].getString());
00370     window->renderText(nil[0],nil[1],nil[2],list.join(QLatin1String("\n")),font);
00371 
00372     // Leave 2D screen mode
00373     glPopAttrib();
00374     glPopMatrix();
00375     glMatrixMode(GL_PROJECTION);
00376     glPopMatrix();
00377     glMatrixMode(GL_MODELVIEW);
00378 
00379     state->pop();
00380 }
00381 
00382 // ------------------------------------------------------
00383 
00384 SO_NODE_SOURCE(SoFrameLabel);
00385 
00386 void SoFrameLabel::initClass()
00387 {
00388     SO_NODE_INIT_CLASS(SoFrameLabel, SoImage, "Image");
00389 }
00390 
00391 SoFrameLabel::SoFrameLabel()
00392 {
00393     SO_NODE_CONSTRUCTOR(SoFrameLabel);
00394     SO_NODE_ADD_FIELD(string, (""));
00395     SO_NODE_ADD_FIELD(textColor, (SbVec3f(1.0f,1.0f,1.0f)));
00396     SO_NODE_ADD_FIELD(backgroundColor, (SbVec3f(0.0f,0.333f,1.0f)));
00397     SO_NODE_ADD_FIELD(justification, (LEFT));
00398     SO_NODE_ADD_FIELD(name, ("Helvetica"));
00399     SO_NODE_ADD_FIELD(size, (12));
00400     SO_NODE_ADD_FIELD(frame, (TRUE));
00401   //SO_NODE_ADD_FIELD(image, (SbVec2s(0,0), 0, NULL));
00402 }
00403 
00404 void SoFrameLabel::notify(SoNotList * list)
00405 {
00406     SoField *f = list->getLastField();
00407     if (f == &this->string ||
00408         f == &this->textColor ||
00409         f == &this->backgroundColor ||
00410         f == &this->justification ||
00411         f == &this->name ||
00412         f == &this->size ||
00413         f == &this->frame) {
00414         drawImage();
00415     }
00416     inherited::notify(list);
00417 }
00418 
00419 void SoFrameLabel::drawImage()
00420 {
00421     const SbString* s = string.getValues(0);
00422     int num = string.getNum();
00423     if (num == 0) {
00424         this->image = SoSFImage();
00425         return;
00426     }
00427 
00428     QFont font(QString::fromAscii(name.getValue()), size.getValue());
00429     QFontMetrics fm(font);
00430     int w = 0;
00431     int h = fm.height() * num;
00432     const SbColor& b = backgroundColor.getValue();
00433     QColor brush;
00434     brush.setRgbF(b[0],b[1],b[2]);
00435     const SbColor& t = textColor.getValue();
00436     QColor front;
00437     front.setRgbF(t[0],t[1],t[2]);
00438 
00439     QStringList lines;
00440     for (int i=0; i<num; i++) {
00441         QString line = QString::fromUtf8(s[i].getString());
00442         w = std::max<int>(w, fm.width(line));
00443         lines << line;
00444     }
00445 
00446     QImage image(w+10,h+10,QImage::Format_ARGB32_Premultiplied);
00447     image.fill(0x00000000);
00448     QPainter painter(&image);
00449     painter.setRenderHint(QPainter::Antialiasing);
00450 
00451     SbBool drawFrame = frame.getValue();
00452     if (drawFrame) {
00453         painter.setPen(QPen(QColor(0,0,127), 2, Qt::SolidLine, Qt::RoundCap,
00454                             Qt::RoundJoin));
00455         painter.setBrush(QBrush(brush, Qt::SolidPattern));
00456         QRectF rectangle(0.0, 0.0, w+10, h+10);
00457         painter.drawRoundedRect(rectangle, 5, 5);
00458     }
00459 
00460     painter.setPen(front);
00461 
00462     Qt::Alignment align = Qt::AlignVCenter;
00463     if (justification.getValue() == 0)
00464         align = Qt::AlignVCenter | Qt::AlignLeft;
00465     else if (justification.getValue() == 1)
00466         align = Qt::AlignVCenter | Qt::AlignRight;
00467     else
00468         align = Qt::AlignVCenter | Qt::AlignHCenter;
00469     QString text = lines.join(QLatin1String("\n"));
00470     painter.setFont(font);
00471     painter.drawText(5,5,w,h,align,text);
00472     painter.end();
00473 
00474     SoSFImage sfimage;
00475     Gui::BitmapFactory().convert(image, sfimage);
00476     this->image = sfimage;
00477 }
00478 
00482 void SoFrameLabel::GLRender(SoGLRenderAction *action)
00483 {
00484     inherited::GLRender(action);
00485 #if 0
00486     QGLWidget* window;
00487     SoState * state = action->getState();
00488     state->push();
00489     SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
00490     SoGLWidgetElement::get(state, window);
00491     if (!window) {
00492         state->pop();
00493         return;
00494     }
00495 
00496     // Enter in 2D screen mode
00497     glMatrixMode(GL_PROJECTION);
00498     glPushMatrix();
00499     glLoadIdentity();
00500     glOrtho(-1,1,-1,1,-1,1);
00501     glMatrixMode(GL_MODELVIEW);
00502     glPushMatrix();
00503     glLoadIdentity();
00504     glPushAttrib(GL_ENABLE_BIT);
00505     glDisable(GL_DEPTH_TEST);
00506     glDisable(GL_LIGHTING);
00507     glDisable(GL_TEXTURE_2D);
00508     glEnable(GL_BLEND);
00509 
00510     QFont font;
00511     font.setStyleStrategy(QFont::NoAntialias);
00512     font.setFamily(QLatin1String(this->name.getValue()));
00513     font.setPixelSize(this->size.getValue());
00514 
00515     glBlendFunc(GL_ONE,GL_SRC_ALPHA);
00516 
00517     /* Background Box */
00518     //glColor4f(1,0.1f,0.1f,1);
00519     //int ln =4;
00520     //float ls = font.pixelSize()*1.5f;
00521     //float bh = -1 + 2.0*(ls*(ln+.25))/float(window->height());
00522 
00523     //glBegin(GL_QUADS);
00524     //glVertex2f(-1.f,bh);   glVertex2f(-1.f,-1.f);
00525     //glVertex2f( 1.f,-1.f); glVertex2f( 1.f,bh);
00526     //glEnd();
00527 
00528     //float middleCol=window->width()*0.40;
00529     //float rightCol=window->width()*0.85;
00530     //float startPos = window->height()-(5+ls*(ln));
00531 
00532     // text color
00533     SbColor color = this->textColor.getValue();
00534     glColor4f(color[0], color[1], color[2],1);
00535     //window->renderText(20,20/*startPos+ 1*ls*/,QLatin1String(this->string[0].getString()),font);
00536     const SbMatrix & mat = SoModelMatrixElement::get(state);
00537     const SbMatrix & projmatrix = (mat * SoViewingMatrixElement::get(state) *
00538                                    SoProjectionMatrixElement::get(state));
00539     SbVec3f nil(0.0f, 0.0f, 0.0f);
00540     projmatrix.multVecMatrix(nil, nil);
00541     QStringList list;
00542     for (int i=0; i<this->string.getNum(); i++)
00543         list << QLatin1String(this->string[i].getString());
00544     window->renderText(nil[0],nil[1],nil[2],list.join(QLatin1String("\n")),font);
00545 
00546     // Leave 2D screen mode
00547     glPopAttrib();
00548     glPopMatrix();
00549     glMatrixMode(GL_PROJECTION);
00550     glPopMatrix();
00551     glMatrixMode(GL_MODELVIEW);
00552 
00553     state->pop();
00554 #endif
00555 }
00556 
00557 // ------------------------------------------------------
00558 
00559 SO_NODE_SOURCE(TranslateManip);
00560 
00561 void
00562 TranslateManip::initClass()
00563 {
00564     SO_NODE_INIT_CLASS(TranslateManip, SoTransformManip,
00565                        "TransformManip");
00566 }
00567 
00568 TranslateManip::TranslateManip()
00569 {
00570     SO_NODE_CONSTRUCTOR(TranslateManip);
00571 
00572     SoTranslate2Dragger *myDrag = new SoTranslate2Dragger;
00573     setDragger(myDrag);
00574 }
00575 
00576 TranslateManip::~TranslateManip()
00577 {
00578 }

Generated on Wed Nov 23 19:00:40 2011 for FreeCAD by  doxygen 1.6.1