GrTextStrike.cpp revision 03e3e89641c93df603dfb705d518848dfe81427e
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
8ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrAtlas.h"
9ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrGpu.h"
10ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrRectanizer.h"
11ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTextStrike.h"
12ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrTextStrike_impl.h"
1303e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org#include "SkString.h"
14ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
15fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.comSK_DEFINE_INST_COUNT(GrFontScaler)
16fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.comSK_DEFINE_INST_COUNT(GrKey)
17fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com
18fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com///////////////////////////////////////////////////////////////////////////////
19fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com
2067ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#define FONT_CACHE_STATS 0
2167ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#if FONT_CACHE_STATS
2267ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.orgstatic int g_PurgeCount = 0;
2367ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#endif
2467ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org
25ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) {
26ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    gpu->ref();
273fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    for (int i = 0; i < kMaskFormatCount; ++i) {
283fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org        fAtlasMgr[i] = NULL;
293fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    }
30ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
31ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fHead = fTail = NULL;
32ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
33ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
34ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrFontCache::~GrFontCache() {
35ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.deleteAll();
363fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    for (int i = 0; i < kMaskFormatCount; ++i) {
373fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org        delete fAtlasMgr[i];
383fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    }
39ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fGpu->unref();
4067ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#if FONT_CACHE_STATS
4167ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org      GrPrintf("Num purges: %d\n", g_PurgeCount);
4267ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#endif
43ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
44ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
45952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.orgstatic GrPixelConfig mask_format_to_pixel_config(GrMaskFormat format) {
46952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org    switch (format) {
47952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org        case kA8_GrMaskFormat:
48952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org            return kAlpha_8_GrPixelConfig;
49952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org        case kA565_GrMaskFormat:
50952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org            return kRGB_565_GrPixelConfig;
51952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org        case kA888_GrMaskFormat:
52952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org            return kSkia8888_GrPixelConfig;
53952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org        default:
54952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org            SkDEBUGFAIL("unknown maskformat");
55952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org    }
56952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org    return kUnknown_GrPixelConfig;
57952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org}
58952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org
59ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler,
60ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                          const Key& key) {
613fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    GrMaskFormat format = scaler->getMaskFormat();
62952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org    GrPixelConfig config = mask_format_to_pixel_config(format);
633fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    if (NULL == fAtlasMgr[format]) {
64952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org        fAtlasMgr[format] = SkNEW_ARGS(GrAtlasMgr, (fGpu, config));
65ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
66c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    GrTextStrike* strike = SkNEW_ARGS(GrTextStrike,
67952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org                                      (this, scaler->getKey(), format, fAtlasMgr[format]));
68ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.insert(key, strike);
69ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
70ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (fHead) {
71ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fHead->fPrev = strike;
72ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else {
73f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(NULL == fTail);
74ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fTail = strike;
75ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
76ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike->fPrev = NULL;
77ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike->fNext = fHead;
78ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fHead = strike;
79ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
80ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return strike;
81ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
82ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
83ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::freeAll() {
84ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.deleteAll();
853fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    for (int i = 0; i < kMaskFormatCount; ++i) {
863fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org        delete fAtlasMgr[i];
873fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org        fAtlasMgr[i] = NULL;
883fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    }
898fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fHead = NULL;
908fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTail = NULL;
91ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
92ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
93ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) {
94bbe55fdf6608b8aec2e5d3945da6b1872b3a380fjvanverth@google.com    SkASSERT(NULL != preserveStrike);
95ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrTextStrike* strike = fTail;
9667ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    bool purge = true;
97bbe55fdf6608b8aec2e5d3945da6b1872b3a380fjvanverth@google.com    GrMaskFormat maskFormat = preserveStrike->fMaskFormat;
9867ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    while (strike) {
99bbe55fdf6608b8aec2e5d3945da6b1872b3a380fjvanverth@google.com        if (strike == preserveStrike || maskFormat != strike->fMaskFormat) {
10067ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org            strike = strike->fPrev;
10167ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org            continue;
10267ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org        }
10367ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org        GrTextStrike* strikeToPurge = strike;
10467ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org        strike = strikeToPurge->fPrev;
10567ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org        if (purge) {
10667ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org            // keep purging if we won't free up any atlases with this strike.
1077d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org            purge = strikeToPurge->fAtlas.isEmpty();
10867ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org            int index = fCache.slowFindIndex(strikeToPurge);
109f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org            SkASSERT(index >= 0);
11067ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org            fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash());
11167ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org            this->detachStrikeFromList(strikeToPurge);
11267ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org            delete strikeToPurge;
11367ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org        }
11467ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    }
11567ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#if FONT_CACHE_STATS
11667ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    ++g_PurgeCount;
11767ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#endif
11867ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org}
11967ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org
1207d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.orgvoid GrFontCache::freePlotExceptFor(GrTextStrike* preserveStrike) {
121bbe55fdf6608b8aec2e5d3945da6b1872b3a380fjvanverth@google.com    SkASSERT(NULL != preserveStrike);
12267ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    GrTextStrike* strike = fTail;
123bbe55fdf6608b8aec2e5d3945da6b1872b3a380fjvanverth@google.com    GrMaskFormat maskFormat = preserveStrike->fMaskFormat;
1247359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com    while (strike) {
125bbe55fdf6608b8aec2e5d3945da6b1872b3a380fjvanverth@google.com        if (strike == preserveStrike || maskFormat != strike->fMaskFormat) {
1267359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com            strike = strike->fPrev;
1277359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com            continue;
1287359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com        }
1297359eae7c6fce8cb88ae28ca7048283b77535db4bsalomon@google.com        GrTextStrike* strikeToPurge = strike;
13067ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org        strike = strikeToPurge->fPrev;
1317d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org        if (strikeToPurge->removeUnusedPlots()) {
1327d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org            if (strikeToPurge->fAtlas.isEmpty()) {
13367ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org                int index = fCache.slowFindIndex(strikeToPurge);
134f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org                SkASSERT(index >= 0);
13567ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org                fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash());
13667ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org                this->detachStrikeFromList(strikeToPurge);
13767ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org                delete strikeToPurge;
13867ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org            }
13967ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org            break;
14067ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org        }
141ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
142ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
143ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
144515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
145ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::validate() const {
146ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int count = fCache.count();
147ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (0 == count) {
148f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(!fHead);
149f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(!fTail);
150ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else if (1 == count) {
151f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(fHead == fTail);
152ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else {
153f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(fHead != fTail);
154ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
155ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
156ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int count2 = 0;
157ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    const GrTextStrike* strike = fHead;
158ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    while (strike) {
159ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        count2 += 1;
160ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        strike = strike->fNext;
161ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
162f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(count == count2);
163ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
164ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    count2 = 0;
165ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike = fTail;
166ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    while (strike) {
167ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        count2 += 1;
168ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        strike = strike->fPrev;
169ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
170f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(count == count2);
171ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
172ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
173ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
17403e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org#ifdef SK_DEVELOPER
17503e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.orgvoid GrFontCache::dump() const {
17603e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org    static int gDumpCount = 0;
17703e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org    for (int i = 0; i < kMaskFormatCount; ++i) {
17803e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org        if (NULL != fAtlasMgr[i]) {
17903e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org            GrTexture* texture = fAtlasMgr[i]->getTexture();
18003e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org            if (NULL != texture) {
18103e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org                SkString filename;
18203e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org                filename.printf("fontcache_%d%d.png", gDumpCount, i);
18303e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org                texture->savePixels(filename.c_str());
18403e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org            }
18503e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org        }
18603e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org    }
18703e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org    ++gDumpCount;
18803e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org}
18903e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org#endif
19003e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org
191ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com///////////////////////////////////////////////////////////////////////////////
192ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
193515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
194ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    static int gCounter;
195ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
196ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
197ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/*
198ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    The text strike is specific to a given font/style/matrix setup, which is
199ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    represented by the GrHostFontScaler object we are given in getGlyph().
200ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
201ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    We map a 32bit glyphID to a GrGlyph record, which in turn points to a
202ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    atlas and a position within that texture.
203ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
204ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
205ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
20698539c607b05f7e25406ae873bf1b24154a36a6freed@google.com                           GrMaskFormat format,
2077d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org                           GrAtlasMgr* atlasMgr) : fPool(64), fAtlas(atlasMgr) {
208ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey = key;
209ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey->ref();
210ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
211ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontCache = cache;     // no need to ref, it won't go away before we do
212ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fAtlasMgr = atlasMgr;   // no need to ref, it won't go away before we do
213ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
21498539c607b05f7e25406ae873bf1b24154a36a6freed@google.com    fMaskFormat = format;
21598539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
216515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
2173ef80cf14c3222f705c291123106991e52061678reed@google.com//    GrPrintf(" GrTextStrike %p %d\n", this, gCounter);
218ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    gCounter += 1;
219ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
220ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
221ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
22267ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org// these signatures are needed because they're used with
22367ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org// SkTDArray::visitAll() (see destructor & removeUnusedAtlases())
22467ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.orgstatic void free_glyph(GrGlyph*& glyph) { glyph->free(); }
22567ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org
22667ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.orgstatic void invalidate_glyph(GrGlyph*& glyph) {
2277d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org    if (glyph->fPlot && glyph->fPlot->drawToken().isIssued()) {
2287d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org        glyph->fPlot = NULL;
22967ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    }
23067ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org}
231ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
232ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::~GrTextStrike() {
233ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey->unref();
23467ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    fCache.getArray().visitAll(free_glyph);
235ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
236515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
237ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    gCounter -= 1;
2383ef80cf14c3222f705c291123106991e52061678reed@google.com//    GrPrintf("~GrTextStrike %p %d\n", this, gCounter);
239ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
240ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
241ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
242ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
243ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                     GrFontScaler* scaler) {
244fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org    SkIRect bounds;
245ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
246ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return NULL;
247ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
248ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
249ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrGlyph* glyph = fPool.alloc();
250ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    glyph->init(packed, bounds);
251ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.insert(packed, glyph);
252ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return glyph;
253ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
254ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
2557d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.orgbool GrTextStrike::removeUnusedPlots() {
25667ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    fCache.getArray().visitAll(invalidate_glyph);
2577d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org    return fAtlasMgr->removeUnusedPlots(&fAtlas);
25867ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org}
25967ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org
260a8916ffd90c04dc6cc1fb9ba94af2ff950284fadcommit-bot@chromium.orgbool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler,
261a8916ffd90c04dc6cc1fb9ba94af2ff950284fadcommit-bot@chromium.org                                 GrDrawTarget::DrawToken currentDrawToken) {
2620ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com#if 0   // testing hack to force us to flush our cache often
2630ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com    static int gCounter;
2640ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com    if ((++gCounter % 10) == 0) return false;
2650ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com#endif
2660ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com
267f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(glyph);
268f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(scaler);
269f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(fCache.contains(glyph));
2707d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org    if (glyph->fPlot) {
2717d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org        glyph->fPlot->setDrawToken(currentDrawToken);
272ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return true;
273ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
274ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
275a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkAutoRef ar(scaler);
27698539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
27798539c607b05f7e25406ae873bf1b24154a36a6freed@google.com    int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat);
27898539c607b05f7e25406ae873bf1b24154a36a6freed@google.com    size_t size = glyph->fBounds.area() * bytesPerPixel;
2793582bf9e3d94feac5d4cc64fdb646dd68a3e4b18bsalomon@google.com    SkAutoSMalloc<1024> storage(size);
280ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
28198539c607b05f7e25406ae873bf1b24154a36a6freed@google.com                                     glyph->height(),
28298539c607b05f7e25406ae873bf1b24154a36a6freed@google.com                                     glyph->width() * bytesPerPixel,
283ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                     storage.get())) {
284ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return false;
285ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
286ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
2877d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org    GrPlot* plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
2887d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org                                         glyph->height(), storage.get(),
2897d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org                                         &glyph->fAtlasLocation);
2907d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org    if (NULL == plot) {
291ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return false;
292ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
293ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
2947d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org    glyph->fPlot = plot;
2957d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org    plot->setDrawToken(currentDrawToken);
296ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return true;
297ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
298