Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrFontScaler.cpp
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
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
28 GrFontDescKey::~GrFontDescKey() {
29     if (fDesc != GrTCast<SkDescriptor*>(fStorage)) {
30         SkDescriptor::Free(fDesc);
31     }
32 }
33
34 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
46 bool GrFontDescKey::eq(const GrFontDescKey& rh) const {
47     const SkDescriptor* srcDesc = (&rh)->fDesc;
48     return fDesc->equals(*srcDesc);
49 }
50
51 ///////////////////////////////////////////////////////////////////////////////
52
53 GrFontScaler::GrFontScaler(SkGlyphCache* strike) {
54     fStrike = strike;
55     fKey = NULL;
56 }
57
58 GrFontScaler::~GrFontScaler() {
59     SkSafeUnref(fKey);
60 }
61
62 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::kLCD32_Format:
72             return kA888_GrMaskFormat;
73         case SkMask::kARGB32_Format:
74             return kARGB_GrMaskFormat;
75         default:
76             SkDEBUGFAIL("unsupported SkMask::Format");
77             return kA8_GrMaskFormat;
78     }
79 }
80
81 const GrFontDescKey* GrFontScaler::getKey() {
82     if (NULL == fKey) {
83         fKey = SkNEW_ARGS(GrFontDescKey, (fStrike->getDescriptor()));
84     }
85     return fKey;
86 }
87
88 GrMaskFormat GrFontScaler::getPackedGlyphMaskFormat(GrGlyph::PackedID packed) const {
89     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
90                                                       GrGlyph::UnpackFixedX(packed),
91                                                       GrGlyph::UnpackFixedY(packed));
92     SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
93     switch (format) {
94         case SkMask::kBW_Format:
95             // fall through to kA8 -- we store BW glyphs in our 8-bit cache
96         case SkMask::kA8_Format:
97             return kA8_GrMaskFormat;
98         case SkMask::kLCD16_Format:
99             return kA565_GrMaskFormat;
100         case SkMask::kLCD32_Format:
101             return kA888_GrMaskFormat;
102         case SkMask::kARGB32_Format:
103             return kARGB_GrMaskFormat;
104         default:
105             SkDEBUGFAIL("unsupported SkMask::Format");
106             return kA8_GrMaskFormat;
107     }
108 }
109
110 bool GrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
111     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
112                                                       GrGlyph::UnpackFixedX(packed),
113                                                       GrGlyph::UnpackFixedY(packed));
114     bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
115
116     return true;
117 }
118
119 bool GrFontScaler::getPackedGlyphDFBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
120     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
121                                                       GrGlyph::UnpackFixedX(packed),
122                                                       GrGlyph::UnpackFixedY(packed));
123     bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
124     bounds->outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
125
126     return true;
127 }
128
129 namespace {
130 // expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to
131 // A8, RGB565, or RGBA8888.
132 template <typename INT_TYPE>
133 void expand_bits(INT_TYPE* dst,
134                  const uint8_t* src,
135                  int width,
136                  int height,
137                  int dstRowBytes,
138                  int srcRowBytes) {
139     for (int i = 0; i < height; ++i) {
140         int rowWritesLeft = width;
141         const uint8_t* s = src;
142         INT_TYPE* d = dst;
143         while (rowWritesLeft > 0) {
144             unsigned mask = *s++;
145             for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) {
146                 *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0;
147             }
148         }
149         dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
150         src += srcRowBytes;
151     }
152 }
153 }
154
155 bool GrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
156                                          int width, int height,
157                                          int dstRB, void* dst) {
158     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
159                                                       GrGlyph::UnpackFixedX(packed),
160                                                       GrGlyph::UnpackFixedY(packed));
161     SkASSERT(glyph.fWidth == width);
162     SkASSERT(glyph.fHeight == height);
163     const void* src = fStrike->findImage(glyph);
164     if (NULL == src) {
165         return false;
166     }
167
168     int srcRB = glyph.rowBytes();
169     // The windows font host sometimes has BW glyphs in a non-BW strike. So it is important here to
170     // check the glyph's format, not the strike's format, and to be able to convert to any of the
171     // GrMaskFormats.
172     if (SkMask::kBW_Format == glyph.fMaskFormat) {
173         // expand bits to our mask type
174         const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
175         switch (this->getMaskFormat()) {
176             case kA8_GrMaskFormat:{
177                 uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
178                 expand_bits(bytes, bits, width, height, dstRB, srcRB);
179                 break;
180             }
181             case kA565_GrMaskFormat: {
182                 uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
183                 expand_bits(rgb565, bits, width, height, dstRB, srcRB);
184                 break;
185             }
186             case kA888_GrMaskFormat: {
187                 uint32_t* rgba8888 = reinterpret_cast<uint32_t*>(dst);
188                 expand_bits(rgba8888, bits, width, height, dstRB, srcRB);
189                 break;
190             }
191             default:
192                 SkFAIL("Invalid GrMaskFormat");
193         }
194     } else if (srcRB == dstRB) {
195         memcpy(dst, src, dstRB * height);
196     } else {
197         const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat());
198         for (int y = 0; y < height; y++) {
199             memcpy(dst, src, width * bbp);
200             src = (const char*)src + srcRB;
201             dst = (char*)dst + dstRB;
202         }
203     }
204     return true;
205 }
206
207 bool GrFontScaler::getPackedGlyphDFImage(GrGlyph::PackedID packed,
208                                            int width, int height,
209                                            void* dst) {
210     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
211                                                       GrGlyph::UnpackFixedX(packed),
212                                                       GrGlyph::UnpackFixedY(packed));
213     SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width);
214     SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height);
215     const void* src = fStrike->findDistanceField(glyph);
216     if (NULL == src) {
217         return false;
218     }
219
220     memcpy(dst, src, width * height);
221
222     return true;
223 }
224
225 // we should just return const SkPath* (NULL means false)
226 bool GrFontScaler::getGlyphPath(uint16_t glyphID, SkPath* path) {
227
228     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID);
229     const SkPath* skPath = fStrike->findPath(glyph);
230     if (skPath) {
231         *path = *skPath;
232         return true;
233     }
234     return false;
235 }