-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
240 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
#include "rive/renderer.hpp" | ||
#include "SkData.h" | ||
|
||
#include <ft2build.h> | ||
#include FT_FREETYPE_H | ||
|
||
#include <freetype/ftadvanc.h> | ||
#include <freetype/ftimage.h> | ||
#include <freetype/ftbitmap.h> | ||
#ifdef FT_COLOR_H // 2.10.0 | ||
# include <freetype/ftcolor.h> | ||
#endif | ||
#include <freetype/freetype.h> | ||
#include <freetype/ftlcdfil.h> | ||
#include <freetype/ftmodapi.h> | ||
#include <freetype/ftmm.h> | ||
#include <freetype/ftoutln.h> | ||
#include <freetype/ftsizes.h> | ||
#include <freetype/ftsystem.h> | ||
#include <freetype/tttables.h> | ||
#include <freetype/t1tables.h> | ||
#include <freetype/ftfntfmt.h> | ||
|
||
|
||
|
||
|
||
typedef struct FT_LibraryRec_* FT_Library; | ||
typedef struct FT_FaceRec_* FT_Face; | ||
typedef struct FT_StreamRec_* FT_Stream; | ||
typedef signed long FT_Pos; | ||
typedef struct FT_BBox_ FT_BBox; | ||
|
||
struct PathSink { | ||
|
||
void move(float x, float y) { | ||
printf("move %g %g\n", x, y); | ||
} | ||
void line(float x, float y) { | ||
printf("line %g %g\n", x, y); | ||
} | ||
void quad(float x0, float y0, float x1, float y1) { | ||
printf("quad %g %g %g %g\n", x0, y0, x1, y1); | ||
} | ||
void cubic(float x0, float y0, float x1, float y1, float x2, float y2) { | ||
printf("cube %g %g %g %g %g %g\n", x0, y0, x1, y1, x2, y2); | ||
} | ||
void close() { | ||
printf("close\n"); | ||
} | ||
}; | ||
|
||
struct FTPathSinkCaller { | ||
private: | ||
PathSink* m_Sink; | ||
// we have to manually close contours | ||
bool m_ReadyToClose = false; | ||
|
||
static inline float dot6tofloat(int32_t x) { | ||
return x * (1.0f/64); | ||
} | ||
|
||
static int Move(const FT_Vector* pt, void* ctx) { | ||
auto caller = (FTPathSinkCaller*)ctx; | ||
if (caller->m_ReadyToClose) { | ||
caller->m_Sink->close(); | ||
caller->m_ReadyToClose = false; | ||
} | ||
caller->m_Sink->move(dot6tofloat(pt->x), -dot6tofloat(pt->y)); | ||
return 0; | ||
} | ||
|
||
static int Line(const FT_Vector* pt, void* ctx) { | ||
auto caller = (FTPathSinkCaller*)ctx; | ||
caller->m_Sink->move(dot6tofloat(pt->x), -dot6tofloat(pt->y)); | ||
caller->m_ReadyToClose = true; | ||
return 0; | ||
} | ||
|
||
static int Quad(const FT_Vector* pt0, const FT_Vector* pt1, void* ctx) { | ||
auto caller = (FTPathSinkCaller*)ctx; | ||
caller->m_Sink->quad(dot6tofloat(pt0->x), -dot6tofloat(pt0->y), | ||
dot6tofloat(pt1->x), -dot6tofloat(pt1->y)); | ||
caller->m_ReadyToClose = true; | ||
return 0; | ||
} | ||
|
||
static int Cubic(const FT_Vector* pt0, const FT_Vector* pt1, const FT_Vector* pt2, void* ctx) { | ||
auto caller = (FTPathSinkCaller*)ctx; | ||
caller->m_Sink->cubic(dot6tofloat(pt0->x), -dot6tofloat(pt0->y), | ||
dot6tofloat(pt1->x), -dot6tofloat(pt1->y), | ||
dot6tofloat(pt2->x), -dot6tofloat(pt2->y)); | ||
caller->m_ReadyToClose = true; | ||
return 0; | ||
} | ||
|
||
public: | ||
FTPathSinkCaller(PathSink* sink) : m_Sink(sink) {} | ||
|
||
inline static constexpr const FT_Outline_Funcs Funcs{ | ||
FTPathSinkCaller::Move, | ||
FTPathSinkCaller::Line, | ||
FTPathSinkCaller::Quad, | ||
FTPathSinkCaller::Cubic, | ||
0, // shift | ||
0, // delta | ||
}; | ||
}; | ||
|
||
struct FTLib { | ||
FT_Library m_Lib; | ||
|
||
FTLib() : m_Lib(nullptr) { | ||
int err = FT_Init_FreeType(&m_Lib); | ||
if (err) { | ||
printf("FT_Init_FreeType returned %d\n", err); | ||
return; | ||
} | ||
|
||
FT_Add_Default_Modules(m_Lib); | ||
FT_Set_Default_Properties(m_Lib); | ||
} | ||
~FTLib() { | ||
if (m_Lib) { | ||
FT_Done_Library(m_Lib); | ||
} | ||
} | ||
|
||
operator bool() const { return m_Lib != nullptr; } | ||
}; | ||
|
||
struct FTFace { | ||
sk_sp<SkData> m_Data; | ||
FT_Face m_Face; | ||
|
||
FTFace() : m_Face(nullptr) {} | ||
~FTFace() { | ||
if (m_Face) { | ||
FT_Done_Face(m_Face); | ||
} | ||
} | ||
|
||
bool load(FT_Library lib, sk_sp<SkData> data) { | ||
int face_index = 0; // todo | ||
int err = FT_New_Memory_Face(lib, (const FT_Byte*)data->data(), | ||
data->size(), face_index, &m_Face); | ||
if (err) { | ||
printf("FT_New_Memory_Face returned %d\n", err); | ||
return false; | ||
} | ||
m_Data = std::move(data); | ||
return true; | ||
} | ||
|
||
operator bool() const { return m_Face != nullptr; } | ||
|
||
int upem() const { | ||
assert(m_Face); | ||
return m_Face->units_per_EM; | ||
} | ||
|
||
bool setSize(int size) { | ||
assert(m_Face); | ||
int err = FT_Set_Char_Size(m_Face, size * 64, 0, 72, 72); | ||
if (err) { | ||
printf("failed to set size %d\n", size); | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
bool getPath(uint16_t glyph, PathSink* sink) { | ||
unsigned flags = FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; | ||
flags &= ~FT_LOAD_RENDER; | ||
|
||
int err = FT_Load_Glyph(m_Face, glyph, flags); | ||
assert(err == 0); | ||
|
||
FTPathSinkCaller caller(sink); | ||
err = FT_Outline_Decompose(&m_Face->glyph->outline, | ||
&FTPathSinkCaller::Funcs, | ||
&caller); | ||
if (err) { | ||
printf("failed calling decompose %d\n", err); | ||
return false; | ||
} | ||
sink->close(); | ||
return true; | ||
} | ||
}; | ||
|
||
void test_fonts(const char path[]) { | ||
FTLib lib; | ||
if (!lib) { | ||
printf("failed to init freetype\n"); | ||
return; | ||
} | ||
|
||
auto data = SkData::MakeFromFileName(path); | ||
if (!data) { | ||
printf("failed to load file %s\n", path); | ||
return; | ||
} | ||
|
||
FTFace face; | ||
if (!face.load(lib.m_Lib, data)) { | ||
printf("failed to load file\n"); | ||
return; | ||
} | ||
|
||
printf("%s has %ld glyphs and %d upem\n", | ||
path, face.m_Face->num_glyphs, face.m_Face->units_per_EM); | ||
|
||
face.setSize(face.upem()); | ||
|
||
int glyph = FT_Get_Char_Index(face.m_Face, 'Q'); | ||
if (glyph == 0) { | ||
printf("char2glyph failed\n"); | ||
return; | ||
} | ||
|
||
PathSink sink; | ||
face.getPath(glyph, &sink); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters