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 "SkGlyphCache.h"
14
15 class SkGrDescKey : public GrKey {
16 public:
17 explicit SkGrDescKey(const SkDescriptor& desc);
18 virtual ~SkGrDescKey();
19
20 protected:
21 // overrides
22 virtual bool lt(const GrKey& rh) const;
23 virtual bool eq(const GrKey& rh) const;
24
25 private:
26 SkDescriptor* fDesc;
27 enum {
28 kMaxStorageInts = 16
29 };
30 uint32_t fStorage[kMaxStorageInts];
31 };
32
33 ///////////////////////////////////////////////////////////////////////////////
34
SkGrDescKey(const SkDescriptor & desc)35 SkGrDescKey::SkGrDescKey(const SkDescriptor& desc) : GrKey(desc.getChecksum()) {
36 size_t size = desc.getLength();
37 if (size <= sizeof(fStorage)) {
38 fDesc = GrTCast<SkDescriptor*>(fStorage);
39 } else {
40 fDesc = SkDescriptor::Alloc(size);
41 }
42 memcpy(fDesc, &desc, size);
43 }
44
~SkGrDescKey()45 SkGrDescKey::~SkGrDescKey() {
46 if (fDesc != GrTCast<SkDescriptor*>(fStorage)) {
47 SkDescriptor::Free(fDesc);
48 }
49 }
50
lt(const GrKey & rh) const51 bool SkGrDescKey::lt(const GrKey& rh) const {
52 const SkDescriptor* srcDesc = ((const SkGrDescKey*)&rh)->fDesc;
53 size_t lenLH = fDesc->getLength();
54 size_t lenRH = srcDesc->getLength();
55 int cmp = memcmp(fDesc, srcDesc, SkMin32(lenLH, lenRH));
56 if (0 == cmp) {
57 return lenLH < lenRH;
58 } else {
59 return cmp < 0;
60 }
61 }
62
eq(const GrKey & rh) const63 bool SkGrDescKey::eq(const GrKey& rh) const {
64 const SkDescriptor* srcDesc = ((const SkGrDescKey*)&rh)->fDesc;
65 return fDesc->equals(*srcDesc);
66 }
67
68 ///////////////////////////////////////////////////////////////////////////////
69
SkGrFontScaler(SkGlyphCache * strike)70 SkGrFontScaler::SkGrFontScaler(SkGlyphCache* strike) {
71 fStrike = strike;
72 fKey = NULL;
73 }
74
~SkGrFontScaler()75 SkGrFontScaler::~SkGrFontScaler() {
76 GrSafeUnref(fKey);
77 }
78
getMaskFormat()79 GrMaskFormat SkGrFontScaler::getMaskFormat() {
80 SkMask::Format format = fStrike->getMaskFormat();
81 switch (format) {
82 case SkMask::kBW_Format:
83 // fall through to kA8 -- we store BW glyphs in our 8-bit cache
84 case SkMask::kA8_Format:
85 return kA8_GrMaskFormat;
86 case SkMask::kLCD16_Format:
87 return kA565_GrMaskFormat;
88 case SkMask::kLCD32_Format:
89 return kA888_GrMaskFormat;
90 default:
91 GrAssert(!"unsupported SkMask::Format");
92 return kA8_GrMaskFormat;
93 }
94 }
95
getKey()96 const GrKey* SkGrFontScaler::getKey() {
97 if (NULL == fKey) {
98 fKey = SkNEW_ARGS(SkGrDescKey, (fStrike->getDescriptor()));
99 }
100 return fKey;
101 }
102
getPackedGlyphBounds(GrGlyph::PackedID packed,GrIRect * bounds)103 bool SkGrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed,
104 GrIRect* bounds) {
105 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
106 GrGlyph::UnpackFixedX(packed),
107 GrGlyph::UnpackFixedY(packed));
108 bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
109 return true;
110
111 }
112
113 namespace {
114 // expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to
115 // A8, RGB565, or RGBA8888.
116 template <typename INT_TYPE>
expand_bits(INT_TYPE * dst,const uint8_t * src,int width,int height,int dstRowBytes,int srcRowBytes)117 void expand_bits(INT_TYPE* dst,
118 const uint8_t* src,
119 int width,
120 int height,
121 int dstRowBytes,
122 int srcRowBytes) {
123 for (int i = 0; i < height; ++i) {
124 int rowWritesLeft = width;
125 const uint8_t* s = src;
126 INT_TYPE* d = dst;
127 while (rowWritesLeft > 0) {
128 unsigned mask = *s++;
129 for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) {
130 *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0;
131 }
132 }
133 dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
134 src += srcRowBytes;
135 }
136 }
137 }
138
getPackedGlyphImage(GrGlyph::PackedID packed,int width,int height,int dstRB,void * dst)139 bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
140 int width, int height,
141 int dstRB, void* dst) {
142 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
143 GrGlyph::UnpackFixedX(packed),
144 GrGlyph::UnpackFixedY(packed));
145 GrAssert(glyph.fWidth == width);
146 GrAssert(glyph.fHeight == height);
147 const void* src = fStrike->findImage(glyph);
148 if (NULL == src) {
149 return false;
150 }
151
152 int srcRB = glyph.rowBytes();
153 // The windows font host sometimes has BW glyphs in a non-BW strike. So it is important here to
154 // check the glyph's format, not the strike's format, and to be able to convert to any of the
155 // GrMaskFormats.
156 if (SkMask::kBW_Format == glyph.fMaskFormat) {
157 // expand bits to our mask type
158 const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
159 switch (this->getMaskFormat()) {
160 case kA8_GrMaskFormat:{
161 uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
162 expand_bits(bytes, bits, width, height, dstRB, srcRB);
163 break;
164 }
165 case kA565_GrMaskFormat: {
166 uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
167 expand_bits(rgb565, bits, width, height, dstRB, srcRB);
168 break;
169 }
170 case kA888_GrMaskFormat: {
171 uint32_t* rgba8888 = reinterpret_cast<uint32_t*>(dst);
172 expand_bits(rgba8888, bits, width, height, dstRB, srcRB);
173 break;
174 }
175 default:
176 GrCrash("Unknown GrMaskFormat");
177 }
178 } else if (srcRB == dstRB) {
179 memcpy(dst, src, dstRB * height);
180 } else {
181 const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat());
182 for (int y = 0; y < height; y++) {
183 memcpy(dst, src, width * bbp);
184 src = (const char*)src + srcRB;
185 dst = (char*)dst + dstRB;
186 }
187 }
188 return true;
189 }
190
191 // we should just return const SkPath* (NULL means false)
getGlyphPath(uint16_t glyphID,SkPath * path)192 bool SkGrFontScaler::getGlyphPath(uint16_t glyphID, SkPath* path) {
193
194 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID);
195 const SkPath* skPath = fStrike->findPath(glyph);
196 if (skPath) {
197 *path = *skPath;
198 return true;
199 }
200 return false;
201 }
202