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