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 11 #include "SkGr.h" 12 #include "SkDescriptor.h" 13 #include "SkGlyphCache.h" 14 15 class SkGrDescKey : public GrKey { 16 public: 17 explicit SkGrDescKey(const SkDescriptor& desc); 18 virtual ~SkGrDescKey(); 19 20 protected: 21 // overrides 22 virtual bool lt(const GrKey& rh) const; 23 virtual bool eq(const GrKey& rh) const; 24 25 private: 26 SkDescriptor* fDesc; 27 enum { 28 kMaxStorageInts = 16 29 }; 30 uint32_t fStorage[kMaxStorageInts]; 31 }; 32 33 /////////////////////////////////////////////////////////////////////////////// 34 35 SkGrDescKey::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 45 SkGrDescKey::~SkGrDescKey() { 46 if (fDesc != GrTCast<SkDescriptor*>(fStorage)) { 47 SkDescriptor::Free(fDesc); 48 } 49 } 50 51 bool 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 63 bool SkGrDescKey::eq(const GrKey& rh) const { 64 const SkDescriptor* srcDesc = ((const SkGrDescKey*)&rh)->fDesc; 65 return fDesc->equals(*srcDesc); 66 } 67 68 /////////////////////////////////////////////////////////////////////////////// 69 70 SkGrFontScaler::SkGrFontScaler(SkGlyphCache* strike) { 71 fStrike = strike; 72 fKey = NULL; 73 } 74 75 SkGrFontScaler::~SkGrFontScaler() { 76 GrSafeUnref(fKey); 77 } 78 79 GrMaskFormat 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 default: 91 GrAssert(!"unsupported SkMask::Format"); 92 return kA8_GrMaskFormat; 93 } 94 } 95 96 const GrKey* SkGrFontScaler::getKey() { 97 if (NULL == fKey) { 98 fKey = new SkGrDescKey(fStrike->getDescriptor()); 99 } 100 return fKey; 101 } 102 103 bool 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; 110 111 } 112 113 static 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 125 bool 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(); 139 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) { 149 memcpy(dst, src, dstRB * height); 150 } else { 151 const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat()); 152 for (int y = 0; y < height; y++) { 153 memcpy(dst, src, width * bbp); 154 src = (const char*)src + srcRB; 155 dst = (char*)dst + dstRB; 156 } 157 } 158 return true; 159 } 160 161 // we should just return const SkPath* (NULL means false) 162 bool SkGrFontScaler::getGlyphPath(uint16_t glyphID, GrPath* path) { 163 164 const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID); 165 const SkPath* skPath = fStrike->findPath(glyph); 166 if (skPath) { 167 *path = *skPath; 168 return true; 169 } 170 return false; 171 } 172 173 174 175