1 /*
2 * Copyright © 2011 Google, Inc.
3 *
4 * This is part of HarfBuzz, a text shaping 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 * Google Author(s): Behdad Esfahbod
25 */
26
27 #ifndef FACE_OPTIONS_HH
28 #define FACE_OPTIONS_HH
29
30 #include "options.hh"
31
32 struct face_options_t
33 {
~face_options_tface_options_t34 ~face_options_t ()
35 {
36 g_free (font_file);
37 }
38
set_faceface_options_t39 void set_face (hb_face_t *face_)
40 { face = face_; }
41
42 void add_options (option_parser_t *parser);
43
44 void post_parse (GError **error);
45
46 static struct cache_t
47 {
~cache_tface_options_t::cache_t48 ~cache_t ()
49 {
50 g_free (font_path);
51 hb_blob_destroy (blob);
52 hb_face_destroy (face);
53 }
54
55 char *font_path = nullptr;
56 hb_blob_t *blob = nullptr;
57 unsigned face_index = (unsigned) -1;
58 hb_face_t *face = nullptr;
59 } cache;
60
61 char *font_file = nullptr;
62 unsigned face_index = 0;
63
64 hb_blob_t *blob = nullptr;
65 hb_face_t *face = nullptr;
66 };
67
68
69 face_options_t::cache_t face_options_t::cache {};
70
71 void
post_parse(GError ** error)72 face_options_t::post_parse (GError **error)
73 {
74 if (!font_file)
75 {
76 g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
77 "No font file set");
78 return;
79 }
80
81 assert (font_file);
82
83 const char *font_path = font_file;
84
85 if (0 == strcmp (font_path, "-"))
86 {
87 #if defined(_WIN32) || defined(__CYGWIN__)
88 setmode (fileno (stdin), O_BINARY);
89 font_path = "STDIN";
90 #else
91 font_path = "/dev/stdin";
92 #endif
93 }
94
95 if (!cache.font_path || 0 != strcmp (cache.font_path, font_path))
96 {
97 hb_blob_destroy (cache.blob);
98 cache.blob = hb_blob_create_from_file_or_fail (font_path);
99
100 free ((char *) cache.font_path);
101 cache.font_path = g_strdup (font_path);
102
103 if (!cache.blob)
104 {
105 g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
106 "%s: Failed reading file", font_path);
107 return;
108 }
109
110 hb_face_destroy (cache.face);
111 cache.face = nullptr;
112 cache.face_index = (unsigned) -1;
113 }
114
115 if (cache.face_index != face_index)
116 {
117 hb_face_destroy (cache.face);
118 cache.face = hb_face_create (cache.blob, face_index);
119 cache.face_index = face_index;
120 }
121
122 blob = cache.blob;
123 face = cache.face;
124 }
125
126 void
add_options(option_parser_t * parser)127 face_options_t::add_options (option_parser_t *parser)
128 {
129 GOptionEntry entries[] =
130 {
131 {"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"},
132 {"face-index", 0, 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"},
133 {nullptr}
134 };
135 parser->add_group (entries,
136 "face",
137 "Font-face options:",
138 "Options for the font face",
139 this);
140 }
141
142 #endif
143