Upstream version 9.38.198.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() {
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 bool GrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
89     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
90                                                       GrGlyph::UnpackFixedX(packed),
91                                                       GrGlyph::UnpackFixedY(packed));
92     bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
93
94     return true;
95 }
96
97 bool GrFontScaler::getPackedGlyphDFBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
98     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
99                                                       GrGlyph::UnpackFixedX(packed),
100                                                       GrGlyph::UnpackFixedY(packed));
101     bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
102     bounds->outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
103
104     return true;
105 }
106
107 namespace {
108 // expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to
109 // A8, RGB565, or RGBA8888.
110 template <typename INT_TYPE>
111 void expand_bits(INT_TYPE* dst,
112                  const uint8_t* src,
113                  int width,
114                  int height,
115                  int dstRowBytes,
116                  int srcRowBytes) {
117     for (int i = 0; i < height; ++i) {
118         int rowWritesLeft = width;
119         const uint8_t* s = src;
120         INT_TYPE* d = dst;
121         while (rowWritesLeft > 0) {
122             unsigned mask = *s++;
123             for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) {
124                 *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0;
125             }
126         }
127         dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
128         src += srcRowBytes;
129     }
130 }
131 }
132
133 bool GrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
134                                          int width, int height,
135                                          int dstRB, void* dst) {
136     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
137                                                       GrGlyph::UnpackFixedX(packed),
138                                                       GrGlyph::UnpackFixedY(packed));
139     SkASSERT(glyph.fWidth == width);
140     SkASSERT(glyph.fHeight == height);
141     const void* src = fStrike->findImage(glyph);
142     if (NULL == src) {
143         return false;
144     }
145
146     int srcRB = glyph.rowBytes();
147     // The windows font host sometimes has BW glyphs in a non-BW strike. So it is important here to
148     // check the glyph's format, not the strike's format, and to be able to convert to any of the
149     // GrMaskFormats.
150     if (SkMask::kBW_Format == glyph.fMaskFormat) {
151         // expand bits to our mask type
152         const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
153         switch (this->getMaskFormat()) {
154             case kA8_GrMaskFormat:{
155                 uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
156                 expand_bits(bytes, bits, width, height, dstRB, srcRB);
157                 break;
158             }
159             case kA565_GrMaskFormat: {
160                 uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
161                 expand_bits(rgb565, bits, width, height, dstRB, srcRB);
162                 break;
163             }
164             case kA888_GrMaskFormat: {
165                 uint32_t* rgba8888 = reinterpret_cast<uint32_t*>(dst);
166                 expand_bits(rgba8888, bits, width, height, dstRB, srcRB);
167                 break;
168             }
169             default:
170                 SkFAIL("Invalid GrMaskFormat");
171         }
172     } else if (srcRB == dstRB) {
173         memcpy(dst, src, dstRB * height);
174     } else {
175         const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat());
176         for (int y = 0; y < height; y++) {
177             memcpy(dst, src, width * bbp);
178             src = (const char*)src + srcRB;
179             dst = (char*)dst + dstRB;
180         }
181     }
182     return true;
183 }
184
185 bool GrFontScaler::getPackedGlyphDFImage(GrGlyph::PackedID packed,
186                                            int width, int height,
187                                            void* dst) {
188     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
189                                                       GrGlyph::UnpackFixedX(packed),
190                                                       GrGlyph::UnpackFixedY(packed));
191     SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width);
192     SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height);
193     const void* src = fStrike->findDistanceField(glyph);
194     if (NULL == src) {
195         return false;
196     }
197
198     memcpy(dst, src, width * height);
199
200     return true;
201 }
202
203 // we should just return const SkPath* (NULL means false)
204 bool GrFontScaler::getGlyphPath(uint16_t glyphID, SkPath* path) {
205
206     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID);
207     const SkPath* skPath = fStrike->findPath(glyph);
208     if (skPath) {
209         *path = *skPath;
210         return true;
211     }
212     return false;
213 }