OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkFontMgr.h" | 8 #include "SkFontMgr.h" |
9 #include "SkFontStyle.h" | 9 #include "SkFontStyle.h" |
10 #include "SkFontConfigInterface.h" | 10 #include "SkFontConfigInterface.h" |
11 #include "SkFontConfigTypeface.h" | 11 #include "SkFontConfigTypeface.h" |
12 #include "SkMath.h" | 12 #include "SkMath.h" |
13 #include "SkString.h" | 13 #include "SkString.h" |
14 #include "SkTDArray.h" | 14 #include "SkTDArray.h" |
15 #include "SkThread.h" | |
16 | |
17 namespace { | |
18 | |
19 // See skia:1497 for background. | |
20 | |
21 #if FC_VERSION < 21091 | |
bungeman-skia
2014/03/31 17:25:51
I'm not sure that it makes sense to use the versio
mtklein
2014/03/31 17:37:36
Duh, fixed.
| |
22 | |
23 // Fontconfig is not threadsafe. We sadly need to manually synchronize all Fc.. .() calls. | |
24 SK_DECLARE_STATIC_MUTEX(gFCMutex); | |
25 static bool gFCSafeToUse; | |
26 | |
27 struct FCLocker { | |
28 FCLocker() { gFCMutex.acquire(); gFCSafeToUse = true; } | |
29 ~FCLocker() { gFCSafeToUse = false; gFCMutex.release(); } | |
30 }; | |
31 | |
32 #else | |
33 | |
34 // Fontconfig is threadsafe. Noops for locking. | |
35 static const bool gFCSafeToUse = true; | |
36 struct FCLocker { | |
37 FCLocker() {} // Stifles unused variable warnings. | |
38 }; | |
39 | |
40 #endif | |
41 | |
42 } // namespace | |
15 | 43 |
16 // for now we pull these in directly. eventually we will solely rely on the | 44 // for now we pull these in directly. eventually we will solely rely on the |
17 // SkFontConfigInterface instance. | 45 // SkFontConfigInterface instance. |
18 #include <fontconfig/fontconfig.h> | 46 #include <fontconfig/fontconfig.h> |
19 #include <unistd.h> | 47 #include <unistd.h> |
20 | 48 |
21 // Defined in SkFontHost_FreeType.cpp | 49 // Defined in SkFontHost_FreeType.cpp |
22 bool find_name_and_attributes(SkStream* stream, SkString* name, | 50 bool find_name_and_attributes(SkStream* stream, SkString* name, |
23 SkTypeface::Style* style, bool* isFixedWidth); | 51 SkTypeface::Style* style, bool* isFixedWidth); |
24 | 52 |
25 // borrow this global from SkFontHost_fontconfig. eventually that file should | 53 // borrow this global from SkFontHost_fontconfig. eventually that file should |
26 // go away, and be replaced with this one. | 54 // go away, and be replaced with this one. |
27 extern SkFontConfigInterface* SkFontHost_fontconfig_ref_global(); | 55 extern SkFontConfigInterface* SkFontHost_fontconfig_ref_global(); |
28 static SkFontConfigInterface* RefFCI() { | 56 static SkFontConfigInterface* RefFCI() { |
29 return SkFontHost_fontconfig_ref_global(); | 57 return SkFontHost_fontconfig_ref_global(); |
30 } | 58 } |
31 | 59 |
32 // look for the last substring after a '/' and return that, or return null. | 60 // look for the last substring after a '/' and return that, or return null. |
33 static const char* find_just_name(const char* str) { | 61 static const char* find_just_name(const char* str) { |
34 const char* last = strrchr(str, '/'); | 62 const char* last = strrchr(str, '/'); |
35 return last ? last + 1 : NULL; | 63 return last ? last + 1 : NULL; |
36 } | 64 } |
37 | 65 |
38 static bool is_lower(char c) { | 66 static bool is_lower(char c) { |
39 return c >= 'a' && c <= 'z'; | 67 return c >= 'a' && c <= 'z'; |
40 } | 68 } |
41 | 69 |
42 static int get_int(FcPattern* pattern, const char field[]) { | 70 static int get_int(FcPattern* pattern, const char field[]) { |
71 SkASSERT(gFCSafeToUse); | |
43 int value; | 72 int value; |
44 if (FcPatternGetInteger(pattern, field, 0, &value) != FcResultMatch) { | 73 if (FcPatternGetInteger(pattern, field, 0, &value) != FcResultMatch) { |
45 value = SK_MinS32; | 74 value = SK_MinS32; |
46 } | 75 } |
47 return value; | 76 return value; |
48 } | 77 } |
49 | 78 |
50 static const char* get_name(FcPattern* pattern, const char field[]) { | 79 static const char* get_name(FcPattern* pattern, const char field[]) { |
80 SkASSERT(gFCSafeToUse); | |
51 const char* name; | 81 const char* name; |
52 if (FcPatternGetString(pattern, field, 0, (FcChar8**)&name) != FcResultMatch ) { | 82 if (FcPatternGetString(pattern, field, 0, (FcChar8**)&name) != FcResultMatch ) { |
53 name = ""; | 83 name = ""; |
54 } | 84 } |
55 return name; | 85 return name; |
56 } | 86 } |
57 | 87 |
58 static bool valid_pattern(FcPattern* pattern) { | 88 static bool valid_pattern(FcPattern* pattern) { |
89 SkASSERT(gFCSafeToUse); | |
59 FcBool is_scalable; | 90 FcBool is_scalable; |
60 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch || !is_scalable) { | 91 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch || !is_scalable) { |
61 return false; | 92 return false; |
62 } | 93 } |
63 | 94 |
64 // fontconfig can also return fonts which are unreadable | 95 // fontconfig can also return fonts which are unreadable |
65 const char* c_filename = get_name(pattern, FC_FILE); | 96 const char* c_filename = get_name(pattern, FC_FILE); |
66 if (0 == *c_filename) { | 97 if (0 == *c_filename) { |
67 return false; | 98 return false; |
68 } | 99 } |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
201 | 232 |
202 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERR IDE { | 233 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERR IDE { |
203 familyName->set(fFamilyNames->atStr(index)); | 234 familyName->set(fFamilyNames->atStr(index)); |
204 } | 235 } |
205 | 236 |
206 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE { | 237 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE { |
207 return this->onMatchFamily(fFamilyNames->atStr(index)); | 238 return this->onMatchFamily(fFamilyNames->atStr(index)); |
208 } | 239 } |
209 | 240 |
210 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER RIDE { | 241 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER RIDE { |
242 FCLocker lock; | |
243 | |
211 FcPattern* pattern = FcPatternCreate(); | 244 FcPattern* pattern = FcPatternCreate(); |
212 | 245 |
213 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); | 246 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); |
214 #if 0 | 247 #if 0 |
215 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); | 248 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
216 #endif | 249 #endif |
217 FcConfigSubstitute(NULL, pattern, FcMatchPattern); | 250 FcConfigSubstitute(NULL, pattern, FcMatchPattern); |
218 FcDefaultSubstitute(pattern); | 251 FcDefaultSubstitute(pattern); |
219 | 252 |
220 const char* post_config_family = get_name(pattern, FC_FAMILY); | 253 const char* post_config_family = get_name(pattern, FC_FAMILY); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
277 return face; | 310 return face; |
278 } | 311 } |
279 | 312 |
280 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE { | 313 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE { |
281 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); | 314 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); |
282 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; | 315 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; |
283 } | 316 } |
284 | 317 |
285 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], | 318 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], |
286 unsigned styleBits) const SK_OVER RIDE { | 319 unsigned styleBits) const SK_OVER RIDE { |
320 FCLocker lock; | |
287 return FontConfigTypeface::LegacyCreateTypeface(NULL, familyName, | 321 return FontConfigTypeface::LegacyCreateTypeface(NULL, familyName, |
288 (SkTypeface::Style)styleBits); | 322 (SkTypeface::Style)styleBits); |
289 } | 323 } |
290 }; | 324 }; |
291 | 325 |
292 SkFontMgr* SkFontMgr::Factory() { | 326 SkFontMgr* SkFontMgr::Factory() { |
293 SkFontConfigInterface* fci = RefFCI(); | 327 SkFontConfigInterface* fci = RefFCI(); |
294 return fci ? SkNEW_ARGS(SkFontMgr_fontconfig, (fci)) : NULL; | 328 return fci ? SkNEW_ARGS(SkFontMgr_fontconfig, (fci)) : NULL; |
295 } | 329 } |
OLD | NEW |