blob: 95c29ffe69eb033a5d6c4b2c7ed7cb76f5c34f4e [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#include "SkGr.h"
12#include "SkDescriptor.h"
13#include "SkGlyphCache.h"
14
15class SkGrDescKey : public GrKey {
16public:
17 explicit SkGrDescKey(const SkDescriptor& desc);
18 virtual ~SkGrDescKey();
reed@google.com1fcd51e2011-01-05 15:50:27 +000019
reed@google.comac10a2d2010-12-22 21:39:39 +000020protected:
21 // overrides
22 virtual bool lt(const GrKey& rh) const;
23 virtual bool eq(const GrKey& rh) const;
reed@google.com1fcd51e2011-01-05 15:50:27 +000024
reed@google.comac10a2d2010-12-22 21:39:39 +000025private:
26 SkDescriptor* fDesc;
27 enum {
28 kMaxStorageInts = 16
29 };
30 uint32_t fStorage[kMaxStorageInts];
31};
32
33///////////////////////////////////////////////////////////////////////////////
34
35SkGrDescKey::SkGrDescKey(const SkDescriptor& desc) : GrKey(desc.getChecksum()) {
36 size_t size = desc.getLength();
37 if (size <= sizeof(fStorage)) {
reed@google.com1fcd51e2011-01-05 15:50:27 +000038 fDesc = GrTCast<SkDescriptor*>(fStorage);
reed@google.comac10a2d2010-12-22 21:39:39 +000039 } else {
40 fDesc = SkDescriptor::Alloc(size);
41 }
42 memcpy(fDesc, &desc, size);
43}
44
45SkGrDescKey::~SkGrDescKey() {
reed@google.com1fcd51e2011-01-05 15:50:27 +000046 if (fDesc != GrTCast<SkDescriptor*>(fStorage)) {
reed@google.comac10a2d2010-12-22 21:39:39 +000047 SkDescriptor::Free(fDesc);
48 }
49}
50
51bool 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
63bool SkGrDescKey::eq(const GrKey& rh) const {
64 const SkDescriptor* srcDesc = ((const SkGrDescKey*)&rh)->fDesc;
65 return fDesc->equals(*srcDesc);
66}
67
68///////////////////////////////////////////////////////////////////////////////
69
70SkGrFontScaler::SkGrFontScaler(SkGlyphCache* strike) {
71 fStrike = strike;
72 fKey = NULL;
73}
74
75SkGrFontScaler::~SkGrFontScaler() {
76 GrSafeUnref(fKey);
77}
78
reed@google.com98539c62011-03-15 15:40:16 +000079GrMaskFormat SkGrFontScaler::getMaskFormat() {
80 SkMask::Format format = fStrike->getMaskFormat();
81 switch (format) {
mike@reedtribe.orgc34effe2011-04-06 00:54:45 +000082 case SkMask::kBW_Format:
83 // fall through to kA8 -- we store BW glyphs in our 8-bit cache
reed@google.com98539c62011-03-15 15:40:16 +000084 case SkMask::kA8_Format:
85 return kA8_GrMaskFormat;
86 case SkMask::kLCD16_Format:
87 return kA565_GrMaskFormat;
caryclark@google.com1eeaf0b2011-06-22 13:19:43 +000088 case SkMask::kLCD32_Format:
89 return kA888_GrMaskFormat;
reed@google.com98539c62011-03-15 15:40:16 +000090 default:
91 GrAssert(!"unsupported SkMask::Format");
92 return kA8_GrMaskFormat;
93 }
94}
95
reed@google.comac10a2d2010-12-22 21:39:39 +000096const GrKey* SkGrFontScaler::getKey() {
97 if (NULL == fKey) {
98 fKey = new SkGrDescKey(fStrike->getDescriptor());
99 }
100 return fKey;
101}
102
103bool 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;
reed@google.com1fcd51e2011-01-05 15:50:27 +0000110
reed@google.comac10a2d2010-12-22 21:39:39 +0000111}
112
mike@reedtribe.orgc34effe2011-04-06 00:54:45 +0000113static void bits_to_bytes(const uint8_t bits[], uint8_t bytes[], int count) {
114 while (count > 0) {
115 unsigned mask = *bits++;
116 for (int i = 7; i >= 0; --i) {
117 *bytes++ = (mask & (1 << i)) ? 0xFF : 0;
118 if (--count == 0) {
119 return;
120 }
121 }
122 }
123}
124
reed@google.comac10a2d2010-12-22 21:39:39 +0000125bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
126 int width, int height,
127 int dstRB, void* dst) {
128 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
129 GrGlyph::UnpackFixedX(packed),
130 GrGlyph::UnpackFixedY(packed));
131 GrAssert(glyph.fWidth == width);
132 GrAssert(glyph.fHeight == height);
133 const void* src = fStrike->findImage(glyph);
134 if (NULL == src) {
135 return false;
136 }
137
138 int srcRB = glyph.rowBytes();
mike@reedtribe.orgc34effe2011-04-06 00:54:45 +0000139 if (SkMask::kBW_Format == fStrike->getMaskFormat()) {
140 // expand bits to bytes
141 const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
142 uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
143 for (int y = 0; y < height; y++) {
144 bits_to_bytes(bits, bytes, width);
145 bits += srcRB;
146 bytes += dstRB;
147 }
148 } else if (srcRB == dstRB) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000149 memcpy(dst, src, dstRB * height);
150 } else {
reed@google.com98539c62011-03-15 15:40:16 +0000151 const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat());
reed@google.comac10a2d2010-12-22 21:39:39 +0000152 for (int y = 0; y < height; y++) {
reed@google.com98539c62011-03-15 15:40:16 +0000153 memcpy(dst, src, width * bbp);
reed@google.comac10a2d2010-12-22 21:39:39 +0000154 src = (const char*)src + srcRB;
155 dst = (char*)dst + dstRB;
156 }
157 }
158 return true;
159}
160
reed@google.com07f3ee12011-05-16 17:21:57 +0000161// we should just return const SkPath* (NULL means false)
reed@google.comac10a2d2010-12-22 21:39:39 +0000162bool SkGrFontScaler::getGlyphPath(uint16_t glyphID, GrPath* path) {
reed@google.com1fcd51e2011-01-05 15:50:27 +0000163
reed@google.comac10a2d2010-12-22 21:39:39 +0000164 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID);
165 const SkPath* skPath = fStrike->findPath(glyph);
166 if (skPath) {
reed@google.com07f3ee12011-05-16 17:21:57 +0000167 *path = *skPath;
reed@google.comac10a2d2010-12-22 21:39:39 +0000168 return true;
169 }
170 return false;
171}
172
173
174