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