Index: src/ports/SkScalerContext_win_dw.cpp |
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp |
index e259479fcb7d320487eb36d70a5559203b705098..eec65663e7adba93aecb21b57ce307670396a7a3 100644 |
--- a/src/ports/SkScalerContext_win_dw.cpp |
+++ b/src/ports/SkScalerContext_win_dw.cpp |
@@ -15,6 +15,7 @@ |
#include "SkHRESULT.h" |
#include "SkMaskGamma.h" |
#include "SkMatrix22.h" |
+#include "SkMutex.h" |
#include "SkOTTable_EBLC.h" |
#include "SkOTTable_EBSC.h" |
#include "SkOTTable_gasp.h" |
@@ -30,11 +31,30 @@ |
# include <dwrite_1.h> |
#endif |
+/* Note: |
+ * In versions 8 and 8.1 of Windows, some calls in DWrite are not thread safe. |
+ * The DWriteFactoryMutex protects the calls that are problematic. |
+ */ |
+SK_DECLARE_STATIC_MUTEX(DWriteFactoryMutex); |
+ |
+class Exclusive { |
+public: |
+ Exclusive(SkBaseMutex& mutex) : fMutex(mutex) { |
+ fMutex.acquire(); |
+ } |
+ ~Exclusive() { |
+ fMutex.release(); |
+ } |
+private: |
+ SkBaseMutex& fMutex; |
+}; |
+ |
static bool isLCD(const SkScalerContext::Rec& rec) { |
return SkMask::kLCD16_Format == rec.fMaskFormat; |
} |
static bool is_hinted_without_gasp(DWriteFontTypeface* typeface) { |
+ Exclusive l(DWriteFactoryMutex); |
AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get()); |
if (!maxp.fExists) { |
return false; |
@@ -104,6 +124,7 @@ static void expand_range_if_gridfit_only(DWriteFontTypeface* typeface, int size, |
} |
static bool has_bitmap_strike(DWriteFontTypeface* typeface, PPEMRange range) { |
+ Exclusive l(DWriteFactoryMutex); |
{ |
AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get()); |
if (!eblc.fExists) { |
@@ -337,6 +358,7 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) { |
if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || |
DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) |
{ |
+ Exclusive l(DWriteFactoryMutex); |
HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics( |
fTextSizeMeasure, |
1.0f, // pixelsPerDip |
@@ -346,12 +368,16 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) { |
&gm), |
"Could not get gdi compatible glyph metrics."); |
} else { |
+ Exclusive l(DWriteFactoryMutex); |
HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm), |
"Could not get design metrics."); |
} |
DWRITE_FONT_METRICS dwfm; |
- fTypeface->fDWriteFontFace->GetMetrics(&dwfm); |
+ { |
+ Exclusive l(DWriteFactoryMutex); |
+ fTypeface->fDWriteFontFace->GetMetrics(&dwfm); |
+ } |
SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure, |
SkIntToScalar(gm.advanceWidth), |
SkIntToScalar(dwfm.designUnitsPerEm)); |
@@ -398,9 +424,10 @@ HRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph, |
run.glyphIndices = &glyphId; |
run.isSideways = FALSE; |
run.glyphOffsets = &offset; |
- |
- SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; |
- HRM(fTypeface->fFactory->CreateGlyphRunAnalysis( |
+ { |
+ Exclusive l(DWriteFactoryMutex); |
+ SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; |
+ HRM(fTypeface->fFactory->CreateGlyphRunAnalysis( |
&run, |
1.0f, // pixelsPerDip, |
&fXform, |
@@ -409,11 +436,11 @@ HRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph, |
0.0f, // baselineOriginX, |
0.0f, // baselineOriginY, |
&glyphRunAnalysis), |
- "Could not create glyph run analysis."); |
- |
- HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox), |
- "Could not get texture bounds."); |
+ "Could not create glyph run analysis."); |
+ HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox), |
+ "Could not get texture bounds."); |
+ } |
return S_OK; |
} |
@@ -651,30 +678,32 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph, |
run.glyphIndices = &index; |
run.isSideways = FALSE; |
run.glyphOffsets = &offset; |
- |
- SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; |
- HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run, |
- 1.0f, // pixelsPerDip, |
- &fXform, |
- renderingMode, |
- fMeasuringMode, |
- 0.0f, // baselineOriginX, |
- 0.0f, // baselineOriginY, |
- &glyphRunAnalysis), |
- "Could not create glyph run analysis."); |
- |
- //NOTE: this assumes that the glyph has already been measured |
- //with an exact same glyph run analysis. |
- RECT bbox; |
- bbox.left = glyph.fLeft; |
- bbox.top = glyph.fTop; |
- bbox.right = glyph.fLeft + glyph.fWidth; |
- bbox.bottom = glyph.fTop + glyph.fHeight; |
- HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType, |
- &bbox, |
- fBits.begin(), |
- sizeNeeded), |
- "Could not draw mask."); |
+ { |
+ Exclusive l(DWriteFactoryMutex); |
+ SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; |
+ HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run, |
+ 1.0f, // pixelsPerDip, |
+ &fXform, |
+ renderingMode, |
+ fMeasuringMode, |
+ 0.0f, // baselineOriginX, |
+ 0.0f, // baselineOriginY, |
+ &glyphRunAnalysis), |
+ "Could not create glyph run analysis."); |
+ |
+ //NOTE: this assumes that the glyph has already been measured |
+ //with an exact same glyph run analysis. |
+ RECT bbox; |
+ bbox.left = glyph.fLeft; |
+ bbox.top = glyph.fTop; |
+ bbox.right = glyph.fLeft + glyph.fWidth; |
+ bbox.bottom = glyph.fTop + glyph.fHeight; |
+ HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType, |
+ &bbox, |
+ fBits.begin(), |
+ sizeNeeded), |
+ "Could not draw mask."); |
+ } |
return fBits.begin(); |
} |
@@ -730,17 +759,20 @@ void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) { |
HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath), |
"Could not create geometry to path converter."); |
uint16_t glyphId = glyph.getGlyphID(); |
- //TODO: convert to<->from DIUs? This would make a difference if hinting. |
- //It may not be needed, it appears that DirectWrite only hints at em size. |
- HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSizeRender), |
- &glyphId, |
- nullptr, //advances |
- nullptr, //offsets |
- 1, //num glyphs |
- FALSE, //sideways |
- FALSE, //rtl |
- geometryToPath.get()), |
- "Could not create glyph outline."); |
+ { |
+ Exclusive l(DWriteFactoryMutex); |
+ //TODO: convert to<->from DIUs? This would make a difference if hinting. |
+ //It may not be needed, it appears that DirectWrite only hints at em size. |
+ HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSizeRender), |
+ &glyphId, |
+ nullptr, //advances |
+ nullptr, //offsets |
+ 1, //num glyphs |
+ FALSE, //sideways |
+ FALSE, //rtl |
+ geometryToPath.get()), |
+ "Could not create glyph outline."); |
+ } |
path->transform(fSkXform); |
} |