Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 04d26b2

Browse filesBrowse files
committed
Simplify/improve error reporting from ft2font.
Provide a simple macro to call a FreeType function and throw an exception if an error is returned, while also including the source file and line location for the error. For example, trying `FT2Font(open("pyproject.toml", "rb"))` now raises "FT_Open_Face (ft2font.cpp line 220) failed with error 0x2: unknown file format" instead of "Can not load face (unknown file format; error code 0x2)"
1 parent def8fa4 commit 04d26b2
Copy full SHA for 04d26b2

File tree

2 files changed

+55
-84
lines changed
Filter options

2 files changed

+55
-84
lines changed

‎src/ft2font.cpp

Copy file name to clipboardExpand all lines: src/ft2font.cpp
+27-81Lines changed: 27 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,6 @@
4343

4444
FT_Library _ft2Library;
4545

46-
// FreeType error codes; loaded as per fterror.h.
47-
static char const* ft_error_string(FT_Error error) {
48-
#undef __FTERRORS_H__
49-
#define FT_ERROR_START_LIST switch (error) {
50-
#define FT_ERRORDEF( e, v, s ) case v: return s;
51-
#define FT_ERROR_END_LIST default: return NULL; }
52-
#include FT_ERRORS_H
53-
}
54-
55-
void throw_ft_error(std::string message, FT_Error error) {
56-
char const* s = ft_error_string(error);
57-
std::ostringstream os("");
58-
if (s) {
59-
os << message << " (" << s << "; error code 0x" << std::hex << error << ")";
60-
} else { // Should not occur, but don't add another error from failed lookup.
61-
os << message << " (error code 0x" << std::hex << error << ")";
62-
}
63-
throw std::runtime_error(os.str());
64-
}
65-
6646
FT2Image::FT2Image(unsigned long width, unsigned long height)
6747
: m_buffer((unsigned char *)calloc(width * height, 1)), m_width(width), m_height(height)
6848
{
@@ -237,26 +217,16 @@ FT2Font::FT2Font(FT_Open_Args &open_args,
237217
kerning_factor(0)
238218
{
239219
clear();
240-
241-
FT_Error error = FT_Open_Face(_ft2Library, &open_args, 0, &face);
242-
if (error) {
243-
throw_ft_error("Can not load face", error);
244-
}
245-
246-
// set a default fontsize 12 pt at 72dpi
247-
error = FT_Set_Char_Size(face, 12 * 64, 0, 72 * (unsigned int)hinting_factor, 72);
248-
if (error) {
249-
FT_Done_Face(face);
250-
throw_ft_error("Could not set the fontsize", error);
251-
}
252-
220+
FT_CHECK(FT_Open_Face, _ft2Library, &open_args, 0, &face);
253221
if (open_args.stream != nullptr) {
254222
face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
255223
}
256-
257-
FT_Matrix transform = { 65536 / hinting_factor, 0, 0, 65536 };
258-
FT_Set_Transform(face, &transform, nullptr);
259-
224+
try {
225+
set_size(12., 72.); // Set a default fontsize 12 pt at 72dpi.
226+
} catch (...) {
227+
FT_Done_Face(face);
228+
throw;
229+
}
260230
// Set fallbacks
261231
std::copy(fallback_list.begin(), fallback_list.end(), std::back_inserter(fallbacks));
262232
}
@@ -293,11 +263,9 @@ void FT2Font::clear()
293263

294264
void FT2Font::set_size(double ptsize, double dpi)
295265
{
296-
FT_Error error = FT_Set_Char_Size(
266+
FT_CHECK(
267+
FT_Set_Char_Size,
297268
face, (FT_F26Dot6)(ptsize * 64), 0, (FT_UInt)(dpi * hinting_factor), (FT_UInt)dpi);
298-
if (error) {
299-
throw_ft_error("Could not set the fontsize", error);
300-
}
301269
FT_Matrix transform = { 65536 / hinting_factor, 0, 0, 65536 };
302270
FT_Set_Transform(face, &transform, nullptr);
303271

@@ -311,17 +279,12 @@ void FT2Font::set_charmap(int i)
311279
if (i >= face->num_charmaps) {
312280
throw std::runtime_error("i exceeds the available number of char maps");
313281
}
314-
FT_CharMap charmap = face->charmaps[i];
315-
if (FT_Error error = FT_Set_Charmap(face, charmap)) {
316-
throw_ft_error("Could not set the charmap", error);
317-
}
282+
FT_CHECK(FT_Set_Charmap, face, face->charmaps[i]);
318283
}
319284

320285
void FT2Font::select_charmap(unsigned long i)
321286
{
322-
if (FT_Error error = FT_Select_Charmap(face, (FT_Encoding)i)) {
323-
throw_ft_error("Could not set the charmap", error);
324-
}
287+
FT_CHECK(FT_Select_Charmap, face, (FT_Encoding)i);
325288
}
326289

327290
int FT2Font::get_kerning(FT_UInt left, FT_UInt right, FT_Kerning_Mode mode,
@@ -477,10 +440,10 @@ void FT2Font::load_char(long charcode, FT_Int32 flags, FT2Font *&ft_object, bool
477440
if (!was_found) {
478441
ft_glyph_warn(charcode, glyph_seen_fonts);
479442
if (charcode_error) {
480-
throw_ft_error("Could not load charcode", charcode_error);
443+
THROW_FT_ERROR("charcode loading", charcode_error);
481444
}
482445
else if (glyph_error) {
483-
throw_ft_error("Could not load charcode", glyph_error);
446+
THROW_FT_ERROR("charcode loading", glyph_error);
484447
}
485448
} else if (ft_object_with_glyph->warn_if_used) {
486449
ft_glyph_warn(charcode, glyph_seen_fonts);
@@ -494,13 +457,9 @@ void FT2Font::load_char(long charcode, FT_Int32 flags, FT2Font *&ft_object, bool
494457
glyph_seen_fonts.insert((face != nullptr)?face->family_name: nullptr);
495458
ft_glyph_warn((FT_ULong)charcode, glyph_seen_fonts);
496459
}
497-
if (FT_Error error = FT_Load_Glyph(face, glyph_index, flags)) {
498-
throw_ft_error("Could not load charcode", error);
499-
}
460+
FT_CHECK(FT_Load_Glyph, face, glyph_index, flags);
500461
FT_Glyph thisGlyph;
501-
if (FT_Error error = FT_Get_Glyph(face->glyph, &thisGlyph)) {
502-
throw_ft_error("Could not get glyph", error);
503-
}
462+
FT_CHECK(FT_Get_Glyph, face->glyph, &thisGlyph);
504463
glyphs.push_back(thisGlyph);
505464
}
506465
}
@@ -600,13 +559,9 @@ void FT2Font::load_glyph(FT_UInt glyph_index,
600559

601560
void FT2Font::load_glyph(FT_UInt glyph_index, FT_Int32 flags)
602561
{
603-
if (FT_Error error = FT_Load_Glyph(face, glyph_index, flags)) {
604-
throw_ft_error("Could not load glyph", error);
605-
}
562+
FT_CHECK(FT_Load_Glyph, face, glyph_index, flags);
606563
FT_Glyph thisGlyph;
607-
if (FT_Error error = FT_Get_Glyph(face->glyph, &thisGlyph)) {
608-
throw_ft_error("Could not get glyph", error);
609-
}
564+
FT_CHECK(FT_Get_Glyph, face->glyph, &thisGlyph);
610565
glyphs.push_back(thisGlyph);
611566
}
612567

@@ -651,13 +606,10 @@ void FT2Font::draw_glyphs_to_bitmap(bool antialiased)
651606
image = py::array_t<uint8_t>{{height, width}};
652607
std::memset(image.mutable_data(0), 0, image.nbytes());
653608

654-
for (auto & glyph : glyphs) {
655-
FT_Error error = FT_Glyph_To_Bitmap(
609+
for (auto & glyph: glyphs) {
610+
FT_CHECK(
611+
FT_Glyph_To_Bitmap,
656612
&glyph, antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, nullptr, 1);
657-
if (error) {
658-
throw_ft_error("Could not convert glyph to bitmap", error);
659-
}
660-
661613
FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph;
662614
// now, draw to our target surface (convert position)
663615

@@ -681,16 +633,12 @@ void FT2Font::draw_glyph_to_bitmap(
681633
throw std::runtime_error("glyph num is out of range");
682634
}
683635

684-
FT_Error error = FT_Glyph_To_Bitmap(
685-
&glyphs[glyphInd],
686-
antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO,
687-
&sub_offset, // additional translation
688-
1 // destroy image
689-
);
690-
if (error) {
691-
throw_ft_error("Could not convert glyph to bitmap", error);
692-
}
693-
636+
FT_CHECK(
637+
FT_Glyph_To_Bitmap,
638+
&glyphs[glyphInd],
639+
antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO,
640+
&sub_offset, // additional translation
641+
1); // destroy image
694642
FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyphs[glyphInd];
695643

696644
draw_bitmap(im, &bitmap->bitmap, x + bitmap->left, y);
@@ -715,9 +663,7 @@ void FT2Font::get_glyph_name(unsigned int glyph_number, std::string &buffer,
715663
throw std::runtime_error("Failed to convert glyph to standard name");
716664
}
717665
} else {
718-
if (FT_Error error = FT_Get_Glyph_Name(face, glyph_number, buffer.data(), buffer.size())) {
719-
throw_ft_error("Could not get glyph names", error);
720-
}
666+
FT_CHECK(FT_Get_Glyph_Name, face, glyph_number, buffer.data(), buffer.size());
721667
auto len = buffer.find('\0');
722668
if (len != buffer.npos) {
723669
buffer.resize(len);

‎src/ft2font.h

Copy file name to clipboardExpand all lines: src/ft2font.h
+28-3Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef MPL_FT2FONT_H
77
#define MPL_FT2FONT_H
88

9+
#include <filesystem>
910
#include <set>
1011
#include <string>
1112
#include <string_view>
@@ -26,12 +27,36 @@ extern "C" {
2627
#include <pybind11/numpy.h>
2728
namespace py = pybind11;
2829

29-
/*
30-
By definition, FT_FIXED as 2 16bit values stored in a single long.
31-
*/
30+
// By definition, FT_FIXED as 2 16bit values stored in a single long.
3231
#define FIXED_MAJOR(val) (signed short)((val & 0xffff0000) >> 16)
3332
#define FIXED_MINOR(val) (unsigned short)(val & 0xffff)
3433

34+
// Error handling (error codes are loaded as described in fterror.h).
35+
inline char const* ft_error_string(FT_Error error) {
36+
#undef __FTERRORS_H__
37+
#define FT_ERROR_START_LIST switch (error) {
38+
#define FT_ERRORDEF( e, v, s ) case v: return s;
39+
#define FT_ERROR_END_LIST default: return NULL; }
40+
#include FT_ERRORS_H
41+
}
42+
43+
// No more than 16 hex digits + "0x" + null byte for a 64-bit int error.
44+
#define THROW_FT_ERROR(name, err) { \
45+
char buf[20] = {0}; \
46+
sprintf(buf, "%#04x", err); \
47+
throw std::runtime_error{ \
48+
name " (" \
49+
+ std::filesystem::path(__FILE__).filename().string() \
50+
+ " line " + std::to_string(__LINE__) + ") failed with error " \
51+
+ std::string{buf} + ": " + std::string{ft_error_string(err)}}; \
52+
} (void)0
53+
54+
#define FT_CHECK(func, ...) { \
55+
if (auto const& error_ = func(__VA_ARGS__)) { \
56+
THROW_FT_ERROR(#func, error_); \
57+
} \
58+
} (void)0
59+
3560
// the FreeType string rendered into a width, height buffer
3661
class FT2Image
3762
{

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.