Add a mutex to protect the DWrite calls.
BUG=skia:4479 Review URL: https://codereview.chromium.org/1421433004
This commit is contained in:
parent
fb02cdafda
commit
c7378af961
@ -15,6 +15,7 @@
|
|||||||
#include "SkHRESULT.h"
|
#include "SkHRESULT.h"
|
||||||
#include "SkMaskGamma.h"
|
#include "SkMaskGamma.h"
|
||||||
#include "SkMatrix22.h"
|
#include "SkMatrix22.h"
|
||||||
|
#include "SkMutex.h"
|
||||||
#include "SkOTTable_EBLC.h"
|
#include "SkOTTable_EBLC.h"
|
||||||
#include "SkOTTable_EBSC.h"
|
#include "SkOTTable_EBSC.h"
|
||||||
#include "SkOTTable_gasp.h"
|
#include "SkOTTable_gasp.h"
|
||||||
@ -30,11 +31,30 @@
|
|||||||
# include <dwrite_1.h>
|
# include <dwrite_1.h>
|
||||||
#endif
|
#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) {
|
static bool isLCD(const SkScalerContext::Rec& rec) {
|
||||||
return SkMask::kLCD16_Format == rec.fMaskFormat;
|
return SkMask::kLCD16_Format == rec.fMaskFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_hinted_without_gasp(DWriteFontTypeface* typeface) {
|
static bool is_hinted_without_gasp(DWriteFontTypeface* typeface) {
|
||||||
|
Exclusive l(DWriteFactoryMutex);
|
||||||
AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get());
|
AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get());
|
||||||
if (!maxp.fExists) {
|
if (!maxp.fExists) {
|
||||||
return false;
|
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) {
|
static bool has_bitmap_strike(DWriteFontTypeface* typeface, PPEMRange range) {
|
||||||
|
Exclusive l(DWriteFactoryMutex);
|
||||||
{
|
{
|
||||||
AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get());
|
AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get());
|
||||||
if (!eblc.fExists) {
|
if (!eblc.fExists) {
|
||||||
@ -337,6 +358,7 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
|
|||||||
if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
|
if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
|
||||||
DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
|
DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
|
||||||
{
|
{
|
||||||
|
Exclusive l(DWriteFactoryMutex);
|
||||||
HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
|
HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
|
||||||
fTextSizeMeasure,
|
fTextSizeMeasure,
|
||||||
1.0f, // pixelsPerDip
|
1.0f, // pixelsPerDip
|
||||||
@ -346,12 +368,16 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
|
|||||||
&gm),
|
&gm),
|
||||||
"Could not get gdi compatible glyph metrics.");
|
"Could not get gdi compatible glyph metrics.");
|
||||||
} else {
|
} else {
|
||||||
|
Exclusive l(DWriteFactoryMutex);
|
||||||
HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
|
HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
|
||||||
"Could not get design metrics.");
|
"Could not get design metrics.");
|
||||||
}
|
}
|
||||||
|
|
||||||
DWRITE_FONT_METRICS dwfm;
|
DWRITE_FONT_METRICS dwfm;
|
||||||
fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
|
{
|
||||||
|
Exclusive l(DWriteFactoryMutex);
|
||||||
|
fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
|
||||||
|
}
|
||||||
SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure,
|
SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure,
|
||||||
SkIntToScalar(gm.advanceWidth),
|
SkIntToScalar(gm.advanceWidth),
|
||||||
SkIntToScalar(dwfm.designUnitsPerEm));
|
SkIntToScalar(dwfm.designUnitsPerEm));
|
||||||
@ -398,9 +424,10 @@ HRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph,
|
|||||||
run.glyphIndices = &glyphId;
|
run.glyphIndices = &glyphId;
|
||||||
run.isSideways = FALSE;
|
run.isSideways = FALSE;
|
||||||
run.glyphOffsets = &offset;
|
run.glyphOffsets = &offset;
|
||||||
|
{
|
||||||
SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
|
Exclusive l(DWriteFactoryMutex);
|
||||||
HRM(fTypeface->fFactory->CreateGlyphRunAnalysis(
|
SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
|
||||||
|
HRM(fTypeface->fFactory->CreateGlyphRunAnalysis(
|
||||||
&run,
|
&run,
|
||||||
1.0f, // pixelsPerDip,
|
1.0f, // pixelsPerDip,
|
||||||
&fXform,
|
&fXform,
|
||||||
@ -409,11 +436,11 @@ HRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph,
|
|||||||
0.0f, // baselineOriginX,
|
0.0f, // baselineOriginX,
|
||||||
0.0f, // baselineOriginY,
|
0.0f, // baselineOriginY,
|
||||||
&glyphRunAnalysis),
|
&glyphRunAnalysis),
|
||||||
"Could not create glyph run analysis.");
|
"Could not create glyph run analysis.");
|
||||||
|
|
||||||
HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox),
|
|
||||||
"Could not get texture bounds.");
|
|
||||||
|
|
||||||
|
HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox),
|
||||||
|
"Could not get texture bounds.");
|
||||||
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,30 +678,32 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph,
|
|||||||
run.glyphIndices = &index;
|
run.glyphIndices = &index;
|
||||||
run.isSideways = FALSE;
|
run.isSideways = FALSE;
|
||||||
run.glyphOffsets = &offset;
|
run.glyphOffsets = &offset;
|
||||||
|
{
|
||||||
|
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.");
|
||||||
|
|
||||||
SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
|
//NOTE: this assumes that the glyph has already been measured
|
||||||
HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run,
|
//with an exact same glyph run analysis.
|
||||||
1.0f, // pixelsPerDip,
|
RECT bbox;
|
||||||
&fXform,
|
bbox.left = glyph.fLeft;
|
||||||
renderingMode,
|
bbox.top = glyph.fTop;
|
||||||
fMeasuringMode,
|
bbox.right = glyph.fLeft + glyph.fWidth;
|
||||||
0.0f, // baselineOriginX,
|
bbox.bottom = glyph.fTop + glyph.fHeight;
|
||||||
0.0f, // baselineOriginY,
|
HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
|
||||||
&glyphRunAnalysis),
|
&bbox,
|
||||||
"Could not create glyph run analysis.");
|
fBits.begin(),
|
||||||
|
sizeNeeded),
|
||||||
//NOTE: this assumes that the glyph has already been measured
|
"Could not draw mask.");
|
||||||
//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();
|
return fBits.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,17 +759,20 @@ void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
|
|||||||
HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
|
HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
|
||||||
"Could not create geometry to path converter.");
|
"Could not create geometry to path converter.");
|
||||||
uint16_t glyphId = glyph.getGlyphID();
|
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.
|
Exclusive l(DWriteFactoryMutex);
|
||||||
HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSizeRender),
|
//TODO: convert to<->from DIUs? This would make a difference if hinting.
|
||||||
&glyphId,
|
//It may not be needed, it appears that DirectWrite only hints at em size.
|
||||||
nullptr, //advances
|
HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSizeRender),
|
||||||
nullptr, //offsets
|
&glyphId,
|
||||||
1, //num glyphs
|
nullptr, //advances
|
||||||
FALSE, //sideways
|
nullptr, //offsets
|
||||||
FALSE, //rtl
|
1, //num glyphs
|
||||||
geometryToPath.get()),
|
FALSE, //sideways
|
||||||
"Could not create glyph outline.");
|
FALSE, //rtl
|
||||||
|
geometryToPath.get()),
|
||||||
|
"Could not create glyph outline.");
|
||||||
|
}
|
||||||
|
|
||||||
path->transform(fSkXform);
|
path->transform(fSkXform);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user