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