GrTextStrike.cpp revision ac10a2d039c5d52eed66e27cbbc503ab523c1cd5
1ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/* 2ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com Copyright 2010 Google Inc. 3ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 4ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com Licensed under the Apache License, Version 2.0 (the "License"); 5ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com you may not use this file except in compliance with the License. 6ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com You may obtain a copy of the License at 7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 8ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com http://www.apache.org/licenses/LICENSE-2.0 9ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 10ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com Unless required by applicable law or agreed to in writing, software 11ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com distributed under the License is distributed on an "AS IS" BASIS, 12ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com See the License for the specific language governing permissions and 14ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com limitations under the License. 15ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 16ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 17ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 18ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrAtlas.h" 19ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrGpu.h" 20ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrMemory.h" 21ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrRectanizer.h" 22ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTextStrike.h" 23ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTextStrike_impl.h" 24ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrRect.h" 25ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 26ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) { 27ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com gpu->ref(); 28ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr = NULL; 29ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 30ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fHead = fTail = NULL; 31ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 32ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 33ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrFontCache::~GrFontCache() { 34ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.deleteAll(); 35ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com delete fAtlasMgr; 36ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fGpu->unref(); 37ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 38ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 39ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler, 40ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com const Key& key) { 41ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (NULL == fAtlasMgr) { 42ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr = new GrAtlasMgr(fGpu); 43ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 44ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrTextStrike* strike = new GrTextStrike(this, scaler->getKey(), fAtlasMgr); 45ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.insert(key, strike); 46ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 47ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (fHead) { 48ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fHead->fPrev = strike; 49ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } else { 50ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(NULL == fTail); 51ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fTail = strike; 52ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 53ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike->fPrev = NULL; 54ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike->fNext = fHead; 55ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fHead = strike; 56ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 57ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return strike; 58ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 59ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 60ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::abandonAll() { 61ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.deleteAll(); 62ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (fAtlasMgr) { 63ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr->abandonAll(); 64ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com delete fAtlasMgr; 65ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr = NULL; 66ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 67ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 68ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 69ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::freeAll() { 70ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.deleteAll(); 71ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com delete fAtlasMgr; 72ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr = NULL; 73ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 74ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 75ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) { 76ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrTextStrike* strike = fTail; 77ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (strike == preserveStrike) { 78ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike = strike->fPrev; 79ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 80ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (strike) { 81ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com int index = fCache.slowFindIndex(strike); 82ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(index >= 0); 83ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.removeAt(index, strike->fFontScalerKey->getHash()); 84ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com this->detachStrikeFromList(strike); 85ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com delete strike; 86ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 87ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 88ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 89ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 90ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::validate() const { 91ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com int count = fCache.count(); 92ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (0 == count) { 93ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(!fHead); 94ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(!fTail); 95ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } else if (1 == count) { 96ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(fHead == fTail); 97ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } else { 98ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(fHead != fTail); 99ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 100ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 101ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com int count2 = 0; 102ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com const GrTextStrike* strike = fHead; 103ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com while (strike) { 104ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com count2 += 1; 105ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike = strike->fNext; 106ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 107ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(count == count2); 108ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 109ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com count2 = 0; 110ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike = fTail; 111ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com while (strike) { 112ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com count2 += 1; 113ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike = strike->fPrev; 114ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 115ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(count == count2); 116ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 117ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 118ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 119ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/////////////////////////////////////////////////////////////////////////////// 120ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 121ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 122ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com static int gCounter; 123ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 124ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 125ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/* 126ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com The text strike is specific to a given font/style/matrix setup, which is 127ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com represented by the GrHostFontScaler object we are given in getGlyph(). 128ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 129ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com We map a 32bit glyphID to a GrGlyph record, which in turn points to a 130ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com atlas and a position within that texture. 131ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 132ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 133ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, 134ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAtlasMgr* atlasMgr) : fPool(64) { 135ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontScalerKey = key; 136ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontScalerKey->ref(); 137ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 138ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontCache = cache; // no need to ref, it won't go away before we do 139ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr = atlasMgr; // no need to ref, it won't go away before we do 140ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlas = NULL; 141ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 142ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 143ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrPrintf(" GrTextStrike %p %d\n", this, gCounter); 144ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com gCounter += 1; 145ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 146ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 147ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 148ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comstatic void FreeGlyph(GrGlyph*& glyph) { glyph->free(); } 149ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 150ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::~GrTextStrike() { 151ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAtlas::FreeLList(fAtlas); 152ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontScalerKey->unref(); 153ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.getArray().visit(FreeGlyph); 154ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 155ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 156ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com gCounter -= 1; 157ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrPrintf("~GrTextStrike %p %d\n", this, gCounter); 158ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 159ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 160ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 161ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, 162ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrFontScaler* scaler) { 163ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrIRect bounds; 164ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (!scaler->getPackedGlyphBounds(packed, &bounds)) { 165ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return NULL; 166ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 167ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 168ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrGlyph* glyph = fPool.alloc(); 169ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com glyph->init(packed, bounds); 170ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.insert(packed, glyph); 171ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return glyph; 172ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 173ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 174ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.combool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { 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); 183ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 184ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com size_t size = glyph->fBounds.area(); 185ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAutoSMalloc<1024> storage(size); 186ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(), 187ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com glyph->height(), glyph->width(), 188ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com storage.get())) { 189ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return false; 190ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 191ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 192ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAtlas* atlas = fAtlasMgr->addToAtlas(fAtlas, glyph->width(), 193ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com glyph->height(), storage.get(), 194ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com &glyph->fAtlasLocation); 195ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (NULL == atlas) { 196ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return false; 197ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 198ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 199ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com // update fAtlas as well, since they may be chained in a linklist 200ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com glyph->fAtlas = fAtlas = atlas; 201ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return true; 202ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 203ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 204ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 205