OLD | NEW |
| (Empty) |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #if !defined(_WIN32) | |
6 #ifdef __linux__ | |
7 // Linux | |
8 #include <ft2build.h> | |
9 #include FT_FREETYPE_H | |
10 #include FT_OUTLINE_H | |
11 #else | |
12 // Mac OS X | |
13 #include <ApplicationServices/ApplicationServices.h> // g++ -framework Cocoa | |
14 #endif // __linux__ | |
15 #include <unistd.h> | |
16 #else | |
17 // Windows | |
18 #include <io.h> | |
19 #include <Windows.h> | |
20 #endif // !defiend(_WIN32) | |
21 | |
22 #include <fcntl.h> | |
23 #include <sys/stat.h> | |
24 | |
25 #include <cstdio> | |
26 #include <cstdlib> | |
27 #include <cstring> | |
28 | |
29 #include "opentype-sanitiser.h" | |
30 #include "ots-memory-stream.h" | |
31 | |
32 namespace { | |
33 | |
34 int Usage(const char *argv0) { | |
35 std::fprintf(stderr, "Usage: %s <ttf file>\n", argv0); | |
36 return 1; | |
37 } | |
38 | |
39 bool ReadFile(const char *file_name, uint8_t **data, size_t *file_size); | |
40 bool DumpResults(const uint8_t *result1, const size_t len1, | |
41 const uint8_t *result2, const size_t len2); | |
42 | |
43 #if defined(_WIN32) | |
44 #define ADDITIONAL_OPEN_FLAGS O_BINARY | |
45 #else | |
46 #define ADDITIONAL_OPEN_FLAGS 0 | |
47 #endif | |
48 | |
49 bool ReadFile(const char *file_name, uint8_t **data, size_t *file_size) { | |
50 const int fd = open(file_name, O_RDONLY | ADDITIONAL_OPEN_FLAGS); | |
51 if (fd < 0) { | |
52 return false; | |
53 } | |
54 | |
55 struct stat st; | |
56 fstat(fd, &st); | |
57 | |
58 *file_size = st.st_size; | |
59 *data = new uint8_t[st.st_size]; | |
60 if (read(fd, *data, st.st_size) != st.st_size) { | |
61 close(fd); | |
62 return false; | |
63 } | |
64 close(fd); | |
65 return true; | |
66 } | |
67 | |
68 bool DumpResults(const uint8_t *result1, const size_t len1, | |
69 const uint8_t *result2, const size_t len2) { | |
70 int fd1 = open("out1.ttf", | |
71 O_WRONLY | O_CREAT | O_TRUNC | ADDITIONAL_OPEN_FLAGS, 0600); | |
72 int fd2 = open("out2.ttf", | |
73 O_WRONLY | O_CREAT | O_TRUNC | ADDITIONAL_OPEN_FLAGS, 0600); | |
74 if (fd1 < 0 || fd2 < 0) { | |
75 perror("opening output file"); | |
76 return false; | |
77 } | |
78 if ((write(fd1, result1, len1) < 0) || | |
79 (write(fd2, result2, len2) < 0)) { | |
80 perror("writing output file"); | |
81 close(fd1); | |
82 close(fd2); | |
83 return false; | |
84 } | |
85 close(fd1); | |
86 close(fd2); | |
87 return true; | |
88 } | |
89 | |
90 // Platform specific implementations. | |
91 bool VerifyTranscodedFont(uint8_t *result, const size_t len); | |
92 | |
93 #if defined(__linux__) | |
94 // Linux | |
95 bool VerifyTranscodedFont(uint8_t *result, const size_t len) { | |
96 FT_Library library; | |
97 FT_Error error = ::FT_Init_FreeType(&library); | |
98 if (error) { | |
99 return false; | |
100 } | |
101 FT_Face dummy; | |
102 error = ::FT_New_Memory_Face(library, result, len, 0, &dummy); | |
103 if (error) { | |
104 return false; | |
105 } | |
106 ::FT_Done_Face(dummy); | |
107 return true; | |
108 } | |
109 | |
110 #elif defined(__APPLE_CC__) | |
111 // Mac | |
112 bool VerifyTranscodedFont(uint8_t *result, const size_t len) { | |
113 CFDataRef data = CFDataCreate(0, result, len); | |
114 if (!data) { | |
115 return false; | |
116 } | |
117 | |
118 CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(data); | |
119 CGFontRef cgFontRef = CGFontCreateWithDataProvider(dataProvider); | |
120 CGDataProviderRelease(dataProvider); | |
121 CFRelease(data); | |
122 if (!cgFontRef) { | |
123 return false; | |
124 } | |
125 | |
126 size_t numGlyphs = CGFontGetNumberOfGlyphs(cgFontRef); | |
127 CGFontRelease(cgFontRef); | |
128 if (!numGlyphs) { | |
129 return false; | |
130 } | |
131 return true; | |
132 } | |
133 | |
134 #elif defined(_WIN32) | |
135 // Windows | |
136 bool VerifyTranscodedFont(uint8_t *result, const size_t len) { | |
137 DWORD num_fonts = 0; | |
138 HANDLE handle = AddFontMemResourceEx(result, len, 0, &num_fonts); | |
139 if (!handle) { | |
140 return false; | |
141 } | |
142 RemoveFontMemResourceEx(handle); | |
143 return true; | |
144 } | |
145 | |
146 #else | |
147 bool VerifyTranscodedFont(uint8_t *result, const size_t len) { | |
148 std::fprintf(stderr, "Can't verify the transcoded font on this platform.\n"); | |
149 return false; | |
150 } | |
151 | |
152 #endif | |
153 | |
154 } // namespace | |
155 | |
156 int main(int argc, char **argv) { | |
157 if (argc != 2) return Usage(argv[0]); | |
158 | |
159 size_t file_size = 0; | |
160 uint8_t *data = 0; | |
161 if (!ReadFile(argv[1], &data, &file_size)) { | |
162 std::fprintf(stderr, "Failed to read file!\n"); | |
163 return 1; | |
164 } | |
165 | |
166 // A transcoded font is usually smaller than an original font. | |
167 // However, it can be slightly bigger than the original one due to | |
168 // name table replacement and/or padding for glyf table. | |
169 // | |
170 // However, a WOFF font gets decompressed and so can be *much* larger than | |
171 // the original. | |
172 uint8_t *result = new uint8_t[file_size * 8]; | |
173 ots::MemoryStream output(result, file_size * 8); | |
174 | |
175 ots::OTSContext context; | |
176 | |
177 bool r = context.Process(&output, data, file_size); | |
178 if (!r) { | |
179 std::fprintf(stderr, "Failed to sanitise file!\n"); | |
180 return 1; | |
181 } | |
182 const size_t result_len = output.Tell(); | |
183 delete[] data; | |
184 | |
185 uint8_t *result2 = new uint8_t[result_len]; | |
186 ots::MemoryStream output2(result2, result_len); | |
187 r = context.Process(&output2, result, result_len); | |
188 if (!r) { | |
189 std::fprintf(stderr, "Failed to sanitise previous output!\n"); | |
190 return 1; | |
191 } | |
192 const size_t result2_len = output2.Tell(); | |
193 | |
194 bool dump_results = false; | |
195 if (result2_len != result_len) { | |
196 std::fprintf(stderr, "Outputs differ in length\n"); | |
197 dump_results = true; | |
198 } else if (std::memcmp(result2, result, result_len)) { | |
199 std::fprintf(stderr, "Outputs differ in content\n"); | |
200 dump_results = true; | |
201 } | |
202 | |
203 if (dump_results) { | |
204 std::fprintf(stderr, "Dumping results to out1.tff and out2.tff\n"); | |
205 if (!DumpResults(result, result_len, result2, result2_len)) { | |
206 std::fprintf(stderr, "Failed to dump output files.\n"); | |
207 return 1; | |
208 } | |
209 } | |
210 | |
211 // Verify that the transcoded font can be opened by the font renderer for | |
212 // Linux (FreeType2), Mac OS X, or Windows. | |
213 if (!VerifyTranscodedFont(result, result_len)) { | |
214 std::fprintf(stderr, "Failed to verify the transcoded font\n"); | |
215 return 1; | |
216 } | |
217 | |
218 return 0; | |
219 } | |
OLD | NEW |