Skip to content

Commit f2cb3c3

Browse files
committed
Add program to dump shaping results as JSON
This will be used for a test suite.
1 parent 555d112 commit f2cb3c3

File tree

2 files changed

+185
-1
lines changed

2 files changed

+185
-1
lines changed

src/Makefile.am

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,16 @@ libharfbuzz_la_CPPFLAGS = $(HBCFLAGS)
9292
libharfbuzz_la_LIBADD = $(HBLIBS)
9393
pkginclude_HEADERS = $(HBHEADERS)
9494

95-
noinst_PROGRAMS = main
95+
noinst_PROGRAMS = main shape
9696

9797
main_SOURCES = main.cc
9898
main_CPPFLAGS = $(HBCFLAGS)
9999
main_LDADD = libharfbuzz.la $(HBLIBS)
100100

101+
shape_SOURCES = shape.c
102+
shape_CPPFLAGS = $(HBCFLAGS)
103+
shape_LDADD = libharfbuzz.la $(HBLIBS)
104+
101105
TESTS =
102106

103107
if HAVE_ICU

src/shape.c

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
* Copyright (C) 2010 Evan Martin <martine@danga.com>
3+
*
4+
* This is part of HarfBuzz, an OpenType Layout engine library.
5+
*
6+
* Permission is hereby granted, without written agreement and without
7+
* license or royalty fees, to use, copy, modify, and distribute this
8+
* software and its documentation for any purpose, provided that the
9+
* above copyright notice and the following two paragraphs appear in
10+
* all copies of this software.
11+
*
12+
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13+
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14+
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15+
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16+
* DAMAGE.
17+
*
18+
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19+
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20+
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21+
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22+
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23+
*/
24+
25+
#include "hb.h"
26+
#include "hb-ft.h"
27+
#include "hb-glib.h"
28+
29+
#include <stdio.h>
30+
#include <glib.h>
31+
32+
/* Print an error message and exit 1. */
33+
void
34+
die (const char *fmt, ...)
35+
{
36+
va_list ap;
37+
va_start (ap, fmt);
38+
fprintf (stderr, "FATAL: ");
39+
vfprintf (stderr, fmt, ap);
40+
exit (1);
41+
}
42+
43+
/* Open and return a font file, aborting on failure. */
44+
FT_Face
45+
open_font (FT_Library library, const char *filename)
46+
{
47+
FT_Face face;
48+
FT_Error error = FT_New_Face (library,
49+
filename,
50+
0, /* TODO(?): face index */
51+
&face);
52+
if (error)
53+
die ("FT_New_Face error %d", error);
54+
55+
error = FT_Set_Char_Size (face, 0, 16*64,
56+
0, 0); /* use default 72dpi */
57+
if (error)
58+
die ("FT_Set_Char_Size error %d", error);
59+
60+
return face;
61+
}
62+
63+
void
64+
do_shape (FT_Face ftface, hb_buffer_t *buffer, char *input_text)
65+
{
66+
hb_font_t *font = hb_ft_font_create (ftface, NULL);
67+
hb_face_t *face = hb_ft_face_create (ftface, NULL);
68+
69+
hb_buffer_set_unicode_funcs (buffer, hb_glib_get_unicode_funcs ());
70+
/* TODO: hb_buffer_set_script, language */
71+
int input_len = strlen (input_text);
72+
hb_buffer_add_utf8 (buffer, input_text, input_len, 0, input_len);
73+
74+
hb_shape (font, face, buffer,
75+
NULL, 0); /* TODO: hb_feature_t */
76+
}
77+
78+
79+
/* Dump, as JSON, the result of shaping the buffer. */
80+
void
81+
dump (char *input_text, hb_buffer_t *buffer)
82+
{
83+
hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos (buffer);
84+
hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions (buffer);
85+
unsigned int len = hb_buffer_get_length (buffer);
86+
87+
printf ("{\n");
88+
printf (" \"input\": \"%s\",\n", input_text); /* XXX escaping */
89+
if (hb_buffer_get_direction (buffer) == HB_DIRECTION_RTL)
90+
printf (" \"rtl\": 1,\n");
91+
printf (" \"XXX\": \"font info (name, hash) would go here.\",\n");
92+
printf (" \"info\": [\n");
93+
unsigned i;
94+
for (i = 0; i < len; i++)
95+
{
96+
hb_glyph_info_t *info = &glyph_info[i];
97+
printf (" { \"codepoint\":%d, \"mask\":%d, \"cluster\":%d }%s\n",
98+
info->codepoint, info->mask, info->cluster,
99+
i < len-1 ? "," : "");
100+
}
101+
printf (" ],\n");
102+
printf (" \"position\": [\n");
103+
for (i = 0; i < len; i++)
104+
{
105+
hb_glyph_position_t *pos = &glyph_pos[i];
106+
printf (" { \"x_advance\":%d, \"y_advance\":%d, "
107+
"\"x_offset\":%d, \"y_offset\":%d }%s\n",
108+
pos->x_advance, pos->y_advance,
109+
pos->x_offset, pos->y_offset,
110+
i < len-1 ? "," : "");
111+
}
112+
printf (" ]\n");
113+
printf ("}\n");
114+
}
115+
116+
gboolean
117+
parse_args (int *argc, char*** argv, hb_buffer_t *buffer,
118+
char **filename, char **input)
119+
{
120+
gboolean rtl = FALSE;
121+
/* Just enough use of GOptionEntry to show the idea. */
122+
GOptionEntry option_entries[] =
123+
{
124+
{ "rtl", 0, 0, G_OPTION_ARG_NONE, &rtl,
125+
"Set buffer direction to RTL", NULL },
126+
{ NULL }
127+
};
128+
129+
GOptionContext *option_context = g_option_context_new ("FONTFILE INPUT");
130+
g_option_context_add_main_entries (option_context, option_entries, NULL);
131+
GError *error = NULL;
132+
if (!g_option_context_parse (option_context, argc, argv, &error))
133+
{
134+
fprintf (stderr, "%s\n", error->message);
135+
goto err;
136+
}
137+
138+
if (*argc < 3)
139+
{
140+
gchar *help = g_option_context_get_help (option_context, TRUE, NULL);
141+
fprintf (stderr, "%s", help);
142+
g_free (help);
143+
goto err;
144+
}
145+
g_option_context_free (option_context);
146+
147+
hb_buffer_set_direction (buffer, rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);
148+
*filename = (*argv)[1];
149+
*input = (*argv)[2];
150+
151+
return TRUE;
152+
153+
err:
154+
g_option_context_free (option_context);
155+
return FALSE;
156+
}
157+
158+
int
159+
main (int argc, char **argv)
160+
{
161+
hb_buffer_t *buffer = hb_buffer_create(0);
162+
163+
char *filename, *input_text;
164+
if (!parse_args (&argc, &argv, buffer, &filename, &input_text))
165+
return 1;
166+
167+
FT_Library ftlibrary;
168+
FT_Error fterror = FT_Init_FreeType (&ftlibrary);
169+
if (fterror)
170+
die ("FT_Init_FreeType error %d", fterror);
171+
FT_Face ftface = open_font (ftlibrary, filename);
172+
173+
do_shape (ftface, buffer, input_text);
174+
175+
dump (input_text, buffer);
176+
177+
FT_Done_FreeType (ftlibrary);
178+
179+
return 0;
180+
}

0 commit comments

Comments
 (0)