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