Skip to content

Make PyFT2Font a subclass of FT2Font #30324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 29 additions & 16 deletions src/ft2font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include <cstdio>
#include <iterator>
#include <set>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
Expand Down Expand Up @@ -207,32 +206,43 @@ FT2Font::get_path(std::vector<double> &vertices, std::vector<unsigned char> &cod
codes.push_back(CLOSEPOLY);
}

FT2Font::FT2Font(FT_Open_Args &open_args,
long hinting_factor_,
std::vector<FT2Font *> &fallback_list,
FT2Font::WarnFunc warn, bool warn_if_used)
: ft_glyph_warn(warn), warn_if_used(warn_if_used), image({1, 1}), face(nullptr),
FT2Font::FT2Font(long hinting_factor_, std::vector<FT2Font *> &fallback_list,
bool warn_if_used)
: warn_if_used(warn_if_used), image({1, 1}), face(nullptr), fallbacks(fallback_list),
hinting_factor(hinting_factor_),
// set default kerning factor to 0, i.e., no kerning manipulation
kerning_factor(0)
{
clear();
}

FT2Font::~FT2Font()
{
close();
}

void FT2Font::open(FT_Open_Args &open_args)
{
FT_CHECK(FT_Open_Face, _ft2Library, &open_args, 0, &face);
if (open_args.stream != nullptr) {
face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
}
// Set fallbacks
std::copy(fallback_list.begin(), fallback_list.end(), std::back_inserter(fallbacks));
}

FT2Font::~FT2Font()
void FT2Font::close()
{
// This should be idempotent, in case a user manually calls close before the
// destructor does. Note for example, that PyFT2Font _does_ call this before the
// base destructor to ensure internal pointers are cleared early enough.

for (auto & glyph : glyphs) {
FT_Done_Glyph(glyph);
}
glyphs.clear();

if (face) {
FT_Done_Face(face);
face = nullptr;
}
}

Expand Down Expand Up @@ -533,21 +543,19 @@ FT_UInt FT2Font::get_char_index(FT_ULong charcode, bool fallback = false)
return FT_Get_Char_Index(ft_object->get_face(), charcode);
}

void FT2Font::get_width_height(long *width, long *height)
std::tuple<long, long> FT2Font::get_width_height()
{
*width = advance;
*height = bbox.yMax - bbox.yMin;
return {advance, bbox.yMax - bbox.yMin};
}

long FT2Font::get_descent()
{
return -bbox.yMin;
}

void FT2Font::get_bitmap_offset(long *x, long *y)
std::tuple<long, long> FT2Font::get_bitmap_offset()
{
*x = bbox.xMin;
*y = 0;
return {bbox.xMin, 0};
}

void FT2Font::draw_glyphs_to_bitmap(bool antialiased)
Expand Down Expand Up @@ -596,8 +604,11 @@ void FT2Font::draw_glyph_to_bitmap(
draw_bitmap(im, &bitmap->bitmap, x + bitmap->left, y);
}

void FT2Font::get_glyph_name(unsigned int glyph_number, std::string &buffer)
std::string FT2Font::get_glyph_name(unsigned int glyph_number)
{
std::string buffer;
buffer.resize(128);

if (!FT_HAS_GLYPH_NAMES(face)) {
/* Note that this generated name must match the name that
is generated by ttconv in ttfont_CharStrings_getname. */
Expand All @@ -614,6 +625,8 @@ void FT2Font::get_glyph_name(unsigned int glyph_number, std::string &buffer)
buffer.resize(len);
}
}

return buffer;
}

long FT2Font::get_name_index(char *name)
Expand Down
19 changes: 10 additions & 9 deletions src/ft2font.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <set>
#include <string>
#include <string_view>
#include <tuple>
#include <unordered_map>
#include <vector>

Expand Down Expand Up @@ -96,13 +97,12 @@ extern FT_Library _ft2Library;

class FT2Font
{
typedef void (*WarnFunc)(FT_ULong charcode, std::set<FT_String*> family_names);

public:
FT2Font(FT_Open_Args &open_args, long hinting_factor,
std::vector<FT2Font *> &fallback_list,
WarnFunc warn, bool warn_if_used);
FT2Font(long hinting_factor, std::vector<FT2Font *> &fallback_list,
bool warn_if_used);
virtual ~FT2Font();
void open(FT_Open_Args &open_args);
void close();
void clear();
void set_size(double ptsize, double dpi);
void set_charmap(int i);
Expand All @@ -123,14 +123,14 @@ class FT2Font
std::set<FT_String*> &glyph_seen_fonts,
bool override);
void load_glyph(FT_UInt glyph_index, FT_Int32 flags);
void get_width_height(long *width, long *height);
void get_bitmap_offset(long *x, long *y);
std::tuple<long, long> get_width_height();
std::tuple<long, long> get_bitmap_offset();
long get_descent();
void draw_glyphs_to_bitmap(bool antialiased);
void draw_glyph_to_bitmap(
py::array_t<uint8_t, py::array::c_style> im,
int x, int y, size_t glyphInd, bool antialiased);
void get_glyph_name(unsigned int glyph_number, std::string &buffer);
std::string get_glyph_name(unsigned int glyph_number);
long get_name_index(char *name);
FT_UInt get_char_index(FT_ULong charcode, bool fallback);
void get_path(std::vector<double> &vertices, std::vector<unsigned char> &codes);
Expand Down Expand Up @@ -166,8 +166,9 @@ class FT2Font
return FT_HAS_KERNING(face);
}

protected:
virtual void ft_glyph_warn(FT_ULong charcode, std::set<FT_String*> family_names) = 0;
private:
WarnFunc ft_glyph_warn;
bool warn_if_used;
py::array_t<uint8_t, py::array::c_style> image;
FT_Face face;
Expand Down
Loading
Loading