From 228fa71bf9186faedff48b3a259d696c7c07b5b5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 21 Oct 2018 17:43:29 -0700 Subject: [PATCH 01/36] [colr] Move sanitize --- src/hb-ot-color-colr-table.hh | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh index aef364934..0e7f6ef23 100644 --- a/src/hb-ot-color-colr-table.hh +++ b/src/hb-ot-color-colr-table.hh @@ -63,15 +63,8 @@ struct LayerRecord struct BaseGlyphRecord { - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this))); - } - - inline int cmp (hb_codepoint_t g) const { - return g < glyphId ? -1 : g > glyphId ? 1 : 0; - } + inline int cmp (hb_codepoint_t g) const + { return g < glyphId ? -1 : g > glyphId ? 1 : 0; } static int cmp (const void *pa, const void *pb) { @@ -80,6 +73,12 @@ struct BaseGlyphRecord return b->cmp (*a); } + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + public: GlyphID glyphId; /* Glyph ID of reference glyph */ HBUINT16 firstLayerIdx; /* Index (from beginning of From ee11fae9d0d2c16a3a4b4ecf5cf328ffe950bb03 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 21 Oct 2018 19:02:47 -0700 Subject: [PATCH 02/36] [color] Rename "gid" to "glyph" We don't expose "gid" in API. --- src/hb-ot-color.cc | 12 ++++++------ src/hb-ot-color.h | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 42ced5284..7588bef87 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -218,10 +218,10 @@ hb_ot_color_get_palette_colors (hb_face_t *face, /** * hb_ot_color_get_color_layers: * @face: a font face. - * @gid: + * @glyph: * @start_offset: * @count: (inout) (optional): - * @gids: (array length=count) (out) (optional): + * @glyphs: (array length=count) (out) (optional): * @color_indices: (array length=count) (out) (optional): * * Returns: @@ -230,16 +230,16 @@ hb_ot_color_get_palette_colors (hb_face_t *face, */ unsigned int hb_ot_color_get_color_layers (hb_face_t *face, - hb_codepoint_t gid, + hb_codepoint_t glyph, unsigned int start_offset, unsigned int *count /* IN/OUT. May be NULL. */, - hb_codepoint_t *gids /* OUT. May be NULL. */, + hb_codepoint_t *glyphs /* OUT. May be NULL. */, unsigned int *color_indices /* OUT. May be NULL. */) { const OT::COLR& colr = _get_colr (face); unsigned int num_results = 0; unsigned int start_layer_index, num_layers = 0; - if (colr.get_base_glyph_record (gid, &start_layer_index, &num_layers)) + if (colr.get_base_glyph_record (glyph, &start_layer_index, &num_layers)) { if (count) { @@ -247,7 +247,7 @@ hb_ot_color_get_color_layers (hb_face_t *face, for (unsigned int i = 0; i < layer_count; i++) { if (colr.get_layer_record (start_layer_index + start_offset + i, - &gids[num_results], &color_indices[num_results])) + &glyphs[num_results], &color_indices[num_results])) ++num_results; } } diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index a5f245d69..7d42eb581 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -57,15 +57,15 @@ HB_EXTERN unsigned int hb_ot_color_get_palette_colors (hb_face_t *face, unsigned int palette, /* default=0 */ unsigned int start_offset, - unsigned int *color_count /* IN/OUT. May be NULL. */, + unsigned int *color_count, /* IN/OUT. May be NULL. */ hb_color_t *colors /* OUT. May be NULL. */); HB_EXTERN unsigned int hb_ot_color_get_color_layers (hb_face_t *face, - hb_codepoint_t gid, + hb_codepoint_t glyph, unsigned int start_offset, - unsigned int *count /* IN/OUT. May be NULL. */, - hb_codepoint_t *gids /* OUT. May be NULL. */, + unsigned int *count, /* IN/OUT. May be NULL. */ + hb_codepoint_t *glyphs, /* OUT. May be NULL. */ unsigned int *color_indices /* OUT. May be NULL. */); /** From 9085a72deb041cf10edfa61d24b7c25f947f736b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 21 Oct 2018 19:08:25 -0700 Subject: [PATCH 03/36] [cpal] Touch up palette flags --- src/hb-ot-color.h | 16 ++++++++++------ test/api/test-ot-color.c | 4 ++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index 7d42eb581..ab2cec981 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -70,21 +70,25 @@ hb_ot_color_get_color_layers (hb_face_t *face, /** * hb_ot_color_palette_flags_t: - * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special to note about a color palette. - * @HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND: flag indicating that the color palette is suitable for rendering text on light background. - * @HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND: flag indicating that the color palette is suitable for rendering text on dark background. + * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special + * to note about a color palette. + * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND: flag indicating that the color + * palette is appropriate to use when displaying the font on a light background such as white. + * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: flag indicating that the color + * palette is appropriate to use when displaying the font on a dark background such as black. * * Since: REPLACEME */ typedef enum { /*< flags >*/ - HB_OT_COLOR_PALETTE_FLAG_DEFAULT = 0x00000000u, - HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND = 0x00000001u, - HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND = 0x00000002u, + HB_OT_COLOR_PALETTE_FLAG_DEFAULT = 0x00000000u, + HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND = 0x00000001u, + HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND = 0x00000002u, } hb_ot_color_palette_flags_t; HB_EXTERN hb_ot_color_palette_flags_t hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette); + HB_END_DECLS #endif /* HB_OT_COLOR_H */ diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c index 0eb0d681e..018b47d1f 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -191,8 +191,8 @@ test_hb_ot_color_get_palette_flags_v0 (void) static void test_hb_ot_color_get_palette_flags_v1 (void) { - g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v1, 0), ==, HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND); - g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v1, 1), ==, HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND); + g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v1, 0), ==, HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND); + g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v1, 1), ==, HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND); g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 2), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); /* numPalettes=3, so palette #3 is out of bounds */ From 3b3668acc8b16afacb96d8c525eff603ef5f411f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 21 Oct 2018 19:23:11 -0700 Subject: [PATCH 04/36] [color] Rename / reorder a bit Implement has_data() for realz. --- src/hb-ot-color-colr-table.hh | 2 + src/hb-ot-color-cpal-table.hh | 2 + src/hb-ot-color.cc | 80 ++++++++++++++++++++--------------- src/hb-ot-color.h | 33 ++++++++++----- test/api/test-ot-color.c | 28 ++++++------ 5 files changed, 85 insertions(+), 60 deletions(-) diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh index 0e7f6ef23..acad25720 100644 --- a/src/hb-ot-color-colr-table.hh +++ b/src/hb-ot-color-colr-table.hh @@ -96,6 +96,8 @@ struct COLR { static const hb_tag_t tableTag = HB_OT_TAG_COLR; + inline bool has_data (void) const { return numBaseGlyphs; } + inline bool get_base_glyph_record (hb_codepoint_t glyph_id, unsigned int *first_layer /* OUT */, unsigned int *num_layers /* OUT */) const diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index 300f2cb44..94c5a3c37 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -112,6 +112,8 @@ struct CPAL { static const hb_tag_t tableTag = HB_OT_TAG_CPAL; + inline bool has_data (void) const { return numPalettes; } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 7588bef87..724e67261 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -77,8 +77,13 @@ _get_svg (hb_face_t *face) } #endif +/* + * CPAL + */ + + /** - * hb_ot_color_has_cpal_data: + * hb_ot_color_has_palettes: * @face: a font face. * * Returns: whether CPAL table is available. @@ -86,23 +91,9 @@ _get_svg (hb_face_t *face) * Since: REPLACEME */ hb_bool_t -hb_ot_color_has_cpal_data (hb_face_t *face) +hb_ot_color_has_palettes (hb_face_t *face) { - return &_get_cpal (face) != &Null(OT::CPAL); -} - -/** - * hb_ot_color_has_colr_data: - * @face: a font face. - * - * Returns: whether COLR table is available. - * - * Since: REPLACEME - */ -hb_bool_t -hb_ot_color_has_colr_data (hb_face_t *face) -{ - return &_get_colr (face) != &Null(OT::COLR); + return _get_cpal (face).has_data (); } /** @@ -215,6 +206,43 @@ hb_ot_color_get_palette_colors (hb_face_t *face, return cpal.get_palette_entries_count (); } +/** + * hb_ot_color_get_palette_flags: + * @face: a font face + * @palette: the index of the color palette whose flags are being requested + * + * Returns: the flags for the requested color palette. If @face has no colors, + * or if @palette is not between 0 and hb_ot_color_get_palette_count(), + * the result is #HB_OT_COLOR_PALETTE_FLAG_DEFAULT. + * + * Since: REPLACEME + */ +hb_ot_color_palette_flags_t +hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette) +{ + const OT::CPAL& cpal = _get_cpal(face); + return cpal.get_palette_flags (palette); +} + + +/* + * COLR + */ + +/** + * hb_ot_color_has_layers: + * @face: a font face. + * + * Returns: whether COLR table is available. + * + * Since: REPLACEME + */ +hb_bool_t +hb_ot_color_has_layers (hb_face_t *face) +{ + return _get_colr (face).has_data (); +} + /** * hb_ot_color_get_color_layers: * @face: a font face. @@ -256,21 +284,3 @@ hb_ot_color_get_color_layers (hb_face_t *face, if (likely (count)) *count = num_results; return num_layers; } - -/** - * hb_ot_color_get_palette_flags: - * @face: a font face - * @palette: the index of the color palette whose flags are being requested - * - * Returns: the flags for the requested color palette. If @face has no colors, - * or if @palette is not between 0 and hb_ot_color_get_palette_count(), - * the result is #HB_OT_COLOR_PALETTE_FLAG_DEFAULT. - * - * Since: REPLACEME - */ -hb_ot_color_palette_flags_t -hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette) -{ - const OT::CPAL& cpal = _get_cpal(face); - return cpal.get_palette_flags (palette); -} diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index ab2cec981..ce289e5c7 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -38,11 +38,13 @@ HB_BEGIN_DECLS -HB_EXTERN hb_bool_t -hb_ot_color_has_cpal_data (hb_face_t *face); + +/* + * Color palettes. + */ HB_EXTERN hb_bool_t -hb_ot_color_has_colr_data (hb_face_t *face); +hb_ot_color_has_palettes (hb_face_t *face); HB_EXTERN unsigned int hb_ot_color_get_palette_count (hb_face_t *face); @@ -60,14 +62,6 @@ hb_ot_color_get_palette_colors (hb_face_t *face, unsigned int *color_count, /* IN/OUT. May be NULL. */ hb_color_t *colors /* OUT. May be NULL. */); -HB_EXTERN unsigned int -hb_ot_color_get_color_layers (hb_face_t *face, - hb_codepoint_t glyph, - unsigned int start_offset, - unsigned int *count, /* IN/OUT. May be NULL. */ - hb_codepoint_t *glyphs, /* OUT. May be NULL. */ - unsigned int *color_indices /* OUT. May be NULL. */); - /** * hb_ot_color_palette_flags_t: * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special @@ -89,6 +83,23 @@ HB_EXTERN hb_ot_color_palette_flags_t hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette); + +/* + * Color layers. + */ + +HB_EXTERN hb_bool_t +hb_ot_color_has_layers (hb_face_t *face); + +HB_EXTERN unsigned int +hb_ot_color_get_color_layers (hb_face_t *face, + hb_codepoint_t glyph, + unsigned int start_offset, + unsigned int *count, /* IN/OUT. May be NULL. */ + hb_codepoint_t *glyphs, /* OUT. May be NULL. */ + unsigned int *color_indices /* OUT. May be NULL. */); + + HB_END_DECLS #endif /* HB_OT_COLOR_H */ diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c index 018b47d1f..9a2ba4518 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -354,21 +354,21 @@ test_hb_ot_color_has_data (void) { hb_face_t *empty = hb_face_get_empty (); - g_assert (hb_ot_color_has_colr_data (empty) == FALSE); - g_assert (hb_ot_color_has_colr_data (cpal_v0) == TRUE); - g_assert (hb_ot_color_has_colr_data (cpal_v1) == TRUE); - g_assert (hb_ot_color_has_colr_data (cpal) == TRUE); - g_assert (hb_ot_color_has_colr_data (cbdt) == FALSE); - g_assert (hb_ot_color_has_colr_data (sbix) == FALSE); - g_assert (hb_ot_color_has_colr_data (svg) == FALSE); + g_assert (hb_ot_color_has_layers (empty) == FALSE); + g_assert (hb_ot_color_has_layers (cpal_v0) == TRUE); + g_assert (hb_ot_color_has_layers (cpal_v1) == TRUE); + g_assert (hb_ot_color_has_layers (cpal) == TRUE); + g_assert (hb_ot_color_has_layers (cbdt) == FALSE); + g_assert (hb_ot_color_has_layers (sbix) == FALSE); + g_assert (hb_ot_color_has_layers (svg) == FALSE); - g_assert (hb_ot_color_has_cpal_data (empty) == FALSE); - g_assert (hb_ot_color_has_cpal_data (cpal_v0) == TRUE); - g_assert (hb_ot_color_has_cpal_data (cpal_v1) == TRUE); - g_assert (hb_ot_color_has_cpal_data (cpal) == TRUE); - g_assert (hb_ot_color_has_cpal_data (cbdt) == FALSE); - g_assert (hb_ot_color_has_cpal_data (sbix) == FALSE); - g_assert (hb_ot_color_has_cpal_data (svg) == FALSE); + g_assert (hb_ot_color_has_palettes (empty) == FALSE); + g_assert (hb_ot_color_has_palettes (cpal_v0) == TRUE); + g_assert (hb_ot_color_has_palettes (cpal_v1) == TRUE); + g_assert (hb_ot_color_has_palettes (cpal) == TRUE); + g_assert (hb_ot_color_has_palettes (cbdt) == FALSE); + g_assert (hb_ot_color_has_palettes (sbix) == FALSE); + g_assert (hb_ot_color_has_palettes (svg) == FALSE); } int From 1de17bdb80b0668f4d4a4700e3f80c8caee3303d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 10:29:01 -0700 Subject: [PATCH 05/36] [colr] Add hb_ot_color_layer_t We never return parallel arrays from functions. That's inconvenient and hard to bind. --- src/hb-ot-color.cc | 18 ++++++++---------- src/hb-ot-color.h | 22 ++++++++++++++++------ test/api/test-ot-color.c | 33 +++++++++++++++------------------ 3 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 724e67261..2672d0a31 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -244,25 +244,23 @@ hb_ot_color_has_layers (hb_face_t *face) } /** - * hb_ot_color_get_color_layers: + * hb_ot_color_glyph_get_layers: * @face: a font face. * @glyph: * @start_offset: * @count: (inout) (optional): - * @glyphs: (array length=count) (out) (optional): - * @color_indices: (array length=count) (out) (optional): + * @layers: (array length=count) (out) (optional): * * Returns: * * Since: REPLACEME */ unsigned int -hb_ot_color_get_color_layers (hb_face_t *face, - hb_codepoint_t glyph, - unsigned int start_offset, - unsigned int *count /* IN/OUT. May be NULL. */, - hb_codepoint_t *glyphs /* OUT. May be NULL. */, - unsigned int *color_indices /* OUT. May be NULL. */) +hb_ot_color_glyph_get_layers (hb_face_t *face, + hb_codepoint_t glyph, + unsigned int start_offset, + unsigned int *count, /* IN/OUT. May be NULL. */ + hb_ot_color_layer_t *layers /* OUT. May be NULL. */) { const OT::COLR& colr = _get_colr (face); unsigned int num_results = 0; @@ -275,7 +273,7 @@ hb_ot_color_get_color_layers (hb_face_t *face, for (unsigned int i = 0; i < layer_count; i++) { if (colr.get_layer_record (start_layer_index + start_offset + i, - &glyphs[num_results], &color_indices[num_results])) + &layers[num_results].glyph, &layers[num_results].color_index)) ++num_results; } } diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index ce289e5c7..e01fafac4 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -91,13 +91,23 @@ hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette); HB_EXTERN hb_bool_t hb_ot_color_has_layers (hb_face_t *face); +/** + * hb_ot_color_layer_t: + * + * Since: REPLACEME + **/ +typedef struct hb_ot_color_layer_t +{ + hb_codepoint_t glyph; + unsigned int color_index; +} hb_ot_color_layer_t; + HB_EXTERN unsigned int -hb_ot_color_get_color_layers (hb_face_t *face, - hb_codepoint_t glyph, - unsigned int start_offset, - unsigned int *count, /* IN/OUT. May be NULL. */ - hb_codepoint_t *glyphs, /* OUT. May be NULL. */ - unsigned int *color_indices /* OUT. May be NULL. */); +hb_ot_color_glyph_get_layers (hb_face_t *face, + hb_codepoint_t glyph, + unsigned int start_offset, + unsigned int *count, /* IN/OUT. May be NULL. */ + hb_ot_color_layer_t *layers /* OUT. May be NULL. */); HB_END_DECLS diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c index 9a2ba4518..5da026315 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -317,36 +317,33 @@ test_hb_ot_color_get_palette_entry_name_id (void) static void -test_hb_ot_color_get_color_layers (void) +test_hb_ot_color_glyph_get_layers (void) { - hb_codepoint_t layer_gids[1]; - unsigned int color_indices[1]; + hb_ot_color_layer_t layers[1]; unsigned int count = 1; - g_assert_cmpuint (hb_ot_color_get_color_layers (cpal_v1, 0, 0, - NULL, NULL, NULL), ==, 0); - g_assert_cmpuint (hb_ot_color_get_color_layers (cpal_v1, 1, 0, - NULL, NULL, NULL), ==, 0); - g_assert_cmpuint (hb_ot_color_get_color_layers (cpal_v1, 2, 0, - NULL, NULL, NULL), ==, 2); + g_assert_cmpuint (hb_ot_color_glyph_get_layers (cpal_v1, 0, 0, + NULL, NULL), ==, 0); + g_assert_cmpuint (hb_ot_color_glyph_get_layers (cpal_v1, 1, 0, + NULL, NULL), ==, 0); + g_assert_cmpuint (hb_ot_color_glyph_get_layers (cpal_v1, 2, 0, + NULL, NULL), ==, 2); unsigned int num_layers; - num_layers = hb_ot_color_get_color_layers (cpal_v1, 2, 0, &count, layer_gids, - color_indices); + num_layers = hb_ot_color_glyph_get_layers (cpal_v1, 2, 0, &count, layers); g_assert_cmpuint (num_layers, ==, 2); g_assert_cmpuint (count, ==, 1); - g_assert_cmpuint (layer_gids[0], ==, 3); - g_assert_cmpuint (color_indices[0], ==, 1); + g_assert_cmpuint (layers[0].glyph, ==, 3); + g_assert_cmpuint (layers[0].color_index, ==, 1); count = 1; - hb_ot_color_get_color_layers (cpal_v1, 2, 1, &count, layer_gids, - color_indices); + hb_ot_color_glyph_get_layers (cpal_v1, 2, 1, &count, layers); g_assert_cmpuint (num_layers, ==, 2); g_assert_cmpuint (count, ==, 1); - g_assert_cmpuint (layer_gids[0], ==, 4); - g_assert_cmpuint (color_indices[0], ==, 0); + g_assert_cmpuint (layers[0].glyph, ==, 4); + g_assert_cmpuint (layers[0].color_index, ==, 0); } static void @@ -394,7 +391,7 @@ main (int argc, char **argv) hb_test_add (test_hb_ot_color_get_palette_colors_v0); hb_test_add (test_hb_ot_color_get_palette_colors_v1); hb_test_add (test_hb_ot_color_get_palette_entry_name_id); - hb_test_add (test_hb_ot_color_get_color_layers); + hb_test_add (test_hb_ot_color_glyph_get_layers); hb_test_add (test_hb_ot_color_has_data); status = hb_test_run(); hb_face_destroy (cpal_v0); From 3bf91bd2690cda34a7687ed5465dc4bb0672f2b6 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 12:40:38 -0700 Subject: [PATCH 06/36] [color] Rewrite colr access COLR table has one function: return layers for a glyph, and we expose exactly that, so should just wire it through. Also use sub_array() for verifiable safety. Also, BaseGlyphRecord's null object is enough. We don't need to special-case the not-found. --- src/hb-dsalgs.hh | 11 ++++++++ src/hb-open-type.hh | 2 +- src/hb-ot-color-colr-table.hh | 53 ++++++++++++++++++----------------- src/hb-ot-color.cc | 19 +------------ 4 files changed, 41 insertions(+), 44 deletions(-) diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index eb15c089e..7e1b7eb1b 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -521,6 +521,17 @@ struct hb_array_t return arrayZ[i]; } + inline hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const + { + unsigned int count = len; + if (unlikely (start_offset > count)) + count = 0; + else + count -= start_offset; + count = MIN (count, seg_count); + return hb_array_t (arrayZ + start_offset, count); + } + inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; } const T *arrayZ; diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index 08e72064a..be0d8b016 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -417,7 +417,7 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf template struct ArrayOf { - const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const + inline const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const { unsigned int count = len; if (unlikely (start_offset > count)) diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh index acad25720..7c5c35d8c 100644 --- a/src/hb-ot-color-colr-table.hh +++ b/src/hb-ot-color-colr-table.hh @@ -98,35 +98,27 @@ struct COLR inline bool has_data (void) const { return numBaseGlyphs; } - inline bool get_base_glyph_record (hb_codepoint_t glyph_id, - unsigned int *first_layer /* OUT */, - unsigned int *num_layers /* OUT */) const + inline unsigned int get_glyph_layers (hb_codepoint_t glyph, + unsigned int start_offset, + unsigned int *count, /* IN/OUT. May be NULL. */ + hb_ot_color_layer_t *layers /* OUT. May be NULL. */) const { - const BaseGlyphRecord* record; - record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs, - sizeof (BaseGlyphRecord), BaseGlyphRecord::cmp); - if (unlikely (!record)) - return false; + const BaseGlyphRecord &record = get_glyph_record (glyph); - if (first_layer) *first_layer = record->firstLayerIdx; - if (num_layers) *num_layers = record->numLayers; - return true; - } - - inline bool get_layer_record (unsigned int record, - hb_codepoint_t *glyph_id /* OUT */, - unsigned int *color_index /* OUT */) const - { - if (unlikely (record >= numLayers)) + hb_array_t all_layers ((this+layersZ).arrayZ, numLayers); + hb_array_t glyph_layers = all_layers.sub_array (record.firstLayerIdx, + record.numLayers); + if (count) { - *glyph_id = 0; - *color_index = 0xFFFF; - return false; + hb_array_t segment_layers = glyph_layers.sub_array (start_offset, *count); + *count = segment_layers.len; + for (unsigned int i = 0; i < segment_layers.len; i++) + { + layers[i].glyph = segment_layers.arrayZ[i].glyphId; + layers[i].color_index = segment_layers.arrayZ[i].colorIdx; + } } - const LayerRecord &layer = (this+layersZ)[record]; - if (glyph_id) *glyph_id = layer.glyphId; - if (color_index) *color_index = layer.colorIdx; - return true; + return glyph_layers.len; } inline bool sanitize (hb_sanitize_context_t *c) const @@ -137,6 +129,17 @@ struct COLR (this+layersZ).sanitize (c, numLayers))); } + private: + inline const BaseGlyphRecord &get_glyph_record (hb_codepoint_t glyph_id) const + { + const BaseGlyphRecord *rec = (BaseGlyphRecord *) bsearch (&glyph_id, + &(this+baseGlyphsZ), + numBaseGlyphs, + sizeof (BaseGlyphRecord), + BaseGlyphRecord::cmp); + return rec ? *rec : Null(BaseGlyphRecord); + } + protected: HBUINT16 version; /* Table version number (starts at 0). */ HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */ diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 2672d0a31..08d98a924 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -263,22 +263,5 @@ hb_ot_color_glyph_get_layers (hb_face_t *face, hb_ot_color_layer_t *layers /* OUT. May be NULL. */) { const OT::COLR& colr = _get_colr (face); - unsigned int num_results = 0; - unsigned int start_layer_index, num_layers = 0; - if (colr.get_base_glyph_record (glyph, &start_layer_index, &num_layers)) - { - if (count) - { - unsigned int layer_count = MIN(*count, num_layers - start_offset); - for (unsigned int i = 0; i < layer_count; i++) - { - if (colr.get_layer_record (start_layer_index + start_offset + i, - &layers[num_results].glyph, &layers[num_results].color_index)) - ++num_results; - } - } - } - - if (likely (count)) *count = num_results; - return num_layers; + return colr.get_glyph_layers (glyph, start_offset, count, layers); } From 7997144b5f08c81b2cce2c7c2a085fb7eeb506e3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 13:02:04 -0700 Subject: [PATCH 07/36] [color] Revamp palette API --- src/hb-ot-color.cc | 81 ++++++++++++------------ src/hb-ot-color.h | 26 ++++---- test/api/test-ot-color.c | 130 +++++++++++++++++++-------------------- 3 files changed, 117 insertions(+), 120 deletions(-) diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 08d98a924..13094579e 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -22,7 +22,7 @@ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * Google Author(s): Sascha Brawer + * Google Author(s): Sascha Brawer, Behdad Esfahbod */ #include "hb-open-type.hh" @@ -97,7 +97,7 @@ hb_ot_color_has_palettes (hb_face_t *face) } /** - * hb_ot_color_get_palette_count: + * hb_ot_color_palette_get_count: * @face: a font face. * * Returns: the number of color palettes in @face, or zero if @face has @@ -106,13 +106,13 @@ hb_ot_color_has_palettes (hb_face_t *face) * Since: REPLACEME */ unsigned int -hb_ot_color_get_palette_count (hb_face_t *face) +hb_ot_color_palette_get_count (hb_face_t *face) { return _get_cpal (face).get_palette_count (); } /** - * hb_ot_color_get_palette_name_id: + * hb_ot_color_palette_get_name_id: * @face: a font face. * @palette: the index of the color palette whose name is being requested. * @@ -120,38 +120,54 @@ hb_ot_color_get_palette_count (hb_face_t *face) * have themed palettes like "Spring", "Summer", "Fall", and "Winter". * * Returns: an identifier within @face's `name` table. - * If the requested palette has no name, or if @face has no colors, - * or if @palette is not between 0 and hb_ot_color_get_palette_count(), - * the result is 0xFFFF. The implementation does not check whether - * the returned palette name id is actually in @face's `name` table. + * If the requested palette has no name the result is #HB_NAME_ID_INVALID. * * Since: REPLACEME */ hb_name_id_t -hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette) +hb_ot_color_palette_get_name_id (hb_face_t *face, + unsigned int palette_index) { - return _get_cpal (face).get_palette_name_id (palette); + return _get_cpal (face).get_palette_name_id (palette_index); } /** - * hb_ot_color_get_palette_entry_name_id: + * hb_ot_color_palette_color_get_name_id: * @face: a font face. - * @palette_entry: + * @color_index: * * Returns: Name ID associated with a palette entry, e.g. eye color * * Since: REPLACEME */ hb_name_id_t -hb_ot_color_get_palette_entry_name_id (hb_face_t *face, unsigned int palette_entry) +hb_ot_color_palette_color_get_name_id (hb_face_t *face, + unsigned int color_index) { - return _get_cpal (face).get_palette_entry_name_id (palette_entry); + return _get_cpal (face).get_palette_entry_name_id (color_index); } /** - * hb_ot_color_get_palette_colors: + * hb_ot_color_palette_get_flags: + * @face: a font face + * @palette_index: the index of the color palette whose flags are being requested + * + * Returns: the flags for the requested color palette. + * + * Since: REPLACEME + */ +hb_ot_color_palette_flags_t +hb_ot_color_palette_get_flags (hb_face_t *face, + unsigned int palette_index) +{ + const OT::CPAL& cpal = _get_cpal(face); + return cpal.get_palette_flags (palette_index); +} + +/** + * hb_ot_color_palette_get_colors: * @face: a font face. - * @palette: the index of the color palette whose colors + * @palette_index:the index of the color palette whose colors * are being requested. * @start_offset: the index of the first color being requested. * @color_count: (inout) (optional): on input, how many colors @@ -164,26 +180,23 @@ hb_ot_color_get_palette_entry_name_id (hb_face_t *face, unsigned int palette_ent * will just return the number of total colors * without storing any actual colors; this can be used * for allocating a buffer of suitable size before calling - * hb_ot_color_get_palette_colors() a second time. + * hb_ot_color_palette_get_colors() a second time. * * Retrieves the colors in a color palette. * - * Returns: the total number of colors in the palette. All palettes in - * a font have the same number of colors. If @face has no colors, or if - * @palette is not between 0 and hb_ot_color_get_palette_count(), - * the result is zero. + * Returns: the total number of colors in the palette. * * Since: REPLACEME */ unsigned int -hb_ot_color_get_palette_colors (hb_face_t *face, - unsigned int palette, /* default=0 */ +hb_ot_color_palette_get_colors (hb_face_t *face, + unsigned int palette_index, /* default=0 */ unsigned int start_offset, unsigned int *colors_count /* IN/OUT. May be NULL. */, hb_color_t *colors /* OUT. May be NULL. */) { const OT::CPAL& cpal = _get_cpal(face); - if (unlikely (palette >= cpal.get_palette_count ())) + if (unlikely (palette_index >= cpal.get_palette_count ())) { if (colors_count) *colors_count = 0; return 0; @@ -197,7 +210,7 @@ hb_ot_color_get_palette_colors (hb_face_t *face, cpal.get_palette_entries_count () - start_offset); for (unsigned int i = 0; i < platte_count; i++) { - if (cpal.get_color_record_argb(start_offset + i, palette, &colors[num_results])) + if (cpal.get_color_record_argb(start_offset + i, palette_index, &colors[num_results])) ++num_results; } } @@ -206,24 +219,6 @@ hb_ot_color_get_palette_colors (hb_face_t *face, return cpal.get_palette_entries_count (); } -/** - * hb_ot_color_get_palette_flags: - * @face: a font face - * @palette: the index of the color palette whose flags are being requested - * - * Returns: the flags for the requested color palette. If @face has no colors, - * or if @palette is not between 0 and hb_ot_color_get_palette_count(), - * the result is #HB_OT_COLOR_PALETTE_FLAG_DEFAULT. - * - * Since: REPLACEME - */ -hb_ot_color_palette_flags_t -hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette) -{ - const OT::CPAL& cpal = _get_cpal(face); - return cpal.get_palette_flags (palette); -} - /* * COLR diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index e01fafac4..4d08eb065 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -23,7 +23,7 @@ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * Google Author(s): Sascha Brawer + * Google Author(s): Sascha Brawer, Behdad Esfahbod */ #ifndef HB_OT_H_IN @@ -47,20 +47,15 @@ HB_EXTERN hb_bool_t hb_ot_color_has_palettes (hb_face_t *face); HB_EXTERN unsigned int -hb_ot_color_get_palette_count (hb_face_t *face); +hb_ot_color_palette_get_count (hb_face_t *face); HB_EXTERN hb_name_id_t -hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette); +hb_ot_color_palette_get_name_id (hb_face_t *face, + unsigned int palette_index); HB_EXTERN hb_name_id_t -hb_ot_color_get_palette_entry_name_id (hb_face_t *face, unsigned int palette_entry); - -HB_EXTERN unsigned int -hb_ot_color_get_palette_colors (hb_face_t *face, - unsigned int palette, /* default=0 */ - unsigned int start_offset, - unsigned int *color_count, /* IN/OUT. May be NULL. */ - hb_color_t *colors /* OUT. May be NULL. */); +hb_ot_color_palette_color_get_name_id (hb_face_t *face, + unsigned int color_index); /** * hb_ot_color_palette_flags_t: @@ -80,8 +75,15 @@ typedef enum { /*< flags >*/ } hb_ot_color_palette_flags_t; HB_EXTERN hb_ot_color_palette_flags_t -hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette); +hb_ot_color_palette_get_flags (hb_face_t *face, + unsigned int palette_index); +HB_EXTERN unsigned int +hb_ot_color_palette_get_colors (hb_face_t *face, + unsigned int palette_index, + unsigned int start_offset, + unsigned int *color_count, /* IN/OUT. May be NULL. */ + hb_color_t *colors /* OUT. May be NULL. */); /* diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c index 5da026315..a514c6aa9 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -128,113 +128,113 @@ static hb_face_t *svg = NULL; static void -test_hb_ot_color_get_palette_count (void) +test_hb_ot_color_palette_get_count (void) { - g_assert_cmpint (hb_ot_color_get_palette_count (hb_face_get_empty()), ==, 0); - g_assert_cmpint (hb_ot_color_get_palette_count (cpal_v0), ==, 2); - g_assert_cmpint (hb_ot_color_get_palette_count (cpal_v1), ==, 3); + g_assert_cmpint (hb_ot_color_palette_get_count (hb_face_get_empty()), ==, 0); + g_assert_cmpint (hb_ot_color_palette_get_count (cpal_v0), ==, 2); + g_assert_cmpint (hb_ot_color_palette_get_count (cpal_v1), ==, 3); } static void -test_hb_ot_color_get_palette_name_id_empty (void) +test_hb_ot_color_palette_get_name_id_empty (void) { /* numPalettes=0, so all calls are for out-of-bounds palette indices */ - g_assert_cmpint (hb_ot_color_get_palette_name_id (hb_face_get_empty(), 0), ==, HB_NAME_ID_INVALID); - g_assert_cmpint (hb_ot_color_get_palette_name_id (hb_face_get_empty(), 1), ==, HB_NAME_ID_INVALID); + g_assert_cmpint (hb_ot_color_palette_get_name_id (hb_face_get_empty(), 0), ==, HB_NAME_ID_INVALID); + g_assert_cmpint (hb_ot_color_palette_get_name_id (hb_face_get_empty(), 1), ==, HB_NAME_ID_INVALID); } static void -test_hb_ot_color_get_palette_name_id_v0 (void) +test_hb_ot_color_palette_get_name_id_v0 (void) { - g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 0), ==, HB_NAME_ID_INVALID); - g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 1), ==, HB_NAME_ID_INVALID); + g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v0, 0), ==, HB_NAME_ID_INVALID); + g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v0, 1), ==, HB_NAME_ID_INVALID); /* numPalettes=2, so palette #2 is out of bounds */ - g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v0, 2), ==, HB_NAME_ID_INVALID); + g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v0, 2), ==, HB_NAME_ID_INVALID); } static void -test_hb_ot_color_get_palette_name_id_v1 (void) +test_hb_ot_color_palette_get_name_id_v1 (void) { - g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 0), ==, 257); - g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 1), ==, HB_NAME_ID_INVALID); - g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 2), ==, 258); + g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v1, 0), ==, 257); + g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v1, 1), ==, HB_NAME_ID_INVALID); + g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v1, 2), ==, 258); /* numPalettes=3, so palette #3 is out of bounds */ - g_assert_cmpint (hb_ot_color_get_palette_name_id (cpal_v1, 3), ==, HB_NAME_ID_INVALID); + g_assert_cmpint (hb_ot_color_palette_get_name_id (cpal_v1, 3), ==, HB_NAME_ID_INVALID); } static void -test_hb_ot_color_get_palette_flags_empty (void) +test_hb_ot_color_palette_get_flags_empty (void) { /* numPalettes=0, so all calls are for out-of-bounds palette indices */ - g_assert_cmpint (hb_ot_color_get_palette_flags (hb_face_get_empty(), 0), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); - g_assert_cmpint (hb_ot_color_get_palette_flags (hb_face_get_empty(), 1), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); + g_assert_cmpint (hb_ot_color_palette_get_flags (hb_face_get_empty(), 0), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); + g_assert_cmpint (hb_ot_color_palette_get_flags (hb_face_get_empty(), 1), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); } static void -test_hb_ot_color_get_palette_flags_v0 (void) +test_hb_ot_color_palette_get_flags_v0 (void) { - g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 0), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); - g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 1), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); + g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v0, 0), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); + g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v0, 1), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); /* numPalettes=2, so palette #2 is out of bounds */ - g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 2), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); + g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v0, 2), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); } static void -test_hb_ot_color_get_palette_flags_v1 (void) +test_hb_ot_color_palette_get_flags_v1 (void) { - g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v1, 0), ==, HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND); - g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v1, 1), ==, HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND); - g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 2), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); + g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v1, 0), ==, HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND); + g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v1, 1), ==, HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND); + g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v0, 2), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); /* numPalettes=3, so palette #3 is out of bounds */ - g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 3), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); + g_assert_cmpint (hb_ot_color_palette_get_flags (cpal_v0, 3), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT); } static void -test_hb_ot_color_get_palette_colors_empty (void) +test_hb_ot_color_palette_get_colors_empty (void) { hb_face_t *empty = hb_face_get_empty (); - g_assert_cmpint (hb_ot_color_get_palette_colors (empty, 0, 0, NULL, NULL), ==, 0); + g_assert_cmpint (hb_ot_color_palette_get_colors (empty, 0, 0, NULL, NULL), ==, 0); } static void -test_hb_ot_color_get_palette_colors_v0 (void) +test_hb_ot_color_palette_get_colors_v0 (void) { - unsigned int num_colors = hb_ot_color_get_palette_colors (cpal_v0, 0, 0, NULL, NULL); + unsigned int num_colors = hb_ot_color_palette_get_colors (cpal_v0, 0, 0, NULL, NULL); hb_color_t *colors = (hb_color_t*) alloca (num_colors * sizeof (hb_color_t)); size_t colors_size = num_colors * sizeof(*colors); g_assert_cmpint (num_colors, ==, 2); /* Palette #0, start_index=0 */ - g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 0, 0, &num_colors, colors), ==, 2); + g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 0, 0, &num_colors, colors), ==, 2); g_assert_cmpint (num_colors, ==, 2); assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff); assert_color_rgba (colors, 1, 0x66, 0xcc, 0xff, 0xff); /* Palette #1, start_index=0 */ - g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 1, 0, &num_colors, colors), ==, 2); + g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 1, 0, &num_colors, colors), ==, 2); g_assert_cmpint (num_colors, ==, 2); assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff); assert_color_rgba (colors, 1, 0x80, 0x00, 0x00, 0xff); /* Palette #2 (there are only #0 and #1 in the font, so this is out of bounds) */ - g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 2, 0, &num_colors, colors), ==, 0); + g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 2, 0, &num_colors, colors), ==, 0); /* Palette #0, start_index=1 */ memset(colors, 0x33, colors_size); num_colors = 2; - g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 0, 1, &num_colors, colors), ==, 2); + g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 0, 1, &num_colors, colors), ==, 2); g_assert_cmpint (num_colors, ==, 1); assert_color_rgba (colors, 0, 0x66, 0xcc, 0xff, 0xff); assert_color_rgba (colors, 1, 0x33, 0x33, 0x33, 0x33); /* untouched */ @@ -242,7 +242,7 @@ test_hb_ot_color_get_palette_colors_v0 (void) /* Palette #0, start_index=0, pretend that we have only allocated space for 1 color */ memset(colors, 0x44, colors_size); num_colors = 1; - g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 0, 0, &num_colors, colors), ==, 2); + g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 0, 0, &num_colors, colors), ==, 2); g_assert_cmpint (num_colors, ==, 1); assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff); assert_color_rgba (colors, 1, 0x44, 0x44, 0x44, 0x44); /* untouched */ @@ -250,7 +250,7 @@ test_hb_ot_color_get_palette_colors_v0 (void) /* start_index > numPaletteEntries */ memset (colors, 0x44, colors_size); num_colors = 2; - g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v0, 0, 9876, &num_colors, colors), ==, 2); + g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v0, 0, 9876, &num_colors, colors), ==, 2); g_assert_cmpint (num_colors, ==, 0); assert_color_rgba (colors, 0, 0x44, 0x44, 0x44, 0x44); /* untouched */ assert_color_rgba (colors, 1, 0x44, 0x44, 0x44, 0x44); /* untouched */ @@ -258,16 +258,16 @@ test_hb_ot_color_get_palette_colors_v0 (void) static void -test_hb_ot_color_get_palette_colors_v1 (void) +test_hb_ot_color_palette_get_colors_v1 (void) { hb_color_t colors[3]; - unsigned int num_colors = hb_ot_color_get_palette_colors (cpal_v1, 0, 0, NULL, NULL); + unsigned int num_colors = hb_ot_color_palette_get_colors (cpal_v1, 0, 0, NULL, NULL); size_t colors_size = 3 * sizeof (hb_color_t); g_assert_cmpint (num_colors, ==, 2); /* Palette #0, start_index=0 */ memset (colors, 0x77, colors_size); - g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 0, 0, &num_colors, colors), ==, 2); + g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v1, 0, 0, &num_colors, colors), ==, 2); g_assert_cmpint (num_colors, ==, 2); assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff); assert_color_rgba (colors, 1, 0x66, 0xcc, 0xff, 0xff); @@ -275,7 +275,7 @@ test_hb_ot_color_get_palette_colors_v1 (void) /* Palette #1, start_index=0 */ memset (colors, 0x77, colors_size); - g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 1, 0, &num_colors, colors), ==, 2); + g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v1, 1, 0, &num_colors, colors), ==, 2); g_assert_cmpint (num_colors, ==, 2); assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff); assert_color_rgba (colors, 1, 0xff, 0xcc, 0x66, 0xff); @@ -283,7 +283,7 @@ test_hb_ot_color_get_palette_colors_v1 (void) /* Palette #2, start_index=0 */ memset (colors, 0x77, colors_size); - g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 2, 0, &num_colors, colors), ==, 2); + g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v1, 2, 0, &num_colors, colors), ==, 2); g_assert_cmpint (num_colors, ==, 2); assert_color_rgba (colors, 0, 0x00, 0x00, 0x00, 0xff); assert_color_rgba (colors, 1, 0x80, 0x00, 0x00, 0xff); @@ -291,7 +291,7 @@ test_hb_ot_color_get_palette_colors_v1 (void) /* Palette #3 (out of bounds), start_index=0 */ memset (colors, 0x77, colors_size); - g_assert_cmpint (hb_ot_color_get_palette_colors (cpal_v1, 3, 0, &num_colors, colors), ==, 0); + g_assert_cmpint (hb_ot_color_palette_get_colors (cpal_v1, 3, 0, &num_colors, colors), ==, 0); g_assert_cmpint (num_colors, ==, 0); assert_color_rgba (colors, 0, 0x77, 0x77, 0x77, 0x77); /* untouched */ assert_color_rgba (colors, 1, 0x77, 0x77, 0x77, 0x77); /* untouched */ @@ -300,19 +300,19 @@ test_hb_ot_color_get_palette_colors_v1 (void) static void -test_hb_ot_color_get_palette_entry_name_id (void) +test_hb_ot_color_palette_color_get_name_id (void) { hb_face_t *empty = hb_face_get_empty (); - g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (empty, 0), ==, HB_NAME_ID_INVALID); - g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (empty, 1), ==, HB_NAME_ID_INVALID); - g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (empty, 2), ==, HB_NAME_ID_INVALID); - g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v0, 0), ==, HB_NAME_ID_INVALID); - g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v0, 1), ==, HB_NAME_ID_INVALID); - g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v0, 2), ==, HB_NAME_ID_INVALID); - g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v1, 0), ==, HB_NAME_ID_INVALID); - g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v1, 1), ==, 256); - g_assert_cmpuint (hb_ot_color_get_palette_entry_name_id (cpal_v1, 2), ==, HB_NAME_ID_INVALID); + g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (empty, 0), ==, HB_NAME_ID_INVALID); + g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (empty, 1), ==, HB_NAME_ID_INVALID); + g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (empty, 2), ==, HB_NAME_ID_INVALID); + g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v0, 0), ==, HB_NAME_ID_INVALID); + g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v0, 1), ==, HB_NAME_ID_INVALID); + g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v0, 2), ==, HB_NAME_ID_INVALID); + g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v1, 0), ==, HB_NAME_ID_INVALID); + g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v1, 1), ==, 256); + g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (cpal_v1, 2), ==, HB_NAME_ID_INVALID); } @@ -380,17 +380,17 @@ main (int argc, char **argv) cbdt = hb_test_open_font_file ("fonts/chromacheck-cbdt.ttf"); sbix = hb_test_open_font_file ("fonts/chromacheck-sbix.ttf"); svg = hb_test_open_font_file ("fonts/chromacheck-svg.ttf"); - hb_test_add (test_hb_ot_color_get_palette_count); - hb_test_add (test_hb_ot_color_get_palette_name_id_empty); - hb_test_add (test_hb_ot_color_get_palette_name_id_v0); - hb_test_add (test_hb_ot_color_get_palette_name_id_v1); - hb_test_add (test_hb_ot_color_get_palette_flags_empty); - hb_test_add (test_hb_ot_color_get_palette_flags_v0); - hb_test_add (test_hb_ot_color_get_palette_flags_v1); - hb_test_add (test_hb_ot_color_get_palette_colors_empty); - hb_test_add (test_hb_ot_color_get_palette_colors_v0); - hb_test_add (test_hb_ot_color_get_palette_colors_v1); - hb_test_add (test_hb_ot_color_get_palette_entry_name_id); + hb_test_add (test_hb_ot_color_palette_get_count); + hb_test_add (test_hb_ot_color_palette_get_name_id_empty); + hb_test_add (test_hb_ot_color_palette_get_name_id_v0); + hb_test_add (test_hb_ot_color_palette_get_name_id_v1); + hb_test_add (test_hb_ot_color_palette_get_flags_empty); + hb_test_add (test_hb_ot_color_palette_get_flags_v0); + hb_test_add (test_hb_ot_color_palette_get_flags_v1); + hb_test_add (test_hb_ot_color_palette_get_colors_empty); + hb_test_add (test_hb_ot_color_palette_get_colors_v0); + hb_test_add (test_hb_ot_color_palette_get_colors_v1); + hb_test_add (test_hb_ot_color_palette_color_get_name_id); hb_test_add (test_hb_ot_color_glyph_get_layers); hb_test_add (test_hb_ot_color_has_data); status = hb_test_run(); From 0babf761c986855f9cdd1a2679380ee6a02390c8 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Tue, 23 Oct 2018 01:33:45 +0330 Subject: [PATCH 08/36] Adopt dump-emoji with latest unreleased APIs changes (#1297) --- src/dump-emoji.cc | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc index fdd0b097f..2f79fc69d 100644 --- a/src/dump-emoji.cc +++ b/src/dump-emoji.cc @@ -95,14 +95,13 @@ colr_cpal_rendering (hb_face_t *face, cairo_font_face_t *cairo_face) unsigned glyph_count = hb_face_get_glyph_count (face); for (hb_codepoint_t gid = 0; gid < glyph_count; ++gid) { - unsigned int num_layers = hb_ot_color_get_color_layers (face, gid, 0, nullptr, nullptr, nullptr); + unsigned int num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, nullptr, nullptr); if (!num_layers) continue; - hb_codepoint_t *layer_gids = (hb_codepoint_t*) calloc (num_layers, sizeof (hb_codepoint_t)); - unsigned int *color_indices = (unsigned int*) calloc (num_layers, sizeof (unsigned int)); + hb_ot_color_layer_t *layers = (hb_ot_color_layer_t*) malloc (num_layers * sizeof (hb_ot_color_layer_t)); - hb_ot_color_get_color_layers (face, gid, 0, &num_layers, layer_gids, color_indices); + hb_ot_color_glyph_get_layers (face, gid, 0, &num_layers, layers); if (num_layers) { // Measure @@ -115,7 +114,7 @@ colr_cpal_rendering (hb_face_t *face, cairo_font_face_t *cairo_face) cairo_glyph_t *glyphs = (cairo_glyph_t *) calloc (num_layers, sizeof (cairo_glyph_t)); for (unsigned int j = 0; j < num_layers; ++j) - glyphs[j].index = layer_gids[j]; + glyphs[j].index = layers[j].glyph; cairo_glyph_extents (cr, glyphs, num_layers, &extents); free (glyphs); cairo_surface_destroy (surface); @@ -129,16 +128,16 @@ colr_cpal_rendering (hb_face_t *face, cairo_font_face_t *cairo_face) extents.y_bearing -= extents.height / 20; // Render - unsigned int palette_count = hb_ot_color_get_palette_count (face); + unsigned int palette_count = hb_ot_color_palette_get_count (face); for (unsigned int palette = 0; palette < palette_count; palette++) { char output_path[255]; - unsigned int num_colors = hb_ot_color_get_palette_colors (face, palette, 0, nullptr, nullptr); + unsigned int num_colors = hb_ot_color_palette_get_colors (face, palette, 0, nullptr, nullptr); if (!num_colors) continue; hb_color_t *colors = (hb_color_t*) calloc (num_colors, sizeof (hb_color_t)); - hb_ot_color_get_palette_colors (face, palette, 0, &num_colors, colors); + hb_ot_color_palette_get_colors (face, palette, 0, &num_colors, colors); if (num_colors) { // If we have more than one palette, use a simpler naming @@ -155,8 +154,8 @@ colr_cpal_rendering (hb_face_t *face, cairo_font_face_t *cairo_face) for (unsigned int layer = 0; layer < num_layers; ++layer) { hb_color_t color = 0x000000FF; - if (color_indices[layer] != 0xFFFF) - color = colors[color_indices[layer]]; + if (layers[layer].color_index != 0xFFFF) + color = colors[layers[layer].color_index]; cairo_set_source_rgba (cr, hb_color_get_red (color) / 255., hb_color_get_green (color) / 255., @@ -164,7 +163,7 @@ colr_cpal_rendering (hb_face_t *face, cairo_font_face_t *cairo_face) hb_color_get_alpha (color) / 255.); cairo_glyph_t glyph; - glyph.index = layer_gids[layer]; + glyph.index = layers[layer].glyph; glyph.x = -extents.x_bearing; glyph.y = -extents.y_bearing; cairo_show_glyphs (cr, &glyph, 1); @@ -177,8 +176,7 @@ colr_cpal_rendering (hb_face_t *face, cairo_font_face_t *cairo_face) } } - free (layer_gids); - free (color_indices); + free (layers); } } From 3600d206037ef23d6448c79a3f010c4f903a971c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 14:43:12 -0700 Subject: [PATCH 09/36] [color] Rename vars in CPAL --- src/hb-ot-color-cpal-table.hh | 32 ++++++++++++++++---------------- src/hb-ot-color.cc | 1 + 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index 94c5a3c37..6035650f7 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -49,34 +49,34 @@ struct CPALV1Tail inline bool sanitize (hb_sanitize_context_t *c, const void *base, - unsigned int palettes, unsigned int paletteEntries) const + unsigned int palette_count, unsigned int paletteEntries) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - (base+paletteFlagsZ).sanitize (c, palettes) && - (base+paletteLabelZ).sanitize (c, palettes) && + (base+paletteFlagsZ).sanitize (c, palette_count) && + (base+paletteLabelZ).sanitize (c, palette_count) && (base+paletteEntryLabelZ).sanitize (c, paletteEntries)); } private: inline hb_ot_color_palette_flags_t - get_palette_flags (const void *base, unsigned int palette, + get_palette_flags (const void *base, unsigned int palette_index, unsigned int palettes_count) const { - if (unlikely (palette >= palettes_count)) + if (unlikely (palette_index >= palettes_count)) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; - return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette]; + return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette_index]; } inline unsigned int - get_palette_name_id (const void *base, unsigned int palette, + get_palette_name_id (const void *base, unsigned int palette_index, unsigned int palettes_count) const { - if (unlikely (palette >= palettes_count)) + if (unlikely (palette_index >= palettes_count)) return HB_NAME_ID_INVALID; - return (base+paletteLabelZ)[palette]; + return (base+paletteLabelZ)[palette_index]; } inline unsigned int @@ -140,22 +140,22 @@ struct CPAL return min_size + numPalettes * sizeof (HBUINT16); } - inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const + inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const { if (unlikely (version == 0)) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; const CPALV1Tail& cpal1 = StructAfter (*this); - return cpal1.get_palette_flags (this, palette, numPalettes); + return cpal1.get_palette_flags (this, palette_index, numPalettes); } - inline unsigned int get_palette_name_id (unsigned int palette) const + inline unsigned int get_palette_name_id (unsigned int palette_index) const { if (unlikely (version == 0)) return HB_NAME_ID_INVALID; const CPALV1Tail& cpal1 = StructAfter (*this); - return cpal1.get_palette_name_id (this, palette, numPalettes); + return cpal1.get_palette_name_id (this, palette_index, numPalettes); } inline unsigned int get_palette_entry_name_id (unsigned int palette_entry) const @@ -174,15 +174,15 @@ struct CPAL { return numPaletteEntries; } bool - get_color_record_argb (unsigned int color_index, unsigned int palette, hb_color_t* color) const + get_color_record_argb (unsigned int color_index, unsigned int palette_index, hb_color_t* color) const { - if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes)) + if (unlikely (color_index >= numPaletteEntries || palette_index >= numPalettes)) return false; /* No need for more range check as it is already done on #sanitize */ const UnsizedArrayOf& color_records = this+colorRecordsZ; if (color) - *color = color_records[colorRecordIndicesZ[palette] + color_index]; + *color = color_records[colorRecordIndicesZ[palette_index] + color_index]; return true; } diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 13094579e..e4052392b 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -77,6 +77,7 @@ _get_svg (hb_face_t *face) } #endif + /* * CPAL */ From 0befb06c468aa36f3337b5ef2235f6d69dda8397 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 14:46:21 -0700 Subject: [PATCH 10/36] [color] More CPAL rename --- src/hb-ot-color-cpal-table.hh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index 6035650f7..5d23ee8d0 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -49,13 +49,13 @@ struct CPALV1Tail inline bool sanitize (hb_sanitize_context_t *c, const void *base, - unsigned int palette_count, unsigned int paletteEntries) const + unsigned int palette_count, unsigned int color_count) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && (base+paletteFlagsZ).sanitize (c, palette_count) && (base+paletteLabelZ).sanitize (c, palette_count) && - (base+paletteEntryLabelZ).sanitize (c, paletteEntries)); + (base+paletteEntryLabelZ).sanitize (c, color_count)); } private: @@ -124,7 +124,7 @@ struct CPAL /* Check for indices sanity so no need for doing it runtime */ for (unsigned int i = 0; i < numPalettes; ++i) - if (unlikely (colorRecordIndicesZ[i] + numPaletteEntries > numColorRecords)) + if (unlikely (colorRecordIndicesZ[i] + numColors > numColorRecords)) return_trace (false); /* If version is zero, we are done here; otherwise we need to check tail also */ @@ -132,7 +132,7 @@ struct CPAL return_trace (true); const CPALV1Tail &v1 = StructAfter (*this); - return_trace (likely (v1.sanitize (c, this, numPalettes, numPaletteEntries))); + return_trace (likely (v1.sanitize (c, this, numPalettes, numColors))); } inline unsigned int get_size (void) const @@ -164,19 +164,19 @@ struct CPAL return HB_NAME_ID_INVALID; const CPALV1Tail& cpal1 = StructAfter (*this); - return cpal1.get_palette_entry_name_id (this, palette_entry, numPaletteEntries); + return cpal1.get_palette_entry_name_id (this, palette_entry, numColors); } inline unsigned int get_palette_count () const { return numPalettes; } inline unsigned int get_palette_entries_count () const - { return numPaletteEntries; } + { return numColors; } bool get_color_record_argb (unsigned int color_index, unsigned int palette_index, hb_color_t* color) const { - if (unlikely (color_index >= numPaletteEntries || palette_index >= numPalettes)) + if (unlikely (color_index >= numColors || palette_index >= numPalettes)) return false; /* No need for more range check as it is already done on #sanitize */ @@ -189,7 +189,7 @@ struct CPAL protected: HBUINT16 version; /* Table version number */ /* Version 0 */ - HBUINT16 numPaletteEntries; /* Number of palette entries in each palette. */ + HBUINT16 numColors; /* Number of colors in each palette. */ HBUINT16 numPalettes; /* Number of palettes in the table. */ HBUINT16 numColorRecords; /* Total number of color records, combined for * all palettes. */ From 69ab72e4aa7cbf197873d38f7e623866b4e40502 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 14:51:40 -0700 Subject: [PATCH 11/36] [color] More CPAL rename --- src/hb-ot-color-cpal-table.hh | 104 +++++++++++++++++----------------- src/hb-ot-color.cc | 6 +- 2 files changed, 54 insertions(+), 56 deletions(-) diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index 5d23ee8d0..abb79ce99 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -47,46 +47,49 @@ struct CPALV1Tail { friend struct CPAL; - inline bool - sanitize (hb_sanitize_context_t *c, const void *base, - unsigned int palette_count, unsigned int color_count) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - (base+paletteFlagsZ).sanitize (c, palette_count) && - (base+paletteLabelZ).sanitize (c, palette_count) && - (base+paletteEntryLabelZ).sanitize (c, color_count)); - } - private: inline hb_ot_color_palette_flags_t - get_palette_flags (const void *base, unsigned int palette_index, - unsigned int palettes_count) const + get_palette_flags (const void *base, + unsigned int palette_index, + unsigned int palette_count) const { - if (unlikely (palette_index >= palettes_count)) + if (unlikely (palette_index >= palette_count)) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette_index]; } inline unsigned int - get_palette_name_id (const void *base, unsigned int palette_index, - unsigned int palettes_count) const + get_palette_name_id (const void *base, + unsigned int palette_index, + unsigned int palette_count) const { - if (unlikely (palette_index >= palettes_count)) + if (unlikely (palette_index >= palette_count)) return HB_NAME_ID_INVALID; return (base+paletteLabelZ)[palette_index]; } inline unsigned int - get_palette_entry_name_id (const void *base, unsigned int palette_entry, - unsigned int palettes_entries_count) const + get_color_name_id (const void *base, + unsigned int color_index, + unsigned int color_count) const { - if (unlikely (palette_entry >= palettes_entries_count)) + if (unlikely (color_index >= color_count)) return HB_NAME_ID_INVALID; - return (base+paletteEntryLabelZ)[palette_entry]; + return (base+paletteEntryLabelZ)[color_index]; + } + + public: + inline bool sanitize (hb_sanitize_context_t *c, const void *base, + unsigned int palette_count, unsigned int color_count) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + (base+paletteFlagsZ).sanitize (c, palette_count) && + (base+paletteLabelZ).sanitize (c, palette_count) && + (base+paletteEntryLabelZ).sanitize (c, color_count)); } protected: @@ -114,31 +117,11 @@ struct CPAL inline bool has_data (void) const { return numPalettes; } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!(c->check_struct (this) && /* it checks colorRecordIndices also - * See #get_size */ - (this+colorRecordsZ).sanitize (c, numColorRecords)))) - return_trace (false); - - /* Check for indices sanity so no need for doing it runtime */ - for (unsigned int i = 0; i < numPalettes; ++i) - if (unlikely (colorRecordIndicesZ[i] + numColors > numColorRecords)) - return_trace (false); - - /* If version is zero, we are done here; otherwise we need to check tail also */ - if (version == 0) - return_trace (true); - - const CPALV1Tail &v1 = StructAfter (*this); - return_trace (likely (v1.sanitize (c, this, numPalettes, numColors))); - } - inline unsigned int get_size (void) const - { - return min_size + numPalettes * sizeof (HBUINT16); - } + { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); } + + inline unsigned int get_palette_count () const { return numPalettes; } + inline unsigned int get_color_count () const { return numColors; } inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const { @@ -158,21 +141,15 @@ struct CPAL return cpal1.get_palette_name_id (this, palette_index, numPalettes); } - inline unsigned int get_palette_entry_name_id (unsigned int palette_entry) const + inline unsigned int get_color_name_id (unsigned int color_index) const { if (unlikely (version == 0)) return HB_NAME_ID_INVALID; const CPALV1Tail& cpal1 = StructAfter (*this); - return cpal1.get_palette_entry_name_id (this, palette_entry, numColors); + return cpal1.get_color_name_id (this, color_index, numColors); } - inline unsigned int get_palette_count () const - { return numPalettes; } - - inline unsigned int get_palette_entries_count () const - { return numColors; } - bool get_color_record_argb (unsigned int color_index, unsigned int palette_index, hb_color_t* color) const { @@ -186,6 +163,27 @@ struct CPAL return true; } + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!(c->check_struct (this) && /* it checks colorRecordIndices also + * See #get_size */ + (this+colorRecordsZ).sanitize (c, numColorRecords)))) + return_trace (false); + + /* Check for indices sanity so no need for doing it runtime */ + for (unsigned int i = 0; i < numPalettes; ++i) + if (unlikely (colorRecordIndicesZ[i] + numColors > numColorRecords)) + return_trace (false); + + /* If version is zero, we are done here; otherwise we need to check tail also */ + if (version == 0) + return_trace (true); + + const CPALV1Tail &v1 = StructAfter (*this); + return_trace (likely (v1.sanitize (c, this, numPalettes, numColors))); + } + protected: HBUINT16 version; /* Table version number */ /* Version 0 */ diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index e4052392b..3ca8751a2 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -145,7 +145,7 @@ hb_name_id_t hb_ot_color_palette_color_get_name_id (hb_face_t *face, unsigned int color_index) { - return _get_cpal (face).get_palette_entry_name_id (color_index); + return _get_cpal (face).get_color_name_id (color_index); } /** @@ -208,7 +208,7 @@ hb_ot_color_palette_get_colors (hb_face_t *face, { unsigned int platte_count; platte_count = MIN(*colors_count, - cpal.get_palette_entries_count () - start_offset); + cpal.get_color_count () - start_offset); for (unsigned int i = 0; i < platte_count; i++) { if (cpal.get_color_record_argb(start_offset + i, palette_index, &colors[num_results])) @@ -217,7 +217,7 @@ hb_ot_color_palette_get_colors (hb_face_t *face, } if (likely (colors_count)) *colors_count = num_results; - return cpal.get_palette_entries_count (); + return cpal.get_color_count (); } From 5ae18855d115577ff796158d483db7b890d9956f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 14:54:55 -0700 Subject: [PATCH 12/36] [color] Check for null CPAL arrays We cannot use a nullable offset here though. --- src/hb-ot-color-cpal-table.hh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index abb79ce99..beef2fce9 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -53,7 +53,7 @@ struct CPALV1Tail unsigned int palette_index, unsigned int palette_count) const { - if (unlikely (palette_index >= palette_count)) + if (unlikely (palette_index >= palette_count || !paletteFlagsZ)) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette_index]; @@ -64,7 +64,7 @@ struct CPALV1Tail unsigned int palette_index, unsigned int palette_count) const { - if (unlikely (palette_index >= palette_count)) + if (unlikely (palette_index >= palette_count || !paletteLabelZ)) return HB_NAME_ID_INVALID; return (base+paletteLabelZ)[palette_index]; @@ -75,7 +75,7 @@ struct CPALV1Tail unsigned int color_index, unsigned int color_count) const { - if (unlikely (color_index >= color_count)) + if (unlikely (color_index >= color_count || !paletteEntryLabelZ)) return HB_NAME_ID_INVALID; return (base+paletteEntryLabelZ)[color_index]; @@ -87,9 +87,9 @@ struct CPALV1Tail { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - (base+paletteFlagsZ).sanitize (c, palette_count) && - (base+paletteLabelZ).sanitize (c, palette_count) && - (base+paletteEntryLabelZ).sanitize (c, color_count)); + (!paletteFlagsZ || (base+paletteFlagsZ).sanitize (c, palette_count)) && + (!paletteLabelZ || (base+paletteLabelZ).sanitize (c, palette_count)) && + (!paletteEntryLabelZ || (base+paletteEntryLabelZ).sanitize (c, color_count))); } protected: From f3336580dd0c6959a1871f92b4a37f7c0a4b2160 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 16:16:21 -0700 Subject: [PATCH 13/36] [color] Use hb_array_t in CPAL Doesn't work though, ouch :(. Need to figure out if it's unreasonable to expect Null(T) inside hb_array_t to see the later specialization of Null for NameID. --- src/hb-open-type.hh | 3 ++- src/hb-ot-color-cpal-table.hh | 47 ++++++++++++++++++----------------- src/hb-static.cc | 1 + 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index be0d8b016..dc2f1f7c0 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -150,7 +150,8 @@ struct Tag : HBUINT32 typedef HBUINT16 GlyphID; /* Name-table index, same as uint16 (length = 16 bits) */ -typedef HBUINT16 NameID; +struct NameID : HBUINT16 {}; +DECLARE_NULL_NAMESPACE_BYTES (OT, NameID); /* Script/language-system/feature index */ struct Index : HBUINT16 { diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index beef2fce9..205613e47 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -53,10 +53,9 @@ struct CPALV1Tail unsigned int palette_index, unsigned int palette_count) const { - if (unlikely (palette_index >= palette_count || !paletteFlagsZ)) - return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; - - return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette_index]; + if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; + return (hb_ot_color_palette_flags_t) (uint32_t) + hb_array_t ((base+paletteFlagsZ).arrayZ, palette_count)[palette_index]; } inline unsigned int @@ -64,10 +63,10 @@ struct CPALV1Tail unsigned int palette_index, unsigned int palette_count) const { - if (unlikely (palette_index >= palette_count || !paletteLabelZ)) - return HB_NAME_ID_INVALID; - - return (base+paletteLabelZ)[palette_index]; + /* XXX the Null(NameID) returned by hb_array_t is wrong. Figure out why + * and remove the explicit bound check. */ + if (!paletteLabelsZ || palette_index >= palette_count) return HB_NAME_ID_INVALID; + return hb_array_t ((base+paletteLabelsZ).arrayZ, palette_count)[palette_index]; } inline unsigned int @@ -75,21 +74,23 @@ struct CPALV1Tail unsigned int color_index, unsigned int color_count) const { - if (unlikely (color_index >= color_count || !paletteEntryLabelZ)) - return HB_NAME_ID_INVALID; - - return (base+paletteEntryLabelZ)[color_index]; + /* XXX the Null(NameID) returned by hb_array_t is wrong. Figure out why + * and remove the explicit bound check. */ + if (!colorLabelsZ || color_index >= color_count) return HB_NAME_ID_INVALID; + return hb_array_t ((base+colorLabelsZ).arrayZ, color_count)[color_index]; } public: - inline bool sanitize (hb_sanitize_context_t *c, const void *base, - unsigned int palette_count, unsigned int color_count) const + inline bool sanitize (hb_sanitize_context_t *c, + const void *base, + unsigned int palette_count, + unsigned int color_count) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - (!paletteFlagsZ || (base+paletteFlagsZ).sanitize (c, palette_count)) && - (!paletteLabelZ || (base+paletteLabelZ).sanitize (c, palette_count)) && - (!paletteEntryLabelZ || (base+paletteEntryLabelZ).sanitize (c, color_count))); + (!paletteFlagsZ || (base+paletteFlagsZ).sanitize (c, palette_count)) && + (!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) && + (!colorLabelsZ || (base+colorLabelsZ).sanitize (c, color_count))); } protected: @@ -97,13 +98,13 @@ struct CPALV1Tail paletteFlagsZ; /* Offset from the beginning of CPAL table to * the Palette Type Array. Set to 0 if no array * is provided. */ - LOffsetTo, false> - paletteLabelZ; /* Offset from the beginning of CPAL table to - * the Palette Labels Array. Set to 0 if no + LOffsetTo, false> + paletteLabelsZ; /* Offset from the beginning of CPAL table to + * the palette labels array. Set to 0 if no * array is provided. */ - LOffsetTo, false> - paletteEntryLabelZ; /* Offset from the beginning of CPAL table to - * the Palette Entry Label Array. Set to 0 + LOffsetTo, false> + colorLabelsZ; /* Offset from the beginning of CPAL table to + * the color labels array. Set to 0 * if no array is provided. */ public: DEFINE_SIZE_STATIC (12); diff --git a/src/hb-static.cc b/src/hb-static.cc index e5507960d..53889a5a6 100644 --- a/src/hb-static.cc +++ b/src/hb-static.cc @@ -40,6 +40,7 @@ hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {}; /*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {}; +DEFINE_NULL_NAMESPACE_BYTES (OT, NameID) = {0xFF,0xFF}; DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF}; DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00}; DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00}; From d7865107ea4664e04c03a1d79678cdcadc0d5ea5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 16:18:34 -0700 Subject: [PATCH 14/36] Remove const from hb_array_t details Will come in through if desired. --- src/hb-aat-layout-trak-table.hh | 6 +++--- src/hb-dsalgs.hh | 6 +++--- src/hb-open-file.hh | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index 16729d16f..c2c50bbb7 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -55,7 +55,7 @@ struct TrackTableEntry unsigned int index, unsigned int nSizes) const { - return hb_array_t ((base+valuesZ).arrayZ, nSizes)[index]; + return hb_array_t ((base+valuesZ).arrayZ, nSizes)[index]; } public: @@ -88,7 +88,7 @@ struct TrackData const void *base) const { unsigned int sizes = nSizes; - hb_array_t size_table ((base+sizeTable).arrayZ, sizes); + hb_array_t size_table ((base+sizeTable).arrayZ, sizes); float s0 = size_table[idx].to_float (); float s1 = size_table[idx + 1].to_float (); @@ -134,7 +134,7 @@ struct TrackData if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes); /* TODO bfind() */ - hb_array_t size_table ((base+sizeTable).arrayZ, sizes); + hb_array_t size_table ((base+sizeTable).arrayZ, sizes); unsigned int size_index; for (size_index = 0; size_index < sizes - 1; size_index++) if (size_table[size_index].to_float () >= csspx) diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index 7e1b7eb1b..27c1a96ef 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -513,9 +513,9 @@ template struct hb_array_t { inline hb_array_t (void) : arrayZ (nullptr), len (0) {} - inline hb_array_t (const T *array_, unsigned int len_) : arrayZ (array_), len (len_) {} + inline hb_array_t (T *array_, unsigned int len_) : arrayZ (array_), len (len_) {} - inline const T& operator [] (unsigned int i) const + inline T& operator [] (unsigned int i) const { if (unlikely (i >= len)) return Null(T); return arrayZ[i]; @@ -534,7 +534,7 @@ struct hb_array_t inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; } - const T *arrayZ; + T *arrayZ; unsigned int len; }; diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh index 817791ab0..a973455d7 100644 --- a/src/hb-open-file.hh +++ b/src/hb-open-file.hh @@ -330,8 +330,8 @@ struct ResourceTypeRecord inline const ResourceRecord& get_resource_record (unsigned int i, const void *type_base) const { - return hb_array_t ((type_base+resourcesZ).arrayZ, - get_resource_count ()) [i]; + return hb_array_t ((type_base+resourcesZ).arrayZ, + get_resource_count ()) [i]; } inline bool sanitize (hb_sanitize_context_t *c, From 14474d21040bf9b025b53bb9b0df599eaf260119 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 16:30:30 -0700 Subject: [PATCH 15/36] [color] Rely on CPALV1Tail Null object --- src/hb-ot-color-cpal-table.hh | 39 +++++++++++++---------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index 205613e47..37e0db36d 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -125,31 +125,13 @@ struct CPAL inline unsigned int get_color_count () const { return numColors; } inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const - { - if (unlikely (version == 0)) - return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; - - const CPALV1Tail& cpal1 = StructAfter (*this); - return cpal1.get_palette_flags (this, palette_index, numPalettes); - } + { return v1 ().get_palette_flags (this, palette_index, numPalettes); } inline unsigned int get_palette_name_id (unsigned int palette_index) const - { - if (unlikely (version == 0)) - return HB_NAME_ID_INVALID; - - const CPALV1Tail& cpal1 = StructAfter (*this); - return cpal1.get_palette_name_id (this, palette_index, numPalettes); - } + { return v1 ().get_palette_name_id (this, palette_index, numPalettes); } inline unsigned int get_color_name_id (unsigned int color_index) const - { - if (unlikely (version == 0)) - return HB_NAME_ID_INVALID; - - const CPALV1Tail& cpal1 = StructAfter (*this); - return cpal1.get_color_name_id (this, color_index, numColors); - } + { return v1 ().get_color_name_id (this, color_index, numColors); } bool get_color_record_argb (unsigned int color_index, unsigned int palette_index, hb_color_t* color) const @@ -164,14 +146,22 @@ struct CPAL return true; } + private: + inline const CPALV1Tail& v1 (void) const + { + if (version == 0) return Null(CPALV1Tail); + return StructAfter (*this); + } + + public: inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (unlikely (!(c->check_struct (this) && /* it checks colorRecordIndices also - * See #get_size */ + if (unlikely (!(c->check_struct (this) && (this+colorRecordsZ).sanitize (c, numColorRecords)))) return_trace (false); + /* TODO */ /* Check for indices sanity so no need for doing it runtime */ for (unsigned int i = 0; i < numPalettes; ++i) if (unlikely (colorRecordIndicesZ[i] + numColors > numColorRecords)) @@ -181,8 +171,7 @@ struct CPAL if (version == 0) return_trace (true); - const CPALV1Tail &v1 = StructAfter (*this); - return_trace (likely (v1.sanitize (c, this, numPalettes, numColors))); + return_trace (likely (v1 ().sanitize (c, this, numPalettes, numColors))); } protected: From 683fad062792a199e2fe86fe161f41b9389d08c3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 16:35:03 -0700 Subject: [PATCH 16/36] [color] Minor --- src/hb-ot-color.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 3ca8751a2..59f7da72f 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -161,8 +161,7 @@ hb_ot_color_palette_flags_t hb_ot_color_palette_get_flags (hb_face_t *face, unsigned int palette_index) { - const OT::CPAL& cpal = _get_cpal(face); - return cpal.get_palette_flags (palette_index); + return _get_cpal(face).get_palette_flags (palette_index); } /** @@ -258,6 +257,5 @@ hb_ot_color_glyph_get_layers (hb_face_t *face, unsigned int *count, /* IN/OUT. May be NULL. */ hb_ot_color_layer_t *layers /* OUT. May be NULL. */) { - const OT::COLR& colr = _get_colr (face); - return colr.get_glyph_layers (glyph, start_offset, count, layers); + return _get_colr (face).get_glyph_layers (glyph, start_offset, count, layers); } From 228f96c9d09272c8f677935a640e75e173b817a3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 16:55:12 -0700 Subject: [PATCH 17/36] [color] Finish reviewing / revamping CPAL Now to hb_color_t. --- src/hb-ot-color-cpal-table.hh | 52 ++++++++++++++++++----------------- src/hb-ot-color.cc | 33 ++++------------------ src/hb-ot-color.h | 10 +++---- 3 files changed, 38 insertions(+), 57 deletions(-) diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index 37e0db36d..3f2165c46 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -133,17 +133,30 @@ struct CPAL inline unsigned int get_color_name_id (unsigned int color_index) const { return v1 ().get_color_name_id (this, color_index, numColors); } - bool - get_color_record_argb (unsigned int color_index, unsigned int palette_index, hb_color_t* color) const + inline unsigned int get_palette_colors (unsigned int palette_index, + unsigned int start_offset, + unsigned int *color_count, /* IN/OUT. May be NULL. */ + hb_color_t *colors /* OUT. May be NULL. */) const { - if (unlikely (color_index >= numColors || palette_index >= numPalettes)) - return false; - - /* No need for more range check as it is already done on #sanitize */ - const UnsizedArrayOf& color_records = this+colorRecordsZ; - if (color) - *color = color_records[colorRecordIndicesZ[palette_index] + color_index]; - return true; + if (unlikely (palette_index >= numPalettes)) + { + if (color_count) *color_count = 0; + return 0; + } + unsigned int start_index = colorRecordIndicesZ[palette_index]; + hb_array_t all_colors ((this+colorRecordsZ).arrayZ, numColorRecords); + hb_array_t palette_colors = all_colors.sub_array (start_index, + numColors); + if (color_count) + { + hb_array_t segment_colors = palette_colors.sub_array (start_offset, *color_count); + /* Always return numColors colors per palette even if it has out-of-bounds start index. */ + unsigned int count = MIN (MAX (numColors - start_offset, 0), *color_count); + *color_count = count; + for (unsigned int i = 0; i < count; i++) + colors[i] = segment_colors[i]; /* Bound-checked read. */ + } + return numColors; } private: @@ -157,21 +170,10 @@ struct CPAL inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (unlikely (!(c->check_struct (this) && - (this+colorRecordsZ).sanitize (c, numColorRecords)))) - return_trace (false); - - /* TODO */ - /* Check for indices sanity so no need for doing it runtime */ - for (unsigned int i = 0; i < numPalettes; ++i) - if (unlikely (colorRecordIndicesZ[i] + numColors > numColorRecords)) - return_trace (false); - - /* If version is zero, we are done here; otherwise we need to check tail also */ - if (version == 0) - return_trace (true); - - return_trace (likely (v1 ().sanitize (c, this, numPalettes, numColors))); + return_trace (c->check_struct (this) && + (this+colorRecordsZ).sanitize (c, numColorRecords) && + colorRecordIndicesZ.sanitize (c, numPalettes) && + (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors))); } protected: diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 59f7da72f..229b6e66f 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -189,34 +189,13 @@ hb_ot_color_palette_get_flags (hb_face_t *face, * Since: REPLACEME */ unsigned int -hb_ot_color_palette_get_colors (hb_face_t *face, - unsigned int palette_index, /* default=0 */ - unsigned int start_offset, - unsigned int *colors_count /* IN/OUT. May be NULL. */, - hb_color_t *colors /* OUT. May be NULL. */) +hb_ot_color_palette_get_colors (hb_face_t *face, + unsigned int palette_index, + unsigned int start_offset, + unsigned int *colors_count /* IN/OUT. May be NULL. */, + hb_color_t *colors /* OUT. May be NULL. */) { - const OT::CPAL& cpal = _get_cpal(face); - if (unlikely (palette_index >= cpal.get_palette_count ())) - { - if (colors_count) *colors_count = 0; - return 0; - } - - unsigned int num_results = 0; - if (colors_count) - { - unsigned int platte_count; - platte_count = MIN(*colors_count, - cpal.get_color_count () - start_offset); - for (unsigned int i = 0; i < platte_count; i++) - { - if (cpal.get_color_record_argb(start_offset + i, palette_index, &colors[num_results])) - ++num_results; - } - } - - if (likely (colors_count)) *colors_count = num_results; - return cpal.get_color_count (); + return _get_cpal (face).get_palette_colors (palette_index, start_offset, colors_count, colors); } diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index 4d08eb065..02b76bffc 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -79,11 +79,11 @@ hb_ot_color_palette_get_flags (hb_face_t *face, unsigned int palette_index); HB_EXTERN unsigned int -hb_ot_color_palette_get_colors (hb_face_t *face, - unsigned int palette_index, - unsigned int start_offset, - unsigned int *color_count, /* IN/OUT. May be NULL. */ - hb_color_t *colors /* OUT. May be NULL. */); +hb_ot_color_palette_get_colors (hb_face_t *face, + unsigned int palette_index, + unsigned int start_offset, + unsigned int *color_count, /* IN/OUT. May be NULL. */ + hb_color_t *colors /* OUT. May be NULL. */); /* From b18acab7bce062fef397d3d8b0efc7826f473b50 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 18:20:57 -0700 Subject: [PATCH 18/36] [color] Add HB_COLOR Normally I would have added to_string / from_string like other types have. But since we don't use hb_color_t much, I'm not going to do that. Although, if we did, we could use it in hb-view to parse colors... --- src/hb-common.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/hb-common.h b/src/hb-common.h index f9171b41d..0858c0e29 100644 --- a/src/hb-common.h +++ b/src/hb-common.h @@ -446,16 +446,20 @@ hb_variation_to_string (hb_variation_t *variation, /** * hb_color_t: - * ARGB data type for holding color values. + * + * Data type for holding color values. * * Since: REPLACEME */ typedef uint32_t hb_color_t; -#define hb_color_get_alpha(color) (color & 0xFF) -#define hb_color_get_red(color) ((color >> 8) & 0xFF) -#define hb_color_get_green(color) ((color >> 16) & 0xFF) -#define hb_color_get_blue(color) ((color >> 24) & 0xFF) +#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a))) + +#define hb_color_get_alpha(color) ((color) & 0xFF) +#define hb_color_get_red(color) (((color) >> 8) & 0xFF) +#define hb_color_get_green(color) (((color) >> 16) & 0xFF) +#define hb_color_get_blue(color) (((color) >> 24) & 0xFF) + HB_END_DECLS From 07386ea410af13e8fc844eb939a6c6e47c2adaf1 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 21:18:27 -0700 Subject: [PATCH 19/36] Remove const and references when binding Null() Fixes https://github.com/harfbuzz/harfbuzz/issues/1299 Removes anomaly I was seeing in cpal table trying to use implicit Null(NameID). --- src/hb-atomic.hh | 5 +---- src/hb-common.cc | 2 +- src/hb-ft.cc | 2 +- src/hb-null.hh | 4 ++-- src/hb-open-type.hh | 6 ++---- src/hb-ot-color-cpal-table.hh | 8 ++------ src/hb-static.cc | 1 - src/hb.hh | 9 +++++++++ 8 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/hb-atomic.hh b/src/hb-atomic.hh index 5cb7ca5d5..697de19c5 100644 --- a/src/hb-atomic.hh +++ b/src/hb-atomic.hh @@ -278,14 +278,11 @@ struct hb_atomic_int_t }; -template struct hb_remove_ptr_t { typedef T value; }; -template struct hb_remove_ptr_t { typedef T value; }; - #define HB_ATOMIC_PTR_INIT(V) {V} template struct hb_atomic_ptr_t { - typedef typename hb_remove_ptr_t

