f680e05cd7274018e060eacc2a44f0965cdcbf48
[platform/upstream/harfbuzz.git] / util / face-options.hh
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 {
34   ~face_options_t ()
35   {
36     g_free (font_file);
37   }
38
39   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   {
48     ~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
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
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