1
/***************************************************************************
2
* Copyright (c) 2009 Werner Mayer <wmayer[at]users.sourceforge.net> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
23
#include "PreCompiled.h"
30
# include <OpenGL/gl.h>
35
# include <QFontMetrics>
38
# include <Inventor/actions/SoGLRenderAction.h>
39
# include <Inventor/bundles/SoMaterialBundle.h>
40
# include <Inventor/elements/SoLazyElement.h>
41
# include <Inventor/misc/SoState.h>
44
#include <Inventor/C/basic.h>
45
#include <Inventor/draggers/SoTranslate2Dragger.h>
46
#include <Inventor/elements/SoCullElement.h>
47
#include <Inventor/elements/SoFontNameElement.h>
48
#include <Inventor/elements/SoGLTextureEnabledElement.h>
49
#include <Inventor/elements/SoModelMatrixElement.h>
50
#include <Inventor/elements/SoProjectionMatrixElement.h>
51
#include <Inventor/elements/SoViewingMatrixElement.h>
52
#include <Inventor/elements/SoViewportRegionElement.h>
53
#include <Inventor/elements/SoViewVolumeElement.h>
55
#if COIN_MAJOR_VERSION > 3
56
#include <Inventor/elements/SoMultiTextureEnabledElement.h>
58
#include <Inventor/elements/SoGLTexture3EnabledElement.h>
63
#include "SoTextLabel.h"
64
#include "BitmapFactory.h"
65
#include "SoFCInteractiveElement.h"
78
Translation { translation 4 0 0 }
88
SoTextLabel { string ["Text label", "Second line"] backgroundColor 1.0 0.447059 0.337255}
92
App.ActiveDocument.addObject("App::InventorObject","iv").Buffer=s
97
SO_NODE_SOURCE(SoTextLabel)
99
void SoTextLabel::initClass()
101
SO_NODE_INIT_CLASS(SoTextLabel, SoText2, "Text2");
104
SoTextLabel::SoTextLabel()
106
SO_NODE_CONSTRUCTOR(SoTextLabel);
107
SO_NODE_ADD_FIELD(backgroundColor, (SbVec3f(1.0f,1.0f,1.0f)));
108
SO_NODE_ADD_FIELD(background, (true));
109
SO_NODE_ADD_FIELD(frameSize, (10.0f));
115
void SoTextLabel::GLRender(SoGLRenderAction *action)
117
if (!this->shouldGLRender(action))
120
// only draw text without background
121
if (!this->background.getValue()) {
122
inherited::GLRender(action);
126
SoState * state = action->getState();
129
SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
133
this->computeBBox(action, box, center);
135
if (!SoCullElement::cullTest(state, box, true)) {
136
SoMaterialBundle mb(action);
138
const SbMatrix & mat = SoModelMatrixElement::get(state);
139
const SbMatrix & projmatrix = (mat * SoViewingMatrixElement::get(state) *
140
SoProjectionMatrixElement::get(state));
141
const SbViewportRegion & vp = SoViewportRegionElement::get(state);
142
SbVec2s vpsize = vp.getViewportSizePixels();
145
SbName fontname = SoFontNameElement::get(state);
146
int lines = this->string.getNum();
148
// get left bottom corner of the label
149
SbVec3f nilpoint(0.0f, 0.0f, 0.0f);
150
projmatrix.multVecMatrix(nilpoint, nilpoint);
151
nilpoint[0] = (nilpoint[0] + 1.0f) * 0.5f * vpsize[0];
152
nilpoint[1] = (nilpoint[1] + 1.0f) * 0.5f * vpsize[1];
154
// Unfortunately, the size of the label is stored in the pimpl class of
155
// SoText2 which cannot be accessed directly. However, there is a trick
156
// to get the required information: set model, viewing and projection
157
// matrix to the identity matrix and also view volume to some default
158
// values. SoText2::computeBBox() then calls SoText2P::getQuad which
159
// returns the sizes in form of the bounding box. These values can be
160
// reverse-engineered to get width and height.
162
SoModelMatrixElement::set(state,this,SbMatrix::identity());
163
SoViewingMatrixElement::set(state,this,SbMatrix::identity());
164
SoProjectionMatrixElement::set(state,this,SbMatrix::identity());
166
vv.ortho(-1,1,-1,1,-1,1);
167
SoViewVolumeElement::set(state,this,vv);
171
this->computeBBox(action, box, center);
174
float xmin,ymin,zmin,xmax,ymax,zmax;
175
box.getBounds(xmin,ymin,zmin,xmax,ymax,zmax);
176
SbVec3f v0(xmin,ymax,zmax);
177
SbVec3f v1(xmax,ymax,zmax);
178
SbVec3f v2(xmax,ymin,zmax);
179
SbVec3f v3(xmin,ymin,zmax);
180
vv.projectToScreen(v0,v0);
181
vv.projectToScreen(v1,v1);
182
vv.projectToScreen(v2,v2);
183
vv.projectToScreen(v3,v3);
186
width = (v1[0]-v0[0])*vpsize[0];
187
height = (v1[1]-v3[1])*vpsize[1];
188
switch (this->justification.getValue()) {
190
nilpoint[0] -= width;
192
case SoText2::CENTER:
193
nilpoint[0] -= 0.5f*width;
200
nilpoint[1] -= (float(lines-1)/(float)lines*height);
203
SbVec3f toppoint = nilpoint;
204
toppoint[0] += width;
205
toppoint[1] += height;
208
glMatrixMode(GL_MODELVIEW);
211
glMatrixMode(GL_PROJECTION);
214
glOrtho(0, vpsize[0], 0, vpsize[1], -1.0f, 1.0f);
215
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
219
// disable textures for all units
220
SoGLTextureEnabledElement::set(state, this, false);
221
#if COIN_MAJOR_VERSION > 3
222
SoMultiTextureEnabledElement::set(state, this, false);
224
SoGLTexture3EnabledElement::set(state, this, false);
227
glPushAttrib(GL_ENABLE_BIT | GL_PIXEL_MODE_BIT | GL_COLOR_BUFFER_BIT);
228
glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
230
// color and frame size
231
SbColor color = this->backgroundColor.getValue();
232
float fs = this->frameSize.getValue();
235
glColor3f(color[0], color[1], color[2]);
237
glVertex3f(nilpoint[0]-fs,nilpoint[1]-fs,0.0f);
238
glVertex3f(toppoint[0]+fs,nilpoint[1]-fs,0.0f);
239
glVertex3f(toppoint[0]+fs,toppoint[1]+fs,0.0f);
240
glVertex3f(nilpoint[0]-fs,toppoint[1]+fs,0.0f);
248
glPixelStorei(GL_UNPACK_ALIGNMENT,4);
249
// Pop old GL matrix state.
250
glMatrixMode(GL_PROJECTION);
252
glMatrixMode(GL_MODELVIEW);
258
inherited::GLRender(action);
261
// ------------------------------------------------------
263
SO_NODE_SOURCE(SoColorBarLabel)
265
void SoColorBarLabel::initClass()
267
SO_NODE_INIT_CLASS(SoColorBarLabel, SoText2, "Text2");
270
SoColorBarLabel::SoColorBarLabel()
272
SO_NODE_CONSTRUCTOR(SoColorBarLabel);
275
void SoColorBarLabel::computeBBox(SoAction * action, SbBox3f & box, SbVec3f & center)
277
inherited::computeBBox(action, box, center);
278
if (!box.hasVolume()) {
279
SbViewVolume vv = SoViewVolumeElement::get(action->getState());
280
// workaround for https://github.com/coin3d/coin/issues/417:
281
// extend by 2 percent
282
vv.scaleWidth(1.02f);
283
SoViewVolumeElement::set(action->getState(), this, vv);
284
inherited::computeBBox(action, box, center);
288
// ------------------------------------------------------
290
SO_NODE_SOURCE(SoStringLabel)
292
void SoStringLabel::initClass()
294
SO_NODE_INIT_CLASS(SoStringLabel, SoNode, "Node");
297
SoStringLabel::SoStringLabel()
299
SO_NODE_CONSTRUCTOR(SoStringLabel);
300
SO_NODE_ADD_FIELD(string, (""));
301
SO_NODE_ADD_FIELD(textColor, (SbVec3f(1.0f,1.0f,1.0f)));
302
SO_NODE_ADD_FIELD(name, ("Helvetica"));
303
SO_NODE_ADD_FIELD(size, (12));
307
* Renders the open edges only.
309
void SoStringLabel::GLRender(SoGLRenderAction *action)
312
SoState * state = action->getState();
314
SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR);
315
SoGLWidgetElement::get(state, window);
321
// Enter in 2D screen mode
322
glMatrixMode(GL_PROJECTION);
325
glOrtho(-1,1,-1,1,-1,1);
326
glMatrixMode(GL_MODELVIEW);
329
glPushAttrib(GL_ENABLE_BIT);
330
glDisable(GL_DEPTH_TEST);
331
glDisable(GL_LIGHTING);
332
glDisable(GL_TEXTURE_2D);
336
font.setStyleStrategy(QFont::NoAntialias);
337
font.setFamily(QLatin1String(this->name.getValue()));
338
font.setPixelSize(this->size.getValue());
340
glBlendFunc(GL_ONE,GL_SRC_ALPHA);
343
SbColor color = this->textColor.getValue();
344
glColor4f(color[0], color[1], color[2], 1);
345
const SbMatrix & mat = SoModelMatrixElement::get(state);
346
const SbMatrix & projmatrix = (mat * SoViewingMatrixElement::get(state) *
347
SoProjectionMatrixElement::get(state));
348
SbVec3f nil(0.0f, 0.0f, 0.0f);
349
projmatrix.multVecMatrix(nil, nil);
351
for (int i=0; i<this->string.getNum(); i++)
352
list << QLatin1String(this->string[i].getString());
354
// Leave 2D screen mode
357
glMatrixMode(GL_PROJECTION);
359
glMatrixMode(GL_MODELVIEW);
364
// ------------------------------------------------------
366
SO_NODE_SOURCE(SoFrameLabel)
368
void SoFrameLabel::initClass()
370
SO_NODE_INIT_CLASS(SoFrameLabel, SoImage, "Image");
373
SoFrameLabel::SoFrameLabel()
375
SO_NODE_CONSTRUCTOR(SoFrameLabel);
376
SO_NODE_ADD_FIELD(string, (""));
377
SO_NODE_ADD_FIELD(textColor, (SbVec3f(1.0f,1.0f,1.0f)));
378
SO_NODE_ADD_FIELD(backgroundColor, (SbVec3f(0.0f,0.333f,1.0f)));
379
SO_NODE_ADD_FIELD(justification, (LEFT));
380
SO_NODE_ADD_FIELD(name, ("Helvetica"));
381
SO_NODE_ADD_FIELD(size, (12));
382
SO_NODE_ADD_FIELD(frame, (true));
383
//SO_NODE_ADD_FIELD(image, (SbVec2s(0,0), 0, NULL));
386
void SoFrameLabel::notify(SoNotList * list)
388
SoField *f = list->getLastField();
389
if (f == &this->string ||
390
f == &this->textColor ||
391
f == &this->backgroundColor ||
392
f == &this->justification ||
398
inherited::notify(list);
401
void SoFrameLabel::drawImage()
403
const SbString* s = string.getValues(0);
404
int num = string.getNum();
406
this->image = SoSFImage();
410
QFont font(QString::fromLatin1(QByteArray(name.getValue())), size.getValue());
411
QFontMetrics fm(font);
413
int h = fm.height() * num;
414
const SbColor& b = backgroundColor.getValue();
416
brush.setRgbF(b[0],b[1],b[2]);
417
const SbColor& t = textColor.getValue();
419
front.setRgbF(t[0],t[1],t[2]);
422
for (int i=0; i<num; i++) {
423
QString line = QString::fromUtf8(s[i].getString());
424
w = std::max<int>(w, QtTools::horizontalAdvance(fm, line));
428
QImage image(w+10,h+10,QImage::Format_ARGB32_Premultiplied);
429
image.fill(0x00000000);
430
QPainter painter(&image);
431
painter.setRenderHint(QPainter::Antialiasing);
433
SbBool drawFrame = frame.getValue();
435
painter.setPen(QPen(QColor(0,0,127), 2, Qt::SolidLine, Qt::RoundCap,
437
painter.setBrush(QBrush(brush, Qt::SolidPattern));
438
QRectF rectangle(0.0, 0.0, w+10, h+10);
439
painter.drawRoundedRect(rectangle, 5, 5);
442
painter.setPen(front);
444
Qt::Alignment align = Qt::AlignVCenter;
445
if (justification.getValue() == 0)
446
align = Qt::AlignVCenter | Qt::AlignLeft;
447
else if (justification.getValue() == 1)
448
align = Qt::AlignVCenter | Qt::AlignRight;
450
align = Qt::AlignVCenter | Qt::AlignHCenter;
451
QString text = lines.join(QLatin1String("\n"));
452
painter.setFont(font);
453
painter.drawText(5,5,w,h,align,text);
457
Gui::BitmapFactory().convert(image, sfimage);
458
this->image = sfimage;
462
* Renders the open edges only.
464
void SoFrameLabel::GLRender(SoGLRenderAction *action)
466
inherited::GLRender(action);
469
// ------------------------------------------------------
471
SO_NODE_SOURCE(TranslateManip)
474
TranslateManip::initClass()
476
SO_NODE_INIT_CLASS(TranslateManip, SoTransformManip,
480
TranslateManip::TranslateManip()
482
SO_NODE_CONSTRUCTOR(TranslateManip);
484
auto myDrag = new SoTranslate2Dragger;
488
TranslateManip::~TranslateManip() = default;