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