From 4d5a99566e11b2f094781ee02187bc6481655dbf Mon Sep 17 00:00:00 2001 From: JCash Date: Mon, 28 Jul 2025 10:06:04 +0200 Subject: [PATCH 1/7] Initial version using ifdef RAQM_FREETYPE --- src/raqm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/raqm.h | 27 ++++++++++- 2 files changed, 162 insertions(+), 4 deletions(-) diff --git a/src/raqm.c b/src/raqm.c index dcd9e2a5..8dfefbb8 100644 --- a/src/raqm.c +++ b/src/raqm.c @@ -28,6 +28,9 @@ #include #include +#include + +#include // debug #ifdef RAQM_SHEENBIDI #ifdef RAQM_SHEENBIDI_GT_2_9 @@ -40,7 +43,9 @@ #endif #include +#ifdef RAQM_FREETYPE #include +#endif #include "raqm.h" @@ -152,7 +157,10 @@ #define RAQM_DBG(...) #endif +#define RAQM_TESTING + #ifdef RAQM_TESTING +#include # define RAQM_TEST(...) printf (__VA_ARGS__) # define SCRIPT_TO_STRING(script) \ char buff[5]; \ @@ -173,8 +181,12 @@ typedef struct { +#ifdef RAQM_FREETYPE FT_Face ftface; int ftloadflags; +#else + hb_font_t *hbfont; +#endif hb_language_t lang; hb_script_t script; int spacing_after; @@ -236,8 +248,12 @@ _raqm_init_text_info (raqm_t *rq) hb_language_t default_lang = hb_language_get_default (); for (size_t i = 0; i < rq->text_len; i++) { +#ifdef RAQM_FREETYPE rq->text_info[i].ftface = NULL; rq->text_info[i].ftloadflags = -1; +#else + rq->text_info[i].hbfont = NULL; +#endif rq->text_info[i].lang = default_lang; rq->text_info[i].script = HB_SCRIPT_INVALID; rq->text_info[i].spacing_after = 0; @@ -250,22 +266,29 @@ _raqm_release_text_info (raqm_t *rq) if (!rq->text_info) return; +#ifdef RAQM_FREETYPE for (size_t i = 0; i < rq->text_len; i++) { if (rq->text_info[i].ftface) FT_Done_Face (rq->text_info[i].ftface); } +#endif } static bool _raqm_compare_text_info (_raqm_text_info a, _raqm_text_info b) { +#ifdef RAQM_FREETYPE if (a.ftface != b.ftface) return false; if (a.ftloadflags != b.ftloadflags) return false; +#else + if (a.hbfont != b.hbfont) + return false; +#endif if (a.lang != b.lang) return false; @@ -358,8 +381,10 @@ _raqm_free_runs (raqm_run_t *runs) if (run->buffer) hb_buffer_destroy (run->buffer); +#ifdef RAQM_FREETYPE if (run->font) hb_font_destroy (run->font); +#endif free (run); } @@ -483,11 +508,15 @@ raqm_clear_contents (raqm_t *rq) if (run->buffer) hb_buffer_reset (run->buffer); +#ifdef RAQM_FREETYPE if (run->font) { hb_font_destroy (run->font); run->font = NULL; } +#else + run->font = NULL; +#endif if (!run->next) { @@ -880,6 +909,8 @@ raqm_add_font_feature (raqm_t *rq, return ok; } +#ifdef RAQM_FREETYPE + static hb_font_t * _raqm_create_hb_font (raqm_t *rq, FT_Face face, @@ -1081,6 +1112,65 @@ raqm_set_freetype_load_flags_range (raqm_t *rq, return _raqm_set_freetype_load_flags (rq, flags, start, end); } +#else + + +static bool +_raqm_set_hb_font (raqm_t *rq, + hb_font_t* font, + size_t start, + size_t end) +{ + if (!rq) + return false; + + if (!rq->text_len) + return true; + + if (start >= rq->text_len || end > rq->text_len) + return false; + + if (!rq->text_info) + return false; + + for (size_t i = start; i < end; i++) + { + rq->text_info[i].hbfont = font; + } + + return true; +} + +RAQM_API bool +raqm_set_hb_font (raqm_t *rq, + hb_font_t* font) +{ + + return _raqm_set_hb_font (rq, font, 0, rq->text_len); +} + +RAQM_API bool +raqm_set_hb_font_range (raqm_t *rq, + hb_font_t* font, + size_t start, + size_t len) +{ + size_t end; + + if (!rq) + return false; + + if (!rq->text_len) + return true; + + end = _raqm_encoding_to_u32_index (rq, start + len); + start = _raqm_encoding_to_u32_index (rq, start); + + return _raqm_set_hb_font (rq, font, start, end); +} + +#endif // RAQM_FREETYPE + static bool _raqm_set_spacing (raqm_t *rq, int spacing, @@ -1292,8 +1382,13 @@ raqm_layout (raqm_t *rq) for (size_t i = 0; i < rq->text_len; i++) { +#ifdef RAQM_FREETYPE if (!rq->text_info[i].ftface) return false; +#else + if (!rq->text_info[i].hbfont) + return false; +#endif } if (!_raqm_itemize (rq)) @@ -1378,12 +1473,21 @@ raqm_get_glyphs (raqm_t *rq, rq->glyphs[count + i].y_advance = position[i].y_advance; rq->glyphs[count + i].x_offset = position[i].x_offset; rq->glyphs[count + i].y_offset = position[i].y_offset; +#ifdef RAQM_FREETYPE rq->glyphs[count + i].ftface = rq->text_info[info[i].cluster].ftface; +#else + rq->glyphs[count + i].hbfont = rq->text_info[info[i].cluster].hbfont; +#endif RAQM_TEST ("glyph [%d]\tx_offset: %d\ty_offset: %d\tx_advance: %d\tfont: %s\n", rq->glyphs[count + i].index, rq->glyphs[count + i].x_offset, rq->glyphs[count + i].y_offset, rq->glyphs[count + i].x_advance, - rq->glyphs[count + i].ftface->family_name); +#ifdef RAQM_FREETYPE + rq->glyphs[count + i].ftface->family_name +#else + "TODO: family name" +#endif + ); } count += len; @@ -1794,8 +1898,13 @@ _raqm_itemize (raqm_t *rq) { run->pos = runs[i].pos + runs[i].len - 1; run->script = rq->text_info[run->pos].script; +#ifdef RAQM_FREETYPE run->font = _raqm_create_hb_font (rq, rq->text_info[run->pos].ftface, rq->text_info[run->pos].ftloadflags); +#else + run->font = rq->text_info[run->pos].hbfont; +#endif + for (int j = runs[i].len - 1; j >= 0; j--) { _raqm_text_info info = rq->text_info[runs[i].pos + j]; @@ -1811,8 +1920,13 @@ _raqm_itemize (raqm_t *rq) newrun->len = 1; newrun->direction = _raqm_hb_dir (rq, runs[i].level); newrun->script = info.script; + +#ifdef RAQM_FREETYPE newrun->font = _raqm_create_hb_font (rq, info.ftface, info.ftloadflags); +#else + newrun->font = info.hbfont; +#endif run->next = newrun; run = newrun; } @@ -1827,8 +1941,12 @@ _raqm_itemize (raqm_t *rq) { run->pos = runs[i].pos; run->script = rq->text_info[run->pos].script; +#ifdef RAQM_FREETYPE run->font = _raqm_create_hb_font (rq, rq->text_info[run->pos].ftface, rq->text_info[run->pos].ftloadflags); +#else + run->font = rq->text_info[run->pos].hbfont; +#endif for (size_t j = 0; j < runs[i].len; j++) { _raqm_text_info info = rq->text_info[runs[i].pos + j]; @@ -1844,8 +1962,12 @@ _raqm_itemize (raqm_t *rq) newrun->len = 1; newrun->direction = _raqm_hb_dir (rq, runs[i].level); newrun->script = info.script; +#ifdef RAQM_FREETYPE newrun->font = _raqm_create_hb_font (rq, info.ftface, info.ftloadflags); +#else + newrun->font = info.hbfont; +#endif run->next = newrun; run = newrun; } @@ -1872,7 +1994,12 @@ _raqm_itemize (raqm_t *rq) RAQM_TEST ("run[%zu]:\t start: %d\tlength: %d\tdirection: %s\tscript: %s\tfont: %s\n", run_count++, run->pos, run->len, hb_direction_to_string (run->direction), buff, - rq->text_info[run->pos].ftface->family_name); +#ifdef RAQM_FREETYPE + rq->text_info[run->pos].ftface->family_name +#else + "TODO: family name" +#endif + ); } RAQM_TEST ("\n"); #endif @@ -2150,6 +2277,7 @@ _raqm_resolve_scripts (raqm_t *rq) return true; } +#ifdef RAQM_FREETYPE static void _raqm_ft_transform (int *x, int *y, @@ -2164,6 +2292,7 @@ _raqm_ft_transform (int *x, *x = vector.x; *y = vector.y; } +#endif #if !HB_VERSION_ATLEAST (10, 4, 0) # define hb_ft_font_get_ft_face hb_ft_font_get_face @@ -2196,19 +2325,25 @@ _raqm_shape (raqm_t *rq) NULL); { +#ifdef RAQM_FREETYPE FT_Matrix matrix; +#endif hb_glyph_info_t *info; hb_glyph_position_t *pos; unsigned int len; +#ifdef RAQM_FREETYPE FT_Get_Transform (hb_ft_font_get_ft_face (run->font), &matrix, NULL); +#endif pos = hb_buffer_get_glyph_positions (run->buffer, &len); info = hb_buffer_get_glyph_infos (run->buffer, &len); for (unsigned int i = 0; i < len; i++) { +#ifdef RAQM_FREETYPE _raqm_ft_transform (&pos[i].x_advance, &pos[i].y_advance, matrix); _raqm_ft_transform (&pos[i].x_offset, &pos[i].y_offset, matrix); +#endif bool set_spacing = false; if (run->direction == HB_DIRECTION_RTL) diff --git a/src/raqm.h b/src/raqm.h index 6fd6089c..f3a0029f 100644 --- a/src/raqm.h +++ b/src/raqm.h @@ -36,8 +36,11 @@ #include #include + +#ifdef RAQM_FREETYPE #include #include FT_FREETYPE_H +#endif #ifdef __cplusplus extern "C" { @@ -76,25 +79,30 @@ typedef enum /** * raqm_glyph_t: + * @hbfont: the harfbuzz font of the glyph. (Only available if RAQM_FREETYPE is not defined) + * @ftface: the @FT_Face of the glyph. (Only available if RAQM_FREETYPE is defined) * @index: the index of the glyph in the font file. * @x_advance: the glyph advance width in horizontal text. * @y_advance: the glyph advance width in vertical text. * @x_offset: the horizontal movement of the glyph from the current point. * @y_offset: the vertical movement of the glyph from the current point. * @cluster: the index of original character in input text. - * @ftface: the @FT_Face of the glyph. * * The structure that holds information about output glyphs, returned from * raqm_get_glyphs(). */ typedef struct raqm_glyph_t { +#ifdef RAQM_FREETYPE + FT_Face ftface; +#else + hb_font_t* hbfont; +#endif unsigned int index; int x_advance; int y_advance; int x_offset; int y_offset; uint32_t cluster; - FT_Face ftface; } raqm_glyph_t; RAQM_API raqm_t * @@ -138,6 +146,8 @@ raqm_add_font_feature (raqm_t *rq, const char *feature, int len); +#ifdef RAQM_FREETYPE + RAQM_API bool raqm_set_freetype_face (raqm_t *rq, FT_Face face); @@ -157,6 +167,19 @@ raqm_set_freetype_load_flags_range (raqm_t *rq, int flags, size_t start, size_t len); +#else + +RAQM_API bool +raqm_set_hb_font (raqm_t *rq, + hb_font_t* font); + +RAQM_API bool +raqm_set_hb_font_range (raqm_t *rq, + hb_font_t* font, + size_t start, + size_t len); + +#endif // RAQM_FREETYPE RAQM_API bool raqm_set_letter_spacing_range(raqm_t *rq, From 90e6a597894bac80402ba9389ca51ff31dc3c3da Mon Sep 17 00:00:00 2001 From: JCash Date: Mon, 28 Jul 2025 10:11:36 +0200 Subject: [PATCH 2/7] Removed usage of FreeType in library --- src/raqm.c | 328 +---------------------------------------------------- src/raqm.h | 37 +----- 2 files changed, 5 insertions(+), 360 deletions(-) diff --git a/src/raqm.c b/src/raqm.c index 8dfefbb8..1da2083b 100644 --- a/src/raqm.c +++ b/src/raqm.c @@ -43,9 +43,6 @@ #endif #include -#ifdef RAQM_FREETYPE -#include -#endif #include "raqm.h" @@ -181,12 +178,7 @@ typedef struct { -#ifdef RAQM_FREETYPE - FT_Face ftface; - int ftloadflags; -#else hb_font_t *hbfont; -#endif hb_language_t lang; hb_script_t script; int spacing_after; @@ -248,12 +240,7 @@ _raqm_init_text_info (raqm_t *rq) hb_language_t default_lang = hb_language_get_default (); for (size_t i = 0; i < rq->text_len; i++) { -#ifdef RAQM_FREETYPE - rq->text_info[i].ftface = NULL; - rq->text_info[i].ftloadflags = -1; -#else rq->text_info[i].hbfont = NULL; -#endif rq->text_info[i].lang = default_lang; rq->text_info[i].script = HB_SCRIPT_INVALID; rq->text_info[i].spacing_after = 0; @@ -265,30 +252,14 @@ _raqm_release_text_info (raqm_t *rq) { if (!rq->text_info) return; - -#ifdef RAQM_FREETYPE - for (size_t i = 0; i < rq->text_len; i++) - { - if (rq->text_info[i].ftface) - FT_Done_Face (rq->text_info[i].ftface); - } -#endif } static bool _raqm_compare_text_info (_raqm_text_info a, _raqm_text_info b) { -#ifdef RAQM_FREETYPE - if (a.ftface != b.ftface) - return false; - - if (a.ftloadflags != b.ftloadflags) - return false; -#else if (a.hbfont != b.hbfont) return false; -#endif if (a.lang != b.lang) return false; @@ -381,11 +352,6 @@ _raqm_free_runs (raqm_run_t *runs) if (run->buffer) hb_buffer_destroy (run->buffer); -#ifdef RAQM_FREETYPE - if (run->font) - hb_font_destroy (run->font); -#endif - free (run); } } @@ -508,15 +474,7 @@ raqm_clear_contents (raqm_t *rq) if (run->buffer) hb_buffer_reset (run->buffer); -#ifdef RAQM_FREETYPE - if (run->font) - { - hb_font_destroy (run->font); - run->font = NULL; - } -#else run->font = NULL; -#endif if (!run->next) { @@ -909,212 +867,6 @@ raqm_add_font_feature (raqm_t *rq, return ok; } -#ifdef RAQM_FREETYPE - -static hb_font_t * -_raqm_create_hb_font (raqm_t *rq, - FT_Face face, - int loadflags) -{ - hb_font_t *font = hb_ft_font_create_referenced (face); - - if (loadflags >= 0) - hb_ft_font_set_load_flags (font, loadflags); - - return font; -} - -static bool -_raqm_set_freetype_face (raqm_t *rq, - FT_Face face, - size_t start, - size_t end) -{ - if (!rq) - return false; - - if (!rq->text_len) - return true; - - if (start >= rq->text_len || end > rq->text_len) - return false; - - if (!rq->text_info) - return false; - - for (size_t i = start; i < end; i++) - { - if (rq->text_info[i].ftface) - FT_Done_Face (rq->text_info[i].ftface); - rq->text_info[i].ftface = face; - FT_Reference_Face (face); - } - - return true; -} - -/** - * raqm_set_freetype_face: - * @rq: a #raqm_t. - * @face: an #FT_Face. - * - * Sets an #FT_Face to be used for all characters in @rq. - * - * See also raqm_set_freetype_face_range(). - * - * Return value: - * `true` if no errors happened, `false` otherwise. - * - * Since: 0.1 - */ -bool -raqm_set_freetype_face (raqm_t *rq, - FT_Face face) -{ - return _raqm_set_freetype_face (rq, face, 0, rq->text_len); -} - -/** - * raqm_set_freetype_face_range: - * @rq: a #raqm_t. - * @face: an #FT_Face. - * @start: index of first character that should use @face from the input string. - * @len: number of elements using @face. - * - * Sets an #FT_Face to be used for @len-number of characters staring at @start. - * The @start and @len are input string array indices, counting elements - * according to the underlying encoding. @start must always be aligned to the - * start of an encoded codepoint, and @len must always end at a codepoint's - * final element. - * - * This method can be used repeatedly to set different faces for different - * parts of the text. It is the responsibility of the client to make sure that - * face ranges cover the whole text, and is properly aligned. - * - * See also raqm_set_freetype_face(). - * - * Return value: - * `true` if no errors happened, `false` otherwise. - * - * Since: 0.1 - */ -bool -raqm_set_freetype_face_range (raqm_t *rq, - FT_Face face, - size_t start, - size_t len) -{ - size_t end; - - if (!rq) - return false; - - if (!rq->text_len) - return true; - - end = _raqm_encoding_to_u32_index (rq, start + len); - start = _raqm_encoding_to_u32_index (rq, start); - - return _raqm_set_freetype_face (rq, face, start, end); -} - -static bool -_raqm_set_freetype_load_flags (raqm_t *rq, - int flags, - size_t start, - size_t end) -{ - if (!rq) - return false; - - if (!rq->text_len) - return true; - - if (start >= rq->text_len || end > rq->text_len) - return false; - - if (!rq->text_info) - return false; - - for (size_t i = start; i < end; i++) - rq->text_info[i].ftloadflags = flags; - - return true; -} - -/** - * raqm_set_freetype_load_flags: - * @rq: a #raqm_t. - * @flags: FreeType load flags. - * - * Sets the load flags passed to FreeType when loading glyphs, should be the - * same flags used by the client when rendering FreeType glyphs. - * - * This requires version of HarfBuzz that has hb_ft_font_set_load_flags(), for - * older version the flags will be ignored. - * - * Return value: - * `true` if no errors happened, `false` otherwise. - * - * Since: 0.3 - */ -bool -raqm_set_freetype_load_flags (raqm_t *rq, - int flags) -{ - return _raqm_set_freetype_load_flags(rq, flags, 0, rq->text_len); -} - -/** - * raqm_set_freetype_load_flags_range: - * @rq: a #raqm_t. - * @flags: FreeType load flags. - * @start: index of first character that should use @flags. - * @len: number of characters using @flags. - * - * Sets the load flags passed to FreeType when loading glyphs for @len-number - * of characters staring at @start. Flags should be the same as used by the - * client when rendering corresponding FreeType glyphs. The @start and @len - * are input string array indices (i.e. counting bytes in UTF-8 and scaler - * values in UTF-32). - * - * This method can be used repeatedly to set different flags for different - * parts of the text. It is the responsibility of the client to make sure that - * flag ranges cover the whole text. - * - * This requires version of HarfBuzz that has hb_ft_font_set_load_flags(), for - * older version the flags will be ignored. - * - * See also raqm_set_freetype_load_flags(). - * - * Return value: - * `true` if no errors happened, `false` otherwise. - * - * Since: 0.9 - */ -bool -raqm_set_freetype_load_flags_range (raqm_t *rq, - int flags, - size_t start, - size_t len) -{ - size_t end; - - if (!rq) - return false; - - if (!rq->text_len) - return true; - - end = _raqm_encoding_to_u32_index (rq, start + len); - start = _raqm_encoding_to_u32_index (rq, start); - - return _raqm_set_freetype_load_flags (rq, flags, start, end); -} - -#else - - static bool _raqm_set_hb_font (raqm_t *rq, hb_font_t* font, @@ -1145,7 +897,6 @@ RAQM_API bool raqm_set_hb_font (raqm_t *rq, hb_font_t* font) { - return _raqm_set_hb_font (rq, font, 0, rq->text_len); } @@ -1169,8 +920,6 @@ raqm_set_hb_font_range (raqm_t *rq, return _raqm_set_hb_font (rq, font, start, end); } -#endif // RAQM_FREETYPE - static bool _raqm_set_spacing (raqm_t *rq, int spacing, @@ -1382,13 +1131,8 @@ raqm_layout (raqm_t *rq) for (size_t i = 0; i < rq->text_len; i++) { -#ifdef RAQM_FREETYPE - if (!rq->text_info[i].ftface) - return false; -#else if (!rq->text_info[i].hbfont) return false; -#endif } if (!_raqm_itemize (rq)) @@ -1473,21 +1217,11 @@ raqm_get_glyphs (raqm_t *rq, rq->glyphs[count + i].y_advance = position[i].y_advance; rq->glyphs[count + i].x_offset = position[i].x_offset; rq->glyphs[count + i].y_offset = position[i].y_offset; -#ifdef RAQM_FREETYPE - rq->glyphs[count + i].ftface = rq->text_info[info[i].cluster].ftface; -#else rq->glyphs[count + i].hbfont = rq->text_info[info[i].cluster].hbfont; -#endif - RAQM_TEST ("glyph [%d]\tx_offset: %d\ty_offset: %d\tx_advance: %d\tfont: %s\n", + RAQM_TEST ("glyph [%d]\tx_offset: %d\ty_offset: %d\tx_advance: %d\t\n", rq->glyphs[count + i].index, rq->glyphs[count + i].x_offset, - rq->glyphs[count + i].y_offset, rq->glyphs[count + i].x_advance, -#ifdef RAQM_FREETYPE - rq->glyphs[count + i].ftface->family_name -#else - "TODO: family name" -#endif - ); + rq->glyphs[count + i].y_offset, rq->glyphs[count + i].x_advance); } count += len; @@ -1898,12 +1632,7 @@ _raqm_itemize (raqm_t *rq) { run->pos = runs[i].pos + runs[i].len - 1; run->script = rq->text_info[run->pos].script; -#ifdef RAQM_FREETYPE - run->font = _raqm_create_hb_font (rq, rq->text_info[run->pos].ftface, - rq->text_info[run->pos].ftloadflags); -#else run->font = rq->text_info[run->pos].hbfont; -#endif for (int j = runs[i].len - 1; j >= 0; j--) { @@ -1921,12 +1650,7 @@ _raqm_itemize (raqm_t *rq) newrun->direction = _raqm_hb_dir (rq, runs[i].level); newrun->script = info.script; -#ifdef RAQM_FREETYPE - newrun->font = _raqm_create_hb_font (rq, info.ftface, - info.ftloadflags); -#else newrun->font = info.hbfont; -#endif run->next = newrun; run = newrun; } @@ -1941,12 +1665,7 @@ _raqm_itemize (raqm_t *rq) { run->pos = runs[i].pos; run->script = rq->text_info[run->pos].script; -#ifdef RAQM_FREETYPE - run->font = _raqm_create_hb_font (rq, rq->text_info[run->pos].ftface, - rq->text_info[run->pos].ftloadflags); -#else run->font = rq->text_info[run->pos].hbfont; -#endif for (size_t j = 0; j < runs[i].len; j++) { _raqm_text_info info = rq->text_info[runs[i].pos + j]; @@ -1962,12 +1681,7 @@ _raqm_itemize (raqm_t *rq) newrun->len = 1; newrun->direction = _raqm_hb_dir (rq, runs[i].level); newrun->script = info.script; -#ifdef RAQM_FREETYPE - newrun->font = _raqm_create_hb_font (rq, info.ftface, - info.ftloadflags); -#else newrun->font = info.hbfont; -#endif run->next = newrun; run = newrun; } @@ -1991,15 +1705,9 @@ _raqm_itemize (raqm_t *rq) for (raqm_run_t *run = rq->runs; run != NULL; run = run->next) { SCRIPT_TO_STRING (run->script); - RAQM_TEST ("run[%zu]:\t start: %d\tlength: %d\tdirection: %s\tscript: %s\tfont: %s\n", + RAQM_TEST ("run[%zu]:\t start: %d\tlength: %d\tdirection: %s\tscript: %s\n", run_count++, run->pos, run->len, - hb_direction_to_string (run->direction), buff, -#ifdef RAQM_FREETYPE - rq->text_info[run->pos].ftface->family_name -#else - "TODO: family name" -#endif - ); + hb_direction_to_string (run->direction), buff); } RAQM_TEST ("\n"); #endif @@ -2277,23 +1985,6 @@ _raqm_resolve_scripts (raqm_t *rq) return true; } -#ifdef RAQM_FREETYPE -static void -_raqm_ft_transform (int *x, - int *y, - FT_Matrix matrix) -{ - FT_Vector vector; - vector.x = *x; - vector.y = *y; - - FT_Vector_Transform (&vector, &matrix); - - *x = vector.x; - *y = vector.y; -} -#endif - #if !HB_VERSION_ATLEAST (10, 4, 0) # define hb_ft_font_get_ft_face hb_ft_font_get_face #endif @@ -2325,26 +2016,15 @@ _raqm_shape (raqm_t *rq) NULL); { -#ifdef RAQM_FREETYPE - FT_Matrix matrix; -#endif hb_glyph_info_t *info; hb_glyph_position_t *pos; unsigned int len; -#ifdef RAQM_FREETYPE - FT_Get_Transform (hb_ft_font_get_ft_face (run->font), &matrix, NULL); -#endif pos = hb_buffer_get_glyph_positions (run->buffer, &len); info = hb_buffer_get_glyph_infos (run->buffer, &len); for (unsigned int i = 0; i < len; i++) { -#ifdef RAQM_FREETYPE - _raqm_ft_transform (&pos[i].x_advance, &pos[i].y_advance, matrix); - _raqm_ft_transform (&pos[i].x_offset, &pos[i].y_offset, matrix); -#endif - bool set_spacing = false; if (run->direction == HB_DIRECTION_RTL) { diff --git a/src/raqm.h b/src/raqm.h index f3a0029f..d98a885b 100644 --- a/src/raqm.h +++ b/src/raqm.h @@ -37,11 +37,6 @@ #include #include -#ifdef RAQM_FREETYPE -#include -#include FT_FREETYPE_H -#endif - #ifdef __cplusplus extern "C" { #endif @@ -79,8 +74,7 @@ typedef enum /** * raqm_glyph_t: - * @hbfont: the harfbuzz font of the glyph. (Only available if RAQM_FREETYPE is not defined) - * @ftface: the @FT_Face of the glyph. (Only available if RAQM_FREETYPE is defined) + * @hbfont: the harfbuzz font of the glyph. * @index: the index of the glyph in the font file. * @x_advance: the glyph advance width in horizontal text. * @y_advance: the glyph advance width in vertical text. @@ -92,11 +86,7 @@ typedef enum * raqm_get_glyphs(). */ typedef struct raqm_glyph_t { -#ifdef RAQM_FREETYPE - FT_Face ftface; -#else hb_font_t* hbfont; -#endif unsigned int index; int x_advance; int y_advance; @@ -146,29 +136,6 @@ raqm_add_font_feature (raqm_t *rq, const char *feature, int len); -#ifdef RAQM_FREETYPE - -RAQM_API bool -raqm_set_freetype_face (raqm_t *rq, - FT_Face face); - -RAQM_API bool -raqm_set_freetype_face_range (raqm_t *rq, - FT_Face face, - size_t start, - size_t len); - -RAQM_API bool -raqm_set_freetype_load_flags (raqm_t *rq, - int flags); - -RAQM_API bool -raqm_set_freetype_load_flags_range (raqm_t *rq, - int flags, - size_t start, - size_t len); -#else - RAQM_API bool raqm_set_hb_font (raqm_t *rq, hb_font_t* font); @@ -179,8 +146,6 @@ raqm_set_hb_font_range (raqm_t *rq, size_t start, size_t len); -#endif // RAQM_FREETYPE - RAQM_API bool raqm_set_letter_spacing_range(raqm_t *rq, int spacing, From f0e83a112f61b5304d36cdeb0d0d4783f42c3847 Mon Sep 17 00:00:00 2001 From: JCash Date: Mon, 28 Jul 2025 10:56:15 +0200 Subject: [PATCH 3/7] Replaced FreeType in test with hb_font_t --- tests/raqm-test.c | 113 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 19 deletions(-) diff --git a/tests/raqm-test.c b/tests/raqm-test.c index 7d10914a..6ad5124c 100644 --- a/tests/raqm-test.c +++ b/tests/raqm-test.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -49,6 +51,15 @@ static int invisible_glyph = 0; /* Special exit code, recognized by automake that we're skipping a test. */ static const int skip_exit_status = 77; +typedef struct _font_data +{ + hb_blob_t *blob; + hb_face_t *face; + hb_font_t *font; + void *data; + struct _font_data* next; +} font_data_t; + static char* encode_bytes (const char *bytes) { @@ -134,28 +145,87 @@ has_requirement (char *req) return ver >= req_ver; } - if (strcmp (req, "FT_") > 0) - { - long req_ver = strtol (req + strlen ("FT_"), NULL, 10); - long ver = FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH; - return ver >= req_ver; - } - fprintf (stderr, "Unknown requirement: %s\n", req); return false; } +static void* +read_file (const char* path, size_t* file_size) +{ + void* mem; + size_t size, nread; + FILE* file; + + file = fopen(path, "rb"); + if (!file) + { + printf("Failed to load %s\n", path); + return 0; + } + + fseek(file, 0, SEEK_END); + size = (size_t)ftell(file); + fseek(file, 0, SEEK_SET); + + mem = malloc(size); + + nread = fread(mem, 1, size, file); + fclose(file); + + if (nread != size) + { + fprintf(stderr, "Failed to read %zu bytes from %s\n", size, path); + free(mem); + return 0; + } + + if (file_size) + *file_size = size; + + return mem; +} + +static font_data_t* +load_font(const char* path) +{ + size_t fontdata_size; + font_data_t *font = (font_data_t*)malloc(sizeof(font_data_t)); + font->next = 0; + font->data = read_file(path, &fontdata_size); + assert (font->data != 0); + + font->blob = hb_blob_create(font->data, fontdata_size, HB_MEMORY_MODE_READONLY, 0, 0); + assert (font->blob != 0); + font->face = hb_face_create(font->blob, 0); + assert (font->face != 0); + font->font = hb_font_create(font->face); + assert (font->font != 0); + + return font; +} + +static void +free_font(font_data_t* font) +{ + if (font->font) + hb_font_destroy(font->font); + if (font->face) + hb_face_destroy(font->face); + if (font->blob) + hb_blob_destroy(font->blob); + free((void*)font->data); + free((void*)font); +} + int main (int argc, char **argv) { - FT_Library library; - FT_Face face; - raqm_t *rq; raqm_glyph_t *glyphs; size_t count, start_index, index; raqm_direction_t dir; int x = 0, y = 0; + font_data_t* fontdata = 0; unsigned int major, minor, micro; @@ -198,23 +268,23 @@ main (int argc, char **argv) rq = raqm_create (); assert (raqm_set_text_utf8 (rq, text, strlen (text))); assert (raqm_set_par_direction (rq, dir)); - assert (!FT_Init_FreeType (&library)); if (fonts) { for (char *tok = strtok (fonts, ","); tok; tok = strtok (NULL, ",")) { int start, length; - assert (!FT_New_Face (library, tok, 0, &face)); - assert (!FT_Set_Char_Size (face, face->units_per_EM, 0, 0, 0)); + font_data_t* font = load_font(tok); + assert (font != 0); + font->next = fontdata; start = atoi (strtok (NULL, ",")); length = atoi (strtok (NULL, ",")); - assert (raqm_set_freetype_face_range(rq, face, start, length)); + assert (raqm_set_hb_font_range(rq, font->font, start, length)); } } else { - assert (!FT_New_Face (library, font, 0, &face)); - assert (!FT_Set_Char_Size (face, face->units_per_EM, 0, 0, 0)); - assert (raqm_set_freetype_face (rq, face)); + fontdata = load_font(font); + assert (font != 0); + assert (raqm_set_hb_font (rq, fontdata->font)); } if (languages) @@ -279,8 +349,13 @@ main (int argc, char **argv) free (text); raqm_destroy (rq); - FT_Done_Face (face); - FT_Done_FreeType (library); + + while (fontdata != 0) + { + font_data_t* next = fontdata->next; + free_font (fontdata); + fontdata = next; + } return 0; } From c69cde6df1d20de81db1fd0cbb1fbd22af19d7d8 Mon Sep 17 00:00:00 2001 From: JCash Date: Mon, 28 Jul 2025 10:58:07 +0200 Subject: [PATCH 4/7] cleanup --- src/raqm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/raqm.c b/src/raqm.c index 1da2083b..4fc68699 100644 --- a/src/raqm.c +++ b/src/raqm.c @@ -154,8 +154,6 @@ #define RAQM_DBG(...) #endif -#define RAQM_TESTING - #ifdef RAQM_TESTING #include # define RAQM_TEST(...) printf (__VA_ARGS__) From e3cfdb0a8de4f3b576bf0dd1ac18110195a94844 Mon Sep 17 00:00:00 2001 From: JCash Date: Mon, 28 Jul 2025 11:18:07 +0200 Subject: [PATCH 5/7] output family name for unit tests --- src/raqm.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/raqm.c b/src/raqm.c index 4fc68699..00fb9677 100644 --- a/src/raqm.c +++ b/src/raqm.c @@ -156,6 +156,7 @@ #ifdef RAQM_TESTING #include +#include // for family name # define RAQM_TEST(...) printf (__VA_ARGS__) # define SCRIPT_TO_STRING(script) \ char buff[5]; \ @@ -1203,6 +1204,15 @@ raqm_get_glyphs (raqm_t *rq, hb_glyph_info_t *info; hb_glyph_position_t *position; +#ifdef RAQM_TESTING + char family[128]; + uint32_t family_name_len = sizeof(family); + hb_face_t *face = hb_font_get_face(run->font); + hb_ot_name_id_t name_id = HB_OT_NAME_ID_FONT_FAMILY; + hb_language_t language = HB_LANGUAGE_INVALID; + hb_ot_name_get_utf8 (face, name_id, language, &family_name_len, family); +#endif + len = hb_buffer_get_length (run->buffer); info = hb_buffer_get_glyph_infos (run->buffer, NULL); position = hb_buffer_get_glyph_positions (run->buffer, NULL); @@ -1217,9 +1227,10 @@ raqm_get_glyphs (raqm_t *rq, rq->glyphs[count + i].y_offset = position[i].y_offset; rq->glyphs[count + i].hbfont = rq->text_info[info[i].cluster].hbfont; - RAQM_TEST ("glyph [%d]\tx_offset: %d\ty_offset: %d\tx_advance: %d\t\n", + RAQM_TEST ("glyph [%d]\tx_offset: %d\ty_offset: %d\tx_advance: %d\tfont: %s\n", rq->glyphs[count + i].index, rq->glyphs[count + i].x_offset, - rq->glyphs[count + i].y_offset, rq->glyphs[count + i].x_advance); + rq->glyphs[count + i].y_offset, rq->glyphs[count + i].x_advance, + family); } count += len; @@ -1702,10 +1713,19 @@ _raqm_itemize (raqm_t *rq) RAQM_TEST ("Final Runs:\n"); for (raqm_run_t *run = rq->runs; run != NULL; run = run->next) { +#ifdef RAQM_TESTING + char family[128]; + uint32_t family_name_len = sizeof(family); + hb_face_t *face = hb_font_get_face(run->font); + hb_ot_name_id_t name_id = HB_OT_NAME_ID_FONT_FAMILY; + hb_language_t language = HB_LANGUAGE_INVALID; + hb_ot_name_get_utf8 (face, name_id, language, &family_name_len, family); +#endif + SCRIPT_TO_STRING (run->script); - RAQM_TEST ("run[%zu]:\t start: %d\tlength: %d\tdirection: %s\tscript: %s\n", + RAQM_TEST ("run[%zu]:\t start: %d\tlength: %d\tdirection: %s\tscript: %s\tfont: %s\n", run_count++, run->pos, run->len, - hb_direction_to_string (run->direction), buff); + hb_direction_to_string (run->direction), buff, family); } RAQM_TEST ("\n"); #endif From f2a794caab95b15eb4b3ce0f2fb58e7d1f674b3c Mon Sep 17 00:00:00 2001 From: JCash Date: Mon, 28 Jul 2025 11:24:26 +0200 Subject: [PATCH 6/7] cleanup --- src/raqm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/raqm.c b/src/raqm.c index 00fb9677..2154b6ef 100644 --- a/src/raqm.c +++ b/src/raqm.c @@ -30,8 +30,6 @@ #include #include -#include // debug - #ifdef RAQM_SHEENBIDI #ifdef RAQM_SHEENBIDI_GT_2_9 #include From d27ce31147e53c939960ee95052656f88fb0384e Mon Sep 17 00:00:00 2001 From: JCash Date: Mon, 28 Jul 2025 11:46:25 +0200 Subject: [PATCH 7/7] review cleanup --- src/raqm.c | 8 ++------ tests/raqm-test.c | 11 +++++------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/raqm.c b/src/raqm.c index 2154b6ef..ce6634c2 100644 --- a/src/raqm.c +++ b/src/raqm.c @@ -1206,9 +1206,7 @@ raqm_get_glyphs (raqm_t *rq, char family[128]; uint32_t family_name_len = sizeof(family); hb_face_t *face = hb_font_get_face(run->font); - hb_ot_name_id_t name_id = HB_OT_NAME_ID_FONT_FAMILY; - hb_language_t language = HB_LANGUAGE_INVALID; - hb_ot_name_get_utf8 (face, name_id, language, &family_name_len, family); + hb_ot_name_get_utf8 (face, HB_OT_NAME_ID_FONT_FAMILY, HB_LANGUAGE_INVALID, &family_name_len, family); #endif len = hb_buffer_get_length (run->buffer); @@ -1715,9 +1713,7 @@ _raqm_itemize (raqm_t *rq) char family[128]; uint32_t family_name_len = sizeof(family); hb_face_t *face = hb_font_get_face(run->font); - hb_ot_name_id_t name_id = HB_OT_NAME_ID_FONT_FAMILY; - hb_language_t language = HB_LANGUAGE_INVALID; - hb_ot_name_get_utf8 (face, name_id, language, &family_name_len, family); + hb_ot_name_get_utf8 (face, HB_OT_NAME_ID_FONT_FAMILY, HB_LANGUAGE_INVALID, &family_name_len, family); #endif SCRIPT_TO_STRING (run->script); diff --git a/tests/raqm-test.c b/tests/raqm-test.c index 6ad5124c..47245ee2 100644 --- a/tests/raqm-test.c +++ b/tests/raqm-test.c @@ -53,7 +53,6 @@ static const int skip_exit_status = 77; typedef struct _font_data { - hb_blob_t *blob; hb_face_t *face; hb_font_t *font; void *data; @@ -188,19 +187,21 @@ read_file (const char* path, size_t* file_size) static font_data_t* load_font(const char* path) { + hb_blob_t *blob; size_t fontdata_size; font_data_t *font = (font_data_t*)malloc(sizeof(font_data_t)); font->next = 0; font->data = read_file(path, &fontdata_size); assert (font->data != 0); - font->blob = hb_blob_create(font->data, fontdata_size, HB_MEMORY_MODE_READONLY, 0, 0); - assert (font->blob != 0); - font->face = hb_face_create(font->blob, 0); + blob = hb_blob_create(font->data, fontdata_size, HB_MEMORY_MODE_READONLY, 0, 0); + assert (blob != 0); + font->face = hb_face_create(blob, 0); assert (font->face != 0); font->font = hb_font_create(font->face); assert (font->font != 0); + hb_blob_destroy(blob); return font; } @@ -211,8 +212,6 @@ free_font(font_data_t* font) hb_font_destroy(font->font); if (font->face) hb_face_destroy(font->face); - if (font->blob) - hb_blob_destroy(font->blob); free((void*)font->data); free((void*)font); }