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 
10 #include "GrTemplates.h"
11 #include "GrFontScaler.h"
12 #include "SkDescriptor.h"
13 #include "SkDistanceFieldGen.h"
14 #include "SkGlyphCache.h"
15 
16 ///////////////////////////////////////////////////////////////////////////////
17 
GrFontDescKey(const SkDescriptor & desc)18 GrFontDescKey::GrFontDescKey(const SkDescriptor& desc) : fHash(desc.getChecksum()) {
19     size_t size = desc.getLength();
20     if (size <= sizeof(fStorage)) {
21         fDesc = GrTCast<SkDescriptor*>(fStorage);
22     } else {
23         fDesc = SkDescriptor::Alloc(size);
24     }
25     memcpy(fDesc, &desc, size);
26 }
27 
~GrFontDescKey()28 GrFontDescKey::~GrFontDescKey() {
29     if (fDesc != GrTCast<SkDescriptor*>(fStorage)) {
30         SkDescriptor::Free(fDesc);
31     }
32 }
33 
lt(const GrFontDescKey & rh) const34 bool GrFontDescKey::lt(const GrFontDescKey& rh) const {
35     const SkDescriptor* srcDesc = (&rh)->fDesc;
36     size_t lenLH = fDesc->getLength();
37     size_t lenRH = srcDesc->getLength();
38     int cmp = memcmp(fDesc, srcDesc, SkTMin<size_t>(lenLH, lenRH));
39     if (0 == cmp) {
40         return lenLH < lenRH;
41     } else {
42         return cmp < 0;
43     }
44 }
45 
eq(const GrFontDescKey & rh) const46 bool GrFontDescKey::eq(const GrFontDescKey& rh) const {
47     const SkDescriptor* srcDesc = (&rh)->fDesc;
48     return fDesc->equals(*srcDesc);
49 }
50 
51 ///////////////////////////////////////////////////////////////////////////////
52 
GrFontScaler(SkGlyphCache * strike)53 GrFontScaler::GrFontScaler(SkGlyphCache* strike) {
54     fStrike = strike;
55     fKey = NULL;
56 }
57 
~GrFontScaler()58 GrFontScaler::~GrFontScaler() {
59     SkSafeUnref(fKey);
60 }
61 
getMaskFormat() const62 GrMaskFormat GrFontScaler::getMaskFormat() const {
63     SkMask::Format format = fStrike->getMaskFormat();
64     switch (format) {
65         case SkMask::kBW_Format:
66             // fall through to kA8 -- we store BW glyphs in our 8-bit cache
67         case SkMask::kA8_Format:
68             return kA8_GrMaskFormat;
69         case SkMask::kLCD16_Format:
70             return kA565_GrMaskFormat;
71         case SkMask::kARGB32_Format:
72             return kARGB_GrMaskFormat;
73         default:
74             SkDEBUGFAIL("unsupported SkMask::Format");
75             return kA8_GrMaskFormat;
76     }
77 }
78 
getKey()79 const GrFontDescKey* GrFontScaler::getKey() {
80     if (NULL == fKey) {
81         fKey = SkNEW_ARGS(GrFontDescKey, (fStrike->getDescriptor()));
82     }
83     return fKey;
84 }
85 
getPackedGlyphMaskFormat(GrGlyph::PackedID packed) const86 GrMaskFormat GrFontScaler::getPackedGlyphMaskFormat(GrGlyph::PackedID packed) const {
87     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
88                                                       GrGlyph::UnpackFixedX(packed),
89                                                       GrGlyph::UnpackFixedY(packed));
90     SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
91     switch (format) {
92         case SkMask::kBW_Format:
93             // fall through to kA8 -- we store BW glyphs in our 8-bit cache
94         case SkMask::kA8_Format:
95             return kA8_GrMaskFormat;
96         case SkMask::kLCD16_Format:
97             return kA565_GrMaskFormat;
98         case SkMask::kARGB32_Format:
99             return kARGB_GrMaskFormat;
100         default:
101             SkDEBUGFAIL("unsupported SkMask::Format");
102             return kA8_GrMaskFormat;
103     }
104 }
105 
getPackedGlyphBounds(GrGlyph::PackedID packed,SkIRect * bounds)106 bool GrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
107     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
108                                                       GrGlyph::UnpackFixedX(packed),
109                                                       GrGlyph::UnpackFixedY(packed));
110     bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
111 
112     return true;
113 }
114 
getPackedGlyphDFBounds(GrGlyph::PackedID packed,SkIRect * bounds)115 bool GrFontScaler::getPackedGlyphDFBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
116     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
117                                                       GrGlyph::UnpackFixedX(packed),
118                                                       GrGlyph::UnpackFixedY(packed));
119     bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
120     bounds->outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
121 
122     return true;
123 }
124 
125 namespace {
126 // expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to
127 // A8, RGB565, or RGBA8888.
128 template <typename INT_TYPE>
expand_bits(INT_TYPE * dst,const uint8_t * src,int width,int height,int dstRowBytes,int srcRowBytes)129 void expand_bits(INT_TYPE* dst,
130                  const uint8_t* src,
131                  int width,
132                  int height,
133                  int dstRowBytes,
134                  int srcRowBytes) {
135     for (int i = 0; i < height; ++i) {
136         int rowWritesLeft = width;
137         const uint8_t* s = src;
138         INT_TYPE* d = dst;
139         while (rowWritesLeft > 0) {
140             unsigned mask = *s++;
141             for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) {
142                 *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0;
143             }
144         }
145         dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
146         src += srcRowBytes;
147     }
148 }
149 }
150 
getPackedGlyphImage(GrGlyph::PackedID packed,int width,int height,int dstRB,void * dst)151 bool GrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
152                                          int width, int height,
153                                          int dstRB, void* dst) {
154     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
155                                                       GrGlyph::UnpackFixedX(packed),
156                                                       GrGlyph::UnpackFixedY(packed));
157     SkASSERT(glyph.fWidth == width);
158     SkASSERT(glyph.fHeight == height);
159     const void* src = fStrike->findImage(glyph);
160     if (NULL == src) {
161         return false;
162     }
163 
164     int srcRB = glyph.rowBytes();
165     // The windows font host sometimes has BW glyphs in a non-BW strike. So it is important here to
166     // check the glyph's format, not the strike's format, and to be able to convert to any of the
167     // GrMaskFormats.
168     if (SkMask::kBW_Format == glyph.fMaskFormat) {
169         // expand bits to our mask type
170         const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
171         switch (this->getMaskFormat()) {
172             case kA8_GrMaskFormat:{
173                 uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
174                 expand_bits(bytes, bits, width, height, dstRB, srcRB);
175                 break;
176             }
177             case kA565_GrMaskFormat: {
178                 uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
179                 expand_bits(rgb565, bits, width, height, dstRB, srcRB);
180                 break;
181             }
182             default:
183                 SkFAIL("Invalid GrMaskFormat");
184         }
185     } else if (srcRB == dstRB) {
186         memcpy(dst, src, dstRB * height);
187     } else {
188         const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat());
189         for (int y = 0; y < height; y++) {
190             memcpy(dst, src, width * bbp);
191             src = (const char*)src + srcRB;
192             dst = (char*)dst + dstRB;
193         }
194     }
195     return true;
196 }
197 
getPackedGlyphDFImage(GrGlyph::PackedID packed,int width,int height,void * dst)198 bool GrFontScaler::getPackedGlyphDFImage(GrGlyph::PackedID packed,
199                                          int width, int height,
200                                          void* dst) {
201     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
202                                                       GrGlyph::UnpackFixedX(packed),
203                                                       GrGlyph::UnpackFixedY(packed));
204     SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width);
205     SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height);
206     const void* image = fStrike->findImage(glyph);
207     if (NULL == image) {
208         return false;
209     }
210     // now generate the distance field
211     SkASSERT(dst);
212     SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
213     if (SkMask::kA8_Format == maskFormat) {
214         // make the distance field from the image
215         SkGenerateDistanceFieldFromA8Image((unsigned char*)dst,
216                                            (unsigned char*)image,
217                                            glyph.fWidth, glyph.fHeight,
218                                            glyph.rowBytes());
219     } else if (SkMask::kBW_Format == maskFormat) {
220         // make the distance field from the image
221         SkGenerateDistanceFieldFromBWImage((unsigned char*)dst,
222                                            (unsigned char*)image,
223                                            glyph.fWidth, glyph.fHeight,
224                                            glyph.rowBytes());
225     } else {
226         return false;
227     }
228 
229     return true;
230 }
231 
232 // we should just return const SkPath* (NULL means false)
getGlyphPath(uint16_t glyphID,SkPath * path)233 bool GrFontScaler::getGlyphPath(uint16_t glyphID, SkPath* path) {
234 
235     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID);
236     const SkPath* skPath = fStrike->findPath(glyph);
237     if (skPath) {
238         *path = *skPath;
239         return true;
240     }
241     return false;
242 }
243