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