1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkPictureFlat_DEFINED 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPictureFlat_DEFINED 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11e2589aeebf321f6d3b5005c19740beacee964be7reed@google.com 1221830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com#include "SkBitmapHeap.h" 139e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com#include "SkChecksum.h" 149e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com#include "SkChunkAlloc.h" 158b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 168b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h" 189e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com#include "SkPicture.h" 199e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com#include "SkPtrRecorder.h" 209e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com#include "SkTDynamicHash.h" 21f4cc18726b52a76ba18c07a6490851c4a5e38835reed@google.com#include "SkTRefArray.h" 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comenum DrawType { 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com UNUSED, 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CLIP_PATH, 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CLIP_REGION, 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CLIP_RECT, 284ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com CLIP_RRECT, 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CONCAT, 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_BITMAP, 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_BITMAP_MATRIX, 32f0b5e1190af9807a027c0adba2f1380663c8e910reed@google.com DRAW_BITMAP_NINE, 337112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.com DRAW_BITMAP_RECT_TO_RECT, 342a98181f048c11f21f52fbd99f803f5fd6118261reed@google.com DRAW_CLEAR, 35cb60844b34766aad4151df5e87c144d4a57e9abereed@android.com DRAW_DATA, 364ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com DRAW_OVAL, 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_PAINT, 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_PATH, 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_PICTURE, 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_POINTS, 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_POS_TEXT, 429efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com DRAW_POS_TEXT_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_POS_TEXT_H, 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_RECT, 464ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com DRAW_RRECT, 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_SPRITE, 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_TEXT, 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_TEXT_ON_PATH, 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_TEXT_TOP_BOTTOM, // fast variant of DRAW_TEXT 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_VERTICES, 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com RESTORE, 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ROTATE, 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SAVE, 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SAVE_LAYER, 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SCALE, 576e073b9e2b70d6bbf8a06050fff1364827204f08reed@android.com SET_MATRIX, 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SKEW, 59ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com TRANSLATE, 60e4ce5b82627d7ef7cab34b808ff88dc208aef7bcrobertphillips@google.com NOOP, 610a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com BEGIN_COMMENT_GROUP, 620a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com COMMENT, 630a4805e33f8ddb445a2fd061462e715e1707f049robertphillips@google.com END_COMMENT_GROUP, 64ffacd3c56d73c03d3fe53b47a49ea6be2ca4748freed@google.com 65ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org // new ops -- feel free to re-alphabetize on next version bump 66ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org DRAW_DRRECT, 67210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org PUSH_CULL, 68210ae2a42613b9048e8e8c4096c5bf4fe2ddf838commit-bot@chromium.org POP_CULL, 69963137b75c0a1fe91f35e9826742f36309f5e65ddandov 70963137b75c0a1fe91f35e9826742f36309f5e65ddandov DRAW_PATCH, // could not add in aphabetical order 71d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed DRAW_PICTURE_MATRIX_PAINT, 72b7425173f96e93b090787e2386ba5f022b6c2869fmalita DRAW_TEXT_BLOB, 73ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org 74b7425173f96e93b090787e2386ba5f022b6c2869fmalita LAST_DRAWTYPE_ENUM = DRAW_TEXT_BLOB 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 77b8f9610ac6efb5426cb799ab9b1ab5d985b7b05arobertphillips@google.com// In the 'match' method, this constant will match any flavor of DRAW_BITMAP* 78b8f9610ac6efb5426cb799ab9b1ab5d985b7b05arobertphillips@google.comstatic const int kDRAW_BITMAP_FLAVOR = LAST_DRAWTYPE_ENUM+1; 79b8f9610ac6efb5426cb799ab9b1ab5d985b7b05arobertphillips@google.com 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comenum DrawVertexFlags { 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_VERTICES_HAS_TEXS = 0x01, 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DRAW_VERTICES_HAS_COLORS = 0x02, 8385e143c33c214e54187aa28146aa7666961a0d17reed@google.com DRAW_VERTICES_HAS_INDICES = 0x04, 8485e143c33c214e54187aa28146aa7666961a0d17reed@google.com DRAW_VERTICES_HAS_XFER = 0x08, 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8783ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com/////////////////////////////////////////////////////////////////////////////// 8883ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com// clipparams are packed in 5 bits 8983ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com// doAA:1 | regionOp:4 9083ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com 9183ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.comstatic inline uint32_t ClipParams_pack(SkRegion::Op op, bool doAA) { 9283ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com unsigned doAABit = doAA ? 1 : 0; 9383ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com return (doAABit << 4) | op; 9483ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com} 9583ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com 9683ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.comstatic inline SkRegion::Op ClipParams_unpackRegionOp(uint32_t packed) { 9783ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com return (SkRegion::Op)(packed & 0xF); 9883ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com} 9983ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com 10083ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.comstatic inline bool ClipParams_unpackDoAA(uint32_t packed) { 10183ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com return SkToBool((packed >> 4) & 1); 10283ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com} 10383ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com 10483ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com/////////////////////////////////////////////////////////////////////////////// 10583ab49556ffc83fd3b2c1142db264362d21e6b19reed@google.com 10621830d90096d2dccc4168d99a427e78035ce942adjsollen@google.comclass SkTypefacePlayback { 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 10821830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com SkTypefacePlayback(); 10921830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com virtual ~SkTypefacePlayback(); 110fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count() const { return fCount; } 112fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 113e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org void reset(const SkRefCntSet*); 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setCount(int count); 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt* set(int index, SkRefCnt*); 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1188b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org void setupBuffer(SkReadBuffer& buffer) const { 11921830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com buffer.setTypefaceArray((SkTypeface**)fArray, fCount); 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 121fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fCount; 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt** fArray; 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkFactoryPlayback { 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFactoryPlayback(int count) : fCount(count) { 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fArray = SkNEW_ARRAY(SkFlattenable::Factory, count); 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkFactoryPlayback() { 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE_ARRAY(fArray); 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 136fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFlattenable::Factory* base() const { return fArray; } 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1398b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org void setupBuffer(SkReadBuffer& buffer) const { 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer.setFactoryPlayback(fArray, fCount); 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 142fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fCount; 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFlattenable::Factory* fArray; 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 148d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com/////////////////////////////////////////////////////////////////////////////// 149d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// 150d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// 151d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// The following templated classes provide an efficient way to store and compare 152d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// objects that have been flattened (i.e. serialized in an ordered binary 153d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// format). 154d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// 155d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// SkFlatData: is a simple indexable container for the flattened data 156d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// which is agnostic to the type of data is is indexing. It is 157d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// also responsible for flattening/unflattening objects but 158fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org// details of that operation are hidden in the provided traits 1594dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com// SkFlatDictionary: is an abstract templated dictionary that maintains a 160ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org// searchable set of SkFlatData objects of type T. 1614dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com// SkFlatController: is an interface provided to SkFlatDictionary which handles 162ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org// allocation (and unallocation in some cases). It also holds 1631554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com// ref count recorders and the like. 164d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// 165fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org// NOTE: any class that wishes to be used in conjunction with SkFlatDictionary must subclass the 166fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org// dictionary and provide the necessary flattening traits. SkFlatController must also be 167fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org// implemented, or SkChunkFlatController can be used to use an SkChunkAllocator and never do 168fed2ab648341ec153ad2af746a31d368963171e4commit-bot@chromium.org// replacements. 169d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// 170d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com// 171d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com/////////////////////////////////////////////////////////////////////////////// 172d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com 1734dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.comclass SkFlatData; 1744dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com 1754dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.comclass SkFlatController : public SkRefCnt { 1764dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.compublic: 177a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com SK_DECLARE_INST_COUNT(SkFlatController) 178a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com 179a2bd2d12ad9504583e9311404fcd82b40df49d30commit-bot@chromium.org SkFlatController(uint32_t writeBufferFlags = 0); 1801554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com virtual ~SkFlatController(); 1814dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com /** 182ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org * Return a new block of memory for the SkFlatDictionary to use. 183ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org * This memory is owned by the controller and has the same lifetime unless you 184ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org * call unalloc(), in which case it may be freed early. 1854dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com */ 1864dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com virtual void* allocThrow(size_t bytes) = 0; 1874dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com 1884dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com /** 189ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org * Hint that this block, which was allocated with allocThrow, is no longer needed. 190ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org * The implementation may choose to free this memory any time beteween now and destruction. 1914dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com */ 1924dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com virtual void unalloc(void* ptr) = 0; 1930c3e5fe728ce4b8606819ee919a4b82f4d9efc85scroggo@google.com 1941554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com /** 19521830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com * Used during creation and unflattening of SkFlatData objects. If the 19621830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com * objects being flattened contain bitmaps they are stored in this heap 19721830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com * and the flattenable stores the index to the bitmap on the heap. 19821830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com * This should be set by the protected setBitmapHeap. 1991554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com */ 20021830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com SkBitmapHeap* getBitmapHeap() { return fBitmapHeap; } 2011554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com 2021554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com /** 2031554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * Used during creation of SkFlatData objects. If a typeface recorder is 2041554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * required to flatten the objects being flattened (i.e. for SkPaints), this 2051554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * should be set by the protected setTypefaceSet. 2061554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com */ 2071554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com SkRefCntSet* getTypefaceSet() { return fTypefaceSet; } 2081554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com 2091554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com /** 2101554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * Used during unflattening of the SkFlatData objects in the 2111554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * SkFlatDictionary. Needs to be set by the protected setTypefacePlayback 2121554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * and needs to be reset to the SkRefCntSet passed to setTypefaceSet. 2131554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com */ 2141554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com SkTypefacePlayback* getTypefacePlayback() { return fTypefacePlayback; } 2151554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com 2161554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com /** 2171554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * Optional factory recorder used during creation of SkFlatData objects. Set 2181554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * using the protected method setNamedFactorySet. 2191554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com */ 2201554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com SkNamedFactorySet* getNamedFactorySet() { return fFactorySet; } 2211554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com 222664fab1b3454faea01cbae2f1dc2777c5afb9998scroggo@google.com /** 223664fab1b3454faea01cbae2f1dc2777c5afb9998scroggo@google.com * Flags to use during creation of SkFlatData objects. Defaults to zero. 224664fab1b3454faea01cbae2f1dc2777c5afb9998scroggo@google.com */ 225664fab1b3454faea01cbae2f1dc2777c5afb9998scroggo@google.com uint32_t getWriteBufferFlags() { return fWriteBufferFlags; } 226664fab1b3454faea01cbae2f1dc2777c5afb9998scroggo@google.com 2271554360a9511d996e1618d19c163c810ef3f128cscroggo@google.comprotected: 2281554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com /** 22921830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com * Set an SkBitmapHeap to be used to store/read SkBitmaps. Ref counted. 2301554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com */ 23121830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com void setBitmapHeap(SkBitmapHeap*); 2321554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com 2331554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com /** 2341554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * Set an SkRefCntSet to be used to store SkTypefaces during flattening. Ref 2351554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * counted. 2361554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com */ 2371554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com void setTypefaceSet(SkRefCntSet*); 2381554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com 2391554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com /** 2401554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * Set an SkTypefacePlayback to be used to find references to SkTypefaces 2411554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * during unflattening. Should be reset to the set provided to 2421554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * setTypefaceSet. 2431554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com */ 2441554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com void setTypefacePlayback(SkTypefacePlayback*); 2451554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com 2461554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com /** 2471554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * Set an SkNamedFactorySet to be used to store Factorys and their 2481554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * corresponding names during flattening. Ref counted. Returns the same 2491554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com * set as a convenience. 2501554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com */ 2511554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com SkNamedFactorySet* setNamedFactorySet(SkNamedFactorySet*); 2521554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com 2531554360a9511d996e1618d19c163c810ef3f128cscroggo@google.comprivate: 25421830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com SkBitmapHeap* fBitmapHeap; 2551554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com SkRefCntSet* fTypefaceSet; 2561554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com SkTypefacePlayback* fTypefacePlayback; 2571554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com SkNamedFactorySet* fFactorySet; 258a2bd2d12ad9504583e9311404fcd82b40df49d30commit-bot@chromium.org const uint32_t fWriteBufferFlags; 259a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com 260a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com typedef SkRefCnt INHERITED; 2614dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com}; 2624dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkFlatData { 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2659e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // Flatten obj into an SkFlatData with this index. controller owns the SkFlatData*. 26607adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org template <typename Traits, typename T> 26707adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org static SkFlatData* Create(SkFlatController* controller, const T& obj, int index) { 26807adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org // A buffer of 256 bytes should fit most paints, regions, and matrices. 26907adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org uint32_t storage[64]; 270a2bd2d12ad9504583e9311404fcd82b40df49d30commit-bot@chromium.org SkWriteBuffer buffer(storage, sizeof(storage), controller->getWriteBufferFlags()); 27107adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org 27207adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org buffer.setBitmapHeap(controller->getBitmapHeap()); 27307adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org buffer.setTypefaceRecorder(controller->getTypefaceSet()); 27407adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org buffer.setNamedFactoryRecorder(controller->getNamedFactorySet()); 27507adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org 276186c0ccac25229534ec6fb84726043083304d4d1commit-bot@chromium.org Traits::Flatten(buffer, obj); 2778b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org size_t size = buffer.bytesWritten(); 27807adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org SkASSERT(SkIsAlign4(size)); 27907adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org 28007adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org // Allocate enough memory to hold SkFlatData struct and the flat data itself. 28107adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org size_t allocSize = sizeof(SkFlatData) + size; 28207adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org SkFlatData* result = (SkFlatData*) controller->allocThrow(allocSize); 28307adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org 28407adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org // Put the serialized contents into the data section of the new allocation. 28507adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org buffer.writeToMemory(result->data()); 28607adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org // Stamp the index, size and checksum in the header. 2877fa2a65c0cfc714364490cb715171461143024e0reed@google.com result->stampHeader(index, SkToS32(size)); 28807adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org return result; 28907adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org } 29007adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org 29107adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps and fonts if given 29207adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org template <typename Traits, typename T> 29307adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org void unflatten(T* result, 29421830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com SkBitmapHeap* bitmapHeap = NULL, 29507adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org SkTypefacePlayback* facePlayback = NULL) const { 2968b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org SkReadBuffer buffer(this->data(), fFlatSize); 29707adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org 29807adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org if (bitmapHeap) { 29907adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org buffer.setBitmapStorage(bitmapHeap); 30007adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org } 30107adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org if (facePlayback) { 30207adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org facePlayback->setupBuffer(buffer); 30307adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org } 30407adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org 305186c0ccac25229534ec6fb84726043083304d4d1commit-bot@chromium.org Traits::Unflatten(buffer, result); 30607adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org SkASSERT(fFlatSize == (int32_t)buffer.offset()); 30707adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org } 308d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com 3099e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // Do these contain the same data? Ignores index() and topBot(). 3109e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com bool operator==(const SkFlatData& that) const { 3119e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com if (this->checksum() != that.checksum() || this->flatSize() != that.flatSize()) { 3129e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com return false; 3139e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com } 3149e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com return memcmp(this->data(), that.data(), this->flatSize()) == 0; 315e2589aeebf321f6d3b5005c19740beacee964be7reed@google.com } 316e2589aeebf321f6d3b5005c19740beacee964be7reed@google.com 3179e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com int index() const { return fIndex; } 3189e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com const uint8_t* data() const { return (const uint8_t*)this + sizeof(*this); } 3199e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com size_t flatSize() const { return fFlatSize; } 3209e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com uint32_t checksum() const { return fChecksum; } 3219e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com 3229e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // Returns true if fTopBot[] has been recorded. 323148a3961b1c82a891012f2feb2a875cea2593170bungeman@google.com bool isTopBotWritten() const { 324148a3961b1c82a891012f2feb2a875cea2593170bungeman@google.com return !SkScalarIsNaN(fTopBot[0]); 3254595426b553c0c721f41aa14d598caa5d9940207reed@google.com } 3264595426b553c0c721f41aa14d598caa5d9940207reed@google.com 3274595426b553c0c721f41aa14d598caa5d9940207reed@google.com // Returns fTopBot array, so it can be passed to a routine to compute them. 3284595426b553c0c721f41aa14d598caa5d9940207reed@google.com // For efficiency, we assert that fTopBot have not been recorded yet. 329f3b1223e6d52b161dbc59a4119ba6a4161b10a54junov@chromium.org SkScalar* writableTopBot() const { 330148a3961b1c82a891012f2feb2a875cea2593170bungeman@google.com SkASSERT(!this->isTopBotWritten()); 3314595426b553c0c721f41aa14d598caa5d9940207reed@google.com return fTopBot; 3324595426b553c0c721f41aa14d598caa5d9940207reed@google.com } 3334595426b553c0c721f41aa14d598caa5d9940207reed@google.com 3349e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // Return the topbot[] after it has been recorded. 3354595426b553c0c721f41aa14d598caa5d9940207reed@google.com const SkScalar* topBot() const { 336148a3961b1c82a891012f2feb2a875cea2593170bungeman@google.com SkASSERT(this->isTopBotWritten()); 3374595426b553c0c721f41aa14d598caa5d9940207reed@google.com return fTopBot; 3384595426b553c0c721f41aa14d598caa5d9940207reed@google.com } 3394595426b553c0c721f41aa14d598caa5d9940207reed@google.com 340d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.comprivate: 34155bd940446506f8409f38271f2e4969e9b4f3991commit-bot@chromium.org struct HashTraits { 34255bd940446506f8409f38271f2e4969e9b4f3991commit-bot@chromium.org static const SkFlatData& GetKey(const SkFlatData& flat) { return flat; } 34355bd940446506f8409f38271f2e4969e9b4f3991commit-bot@chromium.org static uint32_t Hash(const SkFlatData& flat) { return flat.checksum(); } 34455bd940446506f8409f38271f2e4969e9b4f3991commit-bot@chromium.org }; 345b4ed0178d0f86da920b101a661cbe8fd4fda3ab3reed@google.com 3469e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com void setIndex(int index) { fIndex = index; } 3479e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com uint8_t* data() { return (uint8_t*)this + sizeof(*this); } 3484595426b553c0c721f41aa14d598caa5d9940207reed@google.com 3499e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // This assumes the payload flat data has already been written and does not modify it. 3509e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com void stampHeader(int index, int32_t size) { 3519e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com SkASSERT(SkIsAlign4(size)); 3529e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com fIndex = index; 3539e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com fFlatSize = size; 3549e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com fTopBot[0] = SK_ScalarNaN; // Mark as unwritten. 3559e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com fChecksum = SkChecksum::Compute((uint32_t*)this->data(), size); 356148a3961b1c82a891012f2feb2a875cea2593170bungeman@google.com } 357148a3961b1c82a891012f2feb2a875cea2593170bungeman@google.com 3589e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com int fIndex; 3599e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com int32_t fFlatSize; 360ef76060cbf36032a5bef9cd8d18138704349c3aejunov@chromium.org uint32_t fChecksum; 3619e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com mutable SkScalar fTopBot[2]; // Cache of FontMetrics fTop, fBottom. Starts as [NaN,?]. 3629e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // uint32_t flattenedData[] implicitly hangs off the end. 363ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org 36419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org template <typename T, typename Traits> friend class SkFlatDictionary; 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 36719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.orgtemplate <typename T, typename Traits> 368d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.comclass SkFlatDictionary { 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 37007adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org explicit SkFlatDictionary(SkFlatController* controller) 37107adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org : fController(SkRef(controller)) 372a2bd2d12ad9504583e9311404fcd82b40df49d30commit-bot@chromium.org , fScratch(controller->getWriteBufferFlags()) 373ff007e8ff358d9253de22291ebfd5fe7980512edcommit-bot@chromium.org , fReady(false) { 3749e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com this->reset(); 3759e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com } 3769e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com 3779e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com /** 3789e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com * Clears the dictionary of all entries. However, it does NOT free the 3799e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com * memory that was allocated for each entry (that's owned by controller). 3809e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com */ 3819e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com void reset() { 3829e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com fIndexedData.rewind(); 383d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com } 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3850f12e1fe42245a30c5dae856b600803aabbf137bskia.committer@gmail.com int count() const { 3866e83423f1653b97915b80e3adab477e68d2b2933commit-bot@chromium.org SkASSERT(fHash.count() == fIndexedData.count()); 387f85251c74d214ffc7dafa6d9fe23c1be0a2f3aa6commit-bot@chromium.org return fHash.count(); 3887d3451b1844d8f93892f032bc060212f17173214robertphillips@google.com } 389d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com 3909e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // For testing only. Index is zero-based. 3919e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com const SkFlatData* operator[](int index) { 3926e83423f1653b97915b80e3adab477e68d2b2933commit-bot@chromium.org return fIndexedData[index]; 393d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com } 394d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com 395d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com /** 3969e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com * Given an element of type T return its 1-based index in the dictionary. If 3979e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com * the element wasn't previously in the dictionary it is automatically 3989e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com * added. 3999e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com * 400d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com */ 4019e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com int find(const T& element) { 4029e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com return this->findAndReturnFlat(element)->index(); 40383ca337348c74dede813b2022943c25a337f32ebreed@google.com } 4044dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com 405d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com /** 4064dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com * Similar to find. Allows the caller to specify an SkFlatData to replace in 4074dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com * the case of an add. Also tells the caller whether a new SkFlatData was 4084dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com * added and whether the old one was replaced. The parameters added and 4094dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com * replaced are required to be non-NULL. Rather than returning the index of 4104dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com * the entry in the dictionary, it returns the actual SkFlatData. 411d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com */ 4124dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com const SkFlatData* findAndReplace(const T& element, 4139e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com const SkFlatData* toReplace, 4149e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com bool* added, 4154dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com bool* replaced) { 4164dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com SkASSERT(added != NULL && replaced != NULL); 4179e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com 4189e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com const int oldCount = this->count(); 4199e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com SkFlatData* flat = this->findAndReturnMutableFlat(element); 4209e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com *added = this->count() > oldCount; 4219e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com 4229e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // If we don't want to replace anything, we're done. 4239e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com if (!*added || toReplace == NULL) { 4249e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com *replaced = false; 4259e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com return flat; 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 427e2589aeebf321f6d3b5005c19740beacee964be7reed@google.com 4289e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // If we don't have the thing to replace, we're done. 4299e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com const SkFlatData* found = fHash.find(*toReplace); 4309e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com if (found == NULL) { 4319e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com *replaced = false; 4329e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com return flat; 4339e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com } 4349e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com 435f85251c74d214ffc7dafa6d9fe23c1be0a2f3aa6commit-bot@chromium.org // findAndReturnMutableFlat put flat at the back. Swap it into found->index() instead. 4366e83423f1653b97915b80e3adab477e68d2b2933commit-bot@chromium.org // indices in SkFlatData are 1-based, while fIndexedData is 0-based. Watch out! 437f85251c74d214ffc7dafa6d9fe23c1be0a2f3aa6commit-bot@chromium.org SkASSERT(flat->index() == this->count()); 4389e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com flat->setIndex(found->index()); 4396e83423f1653b97915b80e3adab477e68d2b2933commit-bot@chromium.org fIndexedData.removeShuffle(found->index()-1); 4406e83423f1653b97915b80e3adab477e68d2b2933commit-bot@chromium.org SkASSERT(flat == fIndexedData[found->index()-1]); 4419e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com 4429e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // findAndReturnMutableFlat already called fHash.add(), so we just clean up the old entry. 4439e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com fHash.remove(*found); 4449e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com fController->unalloc((void*)found); 4459e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com SkASSERT(this->count() == oldCount); 4469e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com 4479e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com *replaced = true; 4489e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com return flat; 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 450d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com 451f4cc18726b52a76ba18c07a6490851c4a5e38835reed@google.com /** 452f4cc18726b52a76ba18c07a6490851c4a5e38835reed@google.com * Unflatten the objects and return them in SkTRefArray, or return NULL 4539e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com * if there no objects. Caller takes ownership of result. 454f4cc18726b52a76ba18c07a6490851c4a5e38835reed@google.com */ 4551554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com SkTRefArray<T>* unflattenToArray() const { 4569e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com const int count = this->count(); 4579e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com if (count == 0) { 4589e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com return NULL; 4599e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com } 4609e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com SkTRefArray<T>* array = SkTRefArray<T>::Create(count); 4619e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com for (int i = 0; i < count; i++) { 4626e83423f1653b97915b80e3adab477e68d2b2933commit-bot@chromium.org this->unflatten(&array->writableAt(i), fIndexedData[i]); 463f4cc18726b52a76ba18c07a6490851c4a5e38835reed@google.com } 464f4cc18726b52a76ba18c07a6490851c4a5e38835reed@google.com return array; 465f4cc18726b52a76ba18c07a6490851c4a5e38835reed@google.com } 466f4cc18726b52a76ba18c07a6490851c4a5e38835reed@google.com 467e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com /** 4689e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com * Unflatten the specific object at the given index. 4699e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com * Caller takes ownership of the result. 470e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com */ 471e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com T* unflatten(int index) const { 4726e83423f1653b97915b80e3adab477e68d2b2933commit-bot@chromium.org // index is 1-based, while fIndexedData is 0-based. 4736e83423f1653b97915b80e3adab477e68d2b2933commit-bot@chromium.org const SkFlatData* element = fIndexedData[index-1]; 4747d3451b1844d8f93892f032bc060212f17173214robertphillips@google.com SkASSERT(index == element->index()); 475e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com 4767d3451b1844d8f93892f032bc060212f17173214robertphillips@google.com T* dst = new T; 4777d3451b1844d8f93892f032bc060212f17173214robertphillips@google.com this->unflatten(dst, element); 4787d3451b1844d8f93892f032bc060212f17173214robertphillips@google.com return dst; 479e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com } 480e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com 4819e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com /** 4829e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com * Find or insert a flattened version of element into the dictionary. 4839e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com * Caller does not take ownership of the result. This will not return NULL. 4849e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com */ 485664fab1b3454faea01cbae2f1dc2777c5afb9998scroggo@google.com const SkFlatData* findAndReturnFlat(const T& element) { 4869e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com return this->findAndReturnMutableFlat(element); 4874dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com } 488fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 489f3b1223e6d52b161dbc59a4119ba6a4161b10a54junov@chromium.orgprivate: 49019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org // We have to delay fScratch's initialization until its first use; fController might not 49119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org // be fully set up by the time we get it in the constructor. 492ff007e8ff358d9253de22291ebfd5fe7980512edcommit-bot@chromium.org void lazyInit() { 493ff007e8ff358d9253de22291ebfd5fe7980512edcommit-bot@chromium.org if (fReady) { 494ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org return; 495ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org } 496ff007e8ff358d9253de22291ebfd5fe7980512edcommit-bot@chromium.org 497ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org // Without a bitmap heap, we'll flatten bitmaps into paints. That's never what you want. 498ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org SkASSERT(fController->getBitmapHeap() != NULL); 49919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org fScratch.setBitmapHeap(fController->getBitmapHeap()); 50019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org fScratch.setTypefaceRecorder(fController->getTypefaceSet()); 50119382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org fScratch.setNamedFactoryRecorder(fController->getNamedFactorySet()); 502ff007e8ff358d9253de22291ebfd5fe7980512edcommit-bot@chromium.org fReady = true; 503ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org } 504ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org 5059e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // As findAndReturnFlat, but returns a mutable pointer for internal use. 5069e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com SkFlatData* findAndReturnMutableFlat(const T& element) { 5079e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // Only valid until the next call to resetScratch(). 508f85251c74d214ffc7dafa6d9fe23c1be0a2f3aa6commit-bot@chromium.org const SkFlatData& scratch = this->resetScratch(element, this->count()+1); 5099e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com 5109e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com SkFlatData* candidate = fHash.find(scratch); 511d7e0fbef5d6c7c63b312a5ea1955a9802ad4302fcommit-bot@chromium.org if (candidate != NULL) { 512d7e0fbef5d6c7c63b312a5ea1955a9802ad4302fcommit-bot@chromium.org return candidate; 513d7e0fbef5d6c7c63b312a5ea1955a9802ad4302fcommit-bot@chromium.org } 5149e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com 5159e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com SkFlatData* detached = this->detachScratch(); 5169e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com fHash.add(detached); 517f85251c74d214ffc7dafa6d9fe23c1be0a2f3aa6commit-bot@chromium.org *fIndexedData.append() = detached; 518f85251c74d214ffc7dafa6d9fe23c1be0a2f3aa6commit-bot@chromium.org SkASSERT(fIndexedData.top()->index() == this->count()); 5199e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com return detached; 5209e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com } 5219e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com 522ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org // This reference is valid only until the next call to resetScratch() or detachScratch(). 523ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org const SkFlatData& resetScratch(const T& element, int index) { 524ff007e8ff358d9253de22291ebfd5fe7980512edcommit-bot@chromium.org this->lazyInit(); 525ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org 52619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org // Layout of fScratch: [ SkFlatData header, 20 bytes ] [ data ..., 4-byte aligned ] 52719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org fScratch.reset(); 52819382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org fScratch.reserve(sizeof(SkFlatData)); 529186c0ccac25229534ec6fb84726043083304d4d1commit-bot@chromium.org Traits::Flatten(fScratch, element); 53019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org const size_t dataSize = fScratch.bytesWritten() - sizeof(SkFlatData); 531ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org 53219382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org // Reinterpret data in fScratch as an SkFlatData. 53319382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArray(); 53419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org SkASSERT(scratch != NULL); 535dcecb168968ca136c7fb9e8b444bec56f19af70ccommit-bot@chromium.org scratch->stampHeader(index, SkToS32(dataSize)); 53619382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org return *scratch; 537ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org } 538ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org 539ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org // This result is owned by fController and lives as long as it does (unless unalloc'd). 540ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org SkFlatData* detachScratch() { 541ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org // Allocate a new SkFlatData exactly big enough to hold our current scratch. 542ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org // We use the controller for this allocation to extend the allocation's lifetime and allow 543ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org // the controller to do whatever memory management it wants. 54419382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org SkFlatData* detached = (SkFlatData*)fController->allocThrow(fScratch.bytesWritten()); 545ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org 5469e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // Copy scratch into the new SkFlatData. 54719382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArray(); 54819382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org SkASSERT(scratch != NULL); 54919382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org memcpy(detached, scratch, fScratch.bytesWritten()); 550ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org 551ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org // We can now reuse fScratch, and detached will live until fController dies. 552ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org return detached; 553ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org } 554ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org 555e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com void unflatten(T* dst, const SkFlatData* element) const { 55607adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org element->unflatten<Traits>(dst, 55707adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org fController->getBitmapHeap(), 55807adb6359fd137ccb633b2c64ee2287c8edfd701commit-bot@chromium.org fController->getTypefacePlayback()); 559e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com } 560e37ad358b7219e45323a79c484ea67a5c59f34c2robertphillips@google.com 5619e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // All SkFlatData* stored in fIndexedData and fHash are owned by the controller. 562ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org SkAutoTUnref<SkFlatController> fController; 5638b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org SkWriteBuffer fScratch; 564ff007e8ff358d9253de22291ebfd5fe7980512edcommit-bot@chromium.org bool fReady; 5657d3451b1844d8f93892f032bc060212f17173214robertphillips@google.com 5666e83423f1653b97915b80e3adab477e68d2b2933commit-bot@chromium.org // For index -> SkFlatData. 0-based, while all indices in the API are 1-based. Careful! 5677d3451b1844d8f93892f032bc060212f17173214robertphillips@google.com SkTDArray<const SkFlatData*> fIndexedData; 5689e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com 5699e3074e968f52eb02fdc329bb9fbe7be5e674268mtklein@google.com // For SkFlatData -> cached SkFlatData, which has index(). 57055bd940446506f8409f38271f2e4969e9b4f3991commit-bot@chromium.org SkTDynamicHash<SkFlatData, SkFlatData, SkFlatData::HashTraits> fHash; 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 573aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.orgtypedef SkFlatDictionary<SkPaint, SkPaint::FlatteningTraits> SkPaintDictionary; 574d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com 5754dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.comclass SkChunkFlatController : public SkFlatController { 5764dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.compublic: 5774dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com SkChunkFlatController(size_t minSize) 5781554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com : fHeap(minSize) 57946724e457e9df0dd4fbafca4746621a42bd37ac3commit-bot@chromium.org , fTypefaceSet(SkNEW(SkRefCntSet)) 58046724e457e9df0dd4fbafca4746621a42bd37ac3commit-bot@chromium.org , fLastAllocated(NULL) { 5811554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com this->setTypefaceSet(fTypefaceSet); 5821554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com this->setTypefacePlayback(&fTypefacePlayback); 5831554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com } 5844dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com 5851554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com virtual void* allocThrow(size_t bytes) SK_OVERRIDE { 586ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org fLastAllocated = fHeap.allocThrow(bytes); 587ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org return fLastAllocated; 5884dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com } 5894dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com 5901554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com virtual void unalloc(void* ptr) SK_OVERRIDE { 591ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org // fHeap can only free a pointer if it was the last one allocated. Otherwise, we'll just 592ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org // have to wait until fHeap is destroyed. 593ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org if (ptr == fLastAllocated) (void)fHeap.unalloc(ptr); 5944dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com } 5951554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com 5961554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com void setupPlaybacks() const { 597ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org fTypefacePlayback.reset(fTypefaceSet.get()); 5981554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com } 5991554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com 60021830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com void setBitmapStorage(SkBitmapHeap* heap) { 60121830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com this->setBitmapHeap(heap); 60221830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com } 60321830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com 6044dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.comprivate: 6051554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com SkChunkAlloc fHeap; 606ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org SkAutoTUnref<SkRefCntSet> fTypefaceSet; 607ff36a1d07f23f2b7feddaba110d448073a96f83ccommit-bot@chromium.org void* fLastAllocated; 6081554360a9511d996e1618d19c163c810ef3f128cscroggo@google.com mutable SkTypefacePlayback fTypefacePlayback; 6094dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com}; 6104dffc596aa9fabd3104e66bc1f9957e8de4cb65dscroggo@google.com 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 612