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