| 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 |