Flutter Engine
The Flutter Engine
Classes | Typedefs | Functions
main.cc File Reference
#include <hb-subset.h>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <limits>
#include <set>
#include <string>
#include "hb_wrappers.h"

Go to the source code of this file.

Classes

struct  HarfBuzzSubset< T, typename >
 

Typedefs

template<typename... >
using void_t = void
 

Functions

hb_codepoint_t ParseCodepoint (std::string_view arg, bool &optional)
 
void Usage ()
 
int main (int argc, char **argv)
 

Typedef Documentation

◆ void_t

template<typename... >
using void_t = void

Definition at line 65 of file main.cc.

Function Documentation

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 91 of file main.cc.

91 {
92 if (argc != 3) {
93 Usage();
94 return -1;
95 }
96 std::string output_file_path(argv[1]);
97 std::string input_file_path(argv[2]);
98 std::cout << "Using output file: " << output_file_path << std::endl;
99 std::cout << "Using source file: " << input_file_path << std::endl;
100
102 hb_blob_create_from_file(input_file_path.c_str()));
103 if (!hb_blob_get_length(font_blob.get())) {
104 std::cerr << "Failed to load input font " << input_file_path
105 << "; aborting. This error indicates that the font is invalid or "
106 "the current version of Harfbuzz is unable to process it."
107 << std::endl;
108 return -1;
109 }
110
111 HarfbuzzWrappers::HbFacePtr font_face(hb_face_create(font_blob.get(), 0));
112 if (font_face.get() == hb_face_get_empty()) {
113 std::cerr << "Failed to load input font face " << input_file_path
114 << "; aborting. This error indicates that the font is invalid or "
115 "the current version of Harfbuzz is unable to process it."
116 << std::endl;
117 return -1;
118 }
119
120 HarfbuzzWrappers::HbSubsetInputPtr input(hb_subset_input_create_or_fail());
121 {
122 hb_set_t* desired_codepoints = hb_subset_input_unicode_set(input.get());
123 HarfbuzzWrappers::HbSetPtr actual_codepoints(hb_set_create());
124 hb_face_collect_unicodes(font_face.get(), actual_codepoints.get());
125 std::string raw_codepoint;
126 while (std::cin >> raw_codepoint) {
127 bool optional = false;
128 auto codepoint =
129 ParseCodepoint(std::string_view(raw_codepoint), optional);
130 if (!codepoint) {
131 std::cerr << "Invalid codepoint for " << raw_codepoint << "; exiting."
132 << std::endl;
133 return -1;
134 }
135
136 if (!hb_set_has(actual_codepoints.get(), codepoint)) {
137 if (optional) {
138 // Code point is optional, so omit it.
139 continue;
140 }
141
142 std::cerr << "Codepoint " << raw_codepoint
143 << " not found in font, aborting." << std::endl;
144 return -1;
145 }
146 hb_set_add(desired_codepoints, codepoint);
147 }
148 if (hb_set_is_empty(desired_codepoints)) {
149 std::cerr << "No codepoints specified, exiting." << std::endl;
150 return -1;
151 }
152 }
153
155 HarfBuzzSubset<hb_subset_input_t*>::Make(font_face.get(), input.get());
156
157 if (!new_face || new_face.get() == hb_face_get_empty()) {
158 std::cerr
159 << "Failed to subset font; aborting. This error normally indicates "
160 "the current version of Harfbuzz is unable to process it."
161 << std::endl;
162 return -1;
163 }
164
165 HarfbuzzWrappers::HbBlobPtr result(hb_face_reference_blob(new_face.get()));
166 if (!hb_blob_get_length(result.get())) {
167 std::cerr << "Failed get new font bytes; aborting. This error may indicate "
168 "low availability of memory or a bug in Harfbuzz."
169 << std::endl;
170 return -1;
171 }
172
173 unsigned int data_length;
174 const char* data = hb_blob_get_data(result.get(), &data_length);
175
176 std::ofstream output_font_file;
177 output_font_file.open(output_file_path,
179 if (!output_font_file.is_open()) {
180 std::cerr << "Failed to open output file '" << output_file_path
181 << "'. The parent directory may not exist, or the user does not "
182 "have permission to create this file."
183 << std::endl;
184 return -1;
185 }
186 output_font_file.write(data, data_length);
187 output_font_file.flush();
188 output_font_file.close();
189
190 std::cout << "Wrote " << data_length << " bytes to " << output_file_path
191 << std::endl;
192 return 0;
193}
GAsyncResult * result
char ** argv
Definition: library.h:9
std::unique_ptr< hb_subset_input_t, hb_subset_input_deleter > HbSubsetInputPtr
Definition: hb_wrappers.h:32
std::unique_ptr< hb_blob_t, hb_blob_deleter > HbBlobPtr
Definition: hb_wrappers.h:29
std::unique_ptr< hb_face_t, hb_face_deleter > HbFacePtr
Definition: hb_wrappers.h:30
std::unique_ptr< hb_set_t, hb_set_deleter > HbSetPtr
Definition: hb_wrappers.h:33
SIN Vec< N, float > trunc(const Vec< N, float > &x)
Definition: SkVx.h:704
static HarfbuzzWrappers::HbFacePtr Make(hb_face_t *face, T input)
Definition: main.cc:69
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
void Usage()
Definition: main.cc:42
hb_codepoint_t ParseCodepoint(std::string_view arg, bool &optional)
Definition: main.cc:16

