From c7a4e3dfb5c8dd4f8faf08e327bb1900c0096cf6 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Tue, 23 Oct 2018 18:00:48 +0330 Subject: [PATCH 01/11] [svg] Add public API * hb_ot_color_has_svg * hb_ot_color_glyph_svg_create_blob --- src/dump-emoji.cc | 51 ++++++++++++-------- src/hb-open-type.hh | 1 - src/hb-ot-color-sbix-table.hh | 2 + src/hb-ot-color-svg-table.hh | 88 ++++++++++++++++++++++++++--------- src/hb-ot-color.cc | 53 ++++++++++++++++++--- src/hb-ot-color.h | 13 ++++++ src/hb-ot-face.cc | 2 + src/hb-ot-face.hh | 4 +- src/hb-ot-layout.cc | 4 -- test/api/test-ot-color.c | 43 +++++++++++++++-- 10 files changed, 200 insertions(+), 61 deletions(-) diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc index 2f79fc69d..97aab0044 100644 --- a/src/dump-emoji.cc +++ b/src/dump-emoji.cc @@ -69,26 +69,40 @@ sbix_callback (const uint8_t* data, unsigned int length, } static void -svg_callback (const uint8_t* data, unsigned int length, - unsigned int start_glyph, unsigned int end_glyph) +svg_dump (hb_face_t *face) { - char output_path[255]; - if (start_glyph == end_glyph) - sprintf (output_path, "out/svg-%d.svg", start_glyph); - else - sprintf (output_path, "out/svg-%d-%d.svg", start_glyph, end_glyph); + unsigned glyph_count = hb_face_get_glyph_count (face); - // append "z" if the content is gzipped - if ((data[0] == 0x1F) && (data[1] == 0x8B)) - strcat (output_path, "z"); + for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++) + { + hb_codepoint_t start_glyph_id, end_glyph_id; + hb_blob_t *blob = hb_ot_color_glyph_svg_create_blob (face, glyph_id, + &start_glyph_id, &end_glyph_id); - FILE *f = fopen (output_path, "wb"); - fwrite (data, 1, length, f); - fclose (f); + if (hb_blob_get_length (blob) == 0) continue; + + char output_path[255]; + if (start_glyph_id == end_glyph_id) + sprintf (output_path, "out/svg-%d.svg", start_glyph_id); + else + sprintf (output_path, "out/svg-%d-%d.svg", start_glyph_id, end_glyph_id); + + unsigned int length; + const char *data = hb_blob_get_data (blob, &length); + // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405 + if (length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) + strcat (output_path, "z"); + + FILE *f = fopen (output_path, "wb"); + fwrite (data, 1, length, f); + fclose (f); + + if (glyph_id < end_glyph_id) glyph_id = end_glyph_id; + } } static void -colr_cpal_rendering (hb_face_t *face, cairo_font_face_t *cairo_face) +colr_cpal_dump (hb_face_t *face, cairo_font_face_t *cairo_face) { unsigned int upem = hb_face_get_upem (face); @@ -268,10 +282,8 @@ main (int argc, char **argv) sbix.dump (sbix_callback); sbix.fini (); - OT::SVG::accelerator_t svg; - svg.init (face); - svg.dump (svg_callback); - svg.fini (); + if (hb_ot_color_has_svg (face)) + svg_dump (face); cairo_font_face_t *cairo_face; { @@ -281,7 +293,8 @@ main (int argc, char **argv) FT_New_Face (library, argv[1], 0, &ftface); cairo_face = cairo_ft_font_face_create_for_ft_face (ftface, 0); } - colr_cpal_rendering (face, cairo_face); + if (hb_ot_color_has_layers (face) && hb_ot_color_has_palettes (face)) + colr_cpal_dump (face, cairo_face); unsigned int num_glyphs = hb_face_get_glyph_count (face); unsigned int upem = hb_face_get_upem (face); diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index 8b7ea0939..8d17f3ed1 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -523,7 +523,6 @@ struct ArrayOf ::qsort (arrayZ, len, sizeof (Type), Type::cmp); } - private: inline bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh index 1b643c77a..1dd0a5c6d 100644 --- a/src/hb-ot-color-sbix-table.hh +++ b/src/hb-ot-color-sbix-table.hh @@ -142,6 +142,8 @@ struct sbix DEFINE_SIZE_ARRAY (8, strikes); }; +struct sbix_accelerator_t : sbix::accelerator_t {}; + } /* namespace OT */ #endif /* HB_OT_COLOR_SBIX_TABLE_HH */ diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh index 53d466846..fc5b8662a 100644 --- a/src/hb-ot-color-svg-table.hh +++ b/src/hb-ot-color-svg-table.hh @@ -41,12 +41,22 @@ namespace OT { struct SVGDocumentIndexEntry { friend struct SVG; + friend struct SVGDocumentIndex; - inline bool sanitize (hb_sanitize_context_t *c, const void* base) const + inline int cmp (hb_codepoint_t g) const + { return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; } + + static int cmp (const void *pa, const void *pb) + { + const hb_codepoint_t *a = (const hb_codepoint_t *) pa; + const SVGDocumentIndexEntry *b = (const SVGDocumentIndexEntry *) pb; + return b->cmp (*a); + } + + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - (base+svgDoc).sanitize (c, svgDocLength)); + return_trace (c->check_struct (this)); } protected: @@ -57,7 +67,7 @@ struct SVGDocumentIndexEntry LOffsetTo, false> svgDoc; /* Offset from the beginning of the SVG Document Index * to an SVG document. Must be non-zero. */ - HBUINT32 svgDocLength; /* Length of the SVG document. + HBUINT32 svgDocLength; /* Length of the SVG document. * Must be non-zero. */ public: DEFINE_SIZE_STATIC (12); @@ -67,11 +77,22 @@ struct SVGDocumentIndex { friend struct SVG; + inline const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const + { + const SVGDocumentIndexEntry *rec; + rec = (SVGDocumentIndexEntry *) bsearch (&glyph_id, + &entries.arrayZ, + entries.len, + sizeof (SVGDocumentIndexEntry), + SVGDocumentIndexEntry::cmp); + return likely (rec && glyph_id <= rec->endGlyphID) ? *rec : Null(SVGDocumentIndexEntry); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - entries.sanitize (c, this)); + entries.sanitize_shallow (c)); } protected: @@ -85,13 +106,6 @@ struct SVG { static const hb_tag_t tableTag = HB_OT_TAG_SVG; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - (this+svgDocIndex).sanitize (c))); - } - struct accelerator_t { inline void init (hb_face_t *face) @@ -106,20 +120,39 @@ struct SVG hb_blob_destroy (svg_blob); } - inline void - dump (void (*callback) (const uint8_t* data, unsigned int length, - unsigned int start_glyph, unsigned int end_glyph)) const + inline hb_blob_t* + failed_create_blob (hb_codepoint_t glyph_id, + hb_codepoint_t *start_glyph_id, + hb_codepoint_t *end_glyph_id) const { - const SVGDocumentIndex &index = svg+svg->svgDocIndex; - const ArrayOf &entries = index.entries; - for (unsigned int i = 0; i < entries.len; ++i) - { - const SVGDocumentIndexEntry &entry = entries[i]; - callback ((const uint8_t*) &entry.svgDoc (&index), entry.svgDocLength, - entry.startGlyphID, entry.endGlyphID); - } + if (start_glyph_id) *start_glyph_id = 0; + if (end_glyph_id) *end_glyph_id = 0; + return hb_blob_get_empty (); } + inline hb_blob_t* + create_blob (hb_codepoint_t glyph_id, + hb_codepoint_t *start_glyph_id, + hb_codepoint_t *end_glyph_id) const + { + if (unlikely (svg_len == 0)) + return failed_create_blob (glyph_id, start_glyph_id, end_glyph_id); + const SVGDocumentIndex &index = svg+svg->svgDocIndex; + const SVGDocumentIndexEntry &entry = index.get_glyph_entry (glyph_id); + if (unlikely (entry.svgDocLength == 0)) + return failed_create_blob (glyph_id, start_glyph_id, end_glyph_id); + unsigned int blob_offset = entry.svgDoc; + blob_offset += svg->svgDocIndex; + if (unlikely (blob_offset > svg_len || blob_offset + entry.svgDocLength > svg_len)) + return failed_create_blob (glyph_id, start_glyph_id, end_glyph_id); + if (start_glyph_id) *start_glyph_id = entry.startGlyphID; + if (end_glyph_id) *end_glyph_id = entry.endGlyphID; + return hb_blob_create_sub_blob (svg_blob, blob_offset, entry.svgDocLength); + } + + inline bool has_data () const + { return svg_len; } + private: hb_blob_t *svg_blob; const SVG *svg; @@ -127,6 +160,13 @@ struct SVG unsigned int svg_len; }; + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + (this+svgDocIndex).sanitize (c))); + } + protected: HBUINT16 version; /* Table version (starting at 0). */ LOffsetTo @@ -137,6 +177,8 @@ struct SVG DEFINE_SIZE_STATIC (10); }; +struct SVG_accelerator_t : SVG::accelerator_t {}; + } /* namespace OT */ diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 229b6e66f..e2f36ca37 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -54,6 +54,13 @@ _get_cpal (hb_face_t *face) return *(hb_ot_face_data (face)->CPAL.get ()); } +static inline const OT::SVG_accelerator_t& +_get_svg (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::SVG_accelerator_t); + return *(hb_ot_face_data (face)->SVG.get ()); +} + #if 0 static inline const OT::CBDT_accelerator_t& _get_cbdt (hb_face_t *face) @@ -68,13 +75,6 @@ _get_sbix (hb_face_t *face) if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::sbix); return *(hb_ot_face_data (face)->sbix.get ()); } - -static inline const OT::SVG& -_get_svg (hb_face_t *face) -{ - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::SVG); - return *(hb_ot_face_data (face)->SVG.get ()); -} #endif @@ -238,3 +238,42 @@ hb_ot_color_glyph_get_layers (hb_face_t *face, { return _get_colr (face).get_glyph_layers (glyph, start_offset, count, layers); } + + +/* + * SVG + */ + +/** + * hb_ot_color_has_svg: + * @face: a font face. + * + * Returns: whether SVG table is available. + * + * Since: REPLACEME + */ +hb_bool_t +hb_ot_color_has_svg (hb_face_t *face) +{ + return _get_svg (face).has_data (); +} + +/** + * hb_ot_color_glyph_svg_create_blob: + * @face: + * @glyph: + * @start_glyph: (out) (optional): Start of range this SVG supports + * @end_glyph: (out) (optional): End of range this SVG supports + * + * Returns: + * + * Since: REPLACEME + */ +hb_blob_t * +hb_ot_color_glyph_svg_create_blob (hb_face_t *face, + hb_codepoint_t glyph, + hb_codepoint_t *start_glyph, /* OUT. May be NULL. */ + hb_codepoint_t *end_glyph /* OUT. May be NULL. */) +{ + return _get_svg (face).create_blob (glyph, start_glyph, end_glyph); +} diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index 02b76bffc..8b31b687b 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -111,6 +111,19 @@ 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. */); +/* + * SVG + */ + +HB_EXTERN hb_bool_t +hb_ot_color_has_svg (hb_face_t *face); + +HB_EXTERN hb_blob_t * +hb_ot_color_glyph_svg_create_blob (hb_face_t *face, + hb_codepoint_t glyph, + hb_codepoint_t *start_glyph, /* OUT. May be NULL. */ + hb_codepoint_t *end_glyph /* OUT. May be NULL. */); + HB_END_DECLS diff --git a/src/hb-ot-face.cc b/src/hb-ot-face.cc index 1bc68d366..0aba2a691 100644 --- a/src/hb-ot-face.cc +++ b/src/hb-ot-face.cc @@ -32,6 +32,8 @@ #include "hb-ot-kern-table.hh" #include "hb-ot-post-table.hh" #include "hb-ot-color-cbdt-table.hh" +#include "hb-ot-color-sbix-table.hh" +#include "hb-ot-color-svg-table.hh" #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" diff --git a/src/hb-ot-face.hh b/src/hb-ot-face.hh index a45a49361..cce2f1d8f 100644 --- a/src/hb-ot-face.hh +++ b/src/hb-ot-face.hh @@ -73,8 +73,8 @@ HB_OT_TABLE(OT, COLR) \ HB_OT_TABLE(OT, CPAL) \ HB_OT_ACCELERATOR(OT, CBDT) \ - HB_OT_TABLE(OT, sbix) \ - HB_OT_TABLE(OT, SVG) \ + HB_OT_ACCELERATOR(OT, sbix) \ + HB_OT_ACCELERATOR(OT, SVG) \ /* */ /* Declare tables. */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 096fda207..7f3e6c73d 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -41,10 +41,6 @@ // Just so we compile them; unused otherwise: #include "hb-ot-layout-base-table.hh" #include "hb-ot-layout-jstf-table.hh" -#include "hb-ot-color-colr-table.hh" -#include "hb-ot-color-cpal-table.hh" -#include "hb-ot-color-sbix-table.hh" -#include "hb-ot-color-svg-table.hh" #include "hb-ot-kern-table.hh" #include "hb-ot-name-table.hh" diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c index a514c6aa9..f145a4ce6 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -103,6 +103,7 @@ static hb_face_t *cpal = NULL; static hb_face_t *cbdt = NULL; static hb_face_t *sbix = NULL; static hb_face_t *svg = NULL; +static hb_face_t *empty = NULL; #define assert_color_rgba(colors, i, r, g, b, a) G_STMT_START { \ const hb_color_t *_colors = (colors); \ @@ -203,7 +204,6 @@ test_hb_ot_color_palette_get_flags_v1 (void) static void test_hb_ot_color_palette_get_colors_empty (void) { - hb_face_t *empty = hb_face_get_empty (); g_assert_cmpint (hb_ot_color_palette_get_colors (empty, 0, 0, NULL, NULL), ==, 0); } @@ -302,8 +302,6 @@ test_hb_ot_color_palette_get_colors_v1 (void) static 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_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); @@ -349,8 +347,6 @@ test_hb_ot_color_glyph_get_layers (void) static void test_hb_ot_color_has_data (void) { - hb_face_t *empty = hb_face_get_empty (); - 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); @@ -366,6 +362,41 @@ test_hb_ot_color_has_data (void) 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); + + g_assert (hb_ot_color_has_svg (empty) == FALSE); + g_assert (hb_ot_color_has_svg (cpal_v0) == FALSE); + g_assert (hb_ot_color_has_svg (cpal_v1) == FALSE); + g_assert (hb_ot_color_has_svg (cpal) == FALSE); + g_assert (hb_ot_color_has_svg (cbdt) == FALSE); + g_assert (hb_ot_color_has_svg (sbix) == FALSE); + g_assert (hb_ot_color_has_svg (svg) == TRUE); +} + +static void +test_hb_ot_color_svg (void) +{ + hb_codepoint_t start_glyph, end_glyph; + hb_blob_t *blob; + + blob = hb_ot_color_glyph_svg_create_blob (svg, 0, &start_glyph, &end_glyph); + g_assert (hb_blob_get_length (blob) == 0); + g_assert (start_glyph == 0); + g_assert (end_glyph == 0); + + blob = hb_ot_color_glyph_svg_create_blob (svg, 1, &start_glyph, &end_glyph); + unsigned int length; + const char *data = hb_blob_get_data (blob, &length); + g_assert_cmpuint (length, ==, 146); + g_assert_cmpuint (start_glyph, ==, 1); + g_assert_cmpuint (end_glyph, ==, 1); + g_assert (strncmp (data, "", 5) == 0); + hb_blob_destroy (blob); + + blob = hb_ot_color_glyph_svg_create_blob (empty, 0, &start_glyph, &end_glyph); + g_assert (hb_blob_get_length (blob) == 0); + g_assert (start_glyph == 0); + g_assert (end_glyph == 0); } int @@ -380,6 +411,7 @@ 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"); + empty = hb_face_get_empty (); 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); @@ -393,6 +425,7 @@ main (int argc, char **argv) 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); + hb_test_add (test_hb_ot_color_svg); status = hb_test_run(); hb_face_destroy (cpal_v0); hb_face_destroy (cpal_v1); From 4ceabb8c2126fe365303b8d69e667005276c0241 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Thu, 25 Oct 2018 21:52:35 +0330 Subject: [PATCH 02/11] [svg] Hide start_glyph and end_glyph from API --- src/dump-emoji.cc | 21 +++++++----------- src/hb-ot-color-svg-table.hh | 42 +++++++++++------------------------- src/hb-ot-color.cc | 9 ++------ src/hb-ot-color.h | 5 +---- test/api/test-ot-color.c | 11 ++-------- 5 files changed, 25 insertions(+), 63 deletions(-) diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc index 97aab0044..1603d2d98 100644 --- a/src/dump-emoji.cc +++ b/src/dump-emoji.cc @@ -75,29 +75,24 @@ svg_dump (hb_face_t *face) for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++) { - hb_codepoint_t start_glyph_id, end_glyph_id; - hb_blob_t *blob = hb_ot_color_glyph_svg_create_blob (face, glyph_id, - &start_glyph_id, &end_glyph_id); + hb_blob_t *blob = hb_ot_color_glyph_svg_create_blob (face, glyph_id); if (hb_blob_get_length (blob) == 0) continue; - char output_path[255]; - if (start_glyph_id == end_glyph_id) - sprintf (output_path, "out/svg-%d.svg", start_glyph_id); - else - sprintf (output_path, "out/svg-%d-%d.svg", start_glyph_id, end_glyph_id); - unsigned int length; const char *data = hb_blob_get_data (blob, &length); - // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405 - if (length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) - strcat (output_path, "z"); + + char output_path[256]; + sprintf (output_path, "out/svg-%d.svg%s", + glyph_id, + // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405 + (length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) ? "z" : ""); FILE *f = fopen (output_path, "wb"); fwrite (data, 1, length, f); fclose (f); - if (glyph_id < end_glyph_id) glyph_id = end_glyph_id; + hb_blob_destroy (blob); } } diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh index fc5b8662a..9e03ef762 100644 --- a/src/hb-ot-color-svg-table.hh +++ b/src/hb-ot-color-svg-table.hh @@ -40,9 +40,6 @@ namespace OT { struct SVGDocumentIndexEntry { - friend struct SVG; - friend struct SVGDocumentIndex; - inline int cmp (hb_codepoint_t g) const { return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; } @@ -53,6 +50,13 @@ struct SVGDocumentIndexEntry return b->cmp (*a); } + inline hb_blob_t* create_blob (hb_blob_t *svg_blob, unsigned int index_offset) const + { + if (svgDocLength == 0) return hb_blob_get_empty (); + return hb_blob_create_sub_blob (svg_blob, (unsigned int) svgDoc + index_offset, + svgDocLength); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -85,7 +89,7 @@ struct SVGDocumentIndex entries.len, sizeof (SVGDocumentIndexEntry), SVGDocumentIndexEntry::cmp); - return likely (rec && glyph_id <= rec->endGlyphID) ? *rec : Null(SVGDocumentIndexEntry); + return likely (rec) ? *rec : Null(SVGDocumentIndexEntry); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -120,34 +124,12 @@ struct SVG hb_blob_destroy (svg_blob); } - inline hb_blob_t* - failed_create_blob (hb_codepoint_t glyph_id, - hb_codepoint_t *start_glyph_id, - hb_codepoint_t *end_glyph_id) const - { - if (start_glyph_id) *start_glyph_id = 0; - if (end_glyph_id) *end_glyph_id = 0; - return hb_blob_get_empty (); - } - - inline hb_blob_t* - create_blob (hb_codepoint_t glyph_id, - hb_codepoint_t *start_glyph_id, - hb_codepoint_t *end_glyph_id) const + inline hb_blob_t* create_blob_for_glyph (hb_codepoint_t glyph_id) const { if (unlikely (svg_len == 0)) - return failed_create_blob (glyph_id, start_glyph_id, end_glyph_id); - const SVGDocumentIndex &index = svg+svg->svgDocIndex; - const SVGDocumentIndexEntry &entry = index.get_glyph_entry (glyph_id); - if (unlikely (entry.svgDocLength == 0)) - return failed_create_blob (glyph_id, start_glyph_id, end_glyph_id); - unsigned int blob_offset = entry.svgDoc; - blob_offset += svg->svgDocIndex; - if (unlikely (blob_offset > svg_len || blob_offset + entry.svgDocLength > svg_len)) - return failed_create_blob (glyph_id, start_glyph_id, end_glyph_id); - if (start_glyph_id) *start_glyph_id = entry.startGlyphID; - if (end_glyph_id) *end_glyph_id = entry.endGlyphID; - return hb_blob_create_sub_blob (svg_blob, blob_offset, entry.svgDocLength); + return hb_blob_get_empty (); + return (svg+svg->svgDocIndex).get_glyph_entry (glyph_id).create_blob (svg_blob, + svg->svgDocIndex); } inline bool has_data () const diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index e2f36ca37..cdfbaade1 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -262,18 +262,13 @@ hb_ot_color_has_svg (hb_face_t *face) * hb_ot_color_glyph_svg_create_blob: * @face: * @glyph: - * @start_glyph: (out) (optional): Start of range this SVG supports - * @end_glyph: (out) (optional): End of range this SVG supports * * Returns: * * Since: REPLACEME */ hb_blob_t * -hb_ot_color_glyph_svg_create_blob (hb_face_t *face, - hb_codepoint_t glyph, - hb_codepoint_t *start_glyph, /* OUT. May be NULL. */ - hb_codepoint_t *end_glyph /* OUT. May be NULL. */) +hb_ot_color_glyph_svg_create_blob (hb_face_t *face, hb_codepoint_t glyph) { - return _get_svg (face).create_blob (glyph, start_glyph, end_glyph); + return _get_svg (face).create_blob_for_glyph (glyph); } diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index 8b31b687b..259c84987 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -119,10 +119,7 @@ HB_EXTERN hb_bool_t hb_ot_color_has_svg (hb_face_t *face); HB_EXTERN hb_blob_t * -hb_ot_color_glyph_svg_create_blob (hb_face_t *face, - hb_codepoint_t glyph, - hb_codepoint_t *start_glyph, /* OUT. May be NULL. */ - hb_codepoint_t *end_glyph /* OUT. May be NULL. */); +hb_ot_color_glyph_svg_create_blob (hb_face_t *face, hb_codepoint_t glyph); HB_END_DECLS diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c index f145a4ce6..8e4ec0a06 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -375,28 +375,21 @@ test_hb_ot_color_has_data (void) static void test_hb_ot_color_svg (void) { - hb_codepoint_t start_glyph, end_glyph; hb_blob_t *blob; - blob = hb_ot_color_glyph_svg_create_blob (svg, 0, &start_glyph, &end_glyph); + blob = hb_ot_color_glyph_svg_create_blob (svg, 0); g_assert (hb_blob_get_length (blob) == 0); - g_assert (start_glyph == 0); - g_assert (end_glyph == 0); - blob = hb_ot_color_glyph_svg_create_blob (svg, 1, &start_glyph, &end_glyph); + blob = hb_ot_color_glyph_svg_create_blob (svg, 1); unsigned int length; const char *data = hb_blob_get_data (blob, &length); g_assert_cmpuint (length, ==, 146); - g_assert_cmpuint (start_glyph, ==, 1); - g_assert_cmpuint (end_glyph, ==, 1); g_assert (strncmp (data, "", 5) == 0); hb_blob_destroy (blob); blob = hb_ot_color_glyph_svg_create_blob (empty, 0, &start_glyph, &end_glyph); g_assert (hb_blob_get_length (blob) == 0); - g_assert (start_glyph == 0); - g_assert (end_glyph == 0); } int From 5cb1ce868138a10c0663a18c3891bc717aa4bc64 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Thu, 25 Oct 2018 22:39:58 +0330 Subject: [PATCH 03/11] [svg] Collapse SVGDocumentIndex into SVG --- src/hb-ot-color-svg-table.hh | 54 ++++++++++++------------------------ src/hb-ot-color.cc | 2 +- test/api/test-ot-color.c | 2 +- 3 files changed, 20 insertions(+), 38 deletions(-) diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh index 9e03ef762..4ef380745 100644 --- a/src/hb-ot-color-svg-table.hh +++ b/src/hb-ot-color-svg-table.hh @@ -50,7 +50,7 @@ struct SVGDocumentIndexEntry return b->cmp (*a); } - inline hb_blob_t* create_blob (hb_blob_t *svg_blob, unsigned int index_offset) const + inline hb_blob_t* reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const { if (svgDocLength == 0) return hb_blob_get_empty (); return hb_blob_create_sub_blob (svg_blob, (unsigned int) svgDoc + index_offset, @@ -77,35 +77,6 @@ struct SVGDocumentIndexEntry DEFINE_SIZE_STATIC (12); }; -struct SVGDocumentIndex -{ - friend struct SVG; - - inline const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const - { - const SVGDocumentIndexEntry *rec; - rec = (SVGDocumentIndexEntry *) bsearch (&glyph_id, - &entries.arrayZ, - entries.len, - sizeof (SVGDocumentIndexEntry), - SVGDocumentIndexEntry::cmp); - return likely (rec) ? *rec : Null(SVGDocumentIndexEntry); - } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - entries.sanitize_shallow (c)); - } - - protected: - ArrayOf - entries; /* Array of SVG Document Index Entries. */ - public: - DEFINE_SIZE_ARRAY (2, entries); -}; - struct SVG { static const hb_tag_t tableTag = HB_OT_TAG_SVG; @@ -124,12 +95,11 @@ struct SVG hb_blob_destroy (svg_blob); } - inline hb_blob_t* create_blob_for_glyph (hb_codepoint_t glyph_id) const + inline hb_blob_t* reference_blob_for_glyph (hb_codepoint_t glyph_id) const { if (unlikely (svg_len == 0)) return hb_blob_get_empty (); - return (svg+svg->svgDocIndex).get_glyph_entry (glyph_id).create_blob (svg_blob, - svg->svgDocIndex); + return svg->get_glyph_entry (glyph_id).reference_blob (svg_blob, svg->svgDocEntries); } inline bool has_data () const @@ -142,18 +112,30 @@ struct SVG unsigned int svg_len; }; + inline const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const + { + const SVGDocumentIndexEntry *rec; + rec = (SVGDocumentIndexEntry *) bsearch (&glyph_id, + &(this+svgDocEntries).arrayZ, + (this+svgDocEntries).len, + sizeof (SVGDocumentIndexEntry), + SVGDocumentIndexEntry::cmp); + return likely (rec) ? *rec : Null(SVGDocumentIndexEntry); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && - (this+svgDocIndex).sanitize (c))); + (this+svgDocEntries).sanitize_shallow (c))); } protected: HBUINT16 version; /* Table version (starting at 0). */ - LOffsetTo - svgDocIndex; /* Offset (relative to the start of the SVG table) to the + LOffsetTo > + svgDocEntries; /* Offset (relative to the start of the SVG table) to the * SVG Documents Index. Must be non-zero. */ + /* Array of SVG Document Index Entries. */ HBUINT32 reserved; /* Set to 0. */ public: DEFINE_SIZE_STATIC (10); diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index cdfbaade1..3d9f1c1ba 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -270,5 +270,5 @@ hb_ot_color_has_svg (hb_face_t *face) hb_blob_t * hb_ot_color_glyph_svg_create_blob (hb_face_t *face, hb_codepoint_t glyph) { - return _get_svg (face).create_blob_for_glyph (glyph); + return _get_svg (face).reference_blob_for_glyph (glyph); } diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c index 8e4ec0a06..13a25b0b8 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -388,7 +388,7 @@ test_hb_ot_color_svg (void) g_assert (strncmp (data + 140, "", 5) == 0); hb_blob_destroy (blob); - blob = hb_ot_color_glyph_svg_create_blob (empty, 0, &start_glyph, &end_glyph); + blob = hb_ot_color_glyph_svg_create_blob (empty, 0); g_assert (hb_blob_get_length (blob) == 0); } From 30f18039b3c0e5748101f8934ae82aebfc5a83f7 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 26 Oct 2018 09:34:34 +0330 Subject: [PATCH 04/11] [svg] Rename _svg_create_blob to _glyph_reference_blob_svg --- docs/harfbuzz-sections.txt | 2 ++ src/dump-emoji.cc | 2 +- src/hb-ot-color.cc | 4 ++-- src/hb-ot-color.h | 2 +- test/api/test-ot-color.c | 6 +++--- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 7bca7ca20..c385984a7 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -460,8 +460,10 @@ HB_OT_H_IN
hb-ot-color hb_ot_color_glyph_get_layers +hb_ot_color_glyph_reference_blob_svg hb_ot_color_has_layers hb_ot_color_has_palettes +hb_ot_color_has_svg hb_ot_color_layer_t hb_ot_color_palette_color_get_name_id hb_ot_color_palette_flags_t diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc index 1603d2d98..c4710a629 100644 --- a/src/dump-emoji.cc +++ b/src/dump-emoji.cc @@ -75,7 +75,7 @@ svg_dump (hb_face_t *face) for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++) { - hb_blob_t *blob = hb_ot_color_glyph_svg_create_blob (face, glyph_id); + hb_blob_t *blob = hb_ot_color_glyph_reference_blob_svg (face, glyph_id); if (hb_blob_get_length (blob) == 0) continue; diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 3d9f1c1ba..283b3a1e5 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -259,7 +259,7 @@ hb_ot_color_has_svg (hb_face_t *face) } /** - * hb_ot_color_glyph_svg_create_blob: + * hb_ot_color_glyph_reference_blob_svg: * @face: * @glyph: * @@ -268,7 +268,7 @@ hb_ot_color_has_svg (hb_face_t *face) * Since: REPLACEME */ hb_blob_t * -hb_ot_color_glyph_svg_create_blob (hb_face_t *face, hb_codepoint_t glyph) +hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph) { return _get_svg (face).reference_blob_for_glyph (glyph); } diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index 259c84987..fb9a9e370 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -119,7 +119,7 @@ HB_EXTERN hb_bool_t hb_ot_color_has_svg (hb_face_t *face); HB_EXTERN hb_blob_t * -hb_ot_color_glyph_svg_create_blob (hb_face_t *face, hb_codepoint_t glyph); +hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph); HB_END_DECLS diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c index 13a25b0b8..4ffadeec0 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -377,10 +377,10 @@ test_hb_ot_color_svg (void) { hb_blob_t *blob; - blob = hb_ot_color_glyph_svg_create_blob (svg, 0); + blob = hb_ot_color_glyph_reference_blob_svg (svg, 0); g_assert (hb_blob_get_length (blob) == 0); - blob = hb_ot_color_glyph_svg_create_blob (svg, 1); + blob = hb_ot_color_glyph_reference_blob_svg (svg, 1); unsigned int length; const char *data = hb_blob_get_data (blob, &length); g_assert_cmpuint (length, ==, 146); @@ -388,7 +388,7 @@ test_hb_ot_color_svg (void) g_assert (strncmp (data + 140, "", 5) == 0); hb_blob_destroy (blob); - blob = hb_ot_color_glyph_svg_create_blob (empty, 0); + blob = hb_ot_color_glyph_reference_blob_svg (empty, 0); g_assert (hb_blob_get_length (blob) == 0); } From 265ad408ca41e9d0b5a1056a751d834d4eadc911 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Fri, 26 Oct 2018 23:55:11 +0330 Subject: [PATCH 05/11] [ot-color/png] Implement sbix part --- docs/harfbuzz-sections.txt | 2 + src/dump-emoji.cc | 5 +- src/hb-ot-color-cbdt-table.hh | 27 +++++++--- src/hb-ot-color-sbix-table.hh | 98 ++++++++++++++++++++++++++++++----- src/hb-ot-color.cc | 64 +++++++++++++++++++++++ src/hb-ot-color.h | 9 ++++ test/api/test-ot-color.c | 32 ++++++++++++ 7 files changed, 215 insertions(+), 22 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index c385984a7..67f9ae2c4 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -460,9 +460,11 @@ HB_OT_H_IN
hb-ot-color hb_ot_color_glyph_get_layers +hb_ot_color_glyph_reference_blob_png hb_ot_color_glyph_reference_blob_svg hb_ot_color_has_layers hb_ot_color_has_palettes +hb_ot_color_has_png hb_ot_color_has_svg hb_ot_color_layer_t hb_ot_color_palette_color_get_name_id diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc index c4710a629..7c7392f20 100644 --- a/src/dump-emoji.cc +++ b/src/dump-emoji.cc @@ -58,12 +58,13 @@ cbdt_callback (const uint8_t* data, unsigned int length, } static void -sbix_callback (const uint8_t* data, unsigned int length, - unsigned int group, unsigned int gid) +sbix_callback (hb_blob_t *blob, unsigned int group, unsigned int gid) { char output_path[255]; sprintf (output_path, "out/sbix-%d-%d.png", group, gid); FILE *f = fopen (output_path, "wb"); + unsigned int length; + const char* data = hb_blob_get_data (blob, &length); fwrite (data, 1, length, f); fclose (f); } diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh index 1e1fe0956..0f64577d3 100644 --- a/src/hb-ot-color-cbdt-table.hh +++ b/src/hb-ot-color-cbdt-table.hh @@ -376,13 +376,6 @@ struct CBDT { static const hb_tag_t tableTag = HB_OT_TAG_CBDT; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - likely (version.major == 2 || version.major == 3)); - } - struct accelerator_t { inline void init (hb_face_t *face) @@ -511,6 +504,20 @@ struct CBDT } } + inline hb_blob_t* reference_blob_for_glyph (hb_codepoint_t glyph_id, + unsigned int requested_x_ppem, + unsigned int requested_y_ppem, + unsigned int *strike_x_ppem, + unsigned int *strike_y_ppem) const + { +// if (unlikely (cbdt_len == 0)) + return hb_blob_get_empty (); +// return svg->get_glyph_entry (glyph_id).reference_blob (svg_blob, svg->svgDocEntries); + } + + inline bool has_data () const + { return cbdt_len; } + private: hb_blob_t *cblc_blob; hb_blob_t *cbdt_blob; @@ -521,6 +528,12 @@ struct CBDT unsigned int upem; }; + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + likely (version.major == 2 || version.major == 3)); + } protected: FixedVersion<> version; diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh index 1dd0a5c6d..97eac9b58 100644 --- a/src/hb-ot-color-sbix-table.hh +++ b/src/hb-ot-color-sbix-table.hh @@ -62,8 +62,6 @@ struct SBIXGlyph struct SBIXStrike { - friend struct sbix; - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -71,6 +69,48 @@ struct SBIXStrike imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1)); } + inline unsigned int get_ppem () const + { return ppem; } + + inline unsigned int get_resolution () const + { return resolution; } + + inline unsigned int blob_size (unsigned int glyph_id) const + { + return imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] - SBIXGlyph::min_size; + } + + inline hb_blob_t *get_glyph_blob (unsigned int glyph_id, + hb_blob_t *sbix_blob, + unsigned int strike_offset, + unsigned int *x_offset, + unsigned int *y_offset, + hb_tag_t requested_file_type, + unsigned int num_glyphs) const + { + if (imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] == 0) + return hb_blob_get_empty (); + + const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]); + if (unlikely (glyph->graphicType == HB_TAG ('d','u','p','e') && + blob_size (glyph_id) >= 2)) + { + unsigned int new_glyph_id = *((HBUINT16 *) &glyph->data); + if (new_glyph_id < num_glyphs) + { + glyph = &(this+imageOffsetsZ[new_glyph_id]); + glyph_id = new_glyph_id; + } + } + if (unlikely (requested_file_type != glyph->graphicType)) + return hb_blob_get_empty (); + if (likely (x_offset)) *x_offset = glyph->xOffset; + if (likely (y_offset)) *y_offset = glyph->yOffset; + unsigned int offset = strike_offset + SBIXGlyph::min_size; + offset += imageOffsetsZ[glyph_id]; + return hb_blob_create_sub_blob (sbix_blob, offset, blob_size (glyph_id)); + } + protected: HBUINT16 ppem; /* The PPEM size for which this strike was designed. */ HBUINT16 resolution; /* The device pixel density (in PPI) for which this @@ -99,6 +139,7 @@ struct sbix sbix_blob = hb_sanitize_context_t().reference_table (face); sbix_len = hb_blob_get_length (sbix_blob); sbix_table = sbix_blob->as (); + num_glyphs = face->get_num_glyphs (); } inline void fini (void) @@ -106,29 +147,60 @@ struct sbix hb_blob_destroy (sbix_blob); } - inline void dump (void (*callback) (const uint8_t* data, unsigned int length, + inline void dump (void (*callback) (hb_blob_t *data, unsigned int group, unsigned int gid)) const { - for (unsigned group = 0; group < sbix_table->strikes.len; ++group) + for (unsigned group = 0; group < sbix_table->strikes.len; group++) { - const SBIXStrike &strike = sbix_table->strikes[group](sbix_table); - for (unsigned int glyph = 0; glyph < num_glyphs; ++glyph) - if (strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] > 0) - { - const SBIXGlyph &sbixGlyph = strike.imageOffsetsZ[glyph]((const void *) &strike); - callback ((const uint8_t*) &sbixGlyph.data, - strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] - 8, - group, glyph); - } + const SBIXStrike &strike = sbix_table+sbix_table->strikes[group]; + for (unsigned int glyph_id = 0; glyph_id < num_glyphs; glyph_id++) + { + unsigned int x_offset, y_offset; + hb_tag_t tag; + hb_blob_t *blob; + blob = strike.get_glyph_blob (glyph_id, sbix_blob, sbix_table->strikes[group], + &x_offset, &x_offset, + HB_TAG('p','n','g',' '), num_glyphs); + if (hb_blob_get_length (blob)) callback (blob, group, glyph_id); + } } } + inline hb_blob_t* reference_blob_for_glyph (hb_codepoint_t glyph_id, + unsigned int ptem HB_UNUSED, + unsigned int requested_ppem, + unsigned int requested_file_type, + unsigned int *available_x_ppem, + unsigned int *available_y_ppem) const + { + if (unlikely (sbix_len == 0 || sbix_table->strikes.len == 0)) + return hb_blob_get_empty (); + + /* TODO: Does spec guarantee strikes are ascended sorted? */ + unsigned int group = sbix_table->strikes.len - 1; + if (requested_ppem != 0) + /* TODO: Use bsearch maybe or doesn't worth it? */ + for (group = 0; group < sbix_table->strikes.len; group++) + if ((sbix_table+sbix_table->strikes[group]).get_ppem () >= requested_ppem) + break; + + const SBIXStrike &strike = sbix_table+sbix_table->strikes[group]; + if (available_x_ppem) *available_x_ppem = strike.get_ppem (); + if (available_y_ppem) *available_y_ppem = strike.get_ppem (); + return strike.get_glyph_blob (glyph_id, sbix_blob, sbix_table->strikes[group], + nullptr, nullptr, requested_file_type, num_glyphs); + } + + inline bool has_data () const + { return sbix_len; } + private: hb_blob_t *sbix_blob; const sbix *sbix_table; unsigned int sbix_len; unsigned int num_glyphs; + hb_vector_t > data_offsets; }; protected: diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 283b3a1e5..8dd3b2a41 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -47,6 +47,13 @@ _get_colr (hb_face_t *face) return *(hb_ot_face_data (face)->COLR.get ()); } +static inline const OT::CBDT_accelerator_t& +_get_cbdt (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::CBDT_accelerator_t); + return *(hb_ot_face_data (face)->CBDT.get ()); +} + static inline const OT::CPAL& _get_cpal (hb_face_t *face) { @@ -54,6 +61,13 @@ _get_cpal (hb_face_t *face) return *(hb_ot_face_data (face)->CPAL.get ()); } +static inline const OT::sbix_accelerator_t& +_get_sbix (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::sbix_accelerator_t); + return *(hb_ot_face_data (face)->sbix.get ()); +} + static inline const OT::SVG_accelerator_t& _get_svg (hb_face_t *face) { @@ -272,3 +286,53 @@ hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph) { return _get_svg (face).reference_blob_for_glyph (glyph); } + + +/* + * PNG, CBDT or sbix + */ + +/** + * hb_ot_color_has_png: + * @face: a font face. + * + * Returns: whether SVG table is available. + * + * Since: REPLACEME + */ +hb_bool_t +hb_ot_color_has_png (hb_face_t *face) +{ + return _get_cbdt (face).has_data () || _get_sbix (face).has_data (); +} + +/** + * hb_ot_color_glyph_reference_blob_svg: + * @font: + * @glyph: + * @strike_x_ppem: (out): + * @strike_y_ppem: (out): + * + * Returns: + * + * Since: REPLACEME + */ +hb_blob_t * +hb_ot_color_glyph_reference_blob_png (hb_font_t *font, + hb_codepoint_t glyph, + unsigned int *strike_x_ppem /* OUT */, + unsigned int *strike_y_ppem /* OUT */) +{ + /* TODO: if (hb_options ().aat ()) then call sbix first */ + + if (_get_cbdt (font->face).has_data ()) + return _get_cbdt (font->face).reference_blob_for_glyph (glyph, font->x_ppem, font->y_ppem, + strike_x_ppem, strike_y_ppem); + + if (_get_sbix (font->face).has_data ()) + return _get_sbix (font->face).reference_blob_for_glyph (glyph, font->ptem, + MAX (font->x_ppem, font->y_ppem), + HB_TAG('p','n','g',' '), + strike_x_ppem, strike_y_ppem); + +} diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index fb9a9e370..7901a3598 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -121,6 +121,15 @@ hb_ot_color_has_svg (hb_face_t *face); HB_EXTERN hb_blob_t * hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph); +HB_EXTERN hb_bool_t +hb_ot_color_has_png (hb_face_t *face); + +HB_EXTERN hb_blob_t * +hb_ot_color_glyph_reference_blob_png (hb_font_t *font, + hb_codepoint_t glyph, + unsigned int *strike_x_ppem, + unsigned int *strike_y_ppem); + HB_END_DECLS diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c index 4ffadeec0..767a3d61a 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -370,6 +370,14 @@ test_hb_ot_color_has_data (void) g_assert (hb_ot_color_has_svg (cbdt) == FALSE); g_assert (hb_ot_color_has_svg (sbix) == FALSE); g_assert (hb_ot_color_has_svg (svg) == TRUE); + + g_assert (hb_ot_color_has_png (empty) == FALSE); + g_assert (hb_ot_color_has_png (cpal_v0) == FALSE); + g_assert (hb_ot_color_has_png (cpal_v1) == FALSE); + g_assert (hb_ot_color_has_png (cpal) == FALSE); + g_assert (hb_ot_color_has_png (cbdt) == TRUE); + g_assert (hb_ot_color_has_png (sbix) == TRUE); + g_assert (hb_ot_color_has_png (svg) == FALSE); } static void @@ -392,6 +400,29 @@ test_hb_ot_color_svg (void) g_assert (hb_blob_get_length (blob) == 0); } + +static void +test_hb_ot_color_png (void) +{ + hb_blob_t *blob; + + hb_font_t *sbix_font; + sbix_font = hb_font_create (sbix); + blob = hb_ot_color_glyph_reference_blob_png (sbix_font, 0, NULL, NULL); + g_assert (hb_blob_get_length (blob) == 0); + + unsigned int strike_x_ppem, strike_y_ppem; + blob = hb_ot_color_glyph_reference_blob_png (sbix_font, 1, + &strike_x_ppem, &strike_y_ppem); + unsigned int length; + const char *data = hb_blob_get_data (blob, &length); + g_assert_cmpuint (length, ==, 224); + g_assert_cmpuint (strike_x_ppem, ==, 300); + g_assert_cmpuint (strike_y_ppem, ==, 300); + g_assert (strncmp (data + 1, "PNG", 3) == 0); + hb_blob_destroy (blob); +} + int main (int argc, char **argv) { @@ -418,6 +449,7 @@ main (int argc, char **argv) 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); + hb_test_add (test_hb_ot_color_png); hb_test_add (test_hb_ot_color_svg); status = hb_test_run(); hb_face_destroy (cpal_v0); From 6a38fd68a8f4e66d9248e0c943ae3a1cf45c521b Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 27 Oct 2018 10:50:53 +0330 Subject: [PATCH 06/11] [ot-color/png] sbix runtime memory check --- src/hb-ot-color-cbdt-table.hh | 16 +++++++--------- src/hb-ot-color-sbix-table.hh | 18 ++++++++++++------ src/hb-ot-color-svg-table.hh | 4 ++-- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh index 0f64577d3..770fe3eb9 100644 --- a/src/hb-ot-color-cbdt-table.hh +++ b/src/hb-ot-color-cbdt-table.hh @@ -452,7 +452,7 @@ struct CBDT } inline void dump (void (*callback) (const uint8_t* data, unsigned int length, - unsigned int group, unsigned int gid)) const + unsigned int group, unsigned int gid)) const { if (!cblc) return; // Not a color bitmap font. @@ -504,15 +504,13 @@ struct CBDT } } - inline hb_blob_t* reference_blob_for_glyph (hb_codepoint_t glyph_id, - unsigned int requested_x_ppem, - unsigned int requested_y_ppem, - unsigned int *strike_x_ppem, - unsigned int *strike_y_ppem) const + inline hb_blob_t* reference_blob_for_glyph (hb_codepoint_t glyph_id HB_UNUSED, + unsigned int requested_x_ppem HB_UNUSED, + unsigned int requested_y_ppem HB_UNUSED, + unsigned int *strike_x_ppem HB_UNUSED, + unsigned int *strike_y_ppem HB_UNUSED) const { -// if (unlikely (cbdt_len == 0)) - return hb_blob_get_empty (); -// return svg->get_glyph_entry (glyph_id).reference_blob (svg_blob, svg->svgDocEntries); + return hb_blob_get_empty (); } inline bool has_data () const diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh index 97eac9b58..cba62f0cf 100644 --- a/src/hb-ot-color-sbix-table.hh +++ b/src/hb-ot-color-sbix-table.hh @@ -82,6 +82,7 @@ struct SBIXStrike inline hb_blob_t *get_glyph_blob (unsigned int glyph_id, hb_blob_t *sbix_blob, + unsigned int sbix_len, unsigned int strike_offset, unsigned int *x_offset, unsigned int *y_offset, @@ -91,6 +92,9 @@ struct SBIXStrike if (imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] == 0) return hb_blob_get_empty (); + if (strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size > sbix_len) + return hb_blob_get_empty (); + const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]); if (unlikely (glyph->graphicType == HB_TAG ('d','u','p','e') && blob_size (glyph_id) >= 2)) @@ -100,6 +104,8 @@ struct SBIXStrike { glyph = &(this+imageOffsetsZ[new_glyph_id]); glyph_id = new_glyph_id; + if (strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size > sbix_len) + return hb_blob_get_empty (); } } if (unlikely (requested_file_type != glyph->graphicType)) @@ -155,18 +161,18 @@ struct sbix const SBIXStrike &strike = sbix_table+sbix_table->strikes[group]; for (unsigned int glyph_id = 0; glyph_id < num_glyphs; glyph_id++) { - unsigned int x_offset, y_offset; hb_tag_t tag; hb_blob_t *blob; - blob = strike.get_glyph_blob (glyph_id, sbix_blob, sbix_table->strikes[group], - &x_offset, &x_offset, + blob = strike.get_glyph_blob (glyph_id, sbix_blob, sbix_len, + sbix_table->strikes[group], + nullptr, nullptr, HB_TAG('p','n','g',' '), num_glyphs); if (hb_blob_get_length (blob)) callback (blob, group, glyph_id); } } } - inline hb_blob_t* reference_blob_for_glyph (hb_codepoint_t glyph_id, + inline hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id, unsigned int ptem HB_UNUSED, unsigned int requested_ppem, unsigned int requested_file_type, @@ -187,7 +193,8 @@ struct sbix const SBIXStrike &strike = sbix_table+sbix_table->strikes[group]; if (available_x_ppem) *available_x_ppem = strike.get_ppem (); if (available_y_ppem) *available_y_ppem = strike.get_ppem (); - return strike.get_glyph_blob (glyph_id, sbix_blob, sbix_table->strikes[group], + return strike.get_glyph_blob (glyph_id, sbix_blob, sbix_len, + sbix_table->strikes[group], nullptr, nullptr, requested_file_type, num_glyphs); } @@ -200,7 +207,6 @@ struct sbix unsigned int sbix_len; unsigned int num_glyphs; - hb_vector_t > data_offsets; }; protected: diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh index 4ef380745..5238ad458 100644 --- a/src/hb-ot-color-svg-table.hh +++ b/src/hb-ot-color-svg-table.hh @@ -50,7 +50,7 @@ struct SVGDocumentIndexEntry return b->cmp (*a); } - inline hb_blob_t* reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const + inline hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const { if (svgDocLength == 0) return hb_blob_get_empty (); return hb_blob_create_sub_blob (svg_blob, (unsigned int) svgDoc + index_offset, @@ -95,7 +95,7 @@ struct SVG hb_blob_destroy (svg_blob); } - inline hb_blob_t* reference_blob_for_glyph (hb_codepoint_t glyph_id) const + inline hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const { if (unlikely (svg_len == 0)) return hb_blob_get_empty (); From 5e2a52f71a8d081441fbc1c57a3550e3a9573e46 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 27 Oct 2018 12:44:33 +0330 Subject: [PATCH 07/11] [sbix] Remove dump method from sbix accelerator --- src/dump-emoji.cc | 36 +++++++++++++++++++++++------------ src/hb-ot-color-sbix-table.hh | 26 ++++++++++--------------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc index 7c7392f20..73305aa77 100644 --- a/src/dump-emoji.cc +++ b/src/dump-emoji.cc @@ -58,15 +58,30 @@ cbdt_callback (const uint8_t* data, unsigned int length, } static void -sbix_callback (hb_blob_t *blob, unsigned int group, unsigned int gid) +sbix_dump (hb_face_t *face) { - char output_path[255]; - sprintf (output_path, "out/sbix-%d-%d.png", group, gid); - FILE *f = fopen (output_path, "wb"); - unsigned int length; - const char* data = hb_blob_get_data (blob, &length); - fwrite (data, 1, length, f); - fclose (f); + OT::sbix::accelerator_t sbix; + sbix.init (face); + unsigned int length = 0; + unsigned int *available_ppems = sbix.get_available_ppems (&length); + unsigned int num_glyphs = face->num_glyphs; + for (unsigned int group = 0; group < length; group++) + for (unsigned int glyph_id = 0; glyph_id < num_glyphs; glyph_id++) + { + hb_blob_t *blob; + blob = sbix.reference_blob_for_glyph (glyph_id, 0, available_ppems[group], + HB_TAG('p','n','g',' '), NULL, NULL); + if (hb_blob_get_length (blob) == 0) continue; + + char output_path[255]; + sprintf (output_path, "out/sbix-%d-%d.png", available_ppems[group], glyph_id); + FILE *f = fopen (output_path, "wb"); + unsigned int length; + const char* data = hb_blob_get_data (blob, &length); + fwrite (data, 1, length, f); + fclose (f); + } + sbix.fini (); } static void @@ -273,10 +288,7 @@ main (int argc, char **argv) cbdt.dump (cbdt_callback); cbdt.fini (); - OT::sbix::accelerator_t sbix; - sbix.init (face); - sbix.dump (sbix_callback); - sbix.fini (); + sbix_dump (face); if (hb_ot_color_has_svg (face)) svg_dump (face); diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh index cba62f0cf..b48ea1715 100644 --- a/src/hb-ot-color-sbix-table.hh +++ b/src/hb-ot-color-sbix-table.hh @@ -153,23 +153,17 @@ struct sbix hb_blob_destroy (sbix_blob); } - inline void dump (void (*callback) (hb_blob_t *data, - unsigned int group, unsigned int gid)) const + /* only to support dump-emoji, don't use it anywhere else */ + inline unsigned int *get_available_ppems (unsigned int *length) { - for (unsigned group = 0; group < sbix_table->strikes.len; group++) - { - const SBIXStrike &strike = sbix_table+sbix_table->strikes[group]; - for (unsigned int glyph_id = 0; glyph_id < num_glyphs; glyph_id++) - { - hb_tag_t tag; - hb_blob_t *blob; - blob = strike.get_glyph_blob (glyph_id, sbix_blob, sbix_len, - sbix_table->strikes[group], - nullptr, nullptr, - HB_TAG('p','n','g',' '), num_glyphs); - if (hb_blob_get_length (blob)) callback (blob, group, glyph_id); - } - } + if (unlikely (sbix_len == 0 || sbix_table->strikes.len == 0)) + return nullptr; + *length = sbix_table->strikes.len; + unsigned int *result; + result = (unsigned int *) malloc (sizeof (unsigned int) * sbix_table->strikes.len); + for (unsigned int i = 0; i < sbix_table->strikes.len; i++) + result[i] = (sbix_table+sbix_table->strikes[i]).get_ppem (); + return result; } inline hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id, From 9435fb24daadf08add9a701816da01bd54c0cd78 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 27 Oct 2018 13:32:14 +0330 Subject: [PATCH 08/11] [ot-color/png] Implement CBDT part --- src/hb-ot-color-cbdt-table.hh | 56 +++++++++++++++++++++++++++++++---- src/hb-ot-color.cc | 19 ++---------- src/hb-ot-color.h | 4 +++ test/api/test-ot-color.c | 25 ++++++++++++++-- 4 files changed, 79 insertions(+), 25 deletions(-) diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh index 770fe3eb9..a9518b774 100644 --- a/src/hb-ot-color-cbdt-table.hh +++ b/src/hb-ot-color-cbdt-table.hh @@ -504,12 +504,58 @@ struct CBDT } } - inline hb_blob_t* reference_blob_for_glyph (hb_codepoint_t glyph_id HB_UNUSED, - unsigned int requested_x_ppem HB_UNUSED, - unsigned int requested_y_ppem HB_UNUSED, - unsigned int *strike_x_ppem HB_UNUSED, - unsigned int *strike_y_ppem HB_UNUSED) const + inline hb_blob_t* reference_blob_for_glyph (hb_codepoint_t glyph_id, + unsigned int requested_x_ppem, + unsigned int requested_y_ppem, + unsigned int *strike_x_ppem, + unsigned int *strike_y_ppem) const { + if (!cblc) + return hb_blob_get_empty (); // Not a color bitmap font. + + if (requested_x_ppem == 0) requested_x_ppem = upem; + if (requested_y_ppem == 0) requested_y_ppem = upem; + unsigned int x_ppem = requested_x_ppem, y_ppem = requested_y_ppem; + + const void *base; + const IndexSubtableRecord *subtable_record = this->cblc->find_table (glyph_id, &x_ppem, &y_ppem, &base); + if (!subtable_record || !x_ppem || !y_ppem) + return hb_blob_get_empty (); + + unsigned int image_offset = 0, image_length = 0, image_format = 0; + if (!subtable_record->get_image_data (glyph_id, base, &image_offset, &image_length, &image_format)) + return hb_blob_get_empty (); + + switch (image_format) + { + case 17: { + if (strike_x_ppem) *strike_x_ppem = x_ppem; + if (strike_x_ppem) *strike_y_ppem = y_ppem; + const GlyphBitmapDataFormat17& glyphFormat17 = + StructAtOffset (this->cbdt, image_offset); + return hb_blob_create_sub_blob (cbdt_blob, + image_offset + GlyphBitmapDataFormat17::min_size, + glyphFormat17.data.len); + } + case 18: { + if (strike_x_ppem) *strike_x_ppem = x_ppem; + if (strike_x_ppem) *strike_y_ppem = y_ppem; + const GlyphBitmapDataFormat18& glyphFormat18 = + StructAtOffset (this->cbdt, image_offset); + return hb_blob_create_sub_blob (cbdt_blob, + image_offset + GlyphBitmapDataFormat18::min_size, + glyphFormat18.data.len); + } + case 19: { + if (strike_x_ppem) *strike_x_ppem = x_ppem; + if (strike_x_ppem) *strike_y_ppem = y_ppem; + const GlyphBitmapDataFormat19& glyphFormat19 = + StructAtOffset (this->cbdt, image_offset); + return hb_blob_create_sub_blob (cbdt_blob, + image_offset + GlyphBitmapDataFormat19::min_size, + glyphFormat19.data.len); + } + } return hb_blob_get_empty (); } diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 8dd3b2a41..9de2f9ac6 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -75,22 +75,6 @@ _get_svg (hb_face_t *face) return *(hb_ot_face_data (face)->SVG.get ()); } -#if 0 -static inline const OT::CBDT_accelerator_t& -_get_cbdt (hb_face_t *face) -{ - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::CBDT_accelerator_t); - return *(hb_ot_face_data (face)->CBDT.get ()); -} - -static inline const OT::sbix& -_get_sbix (hb_face_t *face) -{ - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::sbix); - return *(hb_ot_face_data (face)->sbix.get ()); -} -#endif - /* * CPAL @@ -289,7 +273,7 @@ hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph) /* - * PNG, CBDT or sbix + * PNG: CBDT or sbix */ /** @@ -335,4 +319,5 @@ hb_ot_color_glyph_reference_blob_png (hb_font_t *font, HB_TAG('p','n','g',' '), strike_x_ppem, strike_y_ppem); + return hb_blob_get_empty (); } diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index 7901a3598..1810cd63b 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -121,6 +121,10 @@ hb_ot_color_has_svg (hb_face_t *face); HB_EXTERN hb_blob_t * hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph); +/* + * PNG: CBDT or sbix + */ + HB_EXTERN hb_bool_t hb_ot_color_has_png (hb_face_t *face); diff --git a/test/api/test-ot-color.c b/test/api/test-ot-color.c index 767a3d61a..51b901d25 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -405,22 +405,41 @@ static void test_hb_ot_color_png (void) { hb_blob_t *blob; + unsigned int length; + const char *data; + unsigned int strike_x_ppem, strike_y_ppem; + /* sbix */ hb_font_t *sbix_font; sbix_font = hb_font_create (sbix); blob = hb_ot_color_glyph_reference_blob_png (sbix_font, 0, NULL, NULL); g_assert (hb_blob_get_length (blob) == 0); - unsigned int strike_x_ppem, strike_y_ppem; blob = hb_ot_color_glyph_reference_blob_png (sbix_font, 1, &strike_x_ppem, &strike_y_ppem); - unsigned int length; - const char *data = hb_blob_get_data (blob, &length); + data = hb_blob_get_data (blob, &length); g_assert_cmpuint (length, ==, 224); g_assert_cmpuint (strike_x_ppem, ==, 300); g_assert_cmpuint (strike_y_ppem, ==, 300); g_assert (strncmp (data + 1, "PNG", 3) == 0); hb_blob_destroy (blob); + hb_font_destroy (sbix_font); + + /* cbdt */ + hb_font_t *cbdt_font; + cbdt_font = hb_font_create (cbdt); + blob = hb_ot_color_glyph_reference_blob_png (cbdt_font, 0, NULL, NULL); + g_assert (hb_blob_get_length (blob) == 0); + + blob = hb_ot_color_glyph_reference_blob_png (cbdt_font, 1, + &strike_x_ppem, &strike_y_ppem); + data = hb_blob_get_data (blob, &length); + g_assert_cmpuint (length, ==, 88); + g_assert_cmpuint (strike_x_ppem, ==, 80); + g_assert_cmpuint (strike_y_ppem, ==, 80); + g_assert (strncmp (data + 1, "PNG", 3) == 0); + hb_blob_destroy (blob); + hb_font_destroy (cbdt_font); } int From b42661ee91ea92309e827a970f370cacc62c73aa Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 27 Oct 2018 14:15:38 +0330 Subject: [PATCH 09/11] [ot-color] Add some documentation --- src/hb-ot-color.cc | 37 +++++++++++++++++++------------------ src/hb-ot-color.h | 2 +- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 9de2f9ac6..84035069c 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -132,8 +132,8 @@ hb_ot_color_palette_get_name_id (hb_face_t *face, /** * hb_ot_color_palette_color_get_name_id: - * @face: a font face. - * @color_index: + * @face: a font face. + * @color_index: palette entry index. * * Returns: Name ID associated with a palette entry, e.g. eye color * @@ -148,7 +148,7 @@ hb_ot_color_palette_color_get_name_id (hb_face_t *face, /** * hb_ot_color_palette_get_flags: - * @face: a font face + * @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. @@ -217,13 +217,14 @@ hb_ot_color_has_layers (hb_face_t *face) /** * hb_ot_color_glyph_get_layers: - * @face: a font face. - * @glyph: - * @start_offset: - * @count: (inout) (optional): - * @layers: (array length=count) (out) (optional): + * @face: a font face. + * @glyph: a layered color glyph id. + * @start_offset: starting offset of layers. + * @count: (inout) (optional): gets number of layers available to be written on buffer + * and returns number of written layers. + * @layers: (array length=count) (out) (optional): layers buffer to buffer. * - * Returns: + * Returns: Total number of layers a layered color glyph have. * * Since: REPLACEME */ @@ -258,10 +259,10 @@ hb_ot_color_has_svg (hb_face_t *face) /** * hb_ot_color_glyph_reference_blob_svg: - * @face: - * @glyph: + * @face: a font face. + * @glyph: a svg glyph index. * - * Returns: + * Returns: respective svg blob of the glyph, if available. * * Since: REPLACEME */ @@ -280,7 +281,7 @@ hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph) * hb_ot_color_has_png: * @face: a font face. * - * Returns: whether SVG table is available. + * Returns: whether either of CBDT or sbix tables is available. * * Since: REPLACEME */ @@ -292,12 +293,14 @@ hb_ot_color_has_png (hb_face_t *face) /** * hb_ot_color_glyph_reference_blob_svg: - * @font: - * @glyph: + * @font: a font object, not face. upem should be set on + * that font object if one wants to get optimal png blob, otherwise + * return the biggest one + * @glyph: a glyph index. * @strike_x_ppem: (out): * @strike_y_ppem: (out): * - * Returns: + * Returns: respective png blob of the glyph, if available. * * Since: REPLACEME */ @@ -307,8 +310,6 @@ hb_ot_color_glyph_reference_blob_png (hb_font_t *font, unsigned int *strike_x_ppem /* OUT */, unsigned int *strike_y_ppem /* OUT */) { - /* TODO: if (hb_options ().aat ()) then call sbix first */ - if (_get_cbdt (font->face).has_data ()) return _get_cbdt (font->face).reference_blob_for_glyph (glyph, font->x_ppem, font->y_ppem, strike_x_ppem, strike_y_ppem); diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index 1810cd63b..a8eae8618 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -94,7 +94,7 @@ HB_EXTERN hb_bool_t hb_ot_color_has_layers (hb_face_t *face); /** - * hb_ot_color_layer_t: + * hb_ot_color_layer_t: Pairs of glyph and color index. * * Since: REPLACEME **/ From 9aa6279a2d64ab8057b0d7acbcc77044442c6d0e Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 27 Oct 2018 14:24:58 +0330 Subject: [PATCH 10/11] [ot-color/png] Try to get image blob from sbix first options.aat is set --- src/hb-ot-color.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index 84035069c..a2b753833 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -310,15 +310,21 @@ hb_ot_color_glyph_reference_blob_png (hb_font_t *font, unsigned int *strike_x_ppem /* OUT */, unsigned int *strike_y_ppem /* OUT */) { - if (_get_cbdt (font->face).has_data ()) - return _get_cbdt (font->face).reference_blob_for_glyph (glyph, font->x_ppem, font->y_ppem, + hb_blob_t *blob = hb_blob_get_empty (); + /* don't run cbdt first if aat is set */ + if (!hb_options ().aat && _get_cbdt (font->face).has_data ()) + blob = _get_cbdt (font->face).reference_blob_for_glyph (glyph, font->x_ppem, font->y_ppem, strike_x_ppem, strike_y_ppem); - if (_get_sbix (font->face).has_data ()) - return _get_sbix (font->face).reference_blob_for_glyph (glyph, font->ptem, + if (_get_sbix (font->face).has_data () && !hb_blob_get_length (blob)) + blob = _get_sbix (font->face).reference_blob_for_glyph (glyph, font->ptem, MAX (font->x_ppem, font->y_ppem), HB_TAG('p','n','g',' '), strike_x_ppem, strike_y_ppem); - return hb_blob_get_empty (); + if (hb_options ().aat && _get_cbdt (font->face).has_data () && !hb_blob_get_length (blob)) + blob = _get_cbdt (font->face).reference_blob_for_glyph (glyph, font->x_ppem, font->y_ppem, + strike_x_ppem, strike_y_ppem); + + return blob; } From 8180c37df0a856dbc3564c0aefd8b2acab8baf8a Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sat, 27 Oct 2018 14:45:00 +0330 Subject: [PATCH 11/11] [ot-color] Remove _png and _svg public APIs --- docs/harfbuzz-sections.txt | 4 ---- src/dump-emoji.cc | 11 ++++++++--- src/hb-ot-color.cc | 39 ++++++++++++++++++++++++++++++++++---- src/hb-ot-color.h | 24 ----------------------- test/api/test-ot-color.c | 8 ++++++-- 5 files changed, 49 insertions(+), 37 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 67f9ae2c4..7bca7ca20 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -460,12 +460,8 @@ HB_OT_H_IN
hb-ot-color hb_ot_color_glyph_get_layers -hb_ot_color_glyph_reference_blob_png -hb_ot_color_glyph_reference_blob_svg hb_ot_color_has_layers hb_ot_color_has_palettes -hb_ot_color_has_png -hb_ot_color_has_svg hb_ot_color_layer_t hb_ot_color_palette_color_get_name_id hb_ot_color_palette_flags_t diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc index 73305aa77..63fb5885f 100644 --- a/src/dump-emoji.cc +++ b/src/dump-emoji.cc @@ -89,9 +89,12 @@ svg_dump (hb_face_t *face) { unsigned glyph_count = hb_face_get_glyph_count (face); + OT::SVG::accelerator_t svg; + svg.init (face); + for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++) { - hb_blob_t *blob = hb_ot_color_glyph_reference_blob_svg (face, glyph_id); + hb_blob_t *blob = svg.reference_blob_for_glyph (glyph_id); if (hb_blob_get_length (blob) == 0) continue; @@ -110,6 +113,8 @@ svg_dump (hb_face_t *face) hb_blob_destroy (blob); } + + svg.fini (); } static void @@ -290,8 +295,8 @@ main (int argc, char **argv) sbix_dump (face); - if (hb_ot_color_has_svg (face)) - svg_dump (face); +// if (hb_ot_color_has_svg (face)) + svg_dump (face); cairo_font_face_t *cairo_face; { diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index a2b753833..7ffc3d88b 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -47,12 +47,14 @@ _get_colr (hb_face_t *face) return *(hb_ot_face_data (face)->COLR.get ()); } +#if 0 static inline const OT::CBDT_accelerator_t& _get_cbdt (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::CBDT_accelerator_t); return *(hb_ot_face_data (face)->CBDT.get ()); } +#endif static inline const OT::CPAL& _get_cpal (hb_face_t *face) @@ -61,6 +63,7 @@ _get_cpal (hb_face_t *face) return *(hb_ot_face_data (face)->CPAL.get ()); } +#if 0 static inline const OT::sbix_accelerator_t& _get_sbix (hb_face_t *face) { @@ -74,6 +77,7 @@ _get_svg (hb_face_t *face) if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::SVG_accelerator_t); return *(hb_ot_face_data (face)->SVG.get ()); } +#endif /* @@ -239,6 +243,7 @@ hb_ot_color_glyph_get_layers (hb_face_t *face, } +#if 0 /* * SVG */ @@ -249,7 +254,7 @@ hb_ot_color_glyph_get_layers (hb_face_t *face, * * Returns: whether SVG table is available. * - * Since: REPLACEME + * Since: DONTREPLACEME */ hb_bool_t hb_ot_color_has_svg (hb_face_t *face) @@ -264,7 +269,7 @@ hb_ot_color_has_svg (hb_face_t *face) * * Returns: respective svg blob of the glyph, if available. * - * Since: REPLACEME + * Since: DONTREPLACEME */ hb_blob_t * hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph) @@ -283,7 +288,7 @@ hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph) * * Returns: whether either of CBDT or sbix tables is available. * - * Since: REPLACEME + * Since: DONTREPLACEME */ hb_bool_t hb_ot_color_has_png (hb_face_t *face) @@ -302,7 +307,7 @@ hb_ot_color_has_png (hb_face_t *face) * * Returns: respective png blob of the glyph, if available. * - * Since: REPLACEME + * Since: DONTREPLACEME */ hb_blob_t * hb_ot_color_glyph_reference_blob_png (hb_font_t *font, @@ -328,3 +333,29 @@ hb_ot_color_glyph_reference_blob_png (hb_font_t *font, return blob; } + +/* To be moved to public header */ + +/* + * SVG + */ + +HB_EXTERN hb_bool_t +hb_ot_color_has_svg (hb_face_t *face); + +HB_EXTERN hb_blob_t * +hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph); + +/* + * PNG: CBDT or sbix + */ + +HB_EXTERN hb_bool_t +hb_ot_color_has_png (hb_face_t *face); + +HB_EXTERN hb_blob_t * +hb_ot_color_glyph_reference_blob_png (hb_font_t *font, + hb_codepoint_t glyph, + unsigned int *strike_x_ppem, + unsigned int *strike_y_ppem); +#endif diff --git a/src/hb-ot-color.h b/src/hb-ot-color.h index a8eae8618..6e4c1777e 100644 --- a/src/hb-ot-color.h +++ b/src/hb-ot-color.h @@ -111,30 +111,6 @@ 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. */); -/* - * SVG - */ - -HB_EXTERN hb_bool_t -hb_ot_color_has_svg (hb_face_t *face); - -HB_EXTERN hb_blob_t * -hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph); - -/* - * PNG: CBDT or sbix - */ - -HB_EXTERN hb_bool_t -hb_ot_color_has_png (hb_face_t *face); - -HB_EXTERN hb_blob_t * -hb_ot_color_glyph_reference_blob_png (hb_font_t *font, - hb_codepoint_t glyph, - unsigned int *strike_x_ppem, - unsigned int *strike_y_ppem); - - 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 51b901d25..27409e10c 100644 --- a/test/api/test-ot-color.c +++ b/test/api/test-ot-color.c @@ -363,6 +363,7 @@ test_hb_ot_color_has_data (void) g_assert (hb_ot_color_has_palettes (sbix) == FALSE); g_assert (hb_ot_color_has_palettes (svg) == FALSE); +#if 0 g_assert (hb_ot_color_has_svg (empty) == FALSE); g_assert (hb_ot_color_has_svg (cpal_v0) == FALSE); g_assert (hb_ot_color_has_svg (cpal_v1) == FALSE); @@ -378,8 +379,10 @@ test_hb_ot_color_has_data (void) g_assert (hb_ot_color_has_png (cbdt) == TRUE); g_assert (hb_ot_color_has_png (sbix) == TRUE); g_assert (hb_ot_color_has_png (svg) == FALSE); +#endif } +#if 0 static void test_hb_ot_color_svg (void) { @@ -441,6 +444,7 @@ test_hb_ot_color_png (void) hb_blob_destroy (blob); hb_font_destroy (cbdt_font); } +#endif int main (int argc, char **argv) @@ -468,8 +472,8 @@ main (int argc, char **argv) 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); - hb_test_add (test_hb_ot_color_png); - hb_test_add (test_hb_ot_color_svg); +// hb_test_add (test_hb_ot_color_png); +// hb_test_add (test_hb_ot_color_svg); status = hb_test_run(); hb_face_destroy (cpal_v0); hb_face_destroy (cpal_v1);