SkGrFontScaler.cpp revision f8cb184095946ebf8f183d253e27bd544a19f23c
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 "SkGlyphCache.h" 14 15class SkGrDescKey : public GrKey { 16public: 17 explicit SkGrDescKey(const SkDescriptor& desc); 18 virtual ~SkGrDescKey(); 19 20protected: 21 // overrides 22 virtual bool lt(const GrKey& rh) const; 23 virtual bool eq(const GrKey& rh) const; 24 25private: 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)) { 38 fDesc = GrTCast<SkDescriptor*>(fStorage); 39 } else { 40 fDesc = SkDescriptor::Alloc(size); 41 } 42 memcpy(fDesc, &desc, size); 43} 44 45SkGrDescKey::~SkGrDescKey() { 46 if (fDesc != GrTCast<SkDescriptor*>(fStorage)) { 47 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, SkTMin<size_t>(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 SkSafeUnref(fKey); 77} 78 79GrMaskFormat SkGrFontScaler::getMaskFormat() { 80 SkMask::Format format = fStrike->getMaskFormat(); 81 switch (format) { 82 case SkMask::kBW_Format: 83 // fall through to kA8 -- we store BW glyphs in our 8-bit cache 84 case SkMask::kA8_Format: 85 return kA8_GrMaskFormat; 86 case SkMask::kLCD16_Format: 87 return kA565_GrMaskFormat; 88 case SkMask::kLCD32_Format: 89 return kA888_GrMaskFormat; 90 case SkMask::kARGB32_Format: 91 return kARGB_GrMaskFormat; 92 default: 93 SkDEBUGFAIL("unsupported SkMask::Format"); 94 return kA8_GrMaskFormat; 95 } 96} 97 98const GrKey* SkGrFontScaler::getKey() { 99 if (NULL == fKey) { 100 fKey = SkNEW_ARGS(SkGrDescKey, (fStrike->getDescriptor())); 101 } 102 return fKey; 103} 104 105bool SkGrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed, 106 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 return true; 112 113} 114 115namespace { 116// expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to 117// A8, RGB565, or RGBA8888. 118template <typename INT_TYPE> 119void expand_bits(INT_TYPE* dst, 120 const uint8_t* src, 121 int width, 122 int height, 123 int dstRowBytes, 124 int srcRowBytes) { 125 for (int i = 0; i < height; ++i) { 126 int rowWritesLeft = width; 127 const uint8_t* s = src; 128 INT_TYPE* d = dst; 129 while (rowWritesLeft > 0) { 130 unsigned mask = *s++; 131 for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) { 132 *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0; 133 } 134 } 135 dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes); 136 src += srcRowBytes; 137 } 138} 139} 140 141bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed, 142 int width, int height, 143 int dstRB, void* dst) { 144 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed), 145 GrGlyph::UnpackFixedX(packed), 146 GrGlyph::UnpackFixedY(packed)); 147 SkASSERT(glyph.fWidth == width); 148 SkASSERT(glyph.fHeight == height); 149 const void* src = fStrike->findImage(glyph); 150 if (NULL == src) { 151 return false; 152 } 153 154 int srcRB = glyph.rowBytes(); 155 // The windows font host sometimes has BW glyphs in a non-BW strike. So it is important here to 156 // check the glyph's format, not the strike's format, and to be able to convert to any of the 157 // GrMaskFormats. 158 if (SkMask::kBW_Format == glyph.fMaskFormat) { 159 // expand bits to our mask type 160 const uint8_t* bits = reinterpret_cast<const uint8_t*>(src); 161 switch (this->getMaskFormat()) { 162 case kA8_GrMaskFormat:{ 163 uint8_t* bytes = reinterpret_cast<uint8_t*>(dst); 164 expand_bits(bytes, bits, width, height, dstRB, srcRB); 165 break; 166 } 167 case kA565_GrMaskFormat: { 168 uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst); 169 expand_bits(rgb565, bits, width, height, dstRB, srcRB); 170 break; 171 } 172 case kA888_GrMaskFormat: { 173 uint32_t* rgba8888 = reinterpret_cast<uint32_t*>(dst); 174 expand_bits(rgba8888, bits, width, height, dstRB, srcRB); 175 break; 176 } 177 default: 178 GrCrash("Invalid GrMaskFormat"); 179 } 180 } else if (srcRB == dstRB) { 181 memcpy(dst, src, dstRB * height); 182 } else { 183 const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat()); 184 for (int y = 0; y < height; y++) { 185 memcpy(dst, src, width * bbp); 186 src = (const char*)src + srcRB; 187 dst = (char*)dst + dstRB; 188 } 189 } 190 return true; 191} 192 193// we should just return const SkPath* (NULL means false) 194bool SkGrFontScaler::getGlyphPath(uint16_t glyphID, SkPath* path) { 195 196 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID); 197 const SkPath* skPath = fStrike->findPath(glyph); 198 if (skPath) { 199 *path = *skPath; 200 return true; 201 } 202 return false; 203} 204