Index: src/fonts/SkFontMgr_fontconfig.cpp |
diff --git a/src/fonts/SkFontMgr_fontconfig.cpp b/src/fonts/SkFontMgr_fontconfig.cpp |
index bd4c8ddc1db2a275b51c4d0b586efadcbf183b0d..1d17111b79213820b68a046302383f47931a4c54 100644 |
--- a/src/fonts/SkFontMgr_fontconfig.cpp |
+++ b/src/fonts/SkFontMgr_fontconfig.cpp |
@@ -12,12 +12,45 @@ |
#include "SkMath.h" |
#include "SkString.h" |
#include "SkTDArray.h" |
+#include "SkThread.h" |
// for now we pull these in directly. eventually we will solely rely on the |
// SkFontConfigInterface instance. |
#include <fontconfig/fontconfig.h> |
#include <unistd.h> |
+namespace { |
+ |
+// Fontconfig is not threadsafe before 2.10.91. Before that, we lock with a global mutex. |
+// See skia:1497 for background. |
+SK_DECLARE_STATIC_MUTEX(gFCMutex); |
+static bool gFCSafeToUse; |
+ |
+struct FCLocker { |
+ FCLocker() { |
+ if (FcGetVersion() < 21091) { // We assume FcGetVersion() has always been thread safe. |
+ gFCMutex.acquire(); |
+ fUnlock = true; |
+ } else { |
+ fUnlock = false; |
+ } |
+ gFCSafeToUse = true; |
+ } |
+ |
+ ~FCLocker() { |
+ gFCSafeToUse = false; |
+ if (fUnlock) { |
+ gFCMutex.release(); |
+ } |
+ } |
+ |
+private: |
+ bool fUnlock; |
+}; |
+ |
+} // namespace |
+ |
+ |
// Defined in SkFontHost_FreeType.cpp |
bool find_name_and_attributes(SkStream* stream, SkString* name, |
SkTypeface::Style* style, bool* isFixedWidth); |
@@ -40,6 +73,7 @@ static bool is_lower(char c) { |
} |
static int get_int(FcPattern* pattern, const char field[]) { |
+ SkASSERT(gFCSafeToUse); |
int value; |
if (FcPatternGetInteger(pattern, field, 0, &value) != FcResultMatch) { |
value = SK_MinS32; |
@@ -48,6 +82,7 @@ static int get_int(FcPattern* pattern, const char field[]) { |
} |
static const char* get_name(FcPattern* pattern, const char field[]) { |
+ SkASSERT(gFCSafeToUse); |
const char* name; |
if (FcPatternGetString(pattern, field, 0, (FcChar8**)&name) != FcResultMatch) { |
name = ""; |
@@ -56,6 +91,7 @@ static const char* get_name(FcPattern* pattern, const char field[]) { |
} |
static bool valid_pattern(FcPattern* pattern) { |
+ SkASSERT(gFCSafeToUse); |
FcBool is_scalable; |
if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch || !is_scalable) { |
return false; |
@@ -208,6 +244,8 @@ protected: |
} |
virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE { |
+ FCLocker lock; |
+ |
FcPattern* pattern = FcPatternCreate(); |
FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); |
@@ -284,6 +322,7 @@ protected: |
virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], |
unsigned styleBits) const SK_OVERRIDE { |
+ FCLocker lock; |
return FontConfigTypeface::LegacyCreateTypeface(NULL, familyName, |
(SkTypeface::Style)styleBits); |
} |