GrTextStrike.cpp revision 98539c607b05f7e25406ae873bf1b24154a36a6f
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    }
4498539c607b05f7e25406ae873bf1b24154a36a6freed@google.com    GrTextStrike* strike = new GrTextStrike(this, scaler->getKey(),
4598539c607b05f7e25406ae873bf1b24154a36a6freed@google.com                                            scaler->getMaskFormat(), fAtlasMgr);
46ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.insert(key, strike);
47ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
48ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (fHead) {
49ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fHead->fPrev = strike;
50ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else {
51ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(NULL == fTail);
52ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fTail = strike;
53ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
54ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike->fPrev = NULL;
55ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike->fNext = fHead;
56ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fHead = strike;
57ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
58ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return strike;
59ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
60ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
61ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::abandonAll() {
62ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.deleteAll();
63ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (fAtlasMgr) {
64ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fAtlasMgr->abandonAll();
65ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        delete fAtlasMgr;
66ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fAtlasMgr = NULL;
67ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
68ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
69ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
70ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::freeAll() {
71ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.deleteAll();
72ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    delete fAtlasMgr;
73ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fAtlasMgr = NULL;
74ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
75ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
76ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) {
77ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrTextStrike* strike = fTail;
78ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (strike == preserveStrike) {
79ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        strike = strike->fPrev;
80ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
81ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (strike) {
82ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        int index = fCache.slowFindIndex(strike);
83ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(index >= 0);
84ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fCache.removeAt(index, strike->fFontScalerKey->getHash());
85ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        this->detachStrikeFromList(strike);
86ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        delete strike;
87ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
88ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
89ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
90ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG
91ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::validate() const {
92ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int count = fCache.count();
93ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (0 == count) {
94ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(!fHead);
95ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(!fTail);
96ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else if (1 == count) {
97ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(fHead == fTail);
98ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else {
99ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        GrAssert(fHead != fTail);
100ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
101ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
102ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int count2 = 0;
103ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    const GrTextStrike* strike = fHead;
104ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    while (strike) {
105ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        count2 += 1;
106ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        strike = strike->fNext;
107ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
108ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(count == count2);
109ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
110ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    count2 = 0;
111ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike = fTail;
112ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    while (strike) {
113ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        count2 += 1;
114ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        strike = strike->fPrev;
115ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
116ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(count == count2);
117ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
118ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
119ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
120ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com///////////////////////////////////////////////////////////////////////////////
121ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
122ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG
123ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    static int gCounter;
124ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
125ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
126ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/*
127ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    The text strike is specific to a given font/style/matrix setup, which is
128ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    represented by the GrHostFontScaler object we are given in getGlyph().
129ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
130ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    We map a 32bit glyphID to a GrGlyph record, which in turn points to a
131ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    atlas and a position within that texture.
132ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
133ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
134ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
13598539c607b05f7e25406ae873bf1b24154a36a6freed@google.com                           GrMaskFormat format,
136ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                           GrAtlasMgr* atlasMgr) : fPool(64) {
137ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey = key;
138ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey->ref();
139ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
140ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontCache = cache;     // no need to ref, it won't go away before we do
141ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fAtlasMgr = atlasMgr;   // no need to ref, it won't go away before we do
142ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fAtlas = NULL;
143ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
14498539c607b05f7e25406ae873bf1b24154a36a6freed@google.com    fMaskFormat = format;
14598539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
146ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG
147ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrPrintf(" GrTextStrike %p %d\n", this, gCounter);
148ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    gCounter += 1;
149ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
150ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
151ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
152ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comstatic void FreeGlyph(GrGlyph*& glyph) { glyph->free(); }
153ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
154ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::~GrTextStrike() {
155ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAtlas::FreeLList(fAtlas);
156ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey->unref();
157ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.getArray().visit(FreeGlyph);
158ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
159ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#if GR_DEBUG
160ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    gCounter -= 1;
161ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrPrintf("~GrTextStrike %p %d\n", this, gCounter);
162ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
163ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
164ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
165ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
166ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                     GrFontScaler* scaler) {
167ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrIRect bounds;
168ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
169ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return NULL;
170ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
171ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
172ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrGlyph* glyph = fPool.alloc();
173ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    glyph->init(packed, bounds);
174ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.insert(packed, glyph);
175ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return glyph;
176ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
177ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
178ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.combool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
179ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(glyph);
180ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(scaler);
181ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAssert(fCache.contains(glyph));
182ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (glyph->fAtlas) {
183ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return true;
184ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
185ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
186ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAutoRef ar(scaler);
18798539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
18898539c607b05f7e25406ae873bf1b24154a36a6freed@google.com    int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat);
18998539c607b05f7e25406ae873bf1b24154a36a6freed@google.com    size_t size = glyph->fBounds.area() * bytesPerPixel;
190ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAutoSMalloc<1024> storage(size);
191ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
19298539c607b05f7e25406ae873bf1b24154a36a6freed@google.com                                     glyph->height(),
19398539c607b05f7e25406ae873bf1b24154a36a6freed@google.com                                     glyph->width() * bytesPerPixel,
194ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                     storage.get())) {
195ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return false;
196ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
197ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
198ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrAtlas* atlas = fAtlasMgr->addToAtlas(fAtlas, glyph->width(),
199ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                           glyph->height(), storage.get(),
20098539c607b05f7e25406ae873bf1b24154a36a6freed@google.com                                           fMaskFormat,
201ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                           &glyph->fAtlasLocation);
202ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (NULL == atlas) {
203ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return false;
204ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
205ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
206ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    // update fAtlas as well, since they may be chained in a linklist
207ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    glyph->fAtlas = fAtlas = atlas;
208ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return true;
209ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
210ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
211ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
212