Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /*
2 * Copyright 2009 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
8 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */
10 #include <string>
11 #include <unistd.h>
12 #include <fcntl.h>
14 #include <fontconfig/fontconfig.h>
16 #include "SkBuffer.h"
17 #include "SkFontConfigInterface.h"
18 #include "SkStream.h"
20 size_t SkFontConfigInterface::FontIdentity::writeToMemory(void* addr) const {
21 size_t size = sizeof(fID) + sizeof(fTTCIndex);
22 size += sizeof(int32_t) + sizeof(int32_t) + sizeof(uint8_t); // weight, width, italic
23 size += sizeof(int32_t) + fString.size(); // store length+data
24 if (addr) {
25 SkWBuffer buffer(addr, size);
27 buffer.write32(fID);
28 buffer.write32(fTTCIndex);
29 buffer.write32(fString.size());
30 buffer.write32(fStyle.weight());
31 buffer.write32(fStyle.width());
32 buffer.write8(fStyle.slant());
33 buffer.write(fString.c_str(), fString.size());
34 buffer.padToAlign4();
36 SkASSERT(buffer.pos() == size);
37 }
38 return size;
39 }
41 size_t SkFontConfigInterface::FontIdentity::readFromMemory(const void* addr,
42 size_t size) {
43 SkRBuffer buffer(addr, size);
45 (void)buffer.readU32(&fID);
46 (void)buffer.readS32(&fTTCIndex);
47 uint32_t strLen, weight, width;
48 (void)buffer.readU32(&strLen);
49 (void)buffer.readU32(&weight);
50 (void)buffer.readU32(&width);
51 uint8_t u8;
52 (void)buffer.readU8(&u8);
53 SkFontStyle::Slant slant = (SkFontStyle::Slant)u8;
54 fStyle = SkFontStyle(weight, width, slant);
55 fString.resize(strLen);
56 (void)buffer.read(fString.writable_str(), strLen);
57 buffer.skipToAlign4();
59 return buffer.pos(); // the actual number of bytes read
60 }
62 #ifdef SK_DEBUG
63 static void make_iden(SkFontConfigInterface::FontIdentity* iden) {
64 iden->fID = 10;
65 iden->fTTCIndex = 2;
66 iden->fString.set("Hello world");
67 iden->fStyle = SkFontStyle(300, 6, SkFontStyle::kItalic_Slant);
68 }
70 static void test_writeToMemory(const SkFontConfigInterface::FontIdentity& iden0,
71 int initValue) {
72 SkFontConfigInterface::FontIdentity iden1;
74 size_t size0 = iden0.writeToMemory(NULL);
76 SkAutoMalloc storage(size0);
77 memset(storage.get(), initValue, size0);
79 size_t size1 = iden0.writeToMemory(storage.get());
80 SkASSERT(size0 == size1);
82 SkASSERT(iden0 != iden1);
83 size_t size2 = iden1.readFromMemory(storage.get(), size1);
84 SkASSERT(size2 == size1);
85 SkASSERT(iden0 == iden1);
86 }
88 static void fontconfiginterface_unittest() {
89 SkFontConfigInterface::FontIdentity iden0, iden1;
91 SkASSERT(iden0 == iden1);
93 make_iden(&iden0);
94 SkASSERT(iden0 != iden1);
96 make_iden(&iden1);
97 SkASSERT(iden0 == iden1);
99 test_writeToMemory(iden0, 0);
100 test_writeToMemory(iden0, 0);
101 }
102 #endif
104 class SkFontConfigInterfaceDirect : public SkFontConfigInterface {
105 public:
106 SkFontConfigInterfaceDirect();
107 virtual ~SkFontConfigInterfaceDirect();
109 virtual bool matchFamilyName(const char familyName[],
110 SkTypeface::Style requested,
111 FontIdentity* outFontIdentifier,
112 SkString* outFamilyName,
113 SkTypeface::Style* outStyle) SK_OVERRIDE;
114 virtual SkStream* openStream(const FontIdentity&) SK_OVERRIDE;
116 // new APIs
117 virtual SkDataTable* getFamilyNames() SK_OVERRIDE;
118 virtual bool matchFamilySet(const char inFamilyName[],
119 SkString* outFamilyName,
120 SkTArray<FontIdentity>*) SK_OVERRIDE;
122 private:
123 SkMutex mutex_;
124 };
126 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface() {
127 static SkFontConfigInterface* gDirect;
128 if (NULL == gDirect) {
129 static SkMutex gMutex;
130 SkAutoMutexAcquire ac(gMutex);
132 if (NULL == gDirect) {
133 gDirect = new SkFontConfigInterfaceDirect;
134 }
135 }
136 return gDirect;
137 }
139 ///////////////////////////////////////////////////////////////////////////////
141 // Returns the string from the pattern, or NULL
142 static const char* get_name(FcPattern* pattern, const char field[],
143 int index = 0) {
144 const char* name;
145 if (FcPatternGetString(pattern, field, index,
146 (FcChar8**)&name) != FcResultMatch) {
147 name = NULL;
148 }
149 return name;
150 }
152 ///////////////////////////////////////////////////////////////////////////////
154 namespace {
156 // Equivalence classes, used to match the Liberation and other fonts
157 // with their metric-compatible replacements. See the discussion in
158 // GetFontEquivClass().
159 enum FontEquivClass
160 {
161 OTHER,
162 SANS,
163 SERIF,
164 MONO,
165 SYMBOL,
166 PGOTHIC,
167 GOTHIC,
168 PMINCHO,
169 MINCHO,
170 SIMSUN,
171 NSIMSUN,
172 SIMHEI,
173 PMINGLIU,
174 MINGLIU,
175 PMINGLIUHK,
176 MINGLIUHK,
177 CAMBRIA,
178 CALIBRI,
179 };
181 // Match the font name against a whilelist of fonts, returning the equivalence
182 // class.
183 FontEquivClass GetFontEquivClass(const char* fontname)
184 {
185 // It would be nice for fontconfig to tell us whether a given suggested
186 // replacement is a "strong" match (that is, an equivalent font) or
187 // a "weak" match (that is, fontconfig's next-best attempt at finding a
188 // substitute). However, I played around with the fontconfig API for
189 // a good few hours and could not make it reveal this information.
190 //
191 // So instead, we hardcode. Initially this function emulated
192 // /etc/fonts/conf.d/30-metric-aliases.conf
193 // from my Ubuntu system, but we're better off being very conservative.
195 // Arimo, Tinos and Cousine are a set of fonts metric-compatible with
196 // Arial, Times New Roman and Courier New with a character repertoire
197 // much larger than Liberation. Note that Cousine is metrically
198 // compatible with Courier New, but the former is sans-serif while
199 // the latter is serif.
202 struct FontEquivMap {
203 FontEquivClass clazz;
204 const char name[40];
205 };
207 static const FontEquivMap kFontEquivMap[] = {
208 { SANS, "Arial" },
209 { SANS, "Arimo" },
210 { SANS, "Liberation Sans" },
212 { SERIF, "Times New Roman" },
213 { SERIF, "Tinos" },
214 { SERIF, "Liberation Serif" },
216 { MONO, "Courier New" },
217 { MONO, "Cousine" },
218 { MONO, "Liberation Mono" },
220 { SYMBOL, "Symbol" },
221 { SYMBOL, "Symbol Neu" },
223 // MS Pゴシック
224 { PGOTHIC, "MS PGothic" },
225 { PGOTHIC, "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0"
226 "\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" },
227 { PGOTHIC, "IPAPGothic" },
228 { PGOTHIC, "MotoyaG04Gothic" },
230 // MS ゴシック
231 { GOTHIC, "MS Gothic" },
232 { GOTHIC, "\xef\xbc\xad\xef\xbc\xb3 "
233 "\xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf" },
234 { GOTHIC, "IPAGothic" },
235 { GOTHIC, "MotoyaG04GothicMono" },
237 // MS P明朝
238 { PMINCHO, "MS PMincho" },
239 { PMINCHO, "\xef\xbc\xad\xef\xbc\xb3 \xef\xbc\xb0"
240 "\xe6\x98\x8e\xe6\x9c\x9d"},
241 { PMINCHO, "IPAPMincho" },
242 { PMINCHO, "MotoyaG04Mincho" },
244 // MS 明朝
245 { MINCHO, "MS Mincho" },
246 { MINCHO, "\xef\xbc\xad\xef\xbc\xb3 \xe6\x98\x8e\xe6\x9c\x9d" },
247 { MINCHO, "IPAMincho" },
248 { MINCHO, "MotoyaG04MinchoMono" },
250 // 宋体
251 { SIMSUN, "Simsun" },
252 { SIMSUN, "\xe5\xae\x8b\xe4\xbd\x93" },
253 { SIMSUN, "MSung GB18030" },
254 { SIMSUN, "Song ASC" },
256 // 新宋体
257 { NSIMSUN, "NSimsun" },
258 { NSIMSUN, "\xe6\x96\xb0\xe5\xae\x8b\xe4\xbd\x93" },
259 { NSIMSUN, "MSung GB18030" },
260 { NSIMSUN, "N Song ASC" },
262 // 黑体
263 { SIMHEI, "Simhei" },
264 { SIMHEI, "\xe9\xbb\x91\xe4\xbd\x93" },
265 { SIMHEI, "MYingHeiGB18030" },
266 { SIMHEI, "MYingHeiB5HK" },
268 // 新細明體
269 { PMINGLIU, "PMingLiU"},
270 { PMINGLIU, "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" },
271 { PMINGLIU, "MSung B5HK"},
273 // 細明體
274 { MINGLIU, "MingLiU"},
275 { MINGLIU, "\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94" },
276 { MINGLIU, "MSung B5HK"},
278 // 新細明體
279 { PMINGLIUHK, "PMingLiU_HKSCS"},
280 { PMINGLIUHK, "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94_HKSCS" },
281 { PMINGLIUHK, "MSung B5HK"},
283 // 細明體
284 { MINGLIUHK, "MingLiU_HKSCS"},
285 { MINGLIUHK, "\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94_HKSCS" },
286 { MINGLIUHK, "MSung B5HK"},
288 // Cambria
289 { CAMBRIA, "Cambria" },
290 { CAMBRIA, "Caladea" },
292 // Calibri
293 { CALIBRI, "Calibri" },
294 { CALIBRI, "Carlito" },
295 };
297 static const size_t kFontCount =
298 sizeof(kFontEquivMap)/sizeof(kFontEquivMap[0]);
300 // TODO(jungshik): If this loop turns out to be hot, turn
301 // the array to a static (hash)map to speed it up.
302 for (size_t i = 0; i < kFontCount; ++i) {
303 if (strcasecmp(kFontEquivMap[i].name, fontname) == 0)
304 return kFontEquivMap[i].clazz;
305 }
306 return OTHER;
307 }
310 // Return true if |font_a| and |font_b| are visually and at the metrics
311 // level interchangeable.
312 bool IsMetricCompatibleReplacement(const char* font_a, const char* font_b)
313 {
314 FontEquivClass class_a = GetFontEquivClass(font_a);
315 FontEquivClass class_b = GetFontEquivClass(font_b);
317 return class_a != OTHER && class_a == class_b;
318 }
320 // Normally we only return exactly the font asked for. In last-resort
321 // cases, the request either doesn't specify a font or is one of the
322 // basic font names like "Sans", "Serif" or "Monospace". This function
323 // tells you whether a given request is for such a fallback.
324 bool IsFallbackFontAllowed(const std::string& family) {
325 const char* family_cstr = family.c_str();
326 return family.empty() ||
327 strcasecmp(family_cstr, "sans") == 0 ||
328 strcasecmp(family_cstr, "serif") == 0 ||
329 strcasecmp(family_cstr, "monospace") == 0;
330 }
332 static bool valid_pattern(FcPattern* pattern) {
333 #ifdef SK_FONT_CONFIG_ONLY_ALLOW_SCALABLE_FONTS
334 FcBool is_scalable;
335 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch
336 || !is_scalable) {
337 return false;
338 }
339 #endif
341 // fontconfig can also return fonts which are unreadable
342 const char* c_filename = get_name(pattern, FC_FILE);
343 if (!c_filename) {
344 return false;
345 }
346 if (access(c_filename, R_OK) != 0) {
347 return false;
348 }
349 return true;
350 }
352 // Find matching font from |font_set| for the given font family.
353 FcPattern* MatchFont(FcFontSet* font_set,
354 const char* post_config_family,
355 const std::string& family) {
356 // Older versions of fontconfig have a bug where they cannot select
357 // only scalable fonts so we have to manually filter the results.
358 FcPattern* match = NULL;
359 for (int i = 0; i < font_set->nfont; ++i) {
360 FcPattern* current = font_set->fonts[i];
361 if (valid_pattern(current)) {
362 match = current;
363 break;
364 }
365 }
367 if (match && !IsFallbackFontAllowed(family)) {
368 bool acceptable_substitute = false;
369 for (int id = 0; id < 255; ++id) {
370 const char* post_match_family = get_name(match, FC_FAMILY, id);
371 if (!post_match_family)
372 break;
373 acceptable_substitute =
374 (strcasecmp(post_config_family, post_match_family) == 0 ||
375 // Workaround for Issue 12530:
376 // requested family: "Bitstream Vera Sans"
377 // post_config_family: "Arial"
378 // post_match_family: "Bitstream Vera Sans"
379 // -> We should treat this case as a good match.
380 strcasecmp(family.c_str(), post_match_family) == 0) ||
381 IsMetricCompatibleReplacement(family.c_str(), post_match_family);
382 if (acceptable_substitute)
383 break;
384 }
385 if (!acceptable_substitute)
386 return NULL;
387 }
389 return match;
390 }
392 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|.
393 SkTypeface::Style GetFontStyle(FcPattern* font) {
394 int resulting_bold;
395 if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold))
396 resulting_bold = FC_WEIGHT_NORMAL;
398 int resulting_italic;
399 if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic))
400 resulting_italic = FC_SLANT_ROMAN;
402 // If we ask for an italic font, fontconfig might take a roman font and set
403 // the undocumented property FC_MATRIX to a skew matrix. It'll then say
404 // that the font is italic or oblique. So, if we see a matrix, we don't
405 // believe that it's italic.
406 FcValue matrix;
407 const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0;
409 // If we ask for an italic font, fontconfig might take a roman font and set
410 // FC_EMBOLDEN.
411 FcValue embolden;
412 const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) == 0;
414 int styleBits = 0;
415 if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) {
416 styleBits |= SkTypeface::kBold;
417 }
418 if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) {
419 styleBits |= SkTypeface::kItalic;
420 }
422 return (SkTypeface::Style)styleBits;
423 }
425 } // anonymous namespace
427 ///////////////////////////////////////////////////////////////////////////////
429 #define kMaxFontFamilyLength 2048
431 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() {
432 SkAutoMutexAcquire ac(mutex_);
434 FcInit();
436 SkDEBUGCODE(fontconfiginterface_unittest();)
437 }
439 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() {
440 }
442 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[],
443 SkTypeface::Style style,
444 FontIdentity* outIdentity,
445 SkString* outFamilyName,
446 SkTypeface::Style* outStyle) {
447 std::string familyStr(familyName ? familyName : "");
448 if (familyStr.length() > kMaxFontFamilyLength) {
449 return false;
450 }
452 SkAutoMutexAcquire ac(mutex_);
454 FcPattern* pattern = FcPatternCreate();
456 if (familyName) {
457 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
458 }
459 FcPatternAddInteger(pattern, FC_WEIGHT,
460 (style & SkTypeface::kBold) ? FC_WEIGHT_BOLD
461 : FC_WEIGHT_NORMAL);
462 FcPatternAddInteger(pattern, FC_SLANT,
463 (style & SkTypeface::kItalic) ? FC_SLANT_ITALIC
464 : FC_SLANT_ROMAN);
465 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
467 FcConfigSubstitute(NULL, pattern, FcMatchPattern);
468 FcDefaultSubstitute(pattern);
470 // Font matching:
471 // CSS often specifies a fallback list of families:
472 // font-family: a, b, c, serif;
473 // However, fontconfig will always do its best to find *a* font when asked
474 // for something so we need a way to tell if the match which it has found is
475 // "good enough" for us. Otherwise, we can return NULL which gets piped up
476 // and lets WebKit know to try the next CSS family name. However, fontconfig
477 // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
478 // wish to support that.
479 //
480 // Thus, if a specific family is requested we set @family_requested. Then we
481 // record two strings: the family name after config processing and the
482 // family name after resolving. If the two are equal, it's a good match.
483 //
484 // So consider the case where a user has mapped Arial to Helvetica in their
485 // config.
486 // requested family: "Arial"
487 // post_config_family: "Helvetica"
488 // post_match_family: "Helvetica"
489 // -> good match
490 //
491 // and for a missing font:
492 // requested family: "Monaco"
493 // post_config_family: "Monaco"
494 // post_match_family: "Times New Roman"
495 // -> BAD match
496 //
497 // However, we special-case fallback fonts; see IsFallbackFontAllowed().
499 const char* post_config_family = get_name(pattern, FC_FAMILY);
500 if (!post_config_family) {
501 // we can just continue with an empty name, e.g. default font
502 post_config_family = "";
503 }
505 FcResult result;
506 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
507 if (!font_set) {
508 FcPatternDestroy(pattern);
509 return false;
510 }
512 FcPattern* match = MatchFont(font_set, post_config_family, familyStr);
513 if (!match) {
514 FcPatternDestroy(pattern);
515 FcFontSetDestroy(font_set);
516 return false;
517 }
519 FcPatternDestroy(pattern);
521 // From here out we just extract our results from 'match'
523 post_config_family = get_name(match, FC_FAMILY);
524 if (!post_config_family) {
525 FcFontSetDestroy(font_set);
526 return false;
527 }
529 const char* c_filename = get_name(match, FC_FILE);
530 if (!c_filename) {
531 FcFontSetDestroy(font_set);
532 return false;
533 }
535 int face_index;
536 if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
537 FcFontSetDestroy(font_set);
538 return false;
539 }
541 FcFontSetDestroy(font_set);
543 if (outIdentity) {
544 outIdentity->fTTCIndex = face_index;
545 outIdentity->fString.set(c_filename);
546 }
547 if (outFamilyName) {
548 outFamilyName->set(post_config_family);
549 }
550 if (outStyle) {
551 *outStyle = GetFontStyle(match);
552 }
553 return true;
554 }
556 SkStream* SkFontConfigInterfaceDirect::openStream(const FontIdentity& identity) {
557 return SkStream::NewFromFile(identity.fString.c_str());
558 }
560 ///////////////////////////////////////////////////////////////////////////////
562 static bool find_name(const SkTDArray<const char*>& list, const char* str) {
563 int count = list.count();
564 for (int i = 0; i < count; ++i) {
565 if (!strcmp(list[i], str)) {
566 return true;
567 }
568 }
569 return false;
570 }
572 SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() {
573 SkAutoMutexAcquire ac(mutex_);
575 FcPattern* pat = FcPatternCreate();
576 SkAutoTCallVProc<FcPattern, FcPatternDestroy> autoDestroyPat(pat);
577 if (NULL == pat) {
578 return NULL;
579 }
581 FcObjectSet* os = FcObjectSetBuild(FC_FAMILY, (char *)0);
582 SkAutoTCallVProc<FcObjectSet, FcObjectSetDestroy> autoDestroyOs(os);
583 if (NULL == os) {
584 return NULL;
585 }
587 FcFontSet* fs = FcFontList(NULL, pat, os);
588 SkAutoTCallVProc<FcFontSet, FcFontSetDestroy> autoDestroyFs(fs);
589 if (NULL == fs) {
590 return NULL;
591 }
593 SkTDArray<const char*> names;
594 SkTDArray<size_t> sizes;
595 for (int i = 0; i < fs->nfont; ++i) {
596 FcPattern* match = fs->fonts[i];
597 const char* famName = get_name(match, FC_FAMILY);
598 if (famName && !find_name(names, famName)) {
599 *names.append() = famName;
600 *sizes.append() = strlen(famName) + 1;
601 }
602 }
604 return SkDataTable::NewCopyArrays((const void*const*)names.begin(),
605 sizes.begin(), names.count());
606 }
608 bool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[],
609 SkString* outFamilyName,
610 SkTArray<FontIdentity>* ids) {
611 SkAutoMutexAcquire ac(mutex_);
613 #if 0
614 std::string familyStr(familyName ? familyName : "");
615 if (familyStr.length() > kMaxFontFamilyLength) {
616 return false;
617 }
619 SkAutoMutexAcquire ac(mutex_);
621 FcPattern* pattern = FcPatternCreate();
623 if (familyName) {
624 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
625 }
626 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
628 FcConfigSubstitute(NULL, pattern, FcMatchPattern);
629 FcDefaultSubstitute(pattern);
631 // Font matching:
632 // CSS often specifies a fallback list of families:
633 // font-family: a, b, c, serif;
634 // However, fontconfig will always do its best to find *a* font when asked
635 // for something so we need a way to tell if the match which it has found is
636 // "good enough" for us. Otherwise, we can return NULL which gets piped up
637 // and lets WebKit know to try the next CSS family name. However, fontconfig
638 // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
639 // wish to support that.
640 //
641 // Thus, if a specific family is requested we set @family_requested. Then we
642 // record two strings: the family name after config processing and the
643 // family name after resolving. If the two are equal, it's a good match.
644 //
645 // So consider the case where a user has mapped Arial to Helvetica in their
646 // config.
647 // requested family: "Arial"
648 // post_config_family: "Helvetica"
649 // post_match_family: "Helvetica"
650 // -> good match
651 //
652 // and for a missing font:
653 // requested family: "Monaco"
654 // post_config_family: "Monaco"
655 // post_match_family: "Times New Roman"
656 // -> BAD match
657 //
658 // However, we special-case fallback fonts; see IsFallbackFontAllowed().
660 const char* post_config_family = get_name(pattern, FC_FAMILY);
662 FcResult result;
663 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
664 if (!font_set) {
665 FcPatternDestroy(pattern);
666 return false;
667 }
669 FcPattern* match = MatchFont(font_set, post_config_family, familyStr);
670 if (!match) {
671 FcPatternDestroy(pattern);
672 FcFontSetDestroy(font_set);
673 return false;
674 }
676 FcPatternDestroy(pattern);
678 // From here out we just extract our results from 'match'
680 if (FcPatternGetString(match, FC_FAMILY, 0, &post_config_family) != FcResultMatch) {
681 FcFontSetDestroy(font_set);
682 return false;
683 }
685 FcChar8* c_filename;
686 if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) {
687 FcFontSetDestroy(font_set);
688 return false;
689 }
691 int face_index;
692 if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
693 FcFontSetDestroy(font_set);
694 return false;
695 }
697 FcFontSetDestroy(font_set);
699 if (outIdentity) {
700 outIdentity->fTTCIndex = face_index;
701 outIdentity->fString.set((const char*)c_filename);
702 }
703 if (outFamilyName) {
704 outFamilyName->set((const char*)post_config_family);
705 }
706 if (outStyle) {
707 *outStyle = GetFontStyle(match);
708 }
709 return true;
711 ////////////////////
713 int count;
714 FcPattern** match = MatchFont(font_set, post_config_family, &count);
715 if (!match) {
716 FcPatternDestroy(pattern);
717 FcFontSetDestroy(font_set);
718 return NULL;
719 }
721 FcPatternDestroy(pattern);
723 SkTDArray<FcPattern*> trimmedMatches;
724 for (int i = 0; i < count; ++i) {
725 const char* justName = find_just_name(get_name(match[i], FC_FILE));
726 if (!is_lower(*justName)) {
727 *trimmedMatches.append() = match[i];
728 }
729 }
731 SkFontStyleSet_FC* sset = SkNEW_ARGS(SkFontStyleSet_FC,
732 (trimmedMatches.begin(),
733 trimmedMatches.count()));
734 #endif
735 return false;
736 }