1/*
2 * Copyright 2013 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 "SkGScalerContext.h"
9#include "SkGlyph.h"
10#include "SkPath.h"
11#include "SkCanvas.h"
12
13class SkGScalerContext : public SkScalerContext {
14public:
15    SkGScalerContext(SkGTypeface*, const SkDescriptor*);
16    virtual ~SkGScalerContext();
17
18protected:
19    unsigned generateGlyphCount() override;
20    uint16_t generateCharToGlyph(SkUnichar) override;
21    void generateAdvance(SkGlyph*) override;
22    void generateMetrics(SkGlyph*) override;
23    void generateImage(const SkGlyph&) override;
24    void generatePath(const SkGlyph&, SkPath*) override;
25    void generateFontMetrics(SkPaint::FontMetrics*) override;
26
27private:
28    SkGTypeface*     fFace;
29    SkScalerContext* fProxy;
30    SkMatrix         fMatrix;
31};
32
33#define STD_SIZE    1
34
35#include "SkDescriptor.h"
36
37SkGScalerContext::SkGScalerContext(SkGTypeface* face, const SkDescriptor* desc)
38        : SkScalerContext(face, desc)
39        , fFace(face)
40{
41
42    size_t  descSize = SkDescriptor::ComputeOverhead(1) + sizeof(SkScalerContext::Rec);
43    SkAutoDescriptor ad(descSize);
44    SkDescriptor*    newDesc = ad.getDesc();
45
46    newDesc->init();
47    void* entry = newDesc->addEntry(kRec_SkDescriptorTag,
48                                    sizeof(SkScalerContext::Rec), &fRec);
49    {
50        SkScalerContext::Rec* rec = (SkScalerContext::Rec*)entry;
51        rec->fTextSize = STD_SIZE;
52        rec->fPreScaleX = SK_Scalar1;
53        rec->fPreSkewX = 0;
54        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
55        rec->fPost2x2[1][0] = rec->fPost2x2[0][1] = 0;
56    }
57    SkASSERT(descSize == newDesc->getLength());
58    newDesc->computeChecksum();
59
60    fProxy = face->proxy()->createScalerContext(newDesc);
61
62    fRec.getSingleMatrix(&fMatrix);
63    fMatrix.preScale(SK_Scalar1 / STD_SIZE, SK_Scalar1 / STD_SIZE);
64}
65
66SkGScalerContext::~SkGScalerContext() { delete fProxy; }
67
68unsigned SkGScalerContext::generateGlyphCount() {
69    return fProxy->getGlyphCount();
70}
71
72uint16_t SkGScalerContext::generateCharToGlyph(SkUnichar uni) {
73    return fProxy->charToGlyphID(uni);
74}
75
76void SkGScalerContext::generateAdvance(SkGlyph* glyph) {
77    fProxy->getAdvance(glyph);
78
79    SkVector advance;
80    fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
81                  SkFixedToScalar(glyph->fAdvanceY), &advance);
82    glyph->fAdvanceX = SkScalarToFixed(advance.fX);
83    glyph->fAdvanceY = SkScalarToFixed(advance.fY);
84}
85
86void SkGScalerContext::generateMetrics(SkGlyph* glyph) {
87    fProxy->getMetrics(glyph);
88
89    SkVector advance;
90    fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
91                  SkFixedToScalar(glyph->fAdvanceY), &advance);
92    glyph->fAdvanceX = SkScalarToFixed(advance.fX);
93    glyph->fAdvanceY = SkScalarToFixed(advance.fY);
94
95    SkPath path;
96    fProxy->getPath(*glyph, &path);
97    path.transform(fMatrix);
98
99    SkRect storage;
100    const SkPaint& paint = fFace->paint();
101    const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
102                                                        &storage,
103                                                        SkPaint::kFill_Style);
104    SkIRect ibounds;
105    newBounds.roundOut(&ibounds);
106    glyph->fLeft = ibounds.fLeft;
107    glyph->fTop = ibounds.fTop;
108    glyph->fWidth = ibounds.width();
109    glyph->fHeight = ibounds.height();
110    glyph->fMaskFormat = SkMask::kARGB32_Format;
111}
112
113void SkGScalerContext::generateImage(const SkGlyph& glyph) {
114    if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
115        SkPath path;
116        fProxy->getPath(glyph, &path);
117
118        SkBitmap bm;
119        bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
120                         glyph.fImage, glyph.rowBytes());
121        bm.eraseColor(0);
122
123        SkCanvas canvas(bm);
124        canvas.translate(-SkIntToScalar(glyph.fLeft),
125                         -SkIntToScalar(glyph.fTop));
126        canvas.concat(fMatrix);
127        canvas.drawPath(path, fFace->paint());
128    } else {
129        fProxy->getImage(glyph);
130    }
131}
132
133void SkGScalerContext::generatePath(const SkGlyph& glyph, SkPath* path) {
134    fProxy->getPath(glyph, path);
135    path->transform(fMatrix);
136}
137
138void SkGScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) {
139    fProxy->getFontMetrics(metrics);
140    if (metrics) {
141        SkScalar scale = fMatrix.getScaleY();
142        metrics->fTop = SkScalarMul(metrics->fTop, scale);
143        metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
144        metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
145        metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
146        metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
147        metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
148        metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
149        metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
150        metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
151    }
152}
153
154///////////////////////////////////////////////////////////////////////////////
155
156#include "SkTypefaceCache.h"
157
158SkGTypeface::SkGTypeface(SkTypeface* proxy, const SkPaint& paint)
159    : SkTypeface(proxy->fontStyle(), SkTypefaceCache::NewFontID(), false)
160    , fProxy(SkRef(proxy))
161    , fPaint(paint) {}
162
163SkGTypeface::~SkGTypeface() {
164    fProxy->unref();
165}
166
167SkScalerContext* SkGTypeface::onCreateScalerContext(
168                                            const SkDescriptor* desc) const {
169    return new SkGScalerContext(const_cast<SkGTypeface*>(this), desc);
170}
171
172void SkGTypeface::onFilterRec(SkScalerContextRec* rec) const {
173    fProxy->filterRec(rec);
174    rec->setHinting(SkPaint::kNo_Hinting);
175    rec->fMaskFormat = SkMask::kARGB32_Format;
176}
177
178SkAdvancedTypefaceMetrics* SkGTypeface::onGetAdvancedTypefaceMetrics(
179                                PerGlyphInfo info,
180                                const uint32_t* glyphIDs,
181                                uint32_t glyphIDsCount) const {
182    return fProxy->getAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
183}
184
185SkStreamAsset* SkGTypeface::onOpenStream(int* ttcIndex) const {
186    return fProxy->openStream(ttcIndex);
187}
188
189void SkGTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
190                                      bool* isLocal) const {
191    fProxy->getFontDescriptor(desc, isLocal);
192}
193
194int SkGTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
195                                 uint16_t glyphs[], int glyphCount) const {
196    return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount);
197}
198
199int SkGTypeface::onCountGlyphs() const {
200    return fProxy->countGlyphs();
201}
202
203int SkGTypeface::onGetUPEM() const {
204    return fProxy->getUnitsPerEm();
205}
206
207void SkGTypeface::onGetFamilyName(SkString* familyName) const {
208    fProxy->getFamilyName(familyName);
209}
210
211SkTypeface::LocalizedStrings* SkGTypeface::onCreateFamilyNameIterator() const {
212    return fProxy->createFamilyNameIterator();
213}
214
215int SkGTypeface::onGetTableTags(SkFontTableTag tags[]) const {
216    return fProxy->getTableTags(tags);
217}
218
219size_t SkGTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
220                                    size_t length, void* data) const {
221    return fProxy->getTableData(tag, offset, length, data);
222}
223
224///////////////////////////////////////////////////////////////////////////////
225
226#if 0
227// under construction -- defining a font purely in terms of skia primitives
228// ala an SVG-font.
229class SkGFont : public SkRefCnt {
230public:
231    virtual ~SkGFont();
232
233    int unicharToGlyph(SkUnichar) const;
234
235    int countGlyphs() const { return fCount; }
236
237    float getAdvance(int index) const {
238        SkASSERT((unsigned)index < (unsigned)fCount);
239        return fGlyphs[index].fAdvance;
240    }
241
242    const SkPath& getPath(int index) const {
243        SkASSERT((unsigned)index < (unsigned)fCount);
244        return fGlyphs[index].fPath;
245    }
246
247private:
248    struct Glyph {
249        SkUnichar   fUni;
250        float       fAdvance;
251        SkPath      fPath;
252    };
253    int fCount;
254    Glyph* fGlyphs;
255
256    friend class SkGFontBuilder;
257    SkGFont(int count, Glyph* array);
258};
259
260class SkGFontBuilder {
261public:
262
263};
264#endif
265