GrTextStrike.cpp revision ac10a2d039c5d52eed66e27cbbc503ab523c1cd5
1ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/*
2ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    Copyright 2010 Google Inc.
3ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
4ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    Licensed under the Apache License, Version 2.0 (the "License");
5ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    you may not use this file except in compliance with the License.
6ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    You may obtain a copy of the License at
7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
8ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com         http://www.apache.org/licenses/LICENSE-2.0
9ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
10ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    Unless required by applicable law or agreed to in writing, software
11ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    distributed under the License is distributed on an "AS IS" BASIS,
12ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    See the License for the specific language governing permissions and
14ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    limitations under the License.
15ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
16ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
17ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
18ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrAtlas.h"
19ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrGpu.h"
20ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrMemory.h"
21ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrRectanizer.h"
22ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTextStrike.h"
23ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTextStrike_impl.h"
24ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrRect.h"
25ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
26ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) {
27ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    gpu->ref();
28ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fAtlasMgr = NULL;
29ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
30ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fHead = fTail = NULL;
31ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
32ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
33ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrFontCache::~GrFontCache() {
34ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.deleteAll();
35ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    delete fAtlasMgr;
36ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fGpu->unref();
37ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
38ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
39ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler,
40ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                          const Key& key) {
41ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (NULL == fAtlasMgr) {
42ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fAtlasMgr = new GrAtlasMgr(fGpu);
43ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
44ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrTextStrike* strike = new GrTextStrike(this, scaler->getKey(), fAtlasMgr);
45ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.insert(key, strike);
46ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
47ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (fHead) {
48ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fHead->fPrev = strike;
49ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else {
50ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(NULL == fTail);
51ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fTail = strike;
52ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
53ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike->fPrev = NULL;
54ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike->fNext = fHead;
55ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fHead = strike;
56ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
57ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return strike;
58ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
59ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
60ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::abandonAll() {
61ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.deleteAll();
62ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (fAtlasMgr) {
63ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fAtlasMgr->abandonAll();
64ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        delete fAtlasMgr;
65ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fAtlasMgr = NULL;
66ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
67ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
68ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
69ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::freeAll() {
70ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.deleteAll();
71ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    delete fAtlasMgr;
72ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fAtlasMgr = NULL;
73ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
74ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
75ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) {
76ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrTextStrike* strike = fTail;
77ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (strike == preserveStrike) {
78ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        strike = strike->fPrev;
79ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
80ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (strike) {
81ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        int index = fCache.slowFindIndex(strike);
82ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(index >= 0);
83ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fCache.removeAt(index, strike->fFontScalerKey->getHash());
84ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        this->detachStrikeFromList(strike);
85ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        delete strike;
86ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
87ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
88ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
89ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG
90ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::validate() const {
91ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int count = fCache.count();
92ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (0 == count) {
93ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(!fHead);
94ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(!fTail);
95ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else if (1 == count) {
96ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(fHead == fTail);
97ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else {
98ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(fHead != fTail);
99ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
100ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
101ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int count2 = 0;
102ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    const GrTextStrike* strike = fHead;
103ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    while (strike) {
104ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        count2 += 1;
105ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        strike = strike->fNext;
106ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
107ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(count == count2);
108ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
109ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    count2 = 0;
110ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike = fTail;
111ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    while (strike) {
112ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        count2 += 1;
113ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        strike = strike->fPrev;
114ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
115ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(count == count2);
116ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
117ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
118ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
119ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com///////////////////////////////////////////////////////////////////////////////
120ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
121ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG
122ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    static int gCounter;
123ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
124ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
125ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/*
126ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    The text strike is specific to a given font/style/matrix setup, which is
127ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    represented by the GrHostFontScaler object we are given in getGlyph().
128ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
129ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    We map a 32bit glyphID to a GrGlyph record, which in turn points to a
130ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    atlas and a position within that texture.
131ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
132ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
133ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
134ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                           GrAtlasMgr* atlasMgr) : fPool(64) {
135ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey = key;
136ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey->ref();
137ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
138ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontCache = cache;     // no need to ref, it won't go away before we do
139ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fAtlasMgr = atlasMgr;   // no need to ref, it won't go away before we do
140ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fAtlas = NULL;
141ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
142ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG
143ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrPrintf(" GrTextStrike %p %d\n", this, gCounter);
144ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    gCounter += 1;
145ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
146ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
147ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
148ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comstatic void FreeGlyph(GrGlyph*& glyph) { glyph->free(); }
149ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
150ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::~GrTextStrike() {
151ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAtlas::FreeLList(fAtlas);
152ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey->unref();
153ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.getArray().visit(FreeGlyph);
154ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
155ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG
156ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    gCounter -= 1;
157ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrPrintf("~GrTextStrike %p %d\n", this, gCounter);
158ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
159ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
160ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
161ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
162ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                     GrFontScaler* scaler) {
163ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrIRect bounds;
164ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
165ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return NULL;
166ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
167ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
168ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrGlyph* glyph = fPool.alloc();
169ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    glyph->init(packed, bounds);
170ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.insert(packed, glyph);
171ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return glyph;
172ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
173ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
174ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.combool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
175ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(glyph);
176ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(scaler);
177ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(fCache.contains(glyph));
178ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (glyph->fAtlas) {
179ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return true;
180ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
181ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
182ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAutoRef ar(scaler);
183ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
184ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    size_t size = glyph->fBounds.area();
185ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAutoSMalloc<1024> storage(size);
186ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
187ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                     glyph->height(), glyph->width(),
188ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                     storage.get())) {
189ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return false;
190ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
191ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
192ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAtlas* atlas = fAtlasMgr->addToAtlas(fAtlas, glyph->width(),
193ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                           glyph->height(), storage.get(),
194ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                           &glyph->fAtlasLocation);
195ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (NULL == atlas) {
196ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return false;
197ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
198ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
199ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    // update fAtlas as well, since they may be chained in a linklist
200ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    glyph->fAtlas = fAtlas = atlas;
201ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return true;
202ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
203ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
204ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
205