GrTextStrike.cpp revision 98539c607b05f7e25406ae873bf1b24154a36a6f
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 } 4498539c607b05f7e25406ae873bf1b24154a36a6freed@google.com GrTextStrike* strike = new GrTextStrike(this, scaler->getKey(), 4598539c607b05f7e25406ae873bf1b24154a36a6freed@google.com scaler->getMaskFormat(), fAtlasMgr); 46ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.insert(key, strike); 47ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 48ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (fHead) { 49ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fHead->fPrev = strike; 50ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } else { 51ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(NULL == fTail); 52ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fTail = strike; 53ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 54ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike->fPrev = NULL; 55ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike->fNext = fHead; 56ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fHead = strike; 57ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 58ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return strike; 59ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 60ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 61ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::abandonAll() { 62ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.deleteAll(); 63ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (fAtlasMgr) { 64ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr->abandonAll(); 65ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com delete fAtlasMgr; 66ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr = NULL; 67ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 68ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 69ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 70ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::freeAll() { 71ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.deleteAll(); 72ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com delete fAtlasMgr; 73ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr = NULL; 74ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 75ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 76ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) { 77ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrTextStrike* strike = fTail; 78ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (strike == preserveStrike) { 79ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike = strike->fPrev; 80ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 81ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (strike) { 82ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com int index = fCache.slowFindIndex(strike); 83ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(index >= 0); 84ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.removeAt(index, strike->fFontScalerKey->getHash()); 85ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com this->detachStrikeFromList(strike); 86ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com delete strike; 87ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 88ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 89ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 90ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 91ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::validate() const { 92ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com int count = fCache.count(); 93ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (0 == count) { 94ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(!fHead); 95ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(!fTail); 96ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } else if (1 == count) { 97ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(fHead == fTail); 98ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } else { 99ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(fHead != fTail); 100ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 101ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 102ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com int count2 = 0; 103ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com const GrTextStrike* strike = fHead; 104ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com while (strike) { 105ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com count2 += 1; 106ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike = strike->fNext; 107ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 108ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(count == count2); 109ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 110ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com count2 = 0; 111ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike = fTail; 112ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com while (strike) { 113ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com count2 += 1; 114ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com strike = strike->fPrev; 115ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 116ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(count == count2); 117ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 118ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 119ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 120ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/////////////////////////////////////////////////////////////////////////////// 121ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 122ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 123ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com static int gCounter; 124ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 125ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 126ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/* 127ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com The text strike is specific to a given font/style/matrix setup, which is 128ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com represented by the GrHostFontScaler object we are given in getGlyph(). 129ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 130ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com We map a 32bit glyphID to a GrGlyph record, which in turn points to a 131ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com atlas and a position within that texture. 132ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 133ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 134ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, 13598539c607b05f7e25406ae873bf1b24154a36a6freed@google.com GrMaskFormat format, 136ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAtlasMgr* atlasMgr) : fPool(64) { 137ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontScalerKey = key; 138ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontScalerKey->ref(); 139ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 140ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontCache = cache; // no need to ref, it won't go away before we do 141ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlasMgr = atlasMgr; // no need to ref, it won't go away before we do 142ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAtlas = NULL; 143ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 14498539c607b05f7e25406ae873bf1b24154a36a6freed@google.com fMaskFormat = format; 14598539c607b05f7e25406ae873bf1b24154a36a6freed@google.com 146ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 147ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrPrintf(" GrTextStrike %p %d\n", this, gCounter); 148ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com gCounter += 1; 149ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 150ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 151ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 152ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comstatic void FreeGlyph(GrGlyph*& glyph) { glyph->free(); } 153ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 154ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::~GrTextStrike() { 155ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAtlas::FreeLList(fAtlas); 156ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fFontScalerKey->unref(); 157ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.getArray().visit(FreeGlyph); 158ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 159ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG 160ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com gCounter -= 1; 161ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrPrintf("~GrTextStrike %p %d\n", this, gCounter); 162ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 163ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 164ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 165ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, 166ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrFontScaler* scaler) { 167ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrIRect bounds; 168ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (!scaler->getPackedGlyphBounds(packed, &bounds)) { 169ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return NULL; 170ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 171ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 172ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrGlyph* glyph = fPool.alloc(); 173ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com glyph->init(packed, bounds); 174ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCache.insert(packed, glyph); 175ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return glyph; 176ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 177ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 178ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.combool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { 179ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(glyph); 180ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(scaler); 181ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAssert(fCache.contains(glyph)); 182ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (glyph->fAtlas) { 183ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return true; 184ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 185ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 186ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAutoRef ar(scaler); 18798539c607b05f7e25406ae873bf1b24154a36a6freed@google.com 18898539c607b05f7e25406ae873bf1b24154a36a6freed@google.com int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); 18998539c607b05f7e25406ae873bf1b24154a36a6freed@google.com size_t size = glyph->fBounds.area() * bytesPerPixel; 190ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAutoSMalloc<1024> storage(size); 191ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(), 19298539c607b05f7e25406ae873bf1b24154a36a6freed@google.com glyph->height(), 19398539c607b05f7e25406ae873bf1b24154a36a6freed@google.com glyph->width() * bytesPerPixel, 194ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com storage.get())) { 195ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return false; 196ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 197ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 198ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com GrAtlas* atlas = fAtlasMgr->addToAtlas(fAtlas, glyph->width(), 199ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com glyph->height(), storage.get(), 20098539c607b05f7e25406ae873bf1b24154a36a6freed@google.com fMaskFormat, 201ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com &glyph->fAtlasLocation); 202ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (NULL == atlas) { 203ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return false; 204ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 205ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 206ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com // update fAtlas as well, since they may be chained in a linklist 207ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com glyph->fAtlas = fAtlas = atlas; 208ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return true; 209ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com} 210ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 211ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 212