::value T; + typedef typename hb_remove_pointer

::value T; inline void init (T* v_ = nullptr) { set_relaxed (v_); } inline void set_relaxed (T* v_) const { hb_atomic_ptr_impl_set_relaxed (&v, v_); } diff --git a/src/hb-common.cc b/src/hb-common.cc index ba48dd561..ccdb4dd94 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -761,7 +761,7 @@ parse_uint32 (const char **pp, const char *end, uint32_t *pv) static void free_static_C_locale (void); #endif -static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t::value, +static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t::value, hb_C_locale_lazy_loader_t> { static inline HB_LOCALE_T create (void) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 18fb72a73..fbf362688 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -737,7 +737,7 @@ hb_ft_font_create_referenced (FT_Face ft_face) static void free_static_ft_library (void); #endif -static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t::value, +static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t::value, hb_ft_library_lazy_loader_t> { static inline FT_Library create (void) diff --git a/src/hb-null.hh b/src/hb-null.hh index 87662265c..3d8a1ae6c 100644 --- a/src/hb-null.hh +++ b/src/hb-null.hh @@ -47,7 +47,7 @@ static inline Type const & Null (void) { static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); return *reinterpret_cast (_hb_NullPool); } -#define Null(Type) Null() +#define Null(Type) Null::value>::value>() /* Specializations for arbitrary-content Null objects expressed in bytes. */ #define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \ @@ -90,7 +90,7 @@ static inline Type& Crap (void) { *obj = Null(Type); return *obj; } -#define Crap(Type) Crap() +#define Crap(Type) Crap::value>::value>() template struct CrapOrNull { diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index dc2f1f7c0..19081447f 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -149,16 +149,14 @@ struct Tag : HBUINT32 /* Glyph index number, same as uint16 (length = 16 bits) */ typedef HBUINT16 GlyphID; -/* Name-table index, same as uint16 (length = 16 bits) */ -struct NameID : HBUINT16 {}; -DECLARE_NULL_NAMESPACE_BYTES (OT, NameID); - /* Script/language-system/feature index */ struct Index : HBUINT16 { enum { NOT_FOUND_INDEX = 0xFFFFu }; }; DECLARE_NULL_NAMESPACE_BYTES (OT, Index); +typedef Index NameID; + /* Offset, Null offset = 0 */ template struct Offset : Type diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index 3f2165c46..7dd0c0f90 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -63,9 +63,7 @@ struct CPALV1Tail unsigned int palette_index, unsigned int palette_count) const { - /* XXX the Null(NameID) returned by hb_array_t is wrong. Figure out why - * and remove the explicit bound check. */ - if (!paletteLabelsZ || palette_index >= palette_count) return HB_NAME_ID_INVALID; + if (!paletteLabelsZ) return HB_NAME_ID_INVALID; return hb_array_t ((base+paletteLabelsZ).arrayZ, palette_count)[palette_index]; } @@ -74,9 +72,7 @@ struct CPALV1Tail unsigned int color_index, unsigned int color_count) const { - /* XXX the Null(NameID) returned by hb_array_t is wrong. Figure out why - * and remove the explicit bound check. */ - if (!colorLabelsZ || color_index >= color_count) return HB_NAME_ID_INVALID; + if (!colorLabelsZ) return HB_NAME_ID_INVALID; return hb_array_t ((base+colorLabelsZ).arrayZ, color_count)[color_index]; } diff --git a/src/hb-static.cc b/src/hb-static.cc index 53889a5a6..e5507960d 100644 --- a/src/hb-static.cc +++ b/src/hb-static.cc @@ -40,7 +40,6 @@ hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {}; /*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {}; -DEFINE_NULL_NAMESPACE_BYTES (OT, NameID) = {0xFF,0xFF}; DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF}; DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00}; DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00}; diff --git a/src/hb.hh b/src/hb.hh index 098b56604..ea474298f 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -495,6 +495,15 @@ _hb_memalign(void **memptr, size_t alignment, size_t size) #define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g')) +/* Some really basic things everyone wants. */ +template struct hb_remove_const { typedef T value; }; +template struct hb_remove_const { typedef T value; }; +template struct hb_remove_reference { typedef T value; }; +template struct hb_remove_reference { typedef T value; }; +template struct hb_remove_pointer { typedef T value; }; +template struct hb_remove_pointer { typedef T value; }; + + /* Headers we include for everyone. Keep sorted. They express dependency amongst * themselves, but no other file should include them.*/ #include "hb-atomic.hh" From 17ffbc070ff4190d8ebaf88f8db62f19e6fa370d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 21:22:25 -0700 Subject: [PATCH 20/36] [color] Use Index for colorIdx Doesn't matter, but matches the description. --- src/hb-ot-color-colr-table.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-color-colr-table.hh b/src/hb-ot-color-colr-table.hh index 7c5c35d8c..b480af51d 100644 --- a/src/hb-ot-color-colr-table.hh +++ b/src/hb-ot-color-colr-table.hh @@ -47,7 +47,7 @@ struct LayerRecord public: GlyphID glyphId; /* Glyph ID of layer glyph */ - HBUINT16 colorIdx; /* Index value to use with a + Index colorIdx; /* Index value to use with a * selected color palette. * An index value of 0xFFFF * is a special case indicating From abfbba191141c3e3cf2a391f365b5323f9dc37c0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 21:27:45 -0700 Subject: [PATCH 21/36] Add hb_array<>() Simplifies transient object creation. Fixes https://github.com/harfbuzz/harfbuzz/issues/1301 --- src/hb-aat-layout-trak-table.hh | 2 +- src/hb-dsalgs.hh | 2 ++ src/hb-open-file.hh | 3 +-- src/hb-ot-color-cpal-table.hh | 6 +++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index c2c50bbb7..823991f2f 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -55,7 +55,7 @@ struct TrackTableEntry unsigned int index, unsigned int nSizes) const { - return hb_array_t ((base+valuesZ).arrayZ, nSizes)[index]; + return hb_array ((base+valuesZ).arrayZ, nSizes)[index]; } public: diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index 27c1a96ef..11a055068 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -537,6 +537,8 @@ struct hb_array_t T *arrayZ; unsigned int len; }; +template +hb_array_t hb_array (T *array, unsigned int len) { return hb_array_t (array, len); } struct hb_bytes_t { diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh index a973455d7..3b742ea74 100644 --- a/src/hb-open-file.hh +++ b/src/hb-open-file.hh @@ -330,8 +330,7 @@ struct ResourceTypeRecord inline const ResourceRecord& get_resource_record (unsigned int i, const void *type_base) const { - return hb_array_t ((type_base+resourcesZ).arrayZ, - get_resource_count ()) [i]; + return hb_array ((type_base+resourcesZ).arrayZ, get_resource_count ())[i]; } inline bool sanitize (hb_sanitize_context_t *c, diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index 7dd0c0f90..4b09d3a5f 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -55,7 +55,7 @@ struct CPALV1Tail { if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; return (hb_ot_color_palette_flags_t) (uint32_t) - hb_array_t ((base+paletteFlagsZ).arrayZ, palette_count)[palette_index]; + hb_array ((base+paletteFlagsZ).arrayZ, palette_count)[palette_index]; } inline unsigned int @@ -64,7 +64,7 @@ struct CPALV1Tail unsigned int palette_count) const { if (!paletteLabelsZ) return HB_NAME_ID_INVALID; - return hb_array_t ((base+paletteLabelsZ).arrayZ, palette_count)[palette_index]; + return hb_array ((base+paletteLabelsZ).arrayZ, palette_count)[palette_index]; } inline unsigned int @@ -73,7 +73,7 @@ struct CPALV1Tail unsigned int color_count) const { if (!colorLabelsZ) return HB_NAME_ID_INVALID; - return hb_array_t ((base+colorLabelsZ).arrayZ, color_count)[color_index]; + return hb_array ((base+colorLabelsZ).arrayZ, color_count)[color_index]; } public: From 8d689f8a7bccda861bcb286d52f1a90fca52df0f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 21:33:18 -0700 Subject: [PATCH 22/36] Add hb_array<>() specialization for UnsizedArrayOf Related https://github.com/harfbuzz/harfbuzz/issues/1301 --- src/hb-aat-layout-trak-table.hh | 2 +- src/hb-open-file.hh | 2 +- src/hb-open-type.hh | 8 ++++++++ src/hb-ot-color-cpal-table.hh | 6 +++--- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index 823991f2f..8cfc8bc37 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -55,7 +55,7 @@ struct TrackTableEntry unsigned int index, unsigned int nSizes) const { - return hb_array ((base+valuesZ).arrayZ, nSizes)[index]; + return hb_array (base+valuesZ, nSizes)[index]; } public: diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh index 3b742ea74..80dc5e614 100644 --- a/src/hb-open-file.hh +++ b/src/hb-open-file.hh @@ -330,7 +330,7 @@ struct ResourceTypeRecord inline const ResourceRecord& get_resource_record (unsigned int i, const void *type_base) const { - return hb_array ((type_base+resourcesZ).arrayZ, get_resource_count ())[i]; + return hb_array (type_base+resourcesZ, get_resource_count ())[i]; } inline bool sanitize (hb_sanitize_context_t *c, diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index 19081447f..a76b111ee 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -385,6 +385,14 @@ struct UnsizedArrayOf public: DEFINE_SIZE_ARRAY (0, arrayZ); }; +} /* namespace OT */ +template +hb_array_t hb_array (OT::UnsizedArrayOf &array, unsigned int len) +{ return hb_array (array.arrayZ, len); } +template +hb_array_t hb_array (const OT::UnsizedArrayOf &array, unsigned int len) +{ return hb_array (array.arrayZ, len); } +namespace OT { /* Unsized array of offset's */ template diff --git a/src/hb-ot-color-cpal-table.hh b/src/hb-ot-color-cpal-table.hh index 4b09d3a5f..7d3733d3f 100644 --- a/src/hb-ot-color-cpal-table.hh +++ b/src/hb-ot-color-cpal-table.hh @@ -55,7 +55,7 @@ struct CPALV1Tail { if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT; return (hb_ot_color_palette_flags_t) (uint32_t) - hb_array ((base+paletteFlagsZ).arrayZ, palette_count)[palette_index]; + hb_array (base+paletteFlagsZ, palette_count)[palette_index]; } inline unsigned int @@ -64,7 +64,7 @@ struct CPALV1Tail unsigned int palette_count) const { if (!paletteLabelsZ) return HB_NAME_ID_INVALID; - return hb_array ((base+paletteLabelsZ).arrayZ, palette_count)[palette_index]; + return hb_array (base+paletteLabelsZ, palette_count)[palette_index]; } inline unsigned int @@ -73,7 +73,7 @@ struct CPALV1Tail unsigned int color_count) const { if (!colorLabelsZ) return HB_NAME_ID_INVALID; - return hb_array ((base+colorLabelsZ).arrayZ, color_count)[color_index]; + return hb_array (base+colorLabelsZ, color_count)[color_index]; } public: From 8c78ced95b639730efd0edc521e4e81ad50af501 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 21:49:42 -0700 Subject: [PATCH 23/36] Unbreak builds --- src/hb-dsalgs.hh | 2 +- src/hb-open-type.hh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index 11a055068..7e846161d 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -537,7 +537,7 @@ struct hb_array_t T *arrayZ; unsigned int len; }; -template +template static inline hb_array_t hb_array (T *array, unsigned int len) { return hb_array_t (array, len); } struct hb_bytes_t diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index a76b111ee..2b1b432ba 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -386,10 +386,10 @@ struct UnsizedArrayOf DEFINE_SIZE_ARRAY (0, arrayZ); }; } /* namespace OT */ -template +template static inline hb_array_t hb_array (OT::UnsizedArrayOf &array, unsigned int len) { return hb_array (array.arrayZ, len); } -template +template static inline hb_array_t hb_array (const OT::UnsizedArrayOf &array, unsigned int len) { return hb_array (array.arrayZ, len); } namespace OT { From e1b8e933f099efae3c3e1f5706be19120b44de20 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Tue, 23 Oct 2018 09:23:48 +0330 Subject: [PATCH 24/36] [ci] Disable llvm-gcc #define Null(Type) Null::value>::value>() raises: hb-blob.cc: In function 'hb_blob_t* hb_blob_get_empty()': hb-blob.cc:194: error: using 'typename' outside of template hb-blob.cc:194: error: using 'typename' outside of template Removing "typename"s fixes the issue but makes newer compiler fail apparently. Probably downstream can patch that locally till we get a solution. --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 97a7b1565..46fb65b2e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -301,8 +301,8 @@ workflows: build: jobs: # macOS - - macos-llvm-gcc-4.2 - - macos-notest-apple-gcc-i686-4.2 + #- macos-llvm-gcc-4.2 + #- macos-notest-apple-gcc-i686-4.2 - macos-notest-ios # both autotools and cmake From 792071de4075cb9af0793f0d7c70da0780923bb6 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 23:38:34 -0700 Subject: [PATCH 25/36] [morx] Leave ligature on stack after ligating Test with Apple Color Emoji.ttf of ~66MB and following sequence: ./hb-shape Apple\ Color\ Emoji-old.ttf --font-funcs=ot -u U+1F468,200d,U+1F469,200d,U+1F467,200d,1f466 Should form full family if matching works correctly. It first makes family of three, then makes family of four out of that and the last two characters. Fixes https://github.com/harfbuzz/harfbuzz/issues/1292 --- src/hb-aat-layout-morx-table.hh | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 651af2188..ddb444c21 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -442,7 +442,6 @@ struct LigatureSubtable action_idx++; } while (!(action & LigActionLast)); - match_length = 0; buffer->move_to (end); } From 1bfb96a9c8d7653f0dee5c5fab3c6e85cea900cd Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 22 Oct 2018 23:41:47 -0700 Subject: [PATCH 26/36] [test/text-rendering-tests] Update from upstream --- .../data/text-rendering-tests/Makefile.sources | 2 +- .../text-rendering-tests/fonts/TestTRAKOne.ttf | Bin 0 -> 1752 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 test/shaping/data/text-rendering-tests/fonts/TestTRAKOne.ttf diff --git a/test/shaping/data/text-rendering-tests/Makefile.sources b/test/shaping/data/text-rendering-tests/Makefile.sources index 5e0db6bd8..136a14d32 100644 --- a/test/shaping/data/text-rendering-tests/Makefile.sources +++ b/test/shaping/data/text-rendering-tests/Makefile.sources @@ -73,8 +73,8 @@ TESTS = \ $(NULL) DISBALED_TESTS = \ - tests/MORX-41.tests \ tests/CMAP-3.tests \ + tests/MORX-41.tests \ tests/SHARAN-1.tests \ tests/SHBALI-1.tests \ tests/SHBALI-2.tests \ diff --git a/test/shaping/data/text-rendering-tests/fonts/TestTRAKOne.ttf b/test/shaping/data/text-rendering-tests/fonts/TestTRAKOne.ttf new file mode 100644 index 0000000000000000000000000000000000000000..425bce6fceeadb7104800759b1faa6422a8c59a6 GIT binary patch literal 1752 zcma)7Uu;uV82_Dn*KOd~tZd*PB=@#OQO62vij#~4E~XjT+$LjcmQ1+rcI{%jc5Pw6 zlQY2wo{SHM@T^Tt^vUpI^aTwrXfhy*N>HXDaWR-^1BMvw@psO>BOB4gw%`4J-*>+A zo!|GJb59`v+=tg-V*AiYygR!o69YsKy@x0AZV|6zl=eHcdo#J?lh>!--AH?hb}gHB zz3{@0Vd9S|JF|2&&KpOGZ&6~|eC1f^TQw$5({9NXCS16%9%rRJ`!b z&1=7C{cHG1jLRNl&a`MZ!BAd)ILBO)tkGCx_Az5lXY$AVr>Q+A_G7Jf2+rM%Mq)1r zGeu3ji4dBNQ^rg5_4``9jBe4XVnRXSy=t`o#X;K)J($-r3C_mCsbnv5kew=l%6XFazVWJHkcnDEE zfh3;6ZuF6@9k!b~5*^WwL^7I8B#Eh;2$#Ler$*HXx zoNCpH*tX+1o@1Y^dJ)^RtJSLQc_&k;>SW4d?fdL4Hh**3NGcU`iBfj26Y);;Y>W@j z%zQ92GaS#@ahpF@#7-D<#s!{NkZw2{PVkus8;{rD8XFVSW8%5`hsK5aWzqHbPQUgR zysbLcu!d$Y#m530X!+PcD-Hy>0gvHufE$V52=E#_jQ0b)PHe{c0JmaL+z9Y`tTnoQ zEFx$zg8U*%e_!B_5g))l6j0=jlrV)1Pk)8G_8z4h+pz;ZM5CDI*aYJ|q|r&wetIU* zg@d%qoNH@tPjt{XP19#_?gIQ|F{rU^6y~G^p6?0ZIE#J+uEvT!HZ>awr z)a&HQGsjAo&(8q81>IZ!rr<%BXL+9f?W1lH6Hf*ALyHbE@c?zFx%KelurJb^YvWa3*Vid(<4@Lb;Jc5v{%R90rZ_1zL zPx1$ORbG)_$xHI0T##SL&*f*llh!joSCoIs+wwO?F3B5=z0T{2mzd>Cd0w8A=l%i33|g=N literal 0 HcmV?d00001 From 0e5bcdef7fb592f986ad5b4e07b80d2efb5e3344 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 23 Oct 2018 00:39:44 -0700 Subject: [PATCH 27/36] [morx] Clear stack upon underflow when acting ligatures --- src/hb-aat-layout-morx-table.hh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index ddb444c21..3f5f29d1d 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -402,7 +402,11 @@ struct LigatureSubtable do { if (unlikely (!cursor)) + { + /* Stack underflow. Clear the stack. */ + match_length = 0; break; + } buffer->move_to (match_positions[--cursor]); From 531f9822b2e8a60f03c43d6f86ef9ed32c951f0e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 23 Oct 2018 01:32:08 -0700 Subject: [PATCH 28/36] [morx] Add a few debug messages to Ligature chain --- src/hb-aat-layout-morx-table.hh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 3f5f29d1d..5577efe86 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -373,6 +373,7 @@ struct LigatureSubtable hb_buffer_t *buffer = driver->buffer; unsigned int flags = entry->flags; + DEBUG_MSG (APPLY, nullptr, "Ligature transition at %d", buffer->idx); if (flags & SetComponent) { if (unlikely (match_length >= ARRAY_LENGTH (match_positions))) @@ -383,10 +384,12 @@ struct LigatureSubtable match_length--; match_positions[match_length++] = buffer->out_len; + DEBUG_MSG (APPLY, nullptr, "Set component at %d", buffer->out_len); } if (flags & PerformAction) { + DEBUG_MSG (APPLY, nullptr, "Perform action with %d", match_length); unsigned int end = buffer->out_len; unsigned int action_idx = entry->data.ligActionIndex; unsigned int action; @@ -404,10 +407,12 @@ struct LigatureSubtable if (unlikely (!cursor)) { /* Stack underflow. Clear the stack. */ + DEBUG_MSG (APPLY, nullptr, "Stack underflow"); match_length = 0; break; } + DEBUG_MSG (APPLY, nullptr, "Moving to stack position %d", cursor - 1); buffer->move_to (match_positions[--cursor]); const HBUINT32 &actionData = ligAction[action_idx]; @@ -426,17 +431,22 @@ struct LigatureSubtable if (unlikely (!componentData.sanitize (&c->sanitizer))) return false; ligature_idx += componentData; + DEBUG_MSG (APPLY, nullptr, "Action store %d last %d", + bool (action & LigActionStore), + bool (action & LigActionLast)); if (action & (LigActionStore | LigActionLast)) { const GlyphID &ligatureData = ligature[ligature_idx]; if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false; hb_codepoint_t lig = ligatureData; + DEBUG_MSG (APPLY, nullptr, "Produced ligature %d", lig); buffer->replace_glyph (lig); /* Now go and delete all subsequent components. */ while (match_length - 1 > cursor) { + DEBUG_MSG (APPLY, nullptr, "Skipping ligature component"); buffer->move_to (match_positions[--match_length]); buffer->skip_glyph (); end--; From 6fb24d5e3e0cf61c0ed3574e5bcf4598a13d6b69 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 23 Oct 2018 01:58:59 -0700 Subject: [PATCH 29/36] [VORG] Add VORG table Cherry-picked from cff-subset branch. --- src/Makefile.sources | 1 + src/hb-ot-face.cc | 1 + src/hb-ot-face.hh | 1 + src/hb-ot-vorg-table.hh | 168 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 171 insertions(+) create mode 100644 src/hb-ot-vorg-table.hh diff --git a/src/Makefile.sources b/src/Makefile.sources index 93965ac02..eed245bca 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -153,6 +153,7 @@ HB_OT_sources = \ hb-ot-var-fvar-table.hh \ hb-ot-var-hvar-table.hh \ hb-ot-var-mvar-table.hh \ + hb-ot-vorg-table.hh \ $(NULL) HB_OT_RAGEL_GENERATED_sources = \ diff --git a/src/hb-ot-face.cc b/src/hb-ot-face.cc index 1bc68d366..202619c3e 100644 --- a/src/hb-ot-face.cc +++ b/src/hb-ot-face.cc @@ -31,6 +31,7 @@ #include "hb-ot-hmtx-table.hh" #include "hb-ot-kern-table.hh" #include "hb-ot-post-table.hh" +#include "hb-ot-vorg-table.hh" #include "hb-ot-color-cbdt-table.hh" #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" diff --git a/src/hb-ot-face.hh b/src/hb-ot-face.hh index 5ea7bf0e8..a45a49361 100644 --- a/src/hb-ot-face.hh +++ b/src/hb-ot-face.hh @@ -68,6 +68,7 @@ HB_OT_ACCELERATOR(OT, post) \ HB_OT_ACCELERATOR(OT, kern) \ HB_OT_ACCELERATOR(OT, glyf) \ + HB_OT_TABLE(OT, VORG) \ /* OpenType color fonts. */ \ HB_OT_TABLE(OT, COLR) \ HB_OT_TABLE(OT, CPAL) \ diff --git a/src/hb-ot-vorg-table.hh b/src/hb-ot-vorg-table.hh new file mode 100644 index 000000000..3b7bf4c06 --- /dev/null +++ b/src/hb-ot-vorg-table.hh @@ -0,0 +1,168 @@ +/* + * Copyright © 2018 Adobe Systems Incorporated. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Adobe Author(s): Michiharu Ariza + */ + +#ifndef HB_OT_VORG_TABLE_HH +#define HB_OT_VORG_TABLE_HH + +#include "hb-open-type.hh" + +/* + * VORG -- Vertical Origin Table + * https://docs.microsoft.com/en-us/typography/opentype/spec/vorg + */ +#define HB_OT_TAG_VORG HB_TAG('V','O','R','G') + +namespace OT { + +struct VertOriginMetric +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + GlyphID glyph; + FWORD vertOriginY; + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct VORG +{ + static const hb_tag_t tableTag = HB_OT_TAG_VORG; + + inline bool _subset (const hb_subset_plan_t *plan, + const VORG *vorg_table, + const hb_vector_t &subset_metrics, + unsigned int dest_sz, + void *dest) const + { + hb_serialize_context_t c (dest, dest_sz); + + VORG *subset_table = c.start_serialize (); + if (unlikely (!c.extend_min (*subset_table))) + return false; + + subset_table->version.major.set (1); + subset_table->version.minor.set (0); + + subset_table->defaultVertOriginY.set (vorg_table->defaultVertOriginY); + subset_table->vertYOrigins.len.set (subset_metrics.len); + + bool success = true; + if (subset_metrics.len > 0) + { + unsigned int size = VertOriginMetric::static_size * subset_metrics.len; + VertOriginMetric *metrics = c.allocate_size (size); + if (likely (metrics != nullptr)) + memcpy (metrics, &subset_metrics[0], size); + else + success = false; + } + c.end_serialize (); + + return success; + } + + inline bool subset (hb_subset_plan_t *plan) const + { + hb_blob_t *vorg_blob = hb_sanitize_context_t().reference_table (plan->source); + const VORG *vorg_table = vorg_blob->as (); + + /* count the number of glyphs to be included in the subset table */ + hb_vector_t subset_metrics; + subset_metrics.init (); + unsigned int glyph = 0; + unsigned int i = 0; + while ((glyph < plan->glyphs.len) && (i < vertYOrigins.len)) + { + if (plan->glyphs[glyph] > vertYOrigins[i].glyph) + i++; + else if (plan->glyphs[glyph] < vertYOrigins[i].glyph) + glyph++; + else + { + VertOriginMetric *metrics = subset_metrics.push (); + metrics->glyph.set (glyph); + metrics->vertOriginY.set (vertYOrigins[i].vertOriginY); + glyph++; + i++; + } + } + + /* alloc the new table */ + unsigned int dest_sz = VORG::min_size + VertOriginMetric::static_size * subset_metrics.len; + void *dest = (void *) malloc (dest_sz); + if (unlikely (!dest)) + { + subset_metrics.fini (); + hb_blob_destroy (vorg_blob); + return false; + } + + /* serialize the new table */ + if (!_subset (plan, vorg_table, subset_metrics, dest_sz, dest)) + { + subset_metrics.fini (); + free (dest); + hb_blob_destroy (vorg_blob); + return false; + } + + hb_blob_t *result = hb_blob_create ((const char *)dest, + dest_sz, + HB_MEMORY_MODE_READONLY, + dest, + free); + bool success = plan->add_table (HB_OT_TAG_VORG, result); + hb_blob_destroy (result); + subset_metrics.fini (); + hb_blob_destroy (vorg_blob); + return success; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + version.major == 1 && + vertYOrigins.sanitize (c)); + } + + protected: + FixedVersion<> version; /* Version of VORG table. Set to 0x00010000u. */ + FWORD defaultVertOriginY; /* The default vertical origin */ + ArrayOfvertYOrigins; /* The array of vertical origins */ + + public: + DEFINE_SIZE_ARRAY(8, vertYOrigins); +}; +} /* namespace OT */ + +#endif /* HB_OT_VORG_TABLE_HH */ From 097ecfd4a991d4fa306bab7330d9952966e94d1f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 23 Oct 2018 02:09:42 -0700 Subject: [PATCH 30/36] [VORG] Add get_y_origin() Unhooked. --- src/hb-ot-vorg-table.hh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/hb-ot-vorg-table.hh b/src/hb-ot-vorg-table.hh index 3b7bf4c06..0baaf2e0e 100644 --- a/src/hb-ot-vorg-table.hh +++ b/src/hb-ot-vorg-table.hh @@ -39,6 +39,8 @@ namespace OT { struct VertOriginMetric { + inline int cmp (hb_codepoint_t g) const { return -glyph.cmp (g); } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -57,6 +59,15 @@ struct VORG { static const hb_tag_t tableTag = HB_OT_TAG_VORG; + inline bool has_data (void) const { return version.to_int (); } + + inline int get_y_origin (hb_codepoint_t glyph) const + { + vertYOrigins.bsearch (glyph); + + return defaultVertOriginY; + } + inline bool _subset (const hb_subset_plan_t *plan, const VORG *vorg_table, const hb_vector_t &subset_metrics, @@ -157,8 +168,9 @@ struct VORG protected: FixedVersion<> version; /* Version of VORG table. Set to 0x00010000u. */ - FWORD defaultVertOriginY; /* The default vertical origin */ - ArrayOfvertYOrigins; /* The array of vertical origins */ + FWORD defaultVertOriginY; /* The default vertical origin. */ + SortedArrayOf + vertYOrigins; /* The array of vertical origins. */ public: DEFINE_SIZE_ARRAY(8, vertYOrigins); From 48ed598a356983f4623029dd5e87254fb59e3691 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 23 Oct 2018 02:19:32 -0700 Subject: [PATCH 31/36] [VORG] Hook up to hb-ot-font's v_origin Fixes https://github.com/harfbuzz/harfbuzz/issues/544 Test added with NotoSansCJK, eg. with U+FF38. --- src/hb-ot-face.cc | 1 - src/hb-ot-font.cc | 11 +++++++++-- src/hb-ot-vorg-table.hh | 6 ++++-- .../4cbbc461be066fccc611dcc634af6e8cb2705537.ttf | Bin 0 -> 2808 bytes test/shaping/data/in-house/tests/vertical.tests | 1 + 5 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 test/shaping/data/in-house/fonts/4cbbc461be066fccc611dcc634af6e8cb2705537.ttf diff --git a/src/hb-ot-face.cc b/src/hb-ot-face.cc index 202619c3e..1bc68d366 100644 --- a/src/hb-ot-face.cc +++ b/src/hb-ot-face.cc @@ -31,7 +31,6 @@ #include "hb-ot-hmtx-table.hh" #include "hb-ot-kern-table.hh" #include "hb-ot-post-table.hh" -#include "hb-ot-vorg-table.hh" #include "hb-ot-color-cbdt-table.hh" #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index e6df038d3..f0b620898 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -37,6 +37,7 @@ #include "hb-ot-kern-table.hh" #include "hb-ot-post-table.hh" #include "hb-ot-glyf-table.hh" +#include "hb-ot-vorg-table.hh" #include "hb-ot-color-cbdt-table.hh" @@ -138,9 +139,15 @@ hb_ot_get_glyph_v_origin (hb_font_t *font, *x = font->get_glyph_h_advance (glyph) / 2; + const OT::VORG &VORG = *ot_face->VORG.get (); + if (VORG.has_data ()) + { + *y = font->em_scale_y (VORG.get_y_origin (glyph)); + return true; + } + hb_glyph_extents_t extents = {0}; - bool ret = ot_face->glyf->get_extents (glyph, &extents); - if (ret) + if (ot_face->glyf->get_extents (glyph, &extents)) { const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx.get (); hb_position_t tsb = vmtx.get_side_bearing (glyph); diff --git a/src/hb-ot-vorg-table.hh b/src/hb-ot-vorg-table.hh index 0baaf2e0e..b6494b51f 100644 --- a/src/hb-ot-vorg-table.hh +++ b/src/hb-ot-vorg-table.hh @@ -39,7 +39,7 @@ namespace OT { struct VertOriginMetric { - inline int cmp (hb_codepoint_t g) const { return -glyph.cmp (g); } + inline int cmp (hb_codepoint_t g) const { return glyph.cmp (g); } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -63,7 +63,9 @@ struct VORG inline int get_y_origin (hb_codepoint_t glyph) const { - vertYOrigins.bsearch (glyph); + int i = vertYOrigins.bsearch (glyph); + if (i != -1) + return vertYOrigins[i].vertOriginY; return defaultVertOriginY; } diff --git a/test/shaping/data/in-house/fonts/4cbbc461be066fccc611dcc634af6e8cb2705537.ttf b/test/shaping/data/in-house/fonts/4cbbc461be066fccc611dcc634af6e8cb2705537.ttf new file mode 100644 index 0000000000000000000000000000000000000000..03166b0c884aa515d80280afa0d5c365f063a1c5 GIT binary patch literal 2808 zcma)8Yitx%6h3!nclsLoqOGk!8K6{XptQAMq4+3mX(^8_-3r=N=yZ3wJ9J-}9ZFY< z5HU!k_y|VOAVM?{2uO{BMEGG$h{PX~5dEn!(HMRpYADRqFB2%9)4RFn-t)ZY zp6}kd>+bAyLpJOI4tg3_uNJEhD475-3gGywrQPlMx%T>DfHV<+9c}SEzsg_R5dcWP zg8aDKv!rHo@S+#M*^WLvo7^2OT#WMpWTGAfZ%B$l>G%x*{y6CavgG6ID_#KLenWm) z00qJy{7Lj*gnU^bqzwv;y@dQsSlYNz9Log_IkZDZpkYlnsKtkGqsKi7`)KtkQha|OM zjP!{uk%&JiQ-DfQ3j4&66c>ACQI-7)hE`>tsDwqYtZEXD+qSDp%%^xYB@&KRS`n!z zB31=gva0fsaFVJmZU{yLQm?Ej-pRBra#&U;SG8_dd|F^Kr*<`hd#9wNAi=x*_fz+F za5jF70|%ZW2Xaov94_~}+3Uqj{l%g`c|BL}I&uEQ$f-*uZ}F$LeA0KqujiXx#dmr0 zpdsil>!xcVZ>F0Y2b6e7?J0Skk6au)J#fy<(l-{D@%m14%$5CV(M|q_?m2w^!^-xSzjybDNQ=cjJC4_=ToBuIvi#phRL9hRzJ0 zdqQ^?&*$}S^ByL`uzc9BuHVzQHD~2r;JBMq(d*yec`iBrTV&qMil*fvZ`GFMXytP} z4S6_TWuq{UVsO#Kem0tQ3GJn=3BTtP^Cm*g;yL=J<9?l(1=%@CjwdKFLBE?gp8{$D=uM$!*^mX! z=>%9Uv6tSFNgAz`2`5<{q&2Nx*9nWfaWx1l{i@s#>jF~P58X%=2=+^135J4_7KULf zXM7T@=xKNwX%9BfARTg2cn4%aZVFF(%1hy$kOlcEybA=Fp2G7m4GN&JUsl7gXDT!* z1vS_=6*_=MFgz8Co1;1rrIA^6O-Hob=sS&kI*!Fw)}>I2bCTMPJW_v2YZ1R8EO9#F zL2XhdU~L%8NQ_t>^tuu@U$B9PuzAM9rrpA(*TP1#u-Ru}bL4*Q2ou7lFhydcQF!X)7-Gudxy(n530rzW=#J8yu(jv*t+mfWrllh-^+z?_ xgomw7qE9~dNwL=;Ile~}gY#N1+9CX}_YUQh3v6^;u-~afE51{fEz)FT{{in!iR1tP literal 0 HcmV?d00001 diff --git a/test/shaping/data/in-house/tests/vertical.tests b/test/shaping/data/in-house/tests/vertical.tests index b18119225..395881338 100644 --- a/test/shaping/data/in-house/tests/vertical.tests +++ b/test/shaping/data/in-house/tests/vertical.tests @@ -1,3 +1,4 @@ ../fonts/191826b9643e3f124d865d617ae609db6a2ce203.ttf:--direction=t --font-funcs=ft:U+300C:[uni300C.vert=0@-512,-578+0,-1024] ../fonts/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ft:U+0041,U+0042:[gid1=0@-654,-2128+0,-2789|gid2=1@-665,-2125+0,-2789] ../fonts/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ot:U+0041,U+0042:[gid1=0@-654,-1468+0,-2048|gid2=1@-665,-1462+0,-2048] +../fonts/4cbbc461be066fccc611dcc634af6e8cb2705537.ttf:--direction=t --font-funcs=ot:U+FF38:[gid2=0@-500,-867+0,-1000] From 205737acdc268b1c90cf00bde2d2038519a8bf48 Mon Sep 17 00:00:00 2001 From: David Corbett Date: Fri, 12 Oct 2018 16:54:54 -0400 Subject: [PATCH 32/36] [use] Prohibit visually ambiguous vowel sequences --- src/Makefile.am | 7 +- src/Makefile.sources | 1 + src/gen-vowel-constraints.py | 286 ++++++++++++ src/hb-ot-shape-complex-indic.cc | 272 +---------- src/hb-ot-shape-complex-use.cc | 3 +- src/hb-ot-shape-complex-vowel-constraints.hh | 434 ++++++++++++++++++ test/shaping/README.md | 4 +- ...669c8860cbfea13562a6ca0d83130ee571137b.ttf | Bin 0 -> 7184 bytes .../tests/use-vowel-letter-spoofing.tests | 94 ++++ 9 files changed, 827 insertions(+), 274 deletions(-) create mode 100755 src/gen-vowel-constraints.py create mode 100644 src/hb-ot-shape-complex-vowel-constraints.hh create mode 100644 test/shaping/data/in-house/fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf create mode 100644 test/shaping/data/in-house/tests/use-vowel-letter-spoofing.tests diff --git a/src/Makefile.am b/src/Makefile.am index e0ea1c5de..782992d1c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -295,6 +295,7 @@ GENERATORS = \ gen-os2-unicode-ranges.py \ gen-tag-table.py \ gen-use-table.py \ + gen-vowel-constraints.py \ $(NULL) EXTRA_DIST += $(GENERATORS) @@ -316,13 +317,17 @@ use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.tx $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-use-table.cc \ || ($(RM) $(srcdir)/hb-ot-shape-complex-use-table.cc; false) +vowel-constraints: gen-vowel-constraints.py use Scripts.txt + $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.hh \ + || ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.hh; false) + emoji-table: gen-emoji-table.py emoji-data.txt $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \ || ($(RM) $(srcdir)/hb-unicode-emoji-table.hh; false) built-sources: $(BUILT_SOURCES) -.PHONY: unicode-tables arabic-table indic-table tag-table use-table emoji-table built-sources +.PHONY: unicode-tables arabic-table indic-table tag-table use-table vowel-constraints emoji-table built-sources RAGEL_GENERATED = \ $(patsubst %,$(srcdir)/%,$(HB_BASE_RAGEL_GENERATED_sources)) \ diff --git a/src/Makefile.sources b/src/Makefile.sources index eed245bca..b30291054 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -142,6 +142,7 @@ HB_OT_sources = \ hb-ot-shape-complex-use.cc \ hb-ot-shape-complex-use.hh \ hb-ot-shape-complex-use-table.cc \ + hb-ot-shape-complex-vowel-constraints.hh \ hb-ot-shape-complex.hh \ hb-ot-shape-normalize.hh \ hb-ot-shape-normalize.cc \ diff --git a/src/gen-vowel-constraints.py b/src/gen-vowel-constraints.py new file mode 100755 index 000000000..bcb5d27bd --- /dev/null +++ b/src/gen-vowel-constraints.py @@ -0,0 +1,286 @@ +#!/usr/bin/python + +"""Generator of the function to prohibit certain vowel sequences. + +It creates ``preprocess_text_vowel_constraints``, which inserts dotted +circles into sequences prohibited by the USE script development spec. +This function should be used as the ``preprocess_text`` of an +``hb_ot_complex_shaper_t``. + +It also creates the helper function ``_output_with_dotted_circle``. +""" + +from __future__ import absolute_import, division, print_function, unicode_literals + +import collections +try: + from HTMLParser import HTMLParser + def write (s): + print (s.encode ('utf-8'), end='') +except ImportError: + from html.parser import HTMLParser + def write (s): + sys.stdout.flush () + sys.stdout.buffer.write (s.encode ('utf-8')) +import itertools +import io +import sys + +if len (sys.argv) != 3: + print ('usage: ./gen-vowel-constraints.py use Scripts.txt', file=sys.stderr) + sys.exit (1) + +try: + from html import unescape + def html_unescape (parser, entity): + return unescape (entity) +except ImportError: + def html_unescape (parser, entity): + return parser.unescape (entity) + +def expect (condition, message=None): + if not condition: + if message is None: + raise AssertionError + raise AssertionError (message) + +with io.open (sys.argv[2], encoding='utf-8') as f: + scripts_header = [f.readline () for i in range (2)] + scripts = {} + script_order = {} + for line in f: + j = line.find ('#') + if j >= 0: + line = line[:j] + fields = [x.strip () for x in line.split (';')] + if len (fields) == 1: + continue + uu = fields[0].split ('..') + start = int (uu[0], 16) + if len (uu) == 1: + end = start + else: + end = int (uu[1], 16) + script = fields[1] + for u in range (start, end + 1): + scripts[u] = script + if script not in script_order: + script_order[script] = start + +class ConstraintSet (object): + """A set of prohibited code point sequences. + + Args: + constraint (List[int]): A prohibited code point sequence. + + """ + def __init__ (self, constraint): + # Either a list or a dictionary. As a list of code points, it + # represents a prohibited code point sequence. As a dictionary, + # it represents a set of prohibited sequences, where each item + # represents the set of prohibited sequences starting with the + # key (a code point) concatenated with any of the values + # (ConstraintSets). + self._c = constraint + + def add (self, constraint): + """Add a constraint to this set.""" + if not constraint: + return + first = constraint[0] + rest = constraint[1:] + if isinstance (self._c, list): + if constraint == self._c[:len (constraint)]: + self._c = constraint + elif self._c != constraint[:len (self._c)]: + self._c = {self._c[0]: ConstraintSet (self._c[1:])} + if isinstance (self._c, dict): + if first in self._c: + self._c[first].add (rest) + else: + self._c[first] = ConstraintSet (rest) + + def _indent (self, depth): + return (' ' * depth).replace (' ', '\t') + + def __str__ (self, index=0, depth=4): + s = [] + indent = self._indent (depth) + if isinstance (self._c, list): + if len (self._c) == 0: + s.append ('{}matched = true;\n'.format (indent)) + elif len (self._c) == 1: + s.append ('{}matched = 0x{:04X}u == buffer->cur ({}).codepoint;\n'.format (indent, next (iter (self._c)), index or '')) + else: + s.append ('{}if (0x{:04X}u == buffer->cur ({}).codepoint &&\n'.format (indent, self._c[0], index)) + s.append ('{}buffer->idx + {} < count &&\n'.format (self._indent (depth + 2), len (self._c))) + for i, cp in enumerate (self._c[1:], start=1): + s.append ('{}0x{:04X}u == buffer->cur ({}).codepoint{}\n'.format ( + self._indent (depth + 2), cp, index + i, ')' if i == len (self._c) - 1 else ' &&')) + s.append ('{}{{\n'.format (indent)) + for i in range (len (self._c)): + s.append ('{}buffer->next_glyph ();\n'.format (self._indent (depth + 1))) + s.append ('{}buffer->output_glyph (0x25CCu);\n'.format (self._indent (depth + 1))) + s.append ('{}}}\n'.format (indent)) + else: + s.append ('{}switch (buffer->cur ({}).codepoint)\n'.format(indent, index or '')) + s.append ('{}{{\n'.format (indent)) + cases = collections.defaultdict (set) + for first, rest in sorted (self._c.items ()): + cases[rest.__str__ (index + 1, depth + 2)].add (first) + for body, labels in sorted (cases.items (), key=lambda b_ls: sorted (b_ls[1])[0]): + for i, cp in enumerate (sorted (labels)): + if i % 4 == 0: + s.append (self._indent (depth + 1)) + else: + s.append (' ') + s.append ('case 0x{:04X}u:{}'.format (cp, '\n' if i % 4 == 3 else '')) + if len (labels) % 4 != 0: + s.append ('\n') + s.append (body) + s.append ('{}break;\n'.format (self._indent (depth + 2))) + s.append ('{}}}\n'.format (indent)) + return ''.join (s) + +class USESpecParser (HTMLParser): + """A parser for the USE script development spec. + + Attributes: + header (str): The ``updated_at`` timestamp of the spec. + constraints (Mapping[str, ConstraintSet]): A map of script names + to the scripts' prohibited sequences. + """ + def __init__ (self): + HTMLParser.__init__ (self) + self.header = '' + self.constraints = {} + # Whether the next contains the vowel constraints. + self._primed = False + # Whether the parser is in the element with the constraints. + self._in_constraints = False + # The text of the constraints. + self._constraints = '' + + def handle_starttag (self, tag, attrs): + if tag == 'meta': + for attr, value in attrs: + if attr == 'name' and value == 'updated_at': + self.header = self.get_starttag_text () + break + elif tag == 'a': + for attr, value in attrs: + if attr == 'id' and value == 'ivdvconstraints': + self._primed = True + break + elif self._primed and tag == 'code': + self._primed = False + self._in_constraints = True + + def handle_endtag (self, tag): + self._in_constraints = False + + def handle_data (self, data): + if self._in_constraints: + self._constraints += data + + def handle_charref (self, name): + self.handle_data (html_unescape (self, '&#%s;' % name)) + + def handle_entityref (self, name): + self.handle_data (html_unescape (self, '&%s;' % name)) + + def parse (self, filename): + """Parse the USE script development spec. + + Args: + filename (str): The file name of the spec. + """ + with io.open (filename, encoding='utf-8') as f: + self.feed (f.read ()) + expect (self.header, 'No header found') + for line in self._constraints.splitlines (): + constraint = [int (cp, 16) for cp in line.split (';')[0].strip ().split (' ')] + expect (2 <= len (constraint), 'Prohibited sequence is too short: {}'.format (constraint)) + script = scripts[constraint[0]] + if script in self.constraints: + self.constraints[script].add (constraint) + else: + self.constraints[script] = ConstraintSet (constraint) + expect (self.constraints, 'No constraints found') + +use_parser = USESpecParser () +use_parser.parse (sys.argv[1]) + +print ('/* == Start of generated functions == */') +print ('/*') +print (' * The following functions are generated by running:') +print (' *') +print (' * %s use Scripts.txt' % sys.argv[0]) +print (' *') +print (' * on files with these headers:') +print (' *') +print (' * %s' % use_parser.header.strip ()) +for line in scripts_header: + print (' * %s' % line.strip ()) +print (' */') +print () +print ('#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH') +print ('#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH') +print () + +print ('static void') +print ('_output_with_dotted_circle (hb_buffer_t *buffer)') +print ('{') +print (' hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu);') +print (' _hb_glyph_info_reset_continuation (&dottedcircle);') +print () +print (' buffer->next_glyph ();') +print ('}') +print () + +print ('static void') +print ('preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,') +print ('\t\t\t\t hb_buffer_t *buffer,') +print ('\t\t\t\t hb_font_t *font)') +print ('{') +print (' /* UGLY UGLY UGLY business of adding dotted-circle in the middle of') +print (' * vowel-sequences that look like another vowel. Data for each script') +print (' * collected from the USE script development spec.') +print (' *') +print (' * https://github.com/harfbuzz/harfbuzz/issues/1019') +print (' */') +print (' bool processed = false;') +print (' buffer->clear_output ();') +print (' unsigned int count = buffer->len;') +print (' switch ((unsigned) buffer->props.script)') +print (' {') + +for script, constraints in sorted (use_parser.constraints.items (), key=lambda s_c: script_order[s_c[0]]): + print (' case HB_SCRIPT_{}:'.format (script.upper ())) + print (' for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)') + print (' {') + print ('\tbool matched = false;') + write (str (constraints)) + print ('\tbuffer->next_glyph ();') + print ('\tif (matched) _output_with_dotted_circle (buffer);') + print (' }') + print (' processed = true;') + print (' break;') + print () + +print (' default:') +print (' break;') +print (' }') +print (' if (processed)') +print (' {') +print (' if (buffer->idx < count)') +print (' buffer->next_glyph ();') +print (' if (likely (buffer->successful))') +print (' buffer->swap_buffers ();') +print (' }') +print ('}') + +print () +print ('#endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */') +print () +print ('/* == End of generated functions == */') diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index f1ae303ad..092ac6846 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -25,6 +25,7 @@ */ #include "hb-ot-shape-complex-indic.hh" +#include "hb-ot-shape-complex-vowel-constraints.hh" #include "hb-ot-layout.hh" @@ -331,275 +332,6 @@ data_destroy_indic (void *data) free (data); } -static void -_output_with_dotted_circle (hb_buffer_t *buffer) -{ - hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu); - _hb_glyph_info_reset_continuation (&dottedcircle); - - buffer->next_glyph (); -} - -static void -preprocess_text_indic (const hb_ot_shape_plan_t *plan, - hb_buffer_t *buffer, - hb_font_t *font) -{ - /* UGLY UGLY UGLY business of adding dotted-circle in the middle of - * vowel-sequences that look like another vowel. Data for each script - * collected from Unicode 11 book, tables named "Vowel Letters" with - * "Use" and "Do Not Use" columns. - * - * https://github.com/harfbuzz/harfbuzz/issues/1019 - */ - bool processed = false; - buffer->clear_output (); - unsigned int count = buffer->len; - switch ((unsigned) buffer->props.script) - { - case HB_SCRIPT_DEVANAGARI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0905u: - switch (buffer->cur(1).codepoint) - { - case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u: - case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu: - case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u: - matched = true; - break; - } - break; - case 0x0906u: - switch (buffer->cur(1).codepoint) - { - case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u: - case 0x0948u: - matched = true; - break; - } - break; - case 0x0909u: - switch (buffer->cur(1).codepoint) - { - case 0x0941u: - matched = true; - break; - } - break; - case 0x090Fu: - switch (buffer->cur(1).codepoint) - { - case 0x0945u: case 0x0946u: case 0x0947u: - matched = true; - break; - } - break; - case 0x0930u: - if (0x094Du == buffer->cur(1).codepoint && - buffer->idx + 2 < count && - 0x0907u == buffer->cur(2).codepoint) - { - buffer->next_glyph (); - buffer->next_glyph (); - buffer->output_glyph (0x25CCu); - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_BENGALI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0985u: - matched = 0x09BE == buffer->cur(1).codepoint; - break; - case 0x098Bu: - matched = 0x09C3 == buffer->cur(1).codepoint; - break; - case 0x098Cu: - matched = 0x09E2 == buffer->cur(1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_GURMUKHI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0A05u: - switch (buffer->cur(1).codepoint) - { - case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu: - matched = true; - break; - } - break; - case 0x0A72u: - switch (buffer->cur(1).codepoint) - { - case 0x0A3Fu: case 0x0A40u: case 0x0A47u: - matched = true; - break; - } - break; - case 0x0A73u: - switch (buffer->cur(1).codepoint) - { - case 0x0A41u: case 0x0A42u: case 0x0A4Bu: - matched = true; - break; - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_GUJARATI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0A85u: - switch (buffer->cur(1).codepoint) - { - case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u: - case 0x0AC9u: case 0x0ACBu: case 0x0ACCu: - matched = true; - break; - } - break; - case 0x0AC5u: - matched = 0x0ABE == buffer->cur(1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_ORIYA: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0B05u: - matched = 0x0B3E == buffer->cur(1).codepoint; - break; - case 0x0B0Fu: case 0x0B13u: - matched = 0x0B57 == buffer->cur(1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_TELUGU: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0C12u: - switch (buffer->cur(1).codepoint) - { - case 0x0C4Cu: case 0x0C55u: - matched = true; - break; - } - break; - case 0x0C3Fu: case 0x0C46u: case 0xC4Au: - matched = 0x0C55 == buffer->cur(1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_KANNADA: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0C89u: case 0x0C8Bu: - matched = 0x0CBE == buffer->cur(1).codepoint; - break; - case 0x0C92u: - matched = 0x0CCC == buffer->cur(1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_MALAYALAM: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur().codepoint) - { - case 0x0D07u: case 0x0D09u: - matched = 0x0D57 == buffer->cur(1).codepoint; - break; - case 0x0D0Eu: - matched = 0x0D46 == buffer->cur(1).codepoint; - break; - case 0x0D12u: - switch (buffer->cur(1).codepoint) - { - case 0x0D3Eu: case 0x0D57u: - matched = true; - break; - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - default: - break; - } - if (processed) - { - if (buffer->idx < count) - buffer->next_glyph (); - if (likely (buffer->successful)) - buffer->swap_buffers (); - } -} - static indic_position_t consonant_position_from_face (const indic_shape_plan_t *indic_plan, const hb_codepoint_t consonant, @@ -1884,7 +1616,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = override_features_indic, data_create_indic, data_destroy_indic, - preprocess_text_indic, + preprocess_text_vowel_constraints, nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, decompose_indic, diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index f9a580ca2..8c44fe016 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -28,6 +28,7 @@ #include "hb-ot-shape-complex-use.hh" #include "hb-ot-shape-complex-arabic.hh" +#include "hb-ot-shape-complex-vowel-constraints.hh" /* buffer var allocations */ #define use_category() complex_var_u8_0() @@ -591,7 +592,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use = nullptr, /* override_features */ data_create_use, data_destroy_use, - nullptr, /* preprocess_text */ + preprocess_text_vowel_constraints, nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, nullptr, /* decompose */ diff --git a/src/hb-ot-shape-complex-vowel-constraints.hh b/src/hb-ot-shape-complex-vowel-constraints.hh new file mode 100644 index 000000000..1b07c2f40 --- /dev/null +++ b/src/hb-ot-shape-complex-vowel-constraints.hh @@ -0,0 +1,434 @@ +/* == Start of generated functions == */ +/* + * The following functions are generated by running: + * + * ./gen-vowel-constraints.py use Scripts.txt + * + * on files with these headers: + * + * + * # Scripts-11.0.0.txt + * # Date: 2018-02-21, 05:34:31 GMT + */ + +#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH +#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH + +static void +_output_with_dotted_circle (hb_buffer_t *buffer) +{ + hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu); + _hb_glyph_info_reset_continuation (&dottedcircle); + + buffer->next_glyph (); +} + +static void +preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) +{ + /* UGLY UGLY UGLY business of adding dotted-circle in the middle of + * vowel-sequences that look like another vowel. Data for each script + * collected from the USE script development spec. + * + * https://github.com/harfbuzz/harfbuzz/issues/1019 + */ + bool processed = false; + buffer->clear_output (); + unsigned int count = buffer->len; + switch ((unsigned) buffer->props.script) + { + case HB_SCRIPT_DEVANAGARI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0905u: + switch (buffer->cur (1).codepoint) + { + case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u: + case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu: + case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u: + matched = true; + break; + } + break; + case 0x0906u: + switch (buffer->cur (1).codepoint) + { + case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u: + case 0x0948u: + matched = true; + break; + } + break; + case 0x0909u: + matched = 0x0941u == buffer->cur (1).codepoint; + break; + case 0x090Fu: + switch (buffer->cur (1).codepoint) + { + case 0x0945u: case 0x0946u: case 0x0947u: + matched = true; + break; + } + break; + case 0x0930u: + if (0x094Du == buffer->cur (1).codepoint && + buffer->idx + 2 < count && + 0x0907u == buffer->cur (2).codepoint) + { + buffer->next_glyph (); + buffer->next_glyph (); + buffer->output_glyph (0x25CCu); + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_BENGALI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0985u: + matched = 0x09BEu == buffer->cur (1).codepoint; + break; + case 0x098Bu: + matched = 0x09C3u == buffer->cur (1).codepoint; + break; + case 0x098Cu: + matched = 0x09E2u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_GURMUKHI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0A05u: + switch (buffer->cur (1).codepoint) + { + case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu: + matched = true; + break; + } + break; + case 0x0A72u: + switch (buffer->cur (1).codepoint) + { + case 0x0A3Fu: case 0x0A40u: case 0x0A47u: + matched = true; + break; + } + break; + case 0x0A73u: + switch (buffer->cur (1).codepoint) + { + case 0x0A41u: case 0x0A42u: case 0x0A4Bu: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_GUJARATI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0A85u: + switch (buffer->cur (1).codepoint) + { + case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u: + case 0x0AC9u: case 0x0ACBu: case 0x0ACCu: + matched = true; + break; + } + break; + case 0x0AC5u: + matched = 0x0ABEu == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_ORIYA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0B05u: + matched = 0x0B3Eu == buffer->cur (1).codepoint; + break; + case 0x0B0Fu: case 0x0B13u: + matched = 0x0B57u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_TELUGU: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0C12u: + switch (buffer->cur (1).codepoint) + { + case 0x0C4Cu: case 0x0C55u: + matched = true; + break; + } + break; + case 0x0C3Fu: case 0x0C46u: case 0x0C4Au: + matched = 0x0C55u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_KANNADA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0C89u: case 0x0C8Bu: + matched = 0x0CBEu == buffer->cur (1).codepoint; + break; + case 0x0C92u: + matched = 0x0CCCu == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_MALAYALAM: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0D07u: case 0x0D09u: + matched = 0x0D57u == buffer->cur (1).codepoint; + break; + case 0x0D0Eu: + matched = 0x0D46u == buffer->cur (1).codepoint; + break; + case 0x0D12u: + switch (buffer->cur (1).codepoint) + { + case 0x0D3Eu: case 0x0D57u: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_SINHALA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0D85u: + switch (buffer->cur (1).codepoint) + { + case 0x0DCFu: case 0x0DD0u: case 0x0DD1u: + matched = true; + break; + } + break; + case 0x0D8Bu: case 0x0D8Fu: case 0x0D94u: + matched = 0x0DDFu == buffer->cur (1).codepoint; + break; + case 0x0D8Du: + matched = 0x0DD8u == buffer->cur (1).codepoint; + break; + case 0x0D91u: + switch (buffer->cur (1).codepoint) + { + case 0x0DCAu: case 0x0DD9u: case 0x0DDAu: case 0x0DDCu: + case 0x0DDDu: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_BRAHMI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11005u: + matched = 0x11038u == buffer->cur (1).codepoint; + break; + case 0x1100Bu: + matched = 0x1103Eu == buffer->cur (1).codepoint; + break; + case 0x1100Fu: + matched = 0x11042u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_KHUDAWADI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x112B0u: + switch (buffer->cur (1).codepoint) + { + case 0x112E0u: case 0x112E5u: case 0x112E6u: case 0x112E7u: + case 0x112E8u: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_TIRHUTA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11481u: + matched = 0x114B0u == buffer->cur (1).codepoint; + break; + case 0x1148Bu: case 0x1148Du: + matched = 0x114BAu == buffer->cur (1).codepoint; + break; + case 0x114AAu: + switch (buffer->cur (1).codepoint) + { + case 0x114B5u: case 0x114B6u: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_MODI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11600u: case 0x11601u: + switch (buffer->cur (1).codepoint) + { + case 0x11639u: case 0x1163Au: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_TAKRI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11680u: + switch (buffer->cur (1).codepoint) + { + case 0x116ADu: case 0x116B4u: case 0x116B5u: + matched = true; + break; + } + break; + case 0x11686u: + matched = 0x116B2u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + default: + break; + } + if (processed) + { + if (buffer->idx < count) + buffer->next_glyph (); + if (likely (buffer->successful)) + buffer->swap_buffers (); + } +} + +#endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */ + +/* == End of generated functions == */ diff --git a/test/shaping/README.md b/test/shaping/README.md index 99498e60c..f386fb965 100644 --- a/test/shaping/README.md +++ b/test/shaping/README.md @@ -25,10 +25,10 @@ what this does is: * If the outputs differ, recording fails. Otherwise, it will move the subset font file into `data/in-house/fonts` and name it after its hash, and print out the test case input, which you can then redirect - to an existing or new test file in `data/in-house/tests` using `-o=`, + to an existing or new test file in `data/in-house/tests` using `-o`, e.g.: ```sh -$ ./hb-unicode-encode 41 42 43 627 | ./record-test.sh -o=data/in-house/tests/test-name.test ../../util/hb-shape font.ttf +$ ./hb-unicode-encode 41 42 43 627 | ./record-test.sh -o data/in-house/tests/test-name.test ../../util/hb-shape font.ttf ``` If you created a new test file, add it to `data/in-house/Makefile.sources` diff --git a/test/shaping/data/in-house/fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf b/test/shaping/data/in-house/fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7d488a31505566033060c724120324bc90b5463e GIT binary patch literal 7184 zcmeHLYitzP6+UNnW?|Ml7>ok}5@HCXBv7*UuGecIhS?e01k5A6Oo#(syv8=z#__AB zsv1WrX;Yvi2vzi{D1E3(l{Q5rLL{YCQj!2}(^M#-6iSMeDry5scfH%FMY!L6C`#4- zt5j9$?&_QGo;&xR^W8Id?%Ww-BAP(M6rkpMzqXDh(IC-`WvHD}zjn=ff3RTy_GZ{+ z_3Jk#Pdt0%Y1l)skE~gLcLf=#6w$;|*v&0nsh-A}KRy7vpUAr2mg?&n8-r(>k-+)! zZJm2|eCr!!S5SVRC_K{Mno3W+x*`t&ucI#Bj*7q^OoOQSL)dfLyZVQw(bO<(m~^dk zcT4Kz))(gxIp>All^W`yA+lf}hh5g4>T2chg{DDz59~ z@H+zGP0hr6i}1oC{nDd>FW4hRx~bJTq?k z<~p<4>^47Ve%U-?e&0N1zHI*5{Jr_U`8R94HN~1^Rancc)mD?W(;BiKvkqHNThCc1 ztr6>j^`4avn!%D_S#V)+NpMAQb8v^w0J6|teEr+oikIZ5$drkA`|88ZqVV?BFJAh1 zXM=Z9!ds^J;aQ*lKl;m=f-w^{sr>L0|1x)&O#TSTiB@yK$~IYi z0~n%Z(2=mm*|uG5N9@IRjqTd2>@{|yz1QAvzhYkrS)pWTd8i@O7up*-89Eg@9U3XJ zii(RS7u6IshD*Xr!*$^m;fC=U^5~s$ga~hq!&OYaWbI^Ix zIqaNq-gGWFmz>LUNAT@}Y)eO8BqP@%@+L&yrz6*d>O(6-y*l!1p|k%{1)72B3mpPjYbk`dp(M(;g6o0hD9;A31R7Ard=K>keJI}nMl1oE2R^AlcY;qT zVD+ZZYrtu=nGZe-h&ys2hJcs?gd7wh9|BYko~%F>VCWH`C>Y}tpcuZrl_*dpc&P%# z!F38$1zw?m=LdzMU4W{=8x;uo4nM9y$a@&M5}+mELke^c7~>Kk=m>m-0X zoE%&y0m8L%CMXc{=s>3cd0_MxARi2!0#pmem;~^YBWJGyA@>fn2oSD;gKv@obT9az z0%3g4lM1vFd{}`nPUnmQVXioD0B@r2YVdjB0?PM+F9MfP-T=O=K$u5!F+KrmB%WwV z5N!q*Nf6x+E|wtL0!~N}Jpite!0HT6N)SCrT=JX*(N^#~5=7g;?*ihUX(ldxM1t@% z<5Jwo08uOWfCSMF@G}xbZD9BW@W=!|54?bK2l#{p(JtaCxcjDvb-5E<4d9wnH+Wcr zu&3ZDk4X?c1b$Y6s26-xf~XIC40s-W`vHSyiq+nk!<%qiZ^Eu7|7-ob6$&Ki#ofG{d-x&lk|kT9>PJxmCJdm5SqP9d1(l z_mnQzQ#xHwjo0mwsr4lzN>{R6`AurQNj+Y#T*dXYeoyDs)A{qXKCe>6 z_Yx|er}N`g>;77&r{nt(rPGh7_I^Z-!`JbAt;5&xe67dVRdv0h`Z8fJSmmMlQG#ciRUIU_J@YtF@^QIBrL|tC00y<5cUK! ziT%2U4S3@aYaNL_rTnS$y);b4@_f_w?l$b0xA&&nsVUt$h;rM`UU3`{$6eiN9J@NZ z#Bq1JgPL~t?m@Y)qdP5+=+&Rv)r(_mC+hnI{k literal 0 HcmV?d00001 diff --git a/test/shaping/data/in-house/tests/use-vowel-letter-spoofing.tests b/test/shaping/data/in-house/tests/use-vowel-letter-spoofing.tests new file mode 100644 index 000000000..45cf80e8a --- /dev/null +++ b/test/shaping/data/in-house/tests/use-vowel-letter-spoofing.tests @@ -0,0 +1,94 @@ +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+093A:[uni0905=0+500|uni25CC=0+500|uni093A=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+093B:[uni0905=0+500|uni25CC=0+500|uni093B=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+093E:[uni0905=0+500|uni25CC=0+500|uni093E=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+0945:[uni0905=0+500|uni25CC=0+500|uni0945=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+0946:[uni0905=0+500|uni25CC=0+500|uni0946=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+0949:[uni0905=0+500|uni25CC=0+500|uni0949=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+094A:[uni0905=0+500|uni25CC=0+500|uni094A=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+094B:[uni0905=0+500|uni25CC=0+500|uni094B=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+094C:[uni0905=0+500|uni25CC=0+500|uni094C=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+094F:[uni0905=0+500|uni25CC=0+500|uni094F=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+0956:[uni0905=0+500|uni25CC=0+500|uni0956=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+0957:[uni0905=0+500|uni25CC=0+500|uni0957=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0906,U+093A:[uni0906=0+500|uni25CC=0+500|uni093A=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0906,U+0945:[uni0906=0+500|uni25CC=0+500|uni0945=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0906,U+0946:[uni0906=0+500|uni25CC=0+500|uni0946=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0906,U+0947:[uni0906=0+500|uni25CC=0+500|uni0947=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0906,U+0948:[uni0906=0+500|uni25CC=0+500|uni0948=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0909,U+0941:[uni0909=0+500|uni25CC=0+500|uni0941=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+090F,U+0945:[uni090F=0+500|uni25CC=0+500|uni0945=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+090F,U+0946:[uni090F=0+500|uni25CC=0+500|uni0946=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+090F,U+0947:[uni090F=0+500|uni25CC=0+500|uni0947=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0930,U+094D,U+0907:[uni0930=0+500|uni094D=0+500|uni25CC=2+500|uni0907=2+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0985,U+09BE:[uni0985=0+500|uni25CC=0+500|.notdef=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+098B,U+09C3:[uni098B=0+500|uni25CC=0+500|uni09C3=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+098C,U+09E2:[uni098C=0+500|uni25CC=0+500|uni09E2=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A05,U+0A3E:[uni0A05=0+500|uni25CC=0+500|uni0A3E=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A05,U+0A48:[uni0A05=0+500|uni25CC=0+500|uni0A48=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A05,U+0A4C:[uni0A05=0+500|uni25CC=0+500|uni0A4C=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A72,U+0A3F:[uni0A72=0+500|uni0A3F=0+500|uni25CC=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A72,U+0A40:[uni0A72=0+500|uni25CC=0+500|uni0A40=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A72,U+0A47:[uni0A72=0+500|uni25CC=0+500|uni0A47=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A73,U+0A41:[uni0A73=0+500|uni25CC=0+500|uni0A41=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A73,U+0A42:[uni0A73=0+500|uni25CC=0+500|uni0A42=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A73,U+0A4B:[uni0A73=0+500|uni25CC=0+500|uni0A4B=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0ABE,U+0AC5:[uni0A85=0+500|uni25CC=0+500|uni0ABE=0+500|uni25CC=0+500|uni0AC5=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0ABE,U+0AC8:[uni0A85=0+500|uni25CC=0+500|uni0ABE=0+500|uni25CC=0+500|uni0AC8=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0ABE:[uni0A85=0+500|uni25CC=0+500|uni0ABE=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0AC5:[uni0A85=0+500|uni25CC=0+500|uni0AC5=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0AC7:[uni0A85=0+500|uni25CC=0+500|uni0AC7=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0AC8:[uni0A85=0+500|uni25CC=0+500|uni0AC8=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0AC9:[uni0A85=0+500|uni25CC=0+500|uni0AC9=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0ACB:[uni0A85=0+500|uni25CC=0+500|uni0ACB=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0ACC:[uni0A85=0+500|uni25CC=0+500|uni0ACC=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0AC5,U+0ABE:[uni25CC=0+500|uni0AC5=0+500|uni25CC=0+500|uni0ABE=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0B05,U+0B3E:[uni0B05=0+500|uni25CC=0+500|uni0B3E=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0B0F,U+0B57:[uni0B0F=0+500|uni25CC=0+500|uni0B57=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0B13,U+0B57:[uni0B13=0+500|uni25CC=0+500|uni0B57=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C12,U+0C4C:[uni0C12=0+500|uni25CC=0+500|uni0C4C=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C12,U+0C55:[uni0C12=0+500|uni25CC=0+500|uni0C55=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C3F,U+0C55:[uni25CC=0+500|uni0C3F=0+500|uni25CC=0+500|uni0C55=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C46,U+0C55:[uni25CC=0+500|uni0C46=0+500|uni25CC=0+500|uni0C55=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C4A,U+0C55:[uni25CC=0+500|uni0C4A=0+500|uni25CC=0+500|uni0C55=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C89,U+0CBE:[uni0C89=0+500|uni25CC=0+500|uni0CBE=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C8B,U+0CBE:[uni0C8B=0+500|uni25CC=0+500|uni0CBE=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C92,U+0CCC:[uni0C92=0+500|uni25CC=0+500|uni0CCC=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D07,U+0D57:[uni0D07=0+500|uni25CC=0+500|uni0D57=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D09,U+0D57:[uni0D09=0+500|uni25CC=0+500|uni0D57=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D0E,U+0D46:[uni0D0E=0+500|uni0D46=0+500|uni25CC=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D12,U+0D3E:[uni0D12=0+500|uni25CC=0+500|uni0D3E=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D12,U+0D57:[uni0D12=0+500|uni25CC=0+500|uni0D57=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D85,U+0DCF:[uni0D85=0+500|uni25CC=0+500|uni0DCF=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D85,U+0DD0:[uni0D85=0+500|uni25CC=0+500|uni0DD0=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D85,U+0DD1:[uni0D85=0+500|uni25CC=0+500|uni0DD1=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D8B,U+0DDF:[uni0D8B=0+500|uni25CC=0+500|uni0DDF=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D8D,U+0DD8:[uni0D8D=0+500|uni25CC=0+500|uni0DD8=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D8F,U+0DDF:[uni0D8F=0+500|uni25CC=0+500|uni0DDF=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DCA:[uni0D91=0+500|uni25CC=0+500|uni0DCA=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DD9:[uni0D91=0+500|uni0DD9=0+500|uni25CC=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DDA:[uni0D91=0+500|uni0DD9=0+500|uni25CC=0+500|uni0DCA=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DDC:[uni0D91=0+500|uni0DD9=0+500|uni25CC=0+500|uni0DCF=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DDD:[uni0D91=0+500|uni0DD9=0+500|uni25CC=0+500|uni0DCF=0+500|uni0DCA=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DDD:[uni0D91=0+500|uni0DD9=0+500|uni25CC=0+500|uni0DCF=0+500|uni0DCA=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D94,U+0DDF:[uni0D94=0+500|uni25CC=0+500|uni0DDF=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11005,U+11038:[u11005=0+500|uni25CC=0+500|u11038=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+1100B,U+1103E:[u1100B=0+500|uni25CC=0+500|u1103E=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+1100F,U+11042:[u1100F=0+500|uni25CC=0+500|u11042=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+112B0,U+112E0:[u112B0=0+500|uni25CC=0+500|u112E0=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+112B0,U+112E5:[u112B0=0+500|uni25CC=0+500|u112E5=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+112B0,U+112E6:[u112B0=0+500|uni25CC=0+500|u112E6=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+112B0,U+112E7:[u112B0=0+500|uni25CC=0+500|u112E7=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+112B0,U+112E8:[u112B0=0+500|uni25CC=0+500|u112E8=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11481,U+114B0:[u11481=0+500|uni25CC=0+500|u114B0=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+1148B,U+114BA:[u1148B=0+500|uni25CC=0+500|u114BA=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+1148D,U+114BA:[u1148D=0+500|uni25CC=0+500|u114BA=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+114AA,U+114B5:[u114AA=0+500|uni25CC=0+500|u114B5=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+114AA,U+114B6:[u114AA=0+500|uni25CC=0+500|u114B6=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11600,U+11639:[u11600=0+500|uni25CC=0+500|u11639=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11600,U+1163A:[u11600=0+500|uni25CC=0+500|u1163A=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11601,U+11639:[u11601=0+500|uni25CC=0+500|u11639=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11601,U+1163A:[u11601=0+500|uni25CC=0+500|u1163A=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11680,U+116AD:[u11680=0+500|uni25CC=0+500|u116AD=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11680,U+116B4:[u11680=0+500|uni25CC=0+500|u116B4=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11680,U+116B5:[u11680=0+500|uni25CC=0+500|u116B5=0+500] +../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11686,U+116B2:[u11686=0+500|uni25CC=0+500|u116B2=0+500] From 6d40eb8372a2c74a6e1294b44a2b19c99d11e7da Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 23 Oct 2018 02:51:42 -0700 Subject: [PATCH 33/36] Touch up on previous commit https://github.com/harfbuzz/harfbuzz/pull/1273 --- src/HBIndicVowelConstraints.txt | 97 ++++ src/Makefile.am | 6 +- src/Makefile.sources | 1 + src/gen-vowel-constraints.py | 124 ++--- src/hb-ot-shape-complex-indic.cc | 10 +- src/hb-ot-shape-complex-use.cc | 11 +- src/hb-ot-shape-complex-vowel-constraints.cc | 433 ++++++++++++++++++ src/hb-ot-shape-complex-vowel-constraints.hh | 447 ++----------------- 8 files changed, 606 insertions(+), 523 deletions(-) create mode 100644 src/HBIndicVowelConstraints.txt create mode 100644 src/hb-ot-shape-complex-vowel-constraints.cc diff --git a/src/HBIndicVowelConstraints.txt b/src/HBIndicVowelConstraints.txt new file mode 100644 index 000000000..146ae1cb8 --- /dev/null +++ b/src/HBIndicVowelConstraints.txt @@ -0,0 +1,97 @@ +# Copied from https://docs.microsoft.com/en-us/typography/script-development/use +# On October 23, 2018; with documentd dated 02/07/2018. + + 0905 0946 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN SHORT E + 0905 093E ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AA + 0930 094D 0907 ; # DEVANAGARI LETTER RA, DEVANAGARI SIGN VIRAMA, DEVANAGARI LETTER I + 0909 0941 ; # DEVANAGARI LETTER U, DEVANAGARI VOWEL SIGN U + 090F 0945 ; # DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN CANDRA E + 090F 0946 ; # DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN SHORT E + 090F 0947 ; # DEVANAGARI LETTER E, DEVANAGARI VOWEL SIGN E + 0905 0949 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN CANDRA O + 0906 0945 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN CANDRA E + 0905 094A ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN SHORT O + 0906 0946 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN SHORT E + 0905 094B ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN O + 0906 0947 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN E + 0905 094C ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AU + 0906 0948 ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN AI + 0905 0945 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN CANDRA E + 0905 093A ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN OE + 0905 093B ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN OOE + 0906 093A ; # DEVANAGARI LETTER AA, DEVANAGARI VOWEL SIGN OE + 0905 094F ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN AW + 0905 0956 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN UE + 0905 0957 ; # DEVANAGARI LETTER A, DEVANAGARI VOWEL SIGN UUE + 0985 09BE ; # BENGALI LETTER A, BENGALI VOWEL SIGN AA + 098B 09C3 ; # BENGALI LETTER VOCALIC R, BENGALI VOWEL SIGN VOCALIC R + 098C 09E2 ; # BENGALI LETTER VOCALIC L, BENGALI VOWEL SIGN VOCALIC L + 0A05 0A3E ; # GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AA + 0A72 0A3F ; # GURMUKHI IRI, GURMUKHI VOWEL SIGN I + 0A72 0A40 ; # GURMUKHI IRI, GURMUKHI VOWEL SIGN II + 0A73 0A41 ; # GURMUKHI URA, GURMUKHI VOWEL SIGN U + 0A73 0A42 ; # GURMUKHI URA, GURMUKHI VOWEL SIGN UU + 0A72 0A47 ; # GURMUKHI IRI, GURMUKHI VOWEL SIGN EE + 0A05 0A48 ; # GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AI + 0A73 0A4B ; # GURMUKHI URA, GURMUKHI VOWEL SIGN OO + 0A05 0A4C ; # GURMUKHI LETTER A, GURMUKHI VOWEL SIGN AU + 0A85 0ABE ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AA + 0A85 0AC5 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN CANDRA E + 0A85 0AC7 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN E + 0A85 0AC8 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AI + 0A85 0AC9 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN CANDRA O + 0A85 0ACB ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN O + 0A85 0ABE 0AC5 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AA, GUJARATI VOWEL SIGN CANDRA E + 0A85 0ACC ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AU + 0A85 0ABE 0AC8 ; # GUJARATI LETTER A, GUJARATI VOWEL SIGN AA, GUJARATI VOWEL SIGN AI + 0AC5 0ABE ; # GUJARATI VOWEL SIGN CANDRA E, GUJARATI VOWEL SIGN AA + 0B05 0B3E ; # ORIYA LETTER A, ORIYA VOWEL SIGN AA + 0B0F 0B57 ; # ORIYA LETTER E, ORIYA AU LENGTH MARK + 0B13 0B57 ; # ORIYA LETTER O, ORIYA AU LENGTH MARK + 0C12 0C55 ; # TELUGU LETTER O, TELUGU LENGTH MARK + 0C12 0C4C ; # TELUGU LETTER O, TELUGU VOWEL SIGN AU + 0C3F 0C55 ; # TELUGU VOWEL SIGN I, TELUGU LENGTH MARK + 0C46 0C55 ; # TELUGU VOWEL SIGN E, TELUGU LENGTH MARK + 0C4A 0C55 ; # TELUGU VOWEL SIGN O, TELUGU LENGTH MARK + 0C89 0CBE ; # KANNADA LETTER U, KANNADA VOWEL SIGN AA + 0C92 0CCC ; # KANNADA LETTER O, KANNADA VOWEL SIGN AU + 0C8B 0CBE ; # KANNADA LETTER VOCALIC R, KANNADA VOWEL SIGN AA + 0D07 0D57 ; # MALAYALAM LETTER I, MALAYALAM AU LENGTH MARK + 0D09 0D57 ; # MALAYALAM LETTER U, MALAYALAM AU LENGTH MARK + 0D0E 0D46 ; # MALAYALAM LETTER E, MALAYALAM VOWEL SIGN E + 0D12 0D3E ; # MALAYALAM LETTER O, MALAYALAM VOWEL SIGN AA + 0D12 0D57 ; # MALAYALAM LETTER O, MALAYALAM AU LENGTH MARK + 0D85 0DCF ; # SINHALA LETTER AYANNA, SINHALA VOWEL SIGN AELA-PILLA + 0D85 0DD0 ; # SINHALA LETTER AYANNA, SINHALA VOWEL SIGN KETTI AEDA-PILLA + 0D85 0DD1 ; # SINHALA LETTER AYANNA, SINHALA VOWEL SIGN DIGA AEDA-PILLA + 0D8B 0DDF ; # SINHALA LETTER UYANNA, SINHALA VOWEL SIGN GAYANUKITTA + 0D8D 0DD8 ; # SINHALA LETTER IRUYANNA, SINHALA VOWEL SIGN GAETTA-PILLA + 0D8F 0DDF ; # SINHALA LETTER ILUYANNA, SINHALA VOWEL SIGN GAYANUKITTA + 0D91 0DCA ; # SINHALA LETTER EYANNA, SINHALA SIGN AL-LAKUNA + 0D91 0DD9 ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA + 0D91 0DDA ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN DIGA KOMBUVA + 0D91 0DDC ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA + 0D91 0DDD ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA + 0D91 0DDD ; # SINHALA LETTER EYANNA, SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA + 0D94 0DDF ; # SINHALA LETTER OYANNA, SINHALA VOWEL SIGN GAYANUKITTA + 11005 11038 ; # BRAHMI LETTER A, BRAHMI VOWEL SIGN AA + 1100B 1103E ; # BRAHMI LETTER VOCALIC R, BRAHMI VOWEL SIGN VOCALIC R + 1100F 11042 ; # BRAHMI LETTER E, BRAHMI VOWEL SIGN E + 11680 116AD ; # TAKRI LETTER A, TAKRI VOWEL SIGN AA + 11686 116B2 ; # TAKRI LETTER E, TAKRI VOWEL SIGN E + 11680 116B4 ; # TAKRI LETTER A, TAKRI VOWEL SIGN O + 11680 116B5 ; # TAKRI LETTER A, TAKRI VOWEL SIGN AU + 112B0 112E0 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN AA + 112B0 112E5 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN E + 112B0 112E6 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN AI + 112B0 112E7 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN O + 112B0 112E8 ; # KHUDAWADI LETTER A, KHUDAWADI VOWEL SIGN AU + 11481 114B0 ; # TIRHUTA LETTER A, TIRHUTA VOWEL SIGN AA + 114AA 114B5 ; # TIRHUTA LETTER LA, TIRHUTA VOWEL SIGN VOCALIC R + 114AA 114B6 ; # TIRHUTA LETTER LA, TIRHUTA VOWEL SIGN VOCALIC RR + 1148B 114BA ; # TIRHUTA LETTER E, TIRHUTA VOWEL SIGN SHORT E + 1148D 114BA ; # TIRHUTA LETTER O, TIRHUTA VOWEL SIGN SHORT E + 11600 11639 ; # MODI LETTER A, MODI VOWEL SIGN E + 11600 1163A ; # MODI LETTER A, MODI VOWEL SIGN AI + 11601 11639 ; # MODI LETTER AA, MODI VOWEL SIGN E + 11601 1163A ; # MODI LETTER AA, MODI VOWEL SIGN AI diff --git a/src/Makefile.am b/src/Makefile.am index 782992d1c..ac03890b3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -317,9 +317,9 @@ use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.tx $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-use-table.cc \ || ($(RM) $(srcdir)/hb-ot-shape-complex-use-table.cc; false) -vowel-constraints: gen-vowel-constraints.py use Scripts.txt - $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.hh \ - || ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.hh; false) +vowel-constraints: gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt + $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc \ + || ($(RM) $(srcdir)/hb-ot-shape-complex-vowel-constraints.cc; false) emoji-table: gen-emoji-table.py emoji-data.txt $(AM_V_GEN) $(builddir)/$^ > $(srcdir)/hb-unicode-emoji-table.hh \ diff --git a/src/Makefile.sources b/src/Makefile.sources index b30291054..72968aee9 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -142,6 +142,7 @@ HB_OT_sources = \ hb-ot-shape-complex-use.cc \ hb-ot-shape-complex-use.hh \ hb-ot-shape-complex-use-table.cc \ + hb-ot-shape-complex-vowel-constraints.cc \ hb-ot-shape-complex-vowel-constraints.hh \ hb-ot-shape-complex.hh \ hb-ot-shape-normalize.hh \ diff --git a/src/gen-vowel-constraints.py b/src/gen-vowel-constraints.py index bcb5d27bd..19629abeb 100755 --- a/src/gen-vowel-constraints.py +++ b/src/gen-vowel-constraints.py @@ -2,12 +2,10 @@ """Generator of the function to prohibit certain vowel sequences. -It creates ``preprocess_text_vowel_constraints``, which inserts dotted +It creates ``_hb_preprocess_text_vowel_constraints``, which inserts dotted circles into sequences prohibited by the USE script development spec. This function should be used as the ``preprocess_text`` of an ``hb_ot_complex_shaper_t``. - -It also creates the helper function ``_output_with_dotted_circle``. """ from __future__ import absolute_import, division, print_function, unicode_literals @@ -27,23 +25,9 @@ import io import sys if len (sys.argv) != 3: - print ('usage: ./gen-vowel-constraints.py use Scripts.txt', file=sys.stderr) + print ('usage: ./gen-vowel-constraints.py HBIndicVowelConstraints.txt Scripts.txt', file=sys.stderr) sys.exit (1) -try: - from html import unescape - def html_unescape (parser, entity): - return unescape (entity) -except ImportError: - def html_unescape (parser, entity): - return parser.unescape (entity) - -def expect (condition, message=None): - if not condition: - if message is None: - raise AssertionError - raise AssertionError (message) - with io.open (sys.argv[2], encoding='utf-8') as f: scripts_header = [f.readline () for i in range (2)] scripts = {} @@ -142,74 +126,22 @@ class ConstraintSet (object): s.append ('{}}}\n'.format (indent)) return ''.join (s) -class USESpecParser (HTMLParser): - """A parser for the USE script development spec. - - Attributes: - header (str): The ``updated_at`` timestamp of the spec. - constraints (Mapping[str, ConstraintSet]): A map of script names - to the scripts' prohibited sequences. - """ - def __init__ (self): - HTMLParser.__init__ (self) - self.header = '' - self.constraints = {} - # Whether the next contains the vowel constraints. - self._primed = False - # Whether the parser is in the element with the constraints. - self._in_constraints = False - # The text of the constraints. - self._constraints = '' - - def handle_starttag (self, tag, attrs): - if tag == 'meta': - for attr, value in attrs: - if attr == 'name' and value == 'updated_at': - self.header = self.get_starttag_text () - break - elif tag == 'a': - for attr, value in attrs: - if attr == 'id' and value == 'ivdvconstraints': - self._primed = True - break - elif self._primed and tag == 'code': - self._primed = False - self._in_constraints = True - - def handle_endtag (self, tag): - self._in_constraints = False - - def handle_data (self, data): - if self._in_constraints: - self._constraints += data - - def handle_charref (self, name): - self.handle_data (html_unescape (self, '&#%s;' % name)) - - def handle_entityref (self, name): - self.handle_data (html_unescape (self, '&%s;' % name)) - - def parse (self, filename): - """Parse the USE script development spec. - - Args: - filename (str): The file name of the spec. - """ - with io.open (filename, encoding='utf-8') as f: - self.feed (f.read ()) - expect (self.header, 'No header found') - for line in self._constraints.splitlines (): - constraint = [int (cp, 16) for cp in line.split (';')[0].strip ().split (' ')] - expect (2 <= len (constraint), 'Prohibited sequence is too short: {}'.format (constraint)) - script = scripts[constraint[0]] - if script in self.constraints: - self.constraints[script].add (constraint) - else: - self.constraints[script] = ConstraintSet (constraint) - expect (self.constraints, 'No constraints found') - -use_parser = USESpecParser () -use_parser.parse (sys.argv[1]) +constraints = {} +with io.open (sys.argv[1], encoding='utf-8') as f: + constraints_header = [f.readline ().strip () for i in range (2)] + for line in f: + j = line.find ('#') + if j >= 0: + line = line[:j] + constraint = [int (cp, 16) for cp in line.split (';')[0].split ()] + if not constraint: continue + assert 2 <= len (constraint), 'Prohibited sequence is too short: {}'.format (constraint) + script = scripts[constraint[0]] + if script in constraints: + constraints[script].add (constraint) + else: + constraints[script] = ConstraintSet (constraint) + assert constraints, 'No constraints found' print ('/* == Start of generated functions == */') print ('/*') @@ -219,15 +151,15 @@ print (' * %s use Scripts.txt' % sys.argv[0]) print (' *') print (' * on files with these headers:') print (' *') -print (' * %s' % use_parser.header.strip ()) +for line in constraints_header: + print (' * %s' % line.strip ()) +print (' *') for line in scripts_header: print (' * %s' % line.strip ()) print (' */') print () -print ('#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH') -print ('#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH') +print ('#include "hb-ot-shape-complex-vowel-constraints.hh"') print () - print ('static void') print ('_output_with_dotted_circle (hb_buffer_t *buffer)') print ('{') @@ -238,10 +170,10 @@ print (' buffer->next_glyph ();') print ('}') print () -print ('static void') -print ('preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,') -print ('\t\t\t\t hb_buffer_t *buffer,') -print ('\t\t\t\t hb_font_t *font)') +print ('void') +print ('_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,') +print ('\t\t\t\t hb_buffer_t *buffer,') +print ('\t\t\t\t hb_font_t *font)') print ('{') print (' /* UGLY UGLY UGLY business of adding dotted-circle in the middle of') print (' * vowel-sequences that look like another vowel. Data for each script') @@ -255,7 +187,7 @@ print (' unsigned int count = buffer->len;') print (' switch ((unsigned) buffer->props.script)') print (' {') -for script, constraints in sorted (use_parser.constraints.items (), key=lambda s_c: script_order[s_c[0]]): +for script, constraints in sorted (constraints.items (), key=lambda s_c: script_order[s_c[0]]): print (' case HB_SCRIPT_{}:'.format (script.upper ())) print (' for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)') print (' {') @@ -280,7 +212,5 @@ print (' buffer->swap_buffers ();') print (' }') print ('}') -print () -print ('#endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */') print () print ('/* == End of generated functions == */') diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 092ac6846..3babbfec6 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1517,6 +1517,14 @@ clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, } +static void +preprocess_text_indic (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) +{ + _hb_preprocess_text_vowel_constraints (plan, buffer, font); +} + static bool decompose_indic (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t ab, @@ -1616,7 +1624,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = override_features_indic, data_create_indic, data_destroy_indic, - preprocess_text_vowel_constraints, + preprocess_text_indic, nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, decompose_indic, diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index 8c44fe016..addfb87ba 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc @@ -572,6 +572,15 @@ reorder (const hb_ot_shape_plan_t *plan, HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); } + +static void +preprocess_text_use (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) +{ + _hb_preprocess_text_vowel_constraints (plan, buffer, font); +} + static bool compose_use (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t a, @@ -592,7 +601,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use = nullptr, /* override_features */ data_create_use, data_destroy_use, - preprocess_text_vowel_constraints, + preprocess_text_use, nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, nullptr, /* decompose */ diff --git a/src/hb-ot-shape-complex-vowel-constraints.cc b/src/hb-ot-shape-complex-vowel-constraints.cc new file mode 100644 index 000000000..e50233924 --- /dev/null +++ b/src/hb-ot-shape-complex-vowel-constraints.cc @@ -0,0 +1,433 @@ +/* == Start of generated functions == */ +/* + * The following functions are generated by running: + * + * ./gen-vowel-constraints.py use Scripts.txt + * + * on files with these headers: + * + * # Copied from https://docs.microsoft.com/en-us/typography/script-development/use + * # On October 23, 2018; with documentd dated 02/07/2018. + * + * # Scripts-11.0.0.txt + * # Date: 2018-02-21, 05:34:31 GMT + */ + +#include "hb-ot-shape-complex-vowel-constraints.hh" + +static void +_output_with_dotted_circle (hb_buffer_t *buffer) +{ + hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu); + _hb_glyph_info_reset_continuation (&dottedcircle); + + buffer->next_glyph (); +} + +void +_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font) +{ + /* UGLY UGLY UGLY business of adding dotted-circle in the middle of + * vowel-sequences that look like another vowel. Data for each script + * collected from the USE script development spec. + * + * https://github.com/harfbuzz/harfbuzz/issues/1019 + */ + bool processed = false; + buffer->clear_output (); + unsigned int count = buffer->len; + switch ((unsigned) buffer->props.script) + { + case HB_SCRIPT_DEVANAGARI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0905u: + switch (buffer->cur (1).codepoint) + { + case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u: + case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu: + case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u: + matched = true; + break; + } + break; + case 0x0906u: + switch (buffer->cur (1).codepoint) + { + case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u: + case 0x0948u: + matched = true; + break; + } + break; + case 0x0909u: + matched = 0x0941u == buffer->cur (1).codepoint; + break; + case 0x090Fu: + switch (buffer->cur (1).codepoint) + { + case 0x0945u: case 0x0946u: case 0x0947u: + matched = true; + break; + } + break; + case 0x0930u: + if (0x094Du == buffer->cur (1).codepoint && + buffer->idx + 2 < count && + 0x0907u == buffer->cur (2).codepoint) + { + buffer->next_glyph (); + buffer->next_glyph (); + buffer->output_glyph (0x25CCu); + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_BENGALI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0985u: + matched = 0x09BEu == buffer->cur (1).codepoint; + break; + case 0x098Bu: + matched = 0x09C3u == buffer->cur (1).codepoint; + break; + case 0x098Cu: + matched = 0x09E2u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_GURMUKHI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0A05u: + switch (buffer->cur (1).codepoint) + { + case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu: + matched = true; + break; + } + break; + case 0x0A72u: + switch (buffer->cur (1).codepoint) + { + case 0x0A3Fu: case 0x0A40u: case 0x0A47u: + matched = true; + break; + } + break; + case 0x0A73u: + switch (buffer->cur (1).codepoint) + { + case 0x0A41u: case 0x0A42u: case 0x0A4Bu: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_GUJARATI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0A85u: + switch (buffer->cur (1).codepoint) + { + case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u: + case 0x0AC9u: case 0x0ACBu: case 0x0ACCu: + matched = true; + break; + } + break; + case 0x0AC5u: + matched = 0x0ABEu == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_ORIYA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0B05u: + matched = 0x0B3Eu == buffer->cur (1).codepoint; + break; + case 0x0B0Fu: case 0x0B13u: + matched = 0x0B57u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_TELUGU: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0C12u: + switch (buffer->cur (1).codepoint) + { + case 0x0C4Cu: case 0x0C55u: + matched = true; + break; + } + break; + case 0x0C3Fu: case 0x0C46u: case 0x0C4Au: + matched = 0x0C55u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_KANNADA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0C89u: case 0x0C8Bu: + matched = 0x0CBEu == buffer->cur (1).codepoint; + break; + case 0x0C92u: + matched = 0x0CCCu == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_MALAYALAM: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0D07u: case 0x0D09u: + matched = 0x0D57u == buffer->cur (1).codepoint; + break; + case 0x0D0Eu: + matched = 0x0D46u == buffer->cur (1).codepoint; + break; + case 0x0D12u: + switch (buffer->cur (1).codepoint) + { + case 0x0D3Eu: case 0x0D57u: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_SINHALA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x0D85u: + switch (buffer->cur (1).codepoint) + { + case 0x0DCFu: case 0x0DD0u: case 0x0DD1u: + matched = true; + break; + } + break; + case 0x0D8Bu: case 0x0D8Fu: case 0x0D94u: + matched = 0x0DDFu == buffer->cur (1).codepoint; + break; + case 0x0D8Du: + matched = 0x0DD8u == buffer->cur (1).codepoint; + break; + case 0x0D91u: + switch (buffer->cur (1).codepoint) + { + case 0x0DCAu: case 0x0DD9u: case 0x0DDAu: case 0x0DDCu: + case 0x0DDDu: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_BRAHMI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11005u: + matched = 0x11038u == buffer->cur (1).codepoint; + break; + case 0x1100Bu: + matched = 0x1103Eu == buffer->cur (1).codepoint; + break; + case 0x1100Fu: + matched = 0x11042u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_KHUDAWADI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x112B0u: + switch (buffer->cur (1).codepoint) + { + case 0x112E0u: case 0x112E5u: case 0x112E6u: case 0x112E7u: + case 0x112E8u: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_TIRHUTA: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11481u: + matched = 0x114B0u == buffer->cur (1).codepoint; + break; + case 0x1148Bu: case 0x1148Du: + matched = 0x114BAu == buffer->cur (1).codepoint; + break; + case 0x114AAu: + switch (buffer->cur (1).codepoint) + { + case 0x114B5u: case 0x114B6u: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_MODI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11600u: case 0x11601u: + switch (buffer->cur (1).codepoint) + { + case 0x11639u: case 0x1163Au: + matched = true; + break; + } + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + case HB_SCRIPT_TAKRI: + for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) + { + bool matched = false; + switch (buffer->cur ().codepoint) + { + case 0x11680u: + switch (buffer->cur (1).codepoint) + { + case 0x116ADu: case 0x116B4u: case 0x116B5u: + matched = true; + break; + } + break; + case 0x11686u: + matched = 0x116B2u == buffer->cur (1).codepoint; + break; + } + buffer->next_glyph (); + if (matched) _output_with_dotted_circle (buffer); + } + processed = true; + break; + + default: + break; + } + if (processed) + { + if (buffer->idx < count) + buffer->next_glyph (); + if (likely (buffer->successful)) + buffer->swap_buffers (); + } +} + +/* == End of generated functions == */ diff --git a/src/hb-ot-shape-complex-vowel-constraints.hh b/src/hb-ot-shape-complex-vowel-constraints.hh index 1b07c2f40..d9082d4ea 100644 --- a/src/hb-ot-shape-complex-vowel-constraints.hh +++ b/src/hb-ot-shape-complex-vowel-constraints.hh @@ -1,434 +1,39 @@ -/* == Start of generated functions == */ /* - * The following functions are generated by running: + * Copyright © 2018 Google, Inc. * - * ./gen-vowel-constraints.py use Scripts.txt + * This is part of HarfBuzz, a text shaping library. * - * on files with these headers: + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. * - * - * # Scripts-11.0.0.txt - * # Date: 2018-02-21, 05:34:31 GMT + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod */ #ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH #define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH -static void -_output_with_dotted_circle (hb_buffer_t *buffer) -{ - hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu); - _hb_glyph_info_reset_continuation (&dottedcircle); +#include "hb.hh" - buffer->next_glyph (); -} +#include "hb-ot-shape-complex.hh" -static void -preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan, - hb_buffer_t *buffer, - hb_font_t *font) -{ - /* UGLY UGLY UGLY business of adding dotted-circle in the middle of - * vowel-sequences that look like another vowel. Data for each script - * collected from the USE script development spec. - * - * https://github.com/harfbuzz/harfbuzz/issues/1019 - */ - bool processed = false; - buffer->clear_output (); - unsigned int count = buffer->len; - switch ((unsigned) buffer->props.script) - { - case HB_SCRIPT_DEVANAGARI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x0905u: - switch (buffer->cur (1).codepoint) - { - case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u: - case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu: - case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u: - matched = true; - break; - } - break; - case 0x0906u: - switch (buffer->cur (1).codepoint) - { - case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u: - case 0x0948u: - matched = true; - break; - } - break; - case 0x0909u: - matched = 0x0941u == buffer->cur (1).codepoint; - break; - case 0x090Fu: - switch (buffer->cur (1).codepoint) - { - case 0x0945u: case 0x0946u: case 0x0947u: - matched = true; - break; - } - break; - case 0x0930u: - if (0x094Du == buffer->cur (1).codepoint && - buffer->idx + 2 < count && - 0x0907u == buffer->cur (2).codepoint) - { - buffer->next_glyph (); - buffer->next_glyph (); - buffer->output_glyph (0x25CCu); - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_BENGALI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x0985u: - matched = 0x09BEu == buffer->cur (1).codepoint; - break; - case 0x098Bu: - matched = 0x09C3u == buffer->cur (1).codepoint; - break; - case 0x098Cu: - matched = 0x09E2u == buffer->cur (1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_GURMUKHI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x0A05u: - switch (buffer->cur (1).codepoint) - { - case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu: - matched = true; - break; - } - break; - case 0x0A72u: - switch (buffer->cur (1).codepoint) - { - case 0x0A3Fu: case 0x0A40u: case 0x0A47u: - matched = true; - break; - } - break; - case 0x0A73u: - switch (buffer->cur (1).codepoint) - { - case 0x0A41u: case 0x0A42u: case 0x0A4Bu: - matched = true; - break; - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_GUJARATI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x0A85u: - switch (buffer->cur (1).codepoint) - { - case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u: - case 0x0AC9u: case 0x0ACBu: case 0x0ACCu: - matched = true; - break; - } - break; - case 0x0AC5u: - matched = 0x0ABEu == buffer->cur (1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_ORIYA: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x0B05u: - matched = 0x0B3Eu == buffer->cur (1).codepoint; - break; - case 0x0B0Fu: case 0x0B13u: - matched = 0x0B57u == buffer->cur (1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_TELUGU: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x0C12u: - switch (buffer->cur (1).codepoint) - { - case 0x0C4Cu: case 0x0C55u: - matched = true; - break; - } - break; - case 0x0C3Fu: case 0x0C46u: case 0x0C4Au: - matched = 0x0C55u == buffer->cur (1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_KANNADA: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x0C89u: case 0x0C8Bu: - matched = 0x0CBEu == buffer->cur (1).codepoint; - break; - case 0x0C92u: - matched = 0x0CCCu == buffer->cur (1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_MALAYALAM: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x0D07u: case 0x0D09u: - matched = 0x0D57u == buffer->cur (1).codepoint; - break; - case 0x0D0Eu: - matched = 0x0D46u == buffer->cur (1).codepoint; - break; - case 0x0D12u: - switch (buffer->cur (1).codepoint) - { - case 0x0D3Eu: case 0x0D57u: - matched = true; - break; - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_SINHALA: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x0D85u: - switch (buffer->cur (1).codepoint) - { - case 0x0DCFu: case 0x0DD0u: case 0x0DD1u: - matched = true; - break; - } - break; - case 0x0D8Bu: case 0x0D8Fu: case 0x0D94u: - matched = 0x0DDFu == buffer->cur (1).codepoint; - break; - case 0x0D8Du: - matched = 0x0DD8u == buffer->cur (1).codepoint; - break; - case 0x0D91u: - switch (buffer->cur (1).codepoint) - { - case 0x0DCAu: case 0x0DD9u: case 0x0DDAu: case 0x0DDCu: - case 0x0DDDu: - matched = true; - break; - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_BRAHMI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x11005u: - matched = 0x11038u == buffer->cur (1).codepoint; - break; - case 0x1100Bu: - matched = 0x1103Eu == buffer->cur (1).codepoint; - break; - case 0x1100Fu: - matched = 0x11042u == buffer->cur (1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_KHUDAWADI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x112B0u: - switch (buffer->cur (1).codepoint) - { - case 0x112E0u: case 0x112E5u: case 0x112E6u: case 0x112E7u: - case 0x112E8u: - matched = true; - break; - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_TIRHUTA: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x11481u: - matched = 0x114B0u == buffer->cur (1).codepoint; - break; - case 0x1148Bu: case 0x1148Du: - matched = 0x114BAu == buffer->cur (1).codepoint; - break; - case 0x114AAu: - switch (buffer->cur (1).codepoint) - { - case 0x114B5u: case 0x114B6u: - matched = true; - break; - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_MODI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x11600u: case 0x11601u: - switch (buffer->cur (1).codepoint) - { - case 0x11639u: case 0x1163Au: - matched = true; - break; - } - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - case HB_SCRIPT_TAKRI: - for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;) - { - bool matched = false; - switch (buffer->cur ().codepoint) - { - case 0x11680u: - switch (buffer->cur (1).codepoint) - { - case 0x116ADu: case 0x116B4u: case 0x116B5u: - matched = true; - break; - } - break; - case 0x11686u: - matched = 0x116B2u == buffer->cur (1).codepoint; - break; - } - buffer->next_glyph (); - if (matched) _output_with_dotted_circle (buffer); - } - processed = true; - break; - - default: - break; - } - if (processed) - { - if (buffer->idx < count) - buffer->next_glyph (); - if (likely (buffer->successful)) - buffer->swap_buffers (); - } -} +HB_INTERNAL void +_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + hb_font_t *font); #endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */ - -/* == End of generated functions == */ From 22ecefd88e1ea1841f363057b948aa792ac871a6 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Tue, 23 Oct 2018 00:52:05 +0330 Subject: [PATCH 34/36] Make tracking optout possible using 'trak' ot feature So '--features=-trak' or 'font-feature-settings: 'trak' 0;' can prevent applying of tracking if used. --- src/hb-ot-shape.cc | 10 +++++++--- test/shaping/data/in-house/tests/aat-trak.tests | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index a5538871b..8de66f3d6 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -116,7 +116,8 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.fallback_mark_positioning = true; /* Currently we always apply trak. */ - plan.apply_trak = hb_aat_layout_has_tracking (face); + plan.apply_trak = hb_aat_layout_has_tracking (face) && + plan.map.needs_fallback (HB_TAG ('t','r','a','k')); } @@ -177,12 +178,15 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, /* Random! */ map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE); - map->enable_feature (HB_TAG('H','A','R','F')); + /* Tracking. */ + map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK); + + map->enable_feature (HB_TAG ('H','A','R','F')); if (planner->shaper->collect_features) planner->shaper->collect_features (planner); - map->enable_feature (HB_TAG('B','U','Z','Z')); + map->enable_feature (HB_TAG ('B','U','Z','Z')); for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++) map->add_feature (common_features[i]); diff --git a/test/shaping/data/in-house/tests/aat-trak.tests b/test/shaping/data/in-house/tests/aat-trak.tests index 48b224f33..c8f10fbcf 100644 --- a/test/shaping/data/in-house/tests/aat-trak.tests +++ b/test/shaping/data/in-house/tests/aat-trak.tests @@ -6,3 +6,5 @@ ../fonts/TestTRAK.ttf:--font-ptem=24:U+0041,U+0042,U+0043:[A.alt=0@-12,0+976|B=1@-12,0+976|C.alt=2@-12,0+976] ../fonts/TestTRAK.ttf:--font-ptem=72:U+0041,U+0042,U+0043:[A.alt=0@-50,0+900|B=1@-50,0+900|C.alt=2@-50,0+900] ../fonts/TestTRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1@-107,0+786|C.alt=2@-107,0+786] +../fonts/TestTRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1@-107,0+786|C.alt=2@-107,0+786] +../fonts/TestTRAK.ttf:--font-ptem=144 --features=-trak:U+0041,U+0042,U+0043:[A.alt=0+1000|B=1+1000|C.alt=2+1000] From 8869436cb8a338b46c138305966a4b7b2c3ee374 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 23 Oct 2018 03:07:48 -0700 Subject: [PATCH 35/36] When parsing feature ranges, accept ';' instead of ':' --- src/hb-common.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-common.cc b/src/hb-common.cc index ccdb4dd94..86d07cf16 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -911,7 +911,7 @@ parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) has_start = parse_uint (pp, end, &feature->start); - if (parse_char (pp, end, ':')) { + if (parse_char (pp, end, ':') || parse_char (pp, end, ';')) { parse_uint (pp, end, &feature->end); } else { if (has_start) From cf92d6579e91d326598dcff93457fe85dfa962c2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 23 Oct 2018 03:10:56 -0700 Subject: [PATCH 36/36] [trak] Allow disabling tracking for ranges of text Fixes https://github.com/harfbuzz/harfbuzz/issues/1303 --- src/hb-aat-layout-trak-table.hh | 4 ++++ src/hb-ot-shape.cc | 11 +++++++---- src/hb-ot-shape.hh | 5 ++++- test/shaping/data/in-house/tests/aat-trak.tests | 1 + 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh index 8cfc8bc37..de2071ad6 100644 --- a/src/hb-aat-layout-trak-table.hh +++ b/src/hb-aat-layout-trak-table.hh @@ -184,6 +184,8 @@ struct trak { TRACE_APPLY (this); + hb_mask_t trak_mask = c->plan->trak_mask; + const float ptem = c->font->ptem; if (unlikely (ptem <= 0.f)) return_trace (false); @@ -197,6 +199,7 @@ struct trak hb_position_t advance_to_add = c->font->em_scalef_x (tracking); foreach_grapheme (buffer, start, end) { + if (!(buffer->info[start].mask & trak_mask)) continue; buffer->pos[start].x_advance += advance_to_add; buffer->pos[start].x_offset += offset_to_add; } @@ -209,6 +212,7 @@ struct trak hb_position_t advance_to_add = c->font->em_scalef_y (tracking); foreach_grapheme (buffer, start, end) { + if (!(buffer->info[start].mask & trak_mask)) continue; buffer->pos[start].y_advance += advance_to_add; buffer->pos[start].y_offset += offset_to_add; } diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 8de66f3d6..e05a67706 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -62,16 +62,18 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.shaper = shaper; map.compile (plan.map, coords, num_coords); - plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r')); plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m')); plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask); + plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ? HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'); plan.kern_mask = plan.map.get_mask (kern_tag); + plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k')); plan.requested_kerning = !!plan.kern_mask; + plan.requested_tracking = !!plan.trak_mask; bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX; bool disable_gpos = plan.shaper->gpos_tag && plan.shaper->gpos_tag != plan.map.chosen_script[1]; @@ -116,8 +118,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, plan.fallback_mark_positioning = true; /* Currently we always apply trak. */ - plan.apply_trak = hb_aat_layout_has_tracking (face) && - plan.map.needs_fallback (HB_TAG ('t','r','a','k')); + plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face); } @@ -178,7 +179,9 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, /* Random! */ map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE); - /* Tracking. */ + /* Tracking. We enable dummy feature here just to allow disabling + * AAT 'trak' table using features. + * https://github.com/harfbuzz/harfbuzz/issues/1303 */ map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK); map->enable_feature (HB_TAG ('H','A','R','F')); diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh index c9c0d3e09..93fce2d97 100644 --- a/src/hb-ot-shape.hh +++ b/src/hb-ot-shape.hh @@ -40,10 +40,13 @@ struct hb_ot_shape_plan_t const struct hb_ot_complex_shaper_t *shaper; hb_ot_map_t map; const void *data; - hb_mask_t rtlm_mask, frac_mask, numr_mask, dnom_mask; + hb_mask_t frac_mask, numr_mask, dnom_mask; + hb_mask_t rtlm_mask; hb_mask_t kern_mask; + hb_mask_t trak_mask; bool requested_kerning : 1; + bool requested_tracking : 1; bool has_frac : 1; bool has_gpos_mark : 1; bool fallback_glyph_classes : 1; diff --git a/test/shaping/data/in-house/tests/aat-trak.tests b/test/shaping/data/in-house/tests/aat-trak.tests index c8f10fbcf..3c558e60e 100644 --- a/test/shaping/data/in-house/tests/aat-trak.tests +++ b/test/shaping/data/in-house/tests/aat-trak.tests @@ -8,3 +8,4 @@ ../fonts/TestTRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1@-107,0+786|C.alt=2@-107,0+786] ../fonts/TestTRAK.ttf:--font-ptem=144:U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1@-107,0+786|C.alt=2@-107,0+786] ../fonts/TestTRAK.ttf:--font-ptem=144 --features=-trak:U+0041,U+0042,U+0043:[A.alt=0+1000|B=1+1000|C.alt=2+1000] +../fonts/TestTRAK.ttf:--font-ptem=144 --features=-trak[1;3]:U+0041,U+0042,U+0043,U+0041,U+0042,U+0043:[A.alt=0@-107,0+786|B=1+1000|C.alt=2+1000|A.alt=3@-107,0+786|B=4@-107,0+786|C.alt=5@-107,0+786]