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 "SkGr.h"
12 #include "SkDescriptor.h"
13 #include "SkDistanceFieldGen.h"
14 #include "SkGlyphCache.h"
15
16 class SkGrDescKey : public GrKey {
17 public:
18 explicit SkGrDescKey(const SkDescriptor& desc);
19 virtual ~SkGrDescKey();
20
21 protected:
22 // overrides
23 virtual bool lt(const GrKey& rh) const;
24 virtual bool eq(const GrKey& rh) const;
25
26 private:
27 SkDescriptor* fDesc;
28 enum {
29 kMaxStorageInts = 16
30 };
31 uint32_t fStorage[kMaxStorageInts];
32 };
33
34 ///////////////////////////////////////////////////////////////////////////////
35
SkGrDescKey(const SkDescriptor & desc)36 SkGrDescKey::SkGrDescKey(const SkDescriptor& desc) : GrKey(desc.getChecksum()) {
37 size_t size = desc.getLength();
38 if (size <= sizeof(fStorage)) {
39 fDesc = GrTCast<SkDescriptor*>(fStorage);
40 } else {
41 fDesc = SkDescriptor::Alloc(size);
42 }
43 memcpy(fDesc, &desc, size);
44 }
45
~SkGrDescKey()46 SkGrDescKey::~SkGrDescKey() {
47 if (fDesc != GrTCast<SkDescriptor*>(fStorage)) {
48 SkDescriptor::Free(fDesc);
49 }
50 }
51
lt(const GrKey & rh) const52 bool SkGrDescKey::lt(const GrKey& rh) const {
53 const SkDescriptor* srcDesc = ((const SkGrDescKey*)&rh)->fDesc;
54 size_t lenLH = fDesc->getLength();
55 size_t lenRH = srcDesc->getLength();
56 int cmp = memcmp(fDesc, srcDesc, SkTMin<size_t>(lenLH, lenRH));
57 if (0 == cmp) {
58 return lenLH < lenRH;
59 } else {
60 return cmp < 0;
61 }
62 }
63
eq(const GrKey & rh) const64 bool SkGrDescKey::eq(const GrKey& rh) const {
65 const SkDescriptor* srcDesc = ((const SkGrDescKey*)&rh)->fDesc;
66 return fDesc->equals(*srcDesc);
67 }
68
69 ///////////////////////////////////////////////////////////////////////////////
70
SkGrFontScaler(SkGlyphCache * strike)71 SkGrFontScaler::SkGrFontScaler(SkGlyphCache* strike) {
72 fStrike = strike;
73 fKey = NULL;
74 }
75
~SkGrFontScaler()76 SkGrFontScaler::~SkGrFontScaler() {
77 SkSafeUnref(fKey);
78 }
79
getMaskFormat()80 GrMaskFormat SkGrFontScaler::getMaskFormat() {
81 SkMask::Format format = fStrike->getMaskFormat();
82 switch (format) {
83 case SkMask::kBW_Format:
84 // fall through to kA8 -- we store BW glyphs in our 8-bit cache
85 case SkMask::kA8_Format:
86 return kA8_GrMaskFormat;
87 case SkMask::kLCD16_Format:
88 return kA565_GrMaskFormat;
89 case SkMask::kLCD32_Format:
90 return kA888_GrMaskFormat;
91 case SkMask::kARGB32_Format:
92 return kARGB_GrMaskFormat;
93 default:
94 SkDEBUGFAIL("unsupported SkMask::Format");
95 return kA8_GrMaskFormat;
96 }
97 }
98
getKey()99 const GrKey* SkGrFontScaler::getKey() {
100 if (NULL == fKey) {
101 fKey = SkNEW_ARGS(SkGrDescKey, (fStrike->getDescriptor()));
102 }
103 return fKey;
104 }
105
getPackedGlyphBounds(GrGlyph::PackedID packed,SkIRect * bounds)106 bool SkGrFontScaler::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 SkGrFontScaler::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 SkGrFontScaler::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 case kA888_GrMaskFormat: {
183 uint32_t* rgba8888 = reinterpret_cast<uint32_t*>(dst);
184 expand_bits(rgba8888, bits, width, height, dstRB, srcRB);
185 break;
186 }
187 default:
188 SkFAIL("Invalid GrMaskFormat");
189 }
190 } else if (srcRB == dstRB) {
191 memcpy(dst, src, dstRB * height);
192 } else {
193 const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat());
194 for (int y = 0; y < height; y++) {
195 memcpy(dst, src, width * bbp);
196 src = (const char*)src + srcRB;
197 dst = (char*)dst + dstRB;
198 }
199 }
200 return true;
201 }
202
getPackedGlyphDFImage(GrGlyph::PackedID packed,int width,int height,void * dst)203 bool SkGrFontScaler::getPackedGlyphDFImage(GrGlyph::PackedID packed,
204 int width, int height,
205 void* dst) {
206 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
207 GrGlyph::UnpackFixedX(packed),
208 GrGlyph::UnpackFixedY(packed));
209 SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width);
210 SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height);
211 const void* src = fStrike->findDistanceField(glyph);
212 if (NULL == src) {
213 return false;
214 }
215
216 memcpy(dst, src, width * height);
217
218 return true;
219 }
220
221 // we should just return const SkPath* (NULL means false)
getGlyphPath(uint16_t glyphID,SkPath * path)222 bool SkGrFontScaler::getGlyphPath(uint16_t glyphID, SkPath* path) {
223
224 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID);
225 const SkPath* skPath = fStrike->findPath(glyph);
226 if (skPath) {
227 *path = *skPath;
228 return true;
229 }
230 return false;
231 }
232