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.cache_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