GrTextStrike.cpp revision 53e1e4d88a06db62898a3bf75751c042729d7160
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
158065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org#include "SkDistanceFieldGen.h"
16d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
17fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com///////////////////////////////////////////////////////////////////////////////
18fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com
1953e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org#define GR_ATLAS_TEXTURE_WIDTH 1024
2053e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org#define GR_ATLAS_TEXTURE_HEIGHT 2048
2153e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org
2253e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org#define GR_PLOT_WIDTH  256
2353e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org#define GR_PLOT_HEIGHT 256
2453e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org
2553e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org#define GR_NUM_PLOTS_X   (GR_ATLAS_TEXTURE_WIDTH / GR_PLOT_WIDTH)
2653e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org#define GR_NUM_PLOTS_Y   (GR_ATLAS_TEXTURE_HEIGHT / GR_PLOT_HEIGHT)
2753e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org
2867ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#define FONT_CACHE_STATS 0
2967ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#if FONT_CACHE_STATS
3067ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.orgstatic int g_PurgeCount = 0;
3167ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#endif
3267ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org
33ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) {
34ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    gpu->ref();
35f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    for (int i = 0; i < kAtlasCount; ++i) {
363fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org        fAtlasMgr[i] = NULL;
373fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    }
38ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
39ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fHead = fTail = NULL;
40ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
41ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
42ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrFontCache::~GrFontCache() {
43ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.deleteAll();
44f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    for (int i = 0; i < kAtlasCount; ++i) {
453fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org        delete fAtlasMgr[i];
463fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    }
47ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fGpu->unref();
4867ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#if FONT_CACHE_STATS
4967ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org      GrPrintf("Num purges: %d\n", g_PurgeCount);
5067ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#endif
51ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
52ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
53952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.orgstatic GrPixelConfig mask_format_to_pixel_config(GrMaskFormat format) {
546e515d67d2365ecd05fb80762eeb76c55e81368cskia.committer@gmail.com    static const GrPixelConfig sPixelConfigs[] = {
556e515d67d2365ecd05fb80762eeb76c55e81368cskia.committer@gmail.com        kAlpha_8_GrPixelConfig,
566e515d67d2365ecd05fb80762eeb76c55e81368cskia.committer@gmail.com        kRGB_565_GrPixelConfig,
57f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org        kSkia8888_GrPixelConfig,
58f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org        kSkia8888_GrPixelConfig
59f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    };
60f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sPixelConfigs) == kMaskFormatCount, array_size_mismatch);
61f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org
62f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    return sPixelConfigs[format];
63f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org}
64f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org
65f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.orgstatic int mask_format_to_atlas_index(GrMaskFormat format) {
666e515d67d2365ecd05fb80762eeb76c55e81368cskia.committer@gmail.com    static const int sAtlasIndices[] = {
676e515d67d2365ecd05fb80762eeb76c55e81368cskia.committer@gmail.com        GrFontCache::kA8_AtlasType,
686e515d67d2365ecd05fb80762eeb76c55e81368cskia.committer@gmail.com        GrFontCache::k565_AtlasType,
696e515d67d2365ecd05fb80762eeb76c55e81368cskia.committer@gmail.com        GrFontCache::k8888_AtlasType,
706e515d67d2365ecd05fb80762eeb76c55e81368cskia.committer@gmail.com        GrFontCache::k8888_AtlasType
71f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    };
72f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, array_size_mismatch);
73f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org
74f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    SkASSERT(sAtlasIndices[format] < GrFontCache::kAtlasCount);
75f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    return sAtlasIndices[format];
76952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org}
77952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org
78ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler,
79ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                          const Key& key) {
803fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    GrMaskFormat format = scaler->getMaskFormat();
81952944144758dd3f9a8a010ec1d99cb4bd035ae4commit-bot@chromium.org    GrPixelConfig config = mask_format_to_pixel_config(format);
82f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    int atlasIndex = mask_format_to_atlas_index(format);
83f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    if (NULL == fAtlasMgr[atlasIndex]) {
8453e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org        SkISize textureSize = SkISize::Make(GR_ATLAS_TEXTURE_WIDTH,
8553e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org                                            GR_ATLAS_TEXTURE_HEIGHT);
8653e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org        fAtlasMgr[atlasIndex] = SkNEW_ARGS(GrAtlasMgr, (fGpu, config,
8753e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org                                                        textureSize,
8853e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org                                                        GR_NUM_PLOTS_X,
8953e1e4d88a06db62898a3bf75751c042729d7160commit-bot@chromium.org                                                        GR_NUM_PLOTS_Y));
90ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
91c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    GrTextStrike* strike = SkNEW_ARGS(GrTextStrike,
92f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org                                      (this, scaler->getKey(), format, fAtlasMgr[atlasIndex]));
93ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.insert(key, strike);
94ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
95ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (fHead) {
96ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fHead->fPrev = strike;
97ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else {
98f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(NULL == fTail);
99ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        fTail = strike;
100ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
101ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike->fPrev = NULL;
102ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike->fNext = fHead;
103ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fHead = strike;
104ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
105ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return strike;
106ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
107ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
108ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::freeAll() {
109ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.deleteAll();
110f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    for (int i = 0; i < kAtlasCount; ++i) {
1113fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org        delete fAtlasMgr[i];
1123fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org        fAtlasMgr[i] = NULL;
1133fddf0eed6dc2873bcc8e584f435c6cd34964518commit-bot@chromium.org    }
1148fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fHead = NULL;
1158fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fTail = NULL;
116ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
117ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
118b2e9fa529862bd1f7b983a17b3c72acfb3d0367dcommit-bot@chromium.orgvoid GrFontCache::purgeStrike(GrTextStrike* strike) {
119b2e9fa529862bd1f7b983a17b3c72acfb3d0367dcommit-bot@chromium.org    const GrFontCache::Key key(strike->fFontScalerKey);
120b2e9fa529862bd1f7b983a17b3c72acfb3d0367dcommit-bot@chromium.org    fCache.remove(key, strike);
121b2e9fa529862bd1f7b983a17b3c72acfb3d0367dcommit-bot@chromium.org    this->detachStrikeFromList(strike);
122b2e9fa529862bd1f7b983a17b3c72acfb3d0367dcommit-bot@chromium.org    delete strike;
123b2e9fa529862bd1f7b983a17b3c72acfb3d0367dcommit-bot@chromium.org}
124b2e9fa529862bd1f7b983a17b3c72acfb3d0367dcommit-bot@chromium.org
125c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.orgbool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike) {
126bbe55fdf6608b8aec2e5d3945da6b1872b3a380fjvanverth@google.com    SkASSERT(NULL != preserveStrike);
127c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org
128c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org    GrAtlasMgr* atlasMgr = preserveStrike->fAtlasMgr;
129c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org    GrPlot* plot = atlasMgr->getUnusedPlot();
130c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org    if (NULL == plot) {
131c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org        return false;
132c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org    }
133c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org    plot->resetRects();
134c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org
135c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org    GrTextStrike* strike = fHead;
136bbe55fdf6608b8aec2e5d3945da6b1872b3a380fjvanverth@google.com    GrMaskFormat maskFormat = preserveStrike->fMaskFormat;
13767ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    while (strike) {
138c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org        if (maskFormat != strike->fMaskFormat) {
139c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org            strike = strike->fNext;
14067ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org            continue;
14167ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org        }
142c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org
14367ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org        GrTextStrike* strikeToPurge = strike;
144c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org        strike = strikeToPurge->fNext;
145c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org        strikeToPurge->removePlot(plot);
146c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org
147c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org        // clear out any empty strikes (except this one)
148c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org        if (strikeToPurge != preserveStrike && strikeToPurge->fAtlas.isEmpty()) {
149b2e9fa529862bd1f7b983a17b3c72acfb3d0367dcommit-bot@chromium.org            this->purgeStrike(strikeToPurge);
15067ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org        }
15167ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    }
152c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org
15367ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#if FONT_CACHE_STATS
15467ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    ++g_PurgeCount;
15567ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org#endif
15667ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org
157c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org    return true;
158ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
159ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
160515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
161ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comvoid GrFontCache::validate() const {
162ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int count = fCache.count();
163ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (0 == count) {
164f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(!fHead);
165f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(!fTail);
166ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else if (1 == count) {
167f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(fHead == fTail);
168ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    } else {
169f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(fHead != fTail);
170ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
171ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
172ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    int count2 = 0;
173ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    const GrTextStrike* strike = fHead;
174ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    while (strike) {
175ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        count2 += 1;
176ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        strike = strike->fNext;
177ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
178f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(count == count2);
179ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
180ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    count2 = 0;
181ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    strike = fTail;
182ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    while (strike) {
183ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        count2 += 1;
184ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        strike = strike->fPrev;
185ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
186f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(count == count2);
187ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
188ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
189ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
19003e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org#ifdef SK_DEVELOPER
19103e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.orgvoid GrFontCache::dump() const {
19203e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org    static int gDumpCount = 0;
193f8cb184095946ebf8f183d253e27bd544a19f23ccommit-bot@chromium.org    for (int i = 0; i < kAtlasCount; ++i) {
19403e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org        if (NULL != fAtlasMgr[i]) {
19503e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org            GrTexture* texture = fAtlasMgr[i]->getTexture();
19603e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org            if (NULL != texture) {
19703e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org                SkString filename;
1984362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org#ifdef SK_BUILD_FOR_ANDROID
1994362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org                filename.printf("/sdcard/fontcache_%d%d.png", gDumpCount, i);
2004362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org#else
20103e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org                filename.printf("fontcache_%d%d.png", gDumpCount, i);
2024362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org#endif
20303e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org                texture->savePixels(filename.c_str());
20403e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org            }
20503e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org        }
20603e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org    }
20703e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org    ++gDumpCount;
20803e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org}
20903e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org#endif
21003e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org
211ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com///////////////////////////////////////////////////////////////////////////////
212ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
213515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
214ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    static int gCounter;
215ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
216ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
2178065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org// this acts as the max magnitude for the distance field,
2188065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org// as well as the pad we need around the glyph
2198065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org#define DISTANCE_FIELD_RANGE   4
220d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
221ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com/*
222ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    The text strike is specific to a given font/style/matrix setup, which is
223ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    represented by the GrHostFontScaler object we are given in getGlyph().
224ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
225ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    We map a 32bit glyphID to a GrGlyph record, which in turn points to a
226ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    atlas and a position within that texture.
227ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */
228ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
229ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
23098539c607b05f7e25406ae873bf1b24154a36a6freed@google.com                           GrMaskFormat format,
231c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org                           GrAtlasMgr* atlasMgr) : fPool(64) {
232ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey = key;
233ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey->ref();
234ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
235ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontCache = cache;     // no need to ref, it won't go away before we do
236ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fAtlasMgr = atlasMgr;   // no need to ref, it won't go away before we do
237ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
23898539c607b05f7e25406ae873bf1b24154a36a6freed@google.com    fMaskFormat = format;
23998539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
240515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
2413ef80cf14c3222f705c291123106991e52061678reed@google.com//    GrPrintf(" GrTextStrike %p %d\n", this, gCounter);
242ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    gCounter += 1;
243ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
244ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
245ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
246c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org// this signature is needed because it's used with
247c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org// SkTDArray::visitAll() (see destructor)
24867ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.orgstatic void free_glyph(GrGlyph*& glyph) { glyph->free(); }
24967ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org
250ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrTextStrike::~GrTextStrike() {
251ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fFontScalerKey->unref();
25267ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org    fCache.getArray().visitAll(free_glyph);
253ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
254515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
255ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    gCounter -= 1;
2563ef80cf14c3222f705c291123106991e52061678reed@google.com//    GrPrintf("~GrTextStrike %p %d\n", this, gCounter);
257ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif
258ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
259ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
260ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comGrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
261ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com                                     GrFontScaler* scaler) {
262fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org    SkIRect bounds;
263ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
264ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return NULL;
265ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
266ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
267ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    GrGlyph* glyph = fPool.alloc();
268d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    // expand bounds to hold full distance field data
2694362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org    // + room for bilerp
2704362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org    int pad = DISTANCE_FIELD_RANGE+1;
271d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    if (fUseDistanceField) {
2724362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        bounds.fLeft   -= pad;
2734362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        bounds.fRight  += pad;
2744362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        bounds.fTop    -= pad;
2754362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        bounds.fBottom += pad;
276d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    }
277ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    glyph->init(packed, bounds);
278ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    fCache.insert(packed, glyph);
279ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return glyph;
280ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
281ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
282c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.orgvoid GrTextStrike::removePlot(const GrPlot* plot) {
283c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org    SkTDArray<GrGlyph*>& glyphArray = fCache.getArray();
284c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org    for (int i = 0; i < glyphArray.count(); ++i) {
285c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org        if (plot == glyphArray[i]->fPlot) {
286c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org            glyphArray[i]->fPlot = NULL;
287c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org        }
288c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org    }
289c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org
290c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.org    fAtlasMgr->removePlot(&fAtlas, plot);
29167ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org}
29267ed64e9aa70f5a95a2d309f9b73dc0009f3ed8ccommit-bot@chromium.org
293d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
294c9b2c885be8d2bb39f1d75cc316278fa8d0fa9f0commit-bot@chromium.orgbool GrTextStrike::addGlyphToAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
2950ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com#if 0   // testing hack to force us to flush our cache often
2960ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com    static int gCounter;
2970ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com    if ((++gCounter % 10) == 0) return false;
2980ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com#endif
2990ebe81a2b7a2dfd3b978520c2594e448bdbadca0reed@google.com
300f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(glyph);
301f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(scaler);
302f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(fCache.contains(glyph));
30349e80830e9c633dcb8e7596bda17ea004ae48bd4commit-bot@chromium.org    SkASSERT(NULL == glyph->fPlot);
304ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
305a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkAutoRef ar(scaler);
30698539c607b05f7e25406ae873bf1b24154a36a6freed@google.com
30798539c607b05f7e25406ae873bf1b24154a36a6freed@google.com    int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat);
308d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
309d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    GrPlot* plot;
310d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    if (fUseDistanceField) {
311d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        // we've already expanded the glyph dimensions to match the final size
312d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        // but must shrink back down to get the packed glyph data
313d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        int dfWidth = glyph->width();
314d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        int dfHeight = glyph->height();
3154362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        int pad = DISTANCE_FIELD_RANGE+1;
3164362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        int width = dfWidth - 2*pad;
3174362a38563a958083aca2b456aaaa9f756f6f4e1commit-bot@chromium.org        int height = dfHeight - 2*pad;
3188065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org        int stride = width*bytesPerPixel;
319d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
320d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        size_t size = width * height * bytesPerPixel;
321d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkAutoSMalloc<1024> storage(size);
322d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        if (!scaler->getPackedGlyphImage(glyph->fPackedID, width, height, stride, storage.get())) {
323d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com            return false;
324d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        }
325d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
326d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        // alloc storage for distance field glyph
327d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        size_t dfSize = dfWidth * dfHeight * bytesPerPixel;
328d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkAutoSMalloc<1024> dfStorage(dfSize);
3290b70816eb157ed6492623eea1e55005ef40c908cskia.committer@gmail.com
3308065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org        if (1 == bytesPerPixel) {
3318065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org            (void) SkGenerateDistanceFieldFromImage((unsigned char*)dfStorage.get(),
3328065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org                                                    (unsigned char*)storage.get(),
3338065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org                                                    width, height, DISTANCE_FIELD_RANGE);
3348065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org        } else {
3358065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org            // TODO: Fix color emoji
3368065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org            // for now, copy glyph into distance field storage
3378065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org            // this is not correct, but it won't crash
3388065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org            sk_bzero(dfStorage.get(), dfSize);
3398065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org            unsigned char* ptr = (unsigned char*) storage.get();
3408065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org            unsigned char* dfPtr = (unsigned char*) dfStorage.get();
3418065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org            size_t dfStride = dfWidth*bytesPerPixel;
3428065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org            dfPtr += DISTANCE_FIELD_RANGE*dfStride;
3438065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org            dfPtr += DISTANCE_FIELD_RANGE*bytesPerPixel;
3448065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org
3458065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org            for (int i = 0; i < height; ++i) {
3468065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org                memcpy(dfPtr, ptr, stride);
3478065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org
3488065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org                dfPtr += dfStride;
3498065ec50f1937c1562810bfe2b216abfb98362b3commit-bot@chromium.org                ptr += stride;
350d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com            }
351d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        }
35211a253b686d2f6e9def2de8a4507591fcadfe987skia.committer@gmail.com
353d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        // copy to atlas
35411a253b686d2f6e9def2de8a4507591fcadfe987skia.committer@gmail.com        plot = fAtlasMgr->addToAtlas(&fAtlas, dfWidth, dfHeight, dfStorage.get(),
355d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                     &glyph->fAtlasLocation);
356d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
357d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com    } else {
358d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        size_t size = glyph->fBounds.area() * bytesPerPixel;
359d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        SkAutoSMalloc<1024> storage(size);
360d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
361d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                         glyph->height(),
362d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                         glyph->width() * bytesPerPixel,
363d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                         storage.get())) {
364d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com            return false;
365d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com        }
366d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com
36711a253b686d2f6e9def2de8a4507591fcadfe987skia.committer@gmail.com        plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
36811a253b686d2f6e9def2de8a4507591fcadfe987skia.committer@gmail.com                                     glyph->height(), storage.get(),
369d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com                                     &glyph->fAtlasLocation);
370ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
371ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
3727d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org    if (NULL == plot) {
373ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com        return false;
374ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    }
375ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com
3767d330eb19cd3c9278abce68ca0e3efabf2ec8f87commit-bot@chromium.org    glyph->fPlot = plot;
377ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com    return true;
378ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}
379