| Index: src/ports/SkFontHost_win_dw.cpp
|
| ===================================================================
|
| --- src/ports/SkFontHost_win_dw.cpp (revision 14081)
|
| +++ src/ports/SkFontHost_win_dw.cpp (working copy)
|
| @@ -123,104 +123,6 @@
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| -class DWriteOffscreen {
|
| -public:
|
| - DWriteOffscreen() : fWidth(0), fHeight(0) { }
|
| -
|
| - void init(IDWriteFactory* factory, IDWriteFontFace* fontFace,
|
| - const DWRITE_MATRIX& xform, FLOAT fontSize)
|
| - {
|
| - fFactory = factory;
|
| - fFontFace = fontFace;
|
| - fFontSize = fontSize;
|
| - fXform = xform;
|
| - }
|
| -
|
| - const void* draw(const SkGlyph&, bool isBW);
|
| -
|
| -private:
|
| - uint16_t fWidth;
|
| - uint16_t fHeight;
|
| - IDWriteFactory* fFactory;
|
| - IDWriteFontFace* fFontFace;
|
| - FLOAT fFontSize;
|
| - DWRITE_MATRIX fXform;
|
| - SkTDArray<uint8_t> fBits;
|
| -};
|
| -
|
| -const void* DWriteOffscreen::draw(const SkGlyph& glyph, bool isBW) {
|
| - if (fWidth < glyph.fWidth || fHeight < glyph.fHeight) {
|
| - fWidth = SkMax32(fWidth, glyph.fWidth);
|
| - fHeight = SkMax32(fHeight, glyph.fHeight);
|
| -
|
| - if (isBW) {
|
| - fBits.setCount(fWidth * fHeight);
|
| - } else {
|
| - fBits.setCount(fWidth * fHeight * 3);
|
| - }
|
| - }
|
| -
|
| - // erase
|
| - memset(fBits.begin(), 0, fBits.count());
|
| -
|
| - fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
|
| - fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
|
| -
|
| - FLOAT advance = 0.0f;
|
| -
|
| - UINT16 index = glyph.getGlyphID();
|
| -
|
| - DWRITE_GLYPH_OFFSET offset;
|
| - offset.advanceOffset = 0.0f;
|
| - offset.ascenderOffset = 0.0f;
|
| -
|
| - DWRITE_GLYPH_RUN run;
|
| - run.glyphCount = 1;
|
| - run.glyphAdvances = &advance;
|
| - run.fontFace = fFontFace;
|
| - run.fontEmSize = fFontSize;
|
| - run.bidiLevel = 0;
|
| - run.glyphIndices = &index;
|
| - run.isSideways = FALSE;
|
| - run.glyphOffsets = &offset;
|
| -
|
| - DWRITE_RENDERING_MODE renderingMode;
|
| - DWRITE_TEXTURE_TYPE textureType;
|
| - if (isBW) {
|
| - renderingMode = DWRITE_RENDERING_MODE_ALIASED;
|
| - textureType = DWRITE_TEXTURE_ALIASED_1x1;
|
| - } else {
|
| - renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
|
| - textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
|
| - }
|
| - SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
|
| - HRNM(fFactory->CreateGlyphRunAnalysis(&run,
|
| - 1.0f, // pixelsPerDip,
|
| - &fXform,
|
| - renderingMode,
|
| - DWRITE_MEASURING_MODE_NATURAL,
|
| - 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(),
|
| - fBits.count()),
|
| - "Could not draw mask.");
|
| - return fBits.begin();
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| class StreamFontFileLoader : public IDWriteFontFileLoader {
|
| public:
|
| // IUnknown methods
|
| @@ -544,10 +446,15 @@
|
| SkPaint::FontMetrics* mY) SK_OVERRIDE;
|
|
|
| private:
|
| - DWriteOffscreen fOffscreen;
|
| + const void* drawDWMask(const SkGlyph& glyph);
|
| +
|
| + SkTDArray<uint8_t> fBits;
|
| DWRITE_MATRIX fXform;
|
| SkAutoTUnref<DWriteFontTypeface> fTypeface;
|
| int fGlyphCount;
|
| + DWRITE_RENDERING_MODE fRenderingMode;
|
| + DWRITE_TEXTURE_TYPE fTextureType;
|
| + DWRITE_MEASURING_MODE fMeasuringMode;
|
| };
|
|
|
| static bool are_same(IUnknown* a, IUnknown* b) {
|
| @@ -676,8 +583,19 @@
|
| fXform.dx = 0;
|
| fXform.dy = 0;
|
|
|
| - fOffscreen.init(fTypeface->fFactory.get(), fTypeface->fDWriteFontFace.get(),
|
| - fXform, SkScalarToFloat(fRec.fTextSize));
|
| + if (SkMask::kBW_Format == fRec.fMaskFormat) {
|
| + fRenderingMode = DWRITE_RENDERING_MODE_ALIASED;
|
| + fTextureType = DWRITE_TEXTURE_ALIASED_1x1;
|
| + fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
|
| + } else {
|
| + fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
|
| + fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
|
| + fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
|
| + }
|
| +
|
| + if (this->isSubpixel()) {
|
| + fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
|
| + }
|
| }
|
|
|
| SkScalerContext_DW::~SkScalerContext_DW() {
|
| @@ -708,17 +626,30 @@
|
|
|
| uint16_t glyphId = glyph->getGlyphID();
|
| DWRITE_GLYPH_METRICS gm;
|
| - HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
|
| - "Could not get design metrics.");
|
|
|
| + if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
|
| + DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
|
| + {
|
| + HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
|
| + fRec.fTextSize,
|
| + 1.0f, // pixelsPerDip
|
| + &fXform,
|
| + DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode,
|
| + &glyphId, 1,
|
| + &gm),
|
| + "Could not get gdi compatible glyph metrics.");
|
| + } else {
|
| + HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
|
| + "Could not get design metrics.");
|
| + }
|
| +
|
| DWRITE_FONT_METRICS dwfm;
|
| fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
|
| -
|
| SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize,
|
| SkIntToScalar(gm.advanceWidth),
|
| SkIntToScalar(dwfm.designUnitsPerEm));
|
|
|
| - if (!(fRec.fFlags & kSubpixelPositioning_Flag)) {
|
| + if (!this->isSubpixel()) {
|
| advanceX = SkScalarRoundToScalar(advanceX);
|
| }
|
|
|
| @@ -758,31 +689,20 @@
|
| run.isSideways = FALSE;
|
| run.glyphOffsets = &offset;
|
|
|
| - const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
|
| - DWRITE_RENDERING_MODE renderingMode;
|
| - DWRITE_TEXTURE_TYPE textureType;
|
| - if (isBW) {
|
| - renderingMode = DWRITE_RENDERING_MODE_ALIASED;
|
| - textureType = DWRITE_TEXTURE_ALIASED_1x1;
|
| - } else {
|
| - renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
|
| - textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
|
| - }
|
| -
|
| SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
|
| HRVM(fTypeface->fFactory->CreateGlyphRunAnalysis(
|
| &run,
|
| 1.0f, // pixelsPerDip,
|
| &fXform,
|
| - renderingMode,
|
| - DWRITE_MEASURING_MODE_NATURAL,
|
| + fRenderingMode,
|
| + fMeasuringMode,
|
| 0.0f, // baselineOriginX,
|
| 0.0f, // baselineOriginY,
|
| &glyphRunAnalysis),
|
| "Could not create glyph run analysis.");
|
|
|
| RECT bbox;
|
| - HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, &bbox),
|
| + HRVM(glyphRunAnalysis->GetAlphaTextureBounds(fTextureType, &bbox),
|
| "Could not get texture bounds.");
|
|
|
| glyph->fWidth = SkToU16(bbox.right - bbox.left);
|
| @@ -792,7 +712,7 @@
|
| }
|
|
|
| void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
|
| - SkPaint::FontMetrics* my) {
|
| + SkPaint::FontMetrics* my) {
|
| if (!(mx || my))
|
| return;
|
|
|
| @@ -804,7 +724,17 @@
|
| }
|
|
|
| DWRITE_FONT_METRICS dwfm;
|
| - fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
|
| + if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
|
| + DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
|
| + {
|
| + fTypeface->fDWriteFontFace->GetGdiCompatibleMetrics(
|
| + fRec.fTextSize,
|
| + 1.0f, // pixelsPerDip
|
| + &fXform,
|
| + &dwfm);
|
| + } else {
|
| + fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
|
| + }
|
|
|
| SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
|
| if (mx) {
|
| @@ -931,12 +861,68 @@
|
| }
|
| }
|
|
|
| +const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) {
|
| + int sizeNeeded = glyph.fWidth * glyph.fHeight;
|
| + if (DWRITE_RENDERING_MODE_ALIASED != fRenderingMode) {
|
| + sizeNeeded *= 3;
|
| + }
|
| + if (sizeNeeded > fBits.count()) {
|
| + fBits.setCount(sizeNeeded);
|
| + }
|
| +
|
| + // erase
|
| + memset(fBits.begin(), 0, sizeNeeded);
|
| +
|
| + fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
|
| + fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
|
| +
|
| + FLOAT advance = 0.0f;
|
| +
|
| + UINT16 index = glyph.getGlyphID();
|
| +
|
| + DWRITE_GLYPH_OFFSET offset;
|
| + offset.advanceOffset = 0.0f;
|
| + offset.ascenderOffset = 0.0f;
|
| +
|
| + DWRITE_GLYPH_RUN run;
|
| + run.glyphCount = 1;
|
| + run.glyphAdvances = &advance;
|
| + run.fontFace = fTypeface->fDWriteFontFace.get();
|
| + run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
|
| + run.bidiLevel = 0;
|
| + run.glyphIndices = &index;
|
| + run.isSideways = FALSE;
|
| + run.glyphOffsets = &offset;
|
| +
|
| + SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
|
| + HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run,
|
| + 1.0f, // pixelsPerDip,
|
| + &fXform,
|
| + fRenderingMode,
|
| + 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(fTextureType,
|
| + &bbox,
|
| + fBits.begin(),
|
| + sizeNeeded),
|
| + "Could not draw mask.");
|
| + return fBits.begin();
|
| +}
|
| +
|
| void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
|
| - const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
|
| - const bool isAA = !isLCD(fRec);
|
| -
|
| //Create the mask.
|
| - const void* bits = fOffscreen.draw(glyph, isBW);
|
| + const void* bits = this->drawDWMask(glyph);
|
| if (!bits) {
|
| sk_bzero(glyph.fImage, glyph.computeImageSize());
|
| return;
|
| @@ -944,9 +930,10 @@
|
|
|
| //Copy the mask into the glyph.
|
| const uint8_t* src = (const uint8_t*)bits;
|
| - if (isBW) {
|
| + if (DWRITE_RENDERING_MODE_ALIASED == fRenderingMode) {
|
| bilevel_to_bw(src, glyph);
|
| - } else if (isAA) {
|
| + ((SkGlyph*)&glyph)->fMaskFormat = SkMask::kBW_Format;
|
| + } else if (!isLCD(fRec)) {
|
| if (fPreBlend.isApplicable()) {
|
| rgb_to_a8<true>(src, glyph, fPreBlend.fG);
|
| } else {
|
|
|