* 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" : "");
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);
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);
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;
// 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);
}
- 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");
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;