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