1 /*
2 * Copyright © 2010 Behdad Esfahbod
3 * Copyright © 2011,2012 Google, Inc.
4 *
5 * This is part of HarfBuzz, a text shaping library.
6 *
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Google Author(s): Behdad Esfahbod
26 */
27
28 #include "batch.hh"
29 #include "font-options.hh"
30 #include "main-font-text.hh"
31 #include "output-options.hh"
32 #include "shape-consumer.hh"
33 #include "shape-format.hh"
34 #include "text-options.hh"
35
36 const unsigned DEFAULT_FONT_SIZE = FONT_SIZE_UPEM;
37 const unsigned SUBPIXEL_BITS = 0;
38
39 struct output_buffer_t : output_options_t<>
40 {
add_optionsoutput_buffer_t41 void add_options (option_parser_t *parser)
42 {
43 parser->set_summary ("Shape text with given font.");
44 output_options_t::add_options (parser, hb_buffer_serialize_list_formats ());
45 format.add_options (parser);
46 }
47
initoutput_buffer_t48 void init (hb_buffer_t *buffer, const font_options_t *font_opts)
49 {
50 gs = g_string_new (nullptr);
51 line_no = 0;
52 font = hb_font_reference (font_opts->font);
53
54 if (!output_format)
55 serialize_format = HB_BUFFER_SERIALIZE_FORMAT_TEXT;
56 else
57 serialize_format = hb_buffer_serialize_format_from_string (output_format, -1);
58 /* An empty "output_format" parameter basically skips output generating.
59 * Useful for benchmarking. */
60 if ((!output_format || *output_format) &&
61 !hb_buffer_serialize_format_to_string (serialize_format))
62 {
63 if (explicit_output_format)
64 fail (false, "Unknown output format `%s'; supported formats are: %s",
65 output_format,
66 g_strjoinv ("/", const_cast<char**> (hb_buffer_serialize_list_formats ())));
67 else
68 /* Just default to TEXT if not explicitly requested and the
69 * file extension is not recognized. */
70 serialize_format = HB_BUFFER_SERIALIZE_FORMAT_TEXT;
71 }
72
73 unsigned int flags = HB_BUFFER_SERIALIZE_FLAG_DEFAULT;
74 if (!format.show_glyph_names)
75 flags |= HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES;
76 if (!format.show_clusters)
77 flags |= HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS;
78 if (!format.show_positions)
79 flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS;
80 if (!format.show_advances)
81 flags |= HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES;
82 if (format.show_extents)
83 flags |= HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS;
84 if (format.show_flags)
85 flags |= HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS;
86 serialize_flags = (hb_buffer_serialize_flags_t) flags;
87
88 if (format.trace)
89 hb_buffer_set_message_func (buffer, message_func, this, nullptr);
90 }
new_lineoutput_buffer_t91 void new_line () { line_no++; }
consume_textoutput_buffer_t92 void consume_text (hb_buffer_t *buffer,
93 const char *text,
94 unsigned int text_len,
95 hb_bool_t utf8_clusters)
96 {
97 g_string_set_size (gs, 0);
98 format.serialize_buffer_of_text (buffer, line_no, text, text_len, font, gs);
99 fprintf (out_fp, "%s", gs->str);
100 }
erroroutput_buffer_t101 void error (const char *message)
102 {
103 g_string_set_size (gs, 0);
104 format.serialize_message (line_no, "error", message, gs);
105 fprintf (out_fp, "%s", gs->str);
106 }
consume_glyphsoutput_buffer_t107 void consume_glyphs (hb_buffer_t *buffer,
108 const char *text,
109 unsigned int text_len,
110 hb_bool_t utf8_clusters)
111 {
112 g_string_set_size (gs, 0);
113 format.serialize_buffer_of_glyphs (buffer, line_no, text, text_len, font,
114 serialize_format, serialize_flags, gs);
115 fprintf (out_fp, "%s", gs->str);
116 }
finishoutput_buffer_t117 void finish (hb_buffer_t *buffer, const font_options_t *font_opts)
118 {
119 hb_buffer_set_message_func (buffer, nullptr, nullptr, nullptr);
120 hb_font_destroy (font);
121 g_string_free (gs, true);
122 gs = nullptr;
123 font = nullptr;
124 }
125
126 static hb_bool_t
message_funcoutput_buffer_t127 message_func (hb_buffer_t *buffer,
128 hb_font_t *font,
129 const char *message,
130 void *user_data)
131 {
132 output_buffer_t *that = (output_buffer_t *) user_data;
133 that->trace (buffer, font, message);
134 return true;
135 }
136
137 void
traceoutput_buffer_t138 trace (hb_buffer_t *buffer,
139 hb_font_t *font,
140 const char *message)
141 {
142 g_string_set_size (gs, 0);
143 format.serialize_line_no (line_no, gs);
144 g_string_append_printf (gs, "trace: %s buffer: ", message);
145 format.serialize (buffer, font, serialize_format, serialize_flags, gs);
146 g_string_append_c (gs, '\n');
147 fprintf (out_fp, "%s", gs->str);
148 }
149
150
151 protected:
152
153 shape_format_options_t format;
154
155 GString *gs = nullptr;
156 unsigned int line_no = 0;
157 hb_font_t *font = nullptr;
158 hb_buffer_serialize_format_t serialize_format = HB_BUFFER_SERIALIZE_FORMAT_INVALID;
159 hb_buffer_serialize_flags_t serialize_flags = HB_BUFFER_SERIALIZE_FLAG_DEFAULT;
160 };
161
162 int
main(int argc,char ** argv)163 main (int argc, char **argv)
164 {
165 using main_t = main_font_text_t<shape_consumer_t<output_buffer_t>, font_options_t, shape_text_options_t>;
166 return batch_main<main_t> (argc, argv);
167 }
168