blob: eb260fb826d79fe45e7ae167e6e3554cc186f903 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "SkGr.h"
19#include "SkDescriptor.h"
20#include "SkGlyphCache.h"
21
22class SkGrDescKey : public GrKey {
23public:
24 explicit SkGrDescKey(const SkDescriptor& desc);
25 virtual ~SkGrDescKey();
reed@google.com1fcd51e2011-01-05 15:50:27 +000026
reed@google.comac10a2d2010-12-22 21:39:39 +000027protected:
28 // overrides
29 virtual bool lt(const GrKey& rh) const;
30 virtual bool eq(const GrKey& rh) const;
reed@google.com1fcd51e2011-01-05 15:50:27 +000031
reed@google.comac10a2d2010-12-22 21:39:39 +000032private:
33 SkDescriptor* fDesc;
34 enum {
35 kMaxStorageInts = 16
36 };
37 uint32_t fStorage[kMaxStorageInts];
38};
39
40///////////////////////////////////////////////////////////////////////////////
41
42SkGrDescKey::SkGrDescKey(const SkDescriptor& desc) : GrKey(desc.getChecksum()) {
43 size_t size = desc.getLength();
44 if (size <= sizeof(fStorage)) {
reed@google.com1fcd51e2011-01-05 15:50:27 +000045 fDesc = GrTCast<SkDescriptor*>(fStorage);
reed@google.comac10a2d2010-12-22 21:39:39 +000046 } else {
47 fDesc = SkDescriptor::Alloc(size);
48 }
49 memcpy(fDesc, &desc, size);
50}
51
52SkGrDescKey::~SkGrDescKey() {
reed@google.com1fcd51e2011-01-05 15:50:27 +000053 if (fDesc != GrTCast<SkDescriptor*>(fStorage)) {
reed@google.comac10a2d2010-12-22 21:39:39 +000054 SkDescriptor::Free(fDesc);
55 }
56}
57
58bool SkGrDescKey::lt(const GrKey& rh) const {
59 const SkDescriptor* srcDesc = ((const SkGrDescKey*)&rh)->fDesc;
60 size_t lenLH = fDesc->getLength();
61 size_t lenRH = srcDesc->getLength();
62 int cmp = memcmp(fDesc, srcDesc, SkMin32(lenLH, lenRH));
63 if (0 == cmp) {
64 return lenLH < lenRH;
65 } else {
66 return cmp < 0;
67 }
68}
69
70bool SkGrDescKey::eq(const GrKey& rh) const {
71 const SkDescriptor* srcDesc = ((const SkGrDescKey*)&rh)->fDesc;
72 return fDesc->equals(*srcDesc);
73}
74
75///////////////////////////////////////////////////////////////////////////////
76
77SkGrFontScaler::SkGrFontScaler(SkGlyphCache* strike) {
78 fStrike = strike;
79 fKey = NULL;
80}
81
82SkGrFontScaler::~SkGrFontScaler() {
83 GrSafeUnref(fKey);
84}
85
reed@google.com98539c62011-03-15 15:40:16 +000086GrMaskFormat SkGrFontScaler::getMaskFormat() {
87 SkMask::Format format = fStrike->getMaskFormat();
88 switch (format) {
mike@reedtribe.orgc34effe2011-04-06 00:54:45 +000089 case SkMask::kBW_Format:
90 // fall through to kA8 -- we store BW glyphs in our 8-bit cache
reed@google.com98539c62011-03-15 15:40:16 +000091 case SkMask::kA8_Format:
92 return kA8_GrMaskFormat;
93 case SkMask::kLCD16_Format:
94 return kA565_GrMaskFormat;
95 default:
96 GrAssert(!"unsupported SkMask::Format");
97 return kA8_GrMaskFormat;
98 }
99}
100
reed@google.comac10a2d2010-12-22 21:39:39 +0000101const GrKey* SkGrFontScaler::getKey() {
102 if (NULL == fKey) {
103 fKey = new SkGrDescKey(fStrike->getDescriptor());
104 }
105 return fKey;
106}
107
108bool SkGrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed,
109 GrIRect* bounds) {
110 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
111 GrGlyph::UnpackFixedX(packed),
112 GrGlyph::UnpackFixedY(packed));
113 bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
114 return true;
reed@google.com1fcd51e2011-01-05 15:50:27 +0000115
reed@google.comac10a2d2010-12-22 21:39:39 +0000116}
117
mike@reedtribe.orgc34effe2011-04-06 00:54:45 +0000118static void bits_to_bytes(const uint8_t bits[], uint8_t bytes[], int count) {
119 while (count > 0) {
120 unsigned mask = *bits++;
121 for (int i = 7; i >= 0; --i) {
122 *bytes++ = (mask & (1 << i)) ? 0xFF : 0;
123 if (--count == 0) {
124 return;
125 }
126 }
127 }
128}
129
reed@google.comac10a2d2010-12-22 21:39:39 +0000130bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
131 int width, int height,
132 int dstRB, void* dst) {
133 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
134 GrGlyph::UnpackFixedX(packed),
135 GrGlyph::UnpackFixedY(packed));
136 GrAssert(glyph.fWidth == width);
137 GrAssert(glyph.fHeight == height);
138 const void* src = fStrike->findImage(glyph);
139 if (NULL == src) {
140 return false;
141 }
142
143 int srcRB = glyph.rowBytes();
mike@reedtribe.orgc34effe2011-04-06 00:54:45 +0000144 if (SkMask::kBW_Format == fStrike->getMaskFormat()) {
145 // expand bits to bytes
146 const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
147 uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
148 for (int y = 0; y < height; y++) {
149 bits_to_bytes(bits, bytes, width);
150 bits += srcRB;
151 bytes += dstRB;
152 }
153 } else if (srcRB == dstRB) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000154 memcpy(dst, src, dstRB * height);
155 } else {
reed@google.com98539c62011-03-15 15:40:16 +0000156 const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat());
reed@google.comac10a2d2010-12-22 21:39:39 +0000157 for (int y = 0; y < height; y++) {
reed@google.com98539c62011-03-15 15:40:16 +0000158 memcpy(dst, src, width * bbp);
reed@google.comac10a2d2010-12-22 21:39:39 +0000159 src = (const char*)src + srcRB;
160 dst = (char*)dst + dstRB;
161 }
162 }
163 return true;
164}
165
reed@google.com07f3ee12011-05-16 17:21:57 +0000166// we should just return const SkPath* (NULL means false)
reed@google.comac10a2d2010-12-22 21:39:39 +0000167bool SkGrFontScaler::getGlyphPath(uint16_t glyphID, GrPath* path) {
reed@google.com1fcd51e2011-01-05 15:50:27 +0000168
reed@google.comac10a2d2010-12-22 21:39:39 +0000169 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID);
170 const SkPath* skPath = fStrike->findPath(glyph);
171 if (skPath) {
reed@google.com07f3ee12011-05-16 17:21:57 +0000172 *path = *skPath;
reed@google.comac10a2d2010-12-22 21:39:39 +0000173 return true;
174 }
175 return false;
176}
177
178
179