blob: 6ee39d0c47ff035d3485f25248e84f38abe2105e [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#ifndef GrTextStrike_DEFINED
12#define GrTextStrike_DEFINED
13
commit-bot@chromium.org7d330eb2013-09-27 19:39:38 +000014#include "GrAtlas.h"
joshualitt947556f2014-11-21 09:03:45 -080015#include "GrDrawTarget.h"
16#include "GrFontScaler.h"
17#include "GrGlyph.h"
18#include "SkTDynamicHash.h"
19#include "SkVarAlloc.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000020
reed@google.comac10a2d2010-12-22 21:39:39 +000021class GrFontCache;
22class GrGpu;
23class GrFontPurgeListener;
24
25/**
jvanverth294c3262014-10-10 11:36:12 -070026 * The textstrike maps a hostfontscaler instance to a dictionary of
reed@google.comac10a2d2010-12-22 21:39:39 +000027 * glyphid->strike
28 */
29class GrTextStrike {
30public:
jvanverth294c3262014-10-10 11:36:12 -070031 GrTextStrike(GrFontCache*, const GrFontDescKey* fontScalerKey);
reed@google.comac10a2d2010-12-22 21:39:39 +000032 ~GrTextStrike();
33
jvanverth733f5f52014-07-11 19:45:16 -070034 const GrFontDescKey* getFontScalerKey() const { return fFontScalerKey; }
reed@google.comac10a2d2010-12-22 21:39:39 +000035 GrFontCache* getFontCache() const { return fFontCache; }
36
jvanverth787cdf92014-12-04 10:46:50 -080037 inline GrGlyph* getGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler) {
38 GrGlyph* glyph = fCache.find(packed);
39 if (NULL == glyph) {
40 glyph = this->generateGlyph(packed, scaler);
41 }
42 return glyph;
43 }
44
jvanverth681e65b2014-09-19 13:07:38 -070045 // returns true if glyph (or glyph+padding for distance field)
46 // is too large to ever fit in texture atlas subregions (GrPlots)
47 bool glyphTooLargeForAtlas(GrGlyph*);
48 // returns true if glyph successfully added to texture atlas, false otherwise
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +000049 bool addGlyphToAtlas(GrGlyph*, GrFontScaler*);
reed@google.comac10a2d2010-12-22 21:39:39 +000050
51 // testing
jvanverthdd6d2272014-07-22 13:25:26 -070052 int countGlyphs() const { return fCache.count(); }
reed@google.comac10a2d2010-12-22 21:39:39 +000053
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +000054 // remove any references to this plot
55 void removePlot(const GrPlot* plot);
commit-bot@chromium.org67ed64e2013-08-05 19:42:56 +000056
jvanverthdd6d2272014-07-22 13:25:26 -070057 static const GrFontDescKey& GetKey(const GrTextStrike& ts) {
58 return *(ts.fFontScalerKey);
59 }
60 static uint32_t Hash(const GrFontDescKey& key) {
61 return key.getHash();
62 }
63
reed@google.comac10a2d2010-12-22 21:39:39 +000064public:
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +000065 // for easy removal from list
reed@google.comac10a2d2010-12-22 21:39:39 +000066 GrTextStrike* fPrev;
67 GrTextStrike* fNext;
68
69private:
jvanverthdd6d2272014-07-22 13:25:26 -070070 SkTDynamicHash<GrGlyph, GrGlyph::PackedID> fCache;
jvanverth733f5f52014-07-11 19:45:16 -070071 const GrFontDescKey* fFontScalerKey;
joshualitt947556f2014-11-21 09:03:45 -080072 SkVarAlloc fPool;
reed@google.comac10a2d2010-12-22 21:39:39 +000073
74 GrFontCache* fFontCache;
jvanverth@google.comd830d132013-11-11 20:54:09 +000075 bool fUseDistanceField;
jvanverth@google.comd830d132013-11-11 20:54:09 +000076
robertphillips1d86ee82014-06-24 15:08:49 -070077 GrAtlas::ClientPlotUsage fPlotUsage;
reed@google.com98539c62011-03-15 15:40:16 +000078
reed@google.comac10a2d2010-12-22 21:39:39 +000079 GrGlyph* generateGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler);
reed@google.comac10a2d2010-12-22 21:39:39 +000080
81 friend class GrFontCache;
82};
83
84class GrFontCache {
85public:
86 GrFontCache(GrGpu*);
87 ~GrFontCache();
88
jvanverth787cdf92014-12-04 10:46:50 -080089 inline GrTextStrike* getStrike(GrFontScaler* scaler, bool useDistanceField) {
90 this->validate();
91
92 GrTextStrike* strike = fCache.find(*(scaler->getKey()));
93 if (NULL == strike) {
94 strike = this->generateStrike(scaler);
95 } else if (strike->fPrev) {
96 // Need to put the strike at the head of its dllist, since that is how
97 // we age the strikes for purging (we purge from the back of the list)
98 this->detachStrikeFromList(strike);
99 // attach at the head
100 fHead->fPrev = strike;
101 strike->fNext = fHead;
102 strike->fPrev = NULL;
103 fHead = strike;
104 }
105 strike->fUseDistanceField = useDistanceField;
106 this->validate();
107 return strike;
108 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000109
jvanverth294c3262014-10-10 11:36:12 -0700110 // add to texture atlas that matches this format
111 GrPlot* addToAtlas(GrMaskFormat format, GrAtlas::ClientPlotUsage* usage,
112 int width, int height, const void* image,
113 SkIPoint16* loc);
114
reed@google.comac10a2d2010-12-22 21:39:39 +0000115 void freeAll();
reed@google.comac10a2d2010-12-22 21:39:39 +0000116
jvanverth294c3262014-10-10 11:36:12 -0700117 // make an unused plot available for this glyph
118 bool freeUnusedPlot(GrTextStrike* preserveStrike, const GrGlyph* glyph);
commit-bot@chromium.org67ed64e2013-08-05 19:42:56 +0000119
reed@google.comac10a2d2010-12-22 21:39:39 +0000120 // testing
jvanverthdd6d2272014-07-22 13:25:26 -0700121 int countStrikes() const { return fCache.count(); }
reed@google.comac10a2d2010-12-22 21:39:39 +0000122 GrTextStrike* getHeadStrike() const { return fHead; }
123
commit-bot@chromium.org7801faa2014-05-14 15:14:51 +0000124 void updateTextures() {
125 for (int i = 0; i < kAtlasCount; ++i) {
robertphillips1d86ee82014-06-24 15:08:49 -0700126 if (fAtlases[i]) {
127 fAtlases[i]->uploadPlotsToTexture();
commit-bot@chromium.org7801faa2014-05-14 15:14:51 +0000128 }
129 }
130 }
131
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000132#ifdef SK_DEBUG
reed@google.comac10a2d2010-12-22 21:39:39 +0000133 void validate() const;
134#else
135 void validate() const {}
136#endif
137
commit-bot@chromium.org03e3e892013-10-02 18:19:17 +0000138 void dump() const;
commit-bot@chromium.org03e3e892013-10-02 18:19:17 +0000139
commit-bot@chromium.orgf8cb1842013-12-03 19:45:22 +0000140 enum AtlasType {
141 kA8_AtlasType, //!< 1-byte per pixel
142 k565_AtlasType, //!< 2-bytes per pixel
143 k8888_AtlasType, //!< 4-bytes per pixel
144
145 kLast_AtlasType = k8888_AtlasType
146 };
147 static const int kAtlasCount = kLast_AtlasType + 1;
148
reed@google.comac10a2d2010-12-22 21:39:39 +0000149private:
150 friend class GrFontPurgeListener;
151
jvanverthdd6d2272014-07-22 13:25:26 -0700152 SkTDynamicHash<GrTextStrike, GrFontDescKey> fCache;
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 // for LRU
154 GrTextStrike* fHead;
155 GrTextStrike* fTail;
156
157 GrGpu* fGpu;
robertphillips1d86ee82014-06-24 15:08:49 -0700158 GrAtlas* fAtlases[kAtlasCount];
reed@google.comac10a2d2010-12-22 21:39:39 +0000159
jvanverthdd6d2272014-07-22 13:25:26 -0700160 GrTextStrike* generateStrike(GrFontScaler*);
jvanverth787cdf92014-12-04 10:46:50 -0800161
162 inline void detachStrikeFromList(GrTextStrike* strike) {
163 if (strike->fPrev) {
164 SkASSERT(fHead != strike);
165 strike->fPrev->fNext = strike->fNext;
166 } else {
167 SkASSERT(fHead == strike);
168 fHead = strike->fNext;
169 }
170
171 if (strike->fNext) {
172 SkASSERT(fTail != strike);
173 strike->fNext->fPrev = strike->fPrev;
174 } else {
175 SkASSERT(fTail == strike);
176 fTail = strike->fPrev;
177 }
178 }
179
commit-bot@chromium.orgb2e9fa52013-10-27 20:50:23 +0000180 void purgeStrike(GrTextStrike* strike);
reed@google.comac10a2d2010-12-22 21:39:39 +0000181};
182
183#endif