Browse Source

Added glyph offset functionality to Font. Closes #13.

Lasse Öörni 11 years ago
parent
commit
d7924f907f

+ 3 - 0
Docs/AngelScriptAPI.h

@@ -4142,6 +4142,7 @@ float quantize;
 class Font
 {
 // Methods:
+IntVector2 GetTotalGlyphOffset(int) const;
 bool Load(File);
 bool Load(VectorBuffer&);
 bool Save(File) const;
@@ -4152,6 +4153,7 @@ bool SaveXML(const String&, int, bool = false);
 void SendEvent(const String&, VariantMap& = VariantMap ( ));
 
 // Properties:
+IntVector2 absoluteGlyphOffset;
 /* readonly */
 StringHash baseType;
 /* readonly */
@@ -4161,6 +4163,7 @@ uint memoryUse;
 String name;
 /* readonly */
 int refs;
+Vector2 scaledGlyphOffset;
 /* readonly */
 StringHash type;
 /* readonly */

+ 14 - 0
Docs/LuaScriptAPI.dox

@@ -2163,6 +2163,20 @@ Methods:
 <a name="Class_Font"></a>
 ### Font : Resource
 
+Methods:
+
+- void SetAbsoluteGlyphOffset(const IntVector2& offset)
+- void SetScaledGlyphOffset(const Vector2& offset)
+- const IntVector2& GetAbsoluteGlyphOffset() const
+- const Vector2& GetScaledGlyphOffset() const
+- IntVector2 GetTotalGlyphOffset(int pointSize) const
+- bool IsSDFFont() const
+
+Properties:
+
+- IntVector2 absoluteGlyphOffset
+- Vector2 scaledGlyphOffset
+
 <a name="Class_Frustum"></a>
 ### Frustum
 

+ 13 - 1
Docs/Reference.dox

@@ -1713,13 +1713,25 @@ To create automatically adjusting layouts, the layout mode can be switched to ei
 
 Left, top, right & bottom border widths and spacing between elements can also be specified for the layout. A grid layout is not directly supported, but it can be manually created with a horizontal layout inside a vertical layout, or vice versa.
 
+\section UI_Fonts Fonts
+
+Urho3D supports both FreeType (.ttf, .otf) and \ref http://www.angelcode.com/products/bmfont/ "bitmap" fonts.
+
+For FreeType fonts, it is possible to adjust the positioning of the font glyphs. See \ref Font::SetAbsoluteGlyphOffset "SetAbsoluteGlyphOffset()" to set a fixed pixel offset for all point sizes, or \ref Font::SetScaledGlyphOffset "SetScaledGlyphOffset()" to set a floating point offset that will be multiplied with the point size before applying. The offset information can be also stored in an accompanying XML file next to the font file, which is formatted in the following way: (it is legal to specify either or both of absolute and scaled offsets, and either or both of X & Y coordinates)
+
+\code
+<font>
+    <absoluteoffset x="xInt" y="yInt" />
+    <scaledoffset x="xFloat" y="yFloat" />
+</font>
+\endcode
+
 \section UI_Sprites Sprites
 
 Sprites are a special kind of %UI element that allow subpixel (float) positioning and scaling, as well as rotation, while the other elements use integer positioning for pixel-perfect display. Sprites can be used to implement rotating HUD elements such as minimaps or speedometer needles.
 
 Due to the free transformability, sprites can not be reliably queried with \ref UI::GetElementAt "GetElementAt()". Also, only other sprites should be parented to sprites, as the other elements do not support scaling and rotation.
 
-
 \page Urho2D Urho2D
 In order to make 2D games in Urho3D, the Urho2D sublibrary is provided. Urho2D includes 2D graphics and 2D physics.
 

+ 3 - 0
Docs/ScriptAPI.dox

@@ -5730,6 +5730,7 @@ Properties:
 
 Methods:
 
+- IntVector2 GetTotalGlyphOffset(int) const
 - bool Load(File@)
 - bool Load(VectorBuffer&)
 - bool Save(File@) const
@@ -5741,11 +5742,13 @@ Methods:
 
 Properties:
 
+- IntVector2 absoluteGlyphOffset
 - StringHash baseType // readonly
 - String category // readonly
 - uint memoryUse // readonly
 - String name
 - int refs // readonly
+- Vector2 scaledGlyphOffset
 - StringHash type // readonly
 - String typeName // readonly
 - uint useTimer // readonly

+ 10 - 0
Source/Engine/LuaScript/pkgs/UI/Font.pkg

@@ -2,4 +2,14 @@ $#include "Font.h"
 
 class Font : public Resource
 {
+    void SetAbsoluteGlyphOffset(const IntVector2& offset);
+    void SetScaledGlyphOffset(const Vector2& offset);
+    
+    const IntVector2& GetAbsoluteGlyphOffset() const;
+    const Vector2& GetScaledGlyphOffset() const;
+    IntVector2 GetTotalGlyphOffset(int pointSize) const;
+    bool IsSDFFont() const;
+    
+    tolua_property__get_set IntVector2 absoluteGlyphOffset;
+    tolua_property__get_set Vector2 scaledGlyphOffset;
 };

+ 5 - 0
Source/Engine/Script/UIAPI.cpp

@@ -66,6 +66,11 @@ static void RegisterFont(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Font", "bool SaveXML(File@+, int, bool arg2 = false)", asMETHOD(Font, SaveXML), asCALL_THISCALL);
     engine->RegisterObjectMethod("Font", "bool SaveXML(VectorBuffer&, int, bool arg2 = false)", asFUNCTION(FontSaveXMLVectorBuffer), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Font", "bool SaveXML(const String&in, int, bool arg2 = false)", asFUNCTION(FontSaveXML), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Font", "IntVector2 GetTotalGlyphOffset(int) const", asMETHOD(Font, GetTotalGlyphOffset), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Font", "void set_absoluteGlyphOffset(const IntVector2&)", asMETHOD(Font, SetAbsoluteGlyphOffset), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Font", "const IntVector2& get_absoluteGlyphOffset() const", asMETHOD(Font, GetAbsoluteGlyphOffset), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Font", "void set_scaledGlyphOffset(const Vector2&)", asMETHOD(Font, SetScaledGlyphOffset), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Font", "const Vector2& get_scaledGlyphOffset() const", asMETHOD(Font, GetScaledGlyphOffset), asCALL_THISCALL);
 }
 
 static void RegisterUIElement(asIScriptEngine* engine)

+ 55 - 0
Source/Engine/UI/Font.cpp

@@ -29,6 +29,9 @@
 #include "FontFaceFreeType.h"
 #include "Graphics.h"
 #include "Profiler.h"
+#include "ResourceCache.h"
+#include "XMLElement.h"
+#include "XMLFile.h"
 
 #include "DebugNew.h"
 
@@ -41,6 +44,8 @@ static const int MAX_POINT_SIZE = 96;
 Font::Font(Context* context) :
     Resource(context),
     fontDataSize_(0),
+    absoluteOffset_(IntVector2::ZERO),
+    scaledOffset_(Vector2::ZERO),
     fontType_(FONT_NONE),
     sdfFont_(false)
 {
@@ -83,7 +88,10 @@ bool Font::BeginLoad(Deserializer& source)
 
     String ext = GetExtension(GetName());
     if (ext == ".ttf" || ext == ".otf" || ext == ".woff")
+    {
         fontType_ = FONT_FREETYPE;
+        LoadParameters();
+    }
     else if (ext == ".xml" || ext == ".fnt" || ext == ".sdf")
         fontType_ = FONT_BITMAP;
 
@@ -108,6 +116,16 @@ bool Font::SaveXML(Serializer& dest, int pointSize, bool usedGlyphs)
     return packedFontFace->Save(dest, pointSize);
 }
 
+void Font::SetAbsoluteGlyphOffset(const IntVector2& offset)
+{
+    absoluteOffset_ = offset;
+}
+
+void Font::SetScaledGlyphOffset(const Vector2& offset)
+{
+    scaledOffset_ = offset;
+}
+
 FontFace* Font::GetFace(int pointSize)
 {
     // In headless mode, always return null
@@ -148,11 +166,48 @@ FontFace* Font::GetFace(int pointSize)
     }
 }
 
