Changeset 13041 for OpenSceneGraph/trunk/src/osgText/Text.cpp
- Timestamp:
- 03/21/12 18:36:20 (14 months ago)
- Files:
-
- 1 modified
-
OpenSceneGraph/trunk/src/osgText/Text.cpp (modified) (49 diffs)
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgText/Text.cpp
r13001 r13041 1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 2 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 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 5 * (at your option) any later version. The full license is in LICENSE file 6 6 * included with this distribution, and on the openscenegraph.org website. 7 * 7 * 8 8 * This library is distributed in the hope that it will be useful, 9 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 11 * OpenSceneGraph Public License for more details. 12 12 */ … … 107 107 { 108 108 unsigned int charcode = *lastChar; 109 109 110 110 if (charcode=='\n') 111 111 { … … 166 166 break; 167 167 } 168 168 169 169 // => word boundary detection & wrapping 170 170 if (outOfSpace) break; … … 227 227 Font* activefont = getActiveFont(); 228 228 if (!activefont) return; 229 229 230 230 _textureGlyphQuadMap.clear(); 231 231 _lineCount = 0; 232 233 if (_text.empty()) 232 233 if (_text.empty()) 234 234 { 235 235 _textBB.set(0,0,0,0,0,0);//no size text … … 237 237 return; 238 238 } 239 239 240 240 //OpenThreads::ScopedLock<Font::FontMutex> lock(*(activefont->getSerializeFontCallsMutex())); 241 241 … … 246 246 osg::Vec2 cursor(startOfLine_coords); 247 247 osg::Vec2 local(0.0f,0.0f); 248 248 249 249 unsigned int previous_charcode = 0; 250 250 unsigned int linelength = 0; 251 251 bool horizontal = _layout!=VERTICAL; 252 252 bool kerning = true; 253 253 254 254 unsigned int lineNumber = 0; 255 255 … … 486 486 ++itr; 487 487 } 488 489 488 489 490 490 // move to new line. 491 491 switch(_layout) … … 517 517 break; 518 518 } 519 519 520 520 ++lineNumber; 521 521 522 522 } 523 523 524 524 TextBase::computePositions(); 525 525 computeBackdropBoundingBox(); … … 530 530 // Returns false if there are no glyphs and the width/height values are invalid. 531 531 // Also sets avg_width and avg_height to 0.0f if the value is invalid. 532 // This method is used several times in a loop for the same object which will produce the same values. 532 // This method is used several times in a loop for the same object which will produce the same values. 533 533 // Further optimization may try saving these values instead of recomputing them. 534 534 bool Text::computeAverageGlyphWidthAndHeight(float& avg_width, float& avg_height) const … … 544 544 bool is_valid_size = true; 545 545 // This section is going to try to compute the average width and height 546 // for a character among the text. The reason I shift by an 547 // average amount per-character instead of shifting each character 548 // by its per-instance amount is because it may look strange to see 549 // the individual backdrop text letters not space themselves the same 546 // for a character among the text. The reason I shift by an 547 // average amount per-character instead of shifting each character 548 // by its per-instance amount is because it may look strange to see 549 // the individual backdrop text letters not space themselves the same 550 550 // way the foreground text does. Using one value gives uniformity. 551 551 // Note: This loop is repeated for each context. I think it may produce … … 600 600 case CENTER_BASE_LINE: _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,0.0f,0.0f); break; 601 601 case RIGHT_BASE_LINE: _offset.set(_textBB.xMax(),0.0f,0.0f); break; 602 602 603 603 case LEFT_BOTTOM_BASE_LINE: _offset.set(0.0f,-_characterHeight*(1.0 + _lineSpacing)*(_lineCount-1),0.0f); break; 604 604 case CENTER_BOTTOM_BASE_LINE: _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,-_characterHeight*(1.0 + _lineSpacing)*(_lineCount-1),0.0f); break; 605 605 case RIGHT_BOTTOM_BASE_LINE: _offset.set(_textBB.xMax(),-_characterHeight*(1.0 + _lineSpacing)*(_lineCount-1),0.0f); break; 606 606 } 607 607 608 608 AutoTransformCache& atc = _autoTransformCache[contextID]; 609 609 osg::Matrix& matrix = atc._matrix; … … 614 614 matrix.makeTranslate(-_offset); 615 615 616 osg::Matrix rotate_matrix; 617 if (_autoRotateToScreen) 616 osg::Matrix rotate_matrix; 617 if (_autoRotateToScreen) 618 618 { 619 619 osg::Vec3d trans(atc._modelview.getTrans()); … … 634 634 M.postMult(atc._modelview); 635 635 osg::Matrix& P = atc._projection; 636 636 637 637 // compute the pixel size vector. 638 638 639 639 // pre adjust P00,P20,P23,P33 by multiplying them by the viewport window matrix. 640 640 // here we do it in short hand with the knowledge of how the window matrix is formed … … 687 687 } 688 688 689 if (_autoRotateToScreen) 689 if (_autoRotateToScreen) 690 690 { 691 691 matrix.postMult(rotate_matrix); … … 713 713 GlyphQuads::Coords2& coords2 = glyphquad._coords; 714 714 GlyphQuads::Coords3& transformedCoords = glyphquad._transformedCoords[contextID]; 715 715 716 716 unsigned int numCoords = coords2.size(); 717 717 if (numCoords!=transformedCoords.size()) … … 719 719 transformedCoords.resize(numCoords); 720 720 } 721 721 722 722 for(unsigned int i=0;i<numCoords;++i) 723 723 { … … 731 731 _normal.normalize(); 732 732 733 const_cast<Text*>(this)->dirtyBound(); 733 const_cast<Text*>(this)->dirtyBound(); 734 734 } 735 735 … … 746 746 unsigned int i; 747 747 bool is_valid_size; 748 748 749 749 AutoTransformCache& atc = _autoTransformCache[contextID]; 750 750 osg::Matrix& matrix = atc._matrix; … … 756 756 757 757 if (!is_valid_size) return; 758 758 759 759 // now apply matrix to the glyphs. 760 760 for(TextureGlyphQuadMap::iterator titr=_textureGlyphQuadMap.begin(); … … 832 832 vertical_shift_direction = 1.0f; 833 833 break; 834 } 834 } 835 835 case DROP_SHADOW_BOTTOM_LEFT: 836 836 { … … 863 863 } 864 864 865 // This method adjusts the bounding box to account for the expanded area caused by the backdrop. 865 // This method adjusts the bounding box to account for the expanded area caused by the backdrop. 866 866 // This assumes that the bounding box has already been computed for the text without the backdrop. 867 867 void Text::computeBackdropBoundingBox() const … … 875 875 float avg_height = 0.0f; 876 876 bool is_valid_size; 877 877 878 878 // FIXME: OPTIMIZE: It is possible that this value has already been computed before 879 879 // from previous calls to this function. This might be worth optimizing. … … 887 887 return; 888 888 } 889 889 890 890 // Finally, we have one more issue to deal with. 891 891 // Now that the text takes more space, we need … … 952 952 ); 953 953 break; 954 } 954 } 955 955 case DROP_SHADOW_BOTTOM_LEFT: 956 956 { … … 1007 1007 } 1008 1008 1009 // This method expands the bounding box to a settable margin when a bounding box drawing mode is active. 1009 // This method expands the bounding box to a settable margin when a bounding box drawing mode is active. 1010 1010 void Text::computeBoundingBoxMargin() const 1011 1011 { … … 1058 1058 1059 1059 for(i=0;i<coords2.size();++i) 1060 { 1060 { 1061 1061 // Min and Max are needed for color gradients 1062 1062 if(coords2[i].x() > max_x) … … 1075 1075 { 1076 1076 min_y = coords2[i].y(); 1077 } 1077 } 1078 1078 1079 1079 } … … 1134 1134 _colorGradientTopRight[2] 1135 1135 ); 1136 // Alpha does not convert to HSV 1136 // Alpha does not convert to HSV 1137 1137 float alpha = bilinearInterpolate( 1138 1138 min_x, … … 1146 1146 _colorGradientBottomRight[3], 1147 1147 _colorGradientTopRight[3] 1148 ); 1148 ); 1149 1149 1150 1150 colorCoords[i] = osg::Vec4(red,green,blue,alpha); … … 1251 1251 } 1252 1252 } 1253 1253 1254 1254 atc._traversalNumber = frameNumber; 1255 1255 atc._width = width; 1256 1256 atc._height = height; 1257 1257 1258 1258 if (doUpdate) 1259 { 1259 { 1260 1260 atc._transformedPosition = newTransformedPosition; 1261 1261 atc._projection = projection; … … 1264 1264 computePositions(contextID); 1265 1265 } 1266 1267 } 1268 1269 1266 1267 } 1268 1269 1270 1270 // Ensure that the glyph coordinates have been transformed for 1271 1271 // this context id. … … 1345 1345 #endif 1346 1346 } 1347 } 1347 } 1348 1348 1349 1349 #if defined(OSG_GL_FIXED_FUNCTION_AVAILABLE) … … 1402 1402 osg::Vec3 c01(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*matrix); 1403 1403 1404 1404 1405 1405 gl.Color4f(colorMultiplier.r()*_textBBColor.r(),colorMultiplier.g()*_textBBColor.g(),colorMultiplier.b()*_textBBColor.b(),colorMultiplier.a()*_textBBColor.a()); 1406 1406 gl.Begin(GL_LINE_LOOP); … … 1427 1427 1428 1428 state.applyTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OFF); 1429 1429 1430 1430 gl.Begin(GL_LINES); 1431 1431 gl.Vertex3fv(hl.ptr()); … … 1434 1434 gl.Vertex3fv(vb.ptr()); 1435 1435 gl.End(); 1436 1437 } 1436 1437 } 1438 1438 } 1439 1439 … … 1460 1460 pf.setVertexArray(glyphquad._transformedCoords[0].size(),&(glyphquad._transformedCoords[0].front())); 1461 1461 pf.drawArrays(GL_QUADS,0,glyphquad._transformedCoords[0].size()); 1462 1463 } 1464 1462 1463 } 1464 1465 1465 } 1466 1466 … … 1476 1476 { 1477 1477 TextBase::resizeGLObjectBuffers(maxSize); 1478 1478 1479 1479 getActiveFont()->resizeGLObjectBuffers(maxSize); 1480 1480 } … … 1557 1557 1558 1558 const GlyphQuads::Coords3& transformedCoords = glyphquad._transformedCoords[contextID]; 1559 if (!transformedCoords.empty()) 1559 if (!transformedCoords.empty()) 1560 1560 { 1561 1561 state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedCoords.front())); … … 1655 1655 { 1656 1656 const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; 1657 if (!transformedBackdropCoords.empty()) 1657 if (!transformedBackdropCoords.empty()) 1658 1658 { 1659 1659 state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); … … 1711 1711 { 1712 1712 const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; 1713 if (!transformedBackdropCoords.empty()) 1713 if (!transformedBackdropCoords.empty()) 1714 1714 { 1715 1715 state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); … … 1731 1731 #endif 1732 1732 } 1733 1733 1734 1734 1735 1735 void Text::renderWithNoDepthBuffer(osg::State& state, const osg::Vec4& colorMultiplier) const … … 1770 1770 { 1771 1771 const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; 1772 if (!transformedBackdropCoords.empty()) 1772 if (!transformedBackdropCoords.empty()) 1773 1773 { 1774 1774 state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); … … 1826 1826 { 1827 1827 const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; 1828 if (!transformedBackdropCoords.empty()) 1828 if (!transformedBackdropCoords.empty()) 1829 1829 { 1830 1830 state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); … … 1865 1865 unsigned int contextID = state.getContextID(); 1866 1866 TextureGlyphQuadMap::iterator titr; // Moved up here for VC6 1867 1867 1868 1868 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_STENCIL_TEST); 1869 1869 … … 1880 1880 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); 1881 1881 1882 // Disable writing to the color buffer so we only write to the stencil 1882 // Disable writing to the color buffer so we only write to the stencil 1883 1883 // buffer and the depth buffer 1884 1884 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); … … 1891 1891 // Arrrgh! Why does the code only seem to work correctly if I call this? 1892 1892 glDepthMask(GL_FALSE); 1893 1893 1894 1894 1895 1895 // Draw all the text to the stencil buffer to mark out the region 1896 1896 // that we can write too. 1897 1897 1898 1898 for(titr=_textureGlyphQuadMap.begin(); 1899 1899 titr!=_textureGlyphQuadMap.end(); … … 1924 1924 { 1925 1925 const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; 1926 if (!transformedBackdropCoords.empty()) 1926 if (!transformedBackdropCoords.empty()) 1927 1927 { 1928 1928 state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front())); … … 1933 1933 // Draw the foreground text 1934 1934 const GlyphQuads::Coords3& transformedCoords = glyphquad._transformedCoords[contextID]; 1935 if (!transformedCoords.empty()) 1935 if (!transformedCoords.empty()) 1936 1936 { 1937 1937 state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedCoords.front())); … … 1992 1992 { 1993 1993 const GlyphQuads::Coords3& transformedBackdropCoords = glyphquad._transformedBackdropCoords[backdrop_index][contextID]; 1994 if (!transformedBackdropCoords.empty()) 1994 if (!transformedBackdropCoords.empty()) 1995 1995 { 1996 1996 state.setVertexPointer( 3, GL_FLOAT, 0, &(transformedBackdropCoords.front()));
