]> git.mxchange.org Git - simgear.git/blobdiff - simgear/canvas/elements/CanvasText.cxx
Canvas: Respect clipping while event handling.
[simgear.git] / simgear / canvas / elements / CanvasText.cxx
index c92a9ecfbad7e80705921389aaf5795c454c60e0..f73a6ce8ccc2d7d14f352fad1294e061e00dbcd5 100644 (file)
@@ -20,6 +20,7 @@
 #include <simgear/canvas/Canvas.hxx>
 #include <simgear/canvas/CanvasSystemAdapter.hxx>
 #include <simgear/scene/util/parse_color.hxx>
+#include <osg/Version>
 #include <osgText/Text>
 
 namespace simgear
@@ -33,7 +34,9 @@ namespace canvas
 
       TextOSG(canvas::Text* text);
 
+      void setFontResolution(int res);
       void setCharacterAspect(float aspect);
+      void setLineHeight(float factor);
       void setFill(const std::string& fill);
       void setBackgroundColor(const std::string& fill);
 
@@ -44,13 +47,21 @@ namespace canvas
     protected:
 
       canvas::Text *_text_element;
+
+      virtual void computePositions(unsigned int contextID) const;
   };
 
   //----------------------------------------------------------------------------
   Text::TextOSG::TextOSG(canvas::Text* text):
     _text_element(text)
   {
+    setBackdropImplementation(NO_DEPTH_BUFFER);
+  }
 
+  //----------------------------------------------------------------------------
+  void Text::TextOSG::setFontResolution(int res)
+  {
+    TextBase::setFontResolution(res, res);
   }
 
   //----------------------------------------------------------------------------
@@ -59,6 +70,12 @@ namespace canvas
     setCharacterSize(getCharacterHeight(), aspect);
   }
 
+  //----------------------------------------------------------------------------
+  void Text::TextOSG::setLineHeight(float factor)
+  {
+    setLineSpacing(factor - 1);
+  }
+
   //----------------------------------------------------------------------------
   void Text::TextOSG::setFill(const std::string& fill)
   {
@@ -165,16 +182,118 @@ namespace canvas
     if( !bb.valid() )
       return bb;
 
+#if OSG_VERSION_LESS_THAN(3,1,0)
     // TODO bounding box still doesn't seem always right (eg. with center
     //      horizontal alignment not completely accurate)
     bb._min.y() += _offset.y();
     bb._max.y() += _offset.y();
+#endif
 
     _text_element->setBoundingBox(bb);
 
     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);
+  }
+
+  //----------------------------------------------------------------------------
+  const std::string Text::TYPE_NAME = "text";
+
+  //----------------------------------------------------------------------------
+  void Text::staticInit()
+  {
+    if( isInit<Text>() )
+      return;
+
+    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("line-height", "numeric", &TextOSG::setLineHeight, text);
+    addStyle("font-resolution", "numeric", &TextOSG::setFontResolution, 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, false);
+  }
+
   //----------------------------------------------------------------------------
   Text::Text( const CanvasWeakPtr& canvas,
               const SGPropertyNode_ptr& node,
@@ -183,28 +302,13 @@ namespace canvas
     Element(canvas, node, parent_style, parent),
     _text( new Text::TextOSG(this) )
   {
+    staticInit();
+
     setDrawable(_text);
     _text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);
     _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);
-
     setupStyle();
   }
 
@@ -223,7 +327,7 @@ namespace canvas
   //----------------------------------------------------------------------------
   void Text::setFont(const char* name)
   {
-    _text->setFont( _canvas.lock()->getSystemAdapter()->getFont(name) );
+    _text->setFont( Canvas::getSystemAdapter()->getFont(name) );
   }
 
   //----------------------------------------------------------------------------