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
24321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy#include <utils/String16.h>
2525dc3a7dbac2f90f5144035e9c8ed99c09cc3132Romain Guy
2625dc3a7dbac2f90f5144035e9c8ed99c09cc3132Romain Guy#include "utils/Compare.h"
2721b028a44f3e0bd9b0f0432b8b92c45f661d22a4Romain Guy#include "utils/GenerationCache.h"
281e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy#include "FontRenderer.h"
291e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy#include "Texture.h"
301e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
311e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guynamespace android {
321e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guynamespace uirenderer {
331e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
341e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guystruct ShadowText {
352fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy    ShadowText(): radius(0), len(0), textSize(0.0f), typeface(NULL) {
36c4d8eb6fb7c88c5c4da38b0b113c24cc4b78c0b7Romain Guy    }
371e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
38416a847633680d94efb926837efdc18726d54918Raph Levien    ShadowText(SkPaint* paint, uint32_t radius, uint32_t len, const char* srcText,
39416a847633680d94efb926837efdc18726d54918Raph Levien            const float* positions):
40416a847633680d94efb926837efdc18726d54918Raph Levien            radius(radius), len(len), positions(positions) {
41321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy        // TODO: Propagate this through the API, we should not cast here
42321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy        text = (const char16_t*) srcText;
431e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
44c4d8eb6fb7c88c5c4da38b0b113c24cc4b78c0b7Romain Guy        textSize = paint->getTextSize();
45c4d8eb6fb7c88c5c4da38b0b113c24cc4b78c0b7Romain Guy        typeface = paint->getTypeface();
46cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy
47cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        flags = 0;
48cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        if (paint->isFakeBoldText()) {
49cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy            flags |= Font::kFakeBold;
50cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        }
51cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy
52cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        const float skewX = paint->getTextSkewX();
53cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        italicStyle = *(uint32_t*) &skewX;
54cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy
55cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        const float scaleXFloat = paint->getTextScaleX();
56cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy        scaleX = *(uint32_t*) &scaleXFloat;
571e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
581e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
591e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    ~ShadowText() {
601e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
611e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
621e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t radius;
631e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t len;
64c4d8eb6fb7c88c5c4da38b0b113c24cc4b78c0b7Romain Guy    float textSize;
65c4d8eb6fb7c88c5c4da38b0b113c24cc4b78c0b7Romain Guy    SkTypeface* typeface;
66cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy    uint32_t flags;
67cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy    uint32_t italicStyle;
68cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy    uint32_t scaleX;
69321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy    const char16_t* text;
70416a847633680d94efb926837efdc18726d54918Raph Levien    const float* positions;
71321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy    String16 str;
72416a847633680d94efb926837efdc18726d54918Raph Levien    Vector<float> positionsCopy;
73321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy
74321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy    void copyTextLocally() {
75321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy        str.setTo((const char16_t*) text, len >> 1);
76321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy        text = str.string();
77416a847633680d94efb926837efdc18726d54918Raph Levien        if (positions != NULL) {
78416a847633680d94efb926837efdc18726d54918Raph Levien            positionsCopy.clear();
79416a847633680d94efb926837efdc18726d54918Raph Levien            positionsCopy.appendArray(positions, len);
80416a847633680d94efb926837efdc18726d54918Raph Levien            positions = positionsCopy.array();
81416a847633680d94efb926837efdc18726d54918Raph Levien        }
82321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy    }
831e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
841e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    bool operator<(const ShadowText& rhs) const {
852fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy        LTE_INT(len) {
862fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy            LTE_INT(radius) {
872fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy                LTE_FLOAT(textSize) {
88321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy                    LTE_INT(typeface) {
89cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy                        LTE_INT(flags) {
90cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy                            LTE_INT(italicStyle) {
91cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy                                LTE_INT(scaleX) {
92416a847633680d94efb926837efdc18726d54918Raph Levien                                    int cmp = memcmp(text, rhs.text, len);
93416a847633680d94efb926837efdc18726d54918Raph Levien                                    if (cmp < 0) return true;
94416a847633680d94efb926837efdc18726d54918Raph Levien                                    if (cmp == 0 && rhs.positions != NULL) {
95416a847633680d94efb926837efdc18726d54918Raph Levien                                        if (positions == NULL) return true;
96416a847633680d94efb926837efdc18726d54918Raph Levien                                        return memcmp(positions, rhs.positions, len << 2) < 0;
97416a847633680d94efb926837efdc18726d54918Raph Levien                                    }
98cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy                                }
99cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy                            }
100cabfcc1364eb7e4de0b15b3574fba45027b45cfcRomain Guy                        }
1011e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy                    }
1021e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy                }
1031e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy            }
1041e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        }
1051e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        return false;
1061e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
1071e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // struct ShadowText
1081e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1091e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy/**
1101e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * Alpha texture used to represent a shadow.
1111e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy */
1121e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guystruct ShadowTexture: public Texture {
1131e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    ShadowTexture(): Texture() {
1141e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
1151e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1161e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    float left;
1171e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    float top;
1181e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // struct ShadowTexture
1191e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1201e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyclass TextDropShadowCache: public OnEntryRemoved<ShadowText, ShadowTexture*> {
1211e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guypublic:
122fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    TextDropShadowCache();
1231e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    TextDropShadowCache(uint32_t maxByteSize);
1241e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    ~TextDropShadowCache();
1251e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1261e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1271e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Used as a callback when an entry is removed from the cache.
1281e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Do not invoke directly.
1291e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1301e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    void operator()(ShadowText& text, ShadowTexture*& texture);
1311e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1321e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    ShadowTexture* get(SkPaint* paint, const char* text, uint32_t len,
133416a847633680d94efb926837efdc18726d54918Raph Levien            int numGlyphs, uint32_t radius, const float* positions);
1341e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1351e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1361e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Clears the cache. This causes all textures to be deleted.
1371e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1381e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    void clear();
1391e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1401e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    void setFontRenderer(FontRenderer& fontRenderer) {
1411e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        mRenderer = &fontRenderer;
1421e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
1431e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1441e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1451e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Sets the maximum size of the cache in bytes.
1461e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1471e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    void setMaxSize(uint32_t maxSize);
1481e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1491e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Returns the maximum size of the cache in bytes.
1501e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1511e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t getMaxSize();
1521e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1531e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Returns the current size of the cache in bytes.
1541e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1551e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t getSize();
1561e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1571e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyprivate:
15825dc3a7dbac2f90f5144035e9c8ed99c09cc3132Romain Guy    void init();
15925dc3a7dbac2f90f5144035e9c8ed99c09cc3132Romain Guy
1601e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    GenerationCache<ShadowText, ShadowTexture*> mCache;
1611e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1621e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t mSize;
1631e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t mMaxSize;
1641e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    FontRenderer* mRenderer;
16525dc3a7dbac2f90f5144035e9c8ed99c09cc3132Romain Guy    bool mDebugEnabled;
1661e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // class TextDropShadowCache
1671e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1681e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // namespace uirenderer
1691e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // namespace android
1701e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1715b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#endif // ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H
172