Bug Summary

File:src/fcfreetype.c
Location:line 2576, column 5
Description:Value stored to 'cur_offset' is never read

Annotated Source Code

1/*
2 * fontconfig/src/fcfreetype.c
3 *
4 * Copyright © 2001 Keith Packard
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of the author(s) not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. The authors make no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
16 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25/*
26 Copyright © 2002-2003 by Juliusz Chroboczek
27
28 Permission is hereby granted, free of charge, to any person obtaining a copy
29 of this software and associated documentation files (the "Software"), to deal
30 in the Software without restriction, including without limitation the rights
31 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
32 copies of the Software, and to permit persons to whom the Software is
33 furnished to do so, subject to the following conditions:
34
35 The above copyright notice and this permission notice shall be included in
36 all copies or substantial portions of the Software.
37
38 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44 THE SOFTWARE.
45*/
46
47#include "fcint.h"
48#include "fcftint.h"
49#include <stdlib.h>
50#include <stdio.h>
51#include <string.h>
52#include <ft2build.h>
53#include FT_FREETYPE_H<freetype/freetype.h>
54#include FT_TRUETYPE_TABLES_H<freetype/tttables.h>
55#include FT_SFNT_NAMES_H<freetype/ftsnames.h>
56#include FT_TRUETYPE_IDS_H<freetype/ttnameid.h>
57#include FT_TYPE1_TABLES_H<freetype/t1tables.h>
58#if HAVE_FT_GET_X11_FONT_FORMAT1
59#include FT_XFREE86_H<freetype/ftxf86.h>
60#endif
61#if HAVE_FT_GET_BDF_PROPERTY1
62#include FT_BDF_H<freetype/ftbdf.h>
63#include FT_MODULE_H<freetype/ftmodapi.h>
64#endif
65#include FT_MULTIPLE_MASTERS_H<freetype/ftmm.h>
66
67#include "ftglue.h"
68
69#if HAVE_WARNING_CPP_DIRECTIVE1
70#if !HAVE_FT_GET_BDF_PROPERTY1
71#warning "No FT_Get_BDF_Property: Please install freetype 2.1.4 or later"
72#endif
73
74#if !HAVE_FT_GET_PS_FONT_INFO1
75#warning "No FT_Get_PS_Font_Info: Please install freetype 2.1.1 or later"
76#endif
77#endif
78
79/*
80 * Keep Han languages separated by eliminating languages
81 * that the codePageRange bits says aren't supported
82 */
83
84static const struct {
85 char bit;
86 const FcChar8 lang[6];
87} FcCodePageRange[] = {
88 { 17, "ja" },
89 { 18, "zh-cn" },
90 { 19, "ko" },
91 { 20, "zh-tw" },
92};
93
94#define NUM_CODE_PAGE_RANGE(int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0]) (int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
95
96FcBool
97FcFreeTypeIsExclusiveLang (const FcChar8 *lang)
98{
99 int i;
100
101 for (i = 0; i < NUM_CODE_PAGE_RANGE(int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0]); i++)
102 {
103 if (FcLangCompare (lang, FcCodePageRange[i].lang) == FcLangEqual)
104 return FcTrue1;
105 }
106 return FcFalse0;
107}
108
109typedef struct {
110 const FT_UShort platform_id;
111 const FT_UShort encoding_id;
112 const char fromcode[12];
113} FcFtEncoding;
114
115#define TT_ENCODING_DONT_CARE0xffff 0xffff
116#define FC_ENCODING_MAC_ROMAN"MACINTOSH" "MACINTOSH"
117
118static const FcFtEncoding fcFtEncoding[] = {
119 { TT_PLATFORM_APPLE_UNICODE0, TT_ENCODING_DONT_CARE0xffff, "UTF-16BE" },
120 { TT_PLATFORM_MACINTOSH1, TT_MAC_ID_ROMAN0, "MACINTOSH" },
121 { TT_PLATFORM_MACINTOSH1, TT_MAC_ID_JAPANESE1, "SJIS" },
122 { TT_PLATFORM_MICROSOFT3, TT_MS_ID_SYMBOL_CS0, "UTF-16BE" },
123 { TT_PLATFORM_MICROSOFT3, TT_MS_ID_UNICODE_CS1, "UTF-16BE" },
124 { TT_PLATFORM_MICROSOFT3, TT_MS_ID_SJIS2, "SJIS-WIN" },
125 { TT_PLATFORM_MICROSOFT3, TT_MS_ID_GB23123, "GB2312" },
126 { TT_PLATFORM_MICROSOFT3, TT_MS_ID_BIG_54, "BIG-5" },
127 { TT_PLATFORM_MICROSOFT3, TT_MS_ID_WANSUNG5, "Wansung" },
128 { TT_PLATFORM_MICROSOFT3, TT_MS_ID_JOHAB6, "Johab" },
129 { TT_PLATFORM_MICROSOFT3, TT_MS_ID_UCS_410, "UTF-16BE" },
130 { TT_PLATFORM_ISO2, TT_ISO_ID_7BIT_ASCII0, "ASCII" },
131 { TT_PLATFORM_ISO2, TT_ISO_ID_106461, "UTF-16BE" },
132 { TT_PLATFORM_ISO2, TT_ISO_ID_8859_12, "ISO-8859-1" },
133};
134
135#define NUM_FC_FT_ENCODING(int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0])) (int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0]))
136
137typedef struct {
138 const FT_UShort platform_id;
139 const FT_UShort language_id;
140 const char lang[8];
141} FcFtLanguage;
142
143#define TT_LANGUAGE_DONT_CARE0xffff 0xffff
144
145static const FcFtLanguage fcFtLanguage[] = {
146 { TT_PLATFORM_APPLE_UNICODE0, TT_LANGUAGE_DONT_CARE0xffff, "" },
147 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_ENGLISH0, "en" },
148 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_FRENCH1, "fr" },
149 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_GERMAN2, "de" },
150 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_ITALIAN3, "it" },
151 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_DUTCH4, "nl" },
152 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SWEDISH5, "sv" },
153 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SPANISH6, "es" },
154 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_DANISH7, "da" },
155 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_PORTUGUESE8, "pt" },
156 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_NORWEGIAN9, "no" },
157 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_HEBREW10, "he" },
158 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_JAPANESE11, "ja" },
159 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_ARABIC12, "ar" },
160 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_FINNISH13, "fi" },
161 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_GREEK14, "el" },
162 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_ICELANDIC15, "is" },
163 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MALTESE16, "mt" },
164 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_TURKISH17, "tr" },
165 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_CROATIAN18, "hr" },
166 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_CHINESE_TRADITIONAL19, "zh-tw" },
167 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_URDU20, "ur" },
168 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_HINDI21, "hi" },
169 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_THAI22, "th" },
170 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_KOREAN23, "ko" },
171 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_LITHUANIAN24, "lt" },
172 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_POLISH25, "pl" },
173 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_HUNGARIAN26, "hu" },
174 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_ESTONIAN27, "et" },
175 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_LETTISH28, "lv" },
176/* { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SAAMISK, ??? */
177 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_FAEROESE30, "fo" },
178 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_FARSI31, "fa" },
179 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_RUSSIAN32, "ru" },
180 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_CHINESE_SIMPLIFIED33, "zh-cn" },
181 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_FLEMISH34, "nl" },
182 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_IRISH35, "ga" },
183 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_ALBANIAN36, "sq" },
184 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_ROMANIAN37, "ro" },
185 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_CZECH38, "cs" },
186 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SLOVAK39, "sk" },
187 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SLOVENIAN40, "sl" },
188 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_YIDDISH41, "yi" },
189 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SERBIAN42, "sr" },
190 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MACEDONIAN43, "mk" },
191 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_BULGARIAN44, "bg" },
192 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_UKRAINIAN45, "uk" },
193 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_BYELORUSSIAN46, "be" },
194 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_UZBEK47, "uz" },
195 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_KAZAKH48, "kk" },
196 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_AZERBAIJANI49, "az" },
197 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT49, "az" },
198 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT50, "ar" },
199 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_ARMENIAN51, "hy" },
200 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_GEORGIAN52, "ka" },
201 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MOLDAVIAN53, "mo" },
202 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_KIRGHIZ54, "ky" },
203 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_TAJIKI55, "tg" },
204 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_TURKMEN56, "tk" },
205 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MONGOLIAN57, "mo" },
206 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT57,"mo" },
207 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT58, "mo" },
208 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_PASHTO59, "ps" },
209 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_KURDISH60, "ku" },
210 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_KASHMIRI61, "ks" },
211 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SINDHI62, "sd" },
212 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_TIBETAN63, "bo" },
213 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_NEPALI64, "ne" },
214 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SANSKRIT65, "sa" },
215 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MARATHI66, "mr" },
216 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_BENGALI67, "bn" },
217 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_ASSAMESE68, "as" },
218 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_GUJARATI69, "gu" },
219 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_PUNJABI70, "pa" },
220 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_ORIYA71, "or" },
221 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MALAYALAM72, "ml" },
222 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_KANNADA73, "kn" },
223 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_TAMIL74, "ta" },
224 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_TELUGU75, "te" },
225 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SINHALESE76, "si" },
226 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_BURMESE77, "my" },
227 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_KHMER78, "km" },
228 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_LAO79, "lo" },
229 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_VIETNAMESE80, "vi" },
230 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_INDONESIAN81, "id" },
231 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_TAGALOG82, "tl" },
232 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MALAY_ROMAN_SCRIPT83, "ms" },
233 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MALAY_ARABIC_SCRIPT84, "ms" },
234 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_AMHARIC85, "am" },
235 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_TIGRINYA86, "ti" },
236 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_GALLA87, "om" },
237 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SOMALI88, "so" },
238 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SWAHILI89, "sw" },
239 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_RUANDA90, "rw" },
240 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_RUNDI91, "rn" },
241 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_CHEWA92, "ny" },
242 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MALAGASY93, "mg" },
243 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_ESPERANTO94, "eo" },
244 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_WELSH128, "cy" },
245 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_BASQUE129, "eu" },
246 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_CATALAN130, "ca" },
247 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_LATIN131, "la" },
248 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_QUECHUA132, "qu" },
249 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_GUARANI133, "gn" },
250 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_AYMARA134, "ay" },
251 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_TATAR135, "tt" },
252 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_UIGHUR136, "ug" },
253 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_DZONGKHA137, "dz" },
254 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_JAVANESE138, "jw" },
255 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SUNDANESE139, "su" },
256
257#if 0 /* these seem to be errors that have been dropped */
258
259 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SCOTTISH_GAELIC144 },
260 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_IRISH_GAELIC146 },
261
262#endif
263
264 /* The following codes are new as of 2000-03-10 */
265 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_GALICIAN140, "gl" },
266 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_AFRIKAANS141, "af" },
267 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_BRETON142, "br" },
268 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_INUKTITUT143, "iu" },
269 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_SCOTTISH_GAELIC144, "gd" },
270 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_MANX_GAELIC145, "gv" },
271 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_IRISH_GAELIC146, "ga" },
272 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_TONGAN147, "to" },
273 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_GREEK_POLYTONIC148, "el" },
274 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_GREELANDIC149, "ik" },
275 { TT_PLATFORM_MACINTOSH1, TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT150,"az" },
276
277 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_SAUDI_ARABIA0x0401, "ar" },
278 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_IRAQ0x0801, "ar" },
279 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_EGYPT0x0c01, "ar" },
280 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_LIBYA0x1001, "ar" },
281 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_ALGERIA0x1401, "ar" },
282 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_MOROCCO0x1801, "ar" },
283 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_TUNISIA0x1c01, "ar" },
284 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_OMAN0x2001, "ar" },
285 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_YEMEN0x2401, "ar" },
286 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_SYRIA0x2801, "ar" },
287 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_JORDAN0x2c01, "ar" },
288 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_LEBANON0x3001, "ar" },
289 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_KUWAIT0x3401, "ar" },
290 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_UAE0x3801, "ar" },
291 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_BAHRAIN0x3c01, "ar" },
292 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_QATAR0x4001, "ar" },
293 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_BULGARIAN_BULGARIA0x0402, "bg" },
294 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_CATALAN_SPAIN0x0403, "ca" },
295 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_CHINESE_TAIWAN0x0404, "zh-tw" },
296 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_CHINESE_PRC0x0804, "zh-cn" },
297 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_CHINESE_HONG_KONG0x0c04, "zh-hk" },
298 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_CHINESE_SINGAPORE0x1004, "zh-sg" },
299
300 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_CHINESE_MACAU0x1404, "zh-mo" },
301
302 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_CZECH_CZECH_REPUBLIC0x0405, "cs" },
303 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_DANISH_DENMARK0x0406, "da" },
304 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_GERMAN_GERMANY0x0407, "de" },
305 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_GERMAN_SWITZERLAND0x0807, "de" },
306 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_GERMAN_AUSTRIA0x0c07, "de" },
307 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_GERMAN_LUXEMBOURG0x1007, "de" },
308 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_GERMAN_LIECHTENSTEI0x1407, "de" },
309 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_GREEK_GREECE0x0408, "el" },
310 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_UNITED_STATES0x0409, "en" },
311 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_UNITED_KINGDOM0x0809, "en" },
312 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_AUSTRALIA0x0c09, "en" },
313 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_CANADA0x1009, "en" },
314 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_NEW_ZEALAND0x1409, "en" },
315 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_IRELAND0x1809, "en" },
316 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_SOUTH_AFRICA0x1c09, "en" },
317 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_JAMAICA0x2009, "en" },
318 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_CARIBBEAN0x2409, "en" },
319 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_BELIZE0x2809, "en" },
320 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_TRINIDAD0x2c09, "en" },
321 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_ZIMBABWE0x3009, "en" },
322 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_PHILIPPINES0x3409, "en" },
323 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT0x040a,"es" },
324 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_MEXICO0x080a, "es" },
325 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT0x0c0a,"es" },
326 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_GUATEMALA0x100a, "es" },
327 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_COSTA_RICA0x140a, "es" },
328 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_PANAMA0x180a, "es" },
329 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC0x1c0a,"es" },
330 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_VENEZUELA0x200a, "es" },
331 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_COLOMBIA0x240a, "es" },
332 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_PERU0x280a, "es" },
333 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_ARGENTINA0x2c0a, "es" },
334 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_ECUADOR0x300a, "es" },
335 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_CHILE0x340a, "es" },
336 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_URUGUAY0x380a, "es" },
337 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_PARAGUAY0x3c0a, "es" },
338 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_BOLIVIA0x400a, "es" },
339 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_EL_SALVADOR0x440a, "es" },
340 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_HONDURAS0x480a, "es" },
341 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_NICARAGUA0x4c0a, "es" },
342 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_PUERTO_RICO0x500a, "es" },
343 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FINNISH_FINLAND0x040b, "fi" },
344 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_FRANCE0x040c, "fr" },
345 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_BELGIUM0x080c, "fr" },
346 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_CANADA0x0c0c, "fr" },
347 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_SWITZERLAND0x100c, "fr" },
348 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_LUXEMBOURG0x140c, "fr" },
349 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_MONACO0x180c, "fr" },
350 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_HEBREW_ISRAEL0x040d, "he" },
351 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_HUNGARIAN_HUNGARY0x040e, "hu" },
352 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ICELANDIC_ICELAND0x040f, "is" },
353 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ITALIAN_ITALY0x0410, "it" },
354 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ITALIAN_SWITZERLAND0x0810, "it" },
355 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_JAPANESE_JAPAN0x0411, "ja" },
356 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA0x0412,"ko" },
357 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_KOREAN_JOHAB_KOREA0x0812, "ko" },
358 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_DUTCH_NETHERLANDS0x0413, "nl" },
359 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_DUTCH_BELGIUM0x0813, "nl" },
360 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL0x0414, "no" },
361 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK0x0814, "nn" },
362 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_POLISH_POLAND0x0415, "pl" },
363 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_PORTUGUESE_BRAZIL0x0416, "pt" },
364 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_PORTUGUESE_PORTUGAL0x0816, "pt" },
365 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND0x0417,"rm" },
366 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ROMANIAN_ROMANIA0x0418, "ro" },
367 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_MOLDAVIAN_MOLDAVIA0x0818, "mo" },
368 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_RUSSIAN_RUSSIA0x0419, "ru" },
369 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_RUSSIAN_MOLDAVIA0x0819, "ru" },
370 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_CROATIAN_CROATIA0x041a, "hr" },
371 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SERBIAN_SERBIA_LATIN0x081a, "sr" },
372 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC0x0c1a, "sr" },
373 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SLOVAK_SLOVAKIA0x041b, "sk" },
374 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ALBANIAN_ALBANIA0x041c, "sq" },
375 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SWEDISH_SWEDEN0x041d, "sv" },
376 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SWEDISH_FINLAND0x081d, "sv" },
377 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_THAI_THAILAND0x041e, "th" },
378 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TURKISH_TURKEY0x041f, "tr" },
379 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_URDU_PAKISTAN0x0420, "ur" },
380 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_INDONESIAN_INDONESIA0x0421, "id" },
381 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_UKRAINIAN_UKRAINE0x0422, "uk" },
382 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_BELARUSIAN_BELARUS0x0423, "be" },
383 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SLOVENE_SLOVENIA0x0424, "sl" },
384 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ESTONIAN_ESTONIA0x0425, "et" },
385 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_LATVIAN_LATVIA0x0426, "lv" },
386 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_LITHUANIAN_LITHUANIA0x0427, "lt" },
387 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA0x0827,"lt" },
388
389#ifdef TT_MS_LANGID_MAORI_NEW_ZELAND
390 /* this seems to be an error that have been dropped */
391 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_MAORI_NEW_ZEALAND0x0481, "mi" },
392#endif
393
394 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FARSI_IRAN0x0429, "fa" },
395 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_VIETNAMESE_VIET_NAM0x042a, "vi" },
396 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARMENIAN_ARMENIA0x042b, "hy" },
397 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN0x042c, "az" },
398 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC0x082c, "az" },
399 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_BASQUE_SPAIN0x042d, "eu" },
400 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SORBIAN_GERMANY0x042e, "wen" },
401 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_MACEDONIAN_MACEDONIA0x042f, "mk" },
402 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SUTU_SOUTH_AFRICA0x0430, "st" },
403 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TSONGA_SOUTH_AFRICA0x0431, "ts" },
404 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TSWANA_SOUTH_AFRICA0x0432, "tn" },
405 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_VENDA_SOUTH_AFRICA0x0433, "ven" },
406 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_XHOSA_SOUTH_AFRICA0x0434, "xh" },
407 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ZULU_SOUTH_AFRICA0x0435, "zu" },
408 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA0x0436, "af" },
409 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_GEORGIAN_GEORGIA0x0437, "ka" },
410 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS0x0438, "fo" },
411 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_HINDI_INDIA0x0439, "hi" },
412 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_MALTESE_MALTA0x043a, "mt" },
413 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SAAMI_LAPONIA0x043b, "se" },
414
415 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM0x083c,"gd" },
416 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_IRISH_GAELIC_IRELAND0x043c, "ga" },
417
418 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_MALAY_MALAYSIA0x043e, "ms" },
419 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM0x083e, "ms" },
420 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_KAZAK_KAZAKSTAN0x043f, "kk" },
421 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SWAHILI_KENYA0x0441, "sw" },
422 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN0x0443, "uz" },
423 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC0x0843, "uz" },
424 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TATAR_TATARSTAN0x0444, "tt" },
425 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_BENGALI_INDIA0x0445, "bn" },
426 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_PUNJABI_INDIA0x0446, "pa" },
427 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_GUJARATI_INDIA0x0447, "gu" },
428 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ORIYA_INDIA0x0448, "or" },
429 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TAMIL_INDIA0x0449, "ta" },
430 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TELUGU_INDIA0x044a, "te" },
431 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_KANNADA_INDIA0x044b, "kn" },
432 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_MALAYALAM_INDIA0x044c, "ml" },
433 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ASSAMESE_INDIA0x044d, "as" },
434 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_MARATHI_INDIA0x044e, "mr" },
435 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SANSKRIT_INDIA0x044f, "sa" },
436 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_KONKANI_INDIA0x0457, "kok" },
437
438 /* new as of 2001-01-01 */
439 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ARABIC_GENERAL0x0001, "ar" },
440 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_CHINESE_GENERAL0x0004, "zh" },
441 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_GENERAL0x0009, "en" },
442 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_WEST_INDIES0x1c0c, "fr" },
443 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_REUNION0x200c, "fr" },
444 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_CONGO0x240c, "fr" },
445
446 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_SENEGAL0x280c, "fr" },
447 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_CAMEROON0x2c0c, "fr" },
448 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_COTE_D_IVOIRE0x300c, "fr" },
449 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_MALI0x340c, "fr" },
450 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA0x141a,"bs" },
451 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_URDU_INDIA0x0820, "ur" },
452 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TAJIK_TAJIKISTAN0x0428, "tg" },
453 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_YIDDISH_GERMANY0x043d, "yi" },
454 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN0x0440, "ky" },
455
456 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TURKMEN_TURKMENISTAN0x0442, "tk" },
457 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_MONGOLIAN_MONGOLIA0x0450, "mn" },
458
459 /* the following seems to be inconsistent;
460 here is the current "official" way: */
461 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TIBETAN_BHUTAN0x0851, "bo" },
462 /* and here is what is used by Passport SDK */
463 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TIBETAN_CHINA0x0451, "bo" },
464 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_DZONGHKA_BHUTAN0x0851, "dz" },
465 /* end of inconsistency */
466
467 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_WELSH_WALES0x0452, "cy" },
468 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_KHMER_CAMBODIA0x0453, "km" },
469 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_LAO_LAOS0x0454, "lo" },
470 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_BURMESE_MYANMAR0x0455, "my" },
471 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_GALICIAN_SPAIN0x0456, "gl" },
472 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_MANIPURI_INDIA0x0458, "mni" },
473 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SINDHI_INDIA0x0459, "sd" },
474 /* the following one is only encountered in Microsoft RTF specification */
475 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_KASHMIRI_PAKISTAN0x0460, "ks" },
476 /* the following one is not in the Passport list, looks like an omission */
477 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_KASHMIRI_INDIA0x0860, "ks" },
478 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_NEPALI_NEPAL0x0461, "ne" },
479 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_NEPALI_INDIA0x0861, "ne" },
480 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRISIAN_NETHERLANDS0x0462, "fy" },
481
482 /* new as of 2001-03-01 (from Office Xp) */
483 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_HONG_KONG0x3c09, "en" },
484 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_INDIA0x4009, "en" },
485 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_MALAYSIA0x4409, "en" },
486 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_ENGLISH_SINGAPORE0x4809, "en" },
487 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SYRIAC_SYRIA0x045a, "syr" },
488 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SINHALESE_SRI_LANKA0x045b, "si" },
489 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_CHEROKEE_UNITED_STATES0x045c, "chr" },
490 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_INUKTITUT_CANADA0x045d, "iu" },
491 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_AMHARIC_ETHIOPIA0x045e, "am" },
492#if 0
493 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TAMAZIGHT_MOROCCO0x045f },
494 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN0x085f },
495#endif
496 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_PASHTO_AFGHANISTAN0x0463, "ps" },
497 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FILIPINO_PHILIPPINES0x0464, "phi" },
498 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_DHIVEHI_MALDIVES0x0465, "div" },
499
500 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_OROMO_ETHIOPIA0x0472, "om" },
501 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TIGRIGNA_ETHIOPIA0x0473, "ti" },
502 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_TIGRIGNA_ERYTHREA0x0873, "ti" },
503
504 /* New additions from Windows Xp/Passport SDK 2001-11-10. */
505
506 /* don't ask what this one means... It is commented out currently. */
507#if 0
508 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_GREEK_GREECE2 },
509#endif
510
511 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_UNITED_STATES0x540a, "es" },
512 /* The following two IDs blatantly violate MS specs by using a */
513 /* sublanguage >,. */
514 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SPANISH_LATIN_AMERICA0xE40aU, "es" },
515 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_NORTH_AFRICA0xE40cU, "fr" },
516
517 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_MOROCCO0x380c, "fr" },
518 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FRENCH_HAITI0x3c0c, "fr" },
519 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_BENGALI_BANGLADESH0x0845, "bn" },
520 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN0x0846, "ar" },
521 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN0x0850,"mn" },
522#if 0
523 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_EDO_NIGERIA0x0466 },
524 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_FULFULDE_NIGERIA0x0467 },
525 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_IBIBIO_NIGERIA0x0469 },
526#endif
527 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_HAUSA_NIGERIA0x0468, "ha" },
528 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_YORUBA_NIGERIA0x046a, "yo" },
529 /* language codes from, to, are (still) unknown. */
530 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_IGBO_NIGERIA0x0470, "ibo" },
531 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_KANURI_NIGERIA0x0471, "kau" },
532 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_GUARANI_PARAGUAY0x0474, "gn" },
533 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_HAWAIIAN_UNITED_STATES0x0475, "haw" },
534 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_LATIN0x0476, "la" },
535 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_SOMALI_SOMALIA0x0477, "so" },
536#if 0
537 /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */
538 /* not written (but OTOH the peculiar writing system is worth */
539 /* studying). */
540 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_YI_CHINA0x0478 },
541#endif
542 { TT_PLATFORM_MICROSOFT3, TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES0x0479,"pap" },
543};
544
545#define NUM_FC_FT_LANGUAGE(int) (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0])) (int) (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0]))
546
547typedef struct {
548 FT_UShort language_id;
549 char fromcode[12];
550} FcMacRomanFake;
551
552static const FcMacRomanFake fcMacRomanFake[] = {
553 { TT_MS_LANGID_JAPANESE_JAPAN0x0411, "SJIS-WIN" },
554 { TT_MS_LANGID_ENGLISH_UNITED_STATES0x0409, "ASCII" },
555};
556
557static FcChar8 *
558FcFontCapabilities(FT_Face face);
559
560#define NUM_FC_MAC_ROMAN_FAKE(int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0])) (int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
561
562
563/* From http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ROMAN.TXT */
564static const FcChar16 fcMacRomanNonASCIIToUnicode[128] = {
565 /*0x80*/ 0x00C4, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
566 /*0x81*/ 0x00C5, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
567 /*0x82*/ 0x00C7, /* LATIN CAPITAL LETTER C WITH CEDILLA */
568 /*0x83*/ 0x00C9, /* LATIN CAPITAL LETTER E WITH ACUTE */
569 /*0x84*/ 0x00D1, /* LATIN CAPITAL LETTER N WITH TILDE */
570 /*0x85*/ 0x00D6, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
571 /*0x86*/ 0x00DC, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
572 /*0x87*/ 0x00E1, /* LATIN SMALL LETTER A WITH ACUTE */
573 /*0x88*/ 0x00E0, /* LATIN SMALL LETTER A WITH GRAVE */
574 /*0x89*/ 0x00E2, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
575 /*0x8A*/ 0x00E4, /* LATIN SMALL LETTER A WITH DIAERESIS */
576 /*0x8B*/ 0x00E3, /* LATIN SMALL LETTER A WITH TILDE */
577 /*0x8C*/ 0x00E5, /* LATIN SMALL LETTER A WITH RING ABOVE */
578 /*0x8D*/ 0x00E7, /* LATIN SMALL LETTER C WITH CEDILLA */
579 /*0x8E*/ 0x00E9, /* LATIN SMALL LETTER E WITH ACUTE */
580 /*0x8F*/ 0x00E8, /* LATIN SMALL LETTER E WITH GRAVE */
581 /*0x90*/ 0x00EA, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
582 /*0x91*/ 0x00EB, /* LATIN SMALL LETTER E WITH DIAERESIS */
583 /*0x92*/ 0x00ED, /* LATIN SMALL LETTER I WITH ACUTE */
584 /*0x93*/ 0x00EC, /* LATIN SMALL LETTER I WITH GRAVE */
585 /*0x94*/ 0x00EE, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
586 /*0x95*/ 0x00EF, /* LATIN SMALL LETTER I WITH DIAERESIS */
587 /*0x96*/ 0x00F1, /* LATIN SMALL LETTER N WITH TILDE */
588 /*0x97*/ 0x00F3, /* LATIN SMALL LETTER O WITH ACUTE */
589 /*0x98*/ 0x00F2, /* LATIN SMALL LETTER O WITH GRAVE */
590 /*0x99*/ 0x00F4, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
591 /*0x9A*/ 0x00F6, /* LATIN SMALL LETTER O WITH DIAERESIS */
592 /*0x9B*/ 0x00F5, /* LATIN SMALL LETTER O WITH TILDE */
593 /*0x9C*/ 0x00FA, /* LATIN SMALL LETTER U WITH ACUTE */
594 /*0x9D*/ 0x00F9, /* LATIN SMALL LETTER U WITH GRAVE */
595 /*0x9E*/ 0x00FB, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
596 /*0x9F*/ 0x00FC, /* LATIN SMALL LETTER U WITH DIAERESIS */
597 /*0xA0*/ 0x2020, /* DAGGER */
598 /*0xA1*/ 0x00B0, /* DEGREE SIGN */
599 /*0xA2*/ 0x00A2, /* CENT SIGN */
600 /*0xA3*/ 0x00A3, /* POUND SIGN */
601 /*0xA4*/ 0x00A7, /* SECTION SIGN */
602 /*0xA5*/ 0x2022, /* BULLET */
603 /*0xA6*/ 0x00B6, /* PILCROW SIGN */
604 /*0xA7*/ 0x00DF, /* LATIN SMALL LETTER SHARP S */
605 /*0xA8*/ 0x00AE, /* REGISTERED SIGN */
606 /*0xA9*/ 0x00A9, /* COPYRIGHT SIGN */
607 /*0xAA*/ 0x2122, /* TRADE MARK SIGN */
608 /*0xAB*/ 0x00B4, /* ACUTE ACCENT */
609 /*0xAC*/ 0x00A8, /* DIAERESIS */
610 /*0xAD*/ 0x2260, /* NOT EQUAL TO */
611 /*0xAE*/ 0x00C6, /* LATIN CAPITAL LETTER AE */
612 /*0xAF*/ 0x00D8, /* LATIN CAPITAL LETTER O WITH STROKE */
613 /*0xB0*/ 0x221E, /* INFINITY */
614 /*0xB1*/ 0x00B1, /* PLUS-MINUS SIGN */
615 /*0xB2*/ 0x2264, /* LESS-THAN OR EQUAL TO */
616 /*0xB3*/ 0x2265, /* GREATER-THAN OR EQUAL TO */
617 /*0xB4*/ 0x00A5, /* YEN SIGN */
618 /*0xB5*/ 0x00B5, /* MICRO SIGN */
619 /*0xB6*/ 0x2202, /* PARTIAL DIFFERENTIAL */
620 /*0xB7*/ 0x2211, /* N-ARY SUMMATION */
621 /*0xB8*/ 0x220F, /* N-ARY PRODUCT */
622 /*0xB9*/ 0x03C0, /* GREEK SMALL LETTER PI */
623 /*0xBA*/ 0x222B, /* INTEGRAL */
624 /*0xBB*/ 0x00AA, /* FEMININE ORDINAL INDICATOR */
625 /*0xBC*/ 0x00BA, /* MASCULINE ORDINAL INDICATOR */
626 /*0xBD*/ 0x03A9, /* GREEK CAPITAL LETTER OMEGA */
627 /*0xBE*/ 0x00E6, /* LATIN SMALL LETTER AE */
628 /*0xBF*/ 0x00F8, /* LATIN SMALL LETTER O WITH STROKE */
629 /*0xC0*/ 0x00BF, /* INVERTED QUESTION MARK */
630 /*0xC1*/ 0x00A1, /* INVERTED EXCLAMATION MARK */
631 /*0xC2*/ 0x00AC, /* NOT SIGN */
632 /*0xC3*/ 0x221A, /* SQUARE ROOT */
633 /*0xC4*/ 0x0192, /* LATIN SMALL LETTER F WITH HOOK */
634 /*0xC5*/ 0x2248, /* ALMOST EQUAL TO */
635 /*0xC6*/ 0x2206, /* INCREMENT */
636 /*0xC7*/ 0x00AB, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
637 /*0xC8*/ 0x00BB, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
638 /*0xC9*/ 0x2026, /* HORIZONTAL ELLIPSIS */
639 /*0xCA*/ 0x00A0, /* NO-BREAK SPACE */
640 /*0xCB*/ 0x00C0, /* LATIN CAPITAL LETTER A WITH GRAVE */
641 /*0xCC*/ 0x00C3, /* LATIN CAPITAL LETTER A WITH TILDE */
642 /*0xCD*/ 0x00D5, /* LATIN CAPITAL LETTER O WITH TILDE */
643 /*0xCE*/ 0x0152, /* LATIN CAPITAL LIGATURE OE */
644 /*0xCF*/ 0x0153, /* LATIN SMALL LIGATURE OE */
645 /*0xD0*/ 0x2013, /* EN DASH */
646 /*0xD1*/ 0x2014, /* EM DASH */
647 /*0xD2*/ 0x201C, /* LEFT DOUBLE QUOTATION MARK */
648 /*0xD3*/ 0x201D, /* RIGHT DOUBLE QUOTATION MARK */
649 /*0xD4*/ 0x2018, /* LEFT SINGLE QUOTATION MARK */
650 /*0xD5*/ 0x2019, /* RIGHT SINGLE QUOTATION MARK */
651 /*0xD6*/ 0x00F7, /* DIVISION SIGN */
652 /*0xD7*/ 0x25CA, /* LOZENGE */
653 /*0xD8*/ 0x00FF, /* LATIN SMALL LETTER Y WITH DIAERESIS */
654 /*0xD9*/ 0x0178, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
655 /*0xDA*/ 0x2044, /* FRACTION SLASH */
656 /*0xDB*/ 0x20AC, /* EURO SIGN */
657 /*0xDC*/ 0x2039, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
658 /*0xDD*/ 0x203A, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
659 /*0xDE*/ 0xFB01, /* LATIN SMALL LIGATURE FI */
660 /*0xDF*/ 0xFB02, /* LATIN SMALL LIGATURE FL */
661 /*0xE0*/ 0x2021, /* DOUBLE DAGGER */
662 /*0xE1*/ 0x00B7, /* MIDDLE DOT */
663 /*0xE2*/ 0x201A, /* SINGLE LOW-9 QUOTATION MARK */
664 /*0xE3*/ 0x201E, /* DOUBLE LOW-9 QUOTATION MARK */
665 /*0xE4*/ 0x2030, /* PER MILLE SIGN */
666 /*0xE5*/ 0x00C2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
667 /*0xE6*/ 0x00CA, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
668 /*0xE7*/ 0x00C1, /* LATIN CAPITAL LETTER A WITH ACUTE */
669 /*0xE8*/ 0x00CB, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
670 /*0xE9*/ 0x00C8, /* LATIN CAPITAL LETTER E WITH GRAVE */
671 /*0xEA*/ 0x00CD, /* LATIN CAPITAL LETTER I WITH ACUTE */
672 /*0xEB*/ 0x00CE, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
673 /*0xEC*/ 0x00CF, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
674 /*0xED*/ 0x00CC, /* LATIN CAPITAL LETTER I WITH GRAVE */
675 /*0xEE*/ 0x00D3, /* LATIN CAPITAL LETTER O WITH ACUTE */
676 /*0xEF*/ 0x00D4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
677 /*0xF0*/ 0xF8FF, /* Apple logo */
678 /*0xF1*/ 0x00D2, /* LATIN CAPITAL LETTER O WITH GRAVE */
679 /*0xF2*/ 0x00DA, /* LATIN CAPITAL LETTER U WITH ACUTE */
680 /*0xF3*/ 0x00DB, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
681 /*0xF4*/ 0x00D9, /* LATIN CAPITAL LETTER U WITH GRAVE */
682 /*0xF5*/ 0x0131, /* LATIN SMALL LETTER DOTLESS I */
683 /*0xF6*/ 0x02C6, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
684 /*0xF7*/ 0x02DC, /* SMALL TILDE */
685 /*0xF8*/ 0x00AF, /* MACRON */
686 /*0xF9*/ 0x02D8, /* BREVE */
687 /*0xFA*/ 0x02D9, /* DOT ABOVE */
688 /*0xFB*/ 0x02DA, /* RING ABOVE */
689 /*0xFC*/ 0x00B8, /* CEDILLA */
690 /*0xFD*/ 0x02DD, /* DOUBLE ACUTE ACCENT */
691 /*0xFE*/ 0x02DB, /* OGONEK */
692 /*0xFF*/ 0x02C7, /* CARON */
693};
694
695#if USE_ICONV0
696#include <iconv.h>
697#endif
698
699/*
700 * A shift-JIS will have many high bits turned on
701 */
702static FcBool
703FcLooksLikeSJIS (FcChar8 *string, int len)
704{
705 int nhigh = 0, nlow = 0;
706
707 while (len-- > 0)
708 {
709 if (*string++ & 0x80) nhigh++;
710 else nlow++;
711 }
712 /*
713 * Heuristic -- if more than 1/3 of the bytes have the high-bit set,
714 * this is likely to be SJIS and not ROMAN
715 */
716 if (nhigh * 2 > nlow)
717 return FcTrue1;
718 return FcFalse0;
719}
720
721static FcChar8 *
722FcSfntNameTranscode (FT_SfntName *sname)
723{
724 int i;
725 const char *fromcode;
726#if USE_ICONV0
727 iconv_t cd;
728#endif
729 FcChar8 *utf8;
730
731 for (i = 0; i < NUM_FC_FT_ENCODING(int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0])); i++)
732 if (fcFtEncoding[i].platform_id == sname->platform_id &&
733 (fcFtEncoding[i].encoding_id == TT_ENCODING_DONT_CARE0xffff ||
734 fcFtEncoding[i].encoding_id == sname->encoding_id))
735 break;
736 if (i == NUM_FC_FT_ENCODING(int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0])))
737 return 0;
738 fromcode = fcFtEncoding[i].fromcode;
739
740 /*
741 * Many names encoded for TT_PLATFORM_MACINTOSH are broken
742 * in various ways. Kludge around them.
743 */
744 if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN"MACINTOSH"))
745 {
746 if (sname->language_id == TT_MAC_LANGID_ENGLISH0 &&
747 FcLooksLikeSJIS (sname->string, sname->string_len))
748 {
749 fromcode = "SJIS";
750 }
751 else if (sname->language_id >= 0x100)
752 {
753 /*
754 * "real" Mac language IDs are all less than 150.
755 * Names using one of the MS language IDs are assumed
756 * to use an associated encoding (Yes, this is a kludge)
757 */
758 int f;
759
760 fromcode = NULL((void*)0);
761 for (f = 0; f < NUM_FC_MAC_ROMAN_FAKE(int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0])); f++)
762 if (fcMacRomanFake[f].language_id == sname->language_id)
763 {
764 fromcode = fcMacRomanFake[f].fromcode;
765 break;
766 }
767 if (!fromcode)
768 return 0;
769 }
770 }
771 if (!strcmp (fromcode, "UCS-2BE") || !strcmp (fromcode, "UTF-16BE"))
772 {
773 FcChar8 *src = sname->string;
774 int src_len = sname->string_len;
775 int len;
776 int wchar;
777 int ilen, olen;
778 FcChar8 *u8;
779 FcChar32 ucs4;
780
781 /*
782 * Convert Utf16 to Utf8
783 */
784
785 if (!FcUtf16Len (src, FcEndianBig, src_len, &len, &wchar))
786 return 0;
787
788 /*
789 * Allocate plenty of space. Freed below
790 */
791 utf8 = malloc (len * FC_UTF8_MAX_LEN6 + 1);
792 if (!utf8)
793 return 0;
794
795 u8 = utf8;
796
797 while ((ilen = FcUtf16ToUcs4 (src, FcEndianBig, &ucs4, src_len)) > 0)
798 {
799 src_len -= ilen;
800 src += ilen;
801 olen = FcUcs4ToUtf8 (ucs4, u8);
802 u8 += olen;
803 }
804 *u8 = '\0';
805 goto done;
806 }
807 if (!strcmp (fromcode, "ASCII") || !strcmp (fromcode, "ISO-8859-1"))
808 {
809 FcChar8 *src = sname->string;
810 int src_len = sname->string_len;
811 int olen;
812 FcChar8 *u8;
813 FcChar32 ucs4;
814
815 /*
816 * Convert Latin1 to Utf8. Freed below
817 */
818 utf8 = malloc (src_len * 2 + 1);
819 if (!utf8)
820 return 0;
821
822 u8 = utf8;
823 while (src_len > 0)
824 {
825 ucs4 = *src++;
826 src_len--;
827 olen = FcUcs4ToUtf8 (ucs4, u8);
828 u8 += olen;
829 }
830 *u8 = '\0';
831 goto done;
832 }
833 if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN"MACINTOSH"))
834 {
835 FcChar8 *src = sname->string;
836 int src_len = sname->string_len;
837 int olen;
838 FcChar8 *u8;
839 FcChar32 ucs4;
840
841 /*
842 * Convert Latin1 to Utf8. Freed below
843 */
844 utf8 = malloc (src_len * 3 + 1);
845 if (!utf8)
846 return 0;
847
848 u8 = utf8;
849 while (src_len > 0)
850 {
851 ucs4 = *src++;
852 if (ucs4 >= 128)
853 ucs4 = fcMacRomanNonASCIIToUnicode[ucs4 - 128];
854 src_len--;
855 olen = FcUcs4ToUtf8 (ucs4, u8);
856 u8 += olen;
857 }
858 *u8 = '\0';
859 goto done;
860 }
861
862#if USE_ICONV0
863 cd = iconv_open ("UTF-8", fromcode);
864 if (cd && cd != (iconv_t) (-1))
865 {
866 size_t in_bytes_left = sname->string_len;
867 size_t out_bytes_left = sname->string_len * FC_UTF8_MAX_LEN6;
868 char *inbuf, *outbuf;
869
870 utf8 = malloc (out_bytes_left + 1);
871 if (!utf8)
872 {
873 iconv_close (cd);
874 return 0;
875 }
876
877 outbuf = (char *) utf8;
878 inbuf = (char *) sname->string;
879
880 while (in_bytes_left)
881 {
882 size_t did = iconv (cd,
883 &inbuf, &in_bytes_left,
884 &outbuf, &out_bytes_left);
885 if (did == (size_t) (-1))
886 {
887 iconv_close (cd);
888 free (utf8);
889 return 0;
890 }
891 }
892 iconv_close (cd);
893 *outbuf = '\0';
894 goto done;
895 }
896#endif
897 return 0;
898done:
899 if (FcStrCmpIgnoreBlanksAndCase (utf8, (FcChar8 *) "") == 0)
900 {
901 free (utf8);
902 return 0;
903 }
904 return utf8;
905}
906
907static const FcChar8 *
908FcSfntNameLanguage (FT_SfntName *sname)
909{
910 int i;
911 FT_UShort platform_id = sname->platform_id;
912 FT_UShort language_id = sname->language_id;
913
914 /*
915 * Many names encoded for TT_PLATFORM_MACINTOSH are broken
916 * in various ways. Kludge around them.
917 */
918 if (platform_id == TT_PLATFORM_MACINTOSH1 &&
919 sname->encoding_id == TT_MAC_ID_ROMAN0 &&
920 FcLooksLikeSJIS (sname->string, sname->string_len))
921 {
922 language_id = TT_MAC_LANGID_JAPANESE11;
923 }
924
925 for (i = 0; i < NUM_FC_FT_LANGUAGE(int) (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0])); i++)
926 if (fcFtLanguage[i].platform_id == platform_id &&
927 (fcFtLanguage[i].language_id == TT_LANGUAGE_DONT_CARE0xffff ||
928 fcFtLanguage[i].language_id == language_id))
929 {
930 if (fcFtLanguage[i].lang[0] == '\0')
931 return NULL((void*)0);
932 else
933 return (FcChar8 *) fcFtLanguage[i].lang;
934 }
935 return 0;
936}
937
938/* Order is significant. For example, some B&H fonts are hinted by
939 URW++, and both strings appear in the notice. */
940
941static const char *FcNoticeFoundries[][2] =
942 {
943 {"Adobe", "adobe"},
944 {"Bigelow", "b&h"},
945 {"Bitstream", "bitstream"},
946 {"Gnat", "culmus"},
947 {"Iorsh", "culmus"},
948 {"HanYang System", "hanyang"},
949 {"Font21", "hwan"},
950 {"IBM", "ibm"},
951 {"International Typeface Corporation", "itc"},
952 {"Linotype", "linotype"},
953 {"LINOTYPE-HELL", "linotype"},
954 {"Microsoft", "microsoft"},
955 {"Monotype", "monotype"},
956 {"Omega", "omega"},
957 {"Tiro Typeworks", "tiro"},
958 {"URW", "urw"},
959 {"XFree86", "xfree86"},
960 {"Xorg", "xorg"},
961};
962
963#define NUM_NOTICE_FOUNDRIES(int) (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries
[0]))
(int) (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
964
965static const FcChar8 *
966FcNoticeFoundry(const FT_String *notice)
967{
968 int i;
969
970 if (notice)
971 for(i = 0; i < NUM_NOTICE_FOUNDRIES(int) (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries
[0]))
; i++)
972 {
973 const char *n = FcNoticeFoundries[i][0];
974 const char *f = FcNoticeFoundries[i][1];
975
976 if (strstr ((const char *) notice, n))
977 return (const FcChar8 *) f;
978 }
979 return 0;
980}
981
982typedef struct _FcStringConst {
983 const FcChar8 *name;
984 int value;
985} FcStringConst;
986
987static int
988FcStringIsConst (const FcChar8 *string,
989 const FcStringConst *c,
990 int nc)
991{
992 int i;
993
994 for (i = 0; i < nc; i++)
995 if (FcStrCmpIgnoreBlanksAndCase (string, c[i].name) == 0)
996 return c[i].value;
997 return -1;
998}
999
1000static int
1001FcStringContainsConst (const FcChar8 *string,
1002 const FcStringConst *c,
1003 int nc)
1004{
1005 int i;
1006
1007 for (i = 0; i < nc; i++)
1008 {
1009 if (c[i].name[0] == '<')
1010 {
1011 if (FcStrContainsWord (string, c[i].name + 1))
1012 return c[i].value;
1013 }
1014 else
1015 {
1016 if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name))
1017 return c[i].value;
1018 }
1019 }
1020 return -1;
1021}
1022
1023typedef FcChar8 *FC8;
1024
1025static const FcStringConst weightConsts[] = {
1026 { (FC8) "thin", FC_WEIGHT_THIN0 },
1027 { (FC8) "extralight", FC_WEIGHT_EXTRALIGHT40 },
1028 { (FC8) "ultralight", FC_WEIGHT_ULTRALIGHT40 },
1029 { (FC8) "demilight", FC_WEIGHT_DEMILIGHT55 },
1030 { (FC8) "semilight", FC_WEIGHT_SEMILIGHT55 },
1031 { (FC8) "light", FC_WEIGHT_LIGHT50 },
1032 { (FC8) "book", FC_WEIGHT_BOOK75 },
1033 { (FC8) "regular", FC_WEIGHT_REGULAR80 },
1034 { (FC8) "normal", FC_WEIGHT_NORMAL80 },
1035 { (FC8) "medium", FC_WEIGHT_MEDIUM100 },
1036 { (FC8) "demibold", FC_WEIGHT_DEMIBOLD180 },
1037 { (FC8) "demi", FC_WEIGHT_DEMIBOLD180 },
1038 { (FC8) "semibold", FC_WEIGHT_SEMIBOLD180 },
1039 { (FC8) "extrabold", FC_WEIGHT_EXTRABOLD205 },
1040 { (FC8) "superbold", FC_WEIGHT_EXTRABOLD205 },
1041 { (FC8) "ultrabold", FC_WEIGHT_ULTRABOLD205 },
1042 { (FC8) "bold", FC_WEIGHT_BOLD200 },
1043 { (FC8) "ultrablack", FC_WEIGHT_ULTRABLACK215 },
1044 { (FC8) "superblack", FC_WEIGHT_EXTRABLACK215 },
1045 { (FC8) "extrablack", FC_WEIGHT_EXTRABLACK215 },
1046 { (FC8) "<ultra", FC_WEIGHT_ULTRABOLD205 }, /* only if a word */
1047 { (FC8) "black", FC_WEIGHT_BLACK210 },
1048 { (FC8) "heavy", FC_WEIGHT_HEAVY210 },
1049};
1050
1051#define NUM_WEIGHT_CONSTS(int) (sizeof (weightConsts) / sizeof (weightConsts[0])) (int) (sizeof (weightConsts) / sizeof (weightConsts[0]))
1052
1053#define FcIsWeight(s)FcStringIsConst(s,weightConsts,(int) (sizeof (weightConsts) /
sizeof (weightConsts[0])))
FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS(int) (sizeof (weightConsts) / sizeof (weightConsts[0])))
1054#define FcContainsWeight(s)FcStringContainsConst (s,weightConsts,(int) (sizeof (weightConsts
) / sizeof (weightConsts[0])))
FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS(int) (sizeof (weightConsts) / sizeof (weightConsts[0])))
1055
1056static const FcStringConst widthConsts[] = {
1057 { (FC8) "ultracondensed", FC_WIDTH_ULTRACONDENSED50 },
1058 { (FC8) "extracondensed", FC_WIDTH_EXTRACONDENSED63 },
1059 { (FC8) "semicondensed", FC_WIDTH_SEMICONDENSED87 },
1060 { (FC8) "condensed", FC_WIDTH_CONDENSED75 }, /* must be after *condensed */
1061 { (FC8) "normal", FC_WIDTH_NORMAL100 },
1062 { (FC8) "semiexpanded", FC_WIDTH_SEMIEXPANDED113 },
1063 { (FC8) "extraexpanded", FC_WIDTH_EXTRAEXPANDED150 },
1064 { (FC8) "ultraexpanded", FC_WIDTH_ULTRAEXPANDED200 },
1065 { (FC8) "expanded", FC_WIDTH_EXPANDED125 }, /* must be after *expanded */
1066 { (FC8) "extended", FC_WIDTH_EXPANDED125 },
1067};
1068
1069#define NUM_WIDTH_CONSTS(int) (sizeof (widthConsts) / sizeof (widthConsts[0])) (int) (sizeof (widthConsts) / sizeof (widthConsts[0]))
1070
1071#define FcIsWidth(s)FcStringIsConst(s,widthConsts,(int) (sizeof (widthConsts) / sizeof
(widthConsts[0])))
FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS(int) (sizeof (widthConsts) / sizeof (widthConsts[0])))
1072#define FcContainsWidth(s)FcStringContainsConst (s,widthConsts,(int) (sizeof (widthConsts
) / sizeof (widthConsts[0])))
FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS(int) (sizeof (widthConsts) / sizeof (widthConsts[0])))
1073
1074static const FcStringConst slantConsts[] = {
1075 { (FC8) "italic", FC_SLANT_ITALIC100 },
1076 { (FC8) "kursiv", FC_SLANT_ITALIC100 },
1077 { (FC8) "oblique", FC_SLANT_OBLIQUE110 },
1078};
1079
1080#define NUM_SLANT_CONSTS(int) (sizeof (slantConsts) / sizeof (slantConsts[0])) (int) (sizeof (slantConsts) / sizeof (slantConsts[0]))
1081
1082#define FcContainsSlant(s)FcStringContainsConst (s,slantConsts,(int) (sizeof (slantConsts
) / sizeof (slantConsts[0])))
FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS(int) (sizeof (slantConsts) / sizeof (slantConsts[0])))
1083
1084static const FcStringConst decorativeConsts[] = {
1085 { (FC8) "shadow", FcTrue1 },
1086 { (FC8) "caps", FcTrue1 },
1087 { (FC8) "antiqua", FcTrue1 },
1088 { (FC8) "romansc", FcTrue1 },
1089 { (FC8) "embosed", FcTrue1 },
1090 { (FC8) "dunhill", FcTrue1 },
1091};
1092
1093#define NUM_DECORATIVE_CONSTS(int) (sizeof (decorativeConsts) / sizeof (decorativeConsts[0
]))
(int) (sizeof (decorativeConsts) / sizeof (decorativeConsts[0]))
1094
1095#define FcContainsDecorative(s)FcStringContainsConst (s,decorativeConsts,(int) (sizeof (decorativeConsts
) / sizeof (decorativeConsts[0])))
FcStringContainsConst (s,decorativeConsts,NUM_DECORATIVE_CONSTS(int) (sizeof (decorativeConsts) / sizeof (decorativeConsts[0
]))
)
1096
1097static double
1098FcGetPixelSize (FT_Face face, int i)
1099{
1100#if HAVE_FT_GET_BDF_PROPERTY1
1101 if (face->num_fixed_sizes == 1)
1102 {
1103 BDF_PropertyRec prop;
1104 int rc;
1105
1106 rc = FT_Get_BDF_Property (face, "PIXEL_SIZE", &prop);
1107 if (rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
1108 return (double) prop.u.integer;
1109 }
1110#endif
1111#if HAVE_FT_BITMAP_SIZE_Y_PPEM1
1112 return (double) face->available_sizes[i].y_ppem / 64.0;
1113#else
1114 return (double) face->available_sizes[i].height;
1115#endif
1116}
1117
1118static FcBool
1119FcStringInPatternElement (FcPattern *pat, const char *elt, FcChar8 *string)
1120{
1121 int e;
1122 FcChar8 *old;
1123 for (e = 0; FcPatternGetString (pat, elt, e, &old) == FcResultMatch; e++)
1124 if (!FcStrCmpIgnoreBlanksAndCase (old, string))
1125 {
1126 return FcTrue1;
1127 }
1128 return FcFalse0;
1129}
1130
1131static const FT_UShort platform_order[] = {
1132 TT_PLATFORM_MICROSOFT3,
1133 TT_PLATFORM_APPLE_UNICODE0,
1134 TT_PLATFORM_MACINTOSH1,
1135};
1136#define NUM_PLATFORM_ORDER(sizeof (platform_order) / sizeof (platform_order[0])) (sizeof (platform_order) / sizeof (platform_order[0]))
1137
1138static const FT_UShort nameid_order[] = {
1139#ifdef TT_NAME_ID_WWS_FAMILY21
1140 TT_NAME_ID_WWS_FAMILY21,
1141#endif
1142 TT_NAME_ID_PREFERRED_FAMILY16,
1143 TT_NAME_ID_FONT_FAMILY1,
1144 TT_NAME_ID_MAC_FULL_NAME18,
1145 TT_NAME_ID_FULL_NAME4,
1146#ifdef TT_NAME_ID_WWS_SUBFAMILY22
1147 TT_NAME_ID_WWS_SUBFAMILY22,
1148#endif
1149 TT_NAME_ID_PREFERRED_SUBFAMILY17,
1150 TT_NAME_ID_FONT_SUBFAMILY2,
1151 TT_NAME_ID_TRADEMARK7,
1152 TT_NAME_ID_MANUFACTURER8,
1153};
1154
1155#define NUM_NAMEID_ORDER(sizeof (nameid_order) / sizeof (nameid_order[0])) (sizeof (nameid_order) / sizeof (nameid_order[0]))
1156FcPattern *
1157FcFreeTypeQueryFace (const FT_Face face,
1158 const FcChar8 *file,
1159 int id,
1160 FcBlanks *blanks)
1161{
1162 FcPattern *pat;
1163 int slant = -1;
1164 int weight = -1;
1165 int width = -1;
1166 FcBool decorative = FcFalse0;
1167 int i;
1168 FcCharSet *cs;
1169 FcLangSet *ls;
1170#if 0
1171 FcChar8 *family = 0;
1172#endif
1173 FcChar8 *complex_, *foundry_ = NULL((void*)0);
1174 const FcChar8 *foundry = 0;
1175 int spacing;
1176
1177 /* Support for glyph-variation named-instances. */
1178 FT_MM_Var *master = NULL((void*)0);
1179 FT_Var_Named_Style *instance = NULL((void*)0);
1180 double weight_mult = 1.0;
1181 double width_mult = 1.0;
1182
1183 TT_OS2 *os2;
1184#if HAVE_FT_GET_PS_FONT_INFO1
1185 PS_FontInfoRec psfontinfo;
1186#endif
1187#if HAVE_FT_GET_BDF_PROPERTY1
1188 BDF_PropertyRec prop;
1189#endif
1190 TT_Header *head;
1191 const FcChar8 *exclusiveLang = 0;
1192 FT_SfntName sname;
1193 FT_UInt snamei, snamec;
1194
1195 int nfamily = 0;
1196 int nfamily_lang = 0;
1197 int nstyle = 0;
1198 int nstyle_lang = 0;
1199 int nfullname = 0;
1200 int nfullname_lang = 0;
1201 unsigned int p, n;
1202 int platform, nameid;
1203
1204 FcChar8 *style = 0;
1205 int st;
1206 char psname[256];
1207 const char *tmp;
1208
1209 FcRange *r = NULL((void*)0);
1210
1211 FcBool symbol = FcFalse0;
1212
1213 FcInitDebug (); /* We might be called with no initizalization whatsoever. */
1214
1215 pat = FcPatternCreate ();
1216 if (!pat)
1217 goto bail0;
1218
1219 {
1220 int has_outline = !!(face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 ));
1221 int has_color = 0;
1222
1223#ifdef FT_FACE_FLAG_COLOR
1224 has_color = !!(face->face_flags & FT_FACE_FLAG_COLOR);
1225#endif
1226
1227 if (!FcPatternAddBool (pat, FC_OUTLINE"outline", has_outline))
1228 goto bail1;
1229
1230#ifdef FT_FACE_FLAG_COLOR
1231 if (!FcPatternAddBool (pat, FC_COLOR"color", has_color))
1232 goto bail1;
1233#endif
1234
1235 /* All color fonts are designed to be scaled, even if they only have
1236 * bitmap strikes. Client is responsible to scale the bitmaps. This
1237 * is in constrast to non-color strikes... */
1238 if (!FcPatternAddBool (pat, FC_SCALABLE"scalable", has_outline || has_color))
1239 goto bail1;
1240 }
1241
1242 if (id >> 16)
1243 {
1244 if (!FT_Get_MM_Var (face, &master))
1245 instance = &master->namedstyle[(id >> 16) - 1];
1246
1247 if (instance)
1248 {
1249 /* Pull out weight and width from named-instance. */
1250 unsigned int i;
1251
1252 for (i = 0; i < master->num_axis; i++)
1253 {
1254 double value = instance->coords[i] / (double) (1 << 16);
1255 double default_value = master->axis[i].def / (double) (1 << 16);
1256 double mult = value / default_value;
1257 //printf ("named-instance, axis %d tag %lx value %g\n", i, master->axis[i].tag, value);
1258 switch (master->axis[i].tag)
1259 {
1260 case FT_MAKE_TAG ('w','g','h','t')(FT_Tag) ( ( (FT_ULong)'w' << 24 ) | ( (FT_ULong)'g' <<
16 ) | ( (FT_ULong)'h' << 8 ) | (FT_ULong)'t' )
:
1261 weight_mult = mult;
1262 break;
1263
1264 case FT_MAKE_TAG ('w','d','t','h')(FT_Tag) ( ( (FT_ULong)'w' << 24 ) | ( (FT_ULong)'d' <<
16 ) | ( (FT_ULong)'t' << 8 ) | (FT_ULong)'h' )
:
1265 width_mult = mult;
1266 break;
1267
1268 /* TODO optical size! */
1269 }
1270 }
1271 }
1272 }
1273
1274 /*
1275 * Get the OS/2 table
1276 */
1277 os2 = (TT_OS2 *) FT_Get_Sfnt_Table (face, ft_sfnt_os2);
1278
1279 /*
1280 * Look first in the OS/2 table for the foundry, if
1281 * not found here, the various notices will be searched for
1282 * that information, either from the sfnt name tables or
1283 * the Postscript FontInfo dictionary. Finally, the
1284 * BDF properties will queried.
1285 */
1286
1287 if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
1288 {
1289 if (os2->achVendID && os2->achVendID[0] != 0)
1290 {
1291 foundry_ = (FcChar8 *) malloc (sizeof (os2->achVendID) + 1);
1292 memcpy ((void *)foundry_, os2->achVendID, sizeof (os2->achVendID))__builtin___memcpy_chk ((void *)foundry_, os2->achVendID, sizeof
(os2->achVendID), __builtin_object_size ((void *)foundry_
, 0))
;
1293 foundry_[sizeof (os2->achVendID)] = 0;
1294 foundry = foundry_;
1295 }
1296 }
1297
1298 if (FcDebug ()(FcDebugVal) & FC_DBG_SCANV256)
1299 printf ("\n");
1300 /*
1301 * Grub through the name table looking for family
1302 * and style names. FreeType makes quite a hash
1303 * of them
1304 */
1305 snamec = FT_Get_Sfnt_Name_Count (face);
1306 for (p = 0; p <= NUM_PLATFORM_ORDER(sizeof (platform_order) / sizeof (platform_order[0])); p++)
1307 {
1308 if (p < NUM_PLATFORM_ORDER(sizeof (platform_order) / sizeof (platform_order[0])))
1309 platform = platform_order[p];
1310 else
1311 platform = 0xffff;
1312
1313 /*
1314 * Order nameids so preferred names appear first
1315 * in the resulting list
1316 */
1317 for (n = 0; n < NUM_NAMEID_ORDER(sizeof (nameid_order) / sizeof (nameid_order[0])); n++)
1318 {
1319 nameid = nameid_order[n];
1320
1321 for (snamei = 0; snamei < snamec; snamei++)
1322 {
1323 FcChar8 *utf8, *pp;
1324 const FcChar8 *lang;
1325 const char *elt = 0, *eltlang = 0;
1326 int *np = 0, *nlangp = 0;
1327 size_t len;
1328
1329 if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0)
1330 continue;
1331
1332 if (instance)
1333 {
1334 /* For named-instances, we regular style nameIDs,
1335 * and map the instance's strid to FONT_SUBFAMILY. */
1336 if (sname.name_id == TT_NAME_ID_WWS_SUBFAMILY22 ||
1337 sname.name_id == TT_NAME_ID_PREFERRED_SUBFAMILY17 ||
1338 sname.name_id == TT_NAME_ID_FONT_SUBFAMILY2)
1339 continue;
1340 if (sname.name_id == instance->strid)
1341 sname.name_id = TT_NAME_ID_FONT_SUBFAMILY2;
1342 }
1343
1344 if (sname.name_id != nameid)
1345 continue;
1346
1347 /*
1348 * Sort platforms in preference order, accepting
1349 * all other platforms last
1350 */
1351 if (p < NUM_PLATFORM_ORDER(sizeof (platform_order) / sizeof (platform_order[0])))
1352 {
1353 if (sname.platform_id != platform)
1354 continue;
1355 }
1356 else
1357 {
1358 unsigned int sp;
1359
1360 for (sp = 0; sp < NUM_PLATFORM_ORDER(sizeof (platform_order) / sizeof (platform_order[0])); sp++)
1361 if (sname.platform_id == platform_order[sp])
1362 break;
1363 if (sp != NUM_PLATFORM_ORDER(sizeof (platform_order) / sizeof (platform_order[0])))
1364 continue;
1365 }
1366 utf8 = FcSfntNameTranscode (&sname);
1367 lang = FcSfntNameLanguage (&sname);
1368
1369 if (!utf8)
1370 continue;
1371
1372 switch (sname.name_id) {
1373#ifdef TT_NAME_ID_WWS_FAMILY21
1374 case TT_NAME_ID_WWS_FAMILY21:
1375#endif
1376 case TT_NAME_ID_PREFERRED_FAMILY16:
1377 case TT_NAME_ID_FONT_FAMILY1:
1378#if 0
1379 case TT_NAME_ID_UNIQUE_ID3:
1380#endif
1381 if (FcDebug ()(FcDebugVal) & FC_DBG_SCANV256)
1382 printf ("found family (n %2d p %d e %d l 0x%04x) %s\n",
1383 sname.name_id, sname.platform_id,
1384 sname.encoding_id, sname.language_id,
1385 utf8);
1386
1387 elt = FC_FAMILY"family";
1388 eltlang = FC_FAMILYLANG"familylang";
1389 np = &nfamily;
1390 nlangp = &nfamily_lang;
1391 break;
1392 case TT_NAME_ID_MAC_FULL_NAME18:
1393 case TT_NAME_ID_FULL_NAME4:
1394 if (FcDebug ()(FcDebugVal) & FC_DBG_SCANV256)
1395 printf ("found full (n %2d p %d e %d l 0x%04x) %s\n",
1396 sname.name_id, sname.platform_id,
1397 sname.encoding_id, sname.language_id,
1398 utf8);
1399
1400 elt = FC_FULLNAME"fullname";
1401 eltlang = FC_FULLNAMELANG"fullnamelang";
1402 np = &nfullname;
1403 nlangp = &nfullname_lang;
1404 break;
1405#ifdef TT_NAME_ID_WWS_SUBFAMILY22
1406 case TT_NAME_ID_WWS_SUBFAMILY22:
1407#endif
1408 case TT_NAME_ID_PREFERRED_SUBFAMILY17:
1409 case TT_NAME_ID_FONT_SUBFAMILY2:
1410 if (utf8)
1411 {
1412 pp = utf8;
1413 while (*pp == ' ')
1414 pp++;
1415 len = strlen ((const char *) pp);
1416 memmove (utf8, pp, len + 1)__builtin___memmove_chk (utf8, pp, len + 1, __builtin_object_size
(utf8, 0))
;
1417 pp = utf8 + len - 1;
1418 while (*pp == ' ')
1419 pp--;
1420 *(pp + 1) = 0;
1421 }
1422 if (FcDebug ()(FcDebugVal) & FC_DBG_SCANV256)
1423 printf ("found style (n %2d p %d e %d l 0x%04x) %s\n",
1424 sname.name_id, sname.platform_id,
1425 sname.encoding_id, sname.language_id,
1426 utf8);
1427
1428 elt = FC_STYLE"style";
1429 eltlang = FC_STYLELANG"stylelang";
1430 np = &nstyle;
1431 nlangp = &nstyle_lang;
1432 break;
1433 case TT_NAME_ID_TRADEMARK7:
1434 case TT_NAME_ID_MANUFACTURER8:
1435 /* If the foundry wasn't found in the OS/2 table, look here */
1436 if(!foundry)
1437 foundry = FcNoticeFoundry((FT_String *) utf8);
1438 break;
1439 }
1440 if (elt)
1441 {
1442 if (FcStringInPatternElement (pat, elt, utf8))
1443 {
1444 free (utf8);
1445 continue;
1446 }
1447
1448 /* add new element */
1449 if (!FcPatternAddString (pat, elt, utf8))
1450 {
1451 free (utf8);
1452 goto bail1;
1453 }
1454 free (utf8);
1455 if (lang)
1456 {
1457 /* pad lang list with 'und' to line up with elt */
1458 while (*nlangp < *np)
1459 {
1460 if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "und"))
1461 goto bail1;
1462 ++*nlangp;
1463 }
1464 if (!FcPatternAddString (pat, eltlang, lang))
1465 goto bail1;
1466 ++*nlangp;
1467 }
1468 ++*np;
1469 }
1470 else
1471 free (utf8);
1472 }
1473 }
1474 }
1475
1476 if (!nfamily && face->family_name &&
1477 FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->family_name, (FcChar8 *) "") != 0)
1478 {
1479 if (FcDebug ()(FcDebugVal) & FC_DBG_SCANV256)
1480 printf ("using FreeType family \"%s\"\n", face->family_name);
1481 if (!FcPatternAddString (pat, FC_FAMILY"family", (FcChar8 *) face->family_name))
1482 goto bail1;
1483 if (!FcPatternAddString (pat, FC_STYLELANG"stylelang", (FcChar8 *) "en"))
1484 goto bail1;
1485 ++nfamily;
1486 }
1487
1488 if (!nstyle && face->style_name &&
1489 FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->style_name, (FcChar8 *) "") != 0)
1490 {
1491 if (FcDebug ()(FcDebugVal) & FC_DBG_SCANV256)
1492 printf ("using FreeType style \"%s\"\n", face->style_name);
1493 if (!FcPatternAddString (pat, FC_STYLE"style", (FcChar8 *) face->style_name))
1494 goto bail1;
1495 if (!FcPatternAddString (pat, FC_STYLELANG"stylelang", (FcChar8 *) "en"))
1496 goto bail1;
1497 ++nstyle;
1498 }
1499
1500 if (!nfamily && file && *file)
1501 {
1502 FcChar8 *start, *end;
1503 FcChar8 *family;
1504
1505 start = (FcChar8 *) strrchr ((char *) file, '/');
1506 if (start)
1507 start++;
1508 else
1509 start = (FcChar8 *) file;
1510 end = (FcChar8 *) strrchr ((char *) start, '.');
1511 if (!end)
1512 end = start + strlen ((char *) start);
1513 /* freed below */
1514 family = malloc (end - start + 1);
1515 strncpy ((char *) family, (char *) start, end - start)__builtin___strncpy_chk ((char *) family, (char *) start, end
- start, __builtin_object_size ((char *) family, 2 > 1 ? 1
: 0))
;
1516 family[end - start] = '\0';
1517 if (FcDebug ()(FcDebugVal) & FC_DBG_SCANV256)
1518 printf ("using filename for family %s\n", family);
1519 if (!FcPatternAddString (pat, FC_FAMILY"family", family))
1520 {
1521 free (family);
1522 goto bail1;
1523 }
1524 free (family);
1525 ++nfamily;
1526 }
1527
1528 /* Add the PostScript name into the cache */
1529 tmp = FT_Get_Postscript_Name (face);
1530 if (!tmp)
1531 {
1532 FcChar8 *family, *familylang = NULL((void*)0);
1533 size_t len;
1534 int n = 0;
1535
1536 /* Workaround when FT_Get_Postscript_Name didn't give any name.
1537 * try to find out the English family name and convert.
1538 */
1539 while (FcPatternObjectGetString (pat, FC_FAMILYLANG_OBJECT, n, &familylang) == FcResultMatch)
1540 {
1541 if (FcStrCmp (familylang, (const FcChar8 *)"en") == 0)
1542 break;
1543 n++;
1544 familylang = NULL((void*)0);
1545 }
1546 if (!familylang)
1547 n = 0;
1548
1549 if (FcPatternObjectGetString (pat, FC_FAMILY_OBJECT, n, &family) != FcResultMatch)
1550 goto bail1;
1551 len = strlen ((const char *)family);
1552 /* the literal name in PostScript Language is limited to 127 characters though,
1553 * It is the architectural limit. so assuming 255 characters may works enough.
1554 */
1555 for (i = 0; i < len && i < 255; i++)
1556 {
1557 /* those characters are not allowed to be the literal name in PostScript */
1558 static const char exclusive_chars[] = "\x04()/<>[]{}\t\f\r\n ";
1559
1560 if (strchr(exclusive_chars, family[i]) != NULL((void*)0))
1561 psname[i] = '-';
1562 else
1563 psname[i] = family[i];
1564 }
1565 psname[i] = 0;
1566 }
1567 else
1568 {
1569 strncpy (psname, tmp, 255)__builtin___strncpy_chk (psname, tmp, 255, __builtin_object_size
(psname, 2 > 1 ? 1 : 0))
;
1570 psname[255] = 0;
1571 }
1572 if (!FcPatternAddString (pat, FC_POSTSCRIPT_NAME"postscriptname", (const FcChar8 *)psname))
1573 goto bail1;
1574
1575 if (file && *file && !FcPatternAddString (pat, FC_FILE"file", file))
1576 goto bail1;
1577
1578 if (!FcPatternAddInteger (pat, FC_INDEX"index", id))
1579 goto bail1;
1580
1581#if 0
1582 /*
1583 * don't even try this -- CJK 'monospace' fonts are really
1584 * dual width, and most other fonts don't bother to set
1585 * the attribute. Sigh.
1586 */
1587 if ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH( 1L << 2 )) != 0)
1588 if (!FcPatternAddInteger (pat, FC_SPACING"spacing", FC_MONO100))
1589 goto bail1;
1590#endif
1591
1592 /*
1593 * Find the font revision (if available)
1594 */
1595 head = (TT_Header *) FT_Get_Sfnt_Table (face, ft_sfnt_head);
1596 if (head)
1597 {
1598 if (!FcPatternAddInteger (pat, FC_FONTVERSION"fontversion", head->Font_Revision))
1599 goto bail1;
1600 }
1601 else
1602 {
1603 if (!FcPatternAddInteger (pat, FC_FONTVERSION"fontversion", 0))
1604 goto bail1;
1605 }
1606
1607 if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
1608 {
1609 for (i = 0; i < NUM_CODE_PAGE_RANGE(int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0]); i++)
1610 {
1611 FT_ULong bits;
1612 int bit;
1613 if (FcCodePageRange[i].bit < 32)
1614 {
1615 bits = os2->ulCodePageRange1;
1616 bit = FcCodePageRange[i].bit;
1617 }
1618 else
1619 {
1620 bits = os2->ulCodePageRange2;
1621 bit = FcCodePageRange[i].bit - 32;
1622 }
1623 if (bits & (1 << bit))
1624 {
1625 /*
1626 * If the font advertises support for multiple
1627 * "exclusive" languages, then include support
1628 * for any language found to have coverage
1629 */
1630 if (exclusiveLang)
1631 {
1632 exclusiveLang = 0;
1633 break;
1634 }
1635 exclusiveLang = FcCodePageRange[i].lang;
1636 }
1637 }
1638 }
1639
1640 if (os2 && os2->version != 0xffff)
1641 {
1642 weight = os2->usWeightClass;
1643 if (weight < 10 && weight_mult != 1.0)
1644 {
1645 /* Work around bad values by cleaning them up before
1646 * multiplying by weight_mult. */
1647 weight = FcWeightToOpenType (FcWeightFromOpenType (weight));
1648 }
1649 weight = FcWeightFromOpenType ((int) (weight * weight_mult + .5));
1650 if ((FcDebug()(FcDebugVal) & FC_DBG_SCANV256) && weight != -1)
1651 printf ("\tos2 weight class %d multiplier %g maps to weight %d\n",
1652 os2->usWeightClass, weight_mult, weight);
1653
1654 /* TODO:
1655 * Add FcWidthFromOpenType and FcWidthToOpenType,
1656 * and apply width_mult post-conversion? */
1657 switch ((int) (os2->usWidthClass * width_mult + .5)) {
1658 case 1: width = FC_WIDTH_ULTRACONDENSED50; break;
1659 case 2: width = FC_WIDTH_EXTRACONDENSED63; break;
1660 case 3: width = FC_WIDTH_CONDENSED75; break;
1661 case 4: width = FC_WIDTH_SEMICONDENSED87; break;
1662 case 5: width = FC_WIDTH_NORMAL100; break;
1663 case 6: width = FC_WIDTH_SEMIEXPANDED113; break;
1664 case 7: width = FC_WIDTH_EXPANDED125; break;
1665 case 8: width = FC_WIDTH_EXTRAEXPANDED150; break;
1666 case 9: width = FC_WIDTH_ULTRAEXPANDED200; break;
1667 }
1668 if ((FcDebug()(FcDebugVal) & FC_DBG_SCANV256) && width != -1)
1669 printf ("\tos2 width class %d multiplier %g maps to width %d\n",
1670 os2->usWidthClass, width_mult, width);
1671 }
1672 if (os2 && (complex_ = FcFontCapabilities(face)))
1673 {
1674 if (!FcPatternAddString (pat, FC_CAPABILITY"capability", complex_))
1675 {
1676 free (complex_);
1677 goto bail1;
1678 }
1679 free (complex_);
1680 }
1681
1682#if defined (HAVE_TT_OS2_USUPPEROPTICALPOINTSIZE) && defined (HAVE_TT_OS2_USLOWEROPTICALPOINTSIZE)
1683 if (os2 && os2->version >= 0x0005 && os2->version != 0xffff)
1684 {
1685 double lower_size, upper_size;
1686
1687 /* usLowerPointSize and usUpperPointSize is actually twips */
1688 lower_size = os2->usLowerOpticalPointSize / 20.0L;
1689 upper_size = os2->usUpperOpticalPointSize / 20.0L;
1690
1691 r = FcRangeCreateDouble (lower_size, upper_size);
1692 if (!FcPatternAddRange (pat, FC_SIZE"size", r))
1693 {
1694 FcRangeDestroy (r);
1695 goto bail1;
1696 }
1697 FcRangeDestroy (r);
1698 }
1699#endif
1700
1701 /*
1702 * Type 1: Check for FontInfo dictionary information
1703 * Code from g2@magestudios.net (Gerard Escalante)
1704 */
1705
1706#if HAVE_FT_GET_PS_FONT_INFO1
1707 if (FT_Get_PS_Font_Info(face, &psfontinfo) == 0)
1708 {
1709 if (weight == -1 && psfontinfo.weight)
1710 {
1711 weight = FcIsWeight ((FcChar8 *) psfontinfo.weight)FcStringIsConst((FcChar8 *) psfontinfo.weight,weightConsts,(int
) (sizeof (weightConsts) / sizeof (weightConsts[0])))
;
1712 if (FcDebug()(FcDebugVal) & FC_DBG_SCANV256)
1713 printf ("\tType1 weight %s maps to %d\n",
1714 psfontinfo.weight, weight);
1715 }
1716
1717#if 0
1718 /*
1719 * Don't bother with italic_angle; FreeType already extracts that
1720 * information for us and sticks it into style_flags
1721 */
1722 if (psfontinfo.italic_angle)
1723 slant = FC_SLANT_ITALIC100;
1724 else
1725 slant = FC_SLANT_ROMAN0;
1726#endif
1727
1728 if(!foundry)
1729 foundry = FcNoticeFoundry(psfontinfo.notice);
1730 }
1731#endif /* HAVE_FT_GET_PS_FONT_INFO */
1732
1733#if HAVE_FT_GET_BDF_PROPERTY1
1734 /*
1735 * Finally, look for a FOUNDRY BDF property if no other
1736 * mechanism has managed to locate a foundry
1737 */
1738
1739 if (!foundry)
1740 {
1741 int rc;
1742 rc = FT_Get_BDF_Property(face, "FOUNDRY", &prop);
1743 if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM)
1744 foundry = (FcChar8 *) prop.u.atom;
1745 }
1746
1747 if (width == -1)
1748 {
1749 if (FT_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 &&
1750 (prop.type == BDF_PROPERTY_TYPE_INTEGER ||
1751 prop.type == BDF_PROPERTY_TYPE_CARDINAL))
1752 {
1753 FT_Int32 value;
1754
1755 if (prop.type == BDF_PROPERTY_TYPE_INTEGER)
1756 value = prop.u.integer;
1757 else
1758 value = (FT_Int32) prop.u.cardinal;
1759 switch ((value + 5) / 10) {
1760 case 1: width = FC_WIDTH_ULTRACONDENSED50; break;
1761 case 2: width = FC_WIDTH_EXTRACONDENSED63; break;
1762 case 3: width = FC_WIDTH_CONDENSED75; break;
1763 case 4: width = FC_WIDTH_SEMICONDENSED87; break;
1764 case 5: width = FC_WIDTH_NORMAL100; break;
1765 case 6: width = FC_WIDTH_SEMIEXPANDED113; break;
1766 case 7: width = FC_WIDTH_EXPANDED125; break;
1767 case 8: width = FC_WIDTH_EXTRAEXPANDED150; break;
1768 case 9: width = FC_WIDTH_ULTRAEXPANDED200; break;
1769 }
1770 }
1771 if (width == -1 &&
1772 FT_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 &&
1773 prop.type == BDF_PROPERTY_TYPE_ATOM && prop.u.atom != NULL((void*)0))
1774 {
1775 width = FcIsWidth ((FcChar8 *) prop.u.atom)FcStringIsConst((FcChar8 *) prop.u.atom,widthConsts,(int) (sizeof
(widthConsts) / sizeof (widthConsts[0])))
;
1776 if (FcDebug ()(FcDebugVal) & FC_DBG_SCANV256)
1777 printf ("\tsetwidth %s maps to %d\n", prop.u.atom, width);
1778 }
1779 }
1780#endif
1781
1782 /*
1783 * Look for weight, width and slant names in the style value
1784 */
1785 for (st = 0; FcPatternGetString (pat, FC_STYLE"style", st, &style) == FcResultMatch; st++)
1786 {
1787 if (weight == -1)
1788 {
1789 weight = FcContainsWeight (style)FcStringContainsConst (style,weightConsts,(int) (sizeof (weightConsts
) / sizeof (weightConsts[0])))
;
1790 if (FcDebug()(FcDebugVal) & FC_DBG_SCANV256)
1791 printf ("\tStyle %s maps to weight %d\n", style, weight);
1792 }
1793 if (width == -1)
1794 {
1795 width = FcContainsWidth (style)FcStringContainsConst (style,widthConsts,(int) (sizeof (widthConsts
) / sizeof (widthConsts[0])))
;
1796 if (FcDebug()(FcDebugVal) & FC_DBG_SCANV256)
1797 printf ("\tStyle %s maps to width %d\n", style, width);
1798 }
1799 if (slant == -1)
1800 {
1801 slant = FcContainsSlant (style)FcStringContainsConst (style,slantConsts,(int) (sizeof (slantConsts
) / sizeof (slantConsts[0])))
;
1802 if (FcDebug()(FcDebugVal) & FC_DBG_SCANV256)
1803 printf ("\tStyle %s maps to slant %d\n", style, slant);
1804 }
1805 if (decorative == FcFalse0)
1806 {
1807 decorative = FcContainsDecorative (style)FcStringContainsConst (style,decorativeConsts,(int) (sizeof (
decorativeConsts) / sizeof (decorativeConsts[0])))
> 0;
1808 if (FcDebug()(FcDebugVal) & FC_DBG_SCANV256)
1809 printf ("\tStyle %s maps to decorative %d\n", style, decorative);
1810 }
1811 }
1812 /*
1813 * Pull default values from the FreeType flags if more
1814 * specific values not found above
1815 */
1816 if (slant == -1)
1817 {
1818 slant = FC_SLANT_ROMAN0;
1819 if (face->style_flags & FT_STYLE_FLAG_ITALIC( 1 << 0 ))
1820 slant = FC_SLANT_ITALIC100;
1821 }
1822
1823 if (weight == -1)
1824 {
1825 weight = FC_WEIGHT_MEDIUM100;
1826 if (face->style_flags & FT_STYLE_FLAG_BOLD( 1 << 1 ))
1827 weight = FC_WEIGHT_BOLD200;
1828 }
1829
1830 if (width == -1)
1831 width = FC_WIDTH_NORMAL100;
1832
1833 if (foundry == 0)
1834 foundry = (FcChar8 *) "unknown";
1835
1836 if (!FcPatternAddInteger (pat, FC_SLANT"slant", slant))
1837 goto bail1;
1838
1839 if (!FcPatternAddInteger (pat, FC_WEIGHT"weight", weight))
1840 goto bail1;
1841
1842 if (!FcPatternAddInteger (pat, FC_WIDTH"width", width))
1843 goto bail1;
1844
1845 if (!FcPatternAddString (pat, FC_FOUNDRY"foundry", foundry))
1846 goto bail1;
1847
1848 if (!FcPatternAddBool (pat, FC_DECORATIVE"decorative", decorative))
1849 goto bail1;
1850
1851
1852 /*
1853 * Compute the unicode coverage for the font
1854 */
1855 cs = FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
1856 if (!cs)
1857 goto bail1;
1858
1859 /* The FcFreeTypeCharSetAndSpacing() chose the encoding; test it for symbol. */
1860 symbol = face->charmap && face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
1861 if (!FcPatternAddBool (pat, FC_SYMBOL"symbol", symbol))
1862 goto bail1;
1863
1864#if HAVE_FT_GET_BDF_PROPERTY1
1865 /* For PCF fonts, override the computed spacing with the one from
1866 the property */
1867 if(FT_Get_BDF_Property(face, "SPACING", &prop) == 0 &&
1868 prop.type == BDF_PROPERTY_TYPE_ATOM && prop.u.atom != NULL((void*)0)) {
1869 if(!strcmp(prop.u.atom, "c") || !strcmp(prop.u.atom, "C"))
1870 spacing = FC_CHARCELL110;
1871 else if(!strcmp(prop.u.atom, "m") || !strcmp(prop.u.atom, "M"))
1872 spacing = FC_MONO100;
1873 else if(!strcmp(prop.u.atom, "p") || !strcmp(prop.u.atom, "P"))
1874 spacing = FC_PROPORTIONAL0;
1875 }
1876#endif
1877
1878 /*
1879 * Skip over PCF fonts that have no encoded characters; they're
1880 * usually just Unicode fonts transcoded to some legacy encoding
1881 * FT forces us to approximate whether a font is a PCF font
1882 * or not by whether it has any BDF properties. Try PIXEL_SIZE;
1883 * I don't know how to get a list of BDF properties on the font. -PL
1884 */
1885 if (FcCharSetCount (cs) == 0)
1886 {
1887#if HAVE_FT_GET_BDF_PROPERTY1
1888 if(FT_Get_BDF_Property(face, "PIXEL_SIZE", &prop) == 0)
1889 goto bail2;
1890#endif
1891 }
1892
1893 if (!FcPatternAddCharSet (pat, FC_CHARSET"charset", cs))
1894 goto bail2;
1895
1896 if (!symbol)
1897 {
1898 ls = FcFreeTypeLangSet (cs, exclusiveLang);
1899 if (!ls)
1900 goto bail2;
1901 }
1902 else
1903 {
1904 /* Symbol fonts don't cover any language, even though they
1905 * claim to support Latin1 range. */
1906 ls = FcLangSetCreate ();
1907 }
1908
1909 if (!FcPatternAddLangSet (pat, FC_LANG"lang", ls))
1910 {
1911 FcLangSetDestroy (ls);
1912 goto bail2;
1913 }
1914
1915 FcLangSetDestroy (ls);
1916
1917 if (spacing != FC_PROPORTIONAL0)
1918 if (!FcPatternAddInteger (pat, FC_SPACING"spacing", spacing))
1919 goto bail2;
1920
1921 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 )))
1922 {
1923 for (i = 0; i < face->num_fixed_sizes; i++)
1924 if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE"pixelsize",
1925 FcGetPixelSize (face, i)))
1926 goto bail2;
1927 if (!FcPatternAddBool (pat, FC_ANTIALIAS"antialias", FcFalse0))
1928 goto bail2;
1929 }
1930#if HAVE_FT_GET_X11_FONT_FORMAT1
1931 /*
1932 * Use the (not well documented or supported) X-specific function
1933 * from FreeType to figure out the font format
1934 */
1935 {
1936 const char *font_format = FT_Get_X11_Font_Format (face);
1937 if (font_format)
1938 if (!FcPatternAddString (pat, FC_FONTFORMAT"fontformat", (FcChar8 *) font_format))
1939 goto bail2;
1940 }
1941#endif
1942
1943 /*
1944 * Drop our reference to the charset
1945 */
1946 FcCharSetDestroy (cs);
1947 if (foundry_)
1948 free (foundry_);
1949
1950 if (master)
1951 {
1952 /* TODO: How to free master?! */
1953 }
1954
1955 return pat;
1956
1957bail2:
1958 FcCharSetDestroy (cs);
1959bail1:
1960 FcPatternDestroy (pat);
1961 if (foundry_)
1962 free (foundry_);
1963bail0:
1964 return NULL((void*)0);
1965}
1966
1967FcPattern *
1968FcFreeTypeQuery(const FcChar8 *file,
1969 int id,
1970 FcBlanks *blanks,
1971 int *count)
1972{
1973 FT_Face face;
1974 FT_Library ftLibrary;
1975 FcPattern *pat = NULL((void*)0);
1976
1977 if (FT_Init_FreeType (&ftLibrary))
1978 return NULL((void*)0);
1979
1980 if (FT_New_Face (ftLibrary, (char *) file, id, &face))
1981 goto bail;
1982
1983 *count = face->num_faces;
1984
1985 pat = FcFreeTypeQueryFace (face, file, id, blanks);
1986
1987 FT_Done_Face (face);
1988bail:
1989 FT_Done_FreeType (ftLibrary);
1990 return pat;
1991}
1992
1993/*
1994 * For our purposes, this approximation is sufficient
1995 */
1996#if !HAVE_FT_GET_NEXT_CHAR1
1997#define FT_Get_Next_Char(face, ucs4, gi) ((ucs4) >= 0xffffff ? \
1998 (*(gi) = 0), 0 : \
1999 (*(gi) = 1), (ucs4) + 1)
2000#warning "No FT_Get_Next_Char: Please install freetype version 2.1.0 or newer"
2001#endif
2002
2003static const FT_Encoding fcFontEncodings[] = {
2004 FT_ENCODING_UNICODE,
2005 FT_ENCODING_MS_SYMBOL
2006};
2007
2008#define NUM_DECODE(int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0])
)
(int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0]))
2009
2010static const FcChar32 prefer_unicode[] = {
2011 0x20ac, /* EURO SIGN */
2012};
2013
2014#include "../fc-glyphname/fcglyphname.h"
2015
2016static FcChar32
2017FcHashGlyphName (const FcChar8 *name)
2018{
2019 FcChar32 h = 0;
2020 FcChar8 c;
2021
2022 while ((c = *name++))
2023 {
2024 h = ((h << 1) | (h >> 31)) ^ c;
2025 }
2026 return h;
2027}
2028
2029#if HAVE_FT_HAS_PS_GLYPH_NAMES1
2030/*
2031 * Use Type1 glyph names for fonts which have reliable names
2032 * and which export an Adobe Custom mapping
2033 */
2034static FcBool
2035FcFreeTypeUseNames (FT_Face face)
2036{
2037 FT_Int map;
2038
2039 if (!FT_Has_PS_Glyph_Names (face))
2040 return FcFalse0;
2041 for (map = 0; map < face->num_charmaps; map++)
2042 if (face->charmaps[map]->encoding == ft_encoding_adobe_customFT_ENCODING_ADOBE_CUSTOM)
2043 return FcTrue1;
2044 return FcFalse0;
2045}
2046
2047static const FcChar8 *
2048FcUcs4ToGlyphName (FcChar32 ucs4)
2049{
2050 int i = (int) (ucs4 % FC_GLYPHNAME_HASH271);
2051 int r = 0;
2052 FcGlyphId gn;
2053
2054 while ((gn = _fc_ucs_to_name[i]) != -1)
2055 {
2056 if (_fc_glyph_names[gn].ucs == ucs4)
2057 return _fc_glyph_names[gn].name;
2058 if (!r)
2059 {
2060 r = (int) (ucs4 % FC_GLYPHNAME_REHASH269);
2061 if (!r)
2062 r = 1;
2063 }
2064 i += r;
2065 if (i >= FC_GLYPHNAME_HASH271)
2066 i -= FC_GLYPHNAME_HASH271;
2067 }
2068 return 0;
2069}
2070
2071static FcChar32
2072FcGlyphNameToUcs4 (FcChar8 *name)
2073{
2074 FcChar32 h = FcHashGlyphName (name);
2075 int i = (int) (h % FC_GLYPHNAME_HASH271);
2076 int r = 0;
2077 FcGlyphId gn;
2078
2079 while ((gn = _fc_name_to_ucs[i]) != -1)
2080 {
2081 if (!strcmp ((char *) name, (char *) _fc_glyph_names[gn].name))
2082 return _fc_glyph_names[gn].ucs;
2083 if (!r)
2084 {
2085 r = (int) (h % FC_GLYPHNAME_REHASH269);
2086 if (!r)
2087 r = 1;
2088 }
2089 i += r;
2090 if (i >= FC_GLYPHNAME_HASH271)
2091 i -= FC_GLYPHNAME_HASH271;
2092 }
2093 return 0xffff;
2094}
2095
2096/*
2097 * Work around a bug in some FreeType versions which fail
2098 * to correctly bounds check glyph name buffers and overwrite
2099 * the stack. As Postscript names have a limit of 127 characters,
2100 * this should be sufficient.
2101 */
2102
2103#if FC_GLYPHNAME_MAXLEN4 < 127
2104# define FC_GLYPHNAME_BUFLEN127 127
2105#else
2106# define FC_GLYPHNAME_BUFLEN127 FC_GLYPHNAME_MAXLEN4
2107#endif
2108
2109/*
2110 * Search through a font for a glyph by name. This is
2111 * currently a linear search as there doesn't appear to be
2112 * any defined order within the font
2113 */
2114static FT_UInt
2115FcFreeTypeGlyphNameIndex (FT_Face face, const FcChar8 *name)
2116{
2117 FT_UInt gindex;
2118 FcChar8 name_buf[FC_GLYPHNAME_BUFLEN127 + 2];
2119
2120 for (gindex = 0; gindex < (FT_UInt) face->num_glyphs; gindex++)
2121 {
2122 if (FT_Get_Glyph_Name (face, gindex, name_buf, FC_GLYPHNAME_BUFLEN127+1) == 0)
2123 if (!strcmp ((char *) name, (char *) name_buf))
2124 return gindex;
2125 }
2126 return 0;
2127}
2128#endif
2129
2130/*
2131 * Map a UCS4 glyph to a glyph index. Use all available encoding
2132 * tables to try and find one that works. This information is expected
2133 * to be cached by higher levels, so performance isn't critical
2134 */
2135
2136FT_UInt
2137FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
2138{
2139 int initial, offset, decode;
2140 FT_UInt glyphindex;
2141
2142 initial = 0;
2143
2144 if (!face)
2145 return 0;
2146
2147 /*
2148 * Find the current encoding
2149 */
2150 if (face->charmap)
2151 {
2152 for (; initial < NUM_DECODE(int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0])
)
; initial++)
2153 if (fcFontEncodings[initial] == face->charmap->encoding)
2154 break;
2155 if (initial == NUM_DECODE(int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0])
)
)
2156 initial = 0;
2157 }
2158 /*
2159 * Check each encoding for the glyph, starting with the current one
2160 */
2161 for (offset = 0; offset < NUM_DECODE(int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0])
)
; offset++)
2162 {
2163 decode = (initial + offset) % NUM_DECODE(int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0])
)
;
2164 if (!face->charmap || face->charmap->encoding != fcFontEncodings[decode])
2165 if (FT_Select_Charmap (face, fcFontEncodings[decode]) != 0)
2166 continue;
2167 glyphindex = FT_Get_Char_Index (face, (FT_ULong) ucs4);
2168 if (glyphindex)
2169 return glyphindex;
2170 if (ucs4 < 0x100 && face->charmap &&
2171 face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
2172 {
2173 /* For symbol-encoded OpenType fonts, we duplicate the
2174 * U+F000..F0FF range at U+0000..U+00FF. That's what
2175 * Windows seems to do, and that's hinted about at:
2176 * http://www.microsoft.com/typography/otspec/recom.htm
2177 * under "Non-Standard (Symbol) Fonts".
2178 *
2179 * See thread with subject "Webdings and other MS symbol
2180 * fonts don't display" on mailing list from May 2015.
2181 */
2182 glyphindex = FT_Get_Char_Index (face, (FT_ULong) ucs4 + 0xF000);
2183 if (glyphindex)
2184 return glyphindex;
2185 }
2186 }
2187#if HAVE_FT_HAS_PS_GLYPH_NAMES1
2188 /*
2189 * Check postscript name table if present
2190 */
2191 if (FcFreeTypeUseNames (face))
2192 {
2193 const FcChar8 *name = FcUcs4ToGlyphName (ucs4);
2194 if (name)
2195 {
2196 glyphindex = FcFreeTypeGlyphNameIndex (face, name);
2197 if (glyphindex)
2198 return glyphindex;
2199 }
2200 }
2201#endif
2202 return 0;
2203}
2204
2205static FcBool
2206FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4,
2207 FT_UInt glyph, FcBlanks *blanks,
2208 FT_Pos *advance,
2209 FcBool using_strike)
2210{
2211 FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH0x200 | FT_LOAD_NO_SCALE0x1 | FT_LOAD_NO_HINTING0x2;
2212 FT_GlyphSlot slot;
2213
2214 if (using_strike)
2215 load_flags &= ~FT_LOAD_NO_SCALE0x1;
2216
2217 /*
2218 * When using scalable fonts, only report those glyphs
2219 * which can be scaled; otherwise those fonts will
2220 * only be available at some sizes, and never when
2221 * transformed. Avoid this by simply reporting bitmap-only
2222 * glyphs as missing
2223 */
2224 if (face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 ))
2225 load_flags |= FT_LOAD_NO_BITMAP0x8;
2226
2227 if (FT_Load_Glyph (face, glyph, load_flags))
2228 return FcFalse0;
2229
2230 slot = face->glyph;
2231 if (!glyph)
2232 return FcFalse0;
2233
2234 *advance = slot->metrics.horiAdvance;
2235
2236 switch ((int) slot->format) {
2237 case ft_glyph_format_bitmapFT_GLYPH_FORMAT_BITMAP:
2238 /*
2239 * Bitmaps are assumed to be reasonable; if
2240 * this proves to be a rash assumption, this
2241 * code can be easily modified
2242 */
2243 return FcTrue1;
2244 case ft_glyph_format_outlineFT_GLYPH_FORMAT_OUTLINE:
2245 /*
2246 * Glyphs with contours are always OK
2247 */
2248 if (slot->outline.n_contours != 0)
2249 return FcTrue1;
2250 /*
2251 * Glyphs with no contours are only OK if
2252 * they're members of the Blanks set specified
2253 * in the configuration. If blanks isn't set,
2254 * then allow any glyph to be blank
2255 */
2256 if (!blanks || FcBlanksIsMember (blanks, ucs4))
2257 return FcTrue1;
2258 /* fall through ... */
2259 default:
2260 break;
2261 }
2262 return FcFalse0;
2263}
2264
2265#define APPROXIMATELY_EQUAL(x,y)((((x) - (y)) < 0 ? -((x) - (y)) : ((x) - (y))) <= ((((
x) < 0 ? -(x) : (x))) > (((y) < 0 ? -(y) : (y))) ? (
((x) < 0 ? -(x) : (x))) : (((y) < 0 ? -(y) : (y)))) / 33
)
(FC_ABS ((x) - (y))(((x) - (y)) < 0 ? -((x) - (y)) : ((x) - (y))) <= FC_MAX (FC_ABS (x), FC_ABS (y))((((x) < 0 ? -(x) : (x))) > (((y) < 0 ? -(y) : (y)))
? (((x) < 0 ? -(x) : (x))) : (((y) < 0 ? -(y) : (y))))
/ 33)
2266
2267static FcCharSet *
2268FcFreeTypeCharSetAndSpacingForSize (FT_Face face, FcBlanks *blanks, int *spacing, FT_Int strike_index)
2269{
2270 FcChar32 page, off, ucs4;
2271#ifdef CHECK
2272 FcChar32 font_max = 0;
2273#endif
2274 FcCharSet *fcs;
2275 FcCharLeaf *leaf;
2276 int o;
2277 FT_UInt glyph;
2278 FT_Pos advance, advance_one = 0, advance_two = 0;
2279 FcBool has_advance = FcFalse0, fixed_advance = FcTrue1, dual_advance = FcFalse0;
2280 FcBool using_strike = FcFalse0;
2281
2282 fcs = FcCharSetCreate ();
2283 if (!fcs)
2284 goto bail0;
2285
2286#if HAVE_FT_SELECT_SIZE1
2287 if (strike_index >= 0) {
2288 if (FT_Select_Size (face, strike_index) != FT_Err_Ok)
2289 goto bail1;
2290 using_strike = FcTrue1;
2291 }
2292#endif
2293
2294#ifdef CHECK
2295 printf ("Family %s style %s\n", face->family_name, face->style_name);
2296#endif
2297 for (o = 0; o < NUM_DECODE(int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0])
)
; o++)
2298 {
2299 if (FT_Select_Charmap (face, fcFontEncodings[o]) != 0)
2300 continue;
2301
2302 {
2303 page = ~0;
2304 leaf = NULL((void*)0);
2305 ucs4 = FT_Get_First_Char (face, &glyph);
2306 while (glyph != 0)
2307 {
2308 if (FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike))
2309 {
2310 if (advance)
2311 {
2312 if (!has_advance)
2313 {
2314 has_advance = FcTrue1;
2315 advance_one = advance;
2316 }
2317 else if (!APPROXIMATELY_EQUAL (advance, advance_one)((((advance) - (advance_one)) < 0 ? -((advance) - (advance_one
)) : ((advance) - (advance_one))) <= ((((advance) < 0 ?
-(advance) : (advance))) > (((advance_one) < 0 ? -(advance_one
) : (advance_one))) ? (((advance) < 0 ? -(advance) : (advance
))) : (((advance_one) < 0 ? -(advance_one) : (advance_one)
))) / 33)
)
2318 {
2319 if (fixed_advance)
2320 {
2321 dual_advance = FcTrue1;
2322 fixed_advance = FcFalse0;
2323 advance_two = advance;
2324 }
2325 else if (!APPROXIMATELY_EQUAL (advance, advance_two)((((advance) - (advance_two)) < 0 ? -((advance) - (advance_two
)) : ((advance) - (advance_two))) <= ((((advance) < 0 ?
-(advance) : (advance))) > (((advance_two) < 0 ? -(advance_two
) : (advance_two))) ? (((advance) < 0 ? -(advance) : (advance
))) : (((advance_two) < 0 ? -(advance_two) : (advance_two)
))) / 33)
)
2326 dual_advance = FcFalse0;
2327 }
2328 }
2329
2330 if ((ucs4 >> 8) != page)
2331 {
2332 page = (ucs4 >> 8);
2333 leaf = FcCharSetFindLeafCreate (fcs, ucs4);
2334 if (!leaf)
2335 goto bail1;
2336 }
2337 off = ucs4 & 0xff;
2338 leaf->map[off >> 5] |= (1 << (off & 0x1f));
2339#ifdef CHECK
2340 if (ucs4 > font_max)
2341 font_max = ucs4;
2342#endif
2343 }
2344 ucs4 = FT_Get_Next_Char (face, ucs4, &glyph);
2345 }
2346 if (fcFontEncodings[o] == FT_ENCODING_MS_SYMBOL)
2347 {
2348 /* For symbol-encoded OpenType fonts, we duplicate the
2349 * U+F000..F0FF range at U+0000..U+00FF. That's what
2350 * Windows seems to do, and that's hinted about at:
2351 * http://www.microsoft.com/typography/otspec/recom.htm
2352 * under "Non-Standard (Symbol) Fonts".
2353 *
2354 * See thread with subject "Webdings and other MS symbol
2355 * fonts don't display" on mailing list from May 2015.
2356 */
2357 for (ucs4 = 0xF000; ucs4 < 0xF100; ucs4++)
2358 {
2359 if (FcCharSetHasChar (fcs, ucs4))
2360 FcCharSetAddChar (fcs, ucs4 - 0xF000);
2361 }
2362 }
2363#ifdef CHECK
2364 for (ucs4 = 0; ucs4 < 0x10000; ucs4++)
2365 {
2366 FcBool FT_Has, FC_Has;
2367
2368 FT_Has = FT_Get_Char_Index (face, ucs4) != 0;
2369 FC_Has = FcCharSetHasChar (fcs, ucs4);
2370 if (FT_Has != FC_Has)
2371 {
2372 printf ("0x%08x FT says %d FC says %d\n", ucs4, FT_Has, FC_Has);
2373 }
2374 }
2375#endif
2376 }
2377
2378 break;
2379 }
2380#if HAVE_FT_HAS_PS_GLYPH_NAMES1
2381 /*
2382 * Add mapping from PS glyph names if available
2383 */
2384 if (FcFreeTypeUseNames (face))
2385 {
2386 FcChar8 name_buf[FC_GLYPHNAME_BUFLEN127 + 2];
2387
2388 for (glyph = 0; glyph < (FT_UInt) face->num_glyphs; glyph++)
2389 {
2390 if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_BUFLEN127+1) == 0)
2391 {
2392 ucs4 = FcGlyphNameToUcs4 (name_buf);
2393 if (ucs4 != 0xffff &&
2394 FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike))
2395 {
2396 if (advance)
2397 {
2398 if (!has_advance)
2399 {
2400 has_advance = FcTrue1;
2401 advance_one = advance;
2402 }
2403 else if (!APPROXIMATELY_EQUAL (advance, advance_one)((((advance) - (advance_one)) < 0 ? -((advance) - (advance_one
)) : ((advance) - (advance_one))) <= ((((advance) < 0 ?
-(advance) : (advance))) > (((advance_one) < 0 ? -(advance_one
) : (advance_one))) ? (((advance) < 0 ? -(advance) : (advance
))) : (((advance_one) < 0 ? -(advance_one) : (advance_one)
))) / 33)
)
2404 {
2405 if (fixed_advance)
2406 {
2407 dual_advance = FcTrue1;
2408 fixed_advance = FcFalse0;
2409 advance_two = advance;
2410 }
2411 else if (!APPROXIMATELY_EQUAL (advance, advance_two)((((advance) - (advance_two)) < 0 ? -((advance) - (advance_two
)) : ((advance) - (advance_two))) <= ((((advance) < 0 ?
-(advance) : (advance))) > (((advance_two) < 0 ? -(advance_two
) : (advance_two))) ? (((advance) < 0 ? -(advance) : (advance
))) : (((advance_two) < 0 ? -(advance_two) : (advance_two)
))) / 33)
)
2412 dual_advance = FcFalse0;
2413 }
2414 }
2415 leaf = FcCharSetFindLeafCreate (fcs, ucs4);
2416 if (!leaf)
2417 goto bail1;
2418 leaf->map[(ucs4 & 0xff) >> 5] |= (1 << (ucs4 & 0x1f));
2419#ifdef CHECK
2420 if (ucs4 > font_max)
2421 font_max = ucs4;
2422#endif
2423 }
2424 }
2425 }
2426 }
2427#endif
2428#ifdef CHECK
2429 printf ("%d glyphs %d encoded\n", (int) face->num_glyphs, FcCharSetCount (fcs));
2430 for (ucs4 = 0; ucs4 <= font_max; ucs4++)
2431 {
2432 FcBool has_char = (glyph = FcFreeTypeCharIndex (face, ucs4)) != 0;
2433 FcBool has_bit = FcCharSetHasChar (fcs, ucs4);
2434
2435 if (has_char && !has_bit)
2436 {
2437 if (!FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike))
2438 printf ("Bitmap missing broken char 0x%x\n", ucs4);
2439 else
2440 printf ("Bitmap missing char 0x%x\n", ucs4);
2441 }
2442 else if (!has_char && has_bit)
2443 printf ("Bitmap extra char 0x%x\n", ucs4);
2444 }
2445#endif
2446 if (fixed_advance)
2447 *spacing = FC_MONO100;
2448 else if (dual_advance && APPROXIMATELY_EQUAL (2 * FC_MIN (advance_one, advance_two), FC_MAX (advance_one, advance_two))((((2 * ((advance_one) < (advance_two) ? (advance_one) : (
advance_two))) - (((advance_one) > (advance_two) ? (advance_one
) : (advance_two)))) < 0 ? -((2 * ((advance_one) < (advance_two
) ? (advance_one) : (advance_two))) - (((advance_one) > (advance_two
) ? (advance_one) : (advance_two)))) : ((2 * ((advance_one) <
(advance_two) ? (advance_one) : (advance_two))) - (((advance_one
) > (advance_two) ? (advance_one) : (advance_two))))) <=
((((2 * ((advance_one) < (advance_two) ? (advance_one) : (
advance_two))) < 0 ? -(2 * ((advance_one) < (advance_two
) ? (advance_one) : (advance_two))) : (2 * ((advance_one) <
(advance_two) ? (advance_one) : (advance_two))))) > (((((
advance_one) > (advance_two) ? (advance_one) : (advance_two
))) < 0 ? -(((advance_one) > (advance_two) ? (advance_one
) : (advance_two))) : (((advance_one) > (advance_two) ? (advance_one
) : (advance_two))))) ? (((2 * ((advance_one) < (advance_two
) ? (advance_one) : (advance_two))) < 0 ? -(2 * ((advance_one
) < (advance_two) ? (advance_one) : (advance_two))) : (2 *
((advance_one) < (advance_two) ? (advance_one) : (advance_two
))))) : (((((advance_one) > (advance_two) ? (advance_one) :
(advance_two))) < 0 ? -(((advance_one) > (advance_two)
? (advance_one) : (advance_two))) : (((advance_one) > (advance_two
) ? (advance_one) : (advance_two)))))) / 33)
)
2449 *spacing = FC_DUAL90;
2450 else
2451 *spacing = FC_PROPORTIONAL0;
2452 return fcs;
2453bail1:
2454 FcCharSetDestroy (fcs);
2455bail0:
2456 return 0;
2457}
2458
2459FcCharSet *
2460FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
2461{
2462 FcCharSet *cs;
2463
2464 /*
2465 * Check for bitmap-only ttf fonts that are missing the glyf table.
2466 * In that case, pick a size and look for glyphs in that size instead
2467 */
2468 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 )) &&
2469 face->num_fixed_sizes > 0 &&
2470 FT_Get_Sfnt_Table (face, ft_sfnt_head))
2471 {
2472 FT_Int strike_index = 0;
2473 int i;
2474
2475 /* Select the face closest to 16 pixels tall */
2476 for (i = 1; i < face->num_fixed_sizes; i++) {
2477 if (abs (face->available_sizes[i].height - 16) <
2478 abs (face->available_sizes[strike_index].height - 16))
2479 strike_index = i;
2480 }
2481 cs = FcFreeTypeCharSetAndSpacingForSize (face, blanks, spacing, strike_index);
2482 }
2483 else
2484 cs = FcFreeTypeCharSetAndSpacingForSize (face, blanks, spacing, -1);
2485 return cs;
2486}
2487
2488FcCharSet *
2489FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks)
2490{
2491 int spacing;
2492
2493 return FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
2494}
2495
2496
2497#define TTAG_GPOS(FT_Tag) ( ( (FT_ULong)'G' << 24 ) | ( (FT_ULong)'P' <<
16 ) | ( (FT_ULong)'O' << 8 ) | (FT_ULong)'S' )
FT_MAKE_TAG( 'G', 'P', 'O', 'S' )(FT_Tag) ( ( (FT_ULong)'G' << 24 ) | ( (FT_ULong)'P' <<
16 ) | ( (FT_ULong)'O' << 8 ) | (FT_ULong)'S' )
2498#define TTAG_GSUB(FT_Tag) ( ( (FT_ULong)'G' << 24 ) | ( (FT_ULong)'S' <<
16 ) | ( (FT_ULong)'U' << 8 ) | (FT_ULong)'B' )
FT_MAKE_TAG( 'G', 'S', 'U', 'B' )(FT_Tag) ( ( (FT_ULong)'G' << 24 ) | ( (FT_ULong)'S' <<
16 ) | ( (FT_ULong)'U' << 8 ) | (FT_ULong)'B' )
2499#define TTAG_SILF(FT_Tag) ( ( (FT_ULong)'S' << 24 ) | ( (FT_ULong)'i' <<
16 ) | ( (FT_ULong)'l' << 8 ) | (FT_ULong)'f' )
FT_MAKE_TAG( 'S', 'i', 'l', 'f')(FT_Tag) ( ( (FT_ULong)'S' << 24 ) | ( (FT_ULong)'i' <<
16 ) | ( (FT_ULong)'l' << 8 ) | (FT_ULong)'f' )
2500
2501#define OTLAYOUT_HEAD"otlayout:" "otlayout:"
2502#define OTLAYOUT_HEAD_LEN9 9
2503#define OTLAYOUT_ID_LEN4 4
2504/* space + head + id */
2505#define OTLAYOUT_LEN(1 + 9 + 4) (1 + OTLAYOUT_HEAD_LEN9 + OTLAYOUT_ID_LEN4)
2506
2507/*
2508 * This is a bit generous; the registry has only lower case and space
2509 * except for 'DFLT'.
2510 */
2511#define FcIsSpace(x)(040 == (x)) (040 == (x))
2512#define FcIsDigit(c)(('0' <= (c) && (c) <= '9')) (('0' <= (c) && (c) <= '9'))
2513#define FcIsValidScript(x)(((0141 <= (x) && (x) <= 0172)) || ((0101 <=
(x) && (x) <= 0132)) || (('0' <= (x) &&
(x) <= '9')) || (040 == (x)))
(FcIsLower(x)((0141 <= (x) && (x) <= 0172)) || FcIsUpper (x)((0101 <= (x) && (x) <= 0132)) || FcIsDigit(x)(('0' <= (x) && (x) <= '9')) || FcIsSpace(x)(040 == (x)))
2514
2515static void
2516addtag(FcChar8 *complex_, FT_ULong tag)
2517{
2518 FcChar8 tagstring[OTLAYOUT_ID_LEN4 + 1];
2519
2520 tagstring[0] = (FcChar8)(tag >> 24),
2521 tagstring[1] = (FcChar8)(tag >> 16),
2522 tagstring[2] = (FcChar8)(tag >> 8),
2523 tagstring[3] = (FcChar8)(tag);
2524 tagstring[4] = '\0';
2525
2526 /* skip tags which aren't alphanumeric, under the assumption that
2527 * they're probably broken
2528 */
2529 if (!FcIsValidScript(tagstring[0])(((0141 <= (tagstring[0]) && (tagstring[0]) <= 0172
)) || ((0101 <= (tagstring[0]) && (tagstring[0]) <=
0132)) || (('0' <= (tagstring[0]) && (tagstring[0
]) <= '9')) || (040 == (tagstring[0])))
||
2530 !FcIsValidScript(tagstring[1])(((0141 <= (tagstring[1]) && (tagstring[1]) <= 0172
)) || ((0101 <= (tagstring[1]) && (tagstring[1]) <=
0132)) || (('0' <= (tagstring[1]) && (tagstring[1
]) <= '9')) || (040 == (tagstring[1])))
||
2531 !FcIsValidScript(tagstring[2])(((0141 <= (tagstring[2]) && (tagstring[2]) <= 0172
)) || ((0101 <= (tagstring[2]) && (tagstring[2]) <=
0132)) || (('0' <= (tagstring[2]) && (tagstring[2
]) <= '9')) || (040 == (tagstring[2])))
||
2532 !FcIsValidScript(tagstring[3])(((0141 <= (tagstring[3]) && (tagstring[3]) <= 0172
)) || ((0101 <= (tagstring[3]) && (tagstring[3]) <=
0132)) || (('0' <= (tagstring[3]) && (tagstring[3
]) <= '9')) || (040 == (tagstring[3])))
)
2533 return;
2534
2535 if (*complex_ != '\0')
2536 strcat ((char *) complex_, " ")__builtin___strcat_chk ((char *) complex_, " ", __builtin_object_size
((char *) complex_, 2 > 1 ? 1 : 0))
;
2537 strcat ((char *) complex_, OTLAYOUT_HEAD)__builtin___strcat_chk ((char *) complex_, "otlayout:", __builtin_object_size
((char *) complex_, 2 > 1 ? 1 : 0))
;
2538 strcat ((char *) complex_, (char *) tagstring)__builtin___strcat_chk ((char *) complex_, (char *) tagstring
, __builtin_object_size ((char *) complex_, 2 > 1 ? 1 : 0)
)
;
2539}
2540
2541static int
2542compareulong (const void *a, const void *b)
2543{
2544 const FT_ULong *ua = (const FT_ULong *) a;
2545 const FT_ULong *ub = (const FT_ULong *) b;
2546 return *ua - *ub;
2547}
2548
2549
2550static int
2551GetScriptTags(FT_Face face, FT_ULong tabletag, FT_ULong **stags)
2552{
2553 FT_ULong cur_offset, new_offset, base_offset;
2554 FT_Stream stream = face->stream;
2555 FT_Error error;
2556 FT_UShort n, p;
2557 int script_count;
2558
2559 if (!stream)
2560 return 0;
2561
2562 if (( error = ftglue_face_goto_table( face, tabletag, stream ) ))
2563 return 0;
2564
2565 base_offset = ftglue_stream_pos ( stream );
2566
2567 /* skip version */
2568
2569 if ( ftglue_stream_seek ( stream, base_offset + 4L ) || ftglue_stream_frame_enter( stream, 2L ) )
2570 return 0;
2571
2572 new_offset = GET_UShort()((FT_UShort)(stream->cursor += 2, (FT_Short)( (*(((FT_Byte
*)stream->cursor)-2) << 8) | *(((FT_Byte*)stream->
cursor)-1) )))
+ base_offset;
2573
2574 ftglue_stream_frame_exit( stream );
2575
2576 cur_offset = ftglue_stream_pos( stream );
Value stored to 'cur_offset' is never read
2577
2578 if ( ftglue_stream_seek( stream, new_offset ) != FT_Err_Ok )
2579 return 0;
2580
2581 base_offset = ftglue_stream_pos( stream );
2582
2583 if ( ftglue_stream_frame_enter( stream, 2L ) )
2584 return 0;
2585
2586 script_count = GET_UShort ()((FT_UShort)(stream->cursor += 2, (FT_Short)( (*(((FT_Byte
*)stream->cursor)-2) << 8) | *(((FT_Byte*)stream->
cursor)-1) )))
;
2587
2588 ftglue_stream_frame_exit( stream );
2589
2590 *stags = malloc(script_count * sizeof (FT_ULong));
2591 if (!stags)
2592 return 0;
2593
2594 p = 0;
2595 for ( n = 0; n < script_count; n++ )
2596 {
2597 if ( ftglue_stream_frame_enter( stream, 6L ) )
2598 goto Fail;
2599
2600 (*stags)[p] = GET_ULong ()((FT_ULong)(stream->cursor += 4, (FT_Long)( (*(((FT_Byte*)
stream->cursor)-4) << 24) | (*(((FT_Byte*)stream->
cursor)-3) << 16) | (*(((FT_Byte*)stream->cursor)-2)
<< 8) | *(((FT_Byte*)stream->cursor)-1) )))
;
2601 new_offset = GET_UShort ()((FT_UShort)(stream->cursor += 2, (FT_Short)( (*(((FT_Byte
*)stream->cursor)-2) << 8) | *(((FT_Byte*)stream->
cursor)-1) )))
+ base_offset;
2602
2603 ftglue_stream_frame_exit( stream );
2604
2605 cur_offset = ftglue_stream_pos( stream );
2606
2607 error = ftglue_stream_seek( stream, new_offset );
2608
2609 if ( error == FT_Err_Ok )
2610 p++;
2611
2612 (void)ftglue_stream_seek( stream, cur_offset );
2613 }
2614
2615 if (!p)
2616 goto Fail;
2617
2618 /* sort the tag list before returning it */
2619 qsort(*stags, script_count, sizeof(FT_ULong), compareulong);
2620
2621 return script_count;
2622
2623Fail:
2624 free(*stags);
2625 *stags = NULL((void*)0);
2626 return 0;
2627}
2628
2629static FcChar8 *
2630FcFontCapabilities(FT_Face face)
2631{
2632 FcBool issilgraphitefont = 0;
2633 FT_Error err;
2634 FT_ULong len = 0;
2635 FT_ULong *gsubtags=NULL((void*)0), *gpostags=NULL((void*)0);
2636 FT_UShort gsub_count=0, gpos_count=0;
2637 FT_ULong maxsize;
2638 FcChar8 *complex_ = NULL((void*)0);
2639 int indx1 = 0, indx2 = 0;
2640
2641 err = FT_Load_Sfnt_Table(face, TTAG_SILF(FT_Tag) ( ( (FT_ULong)'S' << 24 ) | ( (FT_ULong)'i' <<
16 ) | ( (FT_ULong)'l' << 8 ) | (FT_ULong)'f' )
, 0, 0, &len);
2642 issilgraphitefont = ( err == FT_Err_Ok);
2643
2644 gpos_count = GetScriptTags(face, TTAG_GPOS(FT_Tag) ( ( (FT_ULong)'G' << 24 ) | ( (FT_ULong)'P' <<
16 ) | ( (FT_ULong)'O' << 8 ) | (FT_ULong)'S' )
, &gpostags);
2645 gsub_count = GetScriptTags(face, TTAG_GSUB(FT_Tag) ( ( (FT_ULong)'G' << 24 ) | ( (FT_ULong)'S' <<
16 ) | ( (FT_ULong)'U' << 8 ) | (FT_ULong)'B' )
, &gsubtags);
2646
2647 if (!issilgraphitefont && !gsub_count && !gpos_count)
2648 goto bail;
2649
2650 maxsize = (((FT_ULong) gpos_count + (FT_ULong) gsub_count) * OTLAYOUT_LEN(1 + 9 + 4) +
2651 (issilgraphitefont ? 13 : 0));
2652 complex_ = malloc (sizeof (FcChar8) * maxsize);
2653 if (!complex_)
2654 goto bail;
2655
2656 complex_[0] = '\0';
2657 if (issilgraphitefont)
2658 strcpy((char *) complex_, "ttable:Silf ")__builtin___strcpy_chk ((char *) complex_, "ttable:Silf ", __builtin_object_size
((char *) complex_, 2 > 1 ? 1 : 0))
;
2659
2660 while ((indx1 < gsub_count) || (indx2 < gpos_count)) {
2661 if (indx1 == gsub_count) {
2662 addtag(complex_, gpostags[indx2]);
2663 indx2++;
2664 } else if ((indx2 == gpos_count) || (gsubtags[indx1] < gpostags[indx2])) {
2665 addtag(complex_, gsubtags[indx1]);
2666 indx1++;
2667 } else if (gsubtags[indx1] == gpostags[indx2]) {
2668 addtag(complex_, gsubtags[indx1]);
2669 indx1++;
2670 indx2++;
2671 } else {
2672 addtag(complex_, gpostags[indx2]);
2673 indx2++;
2674 }
2675 }
2676 if (FcDebug ()(FcDebugVal) & FC_DBG_SCANV256)
2677 printf("complex_ features in this font: %s\n", complex_);
2678bail:
2679 free(gsubtags);
2680 free(gpostags);
2681 return complex_;
2682}
2683
2684#define __fcfreetype__
2685#include "fcaliastail.h"
2686#include "fcftaliastail.h"
2687#undef __fcfreetype__