aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrTextStrike.h
blob: 09d7323179543950840c1f937e342fcc4dc9c2f0 (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
139

/*
 * 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 "GrAtlas.h"
#include "GrDrawTarget.h"
#include "GrFontScaler.h"
#include "GrGlyph.h"
#include "SkTDynamicHash.h"
#include "SkVarAlloc.h"

class GrFontCache;
class GrGpu;
class GrFontPurgeListener;

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

    const GrFontDescKey* getFontScalerKey() const { return fFontScalerKey; }
    GrFontCache* getFontCache() const { return fFontCache; }

    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;
    SkVarAlloc fPool;

    GrFontCache*    fFontCache;
    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);

    // add to texture atlas that matches this format
    GrPlot* addToAtlas(GrMaskFormat format, GrAtlas::ClientPlotUsage* usage,
                       int width, int height, const void* image,
                       SkIPoint16* loc);

    void freeAll();

    // make an unused plot available for this glyph
    bool freeUnusedPlot(GrTextStrike* preserveStrike, const GrGlyph* glyph);

    // 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