From 793818b23573178b967f5d213163236d56e4ec7b Mon Sep 17 00:00:00 2001 From: Herb Derby Date: Tue, 25 Jun 2019 17:10:11 -0400 Subject: [PATCH] Make all SkGlyph fields private All the scalers are friends, and can still access the fields, but clients of SkGlyph can no longer access them. Change-Id: Idbc26de74ceebeac37fa8fec9277ecf8b870e5e9 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/223801 Reviewed-by: Ben Wagner Commit-Queue: Herb Derby --- src/core/SkGlyph.h | 36 ++++---- src/core/SkStrike.cpp | 2 +- src/ports/SkFontHost_FreeType.cpp | 10 +-- src/ports/SkFontHost_mac.cpp | 64 ++++++++----- src/ports/SkFontHost_win.cpp | 58 ++++++------ src/ports/SkScalerContext_win_dw.cpp | 129 ++++++++++++++------------- src/ports/SkScalerContext_win_dw.h | 16 ++++ 7 files changed, 177 insertions(+), 138 deletions(-) diff --git a/src/core/SkGlyph.h b/src/core/SkGlyph.h index de915c2958..dacabb404f 100644 --- a/src/core/SkGlyph.h +++ b/src/core/SkGlyph.h @@ -118,16 +118,13 @@ class SkGlyph { public: static constexpr SkFixed kSubpixelRound = SK_FixedHalf >> SkPackedGlyphID::kSubBits; - constexpr explicit SkGlyph(SkPackedGlyphID id) : fID{id} {} + constexpr explicit SkGlyph(SkPackedGlyphID id) : fID{id} { } explicit SkGlyph(const SkGlyphPrototype& p); - SkVector advanceVector() const { return SkVector{fAdvanceX, fAdvanceY}; } SkScalar advanceX() const { return fAdvanceX; } SkScalar advanceY() const { return fAdvanceY; } - bool isJustAdvance() const { return MASK_FORMAT_JUST_ADVANCE == fMaskFormat; } - bool isFullMetrics() const { return MASK_FORMAT_JUST_ADVANCE != fMaskFormat; } SkGlyphID getGlyphID() const { return fID.code(); } SkPackedGlyphID getPackedID() const { return fID; } SkFixed getSubXFixed() const { return fID.getSubXFixed(); } @@ -220,16 +217,6 @@ public: void ensureIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos, SkScalar* array, int* count, SkArenaAlloc* alloc); - void* fImage = nullptr; - - // The width and height of the glyph mask. - uint16_t fWidth = 0, - fHeight = 0; - - // The offset from the glyphs origin on the baseline to the top left of the glyph mask. - int16_t fTop = 0, - fLeft = 0; - private: // There are two sides to an SkGlyph, the scaler side (things that create glyph data) have // access to all the fields. Scalers are assumed to maintain all the SkGlyph invariants. The @@ -252,8 +239,6 @@ private: static constexpr uint16_t kMaxGlyphWidth = 1u << 13u; - size_t allocImage(SkArenaAlloc* alloc); - // Support horizontal and vertical skipping strike-through / underlines. // The caller walks the linked list looking for a match. For a horizontal underline, // the fBounds contains the top and bottom of the underline. The fInterval pair contains the @@ -271,9 +256,22 @@ private: bool fHasPath{false}; }; - // path == nullptr indicates there is no path. + size_t allocImage(SkArenaAlloc* alloc); + + // path == nullptr indicates that there is no path. void installPath(SkArenaAlloc* alloc, const SkPath* path); + // The width and height of the glyph mask. + uint16_t fWidth = 0, + fHeight = 0; + + // The offset from the glyphs origin on the baseline to the top left of the glyph mask. + int16_t fTop = 0, + fLeft = 0; + + // fImage must remain null if the glyph is empty or if width > kMaxGlyphWidth. + void* fImage = nullptr; + // Path data has tricky state. If the glyph isEmpty, then fPathData should always be nullptr, // else if fPathData is not null, then a path has been requested. The fPath field of fPathData // may still be null after the request meaning that there is no path for this glyph. @@ -291,9 +289,7 @@ private: // Used by the DirectWrite scaler to track state. int8_t fForceBW = 0; - // TODO(herb) remove friend statement after SkStrike cleanup. - friend class SkStrike; - SkPackedGlyphID fID; + const SkPackedGlyphID fID; }; struct SkGlyphPrototype { diff --git a/src/core/SkStrike.cpp b/src/core/SkStrike.cpp index 01ccec6e20..e41e368545 100644 --- a/src/core/SkStrike.cpp +++ b/src/core/SkStrike.cpp @@ -237,7 +237,7 @@ void SkStrike::forceValidate() const { size_t memoryUsed = sizeof(*this); fGlyphMap.foreach ([&memoryUsed](const SkGlyph* glyphPtr) { memoryUsed += sizeof(SkGlyph); - if (glyphPtr->fImage) { + if (glyphPtr->setImageHasBeenCalled()) { memoryUsed += glyphPtr->imageSize(); } if (glyphPtr->setPathHasBeenCalled() && glyphPtr->path() != nullptr) { diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index cc4633883a..04a6a02169 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -1318,15 +1318,11 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { #endif } -static void clear_glyph_image(const SkGlyph& glyph) { - sk_bzero(glyph.fImage, glyph.rowBytes() * glyph.fHeight); -} - void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { SkAutoMutexExclusive ac(f_t_mutex()); if (this->setupSize()) { - clear_glyph_image(glyph); + sk_bzero(glyph.fImage, glyph.imageSize()); return; } @@ -1334,9 +1330,9 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { if (err != 0) { SK_TRACEFTR(err, "SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d " "width:%d height:%d rb:%d flags:%d) failed.", - glyph.getGlyphID(), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), + glyph.getGlyphID(), glyph.width(), glyph.height(), glyph.rowBytes(), fLoadGlyphFlags); - clear_glyph_image(glyph); + sk_bzero(glyph.fImage, glyph.imageSize()); return; } diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp index 4d9ecefc75..723d77b7b8 100644 --- a/src/ports/SkFontHost_mac.cpp +++ b/src/ports/SkFontHost_mac.cpp @@ -941,6 +941,20 @@ protected: private: static void CTPathElement(void *info, const CGPathElement *element); + template + static void RGBToA8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, + const SkGlyph& glyph, const uint8_t* table8); + template + static uint16_t RGBToLcd16(CGRGBPixel rgb, const uint8_t* tableR, + const uint8_t* tableG, + const uint8_t* tableB); + template + static void RGBToLcd16(const CGRGBPixel* SK_RESTRICT cgPixels, + size_t cgRowBytes, + const SkGlyph& glyph, + const uint8_t* tableR, + const uint8_t* tableG, + const uint8_t* tableB); Offscreen fOffscreen; @@ -1066,12 +1080,12 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& } size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel); - if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) { - if (fSize.fWidth < glyph.fWidth) { - fSize.fWidth = RoundSize(glyph.fWidth); + if (!fCG || fSize.fWidth < glyph.width() || fSize.fHeight < glyph.height()) { + if (fSize.fWidth < glyph.width()) { + fSize.fWidth = RoundSize(glyph.width()); } - if (fSize.fHeight < glyph.fHeight) { - fSize.fHeight = RoundSize(glyph.fHeight); + if (fSize.fHeight < glyph.height()) { + fSize.fHeight = RoundSize(glyph.height()); } rowBytes = fSize.fWidth * sizeof(CGRGBPixel); @@ -1117,11 +1131,11 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get(); // skip rows based on the glyph's height - image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth; + image += (fSize.fHeight - glyph.height()) * fSize.fWidth; // Erase to white (or transparent black if it's a color glyph, to not composite against white). uint32_t bgColor = (!glyph.isColor()) ? 0xFFFFFFFF : 0x00000000; - sk_memset_rect32(image, bgColor, glyph.fWidth, glyph.fHeight, rowBytes); + sk_memset_rect32(image, bgColor, glyph.width(), glyph.height(), rowBytes); float subX = 0; float subY = 0; @@ -1130,7 +1144,7 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& subY = SkFixedToFloat(glyph.getSubYFixed()); } - CGPoint point = CGPointMake(-glyph.fLeft + subX, glyph.fTop + glyph.fHeight - subY); + CGPoint point = CGPointMake(-glyph.left() + subX, glyph.top() + glyph.height() - subY); // Prior to 10.10, CTFontDrawGlyphs acted like CGContextShowGlyphsAtPositions and took // 'positions' which are in text space. The glyph location (in device space) must be // mapped into text space, so that CG can convert it back into device space. @@ -1271,9 +1285,10 @@ static inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) { #endif return lum; } + template -static void rgb_to_a8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, - const SkGlyph& glyph, const uint8_t* table8) { +void SkScalerContext_Mac::RGBToA8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, + const SkGlyph& glyph, const uint8_t* table8) { const int width = glyph.fWidth; size_t dstRB = glyph.rowBytes(); uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; @@ -1288,9 +1303,9 @@ static void rgb_to_a8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, } template -static inline uint16_t rgb_to_lcd16(CGRGBPixel rgb, const uint8_t* tableR, - const uint8_t* tableG, - const uint8_t* tableB) { +uint16_t SkScalerContext_Mac::RGBToLcd16(CGRGBPixel rgb, const uint8_t* tableR, + const uint8_t* tableG, + const uint8_t* tableB) { U8CPU r = sk_apply_lut_if(0xFF - ((rgb >> 16) & 0xFF), tableR); U8CPU g = sk_apply_lut_if(0xFF - ((rgb >> 8) & 0xFF), tableG); U8CPU b = sk_apply_lut_if(0xFF - ((rgb >> 0) & 0xFF), tableB); @@ -1301,16 +1316,21 @@ static inline uint16_t rgb_to_lcd16(CGRGBPixel rgb, const uint8_t* tableR, #endif return SkPack888ToRGB16(r, g, b); } + template -static void rgb_to_lcd16(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, const SkGlyph& glyph, - const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { +void SkScalerContext_Mac::RGBToLcd16(const CGRGBPixel* SK_RESTRICT cgPixels, + size_t cgRowBytes, + const SkGlyph& glyph, + const uint8_t* tableR, + const uint8_t* tableG, + const uint8_t* tableB) { const int width = glyph.fWidth; size_t dstRB = glyph.rowBytes(); uint16_t* SK_RESTRICT dst = (uint16_t*)glyph.fImage; for (int y = 0; y < glyph.fHeight; y++) { for (int i = 0; i < width; i++) { - dst[i] = rgb_to_lcd16(cgPixels[i], tableR, tableG, tableB); + dst[i] = RGBToLcd16(cgPixels[i], tableR, tableG, tableB); } cgPixels = SkTAddOffset(cgPixels, cgRowBytes); dst = SkTAddOffset(dst, dstRB); @@ -1370,18 +1390,18 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { switch (glyph.fMaskFormat) { case SkMask::kLCD16_Format: { if (fPreBlend.isApplicable()) { - rgb_to_lcd16(cgPixels, cgRowBytes, glyph, - fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); + RGBToLcd16(cgPixels, cgRowBytes, glyph, + fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); } else { - rgb_to_lcd16(cgPixels, cgRowBytes, glyph, - fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); + RGBToLcd16(cgPixels, cgRowBytes, glyph, + fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); } } break; case SkMask::kA8_Format: { if (fPreBlend.isApplicable()) { - rgb_to_a8(cgPixels, cgRowBytes, glyph, fPreBlend.fG); + RGBToA8(cgPixels, cgRowBytes, glyph, fPreBlend.fG); } else { - rgb_to_a8(cgPixels, cgRowBytes, glyph, fPreBlend.fG); + RGBToA8(cgPixels, cgRowBytes, glyph, fPreBlend.fG); } } break; case SkMask::kBW_Format: { diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index be783cddf1..7ebfd1ea3a 100644 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -483,14 +483,14 @@ const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW, SkASSERT(prev != CLR_INVALID); } - if (fBM && (fIsBW != isBW || fWidth < glyph.fWidth || fHeight < glyph.fHeight)) { + if (fBM && (fIsBW != isBW || fWidth < glyph.width() || fHeight < glyph.height())) { DeleteObject(fBM); fBM = 0; } fIsBW = isBW; - fWidth = SkMax32(fWidth, glyph.fWidth); - fHeight = SkMax32(fHeight, glyph.fHeight); + fWidth = SkMax32(fWidth, glyph.width()); + fHeight = SkMax32(fHeight, glyph.height()); int biWidth = isBW ? alignTo32(fWidth) : fWidth; @@ -525,8 +525,8 @@ const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW, memset(fBits, 0, size); XFORM xform = fXform; - xform.eDx = (float)-glyph.fLeft; - xform.eDy = (float)-glyph.fTop; + xform.eDx = (float)-glyph.left(); + xform.eDy = (float)-glyph.top(); SetWorldTransform(fDC, &xform); uint16_t glyphID = glyph.getGlyphID(); @@ -537,7 +537,7 @@ const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW, } *srcRBPtr = srcRB; // offset to the start of the image - return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB; + return (const char*)fBits + (fHeight - glyph.height()) * srcRB; } ////////////////////////////////////////////////////////////////////////////// @@ -565,6 +565,13 @@ protected: private: DWORD getGDIGlyphPath(SkGlyphID glyph, UINT flags, SkAutoSTMalloc* glyphbuf); + template + static void RGBToA8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, + const SkGlyph& glyph, const uint8_t* table8); + + template + static void RGBToLcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph, + const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB); HDCOffscreen fOffscreen; /** fGsA is the non-rotational part of total matrix without the text height scale. @@ -816,13 +823,13 @@ void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph) { // Bitmap FON cannot underhang, but vector FON may. // There appears no means of determining underhang of vector FON. glyph->fLeft = SkToS16(0); - glyph->fAdvanceX = glyph->fWidth; + glyph->fAdvanceX = glyph->width(); glyph->fAdvanceY = 0; // Vector FON will transform nicely, but bitmap FON do not. if (fType == SkScalerContext_GDI::kLine_Type) { SkRect bounds = SkRect::MakeXYWH(glyph->fLeft, glyph->fTop, - glyph->fWidth, glyph->fHeight); + glyph->width(), glyph->height()); SkMatrix m; m.setAll(SkFIXEDToScalar(fMat22.eM11), -SkFIXEDToScalar(fMat22.eM21), 0, -SkFIXEDToScalar(fMat22.eM12), SkFIXEDToScalar(fMat22.eM22), 0, @@ -1049,11 +1056,11 @@ static inline uint16_t rgb_to_lcd16(SkGdiRGB rgb, const uint8_t* tableR, } template -static void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, - const SkGlyph& glyph, const uint8_t* table8) { +void SkScalerContext_GDI::RGBToA8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, + const SkGlyph& glyph, const uint8_t* table8) { const size_t dstRB = glyph.rowBytes(); - const int width = glyph.fWidth; - uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); + const int width = glyph.width(); + uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.height() - 1) * dstRB); for (int y = 0; y < glyph.fHeight; y++) { for (int i = 0; i < width; i++) { @@ -1068,11 +1075,12 @@ static void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, } template -static void rgb_to_lcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph, - const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { +void SkScalerContext_GDI::RGBToLcd16( + const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph, + const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { const size_t dstRB = glyph.rowBytes(); - const int width = glyph.fWidth; - uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); + const int width = glyph.width(); + uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.height() - 1) * dstRB); for (int y = 0; y < glyph.fHeight; y++) { for (int i = 0; i < width; i++) { @@ -1116,7 +1124,7 @@ void SkScalerContext_GDI::generateImage(const SkGlyph& glyph) { //one with this and one without. SkGdiRGB* addr = (SkGdiRGB*)bits; for (int y = 0; y < glyph.fHeight; ++y) { - for (int x = 0; x < glyph.fWidth; ++x) { + for (int x = 0; x < glyph.width(); ++x) { int r = (addr[x] >> 16) & 0xFF; int g = (addr[x] >> 8) & 0xFF; int b = (addr[x] >> 0) & 0xFF; @@ -1136,10 +1144,10 @@ void SkScalerContext_GDI::generateImage(const SkGlyph& glyph) { dst -= dstRB; } #if SK_SHOW_TEXT_BLIT_COVERAGE - if (glyph.fWidth > 0 && glyph.fHeight > 0) { - int bitCount = glyph.fWidth & 7; + if (glyph.width() > 0 && glyph.fHeight > 0) { + int bitCount = glyph.width() & 7; uint8_t* first = (uint8_t*)glyph.fImage; - uint8_t* last = (uint8_t*)((char*)glyph.fImage + glyph.fHeight * dstRB - 1); + uint8_t* last = (uint8_t*)((char*)glyph.fImage + glyph.height() * dstRB - 1); *first |= 1 << 7; *last |= bitCount == 0 ? 1 : 1 << (8 - bitCount); } @@ -1149,19 +1157,17 @@ void SkScalerContext_GDI::generateImage(const SkGlyph& glyph) { // ... until we have the caller tell us that explicitly const SkGdiRGB* src = (const SkGdiRGB*)bits; if (fPreBlend.isApplicable()) { - rgb_to_a8(src, srcRB, glyph, fPreBlend.fG); + RGBToA8(src, srcRB, glyph, fPreBlend.fG); } else { - rgb_to_a8(src, srcRB, glyph, fPreBlend.fG); + RGBToA8(src, srcRB, glyph, fPreBlend.fG); } } else { // LCD16 const SkGdiRGB* src = (const SkGdiRGB*)bits; SkASSERT(SkMask::kLCD16_Format == glyph.fMaskFormat); if (fPreBlend.isApplicable()) { - rgb_to_lcd16(src, srcRB, glyph, - fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); + RGBToLcd16(src, srcRB, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); } else { - rgb_to_lcd16(src, srcRB, glyph, - fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); + RGBToLcd16(src, srcRB, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); } } } diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp index f80376e275..f4e8be808e 100644 --- a/src/ports/SkScalerContext_win_dw.cpp +++ b/src/ports/SkScalerContext_win_dw.cpp @@ -490,30 +490,6 @@ HRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph, return S_OK; } -/** GetAlphaTextureBounds succeeds but sometimes returns empty bounds like - * { 0x80000000, 0x80000000, 0x80000000, 0x80000000 } - * for small, but not quite zero, sized glyphs. - * Only set as non-empty if the returned bounds are non-empty. - */ -static bool glyph_check_and_set_bounds(SkGlyph* glyph, const RECT& bbox) { - if (bbox.left >= bbox.right || bbox.top >= bbox.bottom) { - return false; - } - - // We're trying to pack left and top into int16_t, - // and width and height into uint16_t, after outsetting by 1. - if (!SkIRect::MakeXYWH(-32767, -32767, 65535, 65535).contains( - SkIRect::MakeLTRB(bbox.left, bbox.top, bbox.right, bbox.bottom))) { - return false; - } - - glyph->fWidth = SkToU16(bbox.right - bbox.left); - glyph->fHeight = SkToU16(bbox.bottom - bbox.top); - glyph->fLeft = SkToS16(bbox.left); - glyph->fTop = SkToS16(bbox.top); - return true; -} - bool SkScalerContext_DW::isColorGlyph(const SkGlyph& glyph) { SkTScopedComPtr colorLayer; return getColorGlyphRun(glyph, &colorLayer); @@ -673,6 +649,31 @@ void SkScalerContext_DW::generatePngMetrics(SkGlyph* glyph) { } void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { + + + // GetAlphaTextureBounds succeeds but sometimes returns empty bounds like + // { 0x80000000, 0x80000000, 0x80000000, 0x80000000 } + // for small, but not quite zero, sized glyphs. + // Only set as non-empty if the returned bounds are non-empty. + auto glyphCheckAndSetBounds = [](SkGlyph* glyph, const RECT& bbox) { + if (bbox.left >= bbox.right || bbox.top >= bbox.bottom) { + return false; + } + + // We're trying to pack left and top into int16_t, + // and width and height into uint16_t, after outsetting by 1. + if (!SkIRect::MakeXYWH(-32767, -32767, 65535, 65535).contains( + SkIRect::MakeLTRB(bbox.left, bbox.top, bbox.right, bbox.bottom))) { + return false; + } + + glyph->fWidth = SkToU16(bbox.right - bbox.left); + glyph->fHeight = SkToU16(bbox.bottom - bbox.top); + glyph->fLeft = SkToS16(bbox.left); + glyph->fTop = SkToS16(bbox.top); + return true; + }; + glyph->fWidth = 0; glyph->fHeight = 0; glyph->fLeft = 0; @@ -699,7 +700,7 @@ void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { HRVM(this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox), "Requested bounding box could not be determined."); - if (glyph_check_and_set_bounds(glyph, bbox)) { + if (glyphCheckAndSetBounds(glyph, bbox)) { return; } @@ -714,7 +715,7 @@ void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { DWRITE_TEXTURE_ALIASED_1x1, &bbox), "Fallback bounding box could not be determined."); - if (glyph_check_and_set_bounds(glyph, bbox)) { + if (glyphCheckAndSetBounds(glyph, bbox)) { glyph->fForceBW = 1; glyph->fMaskFormat = SkMask::kBW_Format; } @@ -794,15 +795,15 @@ void SkScalerContext_DW::generateFontMetrics(SkFontMetrics* metrics) { #include "include/private/SkColorData.h" -static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) { - const int width = glyph.fWidth; +void SkScalerContext_DW::BilevelToBW(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) { + const int width = glyph.width(); const size_t dstRB = (width + 7) >> 3; uint8_t* SK_RESTRICT dst = static_cast(glyph.fImage); int byteCount = width >> 3; int bitCount = width & 7; - for (int y = 0; y < glyph.fHeight; ++y) { + for (int y = 0; y < glyph.height(); ++y) { if (byteCount > 0) { for (int i = 0; i < byteCount; ++i) { unsigned byte = 0; @@ -833,14 +834,15 @@ static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) } template -static void grayscale_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, - const uint8_t* table8) { +void SkScalerContext_DW::GrayscaleToA8(const uint8_t* SK_RESTRICT src, + const SkGlyph& glyph, + const uint8_t* table8) { const size_t dstRB = glyph.rowBytes(); - const U16CPU width = glyph.fWidth; + const int width = glyph.width(); uint8_t* SK_RESTRICT dst = static_cast(glyph.fImage); - for (U16CPU y = 0; y < glyph.fHeight; y++) { - for (U16CPU i = 0; i < width; i++) { + for (int y = 0; y < glyph.height(); y++) { + for (int i = 0; i < width; i++) { U8CPU a = *(src++); dst[i] = sk_apply_lut_if(a, table8); } @@ -849,13 +851,15 @@ static void grayscale_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph } template -static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) { +void SkScalerContext_DW::RGBToA8(const uint8_t* SK_RESTRICT src, + const SkGlyph& glyph, + const uint8_t* table8) { const size_t dstRB = glyph.rowBytes(); - const U16CPU width = glyph.fWidth; + const int width = glyph.width(); uint8_t* SK_RESTRICT dst = static_cast(glyph.fImage); - for (U16CPU y = 0; y < glyph.fHeight; y++) { - for (U16CPU i = 0; i < width; i++) { + for (int y = 0; y < glyph.height(); y++) { + for (int i = 0; i < width; i++) { U8CPU r = *(src++); U8CPU g = *(src++); U8CPU b = *(src++); @@ -866,14 +870,15 @@ static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, cons } template -static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, - const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { +void SkScalerContext_DW::RGBToLcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, + const uint8_t* tableR, const uint8_t* tableG, + const uint8_t* tableB) { const size_t dstRB = glyph.rowBytes(); - const U16CPU width = glyph.fWidth; + const int width = glyph.width(); uint16_t* SK_RESTRICT dst = static_cast(glyph.fImage); - for (U16CPU y = 0; y < glyph.fHeight; y++) { - for (U16CPU i = 0; i < width; i++) { + for (int y = 0; y < glyph.height(); y++) { + for (int i = 0; i < width; i++) { U8CPU r, g, b; if (RGB) { r = sk_apply_lut_if(*(src++), tableR); @@ -894,7 +899,7 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph, DWRITE_RENDERING_MODE renderingMode, DWRITE_TEXTURE_TYPE textureType) { - int sizeNeeded = glyph.fWidth * glyph.fHeight; + int sizeNeeded = glyph.width() * glyph.height(); if (DWRITE_TEXTURE_CLEARTYPE_3x1 == textureType) { sizeNeeded *= 3; } @@ -959,10 +964,10 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph, //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; + bbox.left = glyph.left(); + bbox.top = glyph.top(); + bbox.right = glyph.left() + glyph.width(); + bbox.bottom = glyph.top() + glyph.height(); { Shared l(DWriteFactoryMutex); HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType, @@ -986,14 +991,14 @@ void SkScalerContext_DW::generateColorGlyphImage(const SkGlyph& glyph) { SkASSERT(colorLayers.get()); SkMatrix matrix = fSkXform; - matrix.postTranslate(-SkIntToScalar(glyph.fLeft), -SkIntToScalar(glyph.fTop)); + matrix.postTranslate(-SkIntToScalar(glyph.left()), -SkIntToScalar(glyph.top())); if (this->isSubpixel()) { matrix.postTranslate(SkFixedToScalar(glyph.getSubXFixed()), SkFixedToScalar(glyph.getSubYFixed())); } - SkRasterClip rc(SkIRect::MakeWH(glyph.fWidth, glyph.fHeight)); + SkRasterClip rc(SkIRect::MakeWH(glyph.width(), glyph.height())); SkDraw draw; - draw.fDst = SkPixmap(SkImageInfo::MakeN32(glyph.fWidth, glyph.fHeight, kPremul_SkAlphaType), + draw.fDst = SkPixmap(SkImageInfo::MakeN32(glyph.width(), glyph.height(), kPremul_SkAlphaType), glyph.fImage, glyph.rowBytesUsingFormat(SkMask::Format::kARGB32_Format)); draw.fMatrix = &matrix; @@ -1066,7 +1071,7 @@ void SkScalerContext_DW::generatePngGlyphImage(const SkGlyph& glyph) { sk_sp image = SkImage::MakeFromEncoded(std::move(data)); SkBitmap dstBitmap; - dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight, + dstBitmap.setInfo(SkImageInfo::Make(glyph.width(), glyph.height(), kN32_SkColorType, kPremul_SkAlphaType), glyph.rowBytes()); @@ -1074,7 +1079,7 @@ void SkScalerContext_DW::generatePngGlyphImage(const SkGlyph& glyph) { SkCanvas canvas(dstBitmap); canvas.clear(SK_ColorTRANSPARENT); - canvas.translate(-glyph.fLeft, -glyph.fTop); + canvas.translate(-glyph.left(), -glyph.top()); if (this->isSubpixel()) { canvas.translate(SkFixedToScalar(glyph.getSubXFixed()), SkFixedToScalar(glyph.getSubYFixed())); @@ -1120,34 +1125,34 @@ void SkScalerContext_DW::generateImage(const SkGlyph& glyph) { if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) { SkASSERT(SkMask::kBW_Format == glyph.fMaskFormat); SkASSERT(DWRITE_TEXTURE_ALIASED_1x1 == textureType); - bilevel_to_bw(src, glyph); + BilevelToBW(src, glyph); } else if (!isLCD(fRec)) { if (textureType == DWRITE_TEXTURE_ALIASED_1x1) { if (fPreBlend.isApplicable()) { - grayscale_to_a8(src, glyph, fPreBlend.fG); + GrayscaleToA8(src, glyph, fPreBlend.fG); } else { - grayscale_to_a8(src, glyph, fPreBlend.fG); + GrayscaleToA8(src, glyph, fPreBlend.fG); } } else { if (fPreBlend.isApplicable()) { - rgb_to_a8(src, glyph, fPreBlend.fG); + RGBToA8(src, glyph, fPreBlend.fG); } else { - rgb_to_a8(src, glyph, fPreBlend.fG); + RGBToA8(src, glyph, fPreBlend.fG); } } } else { SkASSERT(SkMask::kLCD16_Format == glyph.fMaskFormat); if (fPreBlend.isApplicable()) { if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) { - rgb_to_lcd16(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); + RGBToLcd16(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); } else { - rgb_to_lcd16(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); + RGBToLcd16(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); } } else { if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) { - rgb_to_lcd16(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); + RGBToLcd16(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); } else { - rgb_to_lcd16(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); + RGBToLcd16(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); } } } diff --git a/src/ports/SkScalerContext_win_dw.h b/src/ports/SkScalerContext_win_dw.h index 91f37fc15e..61d6d5b7b1 100644 --- a/src/ports/SkScalerContext_win_dw.h +++ b/src/ports/SkScalerContext_win_dw.h @@ -35,6 +35,22 @@ protected: void generateFontMetrics(SkFontMetrics*) override; private: + static void BilevelToBW(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph); + + template + static void GrayscaleToA8(const uint8_t* SK_RESTRICT src, + const SkGlyph& glyph, + const uint8_t* table8); + + template + static void RGBToA8(const uint8_t* SK_RESTRICT src, + const SkGlyph& glyph, + const uint8_t* table8); + + template + static void RGBToLcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, + const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB); + const void* drawDWMask(const SkGlyph& glyph, DWRITE_RENDERING_MODE renderingMode, DWRITE_TEXTURE_TYPE textureType);