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 <bungeman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/core/SkGlyph.h b/src/core/SkGlyph.h
index de915c2..dacabb4 100644
--- a/src/core/SkGlyph.h
+++ b/src/core/SkGlyph.h
@@ -118,16 +118,13 @@
 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 @@
     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 @@
 
     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 @@
         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 @@
     // 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 01ccec6..e41e368 100644
--- a/src/core/SkStrike.cpp
+++ b/src/core/SkStrike.cpp
@@ -237,7 +237,7 @@
     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 cc46338..04a6a02 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -1318,15 +1318,11 @@
 #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 @@
     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 4d9ecef..723d77b 100644
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -941,6 +941,20 @@
 
 private:
     static void CTPathElement(void *info, const CGPathElement *element);
+    template<bool APPLY_PREBLEND>
+    static void RGBToA8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes,
+                        const SkGlyph& glyph, const uint8_t* table8);
+    template<bool APPLY_PREBLEND>
+    static uint16_t RGBToLcd16(CGRGBPixel rgb, const uint8_t* tableR,
+                               const uint8_t* tableG,
+                               const uint8_t* tableB);
+    template<bool APPLY_PREBLEND>
+    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 @@
     }
 
     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* 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 @@
         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 @@
 #endif
     return lum;
 }
+
 template<bool APPLY_PREBLEND>
-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 @@
 }
 
 template<bool APPLY_PREBLEND>
-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<APPLY_PREBLEND>(0xFF - ((rgb >> 16) & 0xFF), tableR);
     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >>  8) & 0xFF), tableG);
     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >>  0) & 0xFF), tableB);
@@ -1301,16 +1316,21 @@
 #endif
     return SkPack888ToRGB16(r, g, b);
 }
+
 template<bool APPLY_PREBLEND>
-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<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB);
+            dst[i] = RGBToLcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB);
         }
         cgPixels = SkTAddOffset<const CGRGBPixel>(cgPixels, cgRowBytes);
         dst = SkTAddOffset<uint16_t>(dst, dstRB);
@@ -1370,18 +1390,18 @@
     switch (glyph.fMaskFormat) {
         case SkMask::kLCD16_Format: {
             if (fPreBlend.isApplicable()) {
-                rgb_to_lcd16<true>(cgPixels, cgRowBytes, glyph,
-                                   fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+                RGBToLcd16<true>(cgPixels, cgRowBytes, glyph,
+                                 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
             } else {
-                rgb_to_lcd16<false>(cgPixels, cgRowBytes, glyph,
-                                    fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+                RGBToLcd16<false>(cgPixels, cgRowBytes, glyph,
+                                  fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
             }
         } break;
         case SkMask::kA8_Format: {
             if (fPreBlend.isApplicable()) {
-                rgb_to_a8<true>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
+                RGBToA8<true>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
             } else {
-                rgb_to_a8<false>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
+                RGBToA8<false>(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 be783cd..7ebfd1e 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -483,14 +483,14 @@
         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 @@
     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 @@
     }
     *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 @@
 private:
     DWORD getGDIGlyphPath(SkGlyphID glyph, UINT flags,
                           SkAutoSTMalloc<BUFFERSIZE, uint8_t>* glyphbuf);
+    template<bool APPLY_PREBLEND>
+    static void RGBToA8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
+                        const SkGlyph& glyph, const uint8_t* table8);
+
+    template<bool APPLY_PREBLEND>
+    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 @@
         // 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 @@
 }
 
 template<bool APPLY_PREBLEND>
-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 @@
 }
 
 template<bool APPLY_PREBLEND>
-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 @@
         //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 @@
             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 @@
         // ... until we have the caller tell us that explicitly
         const SkGdiRGB* src = (const SkGdiRGB*)bits;
         if (fPreBlend.isApplicable()) {
-            rgb_to_a8<true>(src, srcRB, glyph, fPreBlend.fG);
+            RGBToA8<true>(src, srcRB, glyph, fPreBlend.fG);
         } else {
-            rgb_to_a8<false>(src, srcRB, glyph, fPreBlend.fG);
+            RGBToA8<false>(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<true>(src, srcRB, glyph,
-                               fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+            RGBToLcd16<true>(src, srcRB, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
         } else {
-            rgb_to_lcd16<false>(src, srcRB, glyph,
-                                fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+            RGBToLcd16<false>(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 f80376e..f4e8be8 100644
--- a/src/ports/SkScalerContext_win_dw.cpp
+++ b/src/ports/SkScalerContext_win_dw.cpp
@@ -490,30 +490,6 @@
     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<IDWriteColorGlyphRunEnumerator> colorLayer;
     return getColorGlyphRun(glyph, &colorLayer);
@@ -673,6 +649,31 @@
 }
 
 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 @@
     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 @@
                                   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 @@
 
 #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<uint8_t*>(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 @@
 }
 
 template<bool APPLY_PREBLEND>
-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<uint8_t*>(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<APPLY_PREBLEND>(a, table8);
         }
@@ -849,13 +851,15 @@
 }
 
 template<bool APPLY_PREBLEND>
-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<uint8_t*>(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 @@
 }
 
 template<bool APPLY_PREBLEND, bool RGB>
-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<uint16_t*>(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<APPLY_PREBLEND>(*(src++), tableR);
@@ -894,7 +899,7 @@
                                            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 @@
         //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 @@
     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 @@
     sk_sp<SkImage> 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 @@
 
     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 @@
     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<true>(src, glyph, fPreBlend.fG);
+                GrayscaleToA8<true>(src, glyph, fPreBlend.fG);
             } else {
-                grayscale_to_a8<false>(src, glyph, fPreBlend.fG);
+                GrayscaleToA8<false>(src, glyph, fPreBlend.fG);
             }
         } else {
             if (fPreBlend.isApplicable()) {
-                rgb_to_a8<true>(src, glyph, fPreBlend.fG);
+                RGBToA8<true>(src, glyph, fPreBlend.fG);
             } else {
-                rgb_to_a8<false>(src, glyph, fPreBlend.fG);
+                RGBToA8<false>(src, glyph, fPreBlend.fG);
             }
         }
     } else {
         SkASSERT(SkMask::kLCD16_Format == glyph.fMaskFormat);
         if (fPreBlend.isApplicable()) {
             if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) {
-                rgb_to_lcd16<true, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+                RGBToLcd16<true, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
             } else {
-                rgb_to_lcd16<true, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+                RGBToLcd16<true, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
             }
         } else {
             if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) {
-                rgb_to_lcd16<false, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+                RGBToLcd16<false, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
             } else {
-                rgb_to_lcd16<false, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+                RGBToLcd16<false, true>(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 91f37fc..61d6d5b 100644
--- a/src/ports/SkScalerContext_win_dw.h
+++ b/src/ports/SkScalerContext_win_dw.h
@@ -35,6 +35,22 @@
     void generateFontMetrics(SkFontMetrics*) override;
 
 private:
+    static void BilevelToBW(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph);
+
+    template<bool APPLY_PREBLEND>
+    static void GrayscaleToA8(const uint8_t* SK_RESTRICT src,
+                              const SkGlyph& glyph,
+                              const uint8_t* table8);
+
+    template<bool APPLY_PREBLEND>
+    static void RGBToA8(const uint8_t* SK_RESTRICT src,
+                        const SkGlyph& glyph,
+                        const uint8_t* table8);
+
+    template<bool APPLY_PREBLEND, bool RGB>
+    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);