mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-29 19:20:09 +00:00
Add a simple cache system for glyphs
This commit is contained in:
parent
3b2ce80e37
commit
dbf5d69219
@ -50,12 +50,12 @@ doc::Image* render_text(const std::string& fontfile, int fontsize,
|
||||
|
||||
face.forEachGlyph(
|
||||
begin, end,
|
||||
[&bounds, &image, color, antialias](FT_GlyphSlot glyph, int x) {
|
||||
int t, yimg = - bounds.y - glyph->bitmap_top;
|
||||
[&bounds, &image, color, antialias](FT_BitmapGlyph glyph, int x) {
|
||||
int t, yimg = - bounds.y - glyph->top;
|
||||
|
||||
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->bitmap_left;
|
||||
int ximg = x - bounds.x + glyph->left;
|
||||
int bit = 0;
|
||||
|
||||
for (int u=0; u<(int)glyph->bitmap.width; ++u, ++ximg) {
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "ft/freetype_headers.h"
|
||||
#include "gfx/rect.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace ft {
|
||||
|
||||
template<typename Cache>
|
||||
@ -63,10 +65,11 @@ namespace ft {
|
||||
x += kerning.x >> 6;
|
||||
}
|
||||
|
||||
FT_GlyphSlot glyph = m_cache.loadGlyph(m_face, glyph_index, m_antialias);
|
||||
FT_Glyph glyph = m_cache.loadGlyph(m_face, glyph_index, m_antialias);
|
||||
if (glyph) {
|
||||
callback(glyph, x);
|
||||
x += glyph->advance.x >> 6;
|
||||
callback((FT_BitmapGlyph)glyph, x);
|
||||
x += glyph->advance.x >> 16;
|
||||
m_cache.doneGlyph(glyph);
|
||||
}
|
||||
|
||||
prev_glyph = glyph_index;
|
||||
@ -79,11 +82,11 @@ namespace ft {
|
||||
|
||||
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);
|
||||
[&bounds](FT_BitmapGlyph glyph, int x) {
|
||||
bounds |= gfx::Rect(x + glyph->left,
|
||||
-glyph->top,
|
||||
glyph->bitmap.width,
|
||||
glyph->bitmap.rows);
|
||||
});
|
||||
|
||||
return bounds;
|
||||
@ -107,22 +110,77 @@ namespace ft {
|
||||
return FT_Get_Char_Index(face, charCode);
|
||||
}
|
||||
|
||||
FT_GlyphSlot loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
|
||||
FT_Glyph loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
|
||||
FT_Error err = FT_Load_Glyph(
|
||||
face, glyphIndex,
|
||||
FT_LOAD_RENDER |
|
||||
FT_LOAD_NO_BITMAP |
|
||||
(antialias ? FT_LOAD_TARGET_NORMAL:
|
||||
FT_LOAD_TARGET_MONO));
|
||||
if (!err)
|
||||
return face->glyph;
|
||||
else
|
||||
if (err)
|
||||
return nullptr;
|
||||
|
||||
FT_Glyph glyph;
|
||||
err = FT_Get_Glyph(face->glyph, &glyph);
|
||||
if (err)
|
||||
return nullptr;
|
||||
|
||||
if (glyph->format != FT_GLYPH_FORMAT_BITMAP) {
|
||||
err = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
|
||||
if (!err) {
|
||||
FT_Done_Glyph(glyph);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return glyph;
|
||||
}
|
||||
|
||||
void doneGlyph(FT_Glyph glyph) {
|
||||
FT_Done_Glyph(glyph);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef FaceT<NoCache> Face;
|
||||
class SimpleCache : public NoCache {
|
||||
public:
|
||||
~SimpleCache() {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void invalidate() {
|
||||
for (auto& it : m_glyphMap)
|
||||
FT_Done_Glyph(it.second);
|
||||
|
||||
m_glyphMap.clear();
|
||||
}
|
||||
|
||||
FT_Glyph loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
|
||||
auto it = m_glyphMap.find(glyphIndex);
|
||||
if (it != m_glyphMap.end())
|
||||
return it->second;
|
||||
|
||||
FT_Glyph glyph = NoCache::loadGlyph(face, glyphIndex, antialias);
|
||||
if (glyph) {
|
||||
FT_Glyph newGlyph = nullptr;
|
||||
FT_Glyph_Copy(glyph, &newGlyph);
|
||||
if (newGlyph) {
|
||||
m_glyphMap[glyphIndex] = newGlyph;
|
||||
FT_Done_Glyph(glyph);
|
||||
return newGlyph;
|
||||
}
|
||||
}
|
||||
return glyph;
|
||||
}
|
||||
|
||||
void doneGlyph(FT_Glyph glyph) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<FT_UInt, FT_Glyph> m_glyphMap;
|
||||
};
|
||||
|
||||
typedef FaceT<SimpleCache> Face;
|
||||
|
||||
} // namespace ft
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define FT_FREETYPE_HEADERS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "freetype/ftglyph.h"
|
||||
#include "ft2build.h"
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
|
@ -149,14 +149,14 @@ public:
|
||||
|
||||
ttFont->face().forEachGlyph(
|
||||
str.begin(), str.end(),
|
||||
[&](FT_GlyphSlot glyph, int local_x) {
|
||||
[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;
|
||||
int t;
|
||||
|
||||
for (int v=0; v<(int)glyph->bitmap.rows; ++v) {
|
||||
for (int v=0; v<(int)glyph->bitmap.rows; ++v, ++dst_y) {
|
||||
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;
|
||||
int dst_x = x + local_x - bounds.x + glyph->left;
|
||||
|
||||
if (!clip.contains(gfx::Point(dst_x, dst_y)))
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user