SkScalerContext.cpp revision 1cab2921ab279367f8206cdadc9259d12e603548
11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScalerContext.h"
11af2616552738d653d5453915d3236e7154b868cdMike Reed#include "SkColorPriv.h"
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkDescriptor.h"
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkDraw.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFontHost.h"
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMaskFilter.h"
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPathEffect.h"
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRasterizer.h"
181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkRasterClip.h"
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStroke.h"
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkThread.h"
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define ComputeBWRowBytes(width)        (((unsigned)(width) + 7) >> 3)
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkGlyph::toMask(SkMask* mask) const {
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(mask);
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    mask->fImage = (uint8_t*)fImage;
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    mask->fBounds.set(fLeft, fTop, fLeft + fWidth, fTop + fHeight);
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    mask->fRowBytes = this->rowBytes();
30aa4832adcc7eba085987357591bcfeb530ba7b0dMike Reed    mask->fFormat = static_cast<SkMask::Format>(fMaskFormat);
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectsize_t SkGlyph::computeImageSize() const {
34af2616552738d653d5453915d3236e7154b868cdMike Reed    const size_t size = this->rowBytes() * fHeight;
35af2616552738d653d5453915d3236e7154b868cdMike Reed
36af2616552738d653d5453915d3236e7154b868cdMike Reed    switch (fMaskFormat) {
3787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        case SkMask::k3D_Format:
3887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            return 3 * size;
3987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        default:
4087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            return size;
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkGlyph::zeroMetrics() {
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fAdvanceX = 0;
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fAdvanceY = 0;
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fWidth    = 0;
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fHeight   = 0;
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fTop      = 0;
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fLeft     = 0;
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRsbDelta = 0;
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fLsbDelta = 0;
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    #define DUMP_RECx
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkFlattenable* load_flattenable(const SkDescriptor* desc, uint32_t tag) {
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFlattenable*  obj = NULL;
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t        len;
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const void*     data = desc->findEntry(tag, &len);
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (data) {
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkFlattenableReadBuffer   buffer(data, len);
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        obj = buffer.readFlattenable();
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(buffer.offset() == buffer.size());
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return obj;
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalerContext::SkScalerContext(const SkDescriptor* desc)
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    : fPathEffect(NULL), fMaskFilter(NULL)
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBaseGlyphCount = 0;
78af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    fNextContext = NULL;
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const Rec* rec = (const Rec*)desc->findEntry(kRec_SkDescriptorTag, NULL);
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(rec);
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRec = *rec;
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef DUMP_REC
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    desc->assertChecksum();
8787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    SkDebugf("SkScalarContext checksum %x count %d length %d\n",
8887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger             desc->getChecksum(), desc->getCount(), desc->getLength());
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n",
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0],
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fPost2x2[0][1], rec->fPost2x2[1][0], rec->fPost2x2[1][1]);
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDebugf("  frame %g miter %g hints %d framefill %d format %d join %d\n",
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fFrameWidth, rec->fMiterLimit, rec->fHints, rec->fFrameAndFill,
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fMaskFormat, rec->fStrokeJoin);
9587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    SkDebugf("  pathEffect %x maskFilter %x\n",
9687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger             desc->findEntry(kPathEffect_SkDescriptorTag, NULL),
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        desc->findEntry(kMaskFilter_SkDescriptorTag, NULL));
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPathEffect = (SkPathEffect*)load_flattenable(desc, kPathEffect_SkDescriptorTag);
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fMaskFilter = (SkMaskFilter*)load_flattenable(desc, kMaskFilter_SkDescriptorTag);
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRasterizer = (SkRasterizer*)load_flattenable(desc, kRasterizer_SkDescriptorTag);
1031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // initialize based on our settings. subclasses can also force this
1051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fGenerateImageFromPath = fRec.fFrameWidth > 0 || fPathEffect != NULL ||
1061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             fRasterizer != NULL;
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalerContext::~SkScalerContext() {
110af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkDELETE(fNextContext);
111af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project
11240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fPathEffect);
11340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fMaskFilter);
11440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fRasterizer);
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
117af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Projectstatic SkScalerContext* allocNextContext(const SkScalerContext::Rec& rec) {
118af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // fonthost will determine the next possible font to search, based
119af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // on the current font in fRec. It will return NULL if ctx is our
120af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // last font that can be searched (i.e. ultimate fallback font)
1210199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger    uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID);
122af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    if (0 == newFontID) {
123af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        return NULL;
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
126af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkAutoDescriptor    ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
127af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkDescriptor*       desc = ad.getDesc();
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
129af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    desc->init();
130af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkScalerContext::Rec* newRec =
131af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
132af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project                                          sizeof(rec), &rec);
133af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    newRec->fFontID = newFontID;
134af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    desc->computeChecksum();
135af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project
136af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return SkFontHost::CreateScalerContext(desc);
137af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project}
138af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project
139af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project/*  Return the next context, creating it if its not already created, but return
140af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    NULL if the fonthost says there are no more fonts to fallback to.
141af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project */
142af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source ProjectSkScalerContext* SkScalerContext::getNextContext() {
143af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkScalerContext* next = fNextContext;
144af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // if next is null, then either it isn't cached yet, or we're at the
145af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // end of our possible chain
146af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    if (NULL == next) {
147af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        next = allocNextContext(fRec);
148af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (NULL == next) {
149af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            return NULL;
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
151af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        // next's base is our base + our local count
152af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount());
153af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        // cache the answer
154af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        fNextContext = next;
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
156af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return next;
157af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project}
158af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project
159af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source ProjectSkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) {
160af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    unsigned glyphID = glyph.getGlyphID();
161af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkScalerContext* ctx = this;
162af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    for (;;) {
163af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        unsigned count = ctx->getGlyphCount();
164af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (glyphID < count) {
165af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            break;
1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
167af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        glyphID -= count;
168af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        ctx = ctx->getNextContext();
169af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (NULL == ctx) {
170af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID());
171af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            // just return the original context (this)
172af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            return this;
1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
175af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return ctx;
1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*  This loops through all available fallback contexts (if needed) until it
1801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    finds some context that can handle the unichar and return it.
1811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    As this is somewhat expensive operation, it should only be done on the first
1831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    char of a run.
1841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
1851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerunsigned SkScalerContext::getBaseGlyphCount(SkUnichar uni) {
1861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkScalerContext* ctx = this;
1871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    unsigned glyphID;
1881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (;;) {
1891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        glyphID = ctx->generateCharToGlyph(uni);
1901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (glyphID) {
1911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            break;  // found it
1921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
1931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        ctx = ctx->getNextContext();
1941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (NULL == ctx) {
1951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDebugf("--- no context for char %x\n", uni);
1961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // just return the original context (this)
1971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            return this->fBaseGlyphCount;
1981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
1991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return ctx->fBaseGlyphCount;
2011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
2031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
204af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project/*  This loops through all available fallback contexts (if needed) until it
205af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    finds some context that can handle the unichar. If all fail, returns 0
206af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project */
207af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Projectuint16_t SkScalerContext::charToGlyphID(SkUnichar uni) {
208af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkScalerContext* ctx = this;
209af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    unsigned glyphID;
210af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    for (;;) {
211af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        glyphID = ctx->generateCharToGlyph(uni);
212af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (glyphID) {
213af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            break;  // found it
214af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        }
215af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        ctx = ctx->getNextContext();
216af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (NULL == ctx) {
217af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            return 0;   // no more contexts, return missing glyph
2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
220af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // add the ctx's base, making glyphID unique for chain of contexts
221af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    glyphID += ctx->fBaseGlyphCount;
222af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // check for overflow of 16bits, since our glyphID cannot exceed that
223af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    if (glyphID > 0xFFFF) {
224af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        glyphID = 0;
225af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    }
226af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return SkToU16(glyphID);
2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
229091f227385b467090b5a7169a8e2faf19eca7105Mike ReedSkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) {
230091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    SkScalerContext* ctx = this;
231091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    unsigned rangeEnd = 0;
232091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    do {
233091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        unsigned rangeStart = rangeEnd;
234091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
235091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        rangeEnd += ctx->getGlyphCount();
236091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        if (rangeStart <= glyphID && glyphID < rangeEnd) {
237091f227385b467090b5a7169a8e2faf19eca7105Mike Reed            return ctx->generateGlyphToChar(glyphID - rangeStart);
238091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        }
239091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        ctx = ctx->getNextContext();
240091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    } while (NULL != ctx);
241091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    return 0;
242091f227385b467090b5a7169a8e2faf19eca7105Mike Reed}
243091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::getAdvance(SkGlyph* glyph) {
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // mark us as just having a valid advance
2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE;
2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // we mark the format before making the call, in case the impl
2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // internally ends up calling its generateMetrics, which is OK
2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // albeit slower than strictly necessary
2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getGlyphContext(*glyph)->generateAdvance(glyph);
2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::getMetrics(SkGlyph* glyph) {
2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getGlyphContext(*glyph)->generateMetrics(glyph);
2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // for now we have separate cache entries for devkerning on and off
2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // in the future we might share caches, but make our measure/draw
2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // code make the distinction. Thus we zap the values if the caller
2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // has not asked for them.
2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // no devkern, so zap the fields
2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fLsbDelta = glyph->fRsbDelta = 0;
2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // if either dimension is empty, zap the image bounds of the glyph
2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (0 == glyph->fWidth || 0 == glyph->fHeight) {
2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fWidth   = 0;
2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fHeight  = 0;
2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fTop     = 0;
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fLeft    = 0;
2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fMaskFormat = 0;
2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
27440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
2751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fGenerateImageFromPath) {
2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPath      devPath, fillPath;
2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    fillToDevMatrix;
2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fRasterizer) {
2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkMask  mask;
2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                       fMaskFilter, &mask,
2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                       SkMask::kJustComputeBounds_CreateMode)) {
2870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fLeft    = mask.fBounds.fLeft;
2880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fTop     = mask.fBounds.fTop;
2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fWidth   = SkToU16(mask.fBounds.width());
2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fHeight  = SkToU16(mask.fBounds.height());
2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
292030ffe05175291b1d91ec6808e1a32e862ee90cdMike Reed                goto SK_ERROR;
2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // just use devPath
2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkIRect ir;
2970e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed            devPath.getBounds().roundOut(&ir);
29840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
299a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed            if (ir.isEmpty() || !ir.is16Bit()) {
300030ffe05175291b1d91ec6808e1a32e862ee90cdMike Reed                goto SK_ERROR;
301a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed            }
3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fLeft    = ir.fLeft;
3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fTop     = ir.fTop;
3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fWidth   = SkToU16(ir.width());
3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fHeight  = SkToU16(ir.height());
3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
30940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger	if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
31040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger		glyph->fMaskFormat = fRec.fMaskFormat;
31140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger	}
3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fMaskFilter) {
3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMask      src, dst;
3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    matrix;
3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->toMask(&src);
3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec.getMatrixFrom2x2(&matrix);
3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        src.fImage = NULL;  // only want the bounds from the filter
3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) {
3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(dst.fImage == NULL);
3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fLeft    = dst.fBounds.fLeft;
3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fTop     = dst.fBounds.fTop;
3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fWidth   = SkToU16(dst.fBounds.width());
3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fHeight  = SkToU16(dst.fBounds.height());
3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fMaskFormat = dst.fFormat;
3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
330a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    return;
33140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
332030ffe05175291b1d91ec6808e1a32e862ee90cdMike ReedSK_ERROR:
333a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    // draw nothing 'cause we failed
334a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    glyph->fLeft    = 0;
335a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    glyph->fTop     = 0;
336a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    glyph->fWidth   = 0;
337a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    glyph->fHeight  = 0;
33893d11b5b461a8677a8e3ffa94260f4f9897070acMike Reed    // put a valid value here, in case it was earlier set to
33993d11b5b461a8677a8e3ffa94260f4f9897070acMike Reed    // MASK_FORMAT_JUST_ADVANCE
34093d11b5b461a8677a8e3ffa94260f4f9897070acMike Reed    glyph->fMaskFormat = fRec.fMaskFormat;
3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool isLCD(const SkScalerContext::Rec& rec) {
3441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkMask::kLCD16_Format == rec.fMaskFormat ||
3451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger           SkMask::kLCD32_Format == rec.fMaskFormat;
3461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic uint16_t a8_to_rgb565(unsigned a8) {
3491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkPackRGB16(a8 >> 3, a8 >> 2, a8 >> 3);
3501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void copyToLCD16(const SkBitmap& src, const SkMask& dst) {
3531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkBitmap::kA8_Config == src.config());
3541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
3551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int width = dst.fBounds.width();
3571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int height = dst.fBounds.height();
3581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const uint8_t* srcP = src.getAddr8(0, 0);
3591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    size_t srcRB = src.rowBytes();
3601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    uint16_t* dstP = (uint16_t*)dst.fImage;
3611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    size_t dstRB = dst.fRowBytes;
3621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int y = 0; y < height; ++y) {
3631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int x = 0; x < width; ++x) {
3641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            dstP[x] = a8_to_rgb565(srcP[x]);
3651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
3661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        srcP += srcRB;
3671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dstP = (uint16_t*)((char*)dstP + dstRB);
3681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
3691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define SK_FREETYPE_LCD_LERP    160
3721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic int lerp(int start, int end) {
3741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT((unsigned)SK_FREETYPE_LCD_LERP <= 256);
3751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return start + ((end - start) * (SK_FREETYPE_LCD_LERP) >> 8);
3761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic uint16_t packLCD16(unsigned r, unsigned g, unsigned b) {
3791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SK_FREETYPE_LCD_LERP) {
3801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // want (a+b+c)/3, but we approx to avoid the divide
3811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        unsigned ave = (5 * (r + g + b) + g) >> 4;
3821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        r = lerp(r, ave);
3831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        g = lerp(g, ave);
3841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        b = lerp(b, ave);
3851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
3861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkPackRGB16(r >> 3, g >> 2, b >> 3);
3871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void pack3xHToLCD16(const SkBitmap& src, const SkMask& dst) {
3901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkBitmap::kA8_Config == src.config());
3911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
3921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int width = dst.fBounds.width();
3941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int height = dst.fBounds.height();
3951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    uint16_t* dstP = (uint16_t*)dst.fImage;
3961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    size_t dstRB = dst.fRowBytes;
3971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int y = 0; y < height; ++y) {
3981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const uint8_t* srcP = src.getAddr8(0, y);
3991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int x = 0; x < width; ++x) {
4001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned r = *srcP++;
4011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned g = *srcP++;
4021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned b = *srcP++;
4031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            dstP[x] = packLCD16(r, g, b);
4041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dstP = (uint16_t*)((char*)dstP + dstRB);
4061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void pack3xHToLCD32(const SkBitmap& src, const SkMask& dst) {
4101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkBitmap::kA8_Config == src.config());
4111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkMask::kLCD32_Format == dst.fFormat);
4121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int width = dst.fBounds.width();
4141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int height = dst.fBounds.height();
4151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkPMColor* dstP = (SkPMColor*)dst.fImage;
4161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    size_t dstRB = dst.fRowBytes;
4171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int y = 0; y < height; ++y) {
4181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const uint8_t* srcP = src.getAddr8(0, y);
4191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int x = 0; x < width; ++x) {
4201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned r = *srcP++;
4211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned g = *srcP++;
4221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned b = *srcP++;
4231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned a = SkMax32(SkMax32(r, g), b);
4241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            dstP[x] = SkPackARGB32(a, r, g, b);
4251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dstP = (SkPMColor*)((char*)dstP + dstRB);
4271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void generateMask(const SkMask& mask, const SkPath& path) {
4311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkBitmap::Config config;
4321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkPaint     paint;
4331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int srcW = mask.fBounds.width();
4351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int srcH = mask.fBounds.height();
4361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int dstW = srcW;
4371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int dstH = srcH;
4381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int dstRB = mask.fRowBytes;
4391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMatrix matrix;
4411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
4421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        -SkIntToScalar(mask.fBounds.fTop));
4431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SkMask::kBW_Format == mask.fFormat) {
4451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        config = SkBitmap::kA1_Config;
4461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        paint.setAntiAlias(false);
4471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
4481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        config = SkBitmap::kA8_Config;
4491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        paint.setAntiAlias(true);
4501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        switch (mask.fFormat) {
4511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkMask::kA8_Format:
4521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
4531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkMask::kLCD16_Format:
4541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkMask::kLCD32_Format:
4551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                // TODO: trigger off LCD orientation
4561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                dstW *= 3;
4571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                matrix.postScale(SkIntToScalar(3), SK_Scalar1);
4581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                dstRB = 0;  // signals we need a copy
4591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
4601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            default:
4611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkDEBUGFAIL("unexpected mask format");
4621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRasterClip clip;
4661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    clip.setRect(SkIRect::MakeWH(dstW, dstH));
4671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkBitmap bm;
4691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bm.setConfig(config, dstW, dstH, dstRB);
4701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == dstRB) {
4721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bm.allocPixels();
4731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bm.lockPixels();
4741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
4751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bm.setPixels(mask.fImage);
4761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sk_bzero(bm.getPixels(), bm.getSafeSize());
4781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkDraw  draw;
4801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sk_bzero(&draw, sizeof(draw));
4811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    draw.fRC    = &clip;
4821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    draw.fClip  = &clip.bwRgn();
4831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    draw.fMatrix = &matrix;
4841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    draw.fBitmap = &bm;
4851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    draw.drawPath(path, paint);
4861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == dstRB) {
4881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        switch (mask.fFormat) {
4891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkMask::kLCD16_Format:
4901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                pack3xHToLCD16(bm, mask);
4911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
4921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkMask::kLCD32_Format:
4931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                pack3xHToLCD32(bm, mask);
4941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
4951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            default:
4961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkDEBUGFAIL("bad format for copyback");
4971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
5001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::getImage(const SkGlyph& origGlyph) {
5020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkGlyph*  glyph = &origGlyph;
5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyph         tmpGlyph;
5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fMaskFilter) {   // restore the prefilter bounds
50671531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        tmpGlyph.init(origGlyph.fID);
5070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // need the original bounds, sans our maskfilter
5090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMaskFilter* mf = fMaskFilter;
5100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fMaskFilter = NULL;             // temp disable
5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->getMetrics(&tmpGlyph);
5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fMaskFilter = mf;               // restore
5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        tmpGlyph.fImage = origGlyph.fImage;
5150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // we need the prefilter bounds to be <= filter bounds
5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph = &tmpGlyph;
5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fGenerateImageFromPath) {
5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPath      devPath, fillPath;
5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    fillToDevMatrix;
5251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkMask      mask;
5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
5281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        glyph->toMask(&mask);
529af2616552738d653d5453915d3236e7154b868cdMike Reed
5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fRasterizer) {
5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            mask.fFormat = SkMask::kA8_Format;
532a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            sk_bzero(glyph->fImage, mask.computeImageSize());
53340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                        fMaskFilter, &mask,
5360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                        SkMask::kJustRenderImage_CreateMode)) {
5370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                return;
5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
5401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            generateMask(mask, devPath);
54187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
5430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->getGlyphContext(*glyph)->generateImage(*glyph);
5440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fMaskFilter) {
5470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMask      srcM, dstM;
5480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    matrix;
5490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // the src glyph image shouldn't be 3D
5510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
5520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->toMask(&srcM);
5530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec.getMatrixFrom2x2(&matrix);
5540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
5560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
5570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
5580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int dstRB = origGlyph.rowBytes();
5590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int srcRB = dstM.fRowBytes;
56040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const uint8_t* src = (const uint8_t*)dstM.fImage;
5620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            uint8_t* dst = (uint8_t*)origGlyph.fImage;
5630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (SkMask::k3D_Format == dstM.fFormat) {
5650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                // we have to copy 3 times as much
5660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                height *= 3;
5670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // clean out our glyph, since it may be larger than dstM
570a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            //sk_bzero(dst, height * dstRB);
5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (--height >= 0) {
5730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                memcpy(dst, src, width);
5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                src += srcRB;
5750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                dst += dstRB;
5760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkMask::FreeImage(dstM.fImage);
5780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
58287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) {
5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->internalGetPath(glyph, NULL, path, NULL);
5840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
58687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx,
58787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                                     SkPaint::FontMetrics* my) {
5880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->generateFontMetrics(mx, my);
5890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
591091f227385b467090b5a7169a8e2faf19eca7105Mike ReedSkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) {
592091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    return 0;
593091f227385b467090b5a7169a8e2faf19eca7105Mike Reed}
594091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
59587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
5960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
59787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
59887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                                  SkPath* devPath, SkMatrix* fillToDevMatrix) {
5990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPath  path;
6000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getGlyphContext(glyph)->generatePath(glyph, &path);
60240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
6041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkFixed dx = glyph.getSubXFixed();
6051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkFixed dy = glyph.getSubYFixed();
6061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (dx | dy) {
6071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy));
6081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
6091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
61187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    if (fRec.fFrameWidth > 0 || fPathEffect != NULL) {
6120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // need the path in user-space, with only the point-size applied
6130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // so that our stroking and effects will operate the same way they
6140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // would if the user had extracted the path themself, and then
6150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // called drawPath
6160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPath      localPath;
6170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    matrix, inverse;
6180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec.getMatrixFrom2x2(&matrix);
6200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        matrix.invert(&inverse);
6210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        path.transform(inverse, &localPath);
6220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now localPath is only affected by the paint settings, and not the canvas matrix
6230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScalar width = fRec.fFrameWidth;
6250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
62687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (fPathEffect) {
6270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkPath effectPath;
6280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
62987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            if (fPathEffect->filterPath(&effectPath, localPath, &width)) {
6300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                localPath.swap(effectPath);
63187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            }
6320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
63487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (width > 0) {
6350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkStroke    stroker;
6360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkPath      outline;
6370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setWidth(width);
6390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setMiterLimit(fRec.fMiterLimit);
6400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setJoin((SkPaint::Join)fRec.fStrokeJoin);
6410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setDoFill(SkToBool(fRec.fFlags & kFrameAndFill_Flag));
6420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.strokePath(localPath, &outline);
6430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            localPath.swap(outline);
6440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
64540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now return stuff to the caller
64787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (fillToDevMatrix) {
6480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *fillToDevMatrix = matrix;
64987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
65087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (devPath) {
6510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            localPath.transform(matrix, devPath);
65287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
65387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (fillPath) {
6540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fillPath->swap(localPath);
65587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
65687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {   // nothing tricky to do
65787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (fillToDevMatrix) {
6580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fillToDevMatrix->reset();
65987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
66087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (devPath) {
66187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            if (fillPath == NULL) {
6620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                devPath->swap(path);
66387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            } else {
6640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *devPath = path;
66587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            }
6660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
66740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
66887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (fillPath) {
6690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fillPath->swap(path);
67087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
6710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
67240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
67387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    if (devPath) {
6740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        devPath->updateBoundsCache();
67587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    }
67687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    if (fillPath) {
6770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fillPath->updateBoundsCache();
67887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    }
6790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
68287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const {
6830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->reset();
6840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setScaleX(fPost2x2[0][0]);
6850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setSkewX( fPost2x2[0][1]);
6860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setSkewY( fPost2x2[1][0]);
6870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setScaleY(fPost2x2[1][1]);
6880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
69087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::Rec::getLocalMatrix(SkMatrix* m) const {
6910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    m->setScale(SkScalarMul(fTextSize, fPreScaleX), fTextSize);
69287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    if (fPreSkewX) {
6930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        m->postSkew(fPreSkewX, 0);
69487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    }
6950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
69787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const {
6980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getLocalMatrix(m);
6990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //  now concat the device matrix
70187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    SkMatrix    deviceMatrix;
70287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->getMatrixFrom2x2(&deviceMatrix);
70387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    m->postConcat(deviceMatrix);
7040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7061cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix) {
7071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(!matrix.hasPerspective());
7081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == matrix[SkMatrix::kMSkewY]) {
7101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return kX_SkAxisAlignment;
7111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
7121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == matrix[SkMatrix::kMScaleX]) {
7131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return kY_SkAxisAlignment;
7141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
7151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return kNone_SkAxisAlignment;
7161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
7171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
7190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFontHost.h"
7210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkScalerContext_Empty : public SkScalerContext {
7230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
7240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {}
7250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprotected:
72705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    virtual unsigned generateGlyphCount() {
7280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
7290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual uint16_t generateCharToGlyph(SkUnichar uni) {
7310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
7320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateAdvance(SkGlyph* glyph) {
7340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->zeroMetrics();
7350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateMetrics(SkGlyph* glyph) {
7370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->zeroMetrics();
7380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateImage(const SkGlyph& glyph) {}
7400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generatePath(const SkGlyph& glyph, SkPath* path) {}
7410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
7420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                     SkPaint::FontMetrics* my) {
7430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (mx) {
744a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            sk_bzero(mx, sizeof(*mx));
7450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
7460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (my) {
747a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            sk_bzero(my, sizeof(*my));
7480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
7490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
7510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
75240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerextern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
75340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
75487b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) {
75540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger	SkScalerContext* c = NULL;  //SkCreateColorScalerContext(desc);
75640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger	if (NULL == c) {
75740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger		c = SkFontHost::CreateScalerContext(desc);
75840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger	}
7590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (NULL == c) {
7600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        c = SkNEW_ARGS(SkScalerContext_Empty, (desc));
7610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return c;
7630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
765