1 2 /* 3 * Copyright 2010 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 #include "GrFontScaler.h" 10 #include "SkDescriptor.h" 11 #include "SkDistanceFieldGen.h" 12 #include "SkGlyphCache.h" 13 14 /////////////////////////////////////////////////////////////////////////////// 15 16 GrFontScaler::GrFontScaler(SkGlyphCache* strike) { 17 fStrike = strike; 18 fKey = nullptr; 19 } 20 21 GrFontScaler::~GrFontScaler() { 22 SkSafeUnref(fKey); 23 } 24 25 GrMaskFormat GrFontScaler::getMaskFormat() const { 26 SkMask::Format format = fStrike->getMaskFormat(); 27 switch (format) { 28 case SkMask::kBW_Format: 29 // fall through to kA8 -- we store BW glyphs in our 8-bit cache 30 case SkMask::kA8_Format: 31 return kA8_GrMaskFormat; 32 case SkMask::kLCD16_Format: 33 return kA565_GrMaskFormat; 34 case SkMask::kARGB32_Format: 35 return kARGB_GrMaskFormat; 36 default: 37 SkDEBUGFAIL("unsupported SkMask::Format"); 38 return kA8_GrMaskFormat; 39 } 40 } 41 42 const GrFontDescKey* GrFontScaler::getKey() { 43 if (nullptr == fKey) { 44 fKey = new GrFontDescKey(fStrike->getDescriptor()); 45 } 46 return fKey; 47 } 48 49 GrMaskFormat GrFontScaler::getPackedGlyphMaskFormat(const SkGlyph& glyph) const { 50 SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); 51 switch (format) { 52 case SkMask::kBW_Format: 53 // fall through to kA8 -- we store BW glyphs in our 8-bit cache 54 case SkMask::kA8_Format: 55 return kA8_GrMaskFormat; 56 case SkMask::kLCD16_Format: 57 return kA565_GrMaskFormat; 58 case SkMask::kARGB32_Format: 59 return kARGB_GrMaskFormat; 60 default: 61 SkDEBUGFAIL("unsupported SkMask::Format"); 62 return kA8_GrMaskFormat; 63 } 64 } 65 66 bool GrFontScaler::getPackedGlyphBounds(const SkGlyph& glyph, SkIRect* bounds) { 67 #if 1 68 // crbug:510931 69 // Retrieving the image from the cache can actually change the mask format. 70 fStrike->findImage(glyph); 71 #endif 72 bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight); 73 74 return true; 75 } 76 77 bool GrFontScaler::getPackedGlyphDFBounds(const SkGlyph& glyph, SkIRect* bounds) { 78 #if 1 79 // crbug:510931 80 // Retrieving the image from the cache can actually change the mask format. 81 fStrike->findImage(glyph); 82 #endif 83 bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight); 84 bounds->outset(SK_DistanceFieldPad, SK_DistanceFieldPad); 85 86 return true; 87 } 88 89 namespace { 90 // expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to 91 // A8, RGB565, or RGBA8888. 92 template <typename INT_TYPE> 93 void expand_bits(INT_TYPE* dst, 94 const uint8_t* src, 95 int width, 96 int height, 97 int dstRowBytes, 98 int srcRowBytes) { 99 for (int i = 0; i < height; ++i) { 100 int rowWritesLeft = width; 101 const uint8_t* s = src; 102 INT_TYPE* d = dst; 103 while (rowWritesLeft > 0) { 104 unsigned mask = *s++; 105 for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) { 106 *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0; 107 } 108 } 109 dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes); 110 src += srcRowBytes; 111 } 112 } 113 } 114 115 bool GrFontScaler::getPackedGlyphImage(const SkGlyph& glyph, int width, int height, int dstRB, 116 GrMaskFormat expectedMaskFormat, void* dst) { 117 SkASSERT(glyph.fWidth == width); 118 SkASSERT(glyph.fHeight == height); 119 const void* src = fStrike->findImage(glyph); 120 if (nullptr == src) { 121 return false; 122 } 123 124 // crbug:510931 125 // Retrieving the image from the cache can actually change the mask format. This case is very 126 // uncommon so for now we just draw a clear box for these glyphs. 127 if (getPackedGlyphMaskFormat(glyph) != expectedMaskFormat) { 128 const int bpp = GrMaskFormatBytesPerPixel(expectedMaskFormat); 129 for (int y = 0; y < height; y++) { 130 sk_bzero(dst, width * bpp); 131 dst = (char*)dst + dstRB; 132 } 133 return true; 134 } 135 136 int srcRB = glyph.rowBytes(); 137 // The windows font host sometimes has BW glyphs in a non-BW strike. So it is important here to 138 // check the glyph's format, not the strike's format, and to be able to convert to any of the 139 // GrMaskFormats. 140 if (SkMask::kBW_Format == glyph.fMaskFormat) { 141 // expand bits to our mask type 142 const uint8_t* bits = reinterpret_cast<const uint8_t*>(src); 143 switch (expectedMaskFormat) { 144 case kA8_GrMaskFormat:{ 145 uint8_t* bytes = reinterpret_cast<uint8_t*>(dst); 146 expand_bits(bytes, bits, width, height, dstRB, srcRB); 147 break; 148 } 149 case kA565_GrMaskFormat: { 150 uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst); 151 expand_bits(rgb565, bits, width, height, dstRB, srcRB); 152 break; 153 } 154 default: 155 SkFAIL("Invalid GrMaskFormat"); 156 } 157 } else if (srcRB == dstRB) { 158 memcpy(dst, src, dstRB * height); 159 } else { 160 const int bbp = GrMaskFormatBytesPerPixel(expectedMaskFormat); 161 for (int y = 0; y < height; y++) { 162 memcpy(dst, src, width * bbp); 163 src = (const char*)src + srcRB; 164 dst = (char*)dst + dstRB; 165 } 166 } 167 return true; 168 } 169 170 bool GrFontScaler::getPackedGlyphDFImage(const SkGlyph& glyph, int width, int height, void* dst) { 171 SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width); 172 SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height); 173 const void* image = fStrike->findImage(glyph); 174 if (nullptr == image) { 175 return false; 176 } 177 // now generate the distance field 178 SkASSERT(dst); 179 SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 180 if (SkMask::kA8_Format == maskFormat) { 181 // make the distance field from the image 182 SkGenerateDistanceFieldFromA8Image((unsigned char*)dst, 183 (unsigned char*)image, 184 glyph.fWidth, glyph.fHeight, 185 glyph.rowBytes()); 186 } else if (SkMask::kBW_Format == maskFormat) { 187 // make the distance field from the image 188 SkGenerateDistanceFieldFromBWImage((unsigned char*)dst, 189 (unsigned char*)image, 190 glyph.fWidth, glyph.fHeight, 191 glyph.rowBytes()); 192 } else { 193 return false; 194 } 195 196 return true; 197 } 198 199 const SkPath* GrFontScaler::getGlyphPath(const SkGlyph& glyph) { 200 return fStrike->findPath(glyph); 201 } 202 203 const SkGlyph& GrFontScaler::grToSkGlyph(GrGlyph::PackedID id) { 204 return fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(id), 205 GrGlyph::UnpackFixedX(id), 206 GrGlyph::UnpackFixedY(id)); 207 } 208