void setFill(const std::string& fill);
void setBackgroundColor(const std::string& fill);
- osg::Vec2 handleHit(float x, float y);
+ osg::Vec2 handleHit(const osg::Vec2f& pos);
virtual osg::BoundingBox computeBound() const;
protected:
canvas::Text *_text_element;
+
+ virtual void computePositions(unsigned int contextID) const;
};
//----------------------------------------------------------------------------
}
//----------------------------------------------------------------------------
- osg::Vec2 Text::TextOSG::handleHit(float x, float y)
+ osg::Vec2 Text::TextOSG::handleHit(const osg::Vec2f& pos)
{
float line_height = _characterHeight + _lineSpacing;
// TODO check with align other than TOP
float first_line_y = -0.5 * _lineSpacing;//_offset.y() - _characterHeight;
- size_t line = std::max<int>(0, (y - first_line_y) / line_height);
+ size_t line = std::max<int>(0, (pos.y() - first_line_y) / line_height);
if( _textureGlyphQuadMap.empty() )
return osg::Vec2(-1, -1);
const float character_width = getCharacterHeight()
* getCharacterAspectRatio();
- y = (line + 0.5) * line_height;
+ float y = (line + 0.5) * line_height;
bool line_found = false;
for(size_t i = 0; i < line_numbers.size(); ++i)
+ HIT_FRACTION * glyphs[i]->getHorizontalAdvance()
* character_width;
- if( x <= threshold )
+ if( pos.x() <= threshold )
{
+ osg::Vec2 hit(0, y);
if( i == 0 || line_numbers[i - 1] != line )
// first character of line
- x = coords[i * 4].x();
+ hit.x() = coords[i * 4].x();
else if( coords[(i - 1) * 4].x() == coords[(i - 1) * 4 + 2].x() )
// If previous character width is zero set to begin of next character
// (Happens eg. with spaces)
- x = coords[i * 4].x();
+ hit.x() = coords[i * 4].x();
else
// position at center between characters
- x = 0.5 * (coords[(i - 1) * 4 + 2].x() + coords[i * 4].x());
+ hit.x() = 0.5 * (coords[(i - 1) * 4 + 2].x() + coords[i * 4].x());
- return osg::Vec2(x, y);
+ return hit;
}
}
return bb;
}
+ //----------------------------------------------------------------------------
+ void Text::TextOSG::computePositions(unsigned int contextID) const
+ {
+ if( _textureGlyphQuadMap.empty() || _layout == VERTICAL )
+ return osgText::Text::computePositions(contextID);
+
+ // TODO check when it can be larger
+ assert( _textureGlyphQuadMap.size() == 1 );
+
+ const GlyphQuads& quads = _textureGlyphQuadMap.begin()->second;
+ const GlyphQuads::Glyphs& glyphs = quads._glyphs;
+ const GlyphQuads::Coords2& coords = quads._coords;
+ const GlyphQuads::LineNumbers& line_numbers = quads._lineNumbers;
+
+ float wr = _characterHeight / getCharacterAspectRatio();
+
+ size_t cur_line = static_cast<size_t>(-1);
+ for(size_t i = 0; i < glyphs.size(); ++i)
+ {
+ // Check horizontal offsets
+
+ bool first_char = cur_line != line_numbers[i];
+ cur_line = line_numbers[i];
+
+ bool last_char = (i + 1 == glyphs.size())
+ || (cur_line != line_numbers[i + 1]);
+
+ if( first_char || last_char )
+ {
+ // From osg/src/osgText/Text.cpp:
+ //
+ // osg::Vec2 upLeft = local+osg::Vec2(0.0f-fHorizQuadMargin, ...);
+ // osg::Vec2 lowLeft = local+osg::Vec2(0.0f-fHorizQuadMargin, ...);
+ // osg::Vec2 lowRight = local+osg::Vec2(width+fHorizQuadMargin, ...);
+ // osg::Vec2 upRight = local+osg::Vec2(width+fHorizQuadMargin, ...);
+
+ float left = coords[i * 4].x(),
+ right = coords[i * 4 + 2].x(),
+ width = glyphs[i]->getWidth() * wr;
+
+ // (local + width + fHoriz) - (local - fHoriz) = width + 2*fHoriz | -width
+ float margin = 0.5f * (right - left - width),
+ cursor_x = left + margin
+ - glyphs[i]->getHorizontalBearing().x() * wr;
+
+ if( first_char )
+ {
+ if( cur_line == 0 || cursor_x < _textBB._min.x() )
+ _textBB._min.x() = cursor_x;
+ }
+
+ if( last_char )
+ {
+ float cursor_w = cursor_x + glyphs[i]->getHorizontalAdvance() * wr;
+
+ if( cur_line == 0 || cursor_w > _textBB._max.x() )
+ _textBB._max.x() = cursor_w;
+ }
+ }
+ }
+
+ return osgText::Text::computePositions(contextID);
+ }
+
//----------------------------------------------------------------------------
Text::Text( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
_text->setAxisAlignment(osgText::Text::USER_DEFINED_ROTATION);
_text->setRotation(osg::Quat(osg::PI, osg::X_AXIS));
- addStyle("fill", &TextOSG::setFill, _text);
- addStyle("background", &TextOSG::setBackgroundColor, _text);
- addStyle("character-size",
- static_cast<void (TextOSG::*)(float)>(&TextOSG::setCharacterSize),
- _text);
- addStyle("character-aspect-ratio", &TextOSG::setCharacterAspect, _text);
- addStyle("padding", &TextOSG::setBoundingBoxMargin, _text);
- // TEXT = 1 default
- // BOUNDINGBOX = 2
- // FILLEDBOUNDINGBOX = 4
- // ALIGNMENT = 8
- addStyle<int>("draw-mode", &TextOSG::setDrawMode, _text);
- addStyle("max-width", &TextOSG::setMaximumWidth, _text);
- addStyle("font", &Text::setFont, this);
- addStyle("alignment", &Text::setAlignment, this);
- addStyle("text", &Text::setText, this);
+ if( !isInit<Text>() )
+ {
+ osg::ref_ptr<TextOSG> Text::*text = &Text::_text;
+
+ addStyle("fill", "color", &TextOSG::setFill, text);
+ addStyle("background", "color", &TextOSG::setBackgroundColor, text);
+ addStyle("character-size",
+ "numeric",
+ static_cast<
+ void (TextOSG::*)(float)
+ > (&TextOSG::setCharacterSize),
+ text);
+ addStyle("character-aspect-ratio",
+ "numeric",
+ &TextOSG::setCharacterAspect, text);
+ addStyle("padding", "numeric", &TextOSG::setBoundingBoxMargin, text);
+ // TEXT = 1 default
+ // BOUNDINGBOX = 2
+ // FILLEDBOUNDINGBOX = 4
+ // ALIGNMENT = 8
+ addStyle<int>("draw-mode", "", &TextOSG::setDrawMode, text);
+ addStyle("max-width", "numeric", &TextOSG::setMaximumWidth, text);
+ addStyle("font", "", &Text::setFont);
+ addStyle("alignment", "", &Text::setAlignment);
+ addStyle("text", "", &Text::setText);
+ }
setupStyle();
}
#endif
//----------------------------------------------------------------------------
- void Text::childChanged(SGPropertyNode* child)
- {
- if( child->getParent() != _node )
- return;
-
- const std::string& name = child->getNameString();
- if( name == "hit-y" )
- handleHit
- (
- _node->getFloatValue("hit-x"),
- _node->getFloatValue("hit-y")
- );
- }
-
- //----------------------------------------------------------------------------
- void Text::handleHit(float x, float y)
+ osg::Vec2 Text::getNearestCursor(const osg::Vec2& pos) const
{
- const osg::Vec2& pos = _text->handleHit(x, y);
- _node->setFloatValue("cursor-x", pos.x());
- _node->setFloatValue("cursor-y", pos.y());
+ return _text->handleHit(pos);
}
} // namespace canvas