Skip to content

Commit 256d637

Browse files
committed
try calling freetype
1 parent 3f104f0 commit 256d637

4 files changed

Lines changed: 408 additions & 6 deletions

File tree

skia/viewer/build/premake5.lua

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,24 @@ includedirs {"../include", "../../../include", "../../renderer/include", "../../
1919
"../../dependencies/skia", "../../dependencies/skia/include/core",
2020
"../../dependencies/skia/include/effects", "../../dependencies/skia/include/gpu",
2121
"../../dependencies/skia/include/config", "../../dependencies/imgui", "../../dependencies",
22-
"../../dependencies/gl3w/build/include"}
22+
"../../dependencies/gl3w/build/include",
23+
"/Users/mike/other/freetype/include"
24+
}
2325

24-
links {"Cocoa.framework", "IOKit.framework", "CoreVideo.framework", "rive", "skia", "rive_skia_renderer", "glfw3"}
26+
links {
27+
"Cocoa.framework", "IOKit.framework", "CoreVideo.framework",
28+
"rive", "skia", "rive_skia_renderer", "glfw3",
29+
"freetype",
30+
}
2531
libdirs {"../../../build/%{cfg.system}/bin/%{cfg.buildcfg}", "../../dependencies/glfw_build/src",
26-
"../../dependencies/skia/out/static", "../../renderer/build/%{cfg.system}/bin/%{cfg.buildcfg}"}
32+
"../../dependencies/skia/out/static", "../../renderer/build/%{cfg.system}/bin/%{cfg.buildcfg}",}
2733

2834
files {"../src/**.cpp", "../../dependencies/gl3w/build/src/gl3w.c",
2935
"../../dependencies/imgui/backends/imgui_impl_glfw.cpp",
3036
"../../dependencies/imgui/backends/imgui_impl_opengl3.cpp", "../../dependencies/imgui/imgui_widgets.cpp",
3137
"../../dependencies/imgui/imgui.cpp", "../../dependencies/imgui/imgui_tables.cpp",
32-
"../../dependencies/imgui/imgui_draw.cpp"}
38+
"../../dependencies/imgui/imgui_draw.cpp",
39+
}
3340

3441
buildoptions {"-Wall", "-fno-exceptions", "-fno-rtti", "-flto=full"}
3542
filter "configurations:debug"
@@ -40,7 +47,7 @@ filter "configurations:release"
4047

4148
defines {"RELEASE"}
4249
defines {"NDEBUG"}
43-
optimize "On"
50+
symbols "On"
4451

