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
GrFontScaler(SkGlyphCache * strike)16 GrFontScaler::GrFontScaler(SkGlyphCache* strike) {
17 fStrike = strike;
18 fKey = nullptr;
19 }
20
~GrFontScaler()21 GrFontScaler::~GrFontScaler() {
22 SkSafeUnref(fKey);
23 }
24
getMaskFormat() const25 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
getKey()42 const GrFontDescKey* GrFontScaler::getKey() {
43 if (nullptr == fKey) {
44 fKey = new GrFontDescKey(fStrike->getDescriptor());
45 }
46 return fKey;
47 }
48
getPackedGlyphMaskFormat(const SkGlyph & glyph) const49 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
getPackedGlyphBounds(const SkGlyph & glyph,SkIRect * bounds)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
getPackedGlyphDFBounds(const SkGlyph & glyph,SkIRect * bounds)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>
expand_bits(INT_TYPE * dst,const uint8_t * src,int width,int height,int dstRowBytes,int srcRowBytes)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
getPackedGlyphImage(const SkGlyph & glyph,int width,int height,int dstRB,GrMaskFormat expectedMaskFormat,void * dst)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
getPackedGlyphDFImage(const SkGlyph & glyph,int width,int height,void * dst)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
getGlyphPath(const SkGlyph & glyph)199 const SkPath* GrFontScaler::getGlyphPath(const SkGlyph& glyph) {
200 return fStrike->findPath(glyph);
201 }
202
grToSkGlyph(GrGlyph::PackedID id)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