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
272dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "font/Font.h"
281e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy#include "Texture.h"
291e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
301e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guynamespace android {
311e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guynamespace uirenderer {
321e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
338aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guyclass Caches;
342dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudsonclass FontRenderer;
358aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy
361e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guystruct ShadowText {
37a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    ShadowText(): glyphCount(0), radius(0.0f), textSize(0.0f), typeface(nullptr),
38e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            flags(0), italicStyle(0.0f), scaleX(0), glyphs(nullptr), positions(nullptr) {
39c4d8eb6fb7c88c5c4da38b0b113c24cc4b78c0b7Romain Guy    }
401e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
4169fcbccf476ffc55af4da4dfedc72c3de8f91ce8Romain Guy    // len is the number of bytes in text
42e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    ShadowText(const SkPaint* paint, float radius, uint32_t glyphCount, const glyph_t* srcGlyphs,
43e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            const float* positions)
44e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            : glyphCount(glyphCount)
45e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            , radius(radius)
46e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            , textSize(paint->getTextSize())
47e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            , typeface(paint->getTypeface())
48e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            , flags(paint->isFakeBoldText() ? Font::kFakeBold : 0)
49e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            , italicStyle(paint->getTextSkewX())
50e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            , scaleX(paint->getTextScaleX())
51e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            , glyphs(srcGlyphs)
52e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            , positions(positions) {
531e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
541e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
551e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    ~ShadowText() {
561e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
571e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
58059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    hash_t hash() const;
59059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
60059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    static int compare(const ShadowText& lhs, const ShadowText& rhs);
61059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
62059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    bool operator==(const ShadowText& other) const {
63059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy        return compare(*this, other) == 0;
64059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    }
65059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
66059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    bool operator!=(const ShadowText& other) const {
67059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy        return compare(*this, other) != 0;
68059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    }
69321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy
70321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy    void copyTextLocally() {
71e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik        str.setTo(reinterpret_cast<const char16_t*>(glyphs), glyphCount);
72e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik        glyphs = reinterpret_cast<const glyph_t*>(str.string());
73e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik        if (positions != nullptr) {
74416a847633680d94efb926837efdc18726d54918Raph Levien            positionsCopy.clear();
75a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            positionsCopy.appendArray(positions, glyphCount * 2);
76416a847633680d94efb926837efdc18726d54918Raph Levien            positions = positionsCopy.array();
77416a847633680d94efb926837efdc18726d54918Raph Levien        }
78321dce646dc3c2ecfbd72a693d8d9294a6119736Romain Guy    }
791e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
80a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    uint32_t glyphCount;
81059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    float radius;
82059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    float textSize;
83059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    SkTypeface* typeface;
84059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    uint32_t flags;
85059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    float italicStyle;
86059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    float scaleX;
87e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    const glyph_t* glyphs;
88059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    const float* positions;
89059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
90059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    // Not directly used to compute the cache key
91059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    String16 str;
92059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    Vector<float> positionsCopy;
93059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
941e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // struct ShadowText
951e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
96059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy// Caching support
97059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
98059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int strictly_order_type(const ShadowText& lhs, const ShadowText& rhs) {
99059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    return ShadowText::compare(lhs, rhs) < 0;
100059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy}
101059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
102059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline int compare_type(const ShadowText& lhs, const ShadowText& rhs) {
103059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    return ShadowText::compare(lhs, rhs);
104059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy}
105059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
106059e12ccd20f5c249724a8362d6bac325334ea76Romain Guyinline hash_t hash_type(const ShadowText& entry) {
107059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    return entry.hash();
108059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy}
109059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy
1101e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy/**
1111e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * Alpha texture used to represent a shadow.
1121e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy */
1131e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guystruct ShadowTexture: public Texture {
1148aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy    ShadowTexture(Caches& caches): Texture(caches) {
1151e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
1161e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1171e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    float left;
1181e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    float top;
1191e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // struct ShadowTexture
1201e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1211e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyclass TextDropShadowCache: public OnEntryRemoved<ShadowText, ShadowTexture*> {
1221e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guypublic:
123fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    TextDropShadowCache();
1241e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    TextDropShadowCache(uint32_t maxByteSize);
1251e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    ~TextDropShadowCache();
1261e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1271e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1281e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Used as a callback when an entry is removed from the cache.
1291e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Do not invoke directly.
1301e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
131e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik    void operator()(ShadowText& text, ShadowTexture*& texture) override;
1321e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
133e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    ShadowTexture* get(const SkPaint* paint, const glyph_t* text,
134059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy            int numGlyphs, float radius, const float* positions);
1351e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1361e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1371e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Clears the cache. This causes all textures to be deleted.
1381e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1391e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    void clear();
1401e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1411e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    void setFontRenderer(FontRenderer& fontRenderer) {
1421e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy        mRenderer = &fontRenderer;
1431e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    }
1441e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1451e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1461e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Returns the maximum size of the cache in bytes.
1471e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1481e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t getMaxSize();
1491e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    /**
1501e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     * Returns the current size of the cache in bytes.
1511e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy     */
1521e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t getSize();
1531e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1541e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guyprivate:
155059e12ccd20f5c249724a8362d6bac325334ea76Romain Guy    LruCache<ShadowText, ShadowTexture*> mCache;
1561e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1571e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy    uint32_t mSize;
15848a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik    const uint32_t mMaxSize;
15948a8f431fa52ae2ee25ffba9d20676f03bb710ffChris Craik    FontRenderer* mRenderer = nullptr;
16025dc3a7dbac2f90f5144035e9c8ed99c09cc3132Romain Guy    bool mDebugEnabled;
1611e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // class TextDropShadowCache
1621e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1631e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // namespace uirenderer
1641e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy}; // namespace android
1651e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy
1665b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy#endif // ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H
167