tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

display_item_cache.rs (3092B)


      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 {
     16    pub fn display_item(&self) -> &DisplayItem {
     17        &self.item
     18    }
     19 
     20    pub fn data_as_item_range<T>(&self) -> ItemRange<T> {
     21        ItemRange::new(&self.data)
     22    }
     23 }
     24 
     25 impl MallocSizeOf for CachedDisplayItem {
     26    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
     27        self.data.size_of(ops)
     28    }
     29 }
     30 
     31 impl From<DisplayItemRef<'_, '_>> for CachedDisplayItem {
     32    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 {
     60    fn add_item(&mut self, key: ItemKey, item: CachedDisplayItem) {
     61        let entry = &mut self.entries[key as usize];
     62        entry.items.push(item);
     63        entry.occupied = true;
     64    }
     65 
     66    fn clear_entry(&mut self, key: ItemKey) {
     67        let entry = &mut self.entries[key as usize];
     68        entry.items.clear();
     69        entry.occupied = false;
     70    }
     71 
     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 
     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 
     87    pub fn new() -> Self {
     88        Self {
     89            entries: Vec::new(),
     90        }
     91    }
     92 
     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        while let Some(item) = iter.next() {
     99            if let DisplayItem::RetainedItems(key) = item.item() {
    100                current_key = Some(*key);
    101                self.clear_entry(*key);
    102                continue;
    103            }
    104 
    105            let key = current_key.expect("Missing RetainedItems marker");
    106            let cached_item = CachedDisplayItem::from(item);
    107            self.add_item(key, cached_item);
    108        }
    109    }
    110 }