[test-ot-color] Use public APIs on the tool
This commit is contained in:
parent
fb525f8943
commit
9c692e5b8d
|
@ -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 \
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue