1694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy/* 2694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * Copyright (C) 2010 The Android Open Source Project 3694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * 4694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * you may not use this file except in compliance with the License. 6694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * You may obtain a copy of the License at 7694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * 8694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 9694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * 10694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * Unless required by applicable law or agreed to in writing, software 11694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * See the License for the specific language governing permissions and 14694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy * limitations under the License. 15694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy */ 16694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 1796a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "FontRenderer.h" 1896a5c4c7bab6718524de7253da8309143ab48befChris Craik 1996a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "Caches.h" 2096a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "Debug.h" 2196a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "Extensions.h" 22e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik#include "Glop.h" 23e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik#include "GlopBuilder.h" 2496a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "PixelBuffer.h" 2596a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "Rect.h" 2696a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "renderstate/RenderState.h" 2796a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "utils/Blur.h" 2896a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "utils/Timing.h" 29694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 30a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 31a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik#if HWUI_NEW_OPS 329e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "BakedOpDispatcher.h" 33a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik#include "BakedOpRenderer.h" 349e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "BakedOpState.h" 35a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik#else 36a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik#include "OpenGLRenderer.h" 37a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik#endif 38a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 399db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik#include <algorithm> 409db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik#include <cutils/properties.h> 41ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger#include <SkGlyph.h> 42694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy#include <SkUtils.h> 4351769a68a5cb34e9564740c6a854fcb93018789dRomain Guy#include <utils/Log.h> 4451769a68a5cb34e9564740c6a854fcb93018789dRomain Guy 45e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#ifdef ANDROID_ENABLE_RENDERSCRIPT 466e2004089305cf2cd958b52b234459a49a4e5c83Romain Guy#include <RenderScript.h> 47e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#endif 48f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 49694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guynamespace android { 50694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guynamespace uirenderer { 51694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 52f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik// blur inputs smaller than this constant will bypass renderscript 53f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik#define RS_MIN_INPUT_CUTOFF 10000 54f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 55694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy/////////////////////////////////////////////////////////////////////////////// 561e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease// TextSetupFunctor 571e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease/////////////////////////////////////////////////////////////////////////////// 581e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 59828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craikvoid TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) { 6053e51e4aa933f9603587e1780f446c18816bf9beChris Craik int textureFillFlags = TextureFillFlags::None; 6153e51e4aa933f9603587e1780f446c18816bf9beChris Craik if (texture.getFormat() == GL_ALPHA) { 6253e51e4aa933f9603587e1780f446c18816bf9beChris Craik textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture; 6353e51e4aa933f9603587e1780f446c18816bf9beChris Craik } 64e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik if (linearFiltering) { 6553e51e4aa933f9603587e1780f446c18816bf9beChris Craik textureFillFlags |= TextureFillFlags::ForceFilter; 66e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik } 6753e51e4aa933f9603587e1780f446c18816bf9beChris Craik int transformFlags = pureTranslate 6853e51e4aa933f9603587e1780f446c18816bf9beChris Craik ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None; 69e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik Glop glop; 70a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik#if HWUI_NEW_OPS 71a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik GlopBuilder(renderer->renderState(), renderer->caches(), &glop) 72a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .setRoundRectClipState(bakedState->roundRectClipState) 73a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .setMeshTexturedIndexedQuads(texture.mesh(), texture.meshElementCount()) 74a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .setFillTexturePaint(texture.getTexture(), textureFillFlags, paint, bakedState->alpha) 75a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .setTransform(bakedState->computedState.transform, transformFlags) 76f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setModelViewIdentityEmptyBounds() 77a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .build(); 7815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // Note: don't pass dirty bounds here, so user must manage passing dirty bounds to renderer 7915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer->renderGlop(nullptr, clip, glop); 80a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik#else 81e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik GlopBuilder(renderer->mRenderState, renderer->mCaches, &glop) 82a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .setRoundRectClipState(renderer->currentSnapshot()->roundRectClipState) 83e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik .setMeshTexturedIndexedQuads(texture.mesh(), texture.meshElementCount()) 84e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik .setFillTexturePaint(texture.getTexture(), textureFillFlags, paint, renderer->currentSnapshot()->alpha) 8553e51e4aa933f9603587e1780f446c18816bf9beChris Craik .setTransform(*(renderer->currentSnapshot()), transformFlags) 865430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik .setModelViewOffsetRect(0, 0, Rect()) 87e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik .build(); 88e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik renderer->renderGlop(glop); 89a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik#endif 901e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 911e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 921e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease/////////////////////////////////////////////////////////////////////////////// 93694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy// FontRenderer 94694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy/////////////////////////////////////////////////////////////////////////////// 95694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 96514fb18827186591d66973c2362c859b64b63556Romain Guystatic bool sLogFontRendererCreate = true; 97514fb18827186591d66973c2362c859b64b63556Romain Guy 98c08820f587ad94698691a6657e87712de07e484cChris CraikFontRenderer::FontRenderer(const uint8_t* gammaTable) 99c08820f587ad94698691a6657e87712de07e484cChris Craik : mGammaTable(gammaTable) 100083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik , mCurrentFont(nullptr) 101083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik , mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity) 102083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik , mCurrentCacheTexture(nullptr) 103083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik , mUploadTexture(false) 104083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik , mFunctor(nullptr) 105083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik , mClip(nullptr) 106083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik , mBounds(nullptr) 107083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik , mDrawn(false) 108083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik , mInitialized(false) 109083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik , mLinearFiltering(false) { 110e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy 111c9855a53edfac818dc68714557185977556f849dRomain Guy if (sLogFontRendererCreate) { 112c9855a53edfac818dc68714557185977556f849dRomain Guy INIT_LOGD("Creating FontRenderer"); 113c9855a53edfac818dc68714557185977556f849dRomain Guy } 11451769a68a5cb34e9564740c6a854fcb93018789dRomain Guy 115c08820f587ad94698691a6657e87712de07e484cChris Craik mSmallCacheWidth = property_get_int32(PROPERTY_TEXT_SMALL_CACHE_WIDTH, 116c08820f587ad94698691a6657e87712de07e484cChris Craik DEFAULT_TEXT_SMALL_CACHE_WIDTH); 117c08820f587ad94698691a6657e87712de07e484cChris Craik mSmallCacheHeight = property_get_int32(PROPERTY_TEXT_SMALL_CACHE_HEIGHT, 118c08820f587ad94698691a6657e87712de07e484cChris Craik DEFAULT_TEXT_SMALL_CACHE_HEIGHT); 11951769a68a5cb34e9564740c6a854fcb93018789dRomain Guy 120c08820f587ad94698691a6657e87712de07e484cChris Craik mLargeCacheWidth = property_get_int32(PROPERTY_TEXT_LARGE_CACHE_WIDTH, 121c08820f587ad94698691a6657e87712de07e484cChris Craik DEFAULT_TEXT_LARGE_CACHE_WIDTH); 122c08820f587ad94698691a6657e87712de07e484cChris Craik mLargeCacheHeight = property_get_int32(PROPERTY_TEXT_LARGE_CACHE_HEIGHT, 123c08820f587ad94698691a6657e87712de07e484cChris Craik DEFAULT_TEXT_LARGE_CACHE_HEIGHT); 1249f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 1259f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint32_t maxTextureSize = (uint32_t) Caches::getInstance().maxTextureSize; 126083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik 1279db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik mSmallCacheWidth = std::min(mSmallCacheWidth, maxTextureSize); 1289db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik mSmallCacheHeight = std::min(mSmallCacheHeight, maxTextureSize); 1299db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik mLargeCacheWidth = std::min(mLargeCacheWidth, maxTextureSize); 1309db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik mLargeCacheHeight = std::min(mLargeCacheHeight, maxTextureSize); 1319f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 132eb32a499194119b3783b86c925172df02e5d2685Chet Haase if (sLogFontRendererCreate) { 133eb32a499194119b3783b86c925172df02e5d2685Chet Haase INIT_LOGD(" Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i", 134eb32a499194119b3783b86c925172df02e5d2685Chet Haase mSmallCacheWidth, mSmallCacheHeight, 135eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth, mLargeCacheHeight >> 1, 136eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth, mLargeCacheHeight >> 1, 137eb32a499194119b3783b86c925172df02e5d2685Chet Haase mLargeCacheWidth, mLargeCacheHeight); 13851769a68a5cb34e9564740c6a854fcb93018789dRomain Guy } 139514fb18827186591d66973c2362c859b64b63556Romain Guy 140514fb18827186591d66973c2362c859b64b63556Romain Guy sLogFontRendererCreate = false; 141694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 142694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 143272a685f17cc4828257e521a6f62b7b17870f75eJohn Reckvoid clearCacheTextures(std::vector<CacheTexture*>& cacheTextures) { 1441e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 1451e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease delete cacheTextures[i]; 146694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 1471e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTextures.clear(); 1481e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 1491e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 1501e546815bbb736c50679a8aefc25f48561026fc5Victoria LeaseFontRenderer::~FontRenderer() { 1511e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mACacheTextures); 1521e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mRGBACacheTextures); 153694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 154e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 155e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy while (it.next()) { 156e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy delete it.value(); 157694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 158e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy mActiveFonts.clear(); 159694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 160694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 161694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guyvoid FontRenderer::flushAllAndInvalidate() { 162661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy issueDrawCommand(); 1639d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 164e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 165e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy while (it.next()) { 166e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy it.value()->invalidateTextureCache(); 167694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 1689d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 1691e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < mACacheTextures.size(); i++) { 1701e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mACacheTextures[i]->init(); 1711e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 1721e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 1731e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < mRGBACacheTextures.size(); i++) { 1741e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mRGBACacheTextures[i]->init(); 175e816baea651476aca4407200d4a5e629b9ab8dfaChet Haase } 1761f61b1911e03ef3fc51c3db64798071f3a7477ecchaochen 1771f61b1911e03ef3fc51c3db64798071f3a7477ecchaochen mDrawn = false; 178694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 179694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 180272a685f17cc4828257e521a6f62b7b17870f75eJohn Reckvoid FontRenderer::flushLargeCaches(std::vector<CacheTexture*>& cacheTextures) { 181378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase // Start from 1; don't deallocate smallest/default texture 1821e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 1; i < cacheTextures.size(); i++) { 1831e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheTextures[i]; 184cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture->getPixelBuffer()) { 185378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase cacheTexture->init(); 186e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); 187e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy while (it.next()) { 188e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy it.value()->invalidateTextureCache(cacheTexture); 1899a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase } 190e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik cacheTexture->releasePixelBuffer(); 1919a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase } 1929a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase } 1939a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase} 1949a8245629d69d81e0b62e52970feaf9c02580e75Chet Haase 1951e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::flushLargeCaches() { 1961e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease flushLargeCaches(mACacheTextures); 1971e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease flushLargeCaches(mRGBACacheTextures); 1981e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 1991e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 200272a685f17cc4828257e521a6f62b7b17870f75eJohn ReckCacheTexture* FontRenderer::cacheBitmapInTexture(std::vector<CacheTexture*>& cacheTextures, 2011e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease const SkGlyph& glyph, uint32_t* startX, uint32_t* startY) { 2021e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 2031e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (cacheTextures[i]->fitBitmap(glyph, startX, startY)) { 2041e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return cacheTextures[i]; 205378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase } 206378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase } 207378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase // Could not fit glyph into current cache textures 208d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik return nullptr; 209378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase} 210378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase 2117de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haasevoid FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, 212f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase uint32_t* retOriginX, uint32_t* retOriginY, bool precaching) { 2132efd5c5886d9acf747bc92f888d731ed558aabccChet Haase checkInit(); 214a4adcf0239039eb8f005be252409901c41b28839Romain Guy 215a4adcf0239039eb8f005be252409901c41b28839Romain Guy // If the glyph bitmap is empty let's assum the glyph is valid 216a4adcf0239039eb8f005be252409901c41b28839Romain Guy // so we can avoid doing extra work later on 217a4adcf0239039eb8f005be252409901c41b28839Romain Guy if (glyph.fWidth == 0 || glyph.fHeight == 0) { 218a4adcf0239039eb8f005be252409901c41b28839Romain Guy cachedGlyph->mIsValid = true; 219d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik cachedGlyph->mCacheTexture = nullptr; 220a4adcf0239039eb8f005be252409901c41b28839Romain Guy return; 221a4adcf0239039eb8f005be252409901c41b28839Romain Guy } 222a4adcf0239039eb8f005be252409901c41b28839Romain Guy 2237de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase cachedGlyph->mIsValid = false; 224a4adcf0239039eb8f005be252409901c41b28839Romain Guy 2251e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // choose an appropriate cache texture list for this glyph format 2261e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); 227272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck std::vector<CacheTexture*>* cacheTextures = nullptr; 2281e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease switch (format) { 2291e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kA8_Format: 230723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease case SkMask::kBW_Format: 2311e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTextures = &mACacheTextures; 2321e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2331e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kARGB32_Format: 2341e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTextures = &mRGBACacheTextures; 2351e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2361e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease default: 2371e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 2381e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease ALOGD("getCacheTexturesForFormat: unknown SkMask format %x", format); 2391e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2401e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return; 2411e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2421e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 243694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy // If the glyph is too tall, don't cache it 244378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > 2451e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease (*cacheTextures)[cacheTextures->size() - 1]->getHeight()) { 2462efd5c5886d9acf747bc92f888d731ed558aabccChet Haase ALOGE("Font size too large to fit in cache. width, height = %i, %i", 2472efd5c5886d9acf747bc92f888d731ed558aabccChet Haase (int) glyph.fWidth, (int) glyph.fHeight); 2487de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase return; 249694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 250694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 251694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy // Now copy the bitmap into the cache texture 252694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t startX = 0; 253694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t startY = 0; 254694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 2551e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY); 256694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 257378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase if (!cacheTexture) { 258f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase if (!precaching) { 259f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase // If the new glyph didn't fit and we are not just trying to precache it, 260f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase // clear out the cache and try again 261f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase flushAllAndInvalidate(); 2621e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY); 263f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase } 264694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 265378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase if (!cacheTexture) { 266f942cf10e04567f6b9456f6258e29c803b8bfb41Chet Haase // either the glyph didn't fit or we're precaching and will cache it when we draw 2677de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase return; 268694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 269694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 270694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 271378e919ccb75efe24d5a5aa75ac2c6ef255dcb48Chet Haase cachedGlyph->mCacheTexture = cacheTexture; 2727de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase 273694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy *retOriginX = startX; 274694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy *retOriginY = startY; 275694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 276694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t endX = startX + glyph.fWidth; 277694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy uint32_t endY = startY + glyph.fHeight; 278694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 2798087246d9964b11de8ce116bc63b156faa4197e0Romain Guy uint32_t cacheWidth = cacheTexture->getWidth(); 280694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 281cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (!cacheTexture->getPixelBuffer()) { 28244eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik Caches::getInstance().textureState().activateTexture(0); 2837de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase // Large-glyph texture memory is allocated only as needed 284e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik cacheTexture->allocatePixelBuffer(); 2857de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase } 286661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!cacheTexture->mesh()) { 287661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy cacheTexture->allocateMesh(); 288661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 2899d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 290cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint8_t* cacheBuffer = cacheTexture->getPixelBuffer()->map(); 291b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t* bitmapBuffer = (uint8_t*) glyph.fImage; 2921e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease int srcStride = glyph.rowBytes(); 2930b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy 2941e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // Copy the glyph image, taking the mask format into account 295b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy switch (format) { 296b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy case SkMask::kA8_Format: { 2971e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; 2981e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX 2991e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease - TEXTURE_BORDER_SIZE; 3001e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write leading border line 3011e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 3021e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write glyph data 303b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy if (mGammaTable) { 3041e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) { 3050b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy row = cacheY * cacheWidth; 3060b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 307b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) { 308b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t tempCol = bitmapBuffer[bY + bX]; 3090b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + cacheX] = mGammaTable[tempCol]; 310b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 3110b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 312b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 313b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } else { 3141e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) { 3150b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy row = cacheY * cacheWidth; 3160b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy memcpy(&cacheBuffer[row + startX], &bitmapBuffer[bY], glyph.fWidth); 3170b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 3180b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 319b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 320b1d0a4ed21168fefcb82232c8f22cb95d60acb85Romain Guy } 3211e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write trailing border line 3221e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE; 3231e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 3241e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 3251e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 3261e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kARGB32_Format: { 3271e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // prep data lengths 3281e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease const size_t formatSize = PixelBuffer::formatSize(GL_RGBA); 3291e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease const size_t borderSize = formatSize * TEXTURE_BORDER_SIZE; 3301e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease size_t rowSize = formatSize * glyph.fWidth; 3311e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // prep advances 3321e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease size_t dstStride = formatSize * cacheWidth; 3331e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // prep indices 3341e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // - we actually start one row early, and then increment before first copy 3351e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* src = &bitmapBuffer[0 - srcStride]; 3361e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dst = &cacheBuffer[cacheTexture->getOffset(startX, startY - 1)]; 3371e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dstEnd = &cacheBuffer[cacheTexture->getOffset(startX, endY - 1)]; 3381e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dstL = dst - borderSize; 3391e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint8_t* dstR = dst + rowSize; 3401e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write leading border line 3411e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(dstL, 0, rowSize + 2 * borderSize); 3421e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write glyph data 3431e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease while (dst < dstEnd) { 3441e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(dstL += dstStride, 0, borderSize); // leading border column 3451e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memcpy(dst += dstStride, src += srcStride, rowSize); // glyph data 3461e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(dstR += dstStride, 0, borderSize); // trailing border column 3471e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 3481e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write trailing border line 34916c84069a4cc0c0d3c35e798dc5e4b0130d4a26fVictoria Lease memset(dstL += dstStride, 0, rowSize + 2 * borderSize); 350b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy break; 351b1d0a4ed21168fefcb82232c8f22cb95d60acb85Romain Guy } 352b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy case SkMask::kBW_Format: { 3531e19674107e1aa2224c2b8c7d12bfa057efe80eaAndreas Gampe uint32_t cacheX = 0, cacheY = 0; 3541e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX 3551e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease - TEXTURE_BORDER_SIZE; 356b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy static const uint8_t COLORS[2] = { 0, 255 }; 3571e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write leading border line 3581e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 3591e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write glyph data 360b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy for (cacheY = startY; cacheY < endY; cacheY++) { 361b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy cacheX = startX; 3621e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease int rowBytes = srcStride; 363b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t* buffer = bitmapBuffer; 364b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy 3650b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy row = cacheY * cacheWidth; 3660b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; 367b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy while (--rowBytes >= 0) { 368b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy uint8_t b = *buffer++; 369b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy for (int8_t mask = 7; mask >= 0 && cacheX < endX; mask--) { 370b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy cacheBuffer[cacheY * cacheWidth + cacheX++] = COLORS[(b >> mask) & 0x1]; 371b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 372b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy } 3730b58a3deab66c30a8d35072e55aac6279dd367ccRomain Guy cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; 374b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy 3751e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bitmapBuffer += srcStride; 376b1d0a4ed21168fefcb82232c8f22cb95d60acb85Romain Guy } 3771e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // write trailing border line 3781e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE; 3791e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); 380b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy break; 381694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 382b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy default: 3831e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease ALOGW("Unknown glyph format: 0x%x", format); 384b969a0de65730b071d846f8302e751e2637e6dbeRomain Guy break; 385694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 3869777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 3877de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase cachedGlyph->mIsValid = true; 388694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 389694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 3901e546815bbb736c50679a8aefc25f48561026fc5Victoria LeaseCacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format, 3911e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bool allocate) { 39296a5c4c7bab6718524de7253da8309143ab48befChris Craik CacheTexture* cacheTexture = new CacheTexture(width, height, format, kMaxNumberOfQuads); 3939d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 3942a47c14e2a6f152496b43104bc785c488583fd59Chet Haase if (allocate) { 39544eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik Caches::getInstance().textureState().activateTexture(0); 396e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik cacheTexture->allocatePixelBuffer(); 397661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy cacheTexture->allocateMesh(); 3982a47c14e2a6f152496b43104bc785c488583fd59Chet Haase } 3999d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 4002a47c14e2a6f152496b43104bc785c488583fd59Chet Haase return cacheTexture; 4017de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase} 4027de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase 4037de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haasevoid FontRenderer::initTextTexture() { 4041e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mACacheTextures); 4051e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease clearCacheTextures(mRGBACacheTextures); 4069d9758ae30a59dcf594e0d26ba5d4ee153a3e44aRomain Guy 4077de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mUploadTexture = false; 408272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck mACacheTextures.push_back(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, 4091e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, true)); 410272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 4111e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, false)); 412272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 4131e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, false)); 414272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight, 4151e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_ALPHA, false)); 416272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck mRGBACacheTextures.push_back(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, 4171e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_RGBA, false)); 418272a685f17cc4828257e521a6f62b7b17870f75eJohn Reck mRGBACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, 4191e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GL_RGBA, false)); 4201e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease mCurrentCacheTexture = mACacheTextures[0]; 421694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 422694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 423694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy// We don't want to allocate anything unless we actually draw text 424694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guyvoid FontRenderer::checkInit() { 425694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy if (mInitialized) { 426694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy return; 427694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 428694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 429694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy initTextTexture(); 430694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 431694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy mInitialized = true; 432694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 433694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 434272a685f17cc4828257e521a6f62b7b17870f75eJohn Reckvoid checkTextureUpdateForCache(Caches& caches, std::vector<CacheTexture*>& cacheTextures, 4351e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bool& resetPixelStore, GLuint& lastTextureId) { 4361e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 4371e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheTextures[i]; 438cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) { 4398087246d9964b11de8ce116bc63b156faa4197e0Romain Guy if (cacheTexture->getTextureId() != lastTextureId) { 4408087246d9964b11de8ce116bc63b156faa4197e0Romain Guy lastTextureId = cacheTexture->getTextureId(); 44144eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik caches.textureState().activateTexture(0); 44244eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik caches.textureState().bindTexture(lastTextureId); 4430908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy } 4440908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy 445cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture->upload()) { 446cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy resetPixelStore = true; 4472d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy } 4489b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk } 449694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 4501e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 4511e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4521e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::checkTextureUpdate() { 4531e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (!mUploadTexture) { 4541e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return; 4551e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 4561e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4571e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease Caches& caches = Caches::getInstance(); 4581e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease GLuint lastTextureId = 0; 4591e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4601e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease bool resetPixelStore = false; 4611e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4621e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease // Iterate over all the cache textures and see which ones need to be updated 4631e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease checkTextureUpdateForCache(caches, mACacheTextures, resetPixelStore, lastTextureId); 4641e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease checkTextureUpdateForCache(caches, mRGBACacheTextures, resetPixelStore, lastTextureId); 465694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 466cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // Unbind any PBO we might have used to update textures 46744eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik caches.pixelBufferState().unbind(); 468cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 4690908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy // Reset to default unpack row length to avoid affecting texture 4700908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy // uploads in other parts of the renderer 471cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (resetPixelStore) { 4720908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 4730908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy } 4740908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy 4759b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk mUploadTexture = false; 4769b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk} 4779b9902ddbb01548f4a0199087b7035e7c10b2ae7Alex Sakhartchouk 478272a685f17cc4828257e521a6f62b7b17870f75eJohn Reckvoid FontRenderer::issueDrawCommand(std::vector<CacheTexture*>& cacheTextures) { 47996a5c4c7bab6718524de7253da8309143ab48befChris Craik if (!mFunctor) return; 48096a5c4c7bab6718524de7253da8309143ab48befChris Craik 481661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy bool first = true; 4821e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 4831e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* texture = cacheTextures[i]; 484661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (texture->canDraw()) { 485661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (first) { 486e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik checkTextureUpdate(); 487661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy first = false; 488083e733e8223a7d416d6c139f318e61864b28ad6Chris Craik mDrawn = true; 489661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 4907bb3cfe1cca4016ce95d3ef059761f4bb2d668bbSangkyu Lee 491828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik mFunctor->draw(*texture, mLinearFiltering); 492661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 493661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy texture->resetMesh(); 494661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 4957bb3cfe1cca4016ce95d3ef059761f4bb2d668bbSangkyu Lee } 4961e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 4971e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 4981e546815bbb736c50679a8aefc25f48561026fc5Victoria Leasevoid FontRenderer::issueDrawCommand() { 4991e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease issueDrawCommand(mACacheTextures); 5001e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease issueDrawCommand(mRGBACacheTextures); 501694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 502694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 5039777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guyvoid FontRenderer::appendMeshQuadNoClip(float x1, float y1, float u1, float v1, 5049777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5057de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase float x4, float y4, float u4, float v4, CacheTexture* texture) { 5067de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase if (texture != mCurrentCacheTexture) { 5077de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase // Now use the new texture id 5087de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase mCurrentCacheTexture = texture; 5097de0cb12d0e5fd64811da0b5d1ae0c0d58b86f86Chet Haase } 51009147fbdc8206a0cac78bfe9083e7e15b3c5689cRomain Guy 511661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCurrentCacheTexture->addQuad(x1, y1, u1, v1, x2, y2, u2, v2, 512661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy x3, y3, u3, v3, x4, y4, u4, v4); 5139777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy} 5149777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5159777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guyvoid FontRenderer::appendMeshQuad(float x1, float y1, float u1, float v1, 5169777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5179777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x4, float y4, float u4, float v4, CacheTexture* texture) { 5189777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5199777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy if (mClip && 5209777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom)) { 5219777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy return; 5229777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 5239777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5249777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture); 525694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 5265b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (mBounds) { 527e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik mBounds->left = std::min(mBounds->left, x1); 528e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik mBounds->top = std::min(mBounds->top, y3); 529e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik mBounds->right = std::max(mBounds->right, x3); 530e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik mBounds->bottom = std::max(mBounds->bottom, y1); 5315b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 5325b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 533661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (mCurrentCacheTexture->endOfMesh()) { 534694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy issueDrawCommand(); 535694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy } 536694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 537694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 5389777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guyvoid FontRenderer::appendRotatedMeshQuad(float x1, float y1, float u1, float v1, 5399777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3, 5409777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy float x4, float y4, float u4, float v4, CacheTexture* texture) { 5419777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5429777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture); 5439777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 5449777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy if (mBounds) { 545e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik mBounds->left = std::min(mBounds->left, std::min(x1, std::min(x2, std::min(x3, x4)))); 546e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik mBounds->top = std::min(mBounds->top, std::min(y1, std::min(y2, std::min(y3, y4)))); 547e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik mBounds->right = std::max(mBounds->right, std::max(x1, std::max(x2, std::max(x3, x4)))); 548e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik mBounds->bottom = std::max(mBounds->bottom, std::max(y1, std::max(y2, std::max(y3, y4)))); 5499777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 5509777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 551661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (mCurrentCacheTexture->endOfMesh()) { 5529777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy issueDrawCommand(); 5539777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 5549777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy} 5559777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 55659744b79ec302000802cd56d30a1bf70f0183c80Chris Craikvoid FontRenderer::setFont(const SkPaint* paint, const SkMatrix& matrix) { 557e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy mCurrentFont = Font::create(this, paint, matrix); 558694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 5597975fb6d12cb1eb96b75e3a563627cd4c4081bd6Romain Guy 560e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris CraikFontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, const glyph_t *glyphs, 561a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik int numGlyphs, float radius, const float* positions) { 5621e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy checkInit(); 5631e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy 564cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy DropShadow image; 565cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.width = 0; 566cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.height = 0; 567d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik image.image = nullptr; 568cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.penX = 0; 569cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy image.penY = 0; 570cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 5711e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy if (!mCurrentFont) { 5721e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy return image; 5731e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy } 574f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk 5752d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy mDrawn = false; 576d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik mClip = nullptr; 577d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik mBounds = nullptr; 578ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 579f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk Rect bounds; 580e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik mCurrentFont->measure(paint, glyphs, numGlyphs, &bounds, positions); 581ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 582e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger uint32_t intRadius = Blur::convertRadiusToInt(radius); 583e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * intRadius; 584e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * intRadius; 585ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 586cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t maxSize = Caches::getInstance().maxTextureSize; 587cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (paddedWidth > maxSize || paddedHeight > maxSize) { 588cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy return image; 589cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 590cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 591e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#ifdef ANDROID_ENABLE_RENDERSCRIPT 592f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik // Align buffers for renderscript usage 593f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik if (paddedWidth & (RS_CPU_ALLOCATION_ALIGNMENT - 1)) { 594f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik paddedWidth += RS_CPU_ALLOCATION_ALIGNMENT - paddedWidth % RS_CPU_ALLOCATION_ALIGNMENT; 595f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk } 596f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik int size = paddedWidth * paddedHeight; 5976e2004089305cf2cd958b52b234459a49a4e5c83Romain Guy uint8_t* dataBuffer = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, size); 598e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#else 599e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill int size = paddedWidth * paddedHeight; 600e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill uint8_t* dataBuffer = (uint8_t*) malloc(size); 601e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#endif 602e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill 603f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik memset(dataBuffer, 0, size); 604f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 605e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger int penX = intRadius - bounds.left; 606e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger int penY = intRadius - bounds.bottom; 607f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk 608dd8697c095272f19ddad214834a490b00f11a477Chris Craik if ((bounds.right > bounds.left) && (bounds.top > bounds.bottom)) { 609dd8697c095272f19ddad214834a490b00f11a477Chris Craik // text has non-whitespace, so draw and blur to create the shadow 610dd8697c095272f19ddad214834a490b00f11a477Chris Craik // NOTE: bounds.isEmpty() can't be used here, since vertical coordinates are inverted 611dd8697c095272f19ddad214834a490b00f11a477Chris Craik // TODO: don't draw pure whitespace in the first place, and avoid needing this check 612e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik mCurrentFont->render(paint, glyphs, numGlyphs, penX, penY, 613d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, nullptr, positions); 614dd8697c095272f19ddad214834a490b00f11a477Chris Craik 615cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // Unbind any PBO we might have used 61644eb2c00861098dd3e2950d923646814b4cc57c2Chris Craik Caches::getInstance().pixelBufferState().unbind(); 617cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 618dd8697c095272f19ddad214834a490b00f11a477Chris Craik blurImage(&dataBuffer, paddedWidth, paddedHeight, radius); 619dd8697c095272f19ddad214834a490b00f11a477Chris Craik } 620f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk 621f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.width = paddedWidth; 622f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.height = paddedHeight; 623f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.image = dataBuffer; 624f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.penX = penX; 625f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk image.penY = penY; 6262d4fd364843d3efc6e6ee59ccc5beb513a86d789Romain Guy 627f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk return image; 628f18136cb3c881a9d16c1a4f0f341732c276936bfAlex Sakhartchouk} 629694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 630828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craikvoid FontRenderer::initRender(const Rect* clip, Rect* bounds, TextDrawFunctor* functor) { 631694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy checkInit(); 632694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 6335b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mDrawn = false; 6345b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mBounds = bounds; 635257ae3502cfad43df681b1783528d645bdabc63fRomain Guy mFunctor = functor; 63609147fbdc8206a0cac78bfe9083e7e15b3c5689cRomain Guy mClip = clip; 637671d6cf460531825a321edb200523d0faa7792c9Romain Guy} 638ff98fa5a847f66e591287154c634ef7895a9549cRomain Guy 639671d6cf460531825a321edb200523d0faa7792c9Romain Guyvoid FontRenderer::finishRender() { 640d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik mBounds = nullptr; 641d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik mClip = nullptr; 642694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 643661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy issueDrawCommand(); 644671d6cf460531825a321edb200523d0faa7792c9Romain Guy} 645671d6cf460531825a321edb200523d0faa7792c9Romain Guy 646e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craikvoid FontRenderer::precache(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, 64759744b79ec302000802cd56d30a1bf70f0183c80Chris Craik const SkMatrix& matrix) { 648e3a9b24b5e3f9b2058486814a6d27729e51ad466Romain Guy Font* font = Font::create(this, paint, matrix); 649e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik font->precache(paint, glyphs, numGlyphs); 650e816baea651476aca4407200d4a5e629b9ab8dfaChet Haase} 651e816baea651476aca4407200d4a5e629b9ab8dfaChet Haase 652cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid FontRenderer::endPrecaching() { 653cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy checkTextureUpdate(); 654cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 655cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 656e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craikbool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs, 657a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik int numGlyphs, int x, int y, const float* positions, 658a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik Rect* bounds, TextDrawFunctor* functor, bool forceFinish) { 659671d6cf460531825a321edb200523d0faa7792c9Romain Guy if (!mCurrentFont) { 660671d6cf460531825a321edb200523d0faa7792c9Romain Guy ALOGE("No font set"); 661671d6cf460531825a321edb200523d0faa7792c9Romain Guy return false; 662671d6cf460531825a321edb200523d0faa7792c9Romain Guy } 663671d6cf460531825a321edb200523d0faa7792c9Romain Guy 664257ae3502cfad43df681b1783528d645bdabc63fRomain Guy initRender(clip, bounds, functor); 665e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik mCurrentFont->render(paint, glyphs, numGlyphs, x, y, positions); 666527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik 667527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik if (forceFinish) { 668527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik finishRender(); 669527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik } 6705b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6715b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return mDrawn; 6729777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy} 6739777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 674e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craikbool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs, 675a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik int numGlyphs, const SkPath* path, float hOffset, float vOffset, 676a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik Rect* bounds, TextDrawFunctor* functor) { 6779777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy if (!mCurrentFont) { 6789777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy ALOGE("No font set"); 6799777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy return false; 6809777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy } 6819777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 6821e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease initRender(clip, bounds, functor); 683e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik mCurrentFont->render(paint, glyphs, numGlyphs, path, hOffset, vOffset); 6849777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy finishRender(); 6859777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy 6869777173eb6c9eb97c7921c8288ebc65e3ab3ce6fRomain Guy return mDrawn; 687694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy} 688694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy 689e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenbergervoid FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, float radius) { 690e392c81f6b8f9ace0c0a48c9d4df117fda31fd13Derek Sollenberger uint32_t intRadius = Blur::convertRadiusToInt(radius); 691e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#ifdef ANDROID_ENABLE_RENDERSCRIPT 692f3754a84289680782b2c7caac30fda18207a5c23Chris Craik if (width * height * intRadius >= RS_MIN_INPUT_CUTOFF && radius <= 25.0f) { 693e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill uint8_t* outImage = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height); 694e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill 695d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (mRs == nullptr) { 696e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill mRs = new RSC::RS(); 697abe55e92241fd9a19885f7b11db8d3043ab60c61Tim Murray // a null path is OK because there are no custom kernels used 698abe55e92241fd9a19885f7b11db8d3043ab60c61Tim Murray // hence nothing gets cached by RS 699abe55e92241fd9a19885f7b11db8d3043ab60c61Tim Murray if (!mRs->init("", RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) { 700ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRs.clear(); 701e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill ALOGE("blur RS failed to init"); 702ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua } else { 703ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRsElement = RSC::Element::A_8(mRs); 704ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement); 705e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill } 706e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill } 707d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik if (mRs != nullptr) { 708ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0); 709ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t, 710ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RS_ALLOCATION_MIPMAP_NONE, 711ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, 712ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua *image); 713ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t, 714ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RS_ALLOCATION_MIPMAP_NONE, 715ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, 716ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua outImage); 717ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua 718ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRsScript->setRadius(radius); 719ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRsScript->setInput(ain); 720ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua mRsScript->forEach(aout); 721ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua 722ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua // replace the original image's pointer, avoiding a copy back to the original buffer 723ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua free(*image); 724ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua *image = outImage; 725f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik 726ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua return; 727ea42e015277687cef168f960252b9d7596ff1160Lu, Shenghua } 728f2d8ccc15d7272b3416f73605c1f31d1d346bd40Chris Craik } 729e4d9a01bfc7451afff1ed399a5801c7aa2af2831Dan Morrill#endif 730d71dd367af604571c7d00ca473184a1b9240eca2Romain Guy 73151d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik std::unique_ptr<float[]> gaussian(new float[2 * intRadius + 1]); 732a46ca5ec732a884c78d3e98f8b4eb8de03bc23f8huanhuan.x.wang Blur::generateGaussianWeights(gaussian.get(), radius); 733d71dd367af604571c7d00ca473184a1b9240eca2Romain Guy 73451d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik std::unique_ptr<uint8_t[]> scratch(new uint8_t[width * height]); 73551d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik Blur::horizontal(gaussian.get(), intRadius, *image, scratch.get(), width, height); 73651d6a3db97bdd5315f1a17a4b447d10a92217b98Chris Craik Blur::vertical(gaussian.get(), intRadius, scratch.get(), *image, width, height); 73789a524ac2d4a36739e51b01b336c0bade77e2ee0Alex Sakhartchouk} 73889a524ac2d4a36739e51b01b336c0bade77e2ee0Alex Sakhartchouk 739272a685f17cc4828257e521a6f62b7b17870f75eJohn Reckstatic uint32_t calculateCacheSize(const std::vector<CacheTexture*>& cacheTextures) { 740cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t size = 0; 7411e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease for (uint32_t i = 0; i < cacheTextures.size(); i++) { 7421e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease CacheTexture* cacheTexture = cacheTextures[i]; 743cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (cacheTexture && cacheTexture->getPixelBuffer()) { 744cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy size += cacheTexture->getPixelBuffer()->getSize(); 745cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 746cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 747cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy return size; 748cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 749cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 7501e546815bbb736c50679a8aefc25f48561026fc5Victoria Leaseuint32_t FontRenderer::getCacheSize(GLenum format) const { 7511e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease switch (format) { 7521e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case GL_ALPHA: { 7531e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return calculateCacheSize(mACacheTextures); 7541e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 7551e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case GL_RGBA: { 7561e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return calculateCacheSize(mRGBACacheTextures); 7571e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 7581e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease default: { 7591e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return 0; 7601e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 7611e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 7621e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease} 7631e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 764694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy}; // namespace uirenderer 765694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy}; // namespace android 766