1
2/*
3 * Copyright 2006 The Android Open Source Project
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 "SkScalerContext.h"
11#include "SkColorPriv.h"
12#include "SkDescriptor.h"
13#include "SkDraw.h"
14#include "SkFontHost.h"
15#include "SkGlyph.h"
16#include "SkMaskFilter.h"
17#include "SkMaskGamma.h"
18#include "SkOrderedReadBuffer.h"
19#include "SkPathEffect.h"
20#include "SkRasterizer.h"
21#include "SkRasterClip.h"
22#include "SkStroke.h"
23#include "SkThread.h"
24
25
26#define ComputeBWRowBytes(width)        (((unsigned)(width) + 7) >> 3)
27
28void SkGlyph::toMask(SkMask* mask) const {
29    SkASSERT(mask);
30
31    mask->fImage = (uint8_t*)fImage;
32    mask->fBounds.set(fLeft, fTop, fLeft + fWidth, fTop + fHeight);
33    mask->fRowBytes = this->rowBytes();
34    mask->fFormat = static_cast<SkMask::Format>(fMaskFormat);
35}
36
37size_t SkGlyph::computeImageSize() const {
38    const size_t size = this->rowBytes() * fHeight;
39
40    switch (fMaskFormat) {
41        case SkMask::k3D_Format:
42            return 3 * size;
43        default:
44            return size;
45    }
46}
47
48void SkGlyph::zeroMetrics() {
49    fAdvanceX = 0;
50    fAdvanceY = 0;
51    fWidth    = 0;
52    fHeight   = 0;
53    fTop      = 0;
54    fLeft     = 0;
55    fRsbDelta = 0;
56    fLsbDelta = 0;
57}
58
59///////////////////////////////////////////////////////////////////////////////
60
61#ifdef SK_DEBUG
62    #define DUMP_RECx
63#endif
64
65static SkFlattenable* load_flattenable(const SkDescriptor* desc, uint32_t tag) {
66    SkFlattenable*  obj = NULL;
67    uint32_t        len;
68    const void*     data = desc->findEntry(tag, &len);
69
70    if (data) {
71        SkOrderedReadBuffer   buffer(data, len);
72        obj = buffer.readFlattenable();
73        SkASSERT(buffer.offset() == buffer.size());
74    }
75    return obj;
76}
77
78SkScalerContext::SkScalerContext(const SkDescriptor* desc)
79    : fRec(*static_cast<const Rec*>(desc->findEntry(kRec_SkDescriptorTag, NULL)))
80
81    , fBaseGlyphCount(0)
82
83    , fPathEffect(static_cast<SkPathEffect*>(load_flattenable(desc, kPathEffect_SkDescriptorTag)))
84    , fMaskFilter(static_cast<SkMaskFilter*>(load_flattenable(desc, kMaskFilter_SkDescriptorTag)))
85    , fRasterizer(static_cast<SkRasterizer*>(load_flattenable(desc, kRasterizer_SkDescriptorTag)))
86
87      // Initialize based on our settings. Subclasses can also force this.
88    , fGenerateImageFromPath(fRec.fFrameWidth > 0 || fPathEffect != NULL || fRasterizer != NULL)
89
90    , fNextContext(NULL)
91
92    , fPreBlend(fMaskFilter ? SkMaskGamma::PreBlend() : SkScalerContext::GetMaskPreBlend(fRec))
93    , fPreBlendForFilter(fMaskFilter ? SkScalerContext::GetMaskPreBlend(fRec)
94                                     : SkMaskGamma::PreBlend())
95{
96#ifdef DUMP_REC
97    desc->assertChecksum();
98    SkDebugf("SkScalarContext checksum %x count %d length %d\n",
99             desc->getChecksum(), desc->getCount(), desc->getLength());
100    SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n",
101        rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0],
102        rec->fPost2x2[0][1], rec->fPost2x2[1][0], rec->fPost2x2[1][1]);
103    SkDebugf("  frame %g miter %g hints %d framefill %d format %d join %d\n",
104        rec->fFrameWidth, rec->fMiterLimit, rec->fHints, rec->fFrameAndFill,
105        rec->fMaskFormat, rec->fStrokeJoin);
106    SkDebugf("  pathEffect %x maskFilter %x\n",
107             desc->findEntry(kPathEffect_SkDescriptorTag, NULL),
108        desc->findEntry(kMaskFilter_SkDescriptorTag, NULL));
109#endif
110}
111
112SkScalerContext::~SkScalerContext() {
113    SkDELETE(fNextContext);
114
115    SkSafeUnref(fPathEffect);
116    SkSafeUnref(fMaskFilter);
117    SkSafeUnref(fRasterizer);
118}
119
120static SkScalerContext* allocNextContext(const SkScalerContext::Rec& rec) {
121    // fonthost will determine the next possible font to search, based
122    // on the current font in fRec. It will return NULL if ctx is our
123    // last font that can be searched (i.e. ultimate fallback font)
124#ifdef SK_BUILD_FOR_ANDROID
125        // On Android, pass entire rec structure so that clients can change fallback behavior
126        uint32_t newFontID = SkFontHost::NextLogicalFont(rec);
127#else
128        uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID);
129#endif
130
131    if (0 == newFontID) {
132        return NULL;
133    }
134
135    SkAutoDescriptor    ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
136    SkDescriptor*       desc = ad.getDesc();
137
138    desc->init();
139    SkScalerContext::Rec* newRec =
140    (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
141                                          sizeof(rec), &rec);
142    newRec->fFontID = newFontID;
143    desc->computeChecksum();
144
145    return SkFontHost::CreateScalerContext(desc);
146}
147
148/*  Return the next context, creating it if its not already created, but return
149    NULL if the fonthost says there are no more fonts to fallback to.
150 */
151SkScalerContext* SkScalerContext::getNextContext() {
152    SkScalerContext* next = fNextContext;
153    // if next is null, then either it isn't cached yet, or we're at the
154    // end of our possible chain
155    if (NULL == next) {
156        next = allocNextContext(fRec);
157        if (NULL == next) {
158            return NULL;
159        }
160        // next's base is our base + our local count
161        next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount());
162        // cache the answer
163        fNextContext = next;
164    }
165    return next;
166}
167
168SkScalerContext* SkScalerContext::getContextFromChar(SkUnichar uni, unsigned& glyphID) {
169    SkScalerContext* ctx = this;
170    for (;;) {
171        glyphID = ctx->generateCharToGlyph(uni);
172        if (glyphID) {
173            break;  // found it
174        }
175        ctx = ctx->getNextContext();
176        if (NULL == ctx) {
177            return NULL;
178        }
179    }
180    return ctx;
181}
182
183SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) {
184    unsigned glyphID = glyph.getGlyphID();
185    SkScalerContext* ctx = this;
186    for (;;) {
187        unsigned count = ctx->getGlyphCount();
188        if (glyphID < count) {
189            break;
190        }
191        glyphID -= count;
192        ctx = ctx->getNextContext();
193        if (NULL == ctx) {
194//            SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID());
195            // just return the original context (this)
196            return this;
197        }
198    }
199    return ctx;
200}
201
202#ifdef SK_BUILD_FOR_ANDROID
203SkFontID SkScalerContext::findTypefaceIdForChar(SkUnichar uni) {
204    unsigned glyphID;
205    SkScalerContext* ctx = getContextFromChar(uni, glyphID);
206    if (ctx) {
207        return ctx->fRec.fFontID;
208    } else {
209        return 0;
210    }
211}
212
213/*  This loops through all available fallback contexts (if needed) until it
214    finds some context that can handle the unichar and return it.
215
216    As this is somewhat expensive operation, it should only be done on the first
217    char of a run.
218 */
219unsigned SkScalerContext::getBaseGlyphCount(SkUnichar uni) {
220    unsigned glyphID;
221    SkScalerContext* ctx = getContextFromChar(uni, glyphID);
222    if (ctx) {
223        return ctx->fBaseGlyphCount;
224    } else {
225        SkDEBUGF(("--- no context for char %x\n", uni));
226        return this->fBaseGlyphCount;
227    }
228}
229#endif
230
231/*  This loops through all available fallback contexts (if needed) until it
232    finds some context that can handle the unichar. If all fail, returns 0
233 */
234uint16_t SkScalerContext::charToGlyphID(SkUnichar uni) {
235
236    unsigned glyphID;
237    SkScalerContext* ctx = getContextFromChar(uni, glyphID);
238    if (!ctx) {
239        return 0; // no more contexts, return missing glyph
240    }
241    // add the ctx's base, making glyphID unique for chain of contexts
242    glyphID += ctx->fBaseGlyphCount;
243    // check for overflow of 16bits, since our glyphID cannot exceed that
244    if (glyphID > 0xFFFF) {
245        glyphID = 0;
246    }
247    return SkToU16(glyphID);
248}
249
250SkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) {
251    SkScalerContext* ctx = this;
252    unsigned rangeEnd = 0;
253    do {
254        unsigned rangeStart = rangeEnd;
255
256        rangeEnd += ctx->getGlyphCount();
257        if (rangeStart <= glyphID && glyphID < rangeEnd) {
258            return ctx->generateGlyphToChar(glyphID - rangeStart);
259        }
260        ctx = ctx->getNextContext();
261    } while (NULL != ctx);
262    return 0;
263}
264
265void SkScalerContext::getAdvance(SkGlyph* glyph) {
266    // mark us as just having a valid advance
267    glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE;
268    // we mark the format before making the call, in case the impl
269    // internally ends up calling its generateMetrics, which is OK
270    // albeit slower than strictly necessary
271    this->getGlyphContext(*glyph)->generateAdvance(glyph);
272}
273
274void SkScalerContext::getMetrics(SkGlyph* glyph) {
275    this->getGlyphContext(*glyph)->generateMetrics(glyph);
276
277    // for now we have separate cache entries for devkerning on and off
278    // in the future we might share caches, but make our measure/draw
279    // code make the distinction. Thus we zap the values if the caller
280    // has not asked for them.
281    if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
282        // no devkern, so zap the fields
283        glyph->fLsbDelta = glyph->fRsbDelta = 0;
284    }
285
286    // if either dimension is empty, zap the image bounds of the glyph
287    if (0 == glyph->fWidth || 0 == glyph->fHeight) {
288        glyph->fWidth   = 0;
289        glyph->fHeight  = 0;
290        glyph->fTop     = 0;
291        glyph->fLeft    = 0;
292        glyph->fMaskFormat = 0;
293        return;
294    }
295
296    if (fGenerateImageFromPath) {
297        SkPath      devPath, fillPath;
298        SkMatrix    fillToDevMatrix;
299
300        this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
301
302        if (fRasterizer) {
303            SkMask  mask;
304
305            if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
306                                       fMaskFilter, &mask,
307                                       SkMask::kJustComputeBounds_CreateMode)) {
308                glyph->fLeft    = mask.fBounds.fLeft;
309                glyph->fTop     = mask.fBounds.fTop;
310                glyph->fWidth   = SkToU16(mask.fBounds.width());
311                glyph->fHeight  = SkToU16(mask.fBounds.height());
312            } else {
313                goto SK_ERROR;
314            }
315        } else {
316            // just use devPath
317            SkIRect ir;
318            devPath.getBounds().roundOut(&ir);
319
320            if (ir.isEmpty() || !ir.is16Bit()) {
321                goto SK_ERROR;
322            }
323            glyph->fLeft    = ir.fLeft;
324            glyph->fTop     = ir.fTop;
325            glyph->fWidth   = SkToU16(ir.width());
326            glyph->fHeight  = SkToU16(ir.height());
327        }
328    }
329
330    if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
331        glyph->fMaskFormat = fRec.fMaskFormat;
332    }
333
334    if (fMaskFilter) {
335        SkMask      src, dst;
336        SkMatrix    matrix;
337
338        glyph->toMask(&src);
339        fRec.getMatrixFrom2x2(&matrix);
340
341        src.fImage = NULL;  // only want the bounds from the filter
342        if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) {
343            if (dst.fBounds.isEmpty() || !dst.fBounds.is16Bit()) {
344                goto SK_ERROR;
345            }
346            SkASSERT(dst.fImage == NULL);
347            glyph->fLeft    = dst.fBounds.fLeft;
348            glyph->fTop     = dst.fBounds.fTop;
349            glyph->fWidth   = SkToU16(dst.fBounds.width());
350            glyph->fHeight  = SkToU16(dst.fBounds.height());
351            glyph->fMaskFormat = dst.fFormat;
352        }
353    }
354    return;
355
356SK_ERROR:
357    // draw nothing 'cause we failed
358    glyph->fLeft    = 0;
359    glyph->fTop     = 0;
360    glyph->fWidth   = 0;
361    glyph->fHeight  = 0;
362    // put a valid value here, in case it was earlier set to
363    // MASK_FORMAT_JUST_ADVANCE
364    glyph->fMaskFormat = fRec.fMaskFormat;
365}
366
367
368static void applyLUTToA8Mask(const SkMask& mask, const uint8_t* lut) {
369    uint8_t* SK_RESTRICT dst = (uint8_t*)mask.fImage;
370    unsigned rowBytes = mask.fRowBytes;
371
372    for (int y = mask.fBounds.height() - 1; y >= 0; --y) {
373        for (int x = mask.fBounds.width() - 1; x >= 0; --x) {
374            dst[x] = lut[dst[x]];
375        }
376        dst += rowBytes;
377    }
378}
379
380template<bool APPLY_PREBLEND>
381static void pack3xHToLCD16(const SkBitmap& src, const SkMask& dst,
382                           const SkMaskGamma::PreBlend& maskPreBlend) {
383    SkASSERT(SkBitmap::kA8_Config == src.config());
384    SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
385
386    const int width = dst.fBounds.width();
387    const int height = dst.fBounds.height();
388    uint16_t* dstP = (uint16_t*)dst.fImage;
389    size_t dstRB = dst.fRowBytes;
390
391    for (int y = 0; y < height; ++y) {
392        const uint8_t* srcP = src.getAddr8(0, y);
393        for (int x = 0; x < width; ++x) {
394            U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fR);
395            U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fG);
396            U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fB);
397            dstP[x] = SkPack888ToRGB16(r, g, b);
398        }
399        dstP = (uint16_t*)((char*)dstP + dstRB);
400    }
401}
402
403template<bool APPLY_PREBLEND>
404static void pack3xHToLCD32(const SkBitmap& src, const SkMask& dst,
405                           const SkMaskGamma::PreBlend& maskPreBlend) {
406    SkASSERT(SkBitmap::kA8_Config == src.config());
407    SkASSERT(SkMask::kLCD32_Format == dst.fFormat);
408
409    const int width = dst.fBounds.width();
410    const int height = dst.fBounds.height();
411    SkPMColor* dstP = (SkPMColor*)dst.fImage;
412    size_t dstRB = dst.fRowBytes;
413
414    for (int y = 0; y < height; ++y) {
415        const uint8_t* srcP = src.getAddr8(0, y);
416        for (int x = 0; x < width; ++x) {
417            U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fR);
418            U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fG);
419            U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fB);
420            dstP[x] = SkPackARGB32(0xFF, r, g, b);
421        }
422        dstP = (SkPMColor*)((char*)dstP + dstRB);
423    }
424}
425
426static void generateMask(const SkMask& mask, const SkPath& path,
427                         const SkMaskGamma::PreBlend& maskPreBlend) {
428    SkBitmap::Config config;
429    SkPaint     paint;
430
431    int srcW = mask.fBounds.width();
432    int srcH = mask.fBounds.height();
433    int dstW = srcW;
434    int dstH = srcH;
435    int dstRB = mask.fRowBytes;
436
437    SkMatrix matrix;
438    matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
439                        -SkIntToScalar(mask.fBounds.fTop));
440
441    if (SkMask::kBW_Format == mask.fFormat) {
442        config = SkBitmap::kA1_Config;
443        paint.setAntiAlias(false);
444    } else {
445        config = SkBitmap::kA8_Config;
446        paint.setAntiAlias(true);
447        switch (mask.fFormat) {
448            case SkMask::kA8_Format:
449                break;
450            case SkMask::kLCD16_Format:
451            case SkMask::kLCD32_Format:
452                // TODO: trigger off LCD orientation
453                dstW *= 3;
454                matrix.postScale(SkIntToScalar(3), SK_Scalar1);
455                dstRB = 0;  // signals we need a copy
456                break;
457            default:
458                SkDEBUGFAIL("unexpected mask format");
459        }
460    }
461
462    SkRasterClip clip;
463    clip.setRect(SkIRect::MakeWH(dstW, dstH));
464
465    SkBitmap bm;
466    bm.setConfig(config, dstW, dstH, dstRB);
467
468    if (0 == dstRB) {
469        if (!bm.allocPixels()) {
470            // can't allocate offscreen, so empty the mask and return
471            sk_bzero(mask.fImage, mask.computeImageSize());
472            return;
473        }
474        bm.lockPixels();
475    } else {
476        bm.setPixels(mask.fImage);
477    }
478    sk_bzero(bm.getPixels(), bm.getSafeSize());
479
480    SkDraw  draw;
481    draw.fRC    = &clip;
482    draw.fClip  = &clip.bwRgn();
483    draw.fMatrix = &matrix;
484    draw.fBitmap = &bm;
485    draw.drawPath(path, paint);
486
487    switch (mask.fFormat) {
488        case SkMask::kA8_Format:
489            if (maskPreBlend.isApplicable()) {
490                applyLUTToA8Mask(mask, maskPreBlend.fG);
491            }
492            break;
493        case SkMask::kLCD16_Format:
494            if (maskPreBlend.isApplicable()) {
495                pack3xHToLCD16<true>(bm, mask, maskPreBlend);
496            } else {
497                pack3xHToLCD16<false>(bm, mask, maskPreBlend);
498            }
499            break;
500        case SkMask::kLCD32_Format:
501            if (maskPreBlend.isApplicable()) {
502                pack3xHToLCD32<true>(bm, mask, maskPreBlend);
503            } else {
504                pack3xHToLCD32<false>(bm, mask, maskPreBlend);
505            }
506            break;
507        default:
508            break;
509    }
510}
511
512void SkScalerContext::getImage(const SkGlyph& origGlyph) {
513    const SkGlyph*  glyph = &origGlyph;
514    SkGlyph         tmpGlyph;
515
516    if (fMaskFilter) {   // restore the prefilter bounds
517        tmpGlyph.init(origGlyph.fID);
518
519        // need the original bounds, sans our maskfilter
520        SkMaskFilter* mf = fMaskFilter;
521        fMaskFilter = NULL;             // temp disable
522        this->getMetrics(&tmpGlyph);
523        fMaskFilter = mf;               // restore
524
525        tmpGlyph.fImage = origGlyph.fImage;
526
527        // we need the prefilter bounds to be <= filter bounds
528        SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
529        SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
530        glyph = &tmpGlyph;
531    }
532
533    if (fGenerateImageFromPath) {
534        SkPath      devPath, fillPath;
535        SkMatrix    fillToDevMatrix;
536        SkMask      mask;
537
538        this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
539        glyph->toMask(&mask);
540
541        if (fRasterizer) {
542            mask.fFormat = SkMask::kA8_Format;
543            sk_bzero(glyph->fImage, mask.computeImageSize());
544
545            if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
546                                        fMaskFilter, &mask,
547                                        SkMask::kJustRenderImage_CreateMode)) {
548                return;
549            }
550            if (fPreBlend.isApplicable()) {
551                applyLUTToA8Mask(mask, fPreBlend.fG);
552            }
553        } else {
554            generateMask(mask, devPath, fPreBlend);
555        }
556    } else {
557        this->getGlyphContext(*glyph)->generateImage(*glyph);
558    }
559
560    if (fMaskFilter) {
561        SkMask      srcM, dstM;
562        SkMatrix    matrix;
563
564        // the src glyph image shouldn't be 3D
565        SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
566        glyph->toMask(&srcM);
567        fRec.getMatrixFrom2x2(&matrix);
568
569        if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
570            int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
571            int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
572            int dstRB = origGlyph.rowBytes();
573            int srcRB = dstM.fRowBytes;
574
575            const uint8_t* src = (const uint8_t*)dstM.fImage;
576            uint8_t* dst = (uint8_t*)origGlyph.fImage;
577
578            if (SkMask::k3D_Format == dstM.fFormat) {
579                // we have to copy 3 times as much
580                height *= 3;
581            }
582
583            // clean out our glyph, since it may be larger than dstM
584            //sk_bzero(dst, height * dstRB);
585
586            while (--height >= 0) {
587                memcpy(dst, src, width);
588                src += srcRB;
589                dst += dstRB;
590            }
591            SkMask::FreeImage(dstM.fImage);
592
593            if (fPreBlendForFilter.isApplicable()) {
594                applyLUTToA8Mask(srcM, fPreBlendForFilter.fG);
595            }
596        }
597    }
598}
599
600void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) {
601    this->internalGetPath(glyph, NULL, path, NULL);
602}
603
604void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx,
605                                     SkPaint::FontMetrics* my) {
606    this->generateFontMetrics(mx, my);
607}
608
609SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) {
610    return 0;
611}
612
613///////////////////////////////////////////////////////////////////////////////
614
615void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
616                                  SkPath* devPath, SkMatrix* fillToDevMatrix) {
617    SkPath  path;
618
619    this->getGlyphContext(glyph)->generatePath(glyph, &path);
620
621    if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
622        SkFixed dx = glyph.getSubXFixed();
623        SkFixed dy = glyph.getSubYFixed();
624        if (dx | dy) {
625            path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy));
626        }
627    }
628
629    if (fRec.fFrameWidth > 0 || fPathEffect != NULL) {
630        // need the path in user-space, with only the point-size applied
631        // so that our stroking and effects will operate the same way they
632        // would if the user had extracted the path themself, and then
633        // called drawPath
634        SkPath      localPath;
635        SkMatrix    matrix, inverse;
636
637        fRec.getMatrixFrom2x2(&matrix);
638        if (!matrix.invert(&inverse)) {
639            // assume fillPath and devPath are already empty.
640            return;
641        }
642        path.transform(inverse, &localPath);
643        // now localPath is only affected by the paint settings, and not the canvas matrix
644
645        SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
646
647        if (fRec.fFrameWidth > 0) {
648            rec.setStrokeStyle(fRec.fFrameWidth,
649                               SkToBool(fRec.fFlags & kFrameAndFill_Flag));
650            // glyphs are always closed contours, so cap type is ignored,
651            // so we just pass something.
652            rec.setStrokeParams(SkPaint::kButt_Cap,
653                                (SkPaint::Join)fRec.fStrokeJoin,
654                                fRec.fMiterLimit);
655        }
656
657        if (fPathEffect) {
658            SkPath effectPath;
659            if (fPathEffect->filterPath(&effectPath, localPath, &rec, NULL)) {
660                localPath.swap(effectPath);
661            }
662        }
663
664        if (rec.needToApply()) {
665            SkPath strokePath;
666            if (rec.applyToPath(&strokePath, localPath)) {
667                localPath.swap(strokePath);
668            }
669        }
670
671        // now return stuff to the caller
672        if (fillToDevMatrix) {
673            *fillToDevMatrix = matrix;
674        }
675        if (devPath) {
676            localPath.transform(matrix, devPath);
677        }
678        if (fillPath) {
679            fillPath->swap(localPath);
680        }
681    } else {   // nothing tricky to do
682        if (fillToDevMatrix) {
683            fillToDevMatrix->reset();
684        }
685        if (devPath) {
686            if (fillPath == NULL) {
687                devPath->swap(path);
688            } else {
689                *devPath = path;
690            }
691        }
692
693        if (fillPath) {
694            fillPath->swap(path);
695        }
696    }
697
698    if (devPath) {
699        devPath->updateBoundsCache();
700    }
701    if (fillPath) {
702        fillPath->updateBoundsCache();
703    }
704}
705
706
707void SkScalerContextRec::getMatrixFrom2x2(SkMatrix* dst) const {
708    dst->setAll(fPost2x2[0][0], fPost2x2[0][1], 0,
709                fPost2x2[1][0], fPost2x2[1][1], 0,
710                0,              0,              SkScalarToPersp(SK_Scalar1));
711}
712
713void SkScalerContextRec::getLocalMatrix(SkMatrix* m) const {
714    m->setScale(SkScalarMul(fTextSize, fPreScaleX), fTextSize);
715    if (fPreSkewX) {
716        m->postSkew(fPreSkewX, 0);
717    }
718}
719
720void SkScalerContextRec::getSingleMatrix(SkMatrix* m) const {
721    this->getLocalMatrix(m);
722
723    //  now concat the device matrix
724    SkMatrix    deviceMatrix;
725    this->getMatrixFrom2x2(&deviceMatrix);
726    m->postConcat(deviceMatrix);
727}
728
729SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix) {
730    SkASSERT(!matrix.hasPerspective());
731
732    if (0 == matrix[SkMatrix::kMSkewY]) {
733        return kX_SkAxisAlignment;
734    }
735    if (0 == matrix[SkMatrix::kMScaleX]) {
736        return kY_SkAxisAlignment;
737    }
738    return kNone_SkAxisAlignment;
739}
740
741///////////////////////////////////////////////////////////////////////////////
742
743#include "SkFontHost.h"
744
745class SkScalerContext_Empty : public SkScalerContext {
746public:
747    SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {}
748
749protected:
750    virtual unsigned generateGlyphCount() SK_OVERRIDE {
751        return 0;
752    }
753    virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE {
754        return 0;
755    }
756    virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE {
757        glyph->zeroMetrics();
758    }
759    virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE {
760        glyph->zeroMetrics();
761    }
762    virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE {}
763    virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE {}
764    virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
765                                     SkPaint::FontMetrics* my) SK_OVERRIDE {
766        if (mx) {
767            sk_bzero(mx, sizeof(*mx));
768        }
769        if (my) {
770            sk_bzero(my, sizeof(*my));
771        }
772    }
773};
774
775extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
776
777SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) {
778    SkScalerContext* c = NULL;  //SkCreateColorScalerContext(desc);
779    if (NULL == c) {
780        c = SkFontHost::CreateScalerContext(desc);
781    }
782    if (NULL == c) {
783        c = SkNEW_ARGS(SkScalerContext_Empty, (desc));
784    }
785    return c;
786}
787