1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use crate::display_item::*; 6 use crate::display_list::*; 7 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; 8 9 #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] 10 pub struct CachedDisplayItem { 11 item: DisplayItem, 12 data: Vec<u8>, 13 } 14 15 impl CachedDisplayItem { display_item(&self) -> &DisplayItem16 pub fn display_item(&self) -> &DisplayItem { 17 &self.item 18 } 19 data_as_item_range<T>(&self) -> ItemRange<T>20 pub fn data_as_item_range<T>(&self) -> ItemRange<T> { 21 ItemRange::new(&self.data) 22 } 23 } 24 25 impl MallocSizeOf for CachedDisplayItem { size_of(&self, ops: &mut MallocSizeOfOps) -> usize26 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { 27 self.data.size_of(ops) 28 } 29 } 30 31 impl From<DisplayItemRef<'_, '_>> for CachedDisplayItem { from(item_ref: DisplayItemRef) -> Self32 fn from(item_ref: DisplayItemRef) -> Self { 33 let item = item_ref.item(); 34 35 match item { 36 DisplayItem::Text(..) => CachedDisplayItem { 37 item: *item, 38 data: item_ref.glyphs().bytes().to_vec(), 39 }, 40 _ => CachedDisplayItem { 41 item: *item, 42 data: Vec::new(), 43 }, 44 } 45 } 46 } 47 48 #[derive(Clone, Deserialize, MallocSizeOf, Serialize)] 49 struct CacheEntry { 50 items: Vec<CachedDisplayItem>, 51 occupied: bool, 52 } 53 54 #[derive(Clone, Deserialize, MallocSizeOf, Serialize)] 55 pub struct DisplayItemCache { 56 entries: Vec<CacheEntry>, 57 } 58 59 impl DisplayItemCache { add_item(&mut self, key: ItemKey, item: CachedDisplayItem)60 fn add_item(&mut self, key: ItemKey, item: CachedDisplayItem) { 61 let mut entry = &mut self.entries[key as usize]; 62 entry.items.push(item); 63 entry.occupied = true; 64 } 65 clear_entry(&mut self, key: ItemKey)66 fn clear_entry(&mut self, key: ItemKey) { 67 let mut entry = &mut self.entries[key as usize]; 68 entry.items.clear(); 69 entry.occupied = false; 70 } 71 grow_if_needed(&mut self, capacity: usize)72 fn grow_if_needed(&mut self, capacity: usize) { 73 if capacity > self.entries.len() { 74 self.entries.resize_with(capacity, || CacheEntry { 75 items: Vec::new(), 76 occupied: false, 77 }); 78 } 79 } 80 get_items(&self, key: ItemKey) -> &[CachedDisplayItem]81 pub fn get_items(&self, key: ItemKey) -> &[CachedDisplayItem] { 82 let entry = &self.entries[key as usize]; 83 debug_assert!(entry.occupied); 84 entry.items.as_slice() 85 } 86 new() -> Self87 pub fn new() -> Self { 88 Self { 89 entries: Vec::new(), 90 } 91 } 92 update(&mut self, display_list: &BuiltDisplayList)93 pub fn update(&mut self, display_list: &BuiltDisplayList) { 94 self.grow_if_needed(display_list.cache_size()); 95 96 let mut iter = display_list.extra_data_iter(); 97 let mut current_key: Option<ItemKey> = None; 98 loop { 99 let item = match iter.next() { 100 Some(item) => item, 101 None => break, 102 }; 103 104 if let DisplayItem::RetainedItems(key) = item.item() { 105 current_key = Some(*key); 106 self.clear_entry(*key); 107 continue; 108 } 109 110 let key = current_key.expect("Missing RetainedItems marker"); 111 let cached_item = CachedDisplayItem::from(item); 112 self.add_item(key, cached_item); 113 } 114 } 115 } 116