root/OpenSceneGraph/branches/OpenSceneGraph-2.8/src/osgText/TextBase.cpp @ 11238

Revision 11238, 11.4 kB (checked in by paulmartz, 4 years ago)

2.8 branch: Minor bug fixes for ac and 3dc plugins. Merges these revisions from trunk: 10010, 10758, and 11175.

  • Property svn:mergeinfo set to
    /OpenSceneGraph/branches/OpenSceneGraph-2.8.2/src/osgText/TextBase.cpp:10664
    /OpenSceneGraph/trunk/src/osgText/TextBase.cpp:9769,9879-9880,9895,9932,10010,10208,10340,10376,10417,10456,10487,10622-10623,10625,10671-10672,10697,10722,10753,10758,10788,10818,10854-10855,10858,10887,10891,10923,10933,11019,11032,11034-11035,11111,11127,11131,11175
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14
15#include <osgText/TextBase>
16
17#include <osg/Math>
18#include <osg/GL>
19#include <osg/Notify>
20#include <osg/PolygonOffset>
21#include <osg/TexEnv>
22
23#include <osgUtil/CullVisitor>
24
25#include <osgDB/ReadFile>
26
27#include "DefaultFont.h"
28
29using namespace osg;
30using namespace osgText;
31
32//#define TREES_CODE_FOR_MAKING_SPACES_EDITABLE
33
34TextBase::TextBase():
35    _fontSize(32,32),
36    _characterHeight(32),
37    _characterAspectRatio(1.0f),
38    _characterSizeMode(OBJECT_COORDS),
39    _maximumWidth(0.0f),
40    _maximumHeight(0.0f),
41    _lineSpacing(0.0f),
42    _alignment(BASE_LINE),
43    _axisAlignment(XY_PLANE),
44    _autoRotateToScreen(false),
45    _layout(LEFT_TO_RIGHT),
46    _drawMode(TEXT),
47    _kerningType(KERNING_DEFAULT),
48    _lineCount(0)
49{
50    setStateSet(DefaultFont::instance()->getStateSet());
51    setUseDisplayList(false);
52    setSupportsDisplayList(false);
53}
54
55TextBase::TextBase(const TextBase& textBase,const osg::CopyOp& copyop):
56    osg::Drawable(textBase,copyop),
57    _fontSize(textBase._fontSize),
58    _characterHeight(textBase._characterHeight),
59    _characterAspectRatio(textBase._characterAspectRatio),
60    _characterSizeMode(textBase._characterSizeMode),
61    _maximumWidth(textBase._maximumWidth),
62    _maximumHeight(textBase._maximumHeight),
63    _lineSpacing(textBase._lineSpacing),
64    _text(textBase._text),
65    _position(textBase._position),
66    _alignment(textBase._alignment),
67    _axisAlignment(textBase._axisAlignment),
68    _rotation(textBase._rotation),
69    _autoRotateToScreen(textBase._autoRotateToScreen),
70    _layout(textBase._layout),
71    _drawMode(textBase._drawMode),
72    _kerningType(textBase._kerningType),
73    _lineCount(textBase._lineCount)
74{
75}
76
77TextBase::~TextBase()
78{
79}
80
81void TextBase::setFontResolution(unsigned int width, unsigned int height)
82{
83    _fontSize = FontResolution(width,height);
84    computeGlyphRepresentation();
85}
86
87void TextBase::setCharacterSize(float height,float aspectRatio)
88{
89    _characterHeight = height;
90    _characterAspectRatio = aspectRatio;
91    computeGlyphRepresentation();
92}
93
94void TextBase::setMaximumWidth(float maximumWidth)
95{
96    _maximumWidth = maximumWidth;
97    computeGlyphRepresentation();
98}
99
100void  TextBase::setMaximumHeight(float maximumHeight)
101{
102    _maximumHeight = maximumHeight;
103    computeGlyphRepresentation();
104}
105
106void TextBase::setLineSpacing(float lineSpacing)
107{
108    _lineSpacing = lineSpacing;
109    computeGlyphRepresentation();
110}
111   
112
113void TextBase::setText(const String& text)
114{
115    if (_text==text) return;
116   
117    _text = text;
118    computeGlyphRepresentation();
119}
120
121void TextBase::setText(const std::string& text)
122{
123    setText(String(text));
124}
125
126void TextBase::setText(const std::string& text,String::Encoding encoding)
127{
128    setText(String(text,encoding));
129}
130   
131
132void TextBase::setText(const wchar_t* text)
133{
134    setText(String(text));
135}
136
137void TextBase::setPosition(const osg::Vec3& pos)
138{
139    if (_position==pos) return;
140
141    _position = pos;
142    computePositions();
143}
144
145void TextBase::setAlignment(AlignmentType alignment)
146{
147    if (_alignment==alignment) return;
148   
149    _alignment = alignment;
150    computeGlyphRepresentation();
151}
152
153void TextBase::setAxisAlignment(AxisAlignment axis)
154{
155    _axisAlignment = axis;
156
157    switch(axis)
158    {
159    case XZ_PLANE:
160        setAutoRotateToScreen(false);
161        setRotation(osg::Quat(osg::inDegrees(90.0f),osg::Vec3(1.0f,0.0f,0.0f)));
162        break;
163    case REVERSED_XZ_PLANE:
164        setAutoRotateToScreen(false);
165        setRotation(osg::Quat(osg::inDegrees(180.0f),osg::Vec3(0.0f,1.0f,0.0f))*
166                    osg::Quat(osg::inDegrees(90.0f),osg::Vec3(1.0f,0.0f,0.0f)));
167        break;
168    case YZ_PLANE
169        setAutoRotateToScreen(false);
170        setRotation(osg::Quat(osg::inDegrees(90.0f),osg::Vec3(1.0f,0.0f,0.0f))*
171                    osg::Quat(osg::inDegrees(90.0f),osg::Vec3(0.0f,0.0f,1.0f)));
172        break;
173    case REVERSED_YZ_PLANE
174        setAutoRotateToScreen(false);
175        setRotation(osg::Quat(osg::inDegrees(180.0f),osg::Vec3(0.0f,1.0f,0.0f))*
176                    osg::Quat(osg::inDegrees(90.0f),osg::Vec3(1.0f,0.0f,0.0f))*
177                    osg::Quat(osg::inDegrees(90.0f),osg::Vec3(0.0f,0.0f,1.0f)));
178        break;
179    case XY_PLANE:
180        setAutoRotateToScreen(false);
181        setRotation(osg::Quat());  // nop - already on XY plane.
182        break;
183    case REVERSED_XY_PLANE:
184        setAutoRotateToScreen(false);
185        setRotation(osg::Quat(osg::inDegrees(180.0f),osg::Vec3(0.0f,1.0f,0.0f)));
186        break;
187    case SCREEN:
188        setAutoRotateToScreen(true);
189        setRotation(osg::Quat());  // nop - already on XY plane.
190        break;
191    default: break;
192    }
193}
194
195void TextBase::setRotation(const osg::Quat& quat)
196{
197    _rotation = quat;
198    computePositions();
199}
200
201
202void TextBase::setAutoRotateToScreen(bool autoRotateToScreen)
203{
204    if (_autoRotateToScreen==autoRotateToScreen) return;
205   
206    _autoRotateToScreen = autoRotateToScreen;
207    computePositions();
208}
209
210
211void TextBase::setLayout(Layout layout)
212{
213    if (_layout==layout) return;
214
215    _layout = layout;
216    computeGlyphRepresentation();
217}
218
219
220void TextBase::setDrawMode(unsigned int mode)
221{
222    if (_drawMode==mode) return;
223
224    _drawMode=mode;
225}
226
227
228osg::BoundingBox TextBase::computeBound() const
229{
230    osg::BoundingBox  bbox;
231
232    if (_textBB.valid())
233    {
234        for(unsigned int i=0;i<_autoTransformCache.size();++i)
235        {
236            if (_autoTransformCache[i]._traversalNumber<0 && (_characterSizeMode!=OBJECT_COORDS || _autoRotateToScreen))
237            {
238                // _autoTransformCache is not valid so don't take it into accoumt when compute bounding volume.
239#if 0
240                // so fallback to estimating the bounding box size by assuming a scale of 1
241                // but might cause problems due to small feature culling...
242                osg::Matrix matrix;
243                matrix.makeTranslate(_position);
244                bbox.expandBy(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*matrix);
245                bbox.expandBy(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMax())*matrix);
246#endif
247            }
248            else
249            {           
250                osg::Matrix& matrix = _autoTransformCache[i]._matrix;
251                bbox.expandBy(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*matrix);
252                bbox.expandBy(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMax())*matrix);
253            }
254        }
255    }
256   
257    return bbox;
258}
259
260void TextBase::computePositions()
261{
262    unsigned int size = osg::maximum(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts(),_autoTransformCache.size());
263   
264    // FIXME: OPTIMIZE: This would be one of the ideal locations to
265    // call computeAverageGlyphWidthAndHeight(). It is out of the contextID loop
266    // so the value would be computed fewer times. But the code will need changes
267    // to get the value down to the locations it is needed. (Either pass through parameters
268    // or member variables, but we would need a system to know if the values are stale.)
269
270   
271    for(unsigned int i=0;i<size;++i)
272    {
273        computePositions(i);
274    }
275}
276
277void TextBase::setThreadSafeRefUnref(bool threadSafe)
278{
279    Drawable::setThreadSafeRefUnref(threadSafe);
280}
281
282void TextBase::resizeGLObjectBuffers(unsigned int maxSize)
283{
284    Drawable::resizeGLObjectBuffers(maxSize);
285
286    _autoTransformCache.resize(maxSize);
287}
288
289
290void TextBase::releaseGLObjects(osg::State* state) const
291{
292    Drawable::releaseGLObjects(state);
293}
294
295void TextBase::positionCursor(const osg::Vec2 & endOfLine_coords, osg::Vec2 & cursor, unsigned int linelength)
296{
297    switch(_layout)
298    {
299        case LEFT_TO_RIGHT:
300        {
301            switch (_alignment)
302            {
303                // nothing to be done for these
304                //case LEFT_TOP:
305                //case LEFT_CENTER:
306                //case LEFT_BOTTOM:
307                //case LEFT_BASE_LINE:
308                //case LEFT_BOTTOM_BASE_LINE:
309                //  break;
310                case CENTER_TOP:
311                case CENTER_CENTER:
312                case CENTER_BOTTOM:
313                case CENTER_BASE_LINE:
314                case CENTER_BOTTOM_BASE_LINE:
315                    cursor.x() = (cursor.x() - endOfLine_coords.x()) * 0.5f;
316                    break;
317                case RIGHT_TOP:
318                case RIGHT_CENTER:
319                case RIGHT_BOTTOM:
320                case RIGHT_BASE_LINE:
321                case RIGHT_BOTTOM_BASE_LINE:
322                    cursor.x() = cursor.x() - endOfLine_coords.x();
323                    break;
324                default:
325                    break;
326            }
327            break;
328        }
329        case RIGHT_TO_LEFT:
330        {
331            switch (_alignment)
332            {
333                case LEFT_TOP:
334                case LEFT_CENTER:
335                case LEFT_BOTTOM:
336                case LEFT_BASE_LINE:
337                case LEFT_BOTTOM_BASE_LINE:
338                    cursor.x() = 2*cursor.x() - endOfLine_coords.x();
339                    break;
340                case CENTER_TOP:
341                case CENTER_CENTER:
342                case CENTER_BOTTOM:
343                case CENTER_BASE_LINE:
344                case CENTER_BOTTOM_BASE_LINE:
345                    cursor.x() = cursor.x() + (cursor.x() - endOfLine_coords.x()) * 0.5f;
346                    break;
347                    // nothing to be done for these
348                    //case RIGHT_TOP:
349                    //case RIGHT_CENTER:
350                    //case RIGHT_BOTTOM:
351                    //case RIGHT_BASE_LINE:
352                    //case RIGHT_BOTTOM_BASE_LINE:
353                    //  break;
354                default:
355                    break;
356            }
357            break;
358        }
359        case VERTICAL:
360        {
361            switch (_alignment)
362            {
363                // TODO: current behaviour top baselines lined up in both cases - need to implement
364                //       top of characters aligment - Question is this neccesary?
365                // ... otherwise, nothing to be done for these 6 cases
366                //case LEFT_TOP:
367                //case CENTER_TOP:
368                //case RIGHT_TOP:
369                //  break;
370                //case LEFT_BASE_LINE:
371                //case CENTER_BASE_LINE:
372                //case RIGHT_BASE_LINE:
373                //  break;
374                case LEFT_CENTER:
375                case CENTER_CENTER:
376                case RIGHT_CENTER:
377                    cursor.y() = cursor.y() + (cursor.y() - endOfLine_coords.y()) * 0.5f;
378                    break;
379                case LEFT_BOTTOM_BASE_LINE:
380                case CENTER_BOTTOM_BASE_LINE:
381                case RIGHT_BOTTOM_BASE_LINE:
382                    cursor.y() = cursor.y() - (linelength * _characterHeight);
383                    break;
384                case LEFT_BOTTOM:
385                case CENTER_BOTTOM:
386                case RIGHT_BOTTOM:
387                    cursor.y() = 2*cursor.y() - endOfLine_coords.y();
388                    break;
389                default:
390                    break;
391            }
392            break;
393        }
394    }
395}
Note: See TracBrowser for help on using the browser.