1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/SkGrFontScaler.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,203 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2010 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "GrTemplates.h" 1.14 +#include "SkGr.h" 1.15 +#include "SkDescriptor.h" 1.16 +#include "SkGlyphCache.h" 1.17 + 1.18 +class SkGrDescKey : public GrKey { 1.19 +public: 1.20 + explicit SkGrDescKey(const SkDescriptor& desc); 1.21 + virtual ~SkGrDescKey(); 1.22 + 1.23 +protected: 1.24 + // overrides 1.25 + virtual bool lt(const GrKey& rh) const; 1.26 + virtual bool eq(const GrKey& rh) const; 1.27 + 1.28 +private: 1.29 + SkDescriptor* fDesc; 1.30 + enum { 1.31 + kMaxStorageInts = 16 1.32 + }; 1.33 + uint32_t fStorage[kMaxStorageInts]; 1.34 +}; 1.35 + 1.36 +/////////////////////////////////////////////////////////////////////////////// 1.37 + 1.38 +SkGrDescKey::SkGrDescKey(const SkDescriptor& desc) : GrKey(desc.getChecksum()) { 1.39 + size_t size = desc.getLength(); 1.40 + if (size <= sizeof(fStorage)) { 1.41 + fDesc = GrTCast<SkDescriptor*>(fStorage); 1.42 + } else { 1.43 + fDesc = SkDescriptor::Alloc(size); 1.44 + } 1.45 + memcpy(fDesc, &desc, size); 1.46 +} 1.47 + 1.48 +SkGrDescKey::~SkGrDescKey() { 1.49 + if (fDesc != GrTCast<SkDescriptor*>(fStorage)) { 1.50 + SkDescriptor::Free(fDesc); 1.51 + } 1.52 +} 1.53 + 1.54 +bool SkGrDescKey::lt(const GrKey& rh) const { 1.55 + const SkDescriptor* srcDesc = ((const SkGrDescKey*)&rh)->fDesc; 1.56 + size_t lenLH = fDesc->getLength(); 1.57 + size_t lenRH = srcDesc->getLength(); 1.58 + int cmp = memcmp(fDesc, srcDesc, SkTMin<size_t>(lenLH, lenRH)); 1.59 + if (0 == cmp) { 1.60 + return lenLH < lenRH; 1.61 + } else { 1.62 + return cmp < 0; 1.63 + } 1.64 +} 1.65 + 1.66 +bool SkGrDescKey::eq(const GrKey& rh) const { 1.67 + const SkDescriptor* srcDesc = ((const SkGrDescKey*)&rh)->fDesc; 1.68 + return fDesc->equals(*srcDesc); 1.69 +} 1.70 + 1.71 +/////////////////////////////////////////////////////////////////////////////// 1.72 + 1.73 +SkGrFontScaler::SkGrFontScaler(SkGlyphCache* strike) { 1.74 + fStrike = strike; 1.75 + fKey = NULL; 1.76 +} 1.77 + 1.78 +SkGrFontScaler::~SkGrFontScaler() { 1.79 + SkSafeUnref(fKey); 1.80 +} 1.81 + 1.82 +GrMaskFormat SkGrFontScaler::getMaskFormat() { 1.83 + SkMask::Format format = fStrike->getMaskFormat(); 1.84 + switch (format) { 1.85 + case SkMask::kBW_Format: 1.86 + // fall through to kA8 -- we store BW glyphs in our 8-bit cache 1.87 + case SkMask::kA8_Format: 1.88 + return kA8_GrMaskFormat; 1.89 + case SkMask::kLCD16_Format: 1.90 + return kA565_GrMaskFormat; 1.91 + case SkMask::kLCD32_Format: 1.92 + return kA888_GrMaskFormat; 1.93 + case SkMask::kARGB32_Format: 1.94 + return kARGB_GrMaskFormat; 1.95 + default: 1.96 + SkDEBUGFAIL("unsupported SkMask::Format"); 1.97 + return kA8_GrMaskFormat; 1.98 + } 1.99 +} 1.100 + 1.101 +const GrKey* SkGrFontScaler::getKey() { 1.102 + if (NULL == fKey) { 1.103 + fKey = SkNEW_ARGS(SkGrDescKey, (fStrike->getDescriptor())); 1.104 + } 1.105 + return fKey; 1.106 +} 1.107 + 1.108 +bool SkGrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed, 1.109 + SkIRect* bounds) { 1.110 + const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed), 1.111 + GrGlyph::UnpackFixedX(packed), 1.112 + GrGlyph::UnpackFixedY(packed)); 1.113 + bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight); 1.114 + return true; 1.115 + 1.116 +} 1.117 + 1.118 +namespace { 1.119 +// expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to 1.120 +// A8, RGB565, or RGBA8888. 1.121 +template <typename INT_TYPE> 1.122 +void expand_bits(INT_TYPE* dst, 1.123 + const uint8_t* src, 1.124 + int width, 1.125 + int height, 1.126 + int dstRowBytes, 1.127 + int srcRowBytes) { 1.128 + for (int i = 0; i < height; ++i) { 1.129 + int rowWritesLeft = width; 1.130 + const uint8_t* s = src; 1.131 + INT_TYPE* d = dst; 1.132 + while (rowWritesLeft > 0) { 1.133 + unsigned mask = *s++; 1.134 + for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) { 1.135 + *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0; 1.136 + } 1.137 + } 1.138 + dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes); 1.139 + src += srcRowBytes; 1.140 + } 1.141 +} 1.142 +} 1.143 + 1.144 +bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed, 1.145 + int width, int height, 1.146 + int dstRB, void* dst) { 1.147 + const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed), 1.148 + GrGlyph::UnpackFixedX(packed), 1.149 + GrGlyph::UnpackFixedY(packed)); 1.150 + SkASSERT(glyph.fWidth == width); 1.151 + SkASSERT(glyph.fHeight == height); 1.152 + const void* src = fStrike->findImage(glyph); 1.153 + if (NULL == src) { 1.154 + return false; 1.155 + } 1.156 + 1.157 + int srcRB = glyph.rowBytes(); 1.158 + // The windows font host sometimes has BW glyphs in a non-BW strike. So it is important here to 1.159 + // check the glyph's format, not the strike's format, and to be able to convert to any of the 1.160 + // GrMaskFormats. 1.161 + if (SkMask::kBW_Format == glyph.fMaskFormat) { 1.162 + // expand bits to our mask type 1.163 + const uint8_t* bits = reinterpret_cast<const uint8_t*>(src); 1.164 + switch (this->getMaskFormat()) { 1.165 + case kA8_GrMaskFormat:{ 1.166 + uint8_t* bytes = reinterpret_cast<uint8_t*>(dst); 1.167 + expand_bits(bytes, bits, width, height, dstRB, srcRB); 1.168 + break; 1.169 + } 1.170 + case kA565_GrMaskFormat: { 1.171 + uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst); 1.172 + expand_bits(rgb565, bits, width, height, dstRB, srcRB); 1.173 + break; 1.174 + } 1.175 + case kA888_GrMaskFormat: { 1.176 + uint32_t* rgba8888 = reinterpret_cast<uint32_t*>(dst); 1.177 + expand_bits(rgba8888, bits, width, height, dstRB, srcRB); 1.178 + break; 1.179 + } 1.180 + default: 1.181 + GrCrash("Invalid GrMaskFormat"); 1.182 + } 1.183 + } else if (srcRB == dstRB) { 1.184 + memcpy(dst, src, dstRB * height); 1.185 + } else { 1.186 + const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat()); 1.187 + for (int y = 0; y < height; y++) { 1.188 + memcpy(dst, src, width * bbp); 1.189 + src = (const char*)src + srcRB; 1.190 + dst = (char*)dst + dstRB; 1.191 + } 1.192 + } 1.193 + return true; 1.194 +} 1.195 + 1.196 +// we should just return const SkPath* (NULL means false) 1.197 +bool SkGrFontScaler::getGlyphPath(uint16_t glyphID, SkPath* path) { 1.198 + 1.199 + const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID); 1.200 + const SkPath* skPath = fStrike->findPath(glyph); 1.201 + if (skPath) { 1.202 + *path = *skPath; 1.203 + return true; 1.204 + } 1.205 + return false; 1.206 +}