diff --git a/src/Makefile.am b/src/Makefile.am index 0b9ae9dc4..a51048b70 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -377,6 +377,15 @@ test_would_substitute_SOURCES = test-would-substitute.cc test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) +if HAVE_FREETYPE +if HAVE_CAIRO_FT +noinst_PROGRAMS += test-ot-color +test_ot_color_SOURCES = test-ot-color.cc +test_ot_color_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS) +test_ot_color_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS) +endif # HAVE_CAIRO_FT +endif # HAVE_FREETYPE + dist_check_SCRIPTS = \ check-c-linkage-decls.sh \ check-externs.sh \ diff --git a/src/test-ot-color.cc b/src/test-ot-color.cc index e3cabc738..5312554a5 100644 --- a/src/test-ot-color.cc +++ b/src/test-ot-color.cc @@ -23,12 +23,8 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -#include "hb-static.cc" -#include "hb-ot-color-cbdt-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.h" +#include "hb-ot.h" #include "hb-ft.h" @@ -40,71 +36,94 @@ #include #include -#ifdef HAVE_GLIB -#include -#endif #include #include static void -cbdt_callback (const uint8_t* data, unsigned int length, - unsigned int group, unsigned int gid) +png_dump (hb_face_t *face, unsigned int face_index) { - char output_path[255]; - sprintf (output_path, "out/cbdt-%d-%d.png", group, gid); - FILE *f = fopen (output_path, "wb"); - fwrite (data, 1, length, f); - fclose (f); -} + unsigned glyph_count = hb_face_get_glyph_count (face); + hb_font_t *font = hb_font_create (face); -static void -sbix_dump (hb_face_t *face) -{ - 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++) + /* ugly hack, scans the font for strikes, not needed for regular clients */ + #define STRIKES_MAX 20 + unsigned int strikes_count = 0; + unsigned int strikes[STRIKES_MAX] = {0}; + { + /* find a sample glyph */ + unsigned int sample_glyph_id; + /* we don't care much about different strikes for different glyphs */ + for (sample_glyph_id = 0; sample_glyph_id < glyph_count; sample_glyph_id++) { - hb_blob_t *blob; - unsigned int ppem = available_ppems[group]; - blob = sbix.reference_blob_for_glyph (glyph_id, ppem, ppem, - HB_TAG('p','n','g',' '), nullptr, nullptr); + hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id); + unsigned int blob_length = hb_blob_get_length (blob); + hb_blob_destroy (blob); + if (blob_length != 0) + break; + } + /* find strikes it has */ + unsigned int upem = hb_face_get_upem (face); + unsigned int blob_length = 0; + for (unsigned int ppem = 1; ppem <= upem && strikes_count < STRIKES_MAX; ppem++) + { + hb_font_set_ppem (font, ppem, ppem); + hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, sample_glyph_id); + unsigned int new_blob_length = hb_blob_get_length (blob); + if (blob_length != new_blob_length) + { + strikes_count++; + blob_length = new_blob_length; + } + strikes[strikes_count - 1] = ppem; + hb_blob_destroy (blob); + } + /* can't report the biggest strike correctly, and, we can't do anything about it */ + } + #undef STRIKES_MAX + + for (unsigned int strike = 0; strike < strikes_count; strike++) + for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++) + { + unsigned int ppem = strikes[strike]; + hb_font_set_ppem (font, ppem, ppem); + hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, glyph_id); + if (hb_blob_get_length (blob) == 0) continue; - char output_path[255]; - sprintf (output_path, "out/sbix-%d-%d.png", ppem, glyph_id); - FILE *f = fopen (output_path, "wb"); unsigned int length; - const char* data = hb_blob_get_data (blob, &length); + const char *data = hb_blob_get_data (blob, &length); + + char output_path[255]; + sprintf (output_path, "out/png-%d-%d-%d.png", glyph_id, strike, face_index); + + FILE *f = fopen (output_path, "wb"); fwrite (data, 1, length, f); fclose (f); + + hb_blob_destroy (blob); } - sbix.fini (); + + hb_font_destroy (font); } static void -svg_dump (hb_face_t *face) +svg_dump (hb_face_t *face, unsigned int face_index) { 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 = svg.reference_blob_for_glyph (glyph_id); + hb_blob_t *blob = hb_ot_color_glyph_reference_svg (face, glyph_id); if (hb_blob_get_length (blob) == 0) continue; unsigned int length; const char *data = hb_blob_get_data (blob, &length); - char output_path[256]; - sprintf (output_path, "out/svg-%d.svg%s", + char output_path[255]; + sprintf (output_path, "out/svg-%d-%d.svg%s", glyph_id, + face_index, // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405 (length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) ? "z" : ""); @@ -114,12 +133,10 @@ svg_dump (hb_face_t *face) hb_blob_destroy (blob); } - - svg.fini (); } static void -colr_cpal_dump (hb_face_t *face, cairo_font_face_t *cairo_face) +layered_glyph_dump (hb_face_t *face, cairo_font_face_t *cairo_face, unsigned int face_index) { unsigned int upem = hb_face_get_upem (face); @@ -171,11 +188,7 @@ colr_cpal_dump (hb_face_t *face, cairo_font_face_t *cairo_face) 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 - if (palette_count == 1) - sprintf (output_path, "out/colr-%d.svg", gid); - else - sprintf (output_path, "out/colr-%d-%d.svg", gid, palette); + sprintf (output_path, "out/colr-%d-%d-%d.svg", gid, palette, face_index); cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height); cairo_t *cr = cairo_create (surface); @@ -213,10 +226,8 @@ colr_cpal_dump (hb_face_t *face, cairo_font_face_t *cairo_face) static void dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem, - unsigned int num_glyphs) + unsigned int num_glyphs, unsigned int face_index) { - // Dump every glyph available on the font - return; // disabled for now for (unsigned int i = 0; i < num_glyphs; ++i) { cairo_text_extents_t extents; @@ -244,7 +255,7 @@ dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem, // Render { char output_path[255]; - sprintf (output_path, "out/%d.svg", i); + sprintf (output_path, "out/%d-%d.svg", face_index, i); cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height); cairo_t *cr = cairo_create (surface); cairo_set_font_face (cr, cairo_face); @@ -269,14 +280,14 @@ main (int argc, char **argv) } - FILE *font_name_file = fopen ("out/_font_name_file.txt", "r"); + FILE *font_name_file = fopen ("out/.dumped_font_name", "r"); if (font_name_file != nullptr) { fprintf (stderr, "Purge or move ./out folder in order to run a new dump\n"); exit (1); } - font_name_file = fopen ("out/_font_name_file.txt", "w"); + font_name_file = fopen ("out/.dumped_font_name", "w"); if (font_name_file == nullptr) { fprintf (stderr, "./out is not accessible as a folder, create it please\n"); @@ -286,36 +297,49 @@ main (int argc, char **argv) fclose (font_name_file); hb_blob_t *blob = hb_blob_create_from_file (argv[1]); - hb_face_t *face = hb_face_create (blob, 0); - hb_font_t *font = hb_font_create (face); - - OT::CBDT::accelerator_t cbdt; - cbdt.init (face); - cbdt.dump (cbdt_callback); - cbdt.fini (); - - sbix_dump (face); - - if (hb_ot_color_has_svg (face)) - svg_dump (face); - - cairo_font_face_t *cairo_face; + unsigned int num_faces = hb_face_count (blob); + if (num_faces == 0) { - FT_Library library; - FT_Init_FreeType (&library); - FT_Face ftface; - FT_New_Face (library, argv[1], 0, &ftface); - cairo_face = cairo_ft_font_face_create_for_ft_face (ftface, 0); + fprintf (stderr, "error: The file (%s) was corrupted, empty or not found", argv[1]); + exit (1); } - 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); - dump_glyphs (cairo_face, upem, num_glyphs); + for (unsigned int face_index = 0; face_index < hb_face_count (blob); face_index++) + { + hb_face_t *face = hb_face_create (blob, face_index); + hb_font_t *font = hb_font_create (face); + + if (hb_ot_color_has_png (face)) printf ("Dumping png (cbdt/sbix)...\n"); + png_dump (face, face_index); + + if (hb_ot_color_has_svg (face)) printf ("Dumping svg...\n"); + svg_dump (face, face_index); + + cairo_font_face_t *cairo_face; + { + FT_Library library; + FT_Init_FreeType (&library); + FT_Face ft_face; + FT_New_Face (library, argv[1], 0, &ft_face); + cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0); + } + if (hb_ot_color_has_layers (face) && hb_ot_color_has_palettes (face)) + printf ("Dumping layered color glyphs...\n"); + layered_glyph_dump (face, cairo_face, face_index); + + unsigned int num_glyphs = hb_face_get_glyph_count (face); + unsigned int upem = hb_face_get_upem (face); + + // disabled when color font as cairo rendering of NotoColorEmoji is soooo slow + if (!hb_ot_color_has_layers (face) && + !hb_ot_color_has_png (face) && + !hb_ot_color_has_svg (face)) + dump_glyphs (cairo_face, upem, num_glyphs, face_index); + + hb_font_destroy (font); + hb_face_destroy (face); + } - hb_font_destroy (font); - hb_face_destroy (face); hb_blob_destroy (blob); return 0;