blob: e82b8a0451dc454203aa354dd485efc031e66170 [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;
caryclark@google.com1eeaf0b2011-06-22 13:19:43 +000095 case SkMask::kLCD32_Format:
96 return kA888_GrMaskFormat;
reed@google.com98539c62011-03-15 15:40:16 +000097 default:
98 GrAssert(!"unsupported SkMask::Format");
99 return kA8_GrMaskFormat;
100 }
101}
102
reed@google.comac10a2d2010-12-22 21:39:39 +0000103const GrKey* SkGrFontScaler::getKey() {
104 if (NULL == fKey) {
105 fKey = new SkGrDescKey(fStrike->getDescriptor());
106 }
107 return fKey;
108}
109
110bool SkGrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed,
111 GrIRect* bounds) {
112 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
113 GrGlyph::UnpackFixedX(packed),
114 GrGlyph::UnpackFixedY(packed));
115 bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
116 return true;
reed@google.com1fcd51e2011-01-05 15:50:27 +0000117
reed@google.comac10a2d2010-12-22 21:39:39 +0000118}
119
mike@reedtribe.orgc34effe2011-04-06 00:54:45 +0000120static void bits_to_bytes(const uint8_t bits[], uint8_t bytes[], int count) {
121 while (count > 0) {
122 unsigned mask = *bits++;
123 for (int i = 7; i >= 0; --i) {
124 *bytes++ = (mask & (1 << i)) ? 0xFF : 0;
125 if (--count == 0) {
126 return;
127 }
128 }
129 }
130}
131
reed@google.comac10a2d2010-12-22 21:39:39 +0000132bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
133 int width, int height,
134 int dstRB, void* dst) {
135 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
136 GrGlyph::UnpackFixedX(packed),
137 GrGlyph::UnpackFixedY(packed));
138 GrAssert(glyph.fWidth == width);
139 GrAssert(glyph.fHeight == height);
140 const void* src = fStrike->findImage(glyph);
141 if (NULL == src) {
142 return false;
143 }
144
145 int srcRB = glyph.rowBytes();
mike@reedtribe.orgc34effe2011-04-06 00:54:45 +0000146 if (SkMask::kBW_Format == fStrike->getMaskFormat()) {
147 // expand bits to bytes
148 const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
149 uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
150 for (int y = 0; y < height; y++) {
151 bits_to_bytes(bits, bytes, width);
152 bits += srcRB;
153 bytes += dstRB;
154 }
155 } else if (srcRB == dstRB) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000156 memcpy(dst, src, dstRB * height);
157 } else {
reed@google.com98539c62011-03-15 15:40:16 +0000158 const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat());
reed@google.comac10a2d2010-12-22 21:39:39 +0000159 for (int y = 0; y < height; y++) {
reed@google.com98539c62011-03-15 15:40:16 +0000160 memcpy(dst, src, width * bbp);
reed@google.comac10a2d2010-12-22 21:39:39 +0000161 src = (const char*)src + srcRB;
162 dst = (char*)dst + dstRB;
163 }
164 }
165 return true;
166}
167
reed@google.com07f3ee12011-05-16 17:21:57 +0000168// we should just return const SkPath* (NULL means false)
reed@google.comac10a2d2010-12-22 21:39:39 +0000169bool SkGrFontScaler::getGlyphPath(uint16_t glyphID, GrPath* path) {
reed@google.com1fcd51e2011-01-05 15:50:27 +0000170
reed@google.comac10a2d2010-12-22 21:39:39 +0000171 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID);
172 const SkPath* skPath = fStrike->findPath(glyph);
173 if (skPath) {
reed@google.com07f3ee12011-05-16 17:21:57 +0000174 *path = *skPath;
reed@google.comac10a2d2010-12-22 21:39:39 +0000175 return true;
176 }
177 return false;
178}
179
180
181