[aseprite] 71/196: Simplify ft::Face API

Tobias Hansen thansen at moszumanska.debian.org
Wed Apr 20 18:50:03 UTC 2016


This is an automated email from the git hooks/post-receive script.

thansen pushed a commit to branch master
in repository aseprite.

commit 2fd94ed884250a837a846d5323f475dabbc01217
Author: David Capello <davidcapello at gmail.com>
Date:   Tue Mar 15 15:15:37 2016 -0300

    Simplify ft::Face API
    
    Changes:
    * Added ft::FaceBase to create a future Face impl with HarfBuzz as text
      shaping engine
    * Define ft::FaceBase::Glyph as the parameter given to the forEachGlyph
      parameter
    * forEachGlyph and calcTextBounds
    * Remove operator FT_Face (we can use FaceBase::isValid() to know if the
      face isn't null)
---
 src/app/util/freetype_utils.cpp  | 20 ++++-----
 src/ft/face.h                    | 93 +++++++++++++++++++++++++---------------
 src/she/common/freetype_font.cpp | 10 +++--
 src/she/common/generic_surface.h | 56 +++++++++++++++---------
 4 files changed, 109 insertions(+), 70 deletions(-)

diff --git a/src/app/util/freetype_utils.cpp b/src/app/util/freetype_utils.cpp
index 69c4b66..ca095a8 100644
--- a/src/app/util/freetype_utils.cpp
+++ b/src/app/util/freetype_utils.cpp
@@ -11,7 +11,6 @@
 
 #include "app/util/freetype_utils.h"
 
-#include "base/string.h"
 #include "base/unique_ptr.h"
 #include "doc/blend_funcs.h"
 #include "doc/blend_internals.h"
@@ -34,14 +33,13 @@ doc::Image* render_text(const std::string& fontfile, int fontsize,
   ft::Lib ft;
 
   ft::Face face(ft.open(fontfile));
-  if (face) {
+  if (face.isValid()) {
     // Set font size
     face.setSize(fontsize);
     face.setAntialias(antialias);
 
     // Calculate text size
-    base::utf8_const_iterator begin(text.begin()), end(text.end());
-    gfx::Rect bounds = face.calcTextBounds(begin, end);
+    gfx::Rect bounds = face.calcTextBounds(text);
 
     // Render the image and copy it to the clipboard
     if (!bounds.isEmpty()) {
@@ -49,16 +47,16 @@ doc::Image* render_text(const std::string& fontfile, int fontsize,
       doc::clear_image(image, 0);
 
       face.forEachGlyph(
-        begin, end,
-        [&bounds, &image, color, antialias](FT_BitmapGlyph glyph, int x) {
-          int t, yimg = - bounds.y - glyph->top;
+        text,
+        [&bounds, &image, color, antialias](const ft::Face::Glyph& glyph) {
+          int t, yimg = - bounds.y + int(glyph.y);
 
-          for (int v=0; v<(int)glyph->bitmap.rows; ++v, ++yimg) {
-            const uint8_t* p = glyph->bitmap.buffer + v*glyph->bitmap.pitch;
-            int ximg = x - bounds.x + glyph->left;
+          for (int v=0; v<int(glyph.bitmap->rows); ++v, ++yimg) {
+            const uint8_t* p = glyph.bitmap->buffer + v*glyph.bitmap->pitch;
+            int ximg = - bounds.x + int(glyph.x);
             int bit = 0;
 
-            for (int u=0; u<(int)glyph->bitmap.width; ++u, ++ximg) {
+            for (int u=0; u<int(glyph.bitmap->width); ++u, ++ximg) {
               int alpha;
 
               if (antialias) {
diff --git a/src/ft/face.h b/src/ft/face.h
index 0abfed4..437e85b 100644
--- a/src/ft/face.h
+++ b/src/ft/face.h
@@ -9,6 +9,7 @@
 #pragma once
 
 #include "base/disable_copying.h"
+#include "base/string.h"
 #include "ft/freetype_headers.h"
 #include "gfx/rect.h"
 
@@ -17,19 +18,23 @@
 namespace ft {
 
   template<typename Cache>
-  class FaceT {
+  class FaceBase {
   public:
-    FaceT(FT_Face face = nullptr) : m_face(face) {
+    struct Glyph {
+      FT_UInt glyph_index;
+      FT_Bitmap* bitmap;
+      double x;
+      double y;
+    };
+
+    FaceBase(FT_Face face) : m_face(face) {
     }
 
-    ~FaceT() {
+    ~FaceBase() {
       if (m_face)
         FT_Done_Face(m_face);
     }
 
-    operator FT_Face() { return m_face; }
-    FT_Face operator->() { return m_face; }
-
     bool isValid() const {
       return (m_face != nullptr);
     }
@@ -48,56 +53,74 @@ namespace ft {
       m_cache.invalidate();
     }
 
-    template<typename Iterator,
-             typename Callback>
-    void forEachGlyph(Iterator first, Iterator end, Callback callback) {
-      bool use_kerning = (FT_HAS_KERNING(m_face) ? true: false);
+  protected:
+    FT_Face m_face;
+    bool m_antialias;
+    Cache m_cache;
+
+  private:
+    DISABLE_COPYING(FaceBase);
+  };
+
+  template<typename Cache>
+  class FaceFT : public FaceBase<Cache> {
+  public:
+    FaceFT(FT_Face face)
+      : FaceBase<Cache>(face) {
+    }
 
+    template<typename Callback>
+    void forEachGlyph(const std::string& str, Callback callback) {
+      bool use_kerning = (FT_HAS_KERNING(m_face) ? true: false);
       FT_UInt prev_glyph = 0;
-      int x = 0;
-      for (; first != end; ++first) {
-        FT_UInt glyph_index = m_cache.getGlyphIndex(m_face, *first);
+      double x = 0, y = 0;
+
+      auto it = base::utf8_const_iterator(str.begin());
+      auto end = base::utf8_const_iterator(str.end());
+      for (; it != end; ++it) {
+        FT_UInt glyph_index = m_cache.getGlyphIndex(m_face, *it);
 
         if (use_kerning && prev_glyph && glyph_index) {
           FT_Vector kerning;
           FT_Get_Kerning(m_face, prev_glyph, glyph_index,
                          FT_KERNING_DEFAULT, &kerning);
-          x += kerning.x >> 6;
+          x += kerning.x / 64.0;
         }
 
-        FT_Glyph glyph = m_cache.loadGlyph(m_face, glyph_index, m_antialias);
-        if (glyph) {
-          callback((FT_BitmapGlyph)glyph, x);
-          x += glyph->advance.x >> 16;
-          m_cache.doneGlyph(glyph);
+        FT_Glyph bitmapGlyph = m_cache.loadGlyph(m_face, glyph_index, m_antialias);
+        if (bitmapGlyph) {
+          Glyph glyph;
+          glyph.glyph_index = glyph_index;
+          glyph.bitmap = &FT_BitmapGlyph(bitmapGlyph)->bitmap;
+          glyph.x = x + FT_BitmapGlyph(bitmapGlyph)->left;
+          glyph.y = y - FT_BitmapGlyph(bitmapGlyph)->top;
+
+          callback(glyph);
+
+          x += bitmapGlyph->advance.x / double(1 << 16);
+          y += bitmapGlyph->advance.y / double(1 << 16);
+
+          m_cache.doneGlyph(bitmapGlyph);
         }
 
         prev_glyph = glyph_index;
       }
     }
 
-    template<typename Iterator>
-    gfx::Rect calcTextBounds(Iterator first, Iterator end) {
+    gfx::Rect calcTextBounds(const std::string& str) {
       gfx::Rect bounds(0, 0, 0, 0);
 
       forEachGlyph(
-        first, end,
-        [&bounds](FT_BitmapGlyph glyph, int x) {
-          bounds |= gfx::Rect(x + glyph->left,
-                              -glyph->top,
-                              glyph->bitmap.width,
-                              glyph->bitmap.rows);
+        str,
+        [&bounds](Glyph& glyph) {
+          bounds |= gfx::Rect(int(glyph.x),
+                              int(glyph.y),
+                              glyph.bitmap->width,
+                              glyph.bitmap->rows);
         });
 
       return bounds;
     }
-
-  private:
-    FT_Face m_face;
-    bool m_antialias;
-    Cache m_cache;
-
-    DISABLE_COPYING(FaceT);
   };
 
   class NoCache {
@@ -180,7 +203,7 @@ namespace ft {
     std::map<FT_UInt, FT_Glyph> m_glyphMap;
   };
 
-  typedef FaceT<SimpleCache> Face;
+  typedef FaceFT<SimpleCache> Face;
 
 } // namespace ft
 
diff --git a/src/she/common/freetype_font.cpp b/src/she/common/freetype_font.cpp
index ca9d3c5..0ed2662 100644
--- a/src/she/common/freetype_font.cpp
+++ b/src/she/common/freetype_font.cpp
@@ -10,6 +10,7 @@
 
 #include "she/common/freetype_font.h"
 
+#include "base/string.h"
 #include "gfx/point.h"
 #include "gfx/size.h"
 
@@ -45,17 +46,20 @@ FontType FreeTypeFont::type()
 int FreeTypeFont::height() const
 {
   static std::string str = "Tgjp";
-  return m_face.calcTextBounds(str.begin(), str.end()).h;
+  return m_face.calcTextBounds(str).h;
 }
 
 int FreeTypeFont::charWidth(int chr) const
 {
-  return m_face.calcTextBounds(&chr, (&chr)+1).w;
+  // TODO avoid creating a temporary string
+  std::wstring tmp;
+  tmp.push_back(chr);
+  return m_face.calcTextBounds(base::to_utf8(tmp)).w;
 }
 
 int FreeTypeFont::textLength(const std::string& str) const
 {
-  return m_face.calcTextBounds(str.begin(), str.end()).w;
+  return m_face.calcTextBounds(str).w;
 }
 
 bool FreeTypeFont::isScalable() const
diff --git a/src/she/common/generic_surface.h b/src/she/common/generic_surface.h
index 69c5a22..051e7a6 100644
--- a/src/she/common/generic_surface.h
+++ b/src/she/common/generic_surface.h
@@ -140,34 +140,52 @@ public:
         bool antialias = ttFont->face().antialias();
         int fg_alpha = gfx::geta(fg);
 
-        gfx::Rect bounds =
-          ttFont->face().calcTextBounds(str.begin(), str.end());
+        gfx::Rect bounds = ttFont->face().calcTextBounds(str);
+        gfx::Rect clipBounds = static_cast<Base*>(this)->getClipBounds();
 
         she::SurfaceFormatData fd;
         static_cast<Base*>(this)->getFormat(&fd);
 
-        gfx::Rect clip = static_cast<Base*>(this)->getClipBounds();
-
         ttFont->face().forEachGlyph(
-          str.begin(), str.end(),
-          [this, x, y, fg, fg_alpha, bg, antialias, &clip, &bounds, &fd](FT_BitmapGlyph glyph, int local_x) {
-            int dst_y = y - bounds.y - glyph->top;
+          str,
+          [this, x, y, fg, fg_alpha, bg, antialias, &clipBounds, &bounds, &fd](const ft::Face::Glyph& glyph) {
+            gfx::Rect origDstBounds(x - bounds.x + int(glyph.x),
+                                    y - bounds.y + int(glyph.y),
+                                    int(glyph.bitmap->width),
+                                    int(glyph.bitmap->rows));
+            gfx::Rect dstBounds = origDstBounds;
+            dstBounds &= clipBounds;
+            if (dstBounds.isEmpty())
+              return;
+
+            int clippedRows = dstBounds.y - origDstBounds.y;
+            int dst_y = dstBounds.y;
             int t;
-
-            for (int v=0; v<(int)glyph->bitmap.rows; ++v, ++dst_y) {
-              const uint8_t* p = glyph->bitmap.buffer + v*glyph->bitmap.pitch;
+            for (int v=0; v<dstBounds.h; ++v, ++dst_y) {
               int bit = 0;
-              int dst_x = x + local_x - bounds.x + glyph->left;
-
-              if (!clip.contains(gfx::Point(dst_x, dst_y)))
-                break;
-
+              const uint8_t* p = glyph.bitmap->buffer
+                + (v+clippedRows)*glyph.bitmap->pitch;
+              int dst_x = dstBounds.x;
               uint32_t* dst_address =
                 (uint32_t*)static_cast<Base*>(this)->getData(dst_x, dst_y);
 
-              for (int u=0; u<(int)glyph->bitmap.width; ++u) {
-                int alpha;
+              // Skip first clipped pixels
+              for (int u=0; u<dstBounds.x-origDstBounds.x; ++u) {
+                if (antialias) {
+                  ++p;
+                }
+                else {
+                  if (bit == 8) {
+                    bit = 0;
+                    ++p;
+                  }
+                }
+              }
+
+              for (int u=0; u<dstBounds.w; ++u, ++dst_x) {
+                ASSERT(clipBounds.contains(gfx::Point(dst_x, dst_y)));
 
+                int alpha;
                 if (antialias) {
                   alpha = *(p++);
                 }
@@ -202,10 +220,6 @@ public:
                   ((gfx::getb(output) << fd.blueShift ) & fd.blueMask ) |
                   ((gfx::geta(output) << fd.alphaShift) & fd.alphaMask);
 
-                ++dst_x;
-                if (dst_x >= clip.x2())
-                  break;
-
                 ++dst_address;
               }
             }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git



More information about the Pkg-games-commits mailing list