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 "SkMakeUnique.h"
15#include "SkMask.h"
16#include "SkOTUtils.h"
17#include "SkPaintPriv.h"
18#include "SkScalerContext.h"
19#include "SkTestScalerContext.h"
20#include "SkTypefaceCache.h"
21#include "SkUtils.h"
22
23SkTestFont::SkTestFont(const SkTestFontData& fontData)
24    : INHERITED()
25    , fCharCodes(fontData.fCharCodes)
26    , fCharCodesCount(fontData.fCharCodes ? fontData.fCharCodesCount : 0)
27    , fWidths(fontData.fWidths)
28    , fMetrics(fontData.fMetrics)
29    , fName(fontData.fName)
30    , fPaths(nullptr)
31{
32    init(fontData.fPoints, fontData.fVerbs);
33}
34
35SkTestFont::~SkTestFont() {
36    for (unsigned index = 0; index < fCharCodesCount; ++index) {
37        delete fPaths[index];
38    }
39    delete[] fPaths;
40}
41
42int SkTestFont::codeToIndex(SkUnichar charCode) const {
43    for (unsigned index = 0; index < fCharCodesCount; ++index) {
44        if (fCharCodes[index] == (unsigned) charCode) {
45            return (int) index;
46        }
47    }
48    return 0;
49}
50
51void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
52    fPaths = new SkPath* [fCharCodesCount];
53    for (unsigned index = 0; index < fCharCodesCount; ++index) {
54        SkPath* path = new SkPath;
55        SkPath::Verb verb;
56        while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) {
57            switch (verb) {
58                case SkPath::kMove_Verb:
59                    path->moveTo(pts[0], pts[1]);
60                    pts += 2;
61                    break;
62                case SkPath::kLine_Verb:
63                    path->lineTo(pts[0], pts[1]);
64                    pts += 2;
65                    break;
66                case SkPath::kQuad_Verb:
67                    path->quadTo(pts[0], pts[1], pts[2], pts[3]);
68                    pts += 4;
69                    break;
70                case SkPath::kCubic_Verb:
71                    path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
72                    pts += 6;
73                    break;
74                case SkPath::kClose_Verb:
75                    path->close();
76                    break;
77                default:
78                    SkDEBUGFAIL("bad verb");
79                    return;
80            }
81        }
82        // This should make SkPath::getBounds() queries threadsafe.
83        path->updateBoundsCache();
84        fPaths[index] = path;
85    }
86}
87
88SkTestTypeface::SkTestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style)
89    : SkTypeface(style, false)
90    , fTestFont(std::move(testFont)) {
91}
92
93void SkTestTypeface::getAdvance(SkGlyph* glyph) {
94    // TODO(benjaminwagner): Update users to use floats.
95    glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyph->getGlyphID()]);
96    glyph->fAdvanceY = 0;
97}
98
99void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
100    *metrics = fTestFont->fMetrics;
101}
102
103void SkTestTypeface::getMetrics(SkGlyph* glyph) {
104    SkGlyphID glyphID = glyph->getGlyphID();
105    glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
106
107    // TODO(benjaminwagner): Update users to use floats.
108    glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyphID]);
109    glyph->fAdvanceY = 0;
110}
111
112void SkTestTypeface::getPath(SkGlyphID glyphID, SkPath* path) {
113    glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
114    *path = *fTestFont->fPaths[glyphID];
115}
116
117void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
118    rec->setHinting(SkPaint::kNo_Hinting);
119}
120
121std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestTypeface::onGetAdvancedMetrics() const { // pdf only
122    std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
123    info->fFontName.set(fTestFont->fName);
124    int glyphCount = this->onCountGlyphs();
125
126    SkTDArray<SkUnichar>& toUnicode = info->fGlyphToUnicode;
127    toUnicode.setCount(glyphCount);
128    SkASSERT(glyphCount == SkToInt(fTestFont->fCharCodesCount));
129    for (int gid = 0; gid < glyphCount; ++gid) {
130        toUnicode[gid] = SkToS32(fTestFont->fCharCodes[gid]);
131    }
132    return info;
133}
134
135void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
136    desc->setFamilyName(fTestFont->fName);
137    desc->setStyle(this->fontStyle());
138    *isLocal = false;
139}
140
141int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
142                                    uint16_t glyphs[], int glyphCount) const {
143    auto utf8  = (const      char*)chars;
144    auto utf16 = (const  uint16_t*)chars;
145    auto utf32 = (const SkUnichar*)chars;
146
147    for (int i = 0; i < glyphCount; i++) {
148        SkUnichar ch;
149        switch (encoding) {
150            case kUTF8_Encoding:  ch =  SkUTF8_NextUnichar(&utf8 ); break;
151            case kUTF16_Encoding: ch = SkUTF16_NextUnichar(&utf16); break;
152            case kUTF32_Encoding: ch =                    *utf32++; break;
153        }
154        if (glyphs) {
155            glyphs[i] = fTestFont->codeToIndex(ch);
156        }
157    }
158    return glyphCount;
159}
160
161void SkTestTypeface::onGetFamilyName(SkString* familyName) const {
162    *familyName = fTestFont->fName;
163}
164
165SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
166    SkString familyName(fTestFont->fName);
167    SkString language("und"); //undetermined
168    return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
169}
170
171class SkTestScalerContext : public SkScalerContext {
172public:
173    SkTestScalerContext(sk_sp<SkTestTypeface> face, const SkScalerContextEffects& effects,
174                        const SkDescriptor* desc)
175        : SkScalerContext(std::move(face), effects, desc)
176    {
177        fRec.getSingleMatrix(&fMatrix);
178        this->forceGenerateImageFromPath();
179    }
180
181protected:
182    SkTestTypeface* getTestTypeface() const {
183        return static_cast<SkTestTypeface*>(this->getTypeface());
184    }
185
186    unsigned generateGlyphCount() override {
187        return this->getTestTypeface()->onCountGlyphs();
188    }
189
190    uint16_t generateCharToGlyph(SkUnichar uni) override {
191        uint16_t glyph;
192        (void) this->getTestTypeface()->onCharsToGlyphs((const void *) &uni,
193                                                        SkTypeface::kUTF32_Encoding, &glyph, 1);
194        return glyph;
195    }
196
197    void generateAdvance(SkGlyph* glyph) override {
198        this->getTestTypeface()->getAdvance(glyph);
199
200        const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
201                                               SkFloatToScalar(glyph->fAdvanceY));
202        glyph->fAdvanceX = SkScalarToFloat(advance.fX);
203        glyph->fAdvanceY = SkScalarToFloat(advance.fY);
204    }
205
206    void generateMetrics(SkGlyph* glyph) override {
207        this->getTestTypeface()->getMetrics(glyph);
208
209        const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
210                                               SkFloatToScalar(glyph->fAdvanceY));
211        glyph->fAdvanceX = SkScalarToFloat(advance.fX);
212        glyph->fAdvanceY = SkScalarToFloat(advance.fY);
213
214        SkPath path;
215        this->getTestTypeface()->getPath(glyph->getGlyphID(), &path);
216        path.transform(fMatrix);
217
218        SkRect storage;
219        const SkPaint paint;
220        const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
221                                                            &storage,
222                                                            SkPaint::kFill_Style);
223        SkIRect ibounds;
224        newBounds.roundOut(&ibounds);
225        glyph->fLeft = ibounds.fLeft;
226        glyph->fTop = ibounds.fTop;
227        glyph->fWidth = ibounds.width();
228        glyph->fHeight = ibounds.height();
229    }
230
231    void generateImage(const SkGlyph& glyph) override {
232        SkPath path;
233        this->getTestTypeface()->getPath(glyph.getGlyphID(), &path);
234
235        SkBitmap bm;
236        bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
237                            glyph.fImage, glyph.rowBytes());
238        bm.eraseColor(0);
239
240        SkCanvas canvas(bm);
241        canvas.translate(-SkIntToScalar(glyph.fLeft),
242                            -SkIntToScalar(glyph.fTop));
243        canvas.concat(fMatrix);
244        SkPaint paint;
245        paint.setAntiAlias(true);
246        canvas.drawPath(path, paint);
247    }
248
249    void generatePath(SkGlyphID glyph, SkPath* path) override {
250        this->getTestTypeface()->getPath(glyph, path);
251        path->transform(fMatrix);
252    }
253
254    void generateFontMetrics(SkPaint::FontMetrics* metrics) override {
255        this->getTestTypeface()->getFontMetrics(metrics);
256        SkPaintPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
257    }
258
259private:
260    SkMatrix         fMatrix;
261};
262
263SkScalerContext* SkTestTypeface::onCreateScalerContext(
264    const SkScalerContextEffects& effects, const SkDescriptor* desc) const
265{
266    return new SkTestScalerContext(sk_ref_sp(const_cast<SkTestTypeface*>(this)), effects, desc);
267}
268