Przeglądaj źródła

Use glyph metrics for spacing.

The CharacterSpacing property of Font can be used to add additional spacing
between characters and is by default 0.
Michal Srb 11 lat temu
rodzic
commit
15d91ed64c

+ 14 - 14
gameplay/src/Font.cpp

@@ -16,7 +16,7 @@ static std::vector<Font*> __fontCache;
 static Effect* __fontEffect = NULL;
 
 Font::Font() :
-    _format(BITMAP), _style(PLAIN), _size(0), _spacing(0.125f), _glyphs(NULL), _glyphCount(0), _texture(NULL), _batch(NULL), _cutoffParam(NULL)
+    _format(BITMAP), _style(PLAIN), _size(0), _spacing(0.0f), _glyphs(NULL), _glyphCount(0), _texture(NULL), _batch(NULL), _cutoffParam(NULL)
 {
 }
 
@@ -345,7 +345,7 @@ Font::Text* Font::createText(const char* text, const Rectangle& area, const Vect
             {
                 Glyph& g = _glyphs[glyphIndex];
 
-                if (xPos + (int)(g.width*scale) > area.x + area.width)
+                if (xPos + (int)(g.advance*scale) > area.x + area.width)
                 {
                     // Truncate this line and go on to the next one.
                     truncated = true;
@@ -358,11 +358,11 @@ Font::Text* Font::createText(const char* text, const Rectangle& area, const Vect
                     {
                         if (clip)
                         {
-                            _batch->addSprite(xPos, yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color, *clip, &batch->_vertices[batch->_vertexCount]);
+                            _batch->addSprite(xPos + (int)(g.bearingX * scale), yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color, *clip, &batch->_vertices[batch->_vertexCount]);
                         }
                         else
                         {
-                            _batch->addSprite(xPos, yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color, &batch->_vertices[batch->_vertexCount]);
+                            _batch->addSprite(xPos + (int)(g.bearingX * scale), yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color, &batch->_vertices[batch->_vertexCount]);
                         }
 
                         if (batch->_vertexCount == 0)
@@ -395,7 +395,7 @@ Font::Text* Font::createText(const char* text, const Rectangle& area, const Vect
 
                     }
                 }
-                xPos += (int)(g.width)*scale + spacing;
+                xPos += (int)(g.advance)*scale + spacing;
             }
         }
 
@@ -632,8 +632,8 @@ void Font::drawText(const char* text, int x, int y, const Vector4& color, unsign
                         // TODO: Fix me so that smaller font are much smoother
                         _cutoffParam->setVector2(Vector2(1.0, 1.0));
                     }
-                    _batch->draw(xPos, yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color);
-                    xPos += floor(g.width * scale + spacing);
+                    _batch->draw(xPos + (int)(g.bearingX * scale), yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color);
+                    xPos += floor(g.advance * scale + spacing);
                     break;
                 }
                 break;
@@ -778,7 +778,7 @@ void Font::drawText(const char* text, const Rectangle& area, const Vector4& colo
             {
                 Glyph& g = _glyphs[glyphIndex];
 
-                if (xPos + (int)(g.width*scale) > area.x + area.width)
+                if (xPos + (int)(g.advance*scale) > area.x + area.width)
                 {
                     // Truncate this line and go on to the next one.
                     truncated = true;
@@ -798,15 +798,15 @@ void Font::drawText(const char* text, const Rectangle& area, const Vector4& colo
                         }
                         if (clip)
                         {
-                            _batch->draw(xPos, yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color, *clip);
+                            _batch->draw(xPos + (int)(g.bearingX * scale), yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color, *clip);
                         }
                         else
                         {
-                            _batch->draw(xPos, yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color);
+                            _batch->draw(xPos + (int)(g.bearingX * scale), yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color);
                         }
                     }
                 }
-                xPos += (int)(g.width)*scale + spacing;
+                xPos += (int)(g.advance)*scale + spacing;
             }
         }
 
@@ -1627,7 +1627,7 @@ int Font::getIndexOrLocation(const char* text, const Rectangle& area, unsigned i
             {
                 Glyph& g = _glyphs[glyphIndex];
 
-                if (xPos + (int)(g.width*scale) > area.x + area.width)
+                if (xPos + (int)(g.advance*scale) > area.x + area.width)
                 {
                     // Truncate this line and go on to the next one.
                     truncated = true;
@@ -1645,7 +1645,7 @@ int Font::getIndexOrLocation(const char* text, const Rectangle& area, unsigned i
                     return charIndex;
                 }
 
-                xPos += floor(g.width*scale + spacing);
+                xPos += floor(g.advance*scale + spacing);
                 charIndex++;
             }
         }
@@ -1758,7 +1758,7 @@ unsigned int Font::getTokenWidth(const char* token, unsigned int length, unsigne
             if (glyphIndex >= 0 && glyphIndex < (int)_glyphCount)
             {
                 Glyph& g = _glyphs[glyphIndex];
-                tokenWidth += floor(g.width * scale + spacing);
+                tokenWidth += floor(g.advance * scale + spacing);
             }
             break;
         }

+ 13 - 4
gameplay/src/Font.h

@@ -264,15 +264,14 @@ public:
     float getCharacterSpacing() const;
 
     /**
-     * Sets the fixed character spacing for this font.
+     * Sets the additional character spacing for this font.
      *
-     * Character spacing is the fixed amount of space that is inserted between characters. This is a simplified
-     * type of kerning and does not take adjacent characters into consideration. Character spacing is defined
+     * Character spacing is the additional amount of space that is inserted between characters. Character spacing is defined
      * as a floating point value that is interpreted as a percentage of size used to draw the font. For example,
      * a value of 0.1 would cause a spacing of 10% of the font size to be inserted between adjacent characters.
      * For a font size of 20, this would equate to 2 pixels of extra space between characters.
      *
-     * The default character spacing for fonts is 0.125.
+     * The default additional character spacing for fonts is 0.0.
      *
      * @param spacing New fixed character spacing, expressed as a percentage of font size.
      */
@@ -327,6 +326,16 @@ private:
          */
         unsigned int width;
 
+        /**
+         * Glyph left side bearing (in pixels).
+         */
+        int bearingX;
+
+        /**
+         * Glyph horizontal advance (in pixels).
+         */
+        unsigned int advance;
+
         /**
          * Glyph texture coordinates.
          */

+ 2 - 0
tools/encoder/src/TTFFontEncoder.cpp

@@ -361,6 +361,8 @@ int writeFont(const char* inFilePath, const char* outFilePath, std::vector<unsig
 
             glyphArray[i].index = ascii;
             glyphArray[i].width = advance - GLYPH_PADDING;
+            glyphArray[i].bearingX = slot->metrics.horiBearingX >> 6;
+            glyphArray[i].advance = slot->metrics.horiAdvance >> 6;
 
             // Generate UV coords.
             glyphArray[i].uvCoords[0] = (float)penX / (float)imageWidth;

+ 2 - 0
tools/encoder/src/TTFFontEncoder.h

@@ -15,6 +15,8 @@ class TTFGlyph
 public:
     unsigned int index;
     unsigned int width;
+    int bearingX;
+    unsigned int advance;
     float uvCoords[4];
 };