SkTestScalerContext.cpp revision 0007bde42016f879db1ec564c9c64e9f2ffb6709
1/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkAdvancedTypefaceMetrics.h"
9#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkDescriptor.h"
12#include "SkFontDescriptor.h"
13#include "SkGlyph.h"
14#include "SkMask.h"
15// #include "SkOTUtils.h"
16#include "SkScalerContext.h"
17#include "SkTestScalerContext.h"
18#include "SkTypefaceCache.h"
19
20SkTestFont::SkTestFont(const SkTestFontData& fontData)
21    : INHERITED()
22    , fCharCodes(fontData.fCharCodes)
23    , fCharCodesCount(fontData.fCharCodesCount)
24    , fWidths(fontData.fWidths)
25    , fMetrics(fontData.fMetrics)
26    , fName(fontData.fName)
27    , fPaths(NULL)
28{
29    init(fontData.fPoints, fontData.fVerbs);
30#ifdef SK_DEBUG
31    sk_bzero(fDebugBits, sizeof(fDebugBits));
32    sk_bzero(fDebugOverage, sizeof(fDebugOverage));
33#endif
34}
35
36SkTestFont::~SkTestFont() {
37    for (unsigned index = 0; index < fCharCodesCount; ++index) {
38        SkDELETE(fPaths[index]);
39    }
40    SkDELETE_ARRAY(fPaths);
41}
42
43#ifdef SK_DEBUG
44
45#include "SkMutex.h"
46SK_DECLARE_STATIC_MUTEX(gUsedCharsMutex);
47
48#endif
49
50int SkTestFont::codeToIndex(SkUnichar charCode) const {
51#ifdef SK_DEBUG  // detect missing test font data
52    {
53        SkAutoMutexAcquire ac(gUsedCharsMutex);
54        if (charCode >= ' ' && charCode <= '~') {
55            int bitOffset = charCode - ' ';
56            fDebugBits[bitOffset >> 3] |= 1 << (bitOffset & 7);
57        } else {
58            int index = 0;
59            while (fDebugOverage[index] != 0 && fDebugOverage[index] != charCode
60                    && index < (int) sizeof(fDebugOverage)) {
61                ++index;
62            }
63            SkASSERT(index < (int) sizeof(fDebugOverage));
64            if (fDebugOverage[index] == 0) {
65                fDebugOverage[index] = charCode;
66            }
67        }
68    }
69#endif
70    for (unsigned index = 0; index < fCharCodesCount; ++index) {
71        if (fCharCodes[index] == (unsigned) charCode) {
72            return (int) index;
73        }
74    }
75    SkDEBUGF(("missing '%c' (%d) from %s %d\n", (char) charCode, charCode,
76            fDebugName, fDebugStyle));
77    return 0;
78}
79
80void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
81    fPaths = SkNEW_ARRAY(SkPath*, fCharCodesCount);
82    for (unsigned index = 0; index < fCharCodesCount; ++index) {
83        SkPath* path = SkNEW(SkPath);
84        SkPath::Verb verb;
85        while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) {
86            switch (verb) {
87                case SkPath::kMove_Verb:
88                    path->moveTo(pts[0], pts[1]);
89                    pts += 2;
90                    break;
91                case SkPath::kLine_Verb:
92                    path->lineTo(pts[0], pts[1]);
93                    pts += 2;
94                    break;
95                case SkPath::kQuad_Verb:
96                    path->quadTo(pts[0], pts[1], pts[2], pts[3]);
97                    pts += 4;
98                    break;
99                case SkPath::kCubic_Verb:
100                    path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
101                    pts += 6;
102                    break;
103                case SkPath::kClose_Verb:
104                    path->close();
105                    break;
106                default:
107                    SkDEBUGFAIL("bad verb");
108                    return;
109            }
110        }
111        fPaths[index] = path;
112    }
113}
114
115SkTestTypeface::SkTestTypeface(SkTestFont* testFont, const SkFontStyle& style)
116    : SkTypeface(style, SkTypefaceCache::NewFontID(), false)
117    , fTestFont(testFont) {
118}
119
120void SkTestTypeface::getAdvance(SkGlyph* glyph) {
121    glyph->fAdvanceX = fTestFont->fWidths[glyph->getGlyphID()];
122    glyph->fAdvanceY = 0;
123}
124
125void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
126    *metrics = fTestFont->fMetrics;
127}
128
129void SkTestTypeface::getMetrics(SkGlyph* glyph) {
130    glyph->fAdvanceX = fTestFont->fWidths[glyph->getGlyphID()];
131    glyph->fAdvanceY = 0;
132}
133
134void SkTestTypeface::getPath(const SkGlyph& glyph, SkPath* path) {
135    *path = *fTestFont->fPaths[glyph.getGlyphID()];
136}
137
138void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
139    rec->setHinting(SkPaint::kNo_Hinting);
140}
141
142SkAdvancedTypefaceMetrics* SkTestTypeface::onGetAdvancedTypefaceMetrics(
143                                PerGlyphInfo ,
144                                const uint32_t* glyphIDs,
145                                uint32_t glyphIDsCount) const {
146// pdf only
147    SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics;
148    info->fFontName.set(fTestFont->fName);
149    info->fLastGlyphID = SkToU16(onCountGlyphs() - 1);
150    return info;
151}
152
153void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
154    desc->setFamilyName(fTestFont->fName);
155    *isLocal = false;
156}
157
158int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
159                            uint16_t glyphs[], int glyphCount) const {
160    SkASSERT(encoding == kUTF16_Encoding);
161    for (int index = 0; index < glyphCount; ++index) {
162        SkUnichar ch = ((SkUnichar*) chars)[index];
163        glyphs[index] = fTestFont->codeToIndex(ch);
164    }
165    return glyphCount;
166}
167
168void SkTestTypeface::onGetFamilyName(SkString* familyName) const {
169    *familyName = fTestFont->fName;
170}
171
172SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
173    SkString familyName(fTestFont->fName);
174    SkString language("und"); //undetermined
175SkASSERT(0);  // incomplete
176    return NULL;
177//     return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
178}
179
180class SkTestScalerContext : public SkScalerContext {
181public:
182    SkTestScalerContext(SkTestTypeface* face, const SkDescriptor* desc)
183        : SkScalerContext(face, desc)
184        , fFace(face)
185    {
186        fRec.getSingleMatrix(&fMatrix);
187        this->forceGenerateImageFromPath();
188    }
189
190    virtual ~SkTestScalerContext() {
191    }
192
193protected:
194    unsigned generateGlyphCount() override {
195        return fFace->onCountGlyphs();
196    }
197
198    uint16_t generateCharToGlyph(SkUnichar uni) override {
199        uint16_t glyph;
200        (void) fFace->onCharsToGlyphs((const void *) &uni, SkTypeface::kUTF16_Encoding, &glyph, 1);
201        return glyph;
202    }
203
204    void generateAdvance(SkGlyph* glyph) override {
205        fFace->getAdvance(glyph);
206
207        const SkVector advance = fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
208                                               SkFixedToScalar(glyph->fAdvanceY));
209        glyph->fAdvanceX = SkScalarToFixed(advance.fX);
210        glyph->fAdvanceY = SkScalarToFixed(advance.fY);
211    }
212
213    void generateMetrics(SkGlyph* glyph) override {
214        fFace->getMetrics(glyph);
215
216        const SkVector advance = fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
217                                               SkFixedToScalar(glyph->fAdvanceY));
218        glyph->fAdvanceX = SkScalarToFixed(advance.fX);
219        glyph->fAdvanceY = SkScalarToFixed(advance.fY);
220
221        SkPath path;
222        fFace->getPath(*glyph, &path);
223        path.transform(fMatrix);
224
225        SkRect storage;
226        const SkPaint paint;
227        const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
228                                                            &storage,
229                                                            SkPaint::kFill_Style);
230        SkIRect ibounds;
231        newBounds.roundOut(&ibounds);
232        glyph->fLeft = ibounds.fLeft;
233        glyph->fTop = ibounds.fTop;
234        glyph->fWidth = ibounds.width();
235        glyph->fHeight = ibounds.height();
236    }
237
238    void generateImage(const SkGlyph& glyph) override {
239        SkPath path;
240        fFace->getPath(glyph, &path);
241
242        SkBitmap bm;
243        bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
244                            glyph.fImage, glyph.rowBytes());
245        bm.eraseColor(0);
246
247        SkCanvas canvas(bm);
248        canvas.translate(-SkIntToScalar(glyph.fLeft),
249                            -SkIntToScalar(glyph.fTop));
250        canvas.concat(fMatrix);
251        SkPaint paint;
252        paint.setAntiAlias(true);
253        canvas.drawPath(path, paint);
254    }
255
256    void generatePath(const SkGlyph& glyph, SkPath* path) override {
257        fFace->getPath(glyph, path);
258        path->transform(fMatrix);
259    }
260
261    void generateFontMetrics(SkPaint::FontMetrics* metrics) override {
262        fFace->getFontMetrics(metrics);
263        if (metrics) {
264            SkScalar scale = fMatrix.getScaleY();
265            metrics->fTop = SkScalarMul(metrics->fTop, scale);
266            metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
267            metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
268            metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
269            metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
270            metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
271            metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
272            metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
273            metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
274        }
275    }
276
277private:
278    SkTestTypeface*  fFace;
279    SkMatrix         fMatrix;
280};
281
282SkScalerContext* SkTestTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
283    return SkNEW_ARGS(SkTestScalerContext, (const_cast<SkTestTypeface*>(this), desc));
284}
285