[aseprite] 51/196: Add a basic TrueType font impl to she library using FreeType library
Tobias Hansen
thansen at moszumanska.debian.org
Wed Apr 20 18:50:00 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 dfa6bcd16bbbbf7da30375ec345592c00f49b8a7
Author: David Capello <davidcapello at gmail.com>
Date: Thu Mar 10 15:49:13 2016 -0300
Add a basic TrueType font impl to she library using FreeType library
---
src/ft/face.h | 26 +++++---
src/ft/lib.h | 8 ++-
src/she/CMakeLists.txt | 6 +-
src/she/alleg4/alleg_surface.h | 2 +-
src/she/common/freetype_font.cpp | 92 ++++++++++++++++++++++++++
src/she/common/freetype_font.h | 43 +++++++++++++
src/she/common/generic_surface.h | 128 +++++++++++++++++++++++++++++++++----
src/she/common/sprite_sheet_font.h | 4 ++
src/she/common/system.h | 5 ++
src/she/font.h | 9 ++-
src/she/skia/skia_surface.h | 23 +------
src/she/system.h | 1 +
12 files changed, 300 insertions(+), 47 deletions(-)
diff --git a/src/ft/face.h b/src/ft/face.h
index 22e49d5..d42398c 100644
--- a/src/ft/face.h
+++ b/src/ft/face.h
@@ -8,7 +8,9 @@
#define FT_FACE_H_INCLUDED
#pragma once
+#include "base/disable_copying.h"
#include "ft/freetype_headers.h"
+#include "gfx/rect.h"
namespace ft {
@@ -22,8 +24,11 @@ namespace ft {
FT_Done_Face(m_face);
}
- operator FT_Face() {
- return m_face;
+ operator FT_Face() { return m_face; }
+ FT_Face operator->() { return m_face; }
+
+ bool isValid() const {
+ return (m_face != nullptr);
}
bool antialias() const {
@@ -75,13 +80,14 @@ namespace ft {
gfx::Rect calcTextBounds(Iterator first, Iterator end) {
gfx::Rect bounds(0, 0, 0, 0);
- forEachGlyph(first, end,
- [&bounds](FT_GlyphSlot glyph, int x) {
- bounds |= gfx::Rect(x + glyph->bitmap_left,
- -glyph->bitmap_top,
- (int)glyph->bitmap.width,
- (int)glyph->bitmap.rows);
- });
+ forEachGlyph(
+ first, end,
+ [&bounds](FT_GlyphSlot glyph, int x) {
+ bounds |= gfx::Rect(x + glyph->bitmap_left,
+ -glyph->bitmap_top,
+ (int)glyph->bitmap.width,
+ (int)glyph->bitmap.rows);
+ });
return bounds;
}
@@ -89,6 +95,8 @@ namespace ft {
private:
FT_Face m_face;
bool m_antialias;
+
+ DISABLE_COPYING(Face);
};
} // namespace ft
diff --git a/src/ft/lib.h b/src/ft/lib.h
index 91c869f..9bf35d1 100644
--- a/src/ft/lib.h
+++ b/src/ft/lib.h
@@ -8,8 +8,11 @@
#define FT_LIB_H_INCLUDED
#pragma once
+#include "base/disable_copying.h"
#include "ft/freetype_headers.h"
+#include <string>
+
namespace ft {
class Lib {
@@ -19,7 +22,8 @@ namespace ft {
}
~Lib() {
- FT_Done_FreeType(m_ft);
+ if (m_ft)
+ FT_Done_FreeType(m_ft);
}
operator FT_Library() {
@@ -39,6 +43,8 @@ namespace ft {
private:
FT_Library m_ft;
+
+ DISABLE_COPYING(Lib);
};
} // namespace ft
diff --git a/src/she/CMakeLists.txt b/src/she/CMakeLists.txt
index 4dbd4cf..d000ee0 100644
--- a/src/she/CMakeLists.txt
+++ b/src/she/CMakeLists.txt
@@ -1,7 +1,8 @@
# SHE
# Copyright (C) 2012-2016 David Capello
-set(SHE_SOURCES)
+set(SHE_SOURCES
+ common/freetype_font.cpp)
######################################################################
# Allegro 4 backend
@@ -197,7 +198,8 @@ add_library(she ${SHE_SOURCES})
target_link_libraries(she
gfx-lib
- base-lib)
+ base-lib
+ ${FREETYPE_LIBRARY})
if(USE_ALLEG4_BACKEND)
target_link_libraries(she
diff --git a/src/she/alleg4/alleg_surface.h b/src/she/alleg4/alleg_surface.h
index 2636bd4..5e0e3a8 100644
--- a/src/she/alleg4/alleg_surface.h
+++ b/src/she/alleg4/alleg_surface.h
@@ -15,7 +15,7 @@
namespace she {
- class Alleg4Surface : public GenericSurface<Surface> {
+ class Alleg4Surface : public GenericDrawTextSurface<GenericDrawColoredRgbaSurface<Surface> > {
public:
enum DestroyFlag {
None = 0,
diff --git a/src/she/common/freetype_font.cpp b/src/she/common/freetype_font.cpp
new file mode 100644
index 0000000..2e6c15d
--- /dev/null
+++ b/src/she/common/freetype_font.cpp
@@ -0,0 +1,92 @@
+// SHE library
+// Copyright (C) 2016 David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "she/common/freetype_font.h"
+
+#include "gfx/point.h"
+#include "gfx/size.h"
+
+namespace she {
+
+FreeTypeFont::FreeTypeFont(const char* filename, int height)
+ : m_face(m_ft.open(filename))
+{
+ ASSERT(m_face.isValid());
+ if (m_face.isValid())
+ m_face.setSize(height);
+}
+
+FreeTypeFont::~FreeTypeFont()
+{
+}
+
+bool FreeTypeFont::isValid() const
+{
+ return m_face.isValid();
+}
+
+void FreeTypeFont::dispose()
+{
+ delete this;
+}
+
+FontType FreeTypeFont::type()
+{
+ return FontType::kTrueType;
+}
+
+int FreeTypeFont::height() const
+{
+ FT_UInt glyph_index = FT_Get_Char_Index(m_face, 'A');
+
+ FT_Error err = FT_Load_Glyph(
+ m_face, glyph_index,
+ FT_LOAD_RENDER |
+ FT_LOAD_NO_BITMAP |
+ (m_face.antialias() ? FT_LOAD_TARGET_NORMAL:
+ FT_LOAD_TARGET_MONO));
+
+ if (!err)
+ return (int)m_face->glyph->bitmap.rows;
+ else
+ return m_face->height >> 6;
+}
+
+int FreeTypeFont::charWidth(int chr) const
+{
+ return m_face.calcTextBounds(&chr, (&chr)+1).w;
+}
+
+int FreeTypeFont::textLength(const std::string& str) const
+{
+ return m_face.calcTextBounds(str.begin(), str.end()).w;
+}
+
+bool FreeTypeFont::isScalable() const
+{
+ return true;
+}
+
+void FreeTypeFont::setSize(int size)
+{
+ m_face.setSize(size);
+}
+
+FreeTypeFont* loadFreeTypeFont(const char* filename, int height)
+{
+ FreeTypeFont* font = new FreeTypeFont(filename, height);
+ if (!font->isValid()) {
+ delete font;
+ font = nullptr;
+ }
+ return font;
+}
+
+} // namespace she
diff --git a/src/she/common/freetype_font.h b/src/she/common/freetype_font.h
new file mode 100644
index 0000000..aff7d42
--- /dev/null
+++ b/src/she/common/freetype_font.h
@@ -0,0 +1,43 @@
+// SHE library
+// Copyright (C) 2016 David Capello
+//
+// This file is released under the terms of the MIT license.
+// Read LICENSE.txt for more information.
+
+#ifndef SHE_COMMON_FREETYPE_FONT_H_INCLUDED
+#define SHE_COMMON_FREETYPE_FONT_H_INCLUDED
+#pragma once
+
+#include "ft/face.h"
+#include "ft/lib.h"
+#include "she/font.h"
+
+namespace she {
+ class Font;
+
+ class FreeTypeFont : public Font {
+ public:
+ FreeTypeFont(const char* filename, int height);
+ ~FreeTypeFont();
+
+ bool isValid() const;
+ void dispose() override;
+ FontType type() override;
+ int height() const override;
+ int charWidth(int chr) const override;
+ int textLength(const std::string& str) const override;
+ bool isScalable() const override;
+ void setSize(int size) override;
+
+ ft::Face& face() { return m_face; }
+
+ private:
+ mutable ft::Lib m_ft;
+ mutable ft::Face m_face;
+ };
+
+ FreeTypeFont* loadFreeTypeFont(const char* filename, int height);
+
+} // namespace she
+
+#endif
diff --git a/src/she/common/generic_surface.h b/src/she/common/generic_surface.h
index de18e33..b7faac7 100644
--- a/src/she/common/generic_surface.h
+++ b/src/she/common/generic_surface.h
@@ -9,6 +9,7 @@
#pragma once
#include "gfx/clip.h"
+#include "she/common/freetype_font.h"
#include "she/common/sprite_sheet_font.h"
namespace she {
@@ -51,7 +52,7 @@ gfx::Color blend(const gfx::Color backdrop, gfx::Color src)
} // anoynmous namespace
template<typename Base>
-class GenericSurface : public Base {
+class GenericDrawColoredRgbaSurface : public Base {
public:
void drawColoredRgbaSurface(const Surface* src, gfx::Color fg, gfx::Color bg, const gfx::Clip& clipbase) override {
@@ -87,24 +88,127 @@ public:
}
}
}
+};
+
+template<typename Base>
+class GenericDrawTextSurface : public Base {
+public:
void drawChar(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, int chr) override {
- SpriteSheetFont* ssFont = static_cast<SpriteSheetFont*>(font);
+ switch (font->type()) {
+
+ case FontType::kSpriteSheet: {
+ SpriteSheetFont* ssFont = static_cast<SpriteSheetFont*>(font);
+
+ gfx::Rect charBounds = ssFont->getCharBounds(chr);
+ if (!charBounds.isEmpty()) {
+ Surface* sheet = ssFont->getSurfaceSheet();
+ SurfaceLock lock(sheet);
+ drawColoredRgbaSurface(sheet, fg, bg, gfx::Clip(x, y, charBounds));
+ }
+ break;
+ }
+
+ case FontType::kTrueType: {
+ std::string str;
+ str.push_back(chr);
+ drawString(font, fg, bg, x, y, str);
+ break;
+ }
- gfx::Rect charBounds = ssFont->getCharBounds(chr);
- if (!charBounds.isEmpty()) {
- Surface* sheet = ssFont->getSurfaceSheet();
- SurfaceLock lock(sheet);
- drawColoredRgbaSurface(sheet, fg, bg, gfx::Clip(x, y, charBounds));
}
}
void drawString(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, const std::string& str) override {
- base::utf8_const_iterator it(str.begin()), end(str.end());
- while (it != end) {
- drawChar(font, fg, bg, x, y, *it);
- x += font->charWidth(*it);
- ++it;
+ switch (font->type()) {
+
+ case FontType::kSpriteSheet: {
+ base::utf8_const_iterator it(str.begin()), end(str.end());
+ while (it != end) {
+ drawChar(font, fg, bg, x, y, *it);
+ x += font->charWidth(*it);
+ ++it;
+ }
+ break;
+ }
+
+ case FontType::kTrueType: {
+ FreeTypeFont* ttFont = static_cast<FreeTypeFont*>(font);
+ bool antialias = ttFont->face().antialias();
+ int fg_alpha = gfx::geta(fg);
+
+ gfx::Rect bounds =
+ ttFont->face().calcTextBounds(str.begin(), str.end());
+
+ she::SurfaceFormatData fd;
+ getFormat(&fd);
+
+ gfx::Rect clip = getClipBounds();
+
+ ttFont->face().forEachGlyph(
+ str.begin(), str.end(),
+ [&](FT_GlyphSlot glyph, int local_x) {
+ int t;
+
+ for (int v=0; v<(int)glyph->bitmap.rows; ++v) {
+ const uint8_t* p = glyph->bitmap.buffer + v*glyph->bitmap.pitch;
+ int bit = 0;
+ int dst_x = x + local_x - bounds.x + glyph->bitmap_left;
+ int dst_y = y - bounds.y - glyph->bitmap_top + v;
+
+ if (!clip.contains(gfx::Point(dst_x, dst_y)))
+ break;
+
+ uint32_t* dst_address = (uint32_t*)getData(dst_x, dst_y);
+
+ for (int u=0; u<(int)glyph->bitmap.width; ++u) {
+ int alpha;
+
+ if (antialias) {
+ alpha = *(p++);
+ }
+ else {
+ alpha = ((*p) & (1 << (7 - (bit++))) ? 255: 0);
+ if (bit == 8) {
+ bit = 0;
+ ++p;
+ }
+ }
+
+ uint32_t backdrop = *dst_address;
+ gfx::Color backdropColor =
+ gfx::rgba(
+ ((backdrop & fd.redMask) >> fd.redShift),
+ ((backdrop & fd.greenMask) >> fd.greenShift),
+ ((backdrop & fd.blueMask) >> fd.blueShift),
+ ((backdrop & fd.alphaMask) >> fd.alphaShift));
+
+ gfx::Color output = gfx::rgba(gfx::getr(fg),
+ gfx::getg(fg),
+ gfx::getb(fg),
+ MUL_UN8(fg_alpha, alpha, t));
+ if (gfx::geta(bg) > 0)
+ output = blend(blend(backdropColor, bg), output);
+ else
+ output = blend(backdropColor, output);
+
+ *dst_address =
+ ((gfx::getr(output) << fd.redShift ) & fd.redMask ) |
+ ((gfx::getg(output) << fd.greenShift) & fd.greenMask) |
+ ((gfx::getb(output) << fd.blueShift ) & fd.blueMask ) |
+ ((gfx::geta(output) << fd.alphaShift) & fd.alphaMask);
+
+ ++dst_x;
+ if (dst_x >= clip.x2())
+ break;
+
+ ++dst_address;
+ }
+ }
+ });
+ break;
+ }
+
}
}
diff --git a/src/she/common/sprite_sheet_font.h b/src/she/common/sprite_sheet_font.h
index 5f5206d..396fce0 100644
--- a/src/she/common/sprite_sheet_font.h
+++ b/src/she/common/sprite_sheet_font.h
@@ -33,6 +33,10 @@ public:
delete this;
}
+ FontType type() override {
+ return FontType::kSpriteSheet;
+ }
+
int height() const override {
return getCharBounds(' ').h;
}
diff --git a/src/she/common/system.h b/src/she/common/system.h
index f23a772..b5da921 100644
--- a/src/she/common/system.h
+++ b/src/she/common/system.h
@@ -19,6 +19,7 @@
#include "she/native_dialogs.h"
#endif
+#include "she/common/freetype_font.h"
#include "she/common/sprite_sheet_font.h"
namespace she {
@@ -80,6 +81,10 @@ public:
return font;
}
+ Font* loadTrueTypeFont(const char* filename, int height) override {
+ return loadFreeTypeFont(filename, height);
+ }
+
private:
NativeDialogs* m_nativeDialogs;
};
diff --git a/src/she/font.h b/src/she/font.h
index ba8f225..43a607d 100644
--- a/src/she/font.h
+++ b/src/she/font.h
@@ -1,5 +1,5 @@
// SHE library
-// Copyright (C) 2012-2015 David Capello
+// Copyright (C) 2012-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@@ -12,10 +12,17 @@
namespace she {
+ enum class FontType {
+ kUnknown,
+ kSpriteSheet,
+ kTrueType,
+ };
+
class Font {
public:
virtual ~Font() { }
virtual void dispose() = 0;
+ virtual FontType type() = 0;
virtual int height() const = 0;
virtual int charWidth(int chr) const = 0;
virtual int textLength(const std::string& str) const = 0;
diff --git a/src/she/skia/skia_surface.h b/src/she/skia/skia_surface.h
index e005331..5cd46d2 100644
--- a/src/she/skia/skia_surface.h
+++ b/src/she/skia/skia_surface.h
@@ -9,6 +9,7 @@
#pragma once
#include "gfx/clip.h"
+#include "she/common/generic_surface.h"
#include "she/common/sprite_sheet_font.h"
#include "SkBitmap.h"
@@ -29,7 +30,7 @@ inline SkIRect to_skia(const gfx::Rect& rc) {
return SkIRect::MakeXYWH(rc.x, rc.y, rc.w, rc.h);
}
-class SkiaSurface : public Surface {
+class SkiaSurface : public GenericDrawTextSurface<Surface> {
public:
SkiaSurface() : m_surface(nullptr)
, m_canvas(nullptr)
@@ -427,26 +428,6 @@ public:
SkCanvas::kStrict_SrcRectConstraint);
}
- void drawChar(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, int chr) override {
- SpriteSheetFont* commonFont = static_cast<SpriteSheetFont*>(font);
-
- gfx::Rect charBounds = commonFont->getCharBounds(chr);
- if (!charBounds.isEmpty()) {
- Surface* sheet = commonFont->getSurfaceSheet();
- SurfaceLock lock(sheet);
- drawColoredRgbaSurface(sheet, fg, bg, gfx::Clip(x, y, charBounds));
- }
- }
-
- void drawString(Font* font, gfx::Color fg, gfx::Color bg, int x, int y, const std::string& str) override {
- base::utf8_const_iterator it(str.begin()), end(str.end());
- while (it != end) {
- drawChar(font, fg, bg, x, y, *it);
- x += font->charWidth(*it);
- ++it;
- }
- }
-
SkBitmap& bitmap() {
return m_bitmap;
}
diff --git a/src/she/system.h b/src/she/system.h
index a93c9d7..7e7f040 100644
--- a/src/she/system.h
+++ b/src/she/system.h
@@ -47,6 +47,7 @@ namespace she {
virtual Surface* loadSurface(const char* filename) = 0;
virtual Surface* loadRgbaSurface(const char* filename) = 0;
virtual Font* loadSpriteSheetFont(const char* filename, int scale = 1) = 0;
+ virtual Font* loadTrueTypeFont(const char* filename, int height) = 0;
virtual Clipboard* createClipboard() = 0;
};
--
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