]> git.mxchange.org Git - simgear.git/blobdiff - simgear/canvas/elements/CanvasText.cxx
Canvas: rework style setter system.
[simgear.git] / simgear / canvas / elements / CanvasText.cxx
index 3e5d78531cf71c3bfff0124c032894cd8b3b756c..a00cc1fa703f6b362a687034b6255dd273025c2d 100644 (file)
@@ -37,13 +37,15 @@ namespace canvas
       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;
   };
 
   //----------------------------------------------------------------------------
@@ -79,13 +81,13 @@ namespace canvas
   }
 
   //----------------------------------------------------------------------------
-  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);
@@ -102,7 +104,7 @@ namespace canvas
     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)
@@ -132,20 +134,21 @@ namespace canvas
                       + 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;
       }
     }
 
@@ -174,6 +177,70 @@ namespace canvas
     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,
@@ -187,22 +254,32 @@ namespace canvas
     _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();
   }
@@ -266,26 +343,9 @@ namespace canvas
 #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