1
2/*
3 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10
11#ifndef GrTextStrike_DEFINED
12#define GrTextStrike_DEFINED
13
14#include "GrAllocPool.h"
15#include "GrFontScaler.h"
16#include "SkTDynamicHash.h"
17#include "GrGlyph.h"
18#include "GrDrawTarget.h"
19#include "GrAtlas.h"
20
21class GrFontCache;
22class GrGpu;
23class GrFontPurgeListener;
24
25/**
26 *  The textcache maps a hostfontscaler instance to a dictionary of
27 *  glyphid->strike
28 */
29class GrTextStrike {
30public:
31    GrTextStrike(GrFontCache*, const GrFontDescKey* fontScalerKey, GrMaskFormat, GrAtlas*);
32    ~GrTextStrike();
33
34    const GrFontDescKey* getFontScalerKey() const { return fFontScalerKey; }
35    GrFontCache* getFontCache() const { return fFontCache; }
36    GrMaskFormat getMaskFormat() const { return fMaskFormat; }
37    GrTexture*   getTexture() const { return fAtlas->getTexture(); }
38
39    inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*);
40    // returns true if glyph (or glyph+padding for distance field)
41    // is too large to ever fit in texture atlas subregions (GrPlots)
42    bool glyphTooLargeForAtlas(GrGlyph*);
43    // returns true if glyph successfully added to texture atlas, false otherwise
44    bool addGlyphToAtlas(GrGlyph*, GrFontScaler*);
45
46    // testing
47    int countGlyphs() const { return fCache.count(); }
48
49    // remove any references to this plot
50    void removePlot(const GrPlot* plot);
51
52    static const GrFontDescKey& GetKey(const GrTextStrike& ts) {
53        return *(ts.fFontScalerKey);
54    }
55    static uint32_t Hash(const GrFontDescKey& key) {
56        return key.getHash();
57    }
58
59public:
60    // for easy removal from list
61    GrTextStrike*   fPrev;
62    GrTextStrike*   fNext;
63
64private:
65    SkTDynamicHash<GrGlyph, GrGlyph::PackedID> fCache;
66    const GrFontDescKey* fFontScalerKey;
67    GrTAllocPool<GrGlyph> fPool;
68
69    GrFontCache*    fFontCache;
70    GrAtlas*        fAtlas;
71    GrMaskFormat    fMaskFormat;
72    bool            fUseDistanceField;
73
74    GrAtlas::ClientPlotUsage fPlotUsage;
75
76    GrGlyph* generateGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler);
77
78    friend class GrFontCache;
79};
80
81class GrFontCache {
82public:
83    GrFontCache(GrGpu*);
84    ~GrFontCache();
85
86    inline GrTextStrike* getStrike(GrFontScaler*, bool useDistanceField);
87
88    void freeAll();
89
90    // make an unused plot available
91    bool freeUnusedPlot(GrTextStrike* preserveStrike);
92
93    // testing
94    int countStrikes() const { return fCache.count(); }
95    GrTextStrike* getHeadStrike() const { return fHead; }
96
97    void updateTextures() {
98        for (int i = 0; i < kAtlasCount; ++i) {
99            if (fAtlases[i]) {
100                fAtlases[i]->uploadPlotsToTexture();
101            }
102        }
103    }
104
105#ifdef SK_DEBUG
106    void validate() const;
107#else
108    void validate() const {}
109#endif
110
111    void dump() const;
112
113    enum AtlasType {
114        kA8_AtlasType,   //!< 1-byte per pixel
115        k565_AtlasType,  //!< 2-bytes per pixel
116        k8888_AtlasType, //!< 4-bytes per pixel
117
118        kLast_AtlasType = k8888_AtlasType
119    };
120    static const int kAtlasCount = kLast_AtlasType + 1;
121
122private:
123    friend class GrFontPurgeListener;
124
125    SkTDynamicHash<GrTextStrike, GrFontDescKey> fCache;
126    // for LRU
127    GrTextStrike* fHead;
128    GrTextStrike* fTail;
129
130    GrGpu*      fGpu;
131    GrAtlas*    fAtlases[kAtlasCount];
132
133    GrTextStrike* generateStrike(GrFontScaler*);
134    inline void detachStrikeFromList(GrTextStrike*);
135    void purgeStrike(GrTextStrike* strike);
136};
137
138#endif
139