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)
121212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett#ifdef SK_BUILD_FOR_ANDROID
122212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett        // On Android, pass entire rec structure so that clients can change fallback behavior
123212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett        uint32_t newFontID = SkFontHost::NextLogicalFont(rec);
124212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett#else
125212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett        uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID);
126212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett#endif
127212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett
128af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    if (0 == newFontID) {
129af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        return NULL;
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
132af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkAutoDescriptor    ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
133af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkDescriptor*       desc = ad.getDesc();
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
135af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    desc->init();
136af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkScalerContext::Rec* newRec =
137af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
138af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project                                          sizeof(rec), &rec);
139af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    newRec->fFontID = newFontID;
140af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    desc->computeChecksum();
141af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project
142af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return SkFontHost::CreateScalerContext(desc);
143af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project}
144af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project
145af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project/*  Return the next context, creating it if its not already created, but return
146af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    NULL if the fonthost says there are no more fonts to fallback to.
147af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project */
148af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source ProjectSkScalerContext* SkScalerContext::getNextContext() {
149af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkScalerContext* next = fNextContext;
150af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // if next is null, then either it isn't cached yet, or we're at the
151af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // end of our possible chain
152af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    if (NULL == next) {
153af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        next = allocNextContext(fRec);
154af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (NULL == next) {
155af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            return NULL;
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
157af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        // next's base is our base + our local count
158af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount());
159af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        // cache the answer
160af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        fNextContext = next;
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
162af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return next;
163af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project}
164af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project
165725b3e03acb91dc69296554932624b36612bd189Billy HewlettSkScalerContext* SkScalerContext::getContextFromChar(SkUnichar uni, unsigned& glyphID) {
166725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    SkScalerContext* ctx = this;
167725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    for (;;) {
168725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        glyphID = ctx->generateCharToGlyph(uni);
169725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        if (glyphID) {
170725b3e03acb91dc69296554932624b36612bd189Billy Hewlett            break;  // found it
171725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        }
172725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        ctx = ctx->getNextContext();
173725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        if (NULL == ctx) {
174725b3e03acb91dc69296554932624b36612bd189Billy Hewlett            return NULL;
175725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        }
176725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    }
177725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    return ctx;
178725b3e03acb91dc69296554932624b36612bd189Billy Hewlett}
179725b3e03acb91dc69296554932624b36612bd189Billy Hewlett
180af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source ProjectSkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) {
181af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    unsigned glyphID = glyph.getGlyphID();
182af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkScalerContext* ctx = this;
183af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    for (;;) {
184af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        unsigned count = ctx->getGlyphCount();
185af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (glyphID < count) {
186af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            break;
1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
188af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        glyphID -= count;
189af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        ctx = ctx->getNextContext();
190af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (NULL == ctx) {
191af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID());
192af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            // just return the original context (this)
193af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            return this;
1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
196af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return ctx;
1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
200725b3e03acb91dc69296554932624b36612bd189Billy HewlettSkFontID SkScalerContext::findTypefaceIdForChar(SkUnichar uni) {
201725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    unsigned glyphID;
202725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    SkScalerContext* ctx = getContextFromChar(uni, glyphID);
203725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    if (ctx) {
204725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        return ctx->fRec.fFontID;
205725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    } else {
206725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        return 0;
207725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    }
208725b3e03acb91dc69296554932624b36612bd189Billy Hewlett}
209725b3e03acb91dc69296554932624b36612bd189Billy Hewlett
2101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*  This loops through all available fallback contexts (if needed) until it
2111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    finds some context that can handle the unichar and return it.
2121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    As this is somewhat expensive operation, it should only be done on the first
2141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    char of a run.
2151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
2161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerunsigned SkScalerContext::getBaseGlyphCount(SkUnichar uni) {
2171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    unsigned glyphID;
218725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    SkScalerContext* ctx = getContextFromChar(uni, glyphID);
219725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    if (ctx) {
220725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        return ctx->fBaseGlyphCount;
221725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    } else {
22241aa7b9fc3ae452215876143852024720383e102Victoria Lease        SkDEBUGF(("--- no context for char %x\n", uni));
223725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        return this->fBaseGlyphCount;
2241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
2271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
228af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project/*  This loops through all available fallback contexts (if needed) until it
229af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    finds some context that can handle the unichar. If all fail, returns 0
230af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project */
231af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Projectuint16_t SkScalerContext::charToGlyphID(SkUnichar uni) {
232725b3e03acb91dc69296554932624b36612bd189Billy Hewlett
233af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    unsigned glyphID;
234725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    SkScalerContext* ctx = getContextFromChar(uni, glyphID);
235725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    if (!ctx) {
236725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        return 0; // no more contexts, return missing glyph
2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
238af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // add the ctx's base, making glyphID unique for chain of contexts
239af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    glyphID += ctx->fBaseGlyphCount;
240af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // check for overflow of 16bits, since our glyphID cannot exceed that
241af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    if (glyphID > 0xFFFF) {
242af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        glyphID = 0;
243af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    }
244af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return SkToU16(glyphID);
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
247091f227385b467090b5a7169a8e2faf19eca7105Mike ReedSkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) {
248091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    SkScalerContext* ctx = this;
249091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    unsigned rangeEnd = 0;
250091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    do {
251091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        unsigned rangeStart = rangeEnd;
252091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
253091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        rangeEnd += ctx->getGlyphCount();
254091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        if (rangeStart <= glyphID && glyphID < rangeEnd) {
255091f227385b467090b5a7169a8e2faf19eca7105Mike Reed            return ctx->generateGlyphToChar(glyphID - rangeStart);
256091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        }
257091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        ctx = ctx->getNextContext();
258091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    } while (NULL != ctx);
259091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    return 0;
260091f227385b467090b5a7169a8e2faf19eca7105Mike Reed}
261091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::getAdvance(SkGlyph* glyph) {
2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // mark us as just having a valid advance
2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE;
2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // we mark the format before making the call, in case the impl
2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // internally ends up calling its generateMetrics, which is OK
2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // albeit slower than strictly necessary
2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getGlyphContext(*glyph)->generateAdvance(glyph);
2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::getMetrics(SkGlyph* glyph) {
2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getGlyphContext(*glyph)->generateMetrics(glyph);
2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // for now we have separate cache entries for devkerning on and off
2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // in the future we might share caches, but make our measure/draw
2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // code make the distinction. Thus we zap the values if the caller
2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // has not asked for them.
2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // no devkern, so zap the fields
2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fLsbDelta = glyph->fRsbDelta = 0;
2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // if either dimension is empty, zap the image bounds of the glyph
2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (0 == glyph->fWidth || 0 == glyph->fHeight) {
2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fWidth   = 0;
2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fHeight  = 0;
2870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fTop     = 0;
2880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fLeft    = 0;
2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fMaskFormat = 0;
2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
29240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
2931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fGenerateImageFromPath) {
2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPath      devPath, fillPath;
2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    fillToDevMatrix;
2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fRasterizer) {
3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkMask  mask;
3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                       fMaskFilter, &mask,
3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                       SkMask::kJustComputeBounds_CreateMode)) {
3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fLeft    = mask.fBounds.fLeft;
3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fTop     = mask.fBounds.fTop;
3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fWidth   = SkToU16(mask.fBounds.width());
3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fHeight  = SkToU16(mask.fBounds.height());
3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
310030ffe05175291b1d91ec6808e1a32e862ee90cdMike Reed                goto SK_ERROR;
3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // just use devPath
3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkIRect ir;
3150e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed            devPath.getBounds().roundOut(&ir);
31640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
317a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed            if (ir.isEmpty() || !ir.is16Bit()) {
318030ffe05175291b1d91ec6808e1a32e862ee90cdMike Reed                goto SK_ERROR;
319a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed            }
3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fLeft    = ir.fLeft;
3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fTop     = ir.fTop;
3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fWidth   = SkToU16(ir.width());
3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fHeight  = SkToU16(ir.height());
3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
32740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger	if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
32840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger		glyph->fMaskFormat = fRec.fMaskFormat;
32940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger	}
3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fMaskFilter) {
3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMask      src, dst;
3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    matrix;
3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->toMask(&src);
3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec.getMatrixFrom2x2(&matrix);
3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        src.fImage = NULL;  // only want the bounds from the filter
3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) {
3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(dst.fImage == NULL);
3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fLeft    = dst.fBounds.fLeft;
3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fTop     = dst.fBounds.fTop;
3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fWidth   = SkToU16(dst.fBounds.width());
3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fHeight  = SkToU16(dst.fBounds.height());
3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fMaskFormat = dst.fFormat;
3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
348a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    return;
34940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
350030ffe05175291b1d91ec6808e1a32e862ee90cdMike ReedSK_ERROR:
351a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    // draw nothing 'cause we failed
352a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    glyph->fLeft    = 0;
353a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    glyph->fTop     = 0;
354a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    glyph->fWidth   = 0;
355a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed    glyph->fHeight  = 0;
35693d11b5b461a8677a8e3ffa94260f4f9897070acMike Reed    // put a valid value here, in case it was earlier set to
35793d11b5b461a8677a8e3ffa94260f4f9897070acMike Reed    // MASK_FORMAT_JUST_ADVANCE
35893d11b5b461a8677a8e3ffa94260f4f9897070acMike Reed    glyph->fMaskFormat = fRec.fMaskFormat;
3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool isLCD(const SkScalerContext::Rec& rec) {
3621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkMask::kLCD16_Format == rec.fMaskFormat ||
3631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger           SkMask::kLCD32_Format == rec.fMaskFormat;
3641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic uint16_t a8_to_rgb565(unsigned a8) {
3671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkPackRGB16(a8 >> 3, a8 >> 2, a8 >> 3);
3681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void copyToLCD16(const SkBitmap& src, const SkMask& dst) {
3711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkBitmap::kA8_Config == src.config());
3721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
3731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int width = dst.fBounds.width();
3751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int height = dst.fBounds.height();
3761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const uint8_t* srcP = src.getAddr8(0, 0);
3771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    size_t srcRB = src.rowBytes();
3781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    uint16_t* dstP = (uint16_t*)dst.fImage;
3791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    size_t dstRB = dst.fRowBytes;
3801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int y = 0; y < height; ++y) {
3811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int x = 0; x < width; ++x) {
3821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            dstP[x] = a8_to_rgb565(srcP[x]);
3831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
3841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        srcP += srcRB;
3851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dstP = (uint16_t*)((char*)dstP + dstRB);
3861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
3871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define SK_FREETYPE_LCD_LERP    160
3901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic int lerp(int start, int end) {
3921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT((unsigned)SK_FREETYPE_LCD_LERP <= 256);
3931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return start + ((end - start) * (SK_FREETYPE_LCD_LERP) >> 8);
3941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic uint16_t packLCD16(unsigned r, unsigned g, unsigned b) {
3971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SK_FREETYPE_LCD_LERP) {
3981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // want (a+b+c)/3, but we approx to avoid the divide
3991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        unsigned ave = (5 * (r + g + b) + g) >> 4;
4001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        r = lerp(r, ave);
4011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        g = lerp(g, ave);
4021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        b = lerp(b, ave);
4031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkPackRGB16(r >> 3, g >> 2, b >> 3);
4051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void pack3xHToLCD16(const SkBitmap& src, const SkMask& dst) {
4081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkBitmap::kA8_Config == src.config());
4091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
4101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int width = dst.fBounds.width();
4121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int height = dst.fBounds.height();
4131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    uint16_t* dstP = (uint16_t*)dst.fImage;
4141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    size_t dstRB = dst.fRowBytes;
4151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int y = 0; y < height; ++y) {
4161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const uint8_t* srcP = src.getAddr8(0, y);
4171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int x = 0; x < width; ++x) {
4181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned r = *srcP++;
4191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned g = *srcP++;
4201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned b = *srcP++;
4211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            dstP[x] = packLCD16(r, g, b);
4221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dstP = (uint16_t*)((char*)dstP + dstRB);
4241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void pack3xHToLCD32(const SkBitmap& src, const SkMask& dst) {
4281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkBitmap::kA8_Config == src.config());
4291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(SkMask::kLCD32_Format == dst.fFormat);
4301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int width = dst.fBounds.width();
4321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int height = dst.fBounds.height();
4331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkPMColor* dstP = (SkPMColor*)dst.fImage;
4341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    size_t dstRB = dst.fRowBytes;
4351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int y = 0; y < height; ++y) {
4361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const uint8_t* srcP = src.getAddr8(0, y);
4371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int x = 0; x < width; ++x) {
4381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned r = *srcP++;
4391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned g = *srcP++;
4401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned b = *srcP++;
4411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned a = SkMax32(SkMax32(r, g), b);
4421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            dstP[x] = SkPackARGB32(a, r, g, b);
4431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dstP = (SkPMColor*)((char*)dstP + dstRB);
4451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void generateMask(const SkMask& mask, const SkPath& path) {
4491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkBitmap::Config config;
4501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkPaint     paint;
4511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int srcW = mask.fBounds.width();
4531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int srcH = mask.fBounds.height();
4541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int dstW = srcW;
4551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int dstH = srcH;
4561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int dstRB = mask.fRowBytes;
4571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkMatrix matrix;
4591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
4601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        -SkIntToScalar(mask.fBounds.fTop));
4611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SkMask::kBW_Format == mask.fFormat) {
4631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        config = SkBitmap::kA1_Config;
4641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        paint.setAntiAlias(false);
4651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
4661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        config = SkBitmap::kA8_Config;
4671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        paint.setAntiAlias(true);
4681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        switch (mask.fFormat) {
4691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkMask::kA8_Format:
4701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
4711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkMask::kLCD16_Format:
4721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkMask::kLCD32_Format:
4731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                // TODO: trigger off LCD orientation
4741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                dstW *= 3;
4751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                matrix.postScale(SkIntToScalar(3), SK_Scalar1);
4761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                dstRB = 0;  // signals we need a copy
4771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
4781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            default:
4791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkDEBUGFAIL("unexpected mask format");
4801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRasterClip clip;
4841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    clip.setRect(SkIRect::MakeWH(dstW, dstH));
4851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkBitmap bm;
4871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bm.setConfig(config, dstW, dstH, dstRB);
4881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == dstRB) {
4901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bm.allocPixels();
4911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bm.lockPixels();
4921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
4931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bm.setPixels(mask.fImage);
4941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sk_bzero(bm.getPixels(), bm.getSafeSize());
4961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkDraw  draw;
4981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    sk_bzero(&draw, sizeof(draw));
4991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    draw.fRC    = &clip;
5001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    draw.fClip  = &clip.bwRgn();
5011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    draw.fMatrix = &matrix;
5021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    draw.fBitmap = &bm;
5031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    draw.drawPath(path, paint);
5041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == dstRB) {
5061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        switch (mask.fFormat) {
5071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkMask::kLCD16_Format:
5081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                pack3xHToLCD16(bm, mask);
5091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
5101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkMask::kLCD32_Format:
5111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                pack3xHToLCD32(bm, mask);
5121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
5131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            default:
5141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkDEBUGFAIL("bad format for copyback");
5151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
5161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
5171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
5181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::getImage(const SkGlyph& origGlyph) {
5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkGlyph*  glyph = &origGlyph;
5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyph         tmpGlyph;
5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fMaskFilter) {   // restore the prefilter bounds
52471531ca1f484da5837be8017a0c83e5bff701587Derek Sollenberger        tmpGlyph.init(origGlyph.fID);
5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // need the original bounds, sans our maskfilter
5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMaskFilter* mf = fMaskFilter;
5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fMaskFilter = NULL;             // temp disable
5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->getMetrics(&tmpGlyph);
5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fMaskFilter = mf;               // restore
5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        tmpGlyph.fImage = origGlyph.fImage;
5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // we need the prefilter bounds to be <= filter bounds
5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
5360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
5370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph = &tmpGlyph;
5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fGenerateImageFromPath) {
5410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPath      devPath, fillPath;
5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    fillToDevMatrix;
5431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkMask      mask;
5440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
5461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        glyph->toMask(&mask);
547af2616552738d653d5453915d3236e7154b868cdMike Reed
5480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fRasterizer) {
5490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            mask.fFormat = SkMask::kA8_Format;
550a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            sk_bzero(glyph->fImage, mask.computeImageSize());
55140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
5530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                        fMaskFilter, &mask,
5540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                        SkMask::kJustRenderImage_CreateMode)) {
5550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                return;
5560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
5581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            generateMask(mask, devPath);
55987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
5600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
5610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->getGlyphContext(*glyph)->generateImage(*glyph);
5620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fMaskFilter) {
5650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMask      srcM, dstM;
5660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    matrix;
5670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // the src glyph image shouldn't be 3D
5690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
5700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->toMask(&srcM);
5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec.getMatrixFrom2x2(&matrix);
5720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
5750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
5760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int dstRB = origGlyph.rowBytes();
5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int srcRB = dstM.fRowBytes;
57840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const uint8_t* src = (const uint8_t*)dstM.fImage;
5800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            uint8_t* dst = (uint8_t*)origGlyph.fImage;
5810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (SkMask::k3D_Format == dstM.fFormat) {
5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                // we have to copy 3 times as much
5840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                height *= 3;
5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // clean out our glyph, since it may be larger than dstM
588a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            //sk_bzero(dst, height * dstRB);
5890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (--height >= 0) {
5910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                memcpy(dst, src, width);
5920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                src += srcRB;
5930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                dst += dstRB;
5940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkMask::FreeImage(dstM.fImage);
5960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
60087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) {
6010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->internalGetPath(glyph, NULL, path, NULL);
6020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
60487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx,
60587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                                     SkPaint::FontMetrics* my) {
6060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->generateFontMetrics(mx, my);
6070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
609091f227385b467090b5a7169a8e2faf19eca7105Mike ReedSkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) {
610091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    return 0;
611091f227385b467090b5a7169a8e2faf19eca7105Mike Reed}
612091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
61387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
6140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
61587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
61687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                                  SkPath* devPath, SkMatrix* fillToDevMatrix) {
6170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPath  path;
6180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getGlyphContext(glyph)->generatePath(glyph, &path);
62040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
6221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkFixed dx = glyph.getSubXFixed();
6231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkFixed dy = glyph.getSubYFixed();
6241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (dx | dy) {
6251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy));
6261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
6271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
62987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    if (fRec.fFrameWidth > 0 || fPathEffect != NULL) {
6300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // need the path in user-space, with only the point-size applied
6310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // so that our stroking and effects will operate the same way they
6320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // would if the user had extracted the path themself, and then
6330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // called drawPath
6340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPath      localPath;
6350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    matrix, inverse;
6360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec.getMatrixFrom2x2(&matrix);
6380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        matrix.invert(&inverse);
6390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        path.transform(inverse, &localPath);
6400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now localPath is only affected by the paint settings, and not the canvas matrix
6410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScalar width = fRec.fFrameWidth;
6430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
64487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (fPathEffect) {
6450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkPath effectPath;
6460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
64787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            if (fPathEffect->filterPath(&effectPath, localPath, &width)) {
6480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                localPath.swap(effectPath);
64987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            }
6500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
65287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (width > 0) {
6530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkStroke    stroker;
6540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkPath      outline;
6550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setWidth(width);
6570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setMiterLimit(fRec.fMiterLimit);
6580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setJoin((SkPaint::Join)fRec.fStrokeJoin);
6590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setDoFill(SkToBool(fRec.fFlags & kFrameAndFill_Flag));
6600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.strokePath(localPath, &outline);
6610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            localPath.swap(outline);
6620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
66340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now return stuff to the caller
66587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (fillToDevMatrix) {
6660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *fillToDevMatrix = matrix;
66787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
66887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (devPath) {
6690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            localPath.transform(matrix, devPath);
67087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
67187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (fillPath) {
6720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fillPath->swap(localPath);
67387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
67487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {   // nothing tricky to do
67587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (fillToDevMatrix) {
6760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fillToDevMatrix->reset();
67787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
67887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (devPath) {
67987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            if (fillPath == NULL) {
6800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                devPath->swap(path);
68187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            } else {
6820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *devPath = path;
68387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger            }
6840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
68540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
68687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        if (fillPath) {
6870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fillPath->swap(path);
68887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        }
6890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
69040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
69187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    if (devPath) {
6920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        devPath->updateBoundsCache();
69387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    }
69487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    if (fillPath) {
6950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fillPath->updateBoundsCache();
69687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    }
6970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
70087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const {
7010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->reset();
7020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setScaleX(fPost2x2[0][0]);
7030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setSkewX( fPost2x2[0][1]);
7040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setSkewY( fPost2x2[1][0]);
7050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setScaleY(fPost2x2[1][1]);
7060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
70887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::Rec::getLocalMatrix(SkMatrix* m) const {
7090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    m->setScale(SkScalarMul(fTextSize, fPreScaleX), fTextSize);
71087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    if (fPreSkewX) {
7110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        m->postSkew(fPreSkewX, 0);
71287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    }
7130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
71587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const {
7160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getLocalMatrix(m);
7170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //  now concat the device matrix
71987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    SkMatrix    deviceMatrix;
72087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->getMatrixFrom2x2(&deviceMatrix);
72187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    m->postConcat(deviceMatrix);
7220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7241cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix) {
7251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(!matrix.hasPerspective());
7261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == matrix[SkMatrix::kMSkewY]) {
7281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return kX_SkAxisAlignment;
7291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
7301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == matrix[SkMatrix::kMScaleX]) {
7311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return kY_SkAxisAlignment;
7321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
7331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return kNone_SkAxisAlignment;
7341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
7351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
7370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFontHost.h"
7390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkScalerContext_Empty : public SkScalerContext {
7410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
7420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {}
7430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprotected:
74505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    virtual unsigned generateGlyphCount() {
7460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
7470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual uint16_t generateCharToGlyph(SkUnichar uni) {
7490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
7500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateAdvance(SkGlyph* glyph) {
7520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->zeroMetrics();
7530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateMetrics(SkGlyph* glyph) {
7550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->zeroMetrics();
7560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateImage(const SkGlyph& glyph) {}
7580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generatePath(const SkGlyph& glyph, SkPath* path) {}
7590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
7600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                     SkPaint::FontMetrics* my) {
7610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (mx) {
762a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            sk_bzero(mx, sizeof(*mx));
7630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
7640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (my) {
765a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            sk_bzero(my, sizeof(*my));
7660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
7670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
7690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
77040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerextern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
77140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
77287b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) {
77340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger	SkScalerContext* c = NULL;  //SkCreateColorScalerContext(desc);
77440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger	if (NULL == c) {
77540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger		c = SkFontHost::CreateScalerContext(desc);
77640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger	}
7770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (NULL == c) {
7780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        c = SkNEW_ARGS(SkScalerContext_Empty, (desc));
7790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return c;
7810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
783