Index: src/ports/SkScalerContext_win_dw.cpp |
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp |
index f3293bf00348d09ec8e5349461e631e4faecd8b8..c4fab0396b781d4f2af7e331f86a0f99b504b7ba 100644 |
--- a/src/ports/SkScalerContext_win_dw.cpp |
+++ b/src/ports/SkScalerContext_win_dw.cpp |
@@ -17,6 +17,7 @@ |
#include "SkMatrix22.h" |
#include "SkOTTable_EBLC.h" |
#include "SkOTTable_EBSC.h" |
+#include "SkOTTable_gasp.h" |
#include "SkPath.h" |
#include "SkScalerContext.h" |
#include "SkScalerContext_win_dw.h" |
@@ -30,7 +31,57 @@ static bool isLCD(const SkScalerContext::Rec& rec) { |
SkMask::kLCD32_Format == rec.fMaskFormat; |
} |
-static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) { |
+/** A PPEMRange is inclusive, [min, max]. */ |
+struct PPEMRange { |
+ int min; |
+ int max; |
+}; |
+ |
+/** If the rendering mode for the specified 'size' is gridfit, |
+ * then return true and place the gridfit range into 'range'. |
+ * Otherwise, return false, and leave 'range' alone. |
+ */ |
+static bool renderingModeIsGridfit(DWriteFontTypeface* typeface, int size, PPEMRange* range) { |
mtklein
2014/06/23 14:59:20
static void expand_range_if_gridfit_only?
bungeman-skia
2014/06/23 15:13:49
Done.
|
+ AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get()); |
+ if (!gasp.fExists) { |
+ return false; |
+ } |
+ if (gasp.fSize < sizeof(SkOTTableGridAndScanProcedure)) { |
+ return false; |
+ } |
+ if (gasp->version != SkOTTableGridAndScanProcedure::version0 && |
+ gasp->version != SkOTTableGridAndScanProcedure::version1) |
+ { |
+ return false; |
+ } |
+ |
+ uint16_t numRanges = SkEndianSwap16(gasp->numRanges); |
+ if (numRanges > 1024 || |
+ gasp.fSize < sizeof(SkOTTableGridAndScanProcedure) + |
+ sizeof(SkOTTableGridAndScanProcedure::GaspRange) * numRanges) |
+ { |
+ return false; |
+ } |
+ |
+ const SkOTTableGridAndScanProcedure::GaspRange* rangeTable = |
+ SkTAfter<const SkOTTableGridAndScanProcedure::GaspRange>(gasp.get()); |
+ int minPPEM = -1; |
+ for (uint16_t i = 0; i < numRanges; ++i, ++rangeTable) { |
+ int maxPPEM = SkEndianSwap16(rangeTable->maxPPEM); |
+ if (minPPEM < size && size <= maxPPEM && |
+ rangeTable->flags.raw.value == SkOTTableGridAndScanProcedure::GaspRange::behavior::Raw::GridfitMask) |
mtklein
2014/06/23 14:59:20
// _only_ gridfit
bungeman-skia
2014/06/23 15:13:49
Done.
|
+ { |
+ range->min = minPPEM + 1; |
+ range->max = maxPPEM; |
+ return true; |
+ } |
+ minPPEM = maxPPEM; |
+ } |
+ |
+ return false; |
+} |
+ |
+static bool hasBitmapStrike(DWriteFontTypeface* typeface, PPEMRange range) { |
mtklein
2014/06/23 14:59:20
has_bitmap_strike, etc.
bungeman-skia
2014/06/23 15:13:49
Done.
|
{ |
AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get()); |
if (!eblc.fExists) { |
@@ -44,7 +95,8 @@ static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) { |
} |
uint32_t numSizes = SkEndianSwap32(eblc->numSizes); |
- if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) + |
+ if (numSizes > 1024 || |
+ eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) + |
sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable) * numSizes) |
{ |
return false; |
@@ -53,13 +105,15 @@ static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) { |
const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable = |
SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable>(eblc.get()); |
for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) { |
- if (sizeTable->ppemX == size && sizeTable->ppemY == size) { |
+ if (sizeTable->ppemX == sizeTable->ppemY && |
+ range.min <= sizeTable->ppemX && sizeTable->ppemX <= range.max) |
+ { |
// TODO: determine if we should dig through IndexSubTableArray/IndexSubTable |
// to determine the actual number of glyphs with bitmaps. |
// TODO: Ensure that the bitmaps actually cover a significant portion of the strike. |
- //TODO: Endure that the bitmaps are bi-level. |
+ // TODO: Ensure that the bitmaps are bi-level? |
if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3) { |
return true; |
} |
@@ -80,7 +134,8 @@ static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) { |
} |
uint32_t numSizes = SkEndianSwap32(ebsc->numSizes); |
- if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) + |
+ if (numSizes > 1024 || |
+ ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) + |
sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable) * numSizes) |
{ |
return false; |
@@ -89,7 +144,8 @@ static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) { |
const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable = |
SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable>(ebsc.get()); |
for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) { |
- if (scaleTable->ppemX == size && scaleTable->ppemY == size) { |
+ if (scaleTable->ppemX == scaleTable->ppemY && |
+ range.min <= scaleTable->ppemX && scaleTable->ppemX <= range.max) { |
// EBSC tables are normally only found in bitmap only fonts. |
return true; |
} |
@@ -159,10 +215,16 @@ SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, |
} |
bool bitmapRequested = SkToBool(fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag); |
- bool hasBitmap = false; |
+ bool treatLikeBitmap = false; |
bool axisAlignedBitmap = false; |
if (bitmapRequested) { |
- hasBitmap = hasBitmapStrike(typeface, SkScalarTruncToInt(gdiTextSize)); |
+ int bitmapPPEM = SkScalarTruncToInt(gdiTextSize); |
+ PPEMRange range = { bitmapPPEM, bitmapPPEM}; |
mtklein
2014/06/23 14:59:20
This would be a good place to explain why we're do
bungeman-skia
2014/06/23 15:13:49
Done.
|
+#ifndef SK_IGNORE_DWRITE_RENDERING_FIX |
+ renderingModeIsGridfit(typeface, bitmapPPEM, &range); |
+#endif |
+ treatLikeBitmap = hasBitmapStrike(typeface, range); |
+ |
axisAlignedBitmap = isAxisAligned(fRec); |
} |
@@ -176,7 +238,7 @@ SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, |
// If we can use a bitmap, use gdi classic rendering and measurement. |
// This will not always provide a bitmap, but matches expected behavior. |
- } else if (hasBitmap && axisAlignedBitmap) { |
+ } else if (treatLikeBitmap && axisAlignedBitmap) { |
fTextSizeRender = gdiTextSize; |
fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC; |
fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; |
@@ -185,7 +247,7 @@ SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, |
// If rotated but the horizontal text could have used a bitmap, |
// render high quality rotated glyphs but measure using bitmap metrics. |
- } else if (hasBitmap) { |
+ } else if (treatLikeBitmap) { |
fTextSizeRender = gdiTextSize; |
fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; |
fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; |