From a2f9222753050e858e1c054432079f7f35f3d2fc Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 15 Sep 2003 21:43:54 +0000 Subject: [PATCH] Added support for handling of wordwrap in osgText::Text, so that whole words are cut in two, but rather moved completely to the next line. --- ChangeLog | 24 + examples/slideshow3D/SlideShowConstructor.cpp | 4 +- include/osgText/Text | 1 + src/osgText/Text.cpp | 518 ++++++++++++++---- 4 files changed, 439 insertions(+), 108 deletions(-) diff --git a/ChangeLog b/ChangeLog index d064455fc..c9c04a730 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2003-09-15 14:54 robert + + * VisualStudio/examples/slideshow3D/slideshow3D.dsp, + examples/slideshow3D/DefaultPresentation.cpp, + examples/slideshow3D/GNUmakefile, + examples/slideshow3D/ReaderWriterXML.cpp, + examples/slideshow3D/SlideShowConstructor.cpp, + examples/slideshow3D/SlideShowConstructor.h, + examples/slideshow3D/slideshow3D.cpp: Added support for correct + sizing of the created presentation w.r.t the size of the scene, a + default home position, handling of field in the slideshow + xml file, and support for stereo image pairs. + +2003-09-15 11:17 robert + + * ChangeLog, NEWS.txt: Updates ChangeLog and NEWS for the 0.9.6 + release. + +2003-09-15 11:12 robert + + * src/osgPlugins/txp/: trpage_geom.cpp, trpage_readbuf.cpp, + trpage_warchive.cpp, trpage_write.h: Fixes for warnings under + VS.NET from Marco Jez. + 2003-09-15 09:34 robert * NEWS.txt: Updated NEWS date to 15th September 2003, for 0.9.6 diff --git a/examples/slideshow3D/SlideShowConstructor.cpp b/examples/slideshow3D/SlideShowConstructor.cpp index 43379cb4c..1f49b015a 100644 --- a/examples/slideshow3D/SlideShowConstructor.cpp +++ b/examples/slideshow3D/SlideShowConstructor.cpp @@ -48,11 +48,11 @@ void SlideShowConstructor::setPresentationAspectRatio(const std::string& str) void SlideShowConstructor::createPresentation() { - _titleHeight = _slideHeight*0.08f; + _titleHeight = _slideHeight*0.06f; _titleWidth = _slideWidth*0.8f; _titleOrigin = _slideOrigin + osg::Vec3(_slideWidth*0.5f,0.0f,_slideHeight*0.98f-_titleHeight); - _textHeight = _slideHeight*0.05f; + _textHeight = _slideHeight*0.04f; _textWidth = _slideWidth*0.8f; _textOrigin = _slideOrigin + osg::Vec3(_slideWidth*0.1f,0.0f,_titleOrigin.z()-2*_textHeight); diff --git a/include/osgText/Text b/include/osgText/Text index cebd1b801..00fbc2e5f 100644 --- a/include/osgText/Text +++ b/include/osgText/Text @@ -285,6 +285,7 @@ protected: Font* getActiveFont(); const Font* getActiveFont() const; + String::iterator computeLastCharacterOnLine(osg::Vec2 cursor, String::iterator first,String::iterator last); // members which have public access. osg::ref_ptr _font; diff --git a/src/osgText/Text.cpp b/src/osgText/Text.cpp index f349ad89a..9a61ebd1e 100644 --- a/src/osgText/Text.cpp +++ b/src/osgText/Text.cpp @@ -22,6 +22,8 @@ using namespace osgText; +//#define TREES_CODE_FOR_MAKING_SPACES_EDITABLE + Text::Text(): _fontWidth(32), @@ -120,23 +122,17 @@ void Text::setText(const String& text) void Text::setText(const std::string& text) { setText(String(text)); -// _text.set(text); -// computeGlyphRepresentation(); } void Text::setText(const std::string& text,String::Encoding encoding) { setText(String(text,encoding)); -// _text.set(text,encoding); -// computeGlyphRepresentation(); } void Text::setText(const wchar_t* text) { setText(String(text)); -// _text.set(text); -// computeGlyphRepresentation(); } void Text::setPosition(const osg::Vec3& pos) @@ -242,60 +238,36 @@ const Font* Text::getActiveFont() const return _font.valid() ? _font.get() : DefaultFont::instance(); } -void Text::computeGlyphRepresentation() +String::iterator Text::computeLastCharacterOnLine(osg::Vec2 cursor, String::iterator first,String::iterator last) { Font* activefont = getActiveFont(); - if (!activefont) return; - - _textureGlyphQuadMap.clear(); - - if (_text.empty()) - { - _textBB.set(0,0,0,0,0,0);//no size text - computePositions(); //to reset the origin - return; - } - - osg::Vec2 startOfLine(0.0f,0.0f); - osg::Vec2 cursor(startOfLine); - osg::Vec2 local(0.0f,0.0f); - - unsigned int previous_charcode = 0; - bool horizontal = _layout!=VERTICAL; - bool kerning = true; + if (!activefont) return last; - activefont->setSize(_fontWidth,_fontHeight); - float hr = _characterHeight/(float)activefont->getHeight(); float wr = hr/_characterAspectRatio; - for(String::iterator itr=_text.begin(); - itr!=_text.end(); - ++itr) + bool horizontal = _layout!=VERTICAL; + bool kerning = true; + unsigned int previous_charcode = 0; + + for(String::iterator itr=first;itr!=last;++itr) { unsigned int charcode = *itr; if (charcode=='\n') { - if (horizontal) startOfLine.y() -= _characterHeight; - else startOfLine.x() += _characterHeight; - cursor = startOfLine; - previous_charcode = 0; - continue; + return itr; } - - + Font::Glyph* glyph = activefont->getGlyph(charcode); if (glyph) { float width = (float)(glyph->s()-2*activefont->getGlyphImageMargin()) * wr; - float height = (float)(glyph->t()-2*activefont->getGlyphImageMargin()) * hr; - //#define TREES_CODE_FOR_MAKING_SPACES_EDITABLE #ifdef TREES_CODE_FOR_MAKING_SPACES_EDITABLE if (width == 0.0f) width = glyph->getHorizontalAdvance() * wr; - if (height == 0.0f) height = glyph->getVerticalAdvance() * hr; #endif + if (_layout==RIGHT_TO_LEFT) { cursor.x() -= glyph->getHorizontalAdvance() * wr; @@ -323,98 +295,232 @@ void Text::computeGlyphRepresentation() case VERTICAL: break; // no kerning when vertical. } - } - - local = cursor; - + } osg::Vec2 bearing(horizontal?glyph->getHorizontalBearing():glyph->getVerticalBearing()); - local.x() += bearing.x() * wr; - local.y() += bearing.y() * hr; + cursor.x() += bearing.x() * wr; + cursor.y() += bearing.y() * hr; // check to see if we are still within line if not move to next line. switch(_layout) { case LEFT_TO_RIGHT: { - if (_maximumWidth>0.0f) - { - if (local.x()+width>_maximumWidth) - { - startOfLine.y() -= _characterHeight; - cursor = startOfLine; - previous_charcode = 0; - - local = cursor; - local.x() += bearing.x() * wr; - local.y() += bearing.y() * hr; - } - } + if (_maximumWidth>0.0f && cursor.x()+width>_maximumWidth) return itr; break; } case RIGHT_TO_LEFT: { - if (_maximumWidth>0.0f) - { - if (local.x()<-_maximumWidth) - { - startOfLine.y() -= _characterHeight; - cursor = startOfLine; - previous_charcode = 0; - - local = cursor; - local.x() += bearing.x() * wr; - local.y() += bearing.y() * hr; - } -; } + if (_maximumWidth>0.0f && cursor.x()<-_maximumWidth) return itr; break; } case VERTICAL: - if (_maximumHeight>0.0f) - { - if (local.y()<-_maximumHeight) - { - startOfLine.x() += _characterHeight/_characterAspectRatio; - cursor = startOfLine; - previous_charcode = 0; - - local = cursor; - local.x() += bearing.x() * wr; - local.y() += bearing.y() * hr; - } - } + if (_maximumHeight>0.0f && cursor.y()<-_maximumHeight) return itr; break; } - - GlyphQuads& glyphquad = _textureGlyphQuadMap[glyph->getTexture()->getStateSet()]; - glyphquad._glyphs.push_back(glyph); - // set up the coords of the quad - glyphquad._coords.push_back(local+osg::Vec2(0.0f,height)); - glyphquad._coords.push_back(local+osg::Vec2(0.0f,0.0f)); - glyphquad._coords.push_back(local+osg::Vec2(width,0.0f)); - glyphquad._coords.push_back(local+osg::Vec2(width,height)); - - // set up the tex coords of the quad - const osg::Vec2& mintc = glyph->getMinTexCoord(); - const osg::Vec2& maxtc = glyph->getMaxTexCoord(); - - glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),maxtc.y())); - glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),mintc.y())); - glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),mintc.y())); - glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),maxtc.y())); - // move the cursor onto the next character. switch(_layout) { case LEFT_TO_RIGHT: cursor.x() += glyph->getHorizontalAdvance() * wr; break; case VERTICAL: cursor.y() -= glyph->getVerticalAdvance() *hr; break; case RIGHT_TO_LEFT: break; // nop. - } + } } - - previous_charcode = charcode; + + } + return last; +} + + +#if 1 +void Text::computeGlyphRepresentation() +{ + Font* activefont = getActiveFont(); + if (!activefont) return; + + _textureGlyphQuadMap.clear(); + + if (_text.empty()) + { + _textBB.set(0,0,0,0,0,0);//no size text + computePositions(); //to reset the origin + return; + } + + osg::Vec2 startOfLine(0.0f,0.0f); + osg::Vec2 cursor(startOfLine); + osg::Vec2 local(0.0f,0.0f); + + unsigned int previous_charcode = 0; + bool horizontal = _layout!=VERTICAL; + bool kerning = true; + + activefont->setSize(_fontWidth,_fontHeight); + + float hr = _characterHeight/(float)activefont->getHeight(); + float wr = hr/_characterAspectRatio; + + std::set deliminatorSet; + deliminatorSet.insert(' '); + deliminatorSet.insert('\n'); + deliminatorSet.insert(':'); + deliminatorSet.insert('/'); + deliminatorSet.insert(','); + deliminatorSet.insert(';'); + deliminatorSet.insert(':'); + deliminatorSet.insert('.'); + + for(String::iterator itr=_text.begin(); + itr!=_text.end(); + ) + { + + // find the end of the current line. + String::iterator endOfLine = computeLastCharacterOnLine(cursor, itr,_text.end()); + + + if (itr!=endOfLine) + { + if (endOfLine!=_text.end()) + { + if (deliminatorSet.count(*endOfLine)==0) + { + String::iterator lastValidChar = endOfLine; + while (lastValidChar!=itr && deliminatorSet.count(*lastValidChar)==0) + { + --lastValidChar; + } + if (itr!=lastValidChar) + { + ++lastValidChar; + endOfLine = lastValidChar; + } + } + } + + for(;itr!=endOfLine;++itr) + { + + unsigned int charcode = *itr; + + Font::Glyph* glyph = activefont->getGlyph(charcode); + if (glyph) + { + + float width = (float)(glyph->s()-2*activefont->getGlyphImageMargin()) * wr; + float height = (float)(glyph->t()-2*activefont->getGlyphImageMargin()) * hr; + #ifdef TREES_CODE_FOR_MAKING_SPACES_EDITABLE + if (width == 0.0f) width = glyph->getHorizontalAdvance() * wr; + if (height == 0.0f) height = glyph->getVerticalAdvance() * hr; + #endif + if (_layout==RIGHT_TO_LEFT) + { + cursor.x() -= glyph->getHorizontalAdvance() * wr; + } + + // adjust cursor position w.r.t any kerning. + if (kerning && previous_charcode) + { + switch(_layout) + { + case LEFT_TO_RIGHT: + { + osg::Vec2 delta(activefont->getKerning(previous_charcode,charcode,_kerningType)); + cursor.x() += delta.x() * wr; + cursor.y() += delta.y() * hr; + break; + } + case RIGHT_TO_LEFT: + { + osg::Vec2 delta(activefont->getKerning(charcode,previous_charcode,_kerningType)); + cursor.x() -= delta.x() * wr; + cursor.y() -= delta.y() * hr; + break; + } + case VERTICAL: + break; // no kerning when vertical. + } + } + + local = cursor; + + + osg::Vec2 bearing(horizontal?glyph->getHorizontalBearing():glyph->getVerticalBearing()); + local.x() += bearing.x() * wr; + local.y() += bearing.y() * hr; + + + GlyphQuads& glyphquad = _textureGlyphQuadMap[glyph->getTexture()->getStateSet()]; + + glyphquad._glyphs.push_back(glyph); + + // set up the coords of the quad + glyphquad._coords.push_back(local+osg::Vec2(0.0f,height)); + glyphquad._coords.push_back(local+osg::Vec2(0.0f,0.0f)); + glyphquad._coords.push_back(local+osg::Vec2(width,0.0f)); + glyphquad._coords.push_back(local+osg::Vec2(width,height)); + + // set up the tex coords of the quad + const osg::Vec2& mintc = glyph->getMinTexCoord(); + const osg::Vec2& maxtc = glyph->getMaxTexCoord(); + + glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),maxtc.y())); + glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),mintc.y())); + glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),mintc.y())); + glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),maxtc.y())); + + // move the cursor onto the next character. + switch(_layout) + { + case LEFT_TO_RIGHT: cursor.x() += glyph->getHorizontalAdvance() * wr; break; + case VERTICAL: cursor.y() -= glyph->getVerticalAdvance() *hr; break; + case RIGHT_TO_LEFT: break; // nop. + } + + previous_charcode = charcode; + + } + } + } + else + { + ++itr; + } + + if (itr!=_text.end()) + { + // skip over return. + if (*itr=='\n') ++itr; + } + + // move to new line. + switch(_layout) + { + case LEFT_TO_RIGHT: + { + startOfLine.y() -= _characterHeight; + cursor = startOfLine; + previous_charcode = 0; + break; + } + case RIGHT_TO_LEFT: + { + startOfLine.y() -= _characterHeight; + cursor = startOfLine; + previous_charcode = 0; + break; + } + case VERTICAL: + { + startOfLine.x() += _characterHeight/_characterAspectRatio; + cursor = startOfLine; + previous_charcode = 0; + } + break; + } + } _textBB.init(); @@ -441,7 +547,207 @@ void Text::computeGlyphRepresentation() computePositions(); } +#else + void Text::computeGlyphRepresentation() + { + Font* activefont = getActiveFont(); + if (!activefont) return; + + _textureGlyphQuadMap.clear(); + + if (_text.empty()) + { + _textBB.set(0,0,0,0,0,0);//no size text + computePositions(); //to reset the origin + return; + } + + osg::Vec2 startOfLine(0.0f,0.0f); + osg::Vec2 cursor(startOfLine); + osg::Vec2 local(0.0f,0.0f); + + unsigned int previous_charcode = 0; + bool horizontal = _layout!=VERTICAL; + bool kerning = true; + + activefont->setSize(_fontWidth,_fontHeight); + + float hr = _characterHeight/(float)activefont->getHeight(); + float wr = hr/_characterAspectRatio; + + for(String::iterator itr=_text.begin(); + itr!=_text.end(); + ++itr) + { + unsigned int charcode = *itr; + + if (charcode=='\n') + { + if (horizontal) startOfLine.y() -= _characterHeight; + else startOfLine.x() += _characterHeight; + cursor = startOfLine; + previous_charcode = 0; + continue; + } + + + Font::Glyph* glyph = activefont->getGlyph(charcode); + if (glyph) + { + + float width = (float)(glyph->s()-2*activefont->getGlyphImageMargin()) * wr; + float height = (float)(glyph->t()-2*activefont->getGlyphImageMargin()) * hr; + #ifdef TREES_CODE_FOR_MAKING_SPACES_EDITABLE + if (width == 0.0f) width = glyph->getHorizontalAdvance() * wr; + if (height == 0.0f) height = glyph->getVerticalAdvance() * hr; + #endif + if (_layout==RIGHT_TO_LEFT) + { + cursor.x() -= glyph->getHorizontalAdvance() * wr; + } + + // adjust cursor position w.r.t any kerning. + if (kerning && previous_charcode) + { + switch(_layout) + { + case LEFT_TO_RIGHT: + { + osg::Vec2 delta(activefont->getKerning(previous_charcode,charcode,_kerningType)); + cursor.x() += delta.x() * wr; + cursor.y() += delta.y() * hr; + break; + } + case RIGHT_TO_LEFT: + { + osg::Vec2 delta(activefont->getKerning(charcode,previous_charcode,_kerningType)); + cursor.x() -= delta.x() * wr; + cursor.y() -= delta.y() * hr; + break; + } + case VERTICAL: + break; // no kerning when vertical. + } + } + + local = cursor; + + + osg::Vec2 bearing(horizontal?glyph->getHorizontalBearing():glyph->getVerticalBearing()); + local.x() += bearing.x() * wr; + local.y() += bearing.y() * hr; + + // check to see if we are still within line if not move to next line. + switch(_layout) + { + case LEFT_TO_RIGHT: + { + if (_maximumWidth>0.0f) + { + if (local.x()+width>_maximumWidth) + { + startOfLine.y() -= _characterHeight; + cursor = startOfLine; + previous_charcode = 0; + + local = cursor; + local.x() += bearing.x() * wr; + local.y() += bearing.y() * hr; + } + } + break; + } + case RIGHT_TO_LEFT: + { + if (_maximumWidth>0.0f) + { + if (local.x()<-_maximumWidth) + { + startOfLine.y() -= _characterHeight; + cursor = startOfLine; + previous_charcode = 0; + + local = cursor; + local.x() += bearing.x() * wr; + local.y() += bearing.y() * hr; + } + ; } + break; + } + case VERTICAL: + if (_maximumHeight>0.0f) + { + if (local.y()<-_maximumHeight) + { + startOfLine.x() += _characterHeight/_characterAspectRatio; + cursor = startOfLine; + previous_charcode = 0; + + local = cursor; + local.x() += bearing.x() * wr; + local.y() += bearing.y() * hr; + } + } + break; + } + + GlyphQuads& glyphquad = _textureGlyphQuadMap[glyph->getTexture()->getStateSet()]; + + glyphquad._glyphs.push_back(glyph); + + // set up the coords of the quad + glyphquad._coords.push_back(local+osg::Vec2(0.0f,height)); + glyphquad._coords.push_back(local+osg::Vec2(0.0f,0.0f)); + glyphquad._coords.push_back(local+osg::Vec2(width,0.0f)); + glyphquad._coords.push_back(local+osg::Vec2(width,height)); + + // set up the tex coords of the quad + const osg::Vec2& mintc = glyph->getMinTexCoord(); + const osg::Vec2& maxtc = glyph->getMaxTexCoord(); + + glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),maxtc.y())); + glyphquad._texcoords.push_back(osg::Vec2(mintc.x(),mintc.y())); + glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),mintc.y())); + glyphquad._texcoords.push_back(osg::Vec2(maxtc.x(),maxtc.y())); + + // move the cursor onto the next character. + switch(_layout) + { + case LEFT_TO_RIGHT: cursor.x() += glyph->getHorizontalAdvance() * wr; break; + case VERTICAL: cursor.y() -= glyph->getVerticalAdvance() *hr; break; + case RIGHT_TO_LEFT: break; // nop. + } + } + + previous_charcode = charcode; + } + + _textBB.init(); + + for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin(); + titr!=_textureGlyphQuadMap.end(); + ++titr) + { + const GlyphQuads& glyphquad = titr->second; + + for(GlyphQuads::Coords2::const_iterator citr = glyphquad._coords.begin(); + citr != glyphquad._coords.end(); + ++citr) + { + _textBB.expandBy(osg::Vec3(citr->x(),citr->y(),0.0f)); + } + } + + if (!_textureGlyphQuadMap.empty()) + { + setStateSet(const_cast((*_textureGlyphQuadMap.begin()).first.get())); + } + + computePositions(); + } + +#endif void Text::computePositions() { for(unsigned int i=0;i<_autoTransformCache.size();++i)