[test-ot-color] Use public APIs on the tool
authorEbrahim Byagowi <ebrahim@gnu.org>
Mon, 29 Oct 2018 08:06:11 +0000 (11:36 +0330)
committerEbrahim Byagowi <ebrahim@gnu.org>
Mon, 29 Oct 2018 08:52:39 +0000 (12:22 +0330)
src/Makefile.am
src/test-ot-color.cc

index 0b9ae9d..a51048b 100644 (file)
@@ -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 \
index e3cabc7..5312554 100644 (file)
  * 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"
 
 #include <cairo-ft.h>
 #include <cairo-svg.h>
 
-#ifdef HAVE_GLIB
-#include <glib.h>
-#endif
 #include <stdlib.h>
 #include <stdio.h>
 
 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 = 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_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_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;
 
+      unsigned int length;
+      const char *data = hb_blob_get_data (blob, &length);
+
       char output_path[255];
-      sprintf (output_path, "out/sbix-%d-%d.png", ppem, glyph_id);
+      sprintf (output_path, "out/png-%d-%d-%d.png", glyph_id, strike, face_index);
+
       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);
+
+      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);
+  unsigned int num_faces = hb_face_count (blob);
+  if (num_faces == 0)
+  {
+    fprintf (stderr, "error: The file (%s) was corrupted, empty or not found", argv[1]);
+    exit (1);
+  }
 
-  OT::CBDT::accelerator_t cbdt;
-  cbdt.init (face);
-  cbdt.dump (cbdt_callback);
-  cbdt.fini ();
+  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);
 
-  sbix_dump (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))
-    svg_dump (face);
+    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 ftface;
-    FT_New_Face (library, argv[1], 0, &ftface);
-    cairo_face = cairo_ft_font_face_create_for_ft_face (ftface, 0);
-  }
-  if (hb_ot_color_has_layers (face) && hb_ot_color_has_palettes (face))
-    colr_cpal_dump (face, cairo_face);
+    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);
-  dump_glyphs (cairo_face, upem, num_glyphs);
+    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;