[test-ot-color] Use public APIs on the tool

This commit is contained in:
Ebrahim Byagowi 2018-10-29 11:36:11 +03:30
parent fb525f8943
commit 9c692e5b8d
2 changed files with 116 additions and 83 deletions

View File

@ -377,6 +377,15 @@ test_would_substitute_SOURCES = test-would-substitute.cc
test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) 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 = \ dist_check_SCRIPTS = \
check-c-linkage-decls.sh \ check-c-linkage-decls.sh \
check-externs.sh \ check-externs.sh \

View File

@ -23,12 +23,8 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/ */
#include "hb-static.cc" #include "hb.h"
#include "hb-ot-color-cbdt-table.hh" #include "hb-ot.h"
#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-ft.h" #include "hb-ft.h"
@ -40,71 +36,94 @@
#include <cairo-ft.h> #include <cairo-ft.h>
#include <cairo-svg.h> #include <cairo-svg.h>
#ifdef HAVE_GLIB
#include <glib.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
static void static void
cbdt_callback (const uint8_t* data, unsigned int length, png_dump (hb_face_t *face, unsigned int face_index)
unsigned int group, unsigned int gid)
{
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);
}
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++)
{
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);
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);
fwrite (data, 1, length, f);
fclose (f);
}
sbix.fini ();
}
static void
svg_dump (hb_face_t *face)
{ {
unsigned glyph_count = hb_face_get_glyph_count (face); unsigned glyph_count = hb_face_get_glyph_count (face);
hb_font_t *font = hb_font_create (face);
OT::SVG::accelerator_t svg; /* ugly hack, scans the font for strikes, not needed for regular clients */
svg.init (face); #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_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++) for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++)
{ {
hb_blob_t *blob = svg.reference_blob_for_glyph (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; if (hb_blob_get_length (blob) == 0) continue;
unsigned int length; unsigned int length;
const char *data = hb_blob_get_data (blob, &length); const char *data = hb_blob_get_data (blob, &length);
char output_path[256]; char output_path[255];
sprintf (output_path, "out/svg-%d.svg%s", 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);
}
hb_font_destroy (font);
}
static void
svg_dump (hb_face_t *face, unsigned int face_index)
{
unsigned glyph_count = hb_face_get_glyph_count (face);
for (unsigned int glyph_id = 0; glyph_id < glyph_count; 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[255];
sprintf (output_path, "out/svg-%d-%d.svg%s",
glyph_id, glyph_id,
face_index,
// append "z" if the content is gzipped, https://stackoverflow.com/a/6059405 // append "z" if the content is gzipped, https://stackoverflow.com/a/6059405
(length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) ? "z" : ""); (length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) ? "z" : "");
@ -114,12 +133,10 @@ svg_dump (hb_face_t *face)
hb_blob_destroy (blob); hb_blob_destroy (blob);
} }
svg.fini ();
} }
static void 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); 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); hb_ot_color_palette_get_colors (face, palette, 0, &num_colors, colors);
if (num_colors) if (num_colors)
{ {
// If we have more than one palette, use a simpler naming sprintf (output_path, "out/colr-%d-%d-%d.svg", gid, palette, face_index);
if (palette_count == 1)
sprintf (output_path, "out/colr-%d.svg", gid);
else
sprintf (output_path, "out/colr-%d-%d.svg", gid, palette);
cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height); cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
cairo_t *cr = cairo_create (surface); 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 static void
dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem, 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) for (unsigned int i = 0; i < num_glyphs; ++i)
{ {
cairo_text_extents_t extents; cairo_text_extents_t extents;
@ -244,7 +255,7 @@ dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem,
// Render // Render
{ {
char output_path[255]; 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_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
cairo_t *cr = cairo_create (surface); cairo_t *cr = cairo_create (surface);
cairo_set_font_face (cr, cairo_face); 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) if (font_name_file != nullptr)
{ {
fprintf (stderr, "Purge or move ./out folder in order to run a new dump\n"); fprintf (stderr, "Purge or move ./out folder in order to run a new dump\n");
exit (1); 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) if (font_name_file == nullptr)
{ {
fprintf (stderr, "./out is not accessible as a folder, create it please\n"); 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); fclose (font_name_file);
hb_blob_t *blob = hb_blob_create_from_file (argv[1]); hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
hb_face_t *face = hb_face_create (blob, 0); 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);
}
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); hb_font_t *font = hb_font_create (face);
OT::CBDT::accelerator_t cbdt; if (hb_ot_color_has_png (face)) printf ("Dumping png (cbdt/sbix)...\n");
cbdt.init (face); png_dump (face, face_index);
cbdt.dump (cbdt_callback);
cbdt.fini ();
sbix_dump (face); if (hb_ot_color_has_svg (face)) printf ("Dumping svg...\n");
svg_dump (face, face_index);
if (hb_ot_color_has_svg (face))
svg_dump (face);
cairo_font_face_t *cairo_face; cairo_font_face_t *cairo_face;
{ {
FT_Library library; FT_Library library;
FT_Init_FreeType (&library); FT_Init_FreeType (&library);
FT_Face ftface; FT_Face ft_face;
FT_New_Face (library, argv[1], 0, &ftface); FT_New_Face (library, argv[1], 0, &ft_face);
cairo_face = cairo_ft_font_face_create_for_ft_face (ftface, 0); 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)) if (hb_ot_color_has_layers (face) && hb_ot_color_has_palettes (face))
colr_cpal_dump (face, cairo_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 num_glyphs = hb_face_get_glyph_count (face);
unsigned int upem = hb_face_get_upem (face); unsigned int upem = hb_face_get_upem (face);
dump_glyphs (cairo_face, upem, num_glyphs);
// 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_font_destroy (font);
hb_face_destroy (face); hb_face_destroy (face);
}
hb_blob_destroy (blob); hb_blob_destroy (blob);
return 0; return 0;