CacheTexture.cpp revision 38e0c32852e3b9d8ca4a9d3791577f52536419cb
19f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/* 29f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Copyright (C) 2012 The Android Open Source Project 39f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * 49f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 59f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * you may not use this file except in compliance with the License. 69f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * You may obtain a copy of the License at 79f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * 89f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * http://www.apache.org/licenses/LICENSE-2.0 99f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * 109f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Unless required by applicable law or agreed to in writing, software 119f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * distributed under the License is distributed on an "AS IS" BASIS, 129f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * See the License for the specific language governing permissions and 149f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * limitations under the License. 159f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy */ 169f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 17ca79cf69d09efa0c327e9b1237d86a119aea5da7Derek Sollenberger#include <SkGlyph.h> 189f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 199f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#include "CacheTexture.h" 202dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "FontUtil.h" 218aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy#include "../Caches.h" 220908764b2b3cf5075df4178a5f0a8547dcb7b317Romain Guy#include "../Debug.h" 23cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy#include "../Extensions.h" 24cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy#include "../PixelBuffer.h" 259f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 269f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace android { 279f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guynamespace uirenderer { 289f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 299f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 309f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy// CacheBlock 319f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 329f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 339f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/** 349f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * Insert new block into existing linked list of blocks. Blocks are sorted in increasing-width 359f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * order, except for the final block (the remainder space at the right, since we fill from the 369f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy * left). 379f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy */ 38e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain GuyCacheBlock* CacheBlock::insertBlock(CacheBlock* head, CacheBlock* newBlock) { 399f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 409f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("insertBlock: this, x, y, w, h = %p, %d, %d, %d, %d", 419f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock, newBlock->mX, newBlock->mY, 429f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mWidth, newBlock->mHeight); 439f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 449b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 45e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* currBlock = head; 46d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik CacheBlock* prevBlock = nullptr; 479b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 489f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy while (currBlock && currBlock->mY != TEXTURE_BORDER_SIZE) { 499f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (newBlock->mWidth < currBlock->mWidth) { 509f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mNext = currBlock; 519f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mPrev = prevBlock; 529f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock->mPrev = newBlock; 539b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 549f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (prevBlock) { 559f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock->mNext = newBlock; 569f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return head; 579f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 589f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return newBlock; 599f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 609f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 619b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 629f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock = currBlock; 639f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock = currBlock->mNext; 649f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 659b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 669f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // new block larger than all others - insert at end (but before the remainder space, if there) 679f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mNext = currBlock; 689f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mPrev = prevBlock; 699b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 709f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (currBlock) { 719f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy currBlock->mPrev = newBlock; 729f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 739b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 749f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (prevBlock) { 759f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock->mNext = newBlock; 769f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return head; 779f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 789f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return newBlock; 799f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 809f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy} 819f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 82e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain GuyCacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock* blockToRemove) { 839f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 849f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("removeBlock: this, x, y, w, h = %p, %d, %d, %d, %d", 859f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy blockToRemove, blockToRemove->mX, blockToRemove->mY, 869f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy blockToRemove->mWidth, blockToRemove->mHeight); 879f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 889b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 899f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* newHead = head; 909f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* nextBlock = blockToRemove->mNext; 919f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy CacheBlock* prevBlock = blockToRemove->mPrev; 929b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 939f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (prevBlock) { 949f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy prevBlock->mNext = nextBlock; 959f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 969f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newHead = nextBlock; 979f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 989b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 999f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (nextBlock) { 1009f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy nextBlock->mPrev = prevBlock; 1019f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 1029b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 1039f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy delete blockToRemove; 1049b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 1059f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return newHead; 1069f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy} 1079f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 1089f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 1099f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy// CacheTexture 1109f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy/////////////////////////////////////////////////////////////////////////////// 1119f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 112e2bb380bc26749782c873e5488cfdf4e42b27346Chris CraikCacheTexture::CacheTexture(uint16_t width, uint16_t height, GLenum format, uint32_t maxQuadCount) 113e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik : mTexture(Caches::getInstance()) 11438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck , mWidth(width) 11538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck , mHeight(height) 116e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , mFormat(format) 117e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , mMaxQuadCount(maxQuadCount) 118e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik , mCaches(Caches::getInstance()) { 119e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik mTexture.blend = true; 120e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik 121661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 122e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik getWidth() - TEXTURE_BORDER_SIZE, getHeight() - TEXTURE_BORDER_SIZE); 123cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 124cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // OpenGL ES 3.0+ lets us specify the row length for unpack operations such 125cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // as glTexSubImage2D(). This allows us to upload a sub-rectangle of a texture. 126cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // With OpenGL ES 2.0 we have to upload entire stripes instead. 127117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik mHasUnpackRowLength = mCaches.extensions().hasUnpackRowLength(); 128661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 129661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 130661a87ec28a49458f1faf533783abf2ab9927cabRomain GuyCacheTexture::~CacheTexture() { 131661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy releaseMesh(); 132e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik releasePixelBuffer(); 133661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy reset(); 134661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 135661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 136661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::reset() { 137661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // Delete existing cache blocks 138d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik while (mCacheBlocks != nullptr) { 139661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy CacheBlock* tmpBlock = mCacheBlocks; 140661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCacheBlocks = mCacheBlocks->mNext; 141661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy delete tmpBlock; 142661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 143661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mNumGlyphs = 0; 144661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCurrentQuad = 0; 145661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 146661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 147661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::init() { 148661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy // reset, then create a new remainder space to start again 149661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy reset(); 150661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, 151e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik getWidth() - TEXTURE_BORDER_SIZE, getHeight() - TEXTURE_BORDER_SIZE); 152661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 153661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 154661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::releaseMesh() { 155661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy delete[] mMesh; 156661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 157661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 158e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craikvoid CacheTexture::releasePixelBuffer() { 159e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik if (mPixelBuffer) { 160e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik delete mPixelBuffer; 161e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik mPixelBuffer = nullptr; 162661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 16338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck mTexture.deleteTexture(); 164661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mDirty = false; 165661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mCurrentQuad = 0; 166661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 167661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 168e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craikvoid CacheTexture::setLinearFiltering(bool linearFiltering) { 169e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik mTexture.setFilter(linearFiltering ? GL_LINEAR : GL_NEAREST); 170cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 171cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 172661a87ec28a49458f1faf533783abf2ab9927cabRomain Guyvoid CacheTexture::allocateMesh() { 173661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy if (!mMesh) { 174661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy mMesh = new TextureVertex[mMaxQuadCount * 4]; 175661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 176661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 177661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 178e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craikvoid CacheTexture::allocatePixelBuffer() { 179e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik if (!mPixelBuffer) { 180e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik mPixelBuffer = PixelBuffer::create(mFormat, getWidth(), getHeight()); 181661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy } 182661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 18338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck mTexture.resize(mWidth, mHeight, mFormat); 18438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck mTexture.setFilter(getLinearFiltering() ? GL_LINEAR : GL_NEAREST); 18538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck mTexture.setWrap(GL_CLAMP_TO_EDGE); 186661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy} 187661a87ec28a49458f1faf533783abf2ab9927cabRomain Guy 188cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guybool CacheTexture::upload() { 189cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy const Rect& dirtyRect = mDirtyRect; 190cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 191318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy uint32_t x = mHasUnpackRowLength ? dirtyRect.left : 0; 192cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t y = dirtyRect.top; 193e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik uint32_t width = mHasUnpackRowLength ? dirtyRect.getWidth() : getWidth(); 194cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy uint32_t height = dirtyRect.getHeight(); 195cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 196cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // The unpack row length only needs to be specified when a new 197cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy // texture is bound 198318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy if (mHasUnpackRowLength) { 199e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik glPixelStorei(GL_UNPACK_ROW_LENGTH, getWidth()); 200cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 201cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 202e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik mPixelBuffer->upload(x, y, width, height); 203cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy setDirty(false); 204cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 205318ae7bb92869d99a05388c598ad105e7aa4cdbdRomain Guy return mHasUnpackRowLength; 206cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 207cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 208cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guyvoid CacheTexture::setDirty(bool dirty) { 209cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy mDirty = dirty; 210cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy if (!dirty) { 211cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy mDirtyRect.setEmpty(); 212cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy } 213cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy} 214cf51a4199835e9604aa4c8b3854306f8fbabbf33Romain Guy 215e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guybool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY) { 2161e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease switch (glyph.fMaskFormat) { 2171e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kA8_Format: 218723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease case SkMask::kBW_Format: 2191e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (mFormat != GL_ALPHA) { 2201e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 221723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease ALOGD("fitBitmap: texture format %x is inappropriate for monochromatic glyphs", 222723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease mFormat); 2231e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2241e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return false; 2251e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2261e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2271e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease case SkMask::kARGB32_Format: 2281e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease if (mFormat != GL_RGBA) { 2291e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 230723b2feb929b96b1dde40a865c49ea18bc42f055Victoria Lease ALOGD("fitBitmap: texture format %x is inappropriate for colour glyphs", mFormat); 2311e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2321e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return false; 2331e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2341e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease break; 2351e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease default: 2361e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#if DEBUG_FONT_RENDERER 2371e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease ALOGD("fitBitmap: unknown glyph format %x encountered", glyph.fMaskFormat); 2381e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease#endif 2391e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease return false; 2401e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease } 2411e546815bbb736c50679a8aefc25f48561026fc5Victoria Lease 242e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > getHeight()) { 2439f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return false; 2449f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 2459f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 2469f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t glyphW = glyph.fWidth + TEXTURE_BORDER_SIZE; 2479f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t glyphH = glyph.fHeight + TEXTURE_BORDER_SIZE; 2489b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 2499f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // roundedUpW equals glyphW to the next multiple of CACHE_BLOCK_ROUNDING_SIZE. 2509f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // This columns for glyphs that are close but not necessarily exactly the same size. It trades 2519f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // off the loss of a few pixels for some glyphs against the ability to store more glyphs 2529f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // of varying sizes in one block. 253e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy uint16_t roundedUpW = (glyphW + CACHE_BLOCK_ROUNDING_SIZE - 1) & -CACHE_BLOCK_ROUNDING_SIZE; 2549b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 255e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* cacheBlock = mCacheBlocks; 2569f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy while (cacheBlock) { 2579f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Store glyph in this block iff: it fits the block's remaining space and: 2589f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // it's the remainder space (mY == 0) or there's only enough height for this one glyph 2599f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // or it's within ROUNDING_SIZE of the block width 2609f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (roundedUpW <= cacheBlock->mWidth && glyphH <= cacheBlock->mHeight && 2619f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy (cacheBlock->mY == TEXTURE_BORDER_SIZE || 2629f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy (cacheBlock->mWidth - roundedUpW < CACHE_BLOCK_ROUNDING_SIZE))) { 2639f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (cacheBlock->mHeight - glyphH < glyphH) { 2649f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Only enough space for this glyph - don't bother rounding up the width 2659f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy roundedUpW = glyphW; 2669f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 2679b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 2689f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy *retOriginX = cacheBlock->mX; 2699f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy *retOriginY = cacheBlock->mY; 2709b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 2719f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // If this is the remainder space, create a new cache block for this column. Otherwise, 2729f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // adjust the info about this column. 2739f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy if (cacheBlock->mY == TEXTURE_BORDER_SIZE) { 2749f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy uint16_t oldX = cacheBlock->mX; 2759f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Adjust remainder space dimensions 2769f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mWidth -= roundedUpW; 2779f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mX += roundedUpW; 2789b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 279e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik if (getHeight() - glyphH >= glyphH) { 2809f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // There's enough height left over to create a new CacheBlock 281e43f785b7ff3fdf75f6d1c92282ebca6db191f2fRomain Guy CacheBlock* newBlock = new CacheBlock(oldX, glyphH + TEXTURE_BORDER_SIZE, 282e2bb380bc26749782c873e5488cfdf4e42b27346Chris Craik roundedUpW, getHeight() - glyphH - TEXTURE_BORDER_SIZE); 2839f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 2849f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d", 2859f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock, newBlock->mX, newBlock->mY, 2869f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy newBlock->mWidth, newBlock->mHeight); 2879f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 2889f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks = CacheBlock::insertBlock(mCacheBlocks, newBlock); 2899f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 2909f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } else { 2919f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // Insert into current column and adjust column dimensions 2929f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mY += glyphH; 2939f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mHeight -= glyphH; 2949f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 2959f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: Added to existing block: this, x, y, w, h = %p, %d, %d, %d, %d", 2969f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock, cacheBlock->mX, cacheBlock->mY, 2979f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock->mWidth, cacheBlock->mHeight); 2989f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 2999f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3009b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 301e6a15ee3d0c78eb3f2551d73a7d238c3d8d2f075Chris Craik if (cacheBlock->mHeight < std::min(glyphH, glyphW)) { 3029f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy // If remaining space in this block is too small to be useful, remove it 3039f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks = CacheBlock::removeBlock(mCacheBlocks, cacheBlock); 3049f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3059b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 3069f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mDirty = true; 307b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase const Rect r(*retOriginX - TEXTURE_BORDER_SIZE, *retOriginY - TEXTURE_BORDER_SIZE, 308b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase *retOriginX + glyphW, *retOriginY + glyphH); 309b92d8f7979c29c7c09932578a11b2f8d6eec1d90Chet Haase mDirtyRect.unionWith(r); 3109b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy mNumGlyphs++; 3119b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 3129f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 3139f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: current block list:"); 3149f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy mCacheBlocks->output(); 3159f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 3169b1204baf4740b4d443e72157dea98571cf84e1fRomain Guy 3179f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return true; 3189f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3199f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy cacheBlock = cacheBlock->mNext; 3209f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy } 3219f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#if DEBUG_FONT_RENDERER 3229f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy ALOGD("fitBitmap: returning false for glyph of size %d, %d", glyphW, glyphH); 3239f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy#endif 3249f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy return false; 3259f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy} 3269f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy 3279f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace uirenderer 3289f5dab3fc228fa11c32b483e6101ec086895a32bRomain Guy}; // namespace android 329