From d38f137e9b813f8193675ebd3dfbfe8bc42639e9 Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Wed, 12 Oct 2011 19:53:16 +0000 Subject: Move gpu/include/* to include/gpu and gpu/src/* to src/gpu Review URL: http://codereview.appspot.com/5250070/ git-svn-id: http://skia.googlecode.com/svn/trunk@2471 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/GrTextStrike.cpp | 205 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 src/gpu/GrTextStrike.cpp (limited to 'src/gpu/GrTextStrike.cpp') diff --git a/src/gpu/GrTextStrike.cpp b/src/gpu/GrTextStrike.cpp new file mode 100644 index 0000000000..b8762adc11 --- /dev/null +++ b/src/gpu/GrTextStrike.cpp @@ -0,0 +1,205 @@ + +/* + * Copyright 2010 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + + +#include "GrAtlas.h" +#include "GrGpu.h" +#include "GrRectanizer.h" +#include "GrTextStrike.h" +#include "GrTextStrike_impl.h" +#include "GrRect.h" + +GrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) { + gpu->ref(); + fAtlasMgr = NULL; + + fHead = fTail = NULL; +} + +GrFontCache::~GrFontCache() { + fCache.deleteAll(); + delete fAtlasMgr; + fGpu->unref(); +} + +GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler, + const Key& key) { + if (NULL == fAtlasMgr) { + fAtlasMgr = new GrAtlasMgr(fGpu); + } + GrTextStrike* strike = new GrTextStrike(this, scaler->getKey(), + scaler->getMaskFormat(), fAtlasMgr); + fCache.insert(key, strike); + + if (fHead) { + fHead->fPrev = strike; + } else { + GrAssert(NULL == fTail); + fTail = strike; + } + strike->fPrev = NULL; + strike->fNext = fHead; + fHead = strike; + + return strike; +} + +void GrFontCache::freeAll() { + fCache.deleteAll(); + delete fAtlasMgr; + fAtlasMgr = NULL; + fHead = NULL; + fTail = NULL; +} + +void GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) { + GrTextStrike* strike = fTail; + while (strike) { + if (strike == preserveStrike) { + strike = strike->fPrev; + continue; + } + GrTextStrike* strikeToPurge = strike; + // keep going if we won't free up any atlases with this strike. + strike = (NULL == strikeToPurge->fAtlas) ? strikeToPurge->fPrev : NULL; + int index = fCache.slowFindIndex(strikeToPurge); + GrAssert(index >= 0); + fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash()); + this->detachStrikeFromList(strikeToPurge); + delete strikeToPurge; + } +} + +#if GR_DEBUG +void GrFontCache::validate() const { + int count = fCache.count(); + if (0 == count) { + GrAssert(!fHead); + GrAssert(!fTail); + } else if (1 == count) { + GrAssert(fHead == fTail); + } else { + GrAssert(fHead != fTail); + } + + int count2 = 0; + const GrTextStrike* strike = fHead; + while (strike) { + count2 += 1; + strike = strike->fNext; + } + GrAssert(count == count2); + + count2 = 0; + strike = fTail; + while (strike) { + count2 += 1; + strike = strike->fPrev; + } + GrAssert(count == count2); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// + +#if GR_DEBUG + static int gCounter; +#endif + +/* + The text strike is specific to a given font/style/matrix setup, which is + represented by the GrHostFontScaler object we are given in getGlyph(). + + We map a 32bit glyphID to a GrGlyph record, which in turn points to a + atlas and a position within that texture. + */ + +GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, + GrMaskFormat format, + GrAtlasMgr* atlasMgr) : fPool(64) { + fFontScalerKey = key; + fFontScalerKey->ref(); + + fFontCache = cache; // no need to ref, it won't go away before we do + fAtlasMgr = atlasMgr; // no need to ref, it won't go away before we do + fAtlas = NULL; + + fMaskFormat = format; + +#if GR_DEBUG +// GrPrintf(" GrTextStrike %p %d\n", this, gCounter); + gCounter += 1; +#endif +} + +static void FreeGlyph(GrGlyph*& glyph) { glyph->free(); } + +GrTextStrike::~GrTextStrike() { + GrAtlas::FreeLList(fAtlas); + fFontScalerKey->unref(); + fCache.getArray().visit(FreeGlyph); + +#if GR_DEBUG + gCounter -= 1; +// GrPrintf("~GrTextStrike %p %d\n", this, gCounter); +#endif +} + +GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, + GrFontScaler* scaler) { + GrIRect bounds; + if (!scaler->getPackedGlyphBounds(packed, &bounds)) { + return NULL; + } + + GrGlyph* glyph = fPool.alloc(); + glyph->init(packed, bounds); + fCache.insert(packed, glyph); + return glyph; +} + +bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { +#if 0 // testing hack to force us to flush our cache often + static int gCounter; + if ((++gCounter % 10) == 0) return false; +#endif + + GrAssert(glyph); + GrAssert(scaler); + GrAssert(fCache.contains(glyph)); + if (glyph->fAtlas) { + return true; + } + + GrAutoRef ar(scaler); + + int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); + size_t size = glyph->fBounds.area() * bytesPerPixel; + SkAutoSMalloc<1024> storage(size); + if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(), + glyph->height(), + glyph->width() * bytesPerPixel, + storage.get())) { + return false; + } + + GrAtlas* atlas = fAtlasMgr->addToAtlas(fAtlas, glyph->width(), + glyph->height(), storage.get(), + fMaskFormat, + &glyph->fAtlasLocation); + if (NULL == atlas) { + return false; + } + + // update fAtlas as well, since they may be chained in a linklist + glyph->fAtlas = fAtlas = atlas; + return true; +} + + -- cgit v1.2.3