TextLayoutCache.h revision aabe537f1ed3b64f755af9fc62022d6074eec169
1d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio/*
2d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio * Copyright (C) 2011 The Android Open Source Project
3d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio *
4d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio * Licensed under the Apache License, Version 2.0 (the "License");
5d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio * you may not use this file except in compliance with the License.
6d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio * You may obtain a copy of the License at
7d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio *
8d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio *      http://www.apache.org/licenses/LICENSE-2.0
9d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio *
10d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio * Unless required by applicable law or agreed to in writing, software
11d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio * distributed under the License is distributed on an "AS IS" BASIS,
12d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio * See the License for the specific language governing permissions and
14d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio * limitations under the License.
15d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio */
16d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
17d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#ifndef ANDROID_TEXT_LAYOUT_CACHE_H
18d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#define ANDROID_TEXT_LAYOUT_CACHE_H
19d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
20d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#include "RtlProperties.h"
21d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
22eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#include <stddef.h>
23d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#include <utils/threads.h>
24d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#include <utils/String16.h>
25eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#include <utils/GenerationCache.h>
26eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#include <utils/Compare.h>
27d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
28eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#include <SkPaint.h>
29eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#include <SkTemplates.h>
30eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#include <SkUtils.h>
31eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#include <SkScalerContext.h>
32eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#include <SkAutoKern.h>
33d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
34eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#include <unicode/ubidi.h>
35eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#include <unicode/ushape.h>
369f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#include "HarfbuzzSkia.h"
379f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#include "harfbuzz-shaper.h"
38d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
39d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#include <android_runtime/AndroidRuntime.h>
40d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
41d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#define UNICODE_NOT_A_CHAR              0xffff
42d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#define UNICODE_ZWSP                    0x200b
43d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#define UNICODE_FIRST_LOW_SURROGATE     0xdc00
44d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#define UNICODE_FIRST_HIGH_SURROGATE    0xd800
45d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#define UNICODE_FIRST_PRIVATE_USE       0xe000
46d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#define UNICODE_FIRST_RTL_CHAR          0x0590
47d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
48d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio// Temporary buffer size
49d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#define CHAR_BUFFER_SIZE 80
50d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
51d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio// Converts a number of mega-bytes into bytes
52d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#define MB(s) s * 1024 * 1024
53d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
54d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio// Define the default cache size in Mb
55d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#define DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB 0.125f
56d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
57d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio// Define the interval in number of cache hits between two statistics dump
58d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#define DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL 100
59d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
60d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglionamespace android {
61d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
62d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio/**
63d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio * TextLayoutCacheKey is the Cache key
64d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio */
65d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglioclass TextLayoutCacheKey {
66d313c665e618af3194f504064bcd284fe5368682Fabrice Di Megliopublic:
67d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    TextLayoutCacheKey() : text(NULL), start(0), count(0), contextCount(0),
68aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio            dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0),
69aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio            hinting(SkPaint::kNo_Hinting)  {
70d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
71d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
72d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    TextLayoutCacheKey(const SkPaint* paint,
73d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            const UChar* text, size_t start, size_t count,
74d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            size_t contextCount, int dirFlags) :
75d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                text(text), start(start), count(count), contextCount(contextCount),
76d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                dirFlags(dirFlags) {
77d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        typeface = paint->getTypeface();
78aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio        textSize = paint->getTextSize();
79d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        textSkewX = paint->getTextSkewX();
80aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio        textScaleX = paint->getTextScaleX();
81aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio        flags = paint->getFlags();
82aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio        hinting = paint->getHinting();
83d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
84d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
85d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    bool operator<(const TextLayoutCacheKey& rhs) const {
86d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        LTE_INT(count) {
87d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            LTE_INT(contextCount) {
88d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                LTE_INT(start) {
89aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio                    LTE_INT(typeface) {
90aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio                        LTE_FLOAT(textSize) {
91aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio                            LTE_FLOAT(textSkewX) {
92aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio                                LTE_FLOAT(textScaleX) {
93aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio                                    LTE_INT(flags) {
94aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio                                        LTE_INT(hinting) {
95aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio                                            LTE_INT(dirFlags) {
96aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio                                                return strncmp16(text, rhs.text, contextCount) < 0;
97aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio                                            }
98aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio                                        }
99d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                                    }
100d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                                }
101d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                            }
102d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                        }
103d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                    }
104d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                }
105d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            }
106d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        }
107d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        return false;
108d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
109d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
110d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    // We need to copy the text when we insert the key into the cache itself.
111d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    // We don't need to copy the text when we are only comparing keys.
112d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    void internalTextCopy() {
113d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        textCopy.setTo(text, contextCount);
114d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        text = textCopy.string();
115d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
116d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
117d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    /**
118d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Get the size of the Cache key.
119d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     */
120d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    size_t getSize() {
121d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        return sizeof(TextLayoutCacheKey) + sizeof(UChar) * contextCount;
122d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
123d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
124d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglioprivate:
125d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    const UChar* text;
126d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    String16 textCopy;
127d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    size_t start;
128d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    size_t count;
129d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    size_t contextCount;
130d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    int dirFlags;
131d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    SkTypeface* typeface;
132aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio    SkScalar textSize;
133aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio    SkScalar textSkewX;
134aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio    SkScalar textScaleX;
135aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio    uint32_t flags;
136aabe537f1ed3b64f755af9fc62022d6074eec169Fabrice Di Meglio    SkPaint::Hinting hinting;
137d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio}; // TextLayoutCacheKey
138d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
139d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio/*
140d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio * RunAdvanceDescription is the Cache entry
141d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio */
142d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglioclass RunAdvanceDescription {
143d313c665e618af3194f504064bcd284fe5368682Fabrice Di Megliopublic:
144d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    RunAdvanceDescription() {
145d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        advances = NULL;
146d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        totalAdvance = 0;
147d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
148d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
149d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    ~RunAdvanceDescription() {
150d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        delete[] advances;
151d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
152d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
153d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    void setElapsedTime(uint32_t time) {
154d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        elapsedTime = time;
155d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
156d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
157d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    uint32_t getElapsedTime() {
158d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        return elapsedTime;
159d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
160d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
161d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    void computeAdvances(SkPaint* paint, const UChar* chars, size_t start, size_t count,
162d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            size_t contextCount, int dirFlags) {
163d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        advances = new float[count];
164d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        this->count = count;
165d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
1669f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#if RTL_USE_HARFBUZZ
1679f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        computeAdvancesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags,
168d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                advances, &totalAdvance);
1699f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#else
1709f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        computeAdvancesWithICU(paint, chars, start, count, contextCount, dirFlags,
1719f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio                advances, &totalAdvance);
1729f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#endif
1739f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#if DEBUG_ADVANCES
1749f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        LOGD("Advances - count=%d - countextCount=%d - totalAdvance=%f - "
1759f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio                "adv[0]=%f adv[1]=%f adv[2]=%f adv[3]=%f", count, contextCount, totalAdvance,
1769f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio                advances[0], advances[1], advances[2], advances[3]);
1779f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#endif
178d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
179d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
180d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    void copyResult(jfloat* outAdvances, jfloat* outTotalAdvance) {
181d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        memcpy(outAdvances, advances, count * sizeof(jfloat));
182d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        *outTotalAdvance = totalAdvance;
183d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
184d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
185d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    /**
186d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Get the size of the Cache entry
187d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     */
188d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    size_t getSize() {
189d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        return sizeof(RunAdvanceDescription) + sizeof(jfloat) * count;
190d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
191d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
1929f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    static void setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData,
1939f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount,
1949f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            int dirFlags) {
1959f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        bool isRTL = dirFlags & 0x1;
1969f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
1979f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        font->klass = &harfbuzzSkiaClass;
1989f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        font->userData = 0;
1999f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // The values which harfbuzzSkiaClass returns are already scaled to
2009f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // pixel units, so we just set all these to one to disable further
2019f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // scaling.
2029f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        font->x_ppem = 1;
2039f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        font->y_ppem = 1;
2049f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        font->x_scale = 1;
2059f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        font->y_scale = 1;
2069f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2079f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        memset(shaperItem, 0, sizeof(*shaperItem));
2089f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->font = font;
2099f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->face = HB_NewFace(shaperItem->font, harfbuzzSkiaGetTable);
2109f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
211eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        shaperItem->kerning_applied = false;
212eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio
2139f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // We cannot know, ahead of time, how many glyphs a given script run
2149f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // will produce. We take a guess that script runs will not produce more
2159f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // than twice as many glyphs as there are code points plus a bit of
2169f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // padding and fallback if we find that we are wrong.
2179f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        createGlyphArrays(shaperItem, (contextCount + 2) * 2);
2189f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2199f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // Free memory for clusters if needed and recreate the clusters array
2209f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        if (shaperItem->log_clusters) {
2219f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            delete shaperItem->log_clusters;
2229f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        }
2239f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->log_clusters = new unsigned short[contextCount];
2249f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2259f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->item.pos = start;
2269f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->item.length = count;
2279f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->item.bidiLevel = isRTL;
2289f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->item.script = isRTL ? HB_Script_Arabic : HB_Script_Common;
2299f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2309f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->string = chars;
2319f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->stringLength = contextCount;
2329f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2339f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        fontData->typeFace = paint->getTypeface();
234eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        fontData->textSize = paint->getTextSize();
235eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        fontData->textSkewX = paint->getTextSkewX();
236eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        fontData->textScaleX = paint->getTextScaleX();
237eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        fontData->flags = paint->getFlags();
238eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        fontData->hinting = paint->getHinting();
2399f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2409f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->font->userData = fontData;
2419f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    }
2429f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2439f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    static void shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData,
2449f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount,
2459f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            int dirFlags) {
2469f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // Setup Harfbuzz Shaper
2479f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        setupShaperItem(shaperItem, font, fontData, paint, chars, start, count,
2489f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio                contextCount, dirFlags);
2499f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2509f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // Shape
2519f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        resetGlyphArrays(shaperItem);
2529f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        while (!HB_ShapeItem(shaperItem)) {
2539f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            // We overflowed our arrays. Resize and retry.
2549f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            // HB_ShapeItem fills in shaperItem.num_glyphs with the needed size.
2559f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            deleteGlyphArrays(shaperItem);
2569f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            createGlyphArrays(shaperItem, shaperItem->num_glyphs << 1);
2579f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            resetGlyphArrays(shaperItem);
2589f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        }
2599f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    }
2609f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
261eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio#define SkAutoKern_AdjustF(prev, next) (((next) - (prev) + 32) >> 6 << 16)
262eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio
263eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio    static int adjust(int prev, int next) {
264eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        int delta = next - prev;
265eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        if (delta >= 32) {
266eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio            return -1;
267eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        }
268eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        else if (delta < -32) {
269eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio            return +1;
270eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        }
271eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        else {
272eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio            return 0;
273eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        }
274eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio    }
275eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio
2769f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    static void computeAdvancesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start,
2779f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            size_t count, size_t contextCount, int dirFlags,
2789f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            jfloat* outAdvances, jfloat* outTotalAdvance) {
2799f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2809f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        bool isRTL = dirFlags & 0x1;
2819f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2829f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        HB_ShaperItem shaperItem;
2839f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        HB_FontRec font;
2849f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        FontData fontData;
2859f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shapeWithHarfbuzz(&shaperItem, &font, &fontData, paint, chars, start, count,
2869f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio                contextCount, dirFlags);
2879f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2889f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#if DEBUG_ADVANCES
289eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        LOGD("HARFBUZZ -- num_glypth=%d - kerning_applied=%d", shaperItem.num_glyphs, shaperItem.kerning_applied);
290eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        LOGD("         -- string= '%s'", String8(chars, contextCount).string());
291eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio        LOGD("         -- isDevKernText=%d", paint->isDevKernText());
2929f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#endif
2939f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2949f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        jfloat totalAdvance = 0;
295eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio
2969f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        for (size_t i = 0; i < count; i++) {
297eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio            totalAdvance += outAdvances[i] = HBFixedToFloat(shaperItem.advances[i]);
2989f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
2999f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#if DEBUG_ADVANCES
3009f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            LOGD("hb-adv = %d - rebased = %f - total = %f", shaperItem.advances[i], outAdvances[i],
3019f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio                    totalAdvance);
3029f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#endif
3039f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        }
3049f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
3059f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        deleteGlyphArrays(&shaperItem);
3069f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        HB_FreeFace(shaperItem.face);
3079f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
3089f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        *outTotalAdvance = totalAdvance;
3099f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    }
3109f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
3119f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    static void computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start,
3129f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            size_t count, size_t contextCount, int dirFlags,
3139f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio            jfloat* outAdvances, jfloat* outTotalAdvance) {
3149f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
315d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        SkAutoSTMalloc<CHAR_BUFFER_SIZE, jchar> tempBuffer(contextCount);
316d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        jchar* buffer = tempBuffer.get();
317d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
318d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        SkScalar* scalarArray = (SkScalar*)outAdvances;
319d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
320d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        // this is where we'd call harfbuzz
321d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        // for now we just use ushape.c
322d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        size_t widths;
323d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        const jchar* text;
324d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        if (dirFlags & 0x1) { // rtl, call arabic shaping in case
325d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            UErrorCode status = U_ZERO_ERROR;
326d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            // Use fixed length since we need to keep start and count valid
327d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            u_shapeArabic(chars, contextCount, buffer, contextCount,
328d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                    U_SHAPE_LENGTH_FIXED_SPACES_NEAR |
329d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                    U_SHAPE_TEXT_DIRECTION_LOGICAL | U_SHAPE_LETTERS_SHAPE |
330d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                    U_SHAPE_X_LAMALEF_SUB_ALTERNATE, &status);
331d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            // we shouldn't fail unless there's an out of memory condition,
332d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            // in which case we're hosed anyway
333d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            for (int i = start, e = i + count; i < e; ++i) {
334d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                if (buffer[i] == UNICODE_NOT_A_CHAR) {
335d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                    buffer[i] = UNICODE_ZWSP; // zero-width-space for skia
336d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                }
337d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            }
338d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            text = buffer + start;
339d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            widths = paint->getTextWidths(text, count << 1, scalarArray);
340d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        } else {
341d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            text = chars + start;
342d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            widths = paint->getTextWidths(text, count << 1, scalarArray);
343d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        }
344d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
345d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        jfloat totalAdvance = 0;
346d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        if (widths < count) {
3479f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#if DEBUG_ADVANCES
3489f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        LOGD("ICU -- count=%d", widths);
3499f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#endif
350d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            // Skia operates on code points, not code units, so surrogate pairs return only
351d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            // one value. Expand the result so we have one value per UTF-16 code unit.
352d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
353d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            // Note, skia's getTextWidth gets confused if it encounters a surrogate pair,
354d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            // leaving the remaining widths zero.  Not nice.
355d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            for (size_t i = 0, p = 0; i < widths; ++i) {
356d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                totalAdvance += outAdvances[p++] = SkScalarToFloat(scalarArray[i]);
357d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                if (p < count &&
358d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                        text[p] >= UNICODE_FIRST_LOW_SURROGATE &&
359d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                        text[p] < UNICODE_FIRST_PRIVATE_USE &&
360d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                        text[p-1] >= UNICODE_FIRST_HIGH_SURROGATE &&
361d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                        text[p-1] < UNICODE_FIRST_LOW_SURROGATE) {
362d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                    outAdvances[p++] = 0;
363d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                }
3649f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#if DEBUG_ADVANCES
3659f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio                LOGD("icu-adv = %f - total = %f", outAdvances[i], totalAdvance);
3669f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#endif
367d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            }
368d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        } else {
3699f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#if DEBUG_ADVANCES
3709f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        LOGD("ICU -- count=%d", count);
3719f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#endif
372d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            for (size_t i = 0; i < count; i++) {
373d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio                totalAdvance += outAdvances[i] = SkScalarToFloat(scalarArray[i]);
3749f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#if DEBUG_ADVANCES
3759f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio                LOGD("icu-adv = %f - total = %f", outAdvances[i], totalAdvance);
3769f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio#endif
377d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            }
378d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        }
379d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        *outTotalAdvance = totalAdvance;
380d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
381d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
382d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglioprivate:
383d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    jfloat* advances;
384d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    jfloat totalAdvance;
385d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    size_t count;
386d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
387d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    uint32_t elapsedTime;
3889f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
3899f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    static void deleteGlyphArrays(HB_ShaperItem* shaperItem) {
3909f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        delete[] shaperItem->glyphs;
3919f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        delete[] shaperItem->attributes;
3929f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        delete[] shaperItem->advances;
3939f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        delete[] shaperItem->offsets;
3949f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    }
3959f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
3969f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    static void createGlyphArrays(HB_ShaperItem* shaperItem, int size) {
3979f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->glyphs = new HB_Glyph[size];
3989f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->attributes = new HB_GlyphAttributes[size];
3999f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->advances = new HB_Fixed[size];
4009f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->offsets = new HB_FixedPoint[size];
4019f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        shaperItem->num_glyphs = size;
4029f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    }
4039f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
4049f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    static void resetGlyphArrays(HB_ShaperItem* shaperItem) {
4059f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        int size = shaperItem->num_glyphs;
4069f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // All the types here don't have pointers. It is safe to reset to
4079f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        // zero unless Harfbuzz breaks the compatibility in the future.
4089f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        memset(shaperItem->glyphs, 0, size * sizeof(shaperItem->glyphs[0]));
4099f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        memset(shaperItem->attributes, 0, size * sizeof(shaperItem->attributes[0]));
4109f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        memset(shaperItem->advances, 0, size * sizeof(shaperItem->advances[0]));
4119f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio        memset(shaperItem->offsets, 0, size * sizeof(shaperItem->offsets[0]));
4129f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio    }
4139f82b580d744ce4baf057b061994394dcf239eedFabrice Di Meglio
414d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio}; // RunAdvanceDescription
415d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
416d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
417d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglioclass TextLayoutCache: public OnEntryRemoved<TextLayoutCacheKey, RunAdvanceDescription*>
418d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio{
419d313c665e618af3194f504064bcd284fe5368682Fabrice Di Megliopublic:
420d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    TextLayoutCache();
421d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    TextLayoutCache(uint32_t maxByteSize);
422d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
423d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    virtual ~TextLayoutCache();
424d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
425d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    bool isInitialized() {
426d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio        return mInitialized;
427d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    }
428d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
429d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    /**
430d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Used as a callback when an entry is removed from the cache.
431d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Do not invoke directly.
432d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     */
433d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    void operator()(TextLayoutCacheKey& text, RunAdvanceDescription*& desc);
434d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
435d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    /**
436d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Get cache entries
437d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     */
438d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    void getRunAdvances(SkPaint* paint, const jchar* text,
439d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            jint start, jint count, jint contextCount, jint dirFlags,
440d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio            jfloat* outAdvances, jfloat* outTotalAdvance);
441d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
442d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    /**
443d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Clear the cache
444d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     */
445d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    void clear();
446d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
447d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    /**
448d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Sets the maximum size of the cache in bytes.
449d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     */
450d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    void setMaxSize(uint32_t maxSize);
451d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
452d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    /**
453d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Returns the maximum size of the cache in bytes.
454d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     */
455d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    uint32_t getMaxSize();
456d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
457d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    /**
458d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Returns the current size of the cache in bytes.
459d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     */
460d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    uint32_t getSize();
461d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
462d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglioprivate:
463d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    Mutex mLock;
464d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    bool mInitialized;
465d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
466d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    GenerationCache<TextLayoutCacheKey, RunAdvanceDescription*> mCache;
467d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
468d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    uint32_t mSize;
469d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    uint32_t mMaxSize;
470d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
471d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    uint32_t mCacheHitCount;
472d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    uint64_t mNanosecondsSaved;
473d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
474d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    uint64_t mCacheStartTime;
475d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
476d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    RtlDebugLevel mDebugLevel;
477d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    bool mDebugEnabled;
478d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
479d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    /*
480d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Class initialization
481d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     */
482d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    void init();
483d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
484d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    /**
485d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Remove oldest entries until we are having enough space
486d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     */
487d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    void removeOldests();
488d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
489d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    /**
490d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     * Dump Cache statistics
491d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio     */
492d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio    void dumpCacheStats();
493d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio}; // TextLayoutCache
494d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
495d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio} // namespace android
496d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio#endif /* ANDROID_TEXT_LAYOUT_CACHE_H */
497d313c665e618af3194f504064bcd284fe5368682Fabrice Di Meglio
498