11e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy/*
21e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * Copyright (C) 2010 The Android Open Source Project
31e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy *
41e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
51e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * you may not use this file except in compliance with the License.
61e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * You may obtain a copy of the License at
71e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy *
81e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
91e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy *
101e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * Unless required by applicable law or agreed to in writing, software
111e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
121e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * See the License for the specific language governing permissions and
141e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * limitations under the License.
151e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy */
161e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
175b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#ifndef ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H
185b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#define ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H
191e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
201e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy#include <GLES2/gl2.h>
211e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
221e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy#include <SkPaint.h>
231e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
24059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy#include <utils/LruCache.h>
25321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy#include <utils/String16.h>
2625dc3a7dbac2f90f5144035e9c8ed99c09cc3132Romain Guy
271e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy#include "FontRenderer.h"
281e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy#include "Texture.h"
291e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
301e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guynamespace android {
311e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guynamespace uirenderer {
321e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
338aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guyclass Caches;
348aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy
351e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guystruct ShadowText {
36059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    ShadowText(): len(0), radius(0.0f), textSize(0.0f), typeface(NULL),
37059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy            flags(0), italicStyle(0.0f), scaleX(0), text(NULL), positions(NULL) {
38c4d8eb6fb7c88c5c4da38b0b113c24cc4b78c0b7Romain Guy    }
391e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
4069fcbccf476ffc55af4da4dfedc72c3de8f91ce8Romain Guy    // len is the number of bytes in text
41059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    ShadowText(SkPaint* paint, float radius, uint32_t len, const char* srcText,
42416a847633680d94efb926837efdc18726d54918Raph Levien            const float* positions):
43059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy            len(len), radius(radius), positions(positions) {
44321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy        // TODO: Propagate this through the API, we should not cast here
45321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy        text = (const char16_t*) srcText;
461e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
47c4d8eb6fb7c88c5c4da38b0b113c24cc4b78c0b7Romain Guy        textSize = paint->getTextSize();
48c4d8eb6fb7c88c5c4da38b0b113c24cc4b78c0b7Romain Guy        typeface = paint->getTypeface();
49cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy
50cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        flags = 0;
51cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        if (paint->isFakeBoldText()) {
52cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy            flags |= Font::kFakeBold;
53cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        }
54cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy
55059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy        italicStyle = paint->getTextSkewX();
56059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy        scaleX = paint->getTextScaleX();
571e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
581e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
591e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    ~ShadowText() {
601e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
611e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
62059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    hash_t hash() const;
63059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
64059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    static int compare(const ShadowText& lhs, const ShadowText& rhs);
65059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
66059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    bool operator==(const ShadowText& other) const {
67059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy        return compare(*this, other) == 0;
68059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    }
69059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
70059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    bool operator!=(const ShadowText& other) const {
71059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy        return compare(*this, other) != 0;
72059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    }
73321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy
74321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy    void copyTextLocally() {
7569fcbccf476ffc55af4da4dfedc72c3de8f91ce8Romain Guy        uint32_t charCount = len / sizeof(char16_t);
7669fcbccf476ffc55af4da4dfedc72c3de8f91ce8Romain Guy        str.setTo((const char16_t*) text, charCount);
77321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy        text = str.string();
78416a847633680d94efb926837efdc18726d54918Raph Levien        if (positions != NULL) {
79416a847633680d94efb926837efdc18726d54918Raph Levien            positionsCopy.clear();
8069fcbccf476ffc55af4da4dfedc72c3de8f91ce8Romain Guy            positionsCopy.appendArray(positions, charCount * 2);
81416a847633680d94efb926837efdc18726d54918Raph Levien            positions = positionsCopy.array();
82416a847633680d94efb926837efdc18726d54918Raph Levien        }
83321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy    }
841e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
85059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    uint32_t len;
86059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    float radius;
87059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    float textSize;
88059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    SkTypeface* typeface;
89059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    uint32_t flags;
90059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    float italicStyle;
91059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    float scaleX;
92059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    const char16_t* text;
93059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    const float* positions;
94059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
95059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    // Not directly used to compute the cache key
96059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    String16 str;
97059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    Vector<float> positionsCopy;
98059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
991e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // struct ShadowText
1001e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
101059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy// Caching support
102059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
103059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int strictly_order_type(const ShadowText& lhs, const ShadowText& rhs) {
104059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    return ShadowText::compare(lhs, rhs) < 0;
105059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy}
106059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
107059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int compare_type(const ShadowText& lhs, const ShadowText& rhs) {
108059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    return ShadowText::compare(lhs, rhs);
109059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy}
110059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
111059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline hash_t hash_type(const ShadowText& entry) {
112059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    return entry.hash();
113059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy}
114059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
1151e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy/**
1161e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * Alpha texture used to represent a shadow.
1171e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy */
1181e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guystruct ShadowTexture: public Texture {
1198aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy    ShadowTexture(Caches& caches): Texture(caches) {
1201e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
1211e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1221e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    float left;
1231e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    float top;
1241e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // struct ShadowTexture
1251e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1261e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyclass TextDropShadowCache: public OnEntryRemoved<ShadowText, ShadowTexture*> {
1271e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guypublic:
128fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    TextDropShadowCache();
1291e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    TextDropShadowCache(uint32_t maxByteSize);
1301e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    ~TextDropShadowCache();
1311e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1321e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1331e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Used as a callback when an entry is removed from the cache.
1341e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Do not invoke directly.
1351e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1361e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    void operator()(ShadowText& text, ShadowTexture*& texture);
1371e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1381e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    ShadowTexture* get(SkPaint* paint, const char* text, uint32_t len,
139059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy            int numGlyphs, float radius, const float* positions);
1401e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1411e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1421e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Clears the cache. This causes all textures to be deleted.
1431e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1441e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    void clear();
1451e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1461e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    void setFontRenderer(FontRenderer& fontRenderer) {
1471e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        mRenderer = &fontRenderer;
1481e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
1491e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1501e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1511e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Sets the maximum size of the cache in bytes.
1521e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1531e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    void setMaxSize(uint32_t maxSize);
1541e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1551e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Returns the maximum size of the cache in bytes.
1561e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1571e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t getMaxSize();
1581e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1591e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Returns the current size of the cache in bytes.
1601e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1611e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t getSize();
1621e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1631e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyprivate:
16425dc3a7dbac2f90f5144035e9c8ed99c09cc3132Romain Guy    void init();
16525dc3a7dbac2f90f5144035e9c8ed99c09cc3132Romain Guy
166059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    LruCache<ShadowText, ShadowTexture*> mCache;
1671e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1681e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t mSize;
1691e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t mMaxSize;
1701e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    FontRenderer* mRenderer;
17125dc3a7dbac2f90f5144035e9c8ed99c09cc3132Romain Guy    bool mDebugEnabled;
1721e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // class TextDropShadowCache
1731e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1741e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // namespace uirenderer
1751e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // namespace android
1761e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1775b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#endif // ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H
178