4552
-- Clean Function --
4653
newaction {

skia/viewer/src/fonts.cpp

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
#include "fonts.hpp"
2+
3+
#include <cmath>
4+
#include <string>
5+
6+
template <typename T> T pin(T v, T mn, T mx) {
7+
return std::min(std::max(v, mn), mx);
8+
}
9+
10+
struct FTPathSinkCaller {
11+
private:
12+
PathSink* m_Sink;
13+
// we have to manually close contours
14+
bool m_ReadyToClose = false;
15+
16+
static inline float dot6tofloat(int32_t x) {
17+
return x * (1.0f/64);
18+
}
19+
20+
static int Move(const FT_Vector* pt, void* ctx) {
21+
auto caller = (FTPathSinkCaller*)ctx;
22+
if (caller->m_ReadyToClose) {
23+
caller->m_Sink->close();
24+
caller->m_ReadyToClose = false;
25+
}
26+
caller->m_Sink->move(dot6tofloat(pt->x), -dot6tofloat(pt->y));
27+
return 0;
28+
}
29+
30+
static int Line(const FT_Vector* pt, void* ctx) {
31+
auto caller = (FTPathSinkCaller*)ctx;
32+
caller->m_Sink->line(dot6tofloat(pt->x), -dot6tofloat(pt->y));
33+
caller->m_ReadyToClose = true;
34+
return 0;
35+
}
36+
37+
static int Quad(const FT_Vector* pt0, const FT_Vector* pt1, void* ctx) {
38+
auto caller = (FTPathSinkCaller*)ctx;
39+
caller->m_Sink->quad(dot6tofloat(pt0->x), -dot6tofloat(pt0->y),
40+
dot6tofloat(pt1->x), -dot6tofloat(pt1->y));
41+
caller->m_ReadyToClose = true;
42+
return 0;
43+
}
44+
45+
static int Cubic(const FT_Vector* pt0, const FT_Vector* pt1, const FT_Vector* pt2, void* ctx) {
46+
auto caller = (FTPathSinkCaller*)ctx;
47+
caller->m_Sink->cubic(dot6tofloat(pt0->x), -dot6tofloat(pt0->y),
48+
dot6tofloat(pt1->x), -dot6tofloat(pt1->y),
49+
dot6tofloat(pt2->x), -dot6tofloat(pt2->y));
50+
caller->m_ReadyToClose = true;
51+
return 0;
52+
}
53+
54+
public:
55+
FTPathSinkCaller(PathSink* sink) : m_Sink(sink) {}
56+
57+
inline static constexpr const FT_Outline_Funcs Funcs{
58+
FTPathSinkCaller::Move,
59+
FTPathSinkCaller::Line,
60+
FTPathSinkCaller::Quad,
61+
FTPathSinkCaller::Cubic,
62+
0, // shift
63+
0, // delta
64+
};
65+
};
66+
67+
FTLib::FTLib() : m_Lib(nullptr) {
68+
int err = FT_Init_FreeType(&m_Lib);
69+
if (err) {
70+
printf("FT_Init_FreeType returned %d\n", err);
71+
return;
72+
}
73+
74+
FT_Add_Default_Modules(m_Lib);
75+
FT_Set_Default_Properties(m_Lib);
76+
}
77+
78+
FTLib::~FTLib() {
79+
if (m_Lib) {
80+
FT_Done_Library(m_Lib);
81+
}
82+
}
83+
84+
FTFace::~FTFace() {
85+
if (m_Face) {
86+
FT_Done_Face(m_Face);
87+
}
88+
}
89+
90+
static std::string tagname(uint32_t x) {
91+
std::string str("1234");
92+
str[0] = (x >> 24) & 0xFF;
93+
str[1] = (x >> 16) & 0xFF;
94+
str[2] = (x >> 8) & 0xFF;
95+
str[3] = (x >> 0) & 0xFF;
96+
return str;
97+
}
98+
99+
static float fixed2float(int32_t x) {
100+
return x * (1.0f/65536);
101+
}
102+
103+
static int32_t float2fixed(float x) {
104+
return (int)std::floor(x * 65536 + 0.5f);
105+
}
106+
107+
void FTFace::parseAxes(FT_Library lib) {
108+
m_Axes.clear();
109+
110+
FT_MM_Var* var;
111+
int err = FT_Get_MM_Var(m_Face, &var);
112+
if (err) {
113+
printf("failed getting variations %d\n", err);
114+
return;
115+
}
116+
117+
assert(m_Face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS);
118+
119+
printf("%d axes\n", var->num_axis);
120+
for (unsigned i = 0; i < var->num_axis; ++i) {
121+
m_Axes.push_back({
122+
(uint32_t)var->axis[i].tag,
123+
fixed2float(var->axis[i].minimum),
124+
fixed2float(var->axis[i].def),
125+
fixed2float(var->axis[i].maximum),
126+
});
127+
printf(" %s %g %g %g\n",
128+
tagname(var->axis[i].tag).c_str(),
129+
m_Axes[i].m_Min, m_Axes[i].m_Def, m_Axes[i].m_Max);
130+
}
131+
FT_Done_MM_Var(lib, var);
132+
}
133+
134+
bool FTFace::load(FT_Library lib, sk_sp<SkData> data) {
135+
int face_index = 0; // todo
136+
int err = FT_New_Memory_Face(lib, (const FT_Byte*)data->data(),
137+
data->size(), face_index, &m_Face);
138+
if (err) {
139+
printf("FT_New_Memory_Face returned %d\n", err);
140+
return false;
141+
}
142+
m_Data = std::move(data);
143+
144+
this->parseAxes(lib);
145+
146+
return true;
147+
}
148+
149+
void FTFace::setCoords(const FTCoord user[], int count) {
150+
std::vector<FT_Fixed> ftc(m_Axes.size());
151+
for (size_t i = 0; i < m_Axes.size(); ++i) {
152+
const auto& a = m_Axes[i];
153+
float value = a.m_Def;
154+
for (int j = 0; j < count; ++j) {
155+
if (a.m_Tag == user[j].m_Tag) {
156+
value = user[j].m_Value;
157+
}
158+
}
159+
ftc[i] = float2fixed(pin(value, a.m_Min, a.m_Max));
160+
}
161+
162+
int err = FT_Set_Var_Design_Coordinates(m_Face, ftc.size(), ftc.data());
163+
if (err) {
164+
printf("set design coords failed %d\n", err);
165+
}
166+
}
167+
168+
int FTFace::upem() const {
169+
assert(m_Face);
170+
return m_Face->units_per_EM;
171+
}
172+
173+
bool FTFace::setSize(int size) {
174+
assert(m_Face);
175+
int err = FT_Set_Char_Size(m_Face, size * 64, 0, 72, 72);
176+
if (err) {
177+
printf("failed to set size %d\n", size);
178+
return false;
179+
}
180+
return true;
181+
}
182+
183+
bool FTFace::getPath(uint16_t glyph, PathSink* sink) {
184+
unsigned flags = FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP;
185+
flags &= ~FT_LOAD_RENDER;
186+
187+
int err = FT_Load_Glyph(m_Face, glyph, flags);
188+
assert(err == 0);
189+
190+
FTPathSinkCaller caller(sink);
191+
err = FT_Outline_Decompose(&m_Face->glyph->outline,
192+
&FTPathSinkCaller::Funcs,
193+
&caller);
194+
if (err) {
195+
printf("failed calling decompose %d\n", err);
196+
return false;
197+
}
198+
sink->close();
199+
return true;
200+
}

skia/viewer/src/fonts.hpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#ifndef _RIVE_FONT_HPP_
2+
#define _RIVE_FONT_HPP_
3+
4+
#include "rive/rive_types.hpp"
5+
#include "SkData.h"
6+
7+
#include <vector>
8+
9+
#include <ft2build.h>
10+
#include FT_FREETYPE_H
11+
12+
#include <freetype/ftadvanc.h>
13+
#include <freetype/ftimage.h>
14+
#include <freetype/ftbitmap.h>
15+
#ifdef FT_COLOR_H // 2.10.0
16+
# include <freetype/ftcolor.h>
17+
#endif
18+
#include <freetype/freetype.h>
19+
#include <freetype/ftlcdfil.h>
20+
#include <freetype/ftmodapi.h>
21+
#include <freetype/ftmm.h>
22+
#include <freetype/ftoutln.h>
23+
#include <freetype/ftsizes.h>
24+
#include <freetype/ftsystem.h>
25+
#include <freetype/tttables.h>
26+
#include <freetype/t1tables.h>
27+
#include <freetype/ftfntfmt.h>
28+
29+
typedef struct FT_LibraryRec_* FT_Library;
30+
typedef struct FT_FaceRec_* FT_Face;
31+
typedef struct FT_StreamRec_* FT_Stream;
32+
typedef signed long FT_Pos;
33+
typedef struct FT_BBox_ FT_BBox;
34+
35+
struct PathSink {
36+
virtual void move(float x, float y) = 0;
37+
virtual void line(float x, float y) = 0;
38+
virtual void quad(float x0, float y0, float x1, float y1) = 0;
39+
virtual void cubic(float x0, float y0, float x1, float y1, float x2, float y2) = 0;
40+
virtual void close() = 0;
41+
};
42+
43+
struct FTLib {
44+
FT_Library m_Lib;
45+
46+
FTLib();
47+
~FTLib();
48+
49+
operator bool() const { return m_Lib != nullptr; }
50+
};
51+
52+
constexpr uint32_t tag(unsigned a, unsigned b, unsigned c, unsigned d) {
53+
assert(a <= 255 && b <= 255 && c <= 255 && d <= 255);
54+
return (a << 24) | (b << 16) | (c << 8) | d;
55+
}
56+
57+
struct FTAxis {
58+
uint32_t m_Tag;
59+
float m_Min, m_Def, m_Max;
60+
};
61+
62+
struct FTCoord {
63+
uint32_t m_Tag;
64+
float m_Value;
65+
};
66+
67+
struct FTFace {
68+
sk_sp<SkData> m_Data;
69+
FT_Face m_Face;
70+
std::vector<FTAxis> m_Axes;
71+
72+
FTFace() : m_Face(nullptr) {}
73+
~FTFace();
74+
75+
bool load(FT_Library lib, sk_sp<SkData> data);
76+
77+
int axisCount() const { return (int)m_Axes.size(); }
78+
const FTAxis* axes() const { return m_Axes.data(); }
79+
80+
operator bool() const { return m_Face != nullptr; }
81+
82+
int upem() const;
83+
bool setSize(int size);
84+
void setCoords(const FTCoord[], int count);
85+
86+
bool getPath(uint16_t glyph, PathSink* sink);
87+
88+
private:
89+
void parseAxes(FT_Library);
90+
};
91+
92+
struct TestSink : public PathSink {
93+
void move(float x, float y) override {
94+
printf("Move %g %g\n", x, y);
95+
}
96+
void line(float x, float y) override {
97+
printf("line %g %g\n", x, y);
98+
}
99+
void quad(float x0, float y0, float x1, float y1) override {
100+
printf("quad %g %g %g %g\n", x0, y0, x1, y1);
101+
}
102+
void cubic(float x0, float y0, float x1, float y1, float x2, float y2) override {
103+
printf("cube %g %g %g %g %g %g\n", x0, y0, x1, y1, x2, y2);
104+
}
105+
void close() override {
106+
printf("close\n");
107+
}
108+
};
109+
110+
#endif

0 commit comments

Comments
 (0)