SkScalerContext.cpp revision a8c52de60de1d2471206b3c81e9243e2c76f2edb
10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* libs/graphics/sgl/SkScalerContext.cpp
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
30910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** Copyright 2006, The Android Open Source Project
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
50910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
60910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** you may not use this file except in compliance with the License.
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** You may obtain a copy of the License at
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** See the License for the specific language governing permissions and
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** limitations under the License.
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScalerContext.h"
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkDescriptor.h"
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkDraw.h"
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFontHost.h"
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMaskFilter.h"
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPathEffect.h"
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRasterizer.h"
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRegion.h"
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStroke.h"
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkThread.h"
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//    #define TRACK_MISSING_CHARS
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define ComputeBWRowBytes(width)        (((unsigned)(width) + 7) >> 3)
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const uint8_t* gBlackGammaTable;
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const uint8_t* gWhiteGammaTable;
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkGlyph::toMask(SkMask* mask) const {
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(mask);
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    mask->fImage = (uint8_t*)fImage;
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    mask->fBounds.set(fLeft, fTop, fLeft + fWidth, fTop + fHeight);
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    mask->fRowBytes = this->rowBytes();
44aa4832adcc7eba085987357591bcfeb530ba7b0dMike Reed    mask->fFormat = static_cast<SkMask::Format>(fMaskFormat);
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectsize_t SkGlyph::computeImageSize() const {
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t size = this->rowBytes() * fHeight;
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fMaskFormat == SkMask::k3D_Format) {
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        size *= 3;
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return size;
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkGlyph::zeroMetrics() {
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fAdvanceX = 0;
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fAdvanceY = 0;
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fWidth    = 0;
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fHeight   = 0;
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fTop      = 0;
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fLeft     = 0;
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRsbDelta = 0;
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fLsbDelta = 0;
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    #define DUMP_RECx
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkFlattenable* load_flattenable(const SkDescriptor* desc, uint32_t tag) {
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFlattenable*  obj = NULL;
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t        len;
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const void*     data = desc->findEntry(tag, &len);
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (data) {
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkFlattenableReadBuffer   buffer(data, len);
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        obj = buffer.readFlattenable();
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(buffer.offset() == buffer.size());
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return obj;
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalerContext::SkScalerContext(const SkDescriptor* desc)
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    : fPathEffect(NULL), fMaskFilter(NULL)
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static bool gHaveGammaTables;
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (!gHaveGammaTables) {
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const uint8_t* tables[2];
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkFontHost::GetGammaTables(tables);
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        gBlackGammaTable = tables[0];
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        gWhiteGammaTable = tables[1];
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        gHaveGammaTables = true;
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBaseGlyphCount = 0;
98af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    fNextContext = NULL;
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const Rec* rec = (const Rec*)desc->findEntry(kRec_SkDescriptorTag, NULL);
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(rec);
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRec = *rec;
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef DUMP_REC
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    desc->assertChecksum();
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDebugf("SkScalarContext checksum %x count %d length %d\n", desc->getChecksum(), desc->getCount(), desc->getLength());
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n",
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0],
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fPost2x2[0][1], rec->fPost2x2[1][0], rec->fPost2x2[1][1]);
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDebugf("  frame %g miter %g hints %d framefill %d format %d join %d\n",
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fFrameWidth, rec->fMiterLimit, rec->fHints, rec->fFrameAndFill,
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fMaskFormat, rec->fStrokeJoin);
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDebugf("  pathEffect %x maskFilter %x\n", desc->findEntry(kPathEffect_SkDescriptorTag, NULL),
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        desc->findEntry(kMaskFilter_SkDescriptorTag, NULL));
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPathEffect = (SkPathEffect*)load_flattenable(desc, kPathEffect_SkDescriptorTag);
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fMaskFilter = (SkMaskFilter*)load_flattenable(desc, kMaskFilter_SkDescriptorTag);
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRasterizer = (SkRasterizer*)load_flattenable(desc, kRasterizer_SkDescriptorTag);
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalerContext::~SkScalerContext() {
124af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkDELETE(fNextContext);
125af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPathEffect->safeUnref();
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fMaskFilter->safeUnref();
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRasterizer->safeUnref();
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
131af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Projectstatic SkScalerContext* allocNextContext(const SkScalerContext::Rec& rec) {
132af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // fonthost will determine the next possible font to search, based
133af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // on the current font in fRec. It will return NULL if ctx is our
134af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // last font that can be searched (i.e. ultimate fallback font)
135af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID);
136af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    if (0 == newFontID) {
137af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        return NULL;
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
140af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkAutoDescriptor    ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
141af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkDescriptor*       desc = ad.getDesc();
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
143af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    desc->init();
144af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkScalerContext::Rec* newRec =
145af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
146af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project                                          sizeof(rec), &rec);
147af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    newRec->fFontID = newFontID;
148af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    desc->computeChecksum();
149af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project
150af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return SkFontHost::CreateScalerContext(desc);
151af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project}
152af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project
153af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project/*  Return the next context, creating it if its not already created, but return
154af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    NULL if the fonthost says there are no more fonts to fallback to.
155af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project */
156af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source ProjectSkScalerContext* SkScalerContext::getNextContext() {
157af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkScalerContext* next = fNextContext;
158af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // if next is null, then either it isn't cached yet, or we're at the
159af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // end of our possible chain
160af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    if (NULL == next) {
161af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        next = allocNextContext(fRec);
162af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (NULL == next) {
163af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            return NULL;
1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
165af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        // next's base is our base + our local count
166af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount());
167af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        // cache the answer
168af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        fNextContext = next;
1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
170af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return next;
171af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project}
172af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project
173af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source ProjectSkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) {
174af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    unsigned glyphID = glyph.getGlyphID();
175af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkScalerContext* ctx = this;
176af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    for (;;) {
177af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        unsigned count = ctx->getGlyphCount();
178af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (glyphID < count) {
179af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            break;
1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
181af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        glyphID -= count;
182af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        ctx = ctx->getNextContext();
183af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (NULL == ctx) {
184af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID());
185af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            // just return the original context (this)
186af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            return this;
1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
189af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return ctx;
1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
192af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project/*  This loops through all available fallback contexts (if needed) until it
193af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    finds some context that can handle the unichar. If all fail, returns 0
194af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project */
195af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Projectuint16_t SkScalerContext::charToGlyphID(SkUnichar uni) {
196af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    SkScalerContext* ctx = this;
197af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    unsigned glyphID;
198af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    for (;;) {
199af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        glyphID = ctx->generateCharToGlyph(uni);
200af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (glyphID) {
201af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            break;  // found it
202af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        }
203af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        ctx = ctx->getNextContext();
204af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        if (NULL == ctx) {
205af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project            return 0;   // no more contexts, return missing glyph
2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
208af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // add the ctx's base, making glyphID unique for chain of contexts
209af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    glyphID += ctx->fBaseGlyphCount;
210af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    // check for overflow of 16bits, since our glyphID cannot exceed that
211af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    if (glyphID > 0xFFFF) {
212af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project        glyphID = 0;
213af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    }
214af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project    return SkToU16(glyphID);
2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::getAdvance(SkGlyph* glyph) {
2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // mark us as just having a valid advance
2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE;
2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // we mark the format before making the call, in case the impl
2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // internally ends up calling its generateMetrics, which is OK
2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // albeit slower than strictly necessary
2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getGlyphContext(*glyph)->generateAdvance(glyph);
2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::getMetrics(SkGlyph* glyph) {
2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getGlyphContext(*glyph)->generateMetrics(glyph);
2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // for now we have separate cache entries for devkerning on and off
2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // in the future we might share caches, but make our measure/draw
2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // code make the distinction. Thus we zap the values if the caller
2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // has not asked for them.
2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // no devkern, so zap the fields
2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fLsbDelta = glyph->fRsbDelta = 0;
2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // if either dimension is empty, zap the image bounds of the glyph
2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (0 == glyph->fWidth || 0 == glyph->fHeight) {
2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fWidth   = 0;
2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fHeight  = 0;
2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fTop     = 0;
2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fLeft    = 0;
2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->fMaskFormat = 0;
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRec.fFrameWidth > 0 || fPathEffect != NULL || fRasterizer != NULL) {
2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPath      devPath, fillPath;
2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    fillToDevMatrix;
2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fRasterizer) {
2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkMask  mask;
2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                       fMaskFilter, &mask,
2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                       SkMask::kJustComputeBounds_CreateMode)) {
2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fLeft    = mask.fBounds.fLeft;
2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fTop     = mask.fBounds.fTop;
2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fWidth   = SkToU16(mask.fBounds.width());
2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fHeight  = SkToU16(mask.fBounds.height());
2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                // draw nothing 'cause we failed
2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fLeft    = 0;
2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fTop     = 0;
2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fWidth   = 0;
2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                glyph->fHeight  = 0;
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                return;
2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // just use devPath
2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkIRect ir;
2750e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed            devPath.getBounds().roundOut(&ir);
2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fLeft    = ir.fLeft;
2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fTop     = ir.fTop;
2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fWidth   = SkToU16(ir.width());
2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fHeight  = SkToU16(ir.height());
2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    glyph->fMaskFormat = fRec.fMaskFormat;
2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fMaskFilter) {
2870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMask      src, dst;
2880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    matrix;
2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->toMask(&src);
2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec.getMatrixFrom2x2(&matrix);
2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        src.fImage = NULL;  // only want the bounds from the filter
2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) {
2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(dst.fImage == NULL);
2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fLeft    = dst.fBounds.fLeft;
2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fTop     = dst.fBounds.fTop;
2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fWidth   = SkToU16(dst.fBounds.width());
2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fHeight  = SkToU16(dst.fBounds.height());
3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->fMaskFormat = dst.fFormat;
3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::getImage(const SkGlyph& origGlyph) {
3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkGlyph*  glyph = &origGlyph;
3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyph         tmpGlyph;
3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fMaskFilter) {   // restore the prefilter bounds
3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        tmpGlyph.fID = origGlyph.fID;
3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // need the original bounds, sans our maskfilter
3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMaskFilter* mf = fMaskFilter;
3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fMaskFilter = NULL;             // temp disable
3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->getMetrics(&tmpGlyph);
3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fMaskFilter = mf;               // restore
3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        tmpGlyph.fImage = origGlyph.fImage;
3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // we need the prefilter bounds to be <= filter bounds
3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph = &tmpGlyph;
3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRec.fFrameWidth > 0 || fPathEffect != NULL || fRasterizer != NULL) {
3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPath      devPath, fillPath;
3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    fillToDevMatrix;
3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fRasterizer) {
3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkMask  mask;
3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            glyph->toMask(&mask);
3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            mask.fFormat = SkMask::kA8_Format;
337a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            sk_bzero(glyph->fImage, mask.computeImageSize());
3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                        fMaskFilter, &mask,
3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                        SkMask::kJustRenderImage_CreateMode)) {
3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                return;
3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkBitmap    bm;
3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkBitmap::Config config;
3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkMatrix    matrix;
3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkRegion    clip;
3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkPaint     paint;
3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkDraw      draw;
3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (SkMask::kA8_Format == fRec.fMaskFormat) {
3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                config = SkBitmap::kA8_Config;
3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                paint.setAntiAlias(true);
3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(SkMask::kBW_Format == fRec.fMaskFormat);
3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                config = SkBitmap::kA1_Config;
3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                paint.setAntiAlias(false);
3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            clip.setRect(0, 0, glyph->fWidth, glyph->fHeight);
3620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            matrix.setTranslate(-SkIntToScalar(glyph->fLeft),
3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                -SkIntToScalar(glyph->fTop));
3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            bm.setConfig(config, glyph->fWidth, glyph->fHeight,
3650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                         glyph->rowBytes());
3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            bm.setPixels(glyph->fImage);
367a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            sk_bzero(glyph->fImage, bm.height() * bm.rowBytes());
3680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            draw.fClip  = &clip;
3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            draw.fMatrix = &matrix;
3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            draw.fBitmap = &bm;
3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            draw.fBounder = NULL;
3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            draw.drawPath(devPath, paint);
3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->getGlyphContext(*glyph)->generateImage(*glyph);
3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fMaskFilter) {
3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMask      srcM, dstM;
3810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    matrix;
3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // the src glyph image shouldn't be 3D
3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->toMask(&srcM);
3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec.getMatrixFrom2x2(&matrix);
3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int dstRB = origGlyph.rowBytes();
3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int srcRB = dstM.fRowBytes;
3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const uint8_t* src = (const uint8_t*)dstM.fImage;
3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            uint8_t* dst = (uint8_t*)origGlyph.fImage;
3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (SkMask::k3D_Format == dstM.fFormat) {
3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                // we have to copy 3 times as much
3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                height *= 3;
4000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // clean out our glyph, since it may be larger than dstM
403a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            //sk_bzero(dst, height * dstRB);
4040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (--height >= 0) {
4060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                memcpy(dst, src, width);
4070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                src += srcRB;
4080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                dst += dstRB;
4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
4100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkMask::FreeImage(dstM.fImage);
4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // check to see if we should filter the alpha channel
4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (NULL == fMaskFilter &&
4170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec.fMaskFormat != SkMask::kBW_Format &&
4180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        (fRec.fFlags & (kGammaForBlack_Flag | kGammaForWhite_Flag)) != 0)
4190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
4200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const uint8_t* table = (fRec.fFlags & kGammaForBlack_Flag) ? gBlackGammaTable : gWhiteGammaTable;
4210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (NULL != table)
4220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
4230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            uint8_t* dst = (uint8_t*)origGlyph.fImage;
4240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            unsigned rowBytes = origGlyph.rowBytes();
4250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            for (int y = origGlyph.fHeight - 1; y >= 0; --y)
4270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
4280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                for (int x = origGlyph.fWidth - 1; x >= 0; --x)
4290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    dst[x] = table[dst[x]];
4300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                dst += rowBytes;
4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path)
4370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
4380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->internalGetPath(glyph, NULL, path, NULL);
4390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my)
4420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
4430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->generateFontMetrics(mx, my);
4440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////
4470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, SkPath* devPath, SkMatrix* fillToDevMatrix)
4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
4500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPath  path;
4510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getGlyphContext(glyph)->generatePath(glyph, &path);
4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRec.fFrameWidth > 0 || fPathEffect != NULL)
4550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
4560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // need the path in user-space, with only the point-size applied
4570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // so that our stroking and effects will operate the same way they
4580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // would if the user had extracted the path themself, and then
4590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // called drawPath
4600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPath      localPath;
4610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    matrix, inverse;
4620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec.getMatrixFrom2x2(&matrix);
4640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        matrix.invert(&inverse);
4650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        path.transform(inverse, &localPath);
4660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now localPath is only affected by the paint settings, and not the canvas matrix
4670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScalar width = fRec.fFrameWidth;
4690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fPathEffect)
4710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
4720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkPath effectPath;
4730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (fPathEffect->filterPath(&effectPath, localPath, &width))
4750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                localPath.swap(effectPath);
4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (width > 0)
4790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
4800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkStroke    stroker;
4810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkPath      outline;
4820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setWidth(width);
4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setMiterLimit(fRec.fMiterLimit);
4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setJoin((SkPaint::Join)fRec.fStrokeJoin);
4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.setDoFill(SkToBool(fRec.fFlags & kFrameAndFill_Flag));
4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stroker.strokePath(localPath, &outline);
4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            localPath.swap(outline);
4890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now return stuff to the caller
4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fillToDevMatrix)
4930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *fillToDevMatrix = matrix;
4940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (devPath)
4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            localPath.transform(matrix, devPath);
4970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fillPath)
4990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fillPath->swap(localPath);
5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else    // nothing tricky to do
5020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fillToDevMatrix)
5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fillToDevMatrix->reset();
5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (devPath)
5070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (fillPath == NULL)
5090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                devPath->swap(path);
5100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else
5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *devPath = path;
5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fillPath)
5150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fillPath->swap(path);
5160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (devPath)
5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        devPath->updateBoundsCache();
5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fillPath)
5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fillPath->updateBoundsCache();
5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const
5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->reset();
5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setScaleX(fPost2x2[0][0]);
5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setSkewX( fPost2x2[0][1]);
5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setSkewY( fPost2x2[1][0]);
5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    dst->setScaleY(fPost2x2[1][1]);
5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::Rec::getLocalMatrix(SkMatrix* m) const
5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    m->setScale(SkScalarMul(fTextSize, fPreScaleX), fTextSize);
5370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fPreSkewX)
5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        m->postSkew(fPreSkewX, 0);
5390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const
5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->getLocalMatrix(m);
5440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //  now concat the device matrix
5460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
5470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkMatrix    deviceMatrix;
5480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->getMatrixFrom2x2(&deviceMatrix);
5490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        m->postConcat(deviceMatrix);
5500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
5540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFontHost.h"
5560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkScalerContext_Empty : public SkScalerContext {
5580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
5590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {}
5600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprotected:
5620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual unsigned generateGlyphCount() const {
5630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
5640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual uint16_t generateCharToGlyph(SkUnichar uni) {
5660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
5670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateAdvance(SkGlyph* glyph) {
5690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->zeroMetrics();
5700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateMetrics(SkGlyph* glyph) {
5720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        glyph->zeroMetrics();
5730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateImage(const SkGlyph& glyph) {}
5750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generatePath(const SkGlyph& glyph, SkPath* path) {}
5760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                     SkPaint::FontMetrics* my) {
5780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (mx) {
579a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            sk_bzero(mx, sizeof(*mx));
5800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (my) {
582a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed            sk_bzero(my, sizeof(*my));
5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
5860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalerContext* SkScalerContext::Create(const SkDescriptor* desc)
5880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalerContext* c = SkFontHost::CreateScalerContext(desc);
5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (NULL == c) {
5910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        c = SkNEW_ARGS(SkScalerContext_Empty, (desc));
5920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return c;
5940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
596