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() {
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
81const GrFontDescKey* GrFontScaler::getKey() {
82    if (NULL == fKey) {
83        fKey = SkNEW_ARGS(GrFontDescKey, (fStrike->getDescriptor()));
84    }
85    return fKey;
86}
87
88bool 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
97bool 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
107namespace {
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.
110template <typename INT_TYPE>
111void 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
133bool 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
185bool 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)
204bool 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