◆ ParseCodepoint()

hb_codepoint_t ParseCodepoint ( std::string_view  arg,
bool &  optional 
)

Definition at line 16 of file main.cc.

16 {
17 constexpr std::string_view kOptionalPrefix = "optional:";
18 if (arg.substr(0, kOptionalPrefix.length()) == kOptionalPrefix) {
19 optional = true;
20 arg = arg.substr(kOptionalPrefix.length());
21 } else {
22 optional = false;
23 }
24 uint64_t value = 0;
25 // Check for \u123, u123, otherwise let strtoul work it out.
26 if (arg[0] == 'u') {
27 value = strtoul(arg.data() + 1, nullptr, 16);
28 } else if (arg[0] == '\\' && arg[1] == 'u') {
29 value = strtoul(arg.data() + 2, nullptr, 16);
30 } else {
31 value = strtoul(arg.data(), nullptr, 0);
32 }
34 std::cerr << "The value '" << arg << "' (" << value
35 << ") could not be parsed as a valid unicode codepoint; aborting."
36 << std::endl;
37 exit(-1);
38 }
39 return value;
40}
uint8_t value
static float max(float r, float g, float b)
Definition: hsl.cpp:49
exit(kErrorExitCode)

◆ Usage()

void Usage ( )

Definition at line 42 of file main.cc.

42 {
43 std::cout << "Usage:" << std::endl;
44 std::cout << "font-subset <output.ttf> <input.ttf>" << std::endl;
45 std::cout << std::endl;
46 std::cout << "The output.ttf file will be overwritten if it exists already "
47 "and the subsetting operation succeeds."
48 << std::endl;
49 std::cout << "Codepoints should be specified on stdin, separated by spaces, "
50 "and must be input as decimal numbers (123), hexadecimal "
51 "numbers (0x7B), or unicode hexadecimal characters (\\u7B)."
52 << std::endl;
53 std::cout << "Codepoints can be prefixed by the string \"optional:\" to "
54 "specify that the codepoint can be omitted if it isn't found "
55 "in the input font file."
56 << std::endl;
57 std::cout << "Input terminates with a newline." << std::endl;
58 std::cout
59 << "This program will de-duplicate codepoints if the same codepoint is "
60 "specified multiple times, e.g. '123 123' will be treated as '123'."
61 << std::endl;
62}