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 18GrFontDescKey::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 28GrFontDescKey::~GrFontDescKey() { 29 if (fDesc != GrTCast<SkDescriptor*>(fStorage)) { 30 SkDescriptor::Free(fDesc); 31 } 32} 33 34bool 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 46bool GrFontDescKey::eq(const GrFontDescKey& rh) const { 47 const SkDescriptor* srcDesc = (&rh)->fDesc; 48 return fDesc->equals(*srcDesc); 49} 50 51/////////////////////////////////////////////////////////////////////////////// 52 53GrFontScaler::GrFontScaler(SkGlyphCache* strike) { 54 fStrike = strike; 55 fKey = NULL; 56} 57 58GrFontScaler::~GrFontScaler() { 59 SkSafeUnref(fKey); 60} 61 62GrMaskFormat GrFontScaler::getMaskFormat() const { 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::kARGB32_Format: 72 return kARGB_GrMaskFormat; 73 default: 74 SkDEBUGFAIL("unsupported SkMask::Format"); 75 return kA8_GrMaskFormat; 76 } 77} 78 79const GrFontDescKey* GrFontScaler::getKey() { 80 if (NULL == fKey) { 81 fKey = SkNEW_ARGS(GrFontDescKey, (fStrike->getDescriptor())); 82 } 83 return fKey; 84} 85 86GrMaskFormat GrFontScaler::getPackedGlyphMaskFormat(GrGlyph::PackedID packed) const { 87 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed), 88 GrGlyph::UnpackFixedX(packed), 89 GrGlyph::UnpackFixedY(packed)); 90 SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); 91 switch (format) { 92 case SkMask::kBW_Format: 93 // fall through to kA8 -- we store BW glyphs in our 8-bit cache 94 case SkMask::kA8_Format: 95 return kA8_GrMaskFormat; 96 case SkMask::kLCD16_Format: 97 return kA565_GrMaskFormat; 98 case SkMask::kARGB32_Format: 99 return kARGB_GrMaskFormat; 100 default: 101 SkDEBUGFAIL("unsupported SkMask::Format"); 102 return kA8_GrMaskFormat; 103 } 104} 105 106bool GrFontScaler::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 115bool GrFontScaler::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 125namespace { 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. 128template <typename INT_TYPE> 129void 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 151bool GrFontScaler::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 default: 183 SkFAIL("Invalid GrMaskFormat"); 184 } 185 } else if (srcRB == dstRB) { 186 memcpy(dst, src, dstRB * height); 187 } else { 188 const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat()); 189 for (int y = 0; y < height; y++) { 190 memcpy(dst, src, width * bbp); 191 src = (const char*)src + srcRB; 192 dst = (char*)dst + dstRB; 193 } 194 } 195 return true; 196} 197 198bool GrFontScaler::getPackedGlyphDFImage(GrGlyph::PackedID packed, 199 int width, int height, 200 void* dst) { 201 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed), 202 GrGlyph::UnpackFixedX(packed), 203 GrGlyph::UnpackFixedY(packed)); 204 SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width); 205 SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height); 206 const void* image = fStrike->findImage(glyph); 207 if (NULL == image) { 208 return false; 209 } 210 // now generate the distance field 211 SkASSERT(dst); 212 SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 213 if (SkMask::kA8_Format == maskFormat) { 214 // make the distance field from the image 215 SkGenerateDistanceFieldFromA8Image((unsigned char*)dst, 216 (unsigned char*)image, 217 glyph.fWidth, glyph.fHeight, 218 glyph.rowBytes()); 219 } else if (SkMask::kBW_Format == maskFormat) { 220 // make the distance field from the image 221 SkGenerateDistanceFieldFromBWImage((unsigned char*)dst, 222 (unsigned char*)image, 223 glyph.fWidth, glyph.fHeight, 224 glyph.rowBytes()); 225 } else { 226 return false; 227 } 228 229 return true; 230} 231 232// we should just return const SkPath* (NULL means false) 233bool GrFontScaler::getGlyphPath(uint16_t glyphID, SkPath* path) { 234 235 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID); 236 const SkPath* skPath = fStrike->findPath(glyph); 237 if (skPath) { 238 *path = *skPath; 239 return true; 240 } 241 return false; 242} 243