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