+IntVector2 Font::GetTotalGlyphOffset(int pointSize) const
+{
+    Vector2 multipliedOffset = (float)pointSize * scaledOffset_;
+    return absoluteOffset_ + IntVector2((int)multipliedOffset.x_, (int)multipliedOffset.y_);
+}
+
 void Font::ReleaseFaces()
 {
     faces_.Clear();
 }
 
+void Font::LoadParameters()
+{
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    String xmlName = ReplaceExtension(GetName(), ".xml");
+    SharedPtr<XMLFile> xml = cache->GetTempResource<XMLFile>(xmlName, false);
+    if (!xml)
+        return;
+    
+    XMLElement rootElem = xml->GetRoot();
+    
+    XMLElement absoluteElem = rootElem.GetChild("absoluteoffset");
+    if (!absoluteElem)
+        absoluteElem = rootElem.GetChild("absolute");
+    
+    if (absoluteElem)
+    {
+        absoluteOffset_.x_ = absoluteElem.GetInt("x");
+        absoluteOffset_.y_ = absoluteElem.GetInt("y");
+    }
+    
+    XMLElement scaledElem = rootElem.GetChild("scaledoffset");
+    if (!scaledElem)
+        scaledElem = rootElem.GetChild("scaled");
+    
+    if (scaledElem)
+    {
+        scaledOffset_.x_ = scaledElem.GetFloat("x");
+        scaledOffset_.y_ = scaledElem.GetFloat("y");
+    }
+}
+
 FontFace* Font::GetFaceFreeType(int pointSize)
 {
     SharedPtr<FontFace> newFace(new FontFaceFreeType(this));

+ 19 - 2
Source/Engine/UI/Font.h

@@ -59,16 +59,29 @@ public:
     virtual bool BeginLoad(Deserializer& source);
     /// Save resource as a new bitmap font type in XML format. Return true if successful.
     bool SaveXML(Serializer& dest, int pointSize, bool usedGlyphs = false);
+    /// Set absolute (in pixels) position adjustment for glyphs.
+    void SetAbsoluteGlyphOffset(const IntVector2& offset);
+    /// Set point size scaled position adjustment for glyphs.
+    void SetScaledGlyphOffset(const Vector2& offset);
+
     /// Return font face. Pack and render to a texture if not rendered yet. Return null on error.
     FontFace* GetFace(int pointSize);
     /// Is signed distance field font.
     bool IsSDFFont() const { return sdfFont_; }
+    /// Return absolute position adjustment for glyphs.
+    const IntVector2& GetAbsoluteGlyphOffset() const { return absoluteOffset_; }
+    /// Return point size scaled position adjustment for glyphs.
+    const Vector2& GetScaledGlyphOffset() const { return scaledOffset_; }
+    /// Return the total effective offset for a point size.
+    IntVector2 GetTotalGlyphOffset(int pointSize) const;
     
     /// Release font faces and recreate them next time when requested. Called when font textures lost or global font properties change.
     void ReleaseFaces();
     
 private:
-    /// Return font face using FreeTyp. Called internally. Return null on error.
+    /// Load font glyph offset parameters from an optional XML file. Called internally when loading TrueType fonts.
+    void LoadParameters();
+    /// Return font face using FreeType. Called internally. Return null on error.
     FontFace* GetFaceFreeType(int pointSize);
     /// Return bitmap font face. Called internally. Return null on error.
     FontFace* GetFaceBitmap(int pointSize);
@@ -79,9 +92,13 @@ private:
     SharedArrayPtr<unsigned char> fontData_;
     /// Size of font data.
     unsigned fontDataSize_;
+    /// Absolute position adjustment for glyphs.
+    IntVector2 absoluteOffset_;
+    /// Point size scaled position adjustment for glyphs.
+    Vector2 scaledOffset_;
     /// Font type.
     FONT_TYPE fontType_;
-    /// Signed distance field font.
+    /// Signed distance field font flag.
     bool sdfFont_;
 };
 

+ 5 - 2
Source/Engine/UI/Text.cpp

@@ -597,10 +597,13 @@ void Text::UpdateCharLocations()
     for (unsigned i = 0; i < pageGlyphLocations_.Size(); ++i)
         pageGlyphLocations_[i].Clear();
 
+    IntVector2 offset = font_->GetTotalGlyphOffset(fontSize_);
+    
     unsigned rowIndex = 0;
     unsigned lastFilled = 0;
-    int x = GetRowStartPosition(rowIndex);
-    int y = 0;
+    int x = GetRowStartPosition(rowIndex) + offset.x_;
+    int y = offset.y_;
+    
     for (unsigned i = 0; i < printText_.Size(); ++i)
     {
         CharLocation loc;