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