GrTextStrike.cpp revision fd03d4a829efe2d77a712fd991927c55f59a2ffe
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc. 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 8ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrAtlas.h" 9ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrGpu.h" 10ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrRectanizer.h" 11ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTextStrike.h" 12ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTextStrike_impl.h" 13ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 14fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.comSK_DEFINE_INST_COUNT(GrFontScaler) 15fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.comSK_DEFINE_INST_COUNT(GrKey) 16fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com 17fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com/////////////////////////////////////////////////////////////////////////////// 18fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com 19ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) { 20ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com gpu->ref(); 21ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr = NULL; 22ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 23ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fHead = fTail = NULL; 24ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 25ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 26ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrFontCache::~GrFontCache() { 27ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.deleteAll(); 28ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com delete fAtlasMgr; 29ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fGpu->unref(); 30ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 31ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 32ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler, 33ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com const Key& key) { 34ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (NULL == fAtlasMgr) { 35c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com fAtlasMgr = SkNEW_ARGS(GrAtlasMgr, (fGpu)); 36ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 37c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com GrTextStrike* strike = SkNEW_ARGS(GrTextStrike, 38c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com (this, scaler->getKey(), 39c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com scaler->getMaskFormat(), fAtlasMgr)); 40ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.insert(key, strike); 41ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 42ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (fHead) { 43ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fHead->fPrev = strike; 44ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } else { 45ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(NULL == fTail); 46ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fTail = strike; 47ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 48ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike->fPrev = NULL; 49ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike->fNext = fHead; 50ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fHead = strike; 51ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 52ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return strike; 53ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 54ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 55ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::freeAll() { 56ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.deleteAll(); 57ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com delete fAtlasMgr; 58ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr = NULL; 598fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fHead = NULL; 608fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com fTail = NULL; 61ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 62ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 63ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) { 64ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrTextStrike* strike = fTail; 657359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com while (strike) { 667359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com if (strike == preserveStrike) { 677359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com strike = strike->fPrev; 687359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com continue; 697359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com } 707359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com GrTextStrike* strikeToPurge = strike; 717359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com // keep going if we won't free up any atlases with this strike. 727359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com strike = (NULL == strikeToPurge->fAtlas) ? strikeToPurge->fPrev : NULL; 737359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com int index = fCache.slowFindIndex(strikeToPurge); 74ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(index >= 0); 757359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash()); 767359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com this->detachStrikeFromList(strikeToPurge); 777359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com delete strikeToPurge; 78ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 79ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 80ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 81ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 82ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::validate() const { 83ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com int count = fCache.count(); 84ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (0 == count) { 85ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(!fHead); 86ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(!fTail); 87ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } else if (1 == count) { 88ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(fHead == fTail); 89ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } else { 90ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(fHead != fTail); 91ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 92ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 93ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com int count2 = 0; 94ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com const GrTextStrike* strike = fHead; 95ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com while (strike) { 96ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com count2 += 1; 97ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike = strike->fNext; 98ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 99ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(count == count2); 100ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 101ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com count2 = 0; 102ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike = fTail; 103ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com while (strike) { 104ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com count2 += 1; 105ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike = strike->fPrev; 106ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 107ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(count == count2); 108ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 109ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 110ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 111ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/////////////////////////////////////////////////////////////////////////////// 112ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 113ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 114ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com static int gCounter; 115ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 116ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 117ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/* 118ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com The text strike is specific to a given font/style/matrix setup, which is 119ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com represented by the GrHostFontScaler object we are given in getGlyph(). 120ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 121ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com We map a 32bit glyphID to a GrGlyph record, which in turn points to a 122ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com atlas and a position within that texture. 123ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 124ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 125ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, 12698539c607b05f7e25406ae873bf1b24154a36a6freed@google.com GrMaskFormat format, 127ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAtlasMgr* atlasMgr) : fPool(64) { 128ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontScalerKey = key; 129ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontScalerKey->ref(); 130ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 131ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontCache = cache; // no need to ref, it won't go away before we do 132ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr = atlasMgr; // no need to ref, it won't go away before we do 133ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlas = NULL; 134ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 13598539c607b05f7e25406ae873bf1b24154a36a6freed@google.com fMaskFormat = format; 13698539c607b05f7e25406ae873bf1b24154a36a6freed@google.com 137ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 1383ef80cf14c3222f705c291123106991e52061678reed@google.com// GrPrintf(" GrTextStrike %p %d\n", this, gCounter); 139ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com gCounter += 1; 140ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 141ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 142ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 143ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comstatic void FreeGlyph(GrGlyph*& glyph) { glyph->free(); } 144ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 145ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::~GrTextStrike() { 146ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAtlas::FreeLList(fAtlas); 147ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontScalerKey->unref(); 14821cbec4870660f776f470e3a5e327599b6433dd2bsalomon@google.com fCache.getArray().visitAll(FreeGlyph); 149ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 150ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 151ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com gCounter -= 1; 1523ef80cf14c3222f705c291123106991e52061678reed@google.com// GrPrintf("~GrTextStrike %p %d\n", this, gCounter); 153ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 154ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 155ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 156ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, 157ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrFontScaler* scaler) { 158fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkIRect bounds; 159ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (!scaler->getPackedGlyphBounds(packed, &bounds)) { 160ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return NULL; 161ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 162ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 163ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrGlyph* glyph = fPool.alloc(); 164ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com glyph->init(packed, bounds); 165ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.insert(packed, glyph); 166ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return glyph; 167ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 168ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 169ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.combool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { 1700ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com#if 0 // testing hack to force us to flush our cache often 1710ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com static int gCounter; 1720ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com if ((++gCounter % 10) == 0) return false; 1730ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com#endif 1740ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com 175ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(glyph); 176ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(scaler); 177ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(fCache.contains(glyph)); 178ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (glyph->fAtlas) { 179ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return true; 180ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 181ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 182ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAutoRef ar(scaler); 18398539c607b05f7e25406ae873bf1b24154a36a6freed@google.com 18498539c607b05f7e25406ae873bf1b24154a36a6freed@google.com int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); 18598539c607b05f7e25406ae873bf1b24154a36a6freed@google.com size_t size = glyph->fBounds.area() * bytesPerPixel; 1863582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com SkAutoSMalloc<1024> storage(size); 187ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(), 18898539c607b05f7e25406ae873bf1b24154a36a6freed@google.com glyph->height(), 18998539c607b05f7e25406ae873bf1b24154a36a6freed@google.com glyph->width() * bytesPerPixel, 190ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com storage.get())) { 191ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return false; 192ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 193ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 194ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAtlas* atlas = fAtlasMgr->addToAtlas(fAtlas, glyph->width(), 195ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com glyph->height(), storage.get(), 19698539c607b05f7e25406ae873bf1b24154a36a6freed@google.com fMaskFormat, 197ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com &glyph->fAtlasLocation); 198ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (NULL == atlas) { 199ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return false; 200ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 201ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 202ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com // update fAtlas as well, since they may be chained in a linklist 203ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com glyph->fAtlas = fAtlas = atlas; 204ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return true; 205ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 206