aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrTextStrike.h
blob: 401bd7325909aa39be8a2e0ee655e1a08cf3f3e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

/*
 * Copyright 2010 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */



#ifndef GrTextStrike_DEFINED
#define GrTextStrike_DEFINED

#include "GrAllocPool.h"
#include "GrFontScaler.h"
#include "SkTDynamicHash.h"
#include "GrGlyph.h"
#include "GrDrawTarget.h"
#include "GrAtlas.h"

class GrFontCache;
class GrGpu;
class GrFontPurgeListener;

/**
 *  The textcache maps a hostfontscaler instance to a dictionary of
 *  glyphid->strike
 */
class GrTextStrike {
public:
    GrTextStrike(GrFontCache*, const GrFontDescKey* fontScalerKey, GrMaskFormat, GrAtlas*);
    ~GrTextStrike();

    const GrFontDescKey* getFontScalerKey() const { return fFontScalerKey; }
    GrFontCache* getFontCache() const { return fFontCache; }
    GrMaskFormat getMaskFormat() const { return fMaskFormat; }
    GrTexture*   getTexture() const { return fAtlas->getTexture(); }

    inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*);
    // returns true if glyph (or glyph+padding for distance field)
    // is too large to ever fit in texture atlas subregions (GrPlots)
    bool glyphTooLargeForAtlas(GrGlyph*);
    // returns true if glyph successfully added to texture atlas, false otherwise
    bool addGlyphToAtlas(GrGlyph*, GrFontScaler*);

    // testing
    int countGlyphs() const { return fCache.count(); }

    // remove any references to this plot
    void removePlot(const GrPlot* plot);

    static const GrFontDescKey& GetKey(const GrTextStrike& ts) {
        return *(ts.fFontScalerKey);
    }
    static uint32_t Hash(const GrFontDescKey& key) {
        return key.getHash();
    }

public:
    // for easy removal from list
    GrTextStrike*   fPrev;
    GrTextStrike*   fNext;

private:
    SkTDynamicHash<GrGlyph, GrGlyph::PackedID> fCache;
    const GrFontDescKey* fFontScalerKey;
    GrTAllocPool<GrGlyph> fPool;

    GrFontCache*    fFontCache;
    GrAtlas*        fAtlas;
    GrMaskFormat    fMaskFormat;
    bool            fUseDistanceField;

    GrAtlas::ClientPlotUsage fPlotUsage;

    GrGlyph* generateGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler);

    friend class GrFontCache;
};

class GrFontCache {
public:
    GrFontCache(GrGpu*);
    ~GrFontCache();

    inline GrTextStrike* getStrike(GrFontScaler*, bool useDistanceField);

    void freeAll();

    // make an unused plot available
    bool freeUnusedPlot(GrTextStrike* preserveStrike);

    // testing
    int countStrikes() const { return fCache.count(); }
    GrTextStrike* getHeadStrike() const { return fHead; }

    void updateTextures() {
        for (int i = 0; i < kAtlasCount; ++i) {
            if (fAtlases[i]) {
                fAtlases[i]->uploadPlotsToTexture();
            }
        }
    }

#ifdef SK_DEBUG
    void validate() const;
#else
    void validate() const {}
#endif

    void dump() const;

    enum AtlasType {
        kA8_AtlasType,   //!< 1-byte per pixel
        k565_AtlasType,  //!< 2-bytes per pixel
        k8888_AtlasType, //!< 4-bytes per pixel

        kLast_AtlasType = k8888_AtlasType
    };
    static const int kAtlasCount = kLast_AtlasType + 1;

private:
    friend class GrFontPurgeListener;

    SkTDynamicHash<GrTextStrike, GrFontDescKey> fCache;
    // for LRU
    GrTextStrike* fHead;
    GrTextStrike* fTail;

    GrGpu*      fGpu;
    GrAtlas*    fAtlases[kAtlasCount];

    GrTextStrike* generateStrike(GrFontScaler*);
    inline void detachStrikeFromList(GrTextStrike*);
    void purgeStrike(GrTextStrike* strike);
};

#endif