michael@0: michael@0: /* michael@0: * Copyright 2010 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: michael@0: #ifndef GrTextStrike_impl_DEFINED michael@0: #define GrTextStrike_impl_DEFINED michael@0: michael@0: class GrFontCache::Key { michael@0: public: michael@0: explicit Key(const GrKey* fontScalarKey) { michael@0: fFontScalerKey = fontScalarKey; michael@0: } michael@0: michael@0: intptr_t getHash() const { return fFontScalerKey->getHash(); } michael@0: michael@0: static bool LessThan(const GrTextStrike& strike, const Key& key) { michael@0: return *strike.getFontScalerKey() < *key.fFontScalerKey; michael@0: } michael@0: static bool Equals(const GrTextStrike& strike, const Key& key) { michael@0: return *strike.getFontScalerKey() == *key.fFontScalerKey; michael@0: } michael@0: michael@0: private: michael@0: const GrKey* fFontScalerKey; michael@0: }; michael@0: michael@0: void GrFontCache::detachStrikeFromList(GrTextStrike* strike) { michael@0: if (strike->fPrev) { michael@0: SkASSERT(fHead != strike); michael@0: strike->fPrev->fNext = strike->fNext; michael@0: } else { michael@0: SkASSERT(fHead == strike); michael@0: fHead = strike->fNext; michael@0: } michael@0: michael@0: if (strike->fNext) { michael@0: SkASSERT(fTail != strike); michael@0: strike->fNext->fPrev = strike->fPrev; michael@0: } else { michael@0: SkASSERT(fTail == strike); michael@0: fTail = strike->fPrev; michael@0: } michael@0: } michael@0: michael@0: GrTextStrike* GrFontCache::getStrike(GrFontScaler* scaler, bool useDistanceField) { michael@0: this->validate(); michael@0: michael@0: const Key key(scaler->getKey()); michael@0: GrTextStrike* strike = fCache.find(key); michael@0: if (NULL == strike) { michael@0: strike = this->generateStrike(scaler, key); michael@0: } else if (strike->fPrev) { michael@0: // Need to put the strike at the head of its dllist, since that is how michael@0: // we age the strikes for purging (we purge from the back of the list michael@0: this->detachStrikeFromList(strike); michael@0: // attach at the head michael@0: fHead->fPrev = strike; michael@0: strike->fNext = fHead; michael@0: strike->fPrev = NULL; michael@0: fHead = strike; michael@0: } michael@0: strike->fUseDistanceField = useDistanceField; michael@0: this->validate(); michael@0: return strike; michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: /** michael@0: * This Key just wraps a glyphID, and matches the protocol need for michael@0: * GrTHashTable michael@0: */ michael@0: class GrTextStrike::Key { michael@0: public: michael@0: Key(GrGlyph::PackedID id) : fPackedID(id) {} michael@0: michael@0: uint32_t getHash() const { return fPackedID; } michael@0: michael@0: static bool LessThan(const GrGlyph& glyph, const Key& key) { michael@0: return glyph.fPackedID < key.fPackedID; michael@0: } michael@0: static bool Equals(const GrGlyph& glyph, const Key& key) { michael@0: return glyph.fPackedID == key.fPackedID; michael@0: } michael@0: michael@0: private: michael@0: GrGlyph::PackedID fPackedID; michael@0: }; michael@0: michael@0: GrGlyph* GrTextStrike::getGlyph(GrGlyph::PackedID packed, michael@0: GrFontScaler* scaler) { michael@0: GrGlyph* glyph = fCache.find(packed); michael@0: if (NULL == glyph) { michael@0: glyph = this->generateGlyph(packed, scaler); michael@0: } michael@0: return glyph; michael@0: } michael@0: michael@0: #endif