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" |
15 | 16 |
16 // for now we pull these in directly. eventually we will solely rely on the | 17 // for now we pull these in directly. eventually we will solely rely on the |
17 // SkFontConfigInterface instance. | 18 // SkFontConfigInterface instance. |
18 #include <fontconfig/fontconfig.h> | 19 #include <fontconfig/fontconfig.h> |
19 #include <unistd.h> | 20 #include <unistd.h> |
20 | 21 |
| 22 namespace { |
| 23 |
| 24 // Fontconfig is not threadsafe before 2.10.91. Before that, we lock with a glo
bal mutex. |
| 25 // See skia:1497 for background. |
| 26 SK_DECLARE_STATIC_MUTEX(gFCMutex); |
| 27 static bool gFCSafeToUse; |
| 28 |
| 29 struct FCLocker { |
| 30 FCLocker() { |
| 31 if (FcGetVersion() < 21091) { // We assume FcGetVersion() has always be
en thread safe. |
| 32 gFCMutex.acquire(); |
| 33 fUnlock = true; |
| 34 } else { |
| 35 fUnlock = false; |
| 36 } |
| 37 gFCSafeToUse = true; |
| 38 } |
| 39 |
| 40 ~FCLocker() { |
| 41 gFCSafeToUse = false; |
| 42 if (fUnlock) { |
| 43 gFCMutex.release(); |
| 44 } |
| 45 } |
| 46 |
| 47 private: |
| 48 bool fUnlock; |
| 49 }; |
| 50 |
| 51 } // namespace |
| 52 |
| 53 |
21 // Defined in SkFontHost_FreeType.cpp | 54 // Defined in SkFontHost_FreeType.cpp |
22 bool find_name_and_attributes(SkStream* stream, SkString* name, | 55 bool find_name_and_attributes(SkStream* stream, SkString* name, |
23 SkTypeface::Style* style, bool* isFixedWidth); | 56 SkTypeface::Style* style, bool* isFixedWidth); |
24 | 57 |
25 // borrow this global from SkFontHost_fontconfig. eventually that file should | 58 // borrow this global from SkFontHost_fontconfig. eventually that file should |
26 // go away, and be replaced with this one. | 59 // go away, and be replaced with this one. |
27 extern SkFontConfigInterface* SkFontHost_fontconfig_ref_global(); | 60 extern SkFontConfigInterface* SkFontHost_fontconfig_ref_global(); |
28 static SkFontConfigInterface* RefFCI() { | 61 static SkFontConfigInterface* RefFCI() { |
29 return SkFontHost_fontconfig_ref_global(); | 62 return SkFontHost_fontconfig_ref_global(); |
30 } | 63 } |
31 | 64 |
32 // look for the last substring after a '/' and return that, or return null. | 65 // look for the last substring after a '/' and return that, or return null. |
33 static const char* find_just_name(const char* str) { | 66 static const char* find_just_name(const char* str) { |
34 const char* last = strrchr(str, '/'); | 67 const char* last = strrchr(str, '/'); |
35 return last ? last + 1 : NULL; | 68 return last ? last + 1 : NULL; |
36 } | 69 } |
37 | 70 |
38 static bool is_lower(char c) { | 71 static bool is_lower(char c) { |
39 return c >= 'a' && c <= 'z'; | 72 return c >= 'a' && c <= 'z'; |
40 } | 73 } |
41 | 74 |
42 static int get_int(FcPattern* pattern, const char field[]) { | 75 static int get_int(FcPattern* pattern, const char field[]) { |
| 76 SkASSERT(gFCSafeToUse); |
43 int value; | 77 int value; |
44 if (FcPatternGetInteger(pattern, field, 0, &value) != FcResultMatch) { | 78 if (FcPatternGetInteger(pattern, field, 0, &value) != FcResultMatch) { |
45 value = SK_MinS32; | 79 value = SK_MinS32; |
46 } | 80 } |
47 return value; | 81 return value; |
48 } | 82 } |
49 | 83 |
50 static const char* get_name(FcPattern* pattern, const char field[]) { | 84 static const char* get_name(FcPattern* pattern, const char field[]) { |
| 85 SkASSERT(gFCSafeToUse); |
51 const char* name; | 86 const char* name; |
52 if (FcPatternGetString(pattern, field, 0, (FcChar8**)&name) != FcResultMatch
) { | 87 if (FcPatternGetString(pattern, field, 0, (FcChar8**)&name) != FcResultMatch
) { |
53 name = ""; | 88 name = ""; |
54 } | 89 } |
55 return name; | 90 return name; |
56 } | 91 } |
57 | 92 |
58 static bool valid_pattern(FcPattern* pattern) { | 93 static bool valid_pattern(FcPattern* pattern) { |
| 94 SkASSERT(gFCSafeToUse); |
59 FcBool is_scalable; | 95 FcBool is_scalable; |
60 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch
|| !is_scalable) { | 96 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch
|| !is_scalable) { |
61 return false; | 97 return false; |
62 } | 98 } |
63 | 99 |
64 // fontconfig can also return fonts which are unreadable | 100 // fontconfig can also return fonts which are unreadable |
65 const char* c_filename = get_name(pattern, FC_FILE); | 101 const char* c_filename = get_name(pattern, FC_FILE); |
66 if (0 == *c_filename) { | 102 if (0 == *c_filename) { |
67 return false; | 103 return false; |
68 } | 104 } |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 | 237 |
202 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERR
IDE { | 238 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERR
IDE { |
203 familyName->set(fFamilyNames->atStr(index)); | 239 familyName->set(fFamilyNames->atStr(index)); |
204 } | 240 } |
205 | 241 |
206 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE { | 242 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE { |
207 return this->onMatchFamily(fFamilyNames->atStr(index)); | 243 return this->onMatchFamily(fFamilyNames->atStr(index)); |
208 } | 244 } |
209 | 245 |
210 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER
RIDE { | 246 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER
RIDE { |
| 247 FCLocker lock; |
| 248 |
211 FcPattern* pattern = FcPatternCreate(); | 249 FcPattern* pattern = FcPatternCreate(); |
212 | 250 |
213 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); | 251 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); |
214 #if 0 | 252 #if 0 |
215 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); | 253 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
216 #endif | 254 #endif |
217 FcConfigSubstitute(NULL, pattern, FcMatchPattern); | 255 FcConfigSubstitute(NULL, pattern, FcMatchPattern); |
218 FcDefaultSubstitute(pattern); | 256 FcDefaultSubstitute(pattern); |
219 | 257 |
220 const char* post_config_family = get_name(pattern, FC_FAMILY); | 258 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; | 315 return face; |
278 } | 316 } |
279 | 317 |
280 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const
SK_OVERRIDE { | 318 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const
SK_OVERRIDE { |
281 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); | 319 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); |
282 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; | 320 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; |
283 } | 321 } |
284 | 322 |
285 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], | 323 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], |
286 unsigned styleBits) const SK_OVER
RIDE { | 324 unsigned styleBits) const SK_OVER
RIDE { |
| 325 FCLocker lock; |
287 return FontConfigTypeface::LegacyCreateTypeface(NULL, familyName, | 326 return FontConfigTypeface::LegacyCreateTypeface(NULL, familyName, |
288 (SkTypeface::Style)styleBits); | 327 (SkTypeface::Style)styleBits); |
289 } | 328 } |
290 }; | 329 }; |
291 | 330 |
292 SkFontMgr* SkFontMgr::Factory() { | 331 SkFontMgr* SkFontMgr::Factory() { |
293 SkFontConfigInterface* fci = RefFCI(); | 332 SkFontConfigInterface* fci = RefFCI(); |
294 return fci ? SkNEW_ARGS(SkFontMgr_fontconfig, (fci)) : NULL; | 333 return fci ? SkNEW_ARGS(SkFontMgr_fontconfig, (fci)) : NULL; |
295 } | 334 } |
OLD | NEW |