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 euclid::SideOffsets2D;
6 use peek_poke::{ensure_red_zone, peek_from_slice, poke_extend_vec};
7 use peek_poke::{poke_inplace_slice, poke_into_vec, Poke};
8 #[cfg(feature = "deserialize")]
9 use serde::de::Deserializer;
10 #[cfg(feature = "serialize")]
11 use serde::ser::{Serializer, SerializeSeq};
12 use serde::{Deserialize, Serialize};
13 use std::io::Write;
14 use std::marker::PhantomData;
15 use std::ops::Range;
16 use std::mem;
17 use std::collections::HashMap;
18 use time::precise_time_ns;
19 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
20 // local imports
21 use crate::display_item as di;
22 use crate::display_item_cache::*;
23 use crate::api::{PipelineId, PropertyBinding};
24 use crate::gradient_builder::GradientBuilder;
25 use crate::color::ColorF;
26 use crate::font::{FontInstanceKey, GlyphInstance, GlyphOptions};
27 use crate::image::{ColorDepth, ImageKey};
28 use crate::units::*;
29 
30 
31 // We don't want to push a long text-run. If a text-run is too long, split it into several parts.
32 // This needs to be set to (renderer::MAX_VERTEX_TEXTURE_WIDTH - VECS_PER_TEXT_RUN) * 2
33 pub const MAX_TEXT_RUN_LENGTH: usize = 2040;
34 
35 // See ROOT_REFERENCE_FRAME_SPATIAL_ID and ROOT_SCROLL_NODE_SPATIAL_ID
36 // TODO(mrobinson): It would be a good idea to eliminate the root scroll frame which is only
37 // used by Servo.
38 const FIRST_SPATIAL_NODE_INDEX: usize = 2;
39 
40 // See ROOT_SCROLL_NODE_SPATIAL_ID
41 const FIRST_CLIP_NODE_INDEX: usize = 1;
42 
43 #[repr(C)]
44 #[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
45 pub struct ItemRange<'a, T> {
46     bytes: &'a [u8],
47     _boo: PhantomData<T>,
48 }
49 
50 impl<'a, T> Copy for ItemRange<'a, T> {}
51 impl<'a, T> Clone for ItemRange<'a, T> {
clone(&self) -> Self52     fn clone(&self) -> Self {
53         *self
54     }
55 }
56 
57 impl<'a, T> Default for ItemRange<'a, T> {
default() -> Self58     fn default() -> Self {
59         ItemRange {
60             bytes: Default::default(),
61             _boo: PhantomData,
62         }
63     }
64 }
65 
66 impl<'a, T> ItemRange<'a, T> {
new(bytes: &'a [u8]) -> Self67     pub fn new(bytes: &'a [u8]) -> Self {
68         Self {
69             bytes,
70             _boo: PhantomData
71         }
72     }
73 
is_empty(&self) -> bool74     pub fn is_empty(&self) -> bool {
75         // Nothing more than space for a length (0).
76         self.bytes.len() <= mem::size_of::<usize>()
77     }
78 
bytes(&self) -> &[u8]79     pub fn bytes(&self) -> &[u8] {
80         &self.bytes
81     }
82 }
83 
84 impl<'a, T: Default> ItemRange<'a, T> {
iter(&self) -> AuxIter<'a, T>85     pub fn iter(&self) -> AuxIter<'a, T> {
86         AuxIter::new(T::default(), self.bytes)
87     }
88 }
89 
90 impl<'a, T> IntoIterator for ItemRange<'a, T>
91 where
92     T: Copy + Default + peek_poke::Peek,
93 {
94     type Item = T;
95     type IntoIter = AuxIter<'a, T>;
into_iter(self) -> Self::IntoIter96     fn into_iter(self) -> Self::IntoIter {
97         self.iter()
98     }
99 }
100 
101 #[derive(Copy, Clone)]
102 pub struct TempFilterData<'a> {
103     pub func_types: ItemRange<'a, di::ComponentTransferFuncType>,
104     pub r_values: ItemRange<'a, f32>,
105     pub g_values: ItemRange<'a, f32>,
106     pub b_values: ItemRange<'a, f32>,
107     pub a_values: ItemRange<'a, f32>,
108 }
109 
110 /// A display list.
111 #[derive(Clone, Default)]
112 pub struct BuiltDisplayList {
113     /// Serde encoded bytes. Mostly DisplayItems, but some mixed in slices.
114     data: Vec<u8>,
115     descriptor: BuiltDisplayListDescriptor,
116 }
117 
118 /// Describes the memory layout of a display list.
119 ///
120 /// A display list consists of some number of display list items, followed by a number of display
121 /// items.
122 #[repr(C)]
123 #[derive(Copy, Clone, Default, Deserialize, Serialize)]
124 pub struct BuiltDisplayListDescriptor {
125     /// The first IPC time stamp: before any work has been done
126     builder_start_time: u64,
127     /// The second IPC time stamp: after serialization
128     builder_finish_time: u64,
129     /// The third IPC time stamp: just before sending
130     send_start_time: u64,
131     /// The amount of clipping nodes created while building this display list.
132     total_clip_nodes: usize,
133     /// The amount of spatial nodes created while building this display list.
134     total_spatial_nodes: usize,
135     /// The size of the cache for this display list.
136     cache_size: usize,
137     /// The offset for additional display list data.
138     extra_data_offset: usize,
139 }
140 
141 #[derive(Clone)]
142 pub struct DisplayListWithCache {
143     display_list: BuiltDisplayList,
144     cache: DisplayItemCache,
145 }
146 
147 impl DisplayListWithCache {
iter(&self) -> BuiltDisplayListIter148     pub fn iter(&self) -> BuiltDisplayListIter {
149         self.display_list.iter_with_cache(&self.cache)
150     }
151 
new_from_list(display_list: BuiltDisplayList) -> Self152     pub fn new_from_list(display_list: BuiltDisplayList) -> Self {
153         let mut cache = DisplayItemCache::new();
154         cache.update(&display_list);
155 
156         DisplayListWithCache {
157             display_list,
158             cache
159         }
160     }
161 
update(&mut self, display_list: BuiltDisplayList)162     pub fn update(&mut self, display_list: BuiltDisplayList) {
163         self.cache.update(&display_list);
164         self.display_list = display_list;
165     }
166 
descriptor(&self) -> &BuiltDisplayListDescriptor167     pub fn descriptor(&self) -> &BuiltDisplayListDescriptor {
168         self.display_list.descriptor()
169     }
170 
data(&self) -> &[u8]171     pub fn data(&self) -> &[u8] {
172         self.display_list.data()
173     }
174 }
175 
176 impl MallocSizeOf for DisplayListWithCache {
size_of(&self, ops: &mut MallocSizeOfOps) -> usize177     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
178         self.display_list.data.size_of(ops) + self.cache.size_of(ops)
179     }
180 }
181 
182 #[cfg(feature = "serialize")]
183 impl Serialize for DisplayListWithCache {
serialize<S: Serializer>( &self, serializer: S ) -> Result<S::Ok, S::Error>184     fn serialize<S: Serializer>(
185         &self,
186         serializer: S
187     ) -> Result<S::Ok, S::Error> {
188         BuiltDisplayList::serialize_with_iterator(serializer, self.iter())
189     }
190 }
191 
192 #[cfg(feature = "deserialize")]
193 impl<'de> Deserialize<'de> for DisplayListWithCache {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,194     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
195     where
196         D: Deserializer<'de>,
197     {
198         let display_list = BuiltDisplayList::deserialize(deserializer)?;
199         let cache = DisplayItemCache::new();
200 
201         Ok(DisplayListWithCache {
202             display_list,
203             cache,
204         })
205     }
206 }
207 
208 impl BuiltDisplayListDescriptor {}
209 
210 pub struct BuiltDisplayListIter<'a> {
211     list: &'a BuiltDisplayList,
212     data: &'a [u8],
213     cache: Option<&'a DisplayItemCache>,
214     pending_items: std::slice::Iter<'a, CachedDisplayItem>,
215     cur_cached_item: Option<&'a CachedDisplayItem>,
216     cur_item: di::DisplayItem,
217     cur_stops: ItemRange<'a, di::GradientStop>,
218     cur_glyphs: ItemRange<'a, GlyphInstance>,
219     cur_filters: ItemRange<'a, di::FilterOp>,
220     cur_filter_data: Vec<TempFilterData<'a>>,
221     cur_filter_primitives: ItemRange<'a, di::FilterPrimitive>,
222     cur_clip_chain_items: ItemRange<'a, di::ClipId>,
223     cur_complex_clip: ItemRange<'a, di::ComplexClipRegion>,
224     peeking: Peek,
225     /// Should just be initialized but never populated in release builds
226     debug_stats: DebugStats,
227 }
228 
229 /// Internal info used for more detailed analysis of serialized display lists
230 #[allow(dead_code)]
231 struct DebugStats {
232     /// Last address in the buffer we pointed to, for computing serialized sizes
233     last_addr: usize,
234     stats: HashMap<&'static str, ItemStats>,
235 }
236 
237 impl DebugStats {
238     #[cfg(feature = "display_list_stats")]
_update_entry(&mut self, name: &'static str, item_count: usize, byte_count: usize)239     fn _update_entry(&mut self, name: &'static str, item_count: usize, byte_count: usize) {
240         let entry = self.stats.entry(name).or_default();
241         entry.total_count += item_count;
242         entry.num_bytes += byte_count;
243     }
244 
245     /// Computes the number of bytes we've processed since we last called
246     /// this method, so we can compute the serialized size of a display item.
247     #[cfg(feature = "display_list_stats")]
debug_num_bytes(&mut self, data: &[u8]) -> usize248     fn debug_num_bytes(&mut self, data: &[u8]) -> usize {
249         let old_addr = self.last_addr;
250         let new_addr = data.as_ptr() as usize;
251         let delta = new_addr - old_addr;
252         self.last_addr = new_addr;
253 
254         delta
255     }
256 
257     /// Logs stats for the last deserialized display item
258     #[cfg(feature = "display_list_stats")]
log_item(&mut self, data: &[u8], item: &di::DisplayItem)259     fn log_item(&mut self, data: &[u8], item: &di::DisplayItem) {
260         let num_bytes = self.debug_num_bytes(data);
261         self._update_entry(item.debug_name(), 1, num_bytes);
262     }
263 
264     /// Logs the stats for the given serialized slice
265     #[cfg(feature = "display_list_stats")]
log_slice<T: Peek>( &mut self, slice_name: &'static str, range: &ItemRange<T>, )266     fn log_slice<T: Peek>(
267         &mut self,
268         slice_name: &'static str,
269         range: &ItemRange<T>,
270     ) {
271         // Run this so log_item_stats is accurate, but ignore its result
272         // because log_slice_stats may be called after multiple slices have been
273         // processed, and the `range` has everything we need.
274         self.last_addr = range.bytes.as_ptr() as usize + range.bytes.len();
275 
276         self._update_entry(slice_name, range.iter().len(), range.bytes.len());
277     }
278 
279     #[cfg(not(feature = "display_list_stats"))]
log_slice<T>(&mut self, _slice_name: &str, _range: &ItemRange<T>)280     fn log_slice<T>(&mut self, _slice_name: &str, _range: &ItemRange<T>) {
281         /* no-op */
282     }
283 }
284 
285 /// Stats for an individual item
286 #[derive(Copy, Clone, Debug, Default)]
287 pub struct ItemStats {
288     /// How many instances of this kind of item we deserialized
289     pub total_count: usize,
290     /// How many bytes we processed for this kind of item
291     pub num_bytes: usize,
292 }
293 
294 pub struct DisplayItemRef<'a: 'b, 'b> {
295     iter: &'b BuiltDisplayListIter<'a>,
296 }
297 
298 // Some of these might just become ItemRanges
299 impl<'a, 'b> DisplayItemRef<'a, 'b> {
display_list(&self) -> &BuiltDisplayList300     pub fn display_list(&self) -> &BuiltDisplayList {
301         self.iter.display_list()
302     }
303 
304     // Creates a new iterator where this element's iterator is, to hack around borrowck.
sub_iter(&self) -> BuiltDisplayListIter<'a>305     pub fn sub_iter(&self) -> BuiltDisplayListIter<'a> {
306         self.iter.sub_iter()
307     }
308 
item(&self) -> &di::DisplayItem309     pub fn item(&self) -> &di::DisplayItem {
310        self.iter.current_item()
311     }
312 
clip_chain_items(&self) -> ItemRange<di::ClipId>313     pub fn clip_chain_items(&self) -> ItemRange<di::ClipId> {
314         self.iter.cur_clip_chain_items
315     }
316 
complex_clip(&self) -> ItemRange<di::ComplexClipRegion>317     pub fn complex_clip(&self) -> ItemRange<di::ComplexClipRegion> {
318         self.iter.cur_complex_clip
319     }
320 
glyphs(&self) -> ItemRange<GlyphInstance>321     pub fn glyphs(&self) -> ItemRange<GlyphInstance> {
322         self.iter.glyphs()
323     }
324 
gradient_stops(&self) -> ItemRange<di::GradientStop>325     pub fn gradient_stops(&self) -> ItemRange<di::GradientStop> {
326         self.iter.gradient_stops()
327     }
328 
filters(&self) -> ItemRange<di::FilterOp>329     pub fn filters(&self) -> ItemRange<di::FilterOp> {
330         self.iter.cur_filters
331     }
332 
filter_datas(&self) -> &Vec<TempFilterData>333     pub fn filter_datas(&self) -> &Vec<TempFilterData> {
334         &self.iter.cur_filter_data
335     }
336 
filter_primitives(&self) -> ItemRange<di::FilterPrimitive>337     pub fn filter_primitives(&self) -> ItemRange<di::FilterPrimitive> {
338         self.iter.cur_filter_primitives
339     }
340 }
341 
342 #[derive(PartialEq)]
343 enum Peek {
344     StartPeeking,
345     IsPeeking,
346     NotPeeking,
347 }
348 
349 #[derive(Clone)]
350 pub struct AuxIter<'a, T> {
351     item: T,
352     data: &'a [u8],
353     size: usize,
354 //    _boo: PhantomData<T>,
355 }
356 
357 impl BuiltDisplayList {
from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> Self358     pub fn from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> Self {
359         BuiltDisplayList { data, descriptor }
360     }
361 
into_data(self) -> (Vec<u8>, BuiltDisplayListDescriptor)362     pub fn into_data(self) -> (Vec<u8>, BuiltDisplayListDescriptor) {
363         (self.data, self.descriptor)
364     }
365 
data(&self) -> &[u8]366     pub fn data(&self) -> &[u8] {
367         &self.data[..]
368     }
369 
item_slice(&self) -> &[u8]370     pub fn item_slice(&self) -> &[u8] {
371         &self.data[..self.descriptor.extra_data_offset]
372     }
373 
extra_slice(&self) -> &[u8]374     pub fn extra_slice(&self) -> &[u8] {
375         &self.data[self.descriptor.extra_data_offset..]
376     }
377 
descriptor(&self) -> &BuiltDisplayListDescriptor378     pub fn descriptor(&self) -> &BuiltDisplayListDescriptor {
379         &self.descriptor
380     }
381 
set_send_time_ns(&mut self, time: u64)382     pub fn set_send_time_ns(&mut self, time: u64) {
383         self.descriptor.send_start_time = time;
384     }
385 
times(&self) -> (u64, u64, u64)386     pub fn times(&self) -> (u64, u64, u64) {
387         (
388             self.descriptor.builder_start_time,
389             self.descriptor.builder_finish_time,
390             self.descriptor.send_start_time,
391         )
392     }
393 
total_clip_nodes(&self) -> usize394     pub fn total_clip_nodes(&self) -> usize {
395         self.descriptor.total_clip_nodes
396     }
397 
total_spatial_nodes(&self) -> usize398     pub fn total_spatial_nodes(&self) -> usize {
399         self.descriptor.total_spatial_nodes
400     }
401 
iter(&self) -> BuiltDisplayListIter402     pub fn iter(&self) -> BuiltDisplayListIter {
403         BuiltDisplayListIter::new(self, self.item_slice(), None)
404     }
405 
extra_data_iter(&self) -> BuiltDisplayListIter406     pub fn extra_data_iter(&self) -> BuiltDisplayListIter {
407         BuiltDisplayListIter::new(self, self.extra_slice(), None)
408     }
409 
iter_with_cache<'a>( &'a self, cache: &'a DisplayItemCache ) -> BuiltDisplayListIter<'a>410     pub fn iter_with_cache<'a>(
411         &'a self,
412         cache: &'a DisplayItemCache
413     ) -> BuiltDisplayListIter<'a> {
414         BuiltDisplayListIter::new(self, self.item_slice(), Some(cache))
415     }
416 
cache_size(&self) -> usize417     pub fn cache_size(&self) -> usize {
418         self.descriptor.cache_size
419     }
420 
421     #[cfg(feature = "serialize")]
serialize_with_iterator<S: Serializer>( serializer: S, mut iterator: BuiltDisplayListIter, ) -> Result<S::Ok, S::Error>422     pub fn serialize_with_iterator<S: Serializer>(
423         serializer: S,
424         mut iterator: BuiltDisplayListIter,
425     ) -> Result<S::Ok, S::Error> {
426         use crate::display_item::DisplayItem as Real;
427         use crate::display_item::DebugDisplayItem as Debug;
428 
429         let mut seq = serializer.serialize_seq(None)?;
430 
431         while let Some(item) = iterator.next_raw() {
432             let serial_di = match *item.item() {
433                 Real::Clip(v) => Debug::Clip(
434                     v,
435                     item.iter.cur_complex_clip.iter().collect()
436                 ),
437                 Real::ClipChain(v) => Debug::ClipChain(
438                     v,
439                     item.iter.cur_clip_chain_items.iter().collect()
440                 ),
441                 Real::ScrollFrame(v) => Debug::ScrollFrame(v),
442                 Real::Text(v) => Debug::Text(
443                     v,
444                     item.iter.cur_glyphs.iter().collect()
445                 ),
446                 Real::SetFilterOps => Debug::SetFilterOps(
447                     item.iter.cur_filters.iter().collect()
448                 ),
449                 Real::SetFilterData => {
450                     debug_assert!(!item.iter.cur_filter_data.is_empty(),
451                         "next_raw should have populated cur_filter_data");
452                     let temp_filter_data = &item.iter.cur_filter_data[item.iter.cur_filter_data.len()-1];
453 
454                     let func_types: Vec<di::ComponentTransferFuncType> =
455                         temp_filter_data.func_types.iter().collect();
456                     debug_assert!(func_types.len() == 4,
457                         "someone changed the number of filter funcs without updating this code");
458                     Debug::SetFilterData(di::FilterData {
459                         func_r_type: func_types[0],
460                         r_values: temp_filter_data.r_values.iter().collect(),
461                         func_g_type: func_types[1],
462                         g_values: temp_filter_data.g_values.iter().collect(),
463                         func_b_type: func_types[2],
464                         b_values: temp_filter_data.b_values.iter().collect(),
465                         func_a_type: func_types[3],
466                         a_values: temp_filter_data.a_values.iter().collect(),
467                     })
468                 },
469                 Real::SetFilterPrimitives => Debug::SetFilterPrimitives(
470                     item.iter.cur_filter_primitives.iter().collect()
471                 ),
472                 Real::SetGradientStops => Debug::SetGradientStops(
473                     item.iter.cur_stops.iter().collect()
474                 ),
475                 Real::RectClip(v) => Debug::RectClip(v),
476                 Real::RoundedRectClip(v) => Debug::RoundedRectClip(v),
477                 Real::ImageMaskClip(v) => Debug::ImageMaskClip(v),
478                 Real::StickyFrame(v) => Debug::StickyFrame(v),
479                 Real::Rectangle(v) => Debug::Rectangle(v),
480                 Real::ClearRectangle(v) => Debug::ClearRectangle(v),
481                 Real::HitTest(v) => Debug::HitTest(v),
482                 Real::Line(v) => Debug::Line(v),
483                 Real::Image(v) => Debug::Image(v),
484                 Real::RepeatingImage(v) => Debug::RepeatingImage(v),
485                 Real::YuvImage(v) => Debug::YuvImage(v),
486                 Real::Border(v) => Debug::Border(v),
487                 Real::BoxShadow(v) => Debug::BoxShadow(v),
488                 Real::Gradient(v) => Debug::Gradient(v),
489                 Real::RadialGradient(v) => Debug::RadialGradient(v),
490                 Real::ConicGradient(v) => Debug::ConicGradient(v),
491                 Real::Iframe(v) => Debug::Iframe(v),
492                 Real::PushReferenceFrame(v) => Debug::PushReferenceFrame(v),
493                 Real::PushStackingContext(v) => Debug::PushStackingContext(v),
494                 Real::PushShadow(v) => Debug::PushShadow(v),
495                 Real::BackdropFilter(v) => Debug::BackdropFilter(v),
496 
497                 Real::PopReferenceFrame => Debug::PopReferenceFrame,
498                 Real::PopStackingContext => Debug::PopStackingContext,
499                 Real::PopAllShadows => Debug::PopAllShadows,
500                 Real::ReuseItems(_) |
501                 Real::RetainedItems(_) => unreachable!("Unexpected item"),
502             };
503             seq.serialize_element(&serial_di)?
504         }
505         seq.end()
506     }
507 }
508 
509 /// Returns the byte-range the slice occupied.
skip_slice<'a, T: peek_poke::Peek>(data: &mut &'a [u8]) -> ItemRange<'a, T>510 fn skip_slice<'a, T: peek_poke::Peek>(data: &mut &'a [u8]) -> ItemRange<'a, T> {
511     let mut skip_offset = 0usize;
512     *data = peek_from_slice(data, &mut skip_offset);
513     let (skip, rest) = data.split_at(skip_offset);
514 
515     // Adjust data pointer to skip read values
516     *data = rest;
517 
518     ItemRange {
519         bytes: skip,
520         _boo: PhantomData,
521     }
522 }
523 
524 impl<'a> BuiltDisplayListIter<'a> {
new( list: &'a BuiltDisplayList, data: &'a [u8], cache: Option<&'a DisplayItemCache>, ) -> Self525     pub fn new(
526         list: &'a BuiltDisplayList,
527         data: &'a [u8],
528         cache: Option<&'a DisplayItemCache>,
529     ) -> Self {
530         Self {
531             list,
532             data,
533             cache,
534             pending_items: [].iter(),
535             cur_cached_item: None,
536             cur_item: di::DisplayItem::PopStackingContext,
537             cur_stops: ItemRange::default(),
538             cur_glyphs: ItemRange::default(),
539             cur_filters: ItemRange::default(),
540             cur_filter_data: Vec::new(),
541             cur_filter_primitives: ItemRange::default(),
542             cur_clip_chain_items: ItemRange::default(),
543             cur_complex_clip: ItemRange::default(),
544             peeking: Peek::NotPeeking,
545             debug_stats: DebugStats {
546                 last_addr: data.as_ptr() as usize,
547                 stats: HashMap::default(),
548             },
549         }
550     }
551 
sub_iter(&self) -> Self552     pub fn sub_iter(&self) -> Self {
553         let mut iter = BuiltDisplayListIter::new(
554             self.list, self.data, self.cache
555         );
556         iter.pending_items = self.pending_items.clone();
557         iter
558     }
559 
display_list(&self) -> &'a BuiltDisplayList560     pub fn display_list(&self) -> &'a BuiltDisplayList {
561         self.list
562     }
563 
current_item(&self) -> &di::DisplayItem564     pub fn current_item(&self) -> &di::DisplayItem {
565         match self.cur_cached_item {
566             Some(cached_item) => cached_item.display_item(),
567             None => &self.cur_item
568         }
569     }
570 
cached_item_range_or<T>( &self, data: ItemRange<'a, T> ) -> ItemRange<'a, T>571     fn cached_item_range_or<T>(
572         &self,
573         data: ItemRange<'a, T>
574     ) -> ItemRange<'a, T> {
575         match self.cur_cached_item {
576             Some(cached_item) => cached_item.data_as_item_range(),
577             None => data,
578         }
579     }
580 
glyphs(&self) -> ItemRange<GlyphInstance>581     pub fn glyphs(&self) -> ItemRange<GlyphInstance> {
582         self.cached_item_range_or(self.cur_glyphs)
583     }
584 
gradient_stops(&self) -> ItemRange<di::GradientStop>585     pub fn gradient_stops(&self) -> ItemRange<di::GradientStop> {
586         self.cached_item_range_or(self.cur_stops)
587     }
588 
advance_pending_items(&mut self) -> bool589     fn advance_pending_items(&mut self) -> bool {
590         self.cur_cached_item = self.pending_items.next();
591         self.cur_cached_item.is_some()
592     }
593 
next<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>>594     pub fn next<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
595         use crate::DisplayItem::*;
596 
597         match self.peeking {
598             Peek::IsPeeking => {
599                 self.peeking = Peek::NotPeeking;
600                 return Some(self.as_ref());
601             }
602             Peek::StartPeeking => {
603                 self.peeking = Peek::IsPeeking;
604             }
605             Peek::NotPeeking => { /* do nothing */ }
606         }
607 
608         // Don't let these bleed into another item
609         self.cur_stops = ItemRange::default();
610         self.cur_complex_clip = ItemRange::default();
611         self.cur_clip_chain_items = ItemRange::default();
612         self.cur_filters = ItemRange::default();
613         self.cur_filter_primitives = ItemRange::default();
614         self.cur_filter_data.clear();
615 
616         loop {
617             self.next_raw()?;
618             match self.cur_item {
619                 SetGradientStops |
620                 SetFilterOps |
621                 SetFilterData |
622                 SetFilterPrimitives => {
623                     // These are marker items for populating other display items, don't yield them.
624                     continue;
625                 }
626                 _ => {
627                     break;
628                 }
629             }
630         }
631 
632         Some(self.as_ref())
633     }
634 
635     /// Gets the next display item, even if it's a dummy. Also doesn't handle peeking
636     /// and may leave irrelevant ranges live (so a Clip may have GradientStops if
637     /// for some reason you ask).
next_raw<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>>638     pub fn next_raw<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
639         use crate::DisplayItem::*;
640 
641         if self.advance_pending_items() {
642             return Some(self.as_ref());
643         }
644 
645         // A "red zone" of DisplayItem::max_size() bytes has been added to the
646         // end of the serialized display list. If this amount, or less, is
647         // remaining then we've reached the end of the display list.
648         if self.data.len() <= di::DisplayItem::max_size() {
649             return None;
650         }
651 
652         self.data = peek_from_slice(self.data, &mut self.cur_item);
653         self.log_item_stats();
654 
655         match self.cur_item {
656             SetGradientStops => {
657                 self.cur_stops = skip_slice::<di::GradientStop>(&mut self.data);
658                 self.debug_stats.log_slice("set_gradient_stops.stops", &self.cur_stops);
659             }
660             SetFilterOps => {
661                 self.cur_filters = skip_slice::<di::FilterOp>(&mut self.data);
662                 self.debug_stats.log_slice("set_filter_ops.ops", &self.cur_filters);
663             }
664             SetFilterData => {
665                 self.cur_filter_data.push(TempFilterData {
666                     func_types: skip_slice::<di::ComponentTransferFuncType>(&mut self.data),
667                     r_values: skip_slice::<f32>(&mut self.data),
668                     g_values: skip_slice::<f32>(&mut self.data),
669                     b_values: skip_slice::<f32>(&mut self.data),
670                     a_values: skip_slice::<f32>(&mut self.data),
671                 });
672 
673                 let data = *self.cur_filter_data.last().unwrap();
674                 self.debug_stats.log_slice("set_filter_data.func_types", &data.func_types);
675                 self.debug_stats.log_slice("set_filter_data.r_values", &data.r_values);
676                 self.debug_stats.log_slice("set_filter_data.g_values", &data.g_values);
677                 self.debug_stats.log_slice("set_filter_data.b_values", &data.b_values);
678                 self.debug_stats.log_slice("set_filter_data.a_values", &data.a_values);
679             }
680             SetFilterPrimitives => {
681                 self.cur_filter_primitives = skip_slice::<di::FilterPrimitive>(&mut self.data);
682                 self.debug_stats.log_slice("set_filter_primitives.primitives", &self.cur_filter_primitives);
683             }
684             ClipChain(_) => {
685                 self.cur_clip_chain_items = skip_slice::<di::ClipId>(&mut self.data);
686                 self.debug_stats.log_slice("clip_chain.clip_ids", &self.cur_clip_chain_items);
687             }
688             Clip(_) => {
689                 self.cur_complex_clip = skip_slice::<di::ComplexClipRegion>(&mut self.data);
690                 self.debug_stats.log_slice("clip.complex_clips", &self.cur_complex_clip);
691             }
692             Text(_) => {
693                 self.cur_glyphs = skip_slice::<GlyphInstance>(&mut self.data);
694                 self.debug_stats.log_slice("text.glyphs", &self.cur_glyphs);
695             }
696             ReuseItems(key) => {
697                 match self.cache {
698                     Some(cache) => {
699                         self.pending_items = cache.get_items(key).iter();
700                         self.advance_pending_items();
701                     }
702                     None => {
703                         unreachable!("Cache marker without cache!");
704                     }
705                 }
706             }
707             _ => { /* do nothing */ }
708         }
709 
710         Some(self.as_ref())
711     }
712 
as_ref<'b>(&'b self) -> DisplayItemRef<'a, 'b>713     pub fn as_ref<'b>(&'b self) -> DisplayItemRef<'a, 'b> {
714         DisplayItemRef {
715             iter: self,
716         }
717     }
718 
skip_current_stacking_context(&mut self)719     pub fn skip_current_stacking_context(&mut self) {
720         let mut depth = 0;
721         while let Some(item) = self.next() {
722             match *item.item() {
723                 di::DisplayItem::PushStackingContext(..) => depth += 1,
724                 di::DisplayItem::PopStackingContext if depth == 0 => return,
725                 di::DisplayItem::PopStackingContext => depth -= 1,
726                 _ => {}
727             }
728         }
729     }
730 
current_stacking_context_empty(&mut self) -> bool731     pub fn current_stacking_context_empty(&mut self) -> bool {
732         match self.peek() {
733             Some(item) => *item.item() == di::DisplayItem::PopStackingContext,
734             None => true,
735         }
736     }
737 
peek<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>>738     pub fn peek<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
739         if self.peeking == Peek::NotPeeking {
740             self.peeking = Peek::StartPeeking;
741             self.next()
742         } else {
743             Some(self.as_ref())
744         }
745     }
746 
747     /// Get the debug stats for what this iterator has deserialized.
748     /// Should always be empty in release builds.
debug_stats(&mut self) -> Vec<(&'static str, ItemStats)>749     pub fn debug_stats(&mut self) -> Vec<(&'static str, ItemStats)> {
750         let mut result = self.debug_stats.stats.drain().collect::<Vec<_>>();
751         result.sort_by_key(|stats| stats.0);
752         result
753     }
754 
755     /// Adds the debug stats from another to our own, assuming we are a sub-iter of the other
756     /// (so we can ignore where they were in the traversal).
merge_debug_stats_from(&mut self, other: &mut Self)757     pub fn merge_debug_stats_from(&mut self, other: &mut Self) {
758         for (key, other_entry) in other.debug_stats.stats.iter() {
759             let entry = self.debug_stats.stats.entry(key).or_default();
760 
761             entry.total_count += other_entry.total_count;
762             entry.num_bytes += other_entry.num_bytes;
763         }
764     }
765 
766     /// Logs stats for the last deserialized display item
767     #[cfg(feature = "display_list_stats")]
log_item_stats(&mut self)768     fn log_item_stats(&mut self) {
769         self.debug_stats.log_item(self.data, &self.cur_item);
770     }
771 
772     #[cfg(not(feature = "display_list_stats"))]
log_item_stats(&mut self)773     fn log_item_stats(&mut self) { /* no-op */ }
774 }
775 
776 impl<'a, T> AuxIter<'a, T> {
new(item: T, mut data: &'a [u8]) -> Self777     pub fn new(item: T, mut data: &'a [u8]) -> Self {
778         let mut size = 0usize;
779         if !data.is_empty() {
780             data = peek_from_slice(data, &mut size);
781         };
782 
783         AuxIter {
784             item,
785             data,
786             size,
787 //            _boo: PhantomData,
788         }
789     }
790 }
791 
792 impl<'a, T: Copy + peek_poke::Peek> Iterator for AuxIter<'a, T> {
793     type Item = T;
794 
next(&mut self) -> Option<Self::Item>795     fn next(&mut self) -> Option<Self::Item> {
796         if self.size == 0 {
797             None
798         } else {
799             self.size -= 1;
800             self.data = peek_from_slice(self.data, &mut self.item);
801             Some(self.item)
802         }
803     }
804 
size_hint(&self) -> (usize, Option<usize>)805     fn size_hint(&self) -> (usize, Option<usize>) {
806         (self.size, Some(self.size))
807     }
808 }
809 
810 impl<'a, T: Copy + peek_poke::Peek> ::std::iter::ExactSizeIterator for AuxIter<'a, T> {}
811 
812 #[cfg(feature = "serialize")]
813 impl Serialize for BuiltDisplayList {
serialize<S: Serializer>( &self, serializer: S ) -> Result<S::Ok, S::Error>814     fn serialize<S: Serializer>(
815         &self,
816         serializer: S
817     ) -> Result<S::Ok, S::Error> {
818         Self::serialize_with_iterator(serializer, self.iter())
819     }
820 }
821 
822 // The purpose of this implementation is to deserialize
823 // a display list from one format just to immediately
824 // serialize then into a "built" `Vec<u8>`.
825 
826 #[cfg(feature = "deserialize")]
827 impl<'de> Deserialize<'de> for BuiltDisplayList {
deserialize<D: Deserializer<'de>>( deserializer: D ) -> Result<Self, D::Error>828     fn deserialize<D: Deserializer<'de>>(
829         deserializer: D
830     ) -> Result<Self, D::Error> {
831         use crate::display_item::DisplayItem as Real;
832         use crate::display_item::DebugDisplayItem as Debug;
833 
834         let list = Vec::<Debug>::deserialize(deserializer)?;
835 
836         let mut data = Vec::new();
837         let mut temp = Vec::new();
838         let mut total_clip_nodes = FIRST_CLIP_NODE_INDEX;
839         let mut total_spatial_nodes = FIRST_SPATIAL_NODE_INDEX;
840         for complete in list {
841             let item = match complete {
842                 Debug::Clip(v, complex_clips) => {
843                     total_clip_nodes += 1;
844                     DisplayListBuilder::push_iter_impl(&mut temp, complex_clips);
845                     Real::Clip(v)
846                 },
847                 Debug::ClipChain(v, clip_chain_ids) => {
848                     DisplayListBuilder::push_iter_impl(&mut temp, clip_chain_ids);
849                     Real::ClipChain(v)
850                 }
851                 Debug::ScrollFrame(v) => {
852                     total_spatial_nodes += 1;
853                     total_clip_nodes += 1;
854                     Real::ScrollFrame(v)
855                 }
856                 Debug::StickyFrame(v) => {
857                     total_spatial_nodes += 1;
858                     Real::StickyFrame(v)
859                 }
860                 Debug::Text(v, glyphs) => {
861                     DisplayListBuilder::push_iter_impl(&mut temp, glyphs);
862                     Real::Text(v)
863                 },
864                 Debug::Iframe(v) => {
865                     total_clip_nodes += 1;
866                     Real::Iframe(v)
867                 }
868                 Debug::PushReferenceFrame(v) => {
869                     total_spatial_nodes += 1;
870                     Real::PushReferenceFrame(v)
871                 }
872                 Debug::SetFilterOps(filters) => {
873                     DisplayListBuilder::push_iter_impl(&mut temp, filters);
874                     Real::SetFilterOps
875                 },
876                 Debug::SetFilterData(filter_data) => {
877                     let func_types: Vec<di::ComponentTransferFuncType> =
878                         [filter_data.func_r_type,
879                          filter_data.func_g_type,
880                          filter_data.func_b_type,
881                          filter_data.func_a_type].to_vec();
882                     DisplayListBuilder::push_iter_impl(&mut temp, func_types);
883                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.r_values);
884                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.g_values);
885                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.b_values);
886                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.a_values);
887                     Real::SetFilterData
888                 },
889                 Debug::SetFilterPrimitives(filter_primitives) => {
890                     DisplayListBuilder::push_iter_impl(&mut temp, filter_primitives);
891                     Real::SetFilterPrimitives
892                 }
893                 Debug::SetGradientStops(stops) => {
894                     DisplayListBuilder::push_iter_impl(&mut temp, stops);
895                     Real::SetGradientStops
896                 },
897                 Debug::RectClip(v) => Real::RectClip(v),
898                 Debug::RoundedRectClip(v) => Real::RoundedRectClip(v),
899                 Debug::ImageMaskClip(v) => Real::ImageMaskClip(v),
900                 Debug::Rectangle(v) => Real::Rectangle(v),
901                 Debug::ClearRectangle(v) => Real::ClearRectangle(v),
902                 Debug::HitTest(v) => Real::HitTest(v),
903                 Debug::Line(v) => Real::Line(v),
904                 Debug::Image(v) => Real::Image(v),
905                 Debug::RepeatingImage(v) => Real::RepeatingImage(v),
906                 Debug::YuvImage(v) => Real::YuvImage(v),
907                 Debug::Border(v) => Real::Border(v),
908                 Debug::BoxShadow(v) => Real::BoxShadow(v),
909                 Debug::Gradient(v) => Real::Gradient(v),
910                 Debug::RadialGradient(v) => Real::RadialGradient(v),
911                 Debug::ConicGradient(v) => Real::ConicGradient(v),
912                 Debug::PushStackingContext(v) => Real::PushStackingContext(v),
913                 Debug::PushShadow(v) => Real::PushShadow(v),
914                 Debug::BackdropFilter(v) => Real::BackdropFilter(v),
915 
916                 Debug::PopStackingContext => Real::PopStackingContext,
917                 Debug::PopReferenceFrame => Real::PopReferenceFrame,
918                 Debug::PopAllShadows => Real::PopAllShadows,
919             };
920             poke_into_vec(&item, &mut data);
921             // the aux data is serialized after the item, hence the temporary
922             data.extend(temp.drain(..));
923         }
924 
925         // Add `DisplayItem::max_size` zone of zeroes to the end of display list
926         // so there is at least this amount available in the display list during
927         // serialization.
928         ensure_red_zone::<di::DisplayItem>(&mut data);
929         let extra_data_offset = data.len();
930 
931         Ok(BuiltDisplayList {
932             data,
933             descriptor: BuiltDisplayListDescriptor {
934                 builder_start_time: 0,
935                 builder_finish_time: 1,
936                 send_start_time: 1,
937                 total_clip_nodes,
938                 total_spatial_nodes,
939                 extra_data_offset,
940                 cache_size: 0,
941             },
942         })
943     }
944 }
945 
946 #[derive(Clone, Debug)]
947 pub struct SaveState {
948     dl_len: usize,
949     next_clip_index: usize,
950     next_spatial_index: usize,
951     next_clip_chain_id: u64,
952 }
953 
954 /// DisplayListSection determines the target buffer for the display items.
955 pub enum DisplayListSection {
956     /// The main/default buffer: contains item data and item group markers.
957     Data,
958     /// Auxiliary buffer: contains the item data for item groups.
959     ExtraData,
960     /// Temporary buffer: contains the data for pending item group. Flushed to
961     /// one of the buffers above, after item grouping finishes.
962     Chunk,
963 }
964 
965 #[derive(Clone)]
966 pub struct DisplayListBuilder {
967     pub data: Vec<u8>,
968     pub pipeline_id: PipelineId,
969 
970     extra_data: Vec<u8>,
971     pending_chunk: Vec<u8>,
972     writing_to_chunk: bool,
973 
974     next_clip_index: usize,
975     next_spatial_index: usize,
976     next_clip_chain_id: u64,
977     builder_start_time: u64,
978 
979     /// The size of the content of this display list. This is used to allow scrolling
980     /// outside the bounds of the display list items themselves.
981     content_size: LayoutSize,
982     save_state: Option<SaveState>,
983 
984     cache_size: usize,
985     serialized_content_buffer: Option<String>,
986 }
987 
988 impl DisplayListBuilder {
new(pipeline_id: PipelineId, content_size: LayoutSize) -> Self989     pub fn new(pipeline_id: PipelineId, content_size: LayoutSize) -> Self {
990         Self::with_capacity(pipeline_id, content_size, 0)
991     }
992 
with_capacity( pipeline_id: PipelineId, content_size: LayoutSize, capacity: usize, ) -> Self993     pub fn with_capacity(
994         pipeline_id: PipelineId,
995         content_size: LayoutSize,
996         capacity: usize,
997     ) -> Self {
998         let start_time = precise_time_ns();
999 
1000         DisplayListBuilder {
1001             data: Vec::with_capacity(capacity),
1002             pipeline_id,
1003 
1004             extra_data: Vec::new(),
1005             pending_chunk: Vec::new(),
1006             writing_to_chunk: false,
1007 
1008             next_clip_index: FIRST_CLIP_NODE_INDEX,
1009             next_spatial_index: FIRST_SPATIAL_NODE_INDEX,
1010             next_clip_chain_id: 0,
1011             builder_start_time: start_time,
1012             content_size,
1013             save_state: None,
1014             cache_size: 0,
1015             serialized_content_buffer: None,
1016         }
1017     }
1018 
1019     /// Return the content size for this display list
content_size(&self) -> LayoutSize1020     pub fn content_size(&self) -> LayoutSize {
1021         self.content_size
1022     }
1023 
1024     /// Saves the current display list state, so it may be `restore()`'d.
1025     ///
1026     /// # Conditions:
1027     ///
1028     /// * Doesn't support popping clips that were pushed before the save.
1029     /// * Doesn't support nested saves.
1030     /// * Must call `clear_save()` if the restore becomes unnecessary.
save(&mut self)1031     pub fn save(&mut self) {
1032         assert!(self.save_state.is_none(), "DisplayListBuilder doesn't support nested saves");
1033 
1034         self.save_state = Some(SaveState {
1035             dl_len: self.data.len(),
1036             next_clip_index: self.next_clip_index,
1037             next_spatial_index: self.next_spatial_index,
1038             next_clip_chain_id: self.next_clip_chain_id,
1039         });
1040     }
1041 
1042     /// Restores the state of the builder to when `save()` was last called.
restore(&mut self)1043     pub fn restore(&mut self) {
1044         let state = self.save_state.take().expect("No save to restore DisplayListBuilder from");
1045 
1046         self.data.truncate(state.dl_len);
1047         self.next_clip_index = state.next_clip_index;
1048         self.next_spatial_index = state.next_spatial_index;
1049         self.next_clip_chain_id = state.next_clip_chain_id;
1050     }
1051 
1052     /// Discards the builder's save (indicating the attempted operation was successful).
clear_save(&mut self)1053     pub fn clear_save(&mut self) {
1054         self.save_state.take().expect("No save to clear in DisplayListBuilder");
1055     }
1056 
1057     /// Emits a debug representation of display items in the list, for debugging
1058     /// purposes. If the range's start parameter is specified, only display
1059     /// items starting at that index (inclusive) will be printed. If the range's
1060     /// end parameter is specified, only display items before that index
1061     /// (exclusive) will be printed. Calling this function with end <= start is
1062     /// allowed but is just a waste of CPU cycles. The function emits the
1063     /// debug representation of the selected display items, one per line, with
1064     /// the given indent, to the provided sink object. The return value is
1065     /// the total number of items in the display list, which allows the
1066     /// caller to subsequently invoke this function to only dump the newly-added
1067     /// items.
emit_display_list<W>( &mut self, indent: usize, range: Range<Option<usize>>, mut sink: W, ) -> usize where W: Write1068     pub fn emit_display_list<W>(
1069         &mut self,
1070         indent: usize,
1071         range: Range<Option<usize>>,
1072         mut sink: W,
1073     ) -> usize
1074     where
1075         W: Write
1076     {
1077         let mut temp = BuiltDisplayList::default();
1078         mem::swap(&mut temp.data, &mut self.data);
1079 
1080         let mut index: usize = 0;
1081         {
1082             let mut iter = temp.iter();
1083             while let Some(item) = iter.next_raw() {
1084                 if index >= range.start.unwrap_or(0) && range.end.map_or(true, |e| index < e) {
1085                     writeln!(sink, "{}{:?}", "  ".repeat(indent), item.item()).unwrap();
1086                 }
1087                 index += 1;
1088             }
1089         }
1090 
1091         self.data = temp.data;
1092         index
1093     }
1094 
1095     /// Print the display items in the list to stdout.
dump_serialized_display_list(&mut self)1096     pub fn dump_serialized_display_list(&mut self) {
1097         self.serialized_content_buffer = Some(String::new());
1098     }
1099 
add_to_display_list_dump<T: std::fmt::Debug>(&mut self, item: T)1100     fn add_to_display_list_dump<T: std::fmt::Debug>(&mut self, item: T) {
1101         if let Some(ref mut content) = self.serialized_content_buffer {
1102             use std::fmt::Write;
1103             write!(content, "{:?}\n", item).expect("DL dump write failed.");
1104         }
1105     }
1106 
1107     /// Returns the default section that DisplayListBuilder will write to,
1108     /// if no section is specified explicitly.
default_section(&self) -> DisplayListSection1109     fn default_section(&self) -> DisplayListSection {
1110         if self.writing_to_chunk {
1111             DisplayListSection::Chunk
1112         } else {
1113             DisplayListSection::Data
1114         }
1115     }
1116 
buffer_from_section( &mut self, section: DisplayListSection ) -> &mut Vec<u8>1117     fn buffer_from_section(
1118         &mut self,
1119         section: DisplayListSection
1120     ) -> &mut Vec<u8> {
1121         match section {
1122             DisplayListSection::Data => &mut self.data,
1123             DisplayListSection::ExtraData => &mut self.extra_data,
1124             DisplayListSection::Chunk => &mut self.pending_chunk,
1125         }
1126     }
1127 
1128     #[inline]
push_item_to_section( &mut self, item: &di::DisplayItem, section: DisplayListSection, )1129     pub fn push_item_to_section(
1130         &mut self,
1131         item: &di::DisplayItem,
1132         section: DisplayListSection,
1133     ) {
1134         poke_into_vec(item, self.buffer_from_section(section));
1135         self.add_to_display_list_dump(item);
1136     }
1137 
1138     /// Add an item to the display list.
1139     ///
1140     /// NOTE: It is usually preferable to use the specialized methods to push
1141     /// display items. Pushing unexpected or invalid items here may
1142     /// result in WebRender panicking or behaving in unexpected ways.
1143     #[inline]
push_item(&mut self, item: &di::DisplayItem)1144     pub fn push_item(&mut self, item: &di::DisplayItem) {
1145         self.push_item_to_section(item, self.default_section());
1146     }
1147 
push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I) where I: IntoIterator, I::IntoIter: ExactSizeIterator, I::Item: Poke,1148     fn push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I)
1149     where
1150         I: IntoIterator,
1151         I::IntoIter: ExactSizeIterator,
1152         I::Item: Poke,
1153     {
1154         let iter = iter_source.into_iter();
1155         let len = iter.len();
1156         // Format:
1157         // payload_byte_size: usize, item_count: usize, [I; item_count]
1158 
1159         // Track the the location of where to write byte size with offsets
1160         // instead of pointers because data may be moved in memory during
1161         // `serialize_iter_fast`.
1162         let byte_size_offset = data.len();
1163 
1164         // We write a dummy value so there's room for later
1165         poke_into_vec(&0usize, data);
1166         poke_into_vec(&len, data);
1167         let count = poke_extend_vec(iter, data);
1168         debug_assert_eq!(len, count, "iterator.len() returned two different values");
1169 
1170         // Add red zone
1171         ensure_red_zone::<I::Item>(data);
1172 
1173         // Now write the actual byte_size
1174         let final_offset = data.len();
1175         debug_assert!(final_offset >= (byte_size_offset + mem::size_of::<usize>()),
1176             "space was never allocated for this array's byte_size");
1177         let byte_size = final_offset - byte_size_offset - mem::size_of::<usize>();
1178         poke_inplace_slice(&byte_size, &mut data[byte_size_offset..]);
1179     }
1180 
1181     /// Push items from an iterator to the display list.
1182     ///
1183     /// NOTE: Pushing unexpected or invalid items to the display list
1184     /// may result in panic and confusion.
push_iter<I>(&mut self, iter: I) where I: IntoIterator, I::IntoIter: ExactSizeIterator, I::Item: Poke,1185     pub fn push_iter<I>(&mut self, iter: I)
1186     where
1187         I: IntoIterator,
1188         I::IntoIter: ExactSizeIterator,
1189         I::Item: Poke,
1190     {
1191         let mut buffer = self.buffer_from_section(self.default_section());
1192         Self::push_iter_impl(&mut buffer, iter);
1193     }
1194 
push_rect( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, color: ColorF, )1195     pub fn push_rect(
1196         &mut self,
1197         common: &di::CommonItemProperties,
1198         bounds: LayoutRect,
1199         color: ColorF,
1200     ) {
1201         let item = di::DisplayItem::Rectangle(di::RectangleDisplayItem {
1202             common: *common,
1203             color: PropertyBinding::Value(color),
1204             bounds,
1205         });
1206         self.push_item(&item);
1207     }
1208 
push_rect_with_animation( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, color: PropertyBinding<ColorF>, )1209     pub fn push_rect_with_animation(
1210         &mut self,
1211         common: &di::CommonItemProperties,
1212         bounds: LayoutRect,
1213         color: PropertyBinding<ColorF>,
1214     ) {
1215         let item = di::DisplayItem::Rectangle(di::RectangleDisplayItem {
1216             common: *common,
1217             color,
1218             bounds,
1219         });
1220         self.push_item(&item);
1221     }
1222 
push_clear_rect( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, )1223     pub fn push_clear_rect(
1224         &mut self,
1225         common: &di::CommonItemProperties,
1226         bounds: LayoutRect,
1227     ) {
1228         let item = di::DisplayItem::ClearRectangle(di::ClearRectangleDisplayItem {
1229             common: *common,
1230             bounds,
1231         });
1232         self.push_item(&item);
1233     }
1234 
push_hit_test( &mut self, common: &di::CommonItemProperties, )1235     pub fn push_hit_test(
1236         &mut self,
1237         common: &di::CommonItemProperties,
1238     ) {
1239         let item = di::DisplayItem::HitTest(di::HitTestDisplayItem {
1240             common: *common,
1241         });
1242         self.push_item(&item);
1243     }
1244 
push_line( &mut self, common: &di::CommonItemProperties, area: &LayoutRect, wavy_line_thickness: f32, orientation: di::LineOrientation, color: &ColorF, style: di::LineStyle, )1245     pub fn push_line(
1246         &mut self,
1247         common: &di::CommonItemProperties,
1248         area: &LayoutRect,
1249         wavy_line_thickness: f32,
1250         orientation: di::LineOrientation,
1251         color: &ColorF,
1252         style: di::LineStyle,
1253     ) {
1254         let item = di::DisplayItem::Line(di::LineDisplayItem {
1255             common: *common,
1256             area: *area,
1257             wavy_line_thickness,
1258             orientation,
1259             color: *color,
1260             style,
1261         });
1262 
1263         self.push_item(&item);
1264     }
1265 
push_image( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, image_rendering: di::ImageRendering, alpha_type: di::AlphaType, key: ImageKey, color: ColorF, )1266     pub fn push_image(
1267         &mut self,
1268         common: &di::CommonItemProperties,
1269         bounds: LayoutRect,
1270         image_rendering: di::ImageRendering,
1271         alpha_type: di::AlphaType,
1272         key: ImageKey,
1273         color: ColorF,
1274     ) {
1275         let item = di::DisplayItem::Image(di::ImageDisplayItem {
1276             common: *common,
1277             bounds,
1278             image_key: key,
1279             image_rendering,
1280             alpha_type,
1281             color,
1282         });
1283 
1284         self.push_item(&item);
1285     }
1286 
push_repeating_image( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, stretch_size: LayoutSize, tile_spacing: LayoutSize, image_rendering: di::ImageRendering, alpha_type: di::AlphaType, key: ImageKey, color: ColorF, )1287     pub fn push_repeating_image(
1288         &mut self,
1289         common: &di::CommonItemProperties,
1290         bounds: LayoutRect,
1291         stretch_size: LayoutSize,
1292         tile_spacing: LayoutSize,
1293         image_rendering: di::ImageRendering,
1294         alpha_type: di::AlphaType,
1295         key: ImageKey,
1296         color: ColorF,
1297     ) {
1298         let item = di::DisplayItem::RepeatingImage(di::RepeatingImageDisplayItem {
1299             common: *common,
1300             bounds,
1301             image_key: key,
1302             stretch_size,
1303             tile_spacing,
1304             image_rendering,
1305             alpha_type,
1306             color,
1307         });
1308 
1309         self.push_item(&item);
1310     }
1311 
1312     /// Push a yuv image. All planar data in yuv image should use the same buffer type.
push_yuv_image( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, yuv_data: di::YuvData, color_depth: ColorDepth, color_space: di::YuvColorSpace, color_range: di::ColorRange, image_rendering: di::ImageRendering, )1313     pub fn push_yuv_image(
1314         &mut self,
1315         common: &di::CommonItemProperties,
1316         bounds: LayoutRect,
1317         yuv_data: di::YuvData,
1318         color_depth: ColorDepth,
1319         color_space: di::YuvColorSpace,
1320         color_range: di::ColorRange,
1321         image_rendering: di::ImageRendering,
1322     ) {
1323         let item = di::DisplayItem::YuvImage(di::YuvImageDisplayItem {
1324             common: *common,
1325             bounds,
1326             yuv_data,
1327             color_depth,
1328             color_space,
1329             color_range,
1330             image_rendering,
1331         });
1332         self.push_item(&item);
1333     }
1334 
push_text( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, glyphs: &[GlyphInstance], font_key: FontInstanceKey, color: ColorF, glyph_options: Option<GlyphOptions>, )1335     pub fn push_text(
1336         &mut self,
1337         common: &di::CommonItemProperties,
1338         bounds: LayoutRect,
1339         glyphs: &[GlyphInstance],
1340         font_key: FontInstanceKey,
1341         color: ColorF,
1342         glyph_options: Option<GlyphOptions>,
1343     ) {
1344         let item = di::DisplayItem::Text(di::TextDisplayItem {
1345             common: *common,
1346             bounds,
1347             color,
1348             font_key,
1349             glyph_options,
1350         });
1351 
1352         for split_glyphs in glyphs.chunks(MAX_TEXT_RUN_LENGTH) {
1353             self.push_item(&item);
1354             self.push_iter(split_glyphs);
1355         }
1356     }
1357 
1358     /// NOTE: gradients must be pushed in the order they're created
1359     /// because create_gradient stores the stops in anticipation.
create_gradient( &mut self, start_point: LayoutPoint, end_point: LayoutPoint, stops: Vec<di::GradientStop>, extend_mode: di::ExtendMode, ) -> di::Gradient1360     pub fn create_gradient(
1361         &mut self,
1362         start_point: LayoutPoint,
1363         end_point: LayoutPoint,
1364         stops: Vec<di::GradientStop>,
1365         extend_mode: di::ExtendMode,
1366     ) -> di::Gradient {
1367         let mut builder = GradientBuilder::with_stops(stops);
1368         let gradient = builder.gradient(start_point, end_point, extend_mode);
1369         self.push_stops(builder.stops());
1370         gradient
1371     }
1372 
1373     /// NOTE: gradients must be pushed in the order they're created
1374     /// because create_gradient stores the stops in anticipation.
create_radial_gradient( &mut self, center: LayoutPoint, radius: LayoutSize, stops: Vec<di::GradientStop>, extend_mode: di::ExtendMode, ) -> di::RadialGradient1375     pub fn create_radial_gradient(
1376         &mut self,
1377         center: LayoutPoint,
1378         radius: LayoutSize,
1379         stops: Vec<di::GradientStop>,
1380         extend_mode: di::ExtendMode,
1381     ) -> di::RadialGradient {
1382         let mut builder = GradientBuilder::with_stops(stops);
1383         let gradient = builder.radial_gradient(center, radius, extend_mode);
1384         self.push_stops(builder.stops());
1385         gradient
1386     }
1387 
1388     /// NOTE: gradients must be pushed in the order they're created
1389     /// because create_gradient stores the stops in anticipation.
create_conic_gradient( &mut self, center: LayoutPoint, angle: f32, stops: Vec<di::GradientStop>, extend_mode: di::ExtendMode, ) -> di::ConicGradient1390     pub fn create_conic_gradient(
1391         &mut self,
1392         center: LayoutPoint,
1393         angle: f32,
1394         stops: Vec<di::GradientStop>,
1395         extend_mode: di::ExtendMode,
1396     ) -> di::ConicGradient {
1397         let mut builder = GradientBuilder::with_stops(stops);
1398         let gradient = builder.conic_gradient(center, angle, extend_mode);
1399         self.push_stops(builder.stops());
1400         gradient
1401     }
1402 
push_border( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, widths: LayoutSideOffsets, details: di::BorderDetails, )1403     pub fn push_border(
1404         &mut self,
1405         common: &di::CommonItemProperties,
1406         bounds: LayoutRect,
1407         widths: LayoutSideOffsets,
1408         details: di::BorderDetails,
1409     ) {
1410         let item = di::DisplayItem::Border(di::BorderDisplayItem {
1411             common: *common,
1412             bounds,
1413             details,
1414             widths,
1415         });
1416 
1417         self.push_item(&item);
1418     }
1419 
push_box_shadow( &mut self, common: &di::CommonItemProperties, box_bounds: LayoutRect, offset: LayoutVector2D, color: ColorF, blur_radius: f32, spread_radius: f32, border_radius: di::BorderRadius, clip_mode: di::BoxShadowClipMode, )1420     pub fn push_box_shadow(
1421         &mut self,
1422         common: &di::CommonItemProperties,
1423         box_bounds: LayoutRect,
1424         offset: LayoutVector2D,
1425         color: ColorF,
1426         blur_radius: f32,
1427         spread_radius: f32,
1428         border_radius: di::BorderRadius,
1429         clip_mode: di::BoxShadowClipMode,
1430     ) {
1431         let item = di::DisplayItem::BoxShadow(di::BoxShadowDisplayItem {
1432             common: *common,
1433             box_bounds,
1434             offset,
1435             color,
1436             blur_radius,
1437             spread_radius,
1438             border_radius,
1439             clip_mode,
1440         });
1441 
1442         self.push_item(&item);
1443     }
1444 
1445     /// Pushes a linear gradient to be displayed.
1446     ///
1447     /// The gradient itself is described in the
1448     /// `gradient` parameter. It is drawn on
1449     /// a "tile" with the dimensions from `tile_size`.
1450     /// These tiles are now repeated to the right and
1451     /// to the bottom infinitely. If `tile_spacing`
1452     /// is not zero spacers with the given dimensions
1453     /// are inserted between the tiles as seams.
1454     ///
1455     /// The origin of the tiles is given in `layout.rect.origin`.
1456     /// If the gradient should only be displayed once limit
1457     /// the `layout.rect.size` to a single tile.
1458     /// The gradient is only visible within the local clip.
push_gradient( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, gradient: di::Gradient, tile_size: LayoutSize, tile_spacing: LayoutSize, )1459     pub fn push_gradient(
1460         &mut self,
1461         common: &di::CommonItemProperties,
1462         bounds: LayoutRect,
1463         gradient: di::Gradient,
1464         tile_size: LayoutSize,
1465         tile_spacing: LayoutSize,
1466     ) {
1467         let item = di::DisplayItem::Gradient(di::GradientDisplayItem {
1468             common: *common,
1469             bounds,
1470             gradient,
1471             tile_size,
1472             tile_spacing,
1473         });
1474 
1475         self.push_item(&item);
1476     }
1477 
1478     /// Pushes a radial gradient to be displayed.
1479     ///
1480     /// See [`push_gradient`](#method.push_gradient) for explanation.
push_radial_gradient( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, gradient: di::RadialGradient, tile_size: LayoutSize, tile_spacing: LayoutSize, )1481     pub fn push_radial_gradient(
1482         &mut self,
1483         common: &di::CommonItemProperties,
1484         bounds: LayoutRect,
1485         gradient: di::RadialGradient,
1486         tile_size: LayoutSize,
1487         tile_spacing: LayoutSize,
1488     ) {
1489         let item = di::DisplayItem::RadialGradient(di::RadialGradientDisplayItem {
1490             common: *common,
1491             bounds,
1492             gradient,
1493             tile_size,
1494             tile_spacing,
1495         });
1496 
1497         self.push_item(&item);
1498     }
1499 
1500     /// Pushes a conic gradient to be displayed.
1501     ///
1502     /// See [`push_gradient`](#method.push_gradient) for explanation.
push_conic_gradient( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, gradient: di::ConicGradient, tile_size: LayoutSize, tile_spacing: LayoutSize, )1503     pub fn push_conic_gradient(
1504         &mut self,
1505         common: &di::CommonItemProperties,
1506         bounds: LayoutRect,
1507         gradient: di::ConicGradient,
1508         tile_size: LayoutSize,
1509         tile_spacing: LayoutSize,
1510     ) {
1511         let item = di::DisplayItem::ConicGradient(di::ConicGradientDisplayItem {
1512             common: *common,
1513             bounds,
1514             gradient,
1515             tile_size,
1516             tile_spacing,
1517         });
1518 
1519         self.push_item(&item);
1520     }
1521 
push_reference_frame( &mut self, origin: LayoutPoint, parent_spatial_id: di::SpatialId, transform_style: di::TransformStyle, transform: PropertyBinding<LayoutTransform>, kind: di::ReferenceFrameKind, ) -> di::SpatialId1522     pub fn push_reference_frame(
1523         &mut self,
1524         origin: LayoutPoint,
1525         parent_spatial_id: di::SpatialId,
1526         transform_style: di::TransformStyle,
1527         transform: PropertyBinding<LayoutTransform>,
1528         kind: di::ReferenceFrameKind,
1529     ) -> di::SpatialId {
1530         let id = self.generate_spatial_index();
1531 
1532         let item = di::DisplayItem::PushReferenceFrame(di::ReferenceFrameDisplayListItem {
1533             parent_spatial_id,
1534             origin,
1535             reference_frame: di::ReferenceFrame {
1536                 transform_style,
1537                 transform,
1538                 kind,
1539                 id,
1540             },
1541         });
1542 
1543         self.push_item(&item);
1544         id
1545     }
1546 
pop_reference_frame(&mut self)1547     pub fn pop_reference_frame(&mut self) {
1548         self.push_item(&di::DisplayItem::PopReferenceFrame);
1549     }
1550 
push_stacking_context( &mut self, origin: LayoutPoint, spatial_id: di::SpatialId, prim_flags: di::PrimitiveFlags, clip_id: Option<di::ClipId>, transform_style: di::TransformStyle, mix_blend_mode: di::MixBlendMode, filters: &[di::FilterOp], filter_datas: &[di::FilterData], filter_primitives: &[di::FilterPrimitive], raster_space: di::RasterSpace, flags: di::StackingContextFlags, )1551     pub fn push_stacking_context(
1552         &mut self,
1553         origin: LayoutPoint,
1554         spatial_id: di::SpatialId,
1555         prim_flags: di::PrimitiveFlags,
1556         clip_id: Option<di::ClipId>,
1557         transform_style: di::TransformStyle,
1558         mix_blend_mode: di::MixBlendMode,
1559         filters: &[di::FilterOp],
1560         filter_datas: &[di::FilterData],
1561         filter_primitives: &[di::FilterPrimitive],
1562         raster_space: di::RasterSpace,
1563         flags: di::StackingContextFlags,
1564     ) {
1565         self.push_filters(filters, filter_datas, filter_primitives);
1566 
1567         let item = di::DisplayItem::PushStackingContext(di::PushStackingContextDisplayItem {
1568             origin,
1569             spatial_id,
1570             prim_flags,
1571             stacking_context: di::StackingContext {
1572                 transform_style,
1573                 mix_blend_mode,
1574                 clip_id,
1575                 raster_space,
1576                 flags,
1577             },
1578         });
1579 
1580         self.push_item(&item);
1581     }
1582 
1583     /// Helper for examples/ code.
push_simple_stacking_context( &mut self, origin: LayoutPoint, spatial_id: di::SpatialId, prim_flags: di::PrimitiveFlags, )1584     pub fn push_simple_stacking_context(
1585         &mut self,
1586         origin: LayoutPoint,
1587         spatial_id: di::SpatialId,
1588         prim_flags: di::PrimitiveFlags,
1589     ) {
1590         self.push_simple_stacking_context_with_filters(
1591             origin,
1592             spatial_id,
1593             prim_flags,
1594             &[],
1595             &[],
1596             &[],
1597         );
1598     }
1599 
1600     /// Helper for examples/ code.
push_simple_stacking_context_with_filters( &mut self, origin: LayoutPoint, spatial_id: di::SpatialId, prim_flags: di::PrimitiveFlags, filters: &[di::FilterOp], filter_datas: &[di::FilterData], filter_primitives: &[di::FilterPrimitive], )1601     pub fn push_simple_stacking_context_with_filters(
1602         &mut self,
1603         origin: LayoutPoint,
1604         spatial_id: di::SpatialId,
1605         prim_flags: di::PrimitiveFlags,
1606         filters: &[di::FilterOp],
1607         filter_datas: &[di::FilterData],
1608         filter_primitives: &[di::FilterPrimitive],
1609     ) {
1610         self.push_stacking_context(
1611             origin,
1612             spatial_id,
1613             prim_flags,
1614             None,
1615             di::TransformStyle::Flat,
1616             di::MixBlendMode::Normal,
1617             filters,
1618             filter_datas,
1619             filter_primitives,
1620             di::RasterSpace::Screen,
1621             di::StackingContextFlags::empty(),
1622         );
1623     }
1624 
pop_stacking_context(&mut self)1625     pub fn pop_stacking_context(&mut self) {
1626         self.push_item(&di::DisplayItem::PopStackingContext);
1627     }
1628 
push_stops(&mut self, stops: &[di::GradientStop])1629     pub fn push_stops(&mut self, stops: &[di::GradientStop]) {
1630         if stops.is_empty() {
1631             return;
1632         }
1633         self.push_item(&di::DisplayItem::SetGradientStops);
1634         self.push_iter(stops);
1635     }
1636 
push_backdrop_filter( &mut self, common: &di::CommonItemProperties, filters: &[di::FilterOp], filter_datas: &[di::FilterData], filter_primitives: &[di::FilterPrimitive], )1637     pub fn push_backdrop_filter(
1638         &mut self,
1639         common: &di::CommonItemProperties,
1640         filters: &[di::FilterOp],
1641         filter_datas: &[di::FilterData],
1642         filter_primitives: &[di::FilterPrimitive],
1643     ) {
1644         self.push_filters(filters, filter_datas, filter_primitives);
1645 
1646         let item = di::DisplayItem::BackdropFilter(di::BackdropFilterDisplayItem {
1647             common: *common,
1648         });
1649         self.push_item(&item);
1650     }
1651 
push_filters( &mut self, filters: &[di::FilterOp], filter_datas: &[di::FilterData], filter_primitives: &[di::FilterPrimitive], )1652     pub fn push_filters(
1653         &mut self,
1654         filters: &[di::FilterOp],
1655         filter_datas: &[di::FilterData],
1656         filter_primitives: &[di::FilterPrimitive],
1657     ) {
1658         if !filters.is_empty() {
1659             self.push_item(&di::DisplayItem::SetFilterOps);
1660             self.push_iter(filters);
1661         }
1662 
1663         for filter_data in filter_datas {
1664             let func_types = [
1665                 filter_data.func_r_type, filter_data.func_g_type,
1666                 filter_data.func_b_type, filter_data.func_a_type];
1667             self.push_item(&di::DisplayItem::SetFilterData);
1668             self.push_iter(&func_types);
1669             self.push_iter(&filter_data.r_values);
1670             self.push_iter(&filter_data.g_values);
1671             self.push_iter(&filter_data.b_values);
1672             self.push_iter(&filter_data.a_values);
1673         }
1674 
1675         if !filter_primitives.is_empty() {
1676             self.push_item(&di::DisplayItem::SetFilterPrimitives);
1677             self.push_iter(filter_primitives);
1678         }
1679     }
1680 
generate_clip_index(&mut self) -> di::ClipId1681     fn generate_clip_index(&mut self) -> di::ClipId {
1682         self.next_clip_index += 1;
1683         di::ClipId::Clip(self.next_clip_index - 1, self.pipeline_id)
1684     }
1685 
generate_spatial_index(&mut self) -> di::SpatialId1686     fn generate_spatial_index(&mut self) -> di::SpatialId {
1687         self.next_spatial_index += 1;
1688         di::SpatialId::new(self.next_spatial_index - 1, self.pipeline_id)
1689     }
1690 
generate_clip_chain_id(&mut self) -> di::ClipChainId1691     fn generate_clip_chain_id(&mut self) -> di::ClipChainId {
1692         self.next_clip_chain_id += 1;
1693         di::ClipChainId(self.next_clip_chain_id - 1, self.pipeline_id)
1694     }
1695 
define_scroll_frame( &mut self, parent_space_and_clip: &di::SpaceAndClipInfo, external_id: Option<di::ExternalScrollId>, content_rect: LayoutRect, clip_rect: LayoutRect, scroll_sensitivity: di::ScrollSensitivity, external_scroll_offset: LayoutVector2D, ) -> di::SpaceAndClipInfo1696     pub fn define_scroll_frame(
1697         &mut self,
1698         parent_space_and_clip: &di::SpaceAndClipInfo,
1699         external_id: Option<di::ExternalScrollId>,
1700         content_rect: LayoutRect,
1701         clip_rect: LayoutRect,
1702         scroll_sensitivity: di::ScrollSensitivity,
1703         external_scroll_offset: LayoutVector2D,
1704     ) -> di::SpaceAndClipInfo {
1705         let clip_id = self.generate_clip_index();
1706         let scroll_frame_id = self.generate_spatial_index();
1707         let item = di::DisplayItem::ScrollFrame(di::ScrollFrameDisplayItem {
1708             content_rect,
1709             clip_rect,
1710             parent_space_and_clip: *parent_space_and_clip,
1711             clip_id,
1712             scroll_frame_id,
1713             external_id,
1714             scroll_sensitivity,
1715             external_scroll_offset,
1716         });
1717 
1718         self.push_item(&item);
1719 
1720         di::SpaceAndClipInfo {
1721             spatial_id: scroll_frame_id,
1722             clip_id,
1723         }
1724     }
1725 
define_clip_chain<I>( &mut self, parent: Option<di::ClipChainId>, clips: I, ) -> di::ClipChainId where I: IntoIterator<Item = di::ClipId>, I::IntoIter: ExactSizeIterator + Clone,1726     pub fn define_clip_chain<I>(
1727         &mut self,
1728         parent: Option<di::ClipChainId>,
1729         clips: I,
1730     ) -> di::ClipChainId
1731     where
1732         I: IntoIterator<Item = di::ClipId>,
1733         I::IntoIter: ExactSizeIterator + Clone,
1734     {
1735         let id = self.generate_clip_chain_id();
1736         self.push_item(&di::DisplayItem::ClipChain(di::ClipChainItem { id, parent }));
1737         self.push_iter(clips);
1738         id
1739     }
1740 
define_clip_image_mask( &mut self, parent_space_and_clip: &di::SpaceAndClipInfo, image_mask: di::ImageMask, ) -> di::ClipId1741     pub fn define_clip_image_mask(
1742         &mut self,
1743         parent_space_and_clip: &di::SpaceAndClipInfo,
1744         image_mask: di::ImageMask,
1745     ) -> di::ClipId {
1746         let id = self.generate_clip_index();
1747         let item = di::DisplayItem::ImageMaskClip(di::ImageMaskClipDisplayItem {
1748             id,
1749             parent_space_and_clip: *parent_space_and_clip,
1750             image_mask,
1751         });
1752 
1753         self.push_item(&item);
1754         id
1755     }
1756 
define_clip_rect( &mut self, parent_space_and_clip: &di::SpaceAndClipInfo, clip_rect: LayoutRect, ) -> di::ClipId1757     pub fn define_clip_rect(
1758         &mut self,
1759         parent_space_and_clip: &di::SpaceAndClipInfo,
1760         clip_rect: LayoutRect,
1761     ) -> di::ClipId {
1762         let id = self.generate_clip_index();
1763         let item = di::DisplayItem::RectClip(di::RectClipDisplayItem {
1764             id,
1765             parent_space_and_clip: *parent_space_and_clip,
1766             clip_rect,
1767         });
1768 
1769         self.push_item(&item);
1770         id
1771     }
1772 
define_clip_rounded_rect( &mut self, parent_space_and_clip: &di::SpaceAndClipInfo, clip: di::ComplexClipRegion, ) -> di::ClipId1773     pub fn define_clip_rounded_rect(
1774         &mut self,
1775         parent_space_and_clip: &di::SpaceAndClipInfo,
1776         clip: di::ComplexClipRegion,
1777     ) -> di::ClipId {
1778         let id = self.generate_clip_index();
1779         let item = di::DisplayItem::RoundedRectClip(di::RoundedRectClipDisplayItem {
1780             id,
1781             parent_space_and_clip: *parent_space_and_clip,
1782             clip,
1783         });
1784 
1785         self.push_item(&item);
1786         id
1787     }
1788 
define_clip<I>( &mut self, parent_space_and_clip: &di::SpaceAndClipInfo, clip_rect: LayoutRect, complex_clips: I, ) -> di::ClipId where I: IntoIterator<Item = di::ComplexClipRegion>, I::IntoIter: ExactSizeIterator + Clone,1789     pub fn define_clip<I>(
1790         &mut self,
1791         parent_space_and_clip: &di::SpaceAndClipInfo,
1792         clip_rect: LayoutRect,
1793         complex_clips: I,
1794     ) -> di::ClipId
1795     where
1796         I: IntoIterator<Item = di::ComplexClipRegion>,
1797         I::IntoIter: ExactSizeIterator + Clone,
1798     {
1799         let id = self.generate_clip_index();
1800         let item = di::DisplayItem::Clip(di::ClipDisplayItem {
1801             id,
1802             parent_space_and_clip: *parent_space_and_clip,
1803             clip_rect,
1804         });
1805 
1806         self.push_item(&item);
1807         self.push_iter(complex_clips);
1808         id
1809     }
1810 
define_sticky_frame( &mut self, parent_spatial_id: di::SpatialId, frame_rect: LayoutRect, margins: SideOffsets2D<Option<f32>, LayoutPixel>, vertical_offset_bounds: di::StickyOffsetBounds, horizontal_offset_bounds: di::StickyOffsetBounds, previously_applied_offset: LayoutVector2D, ) -> di::SpatialId1811     pub fn define_sticky_frame(
1812         &mut self,
1813         parent_spatial_id: di::SpatialId,
1814         frame_rect: LayoutRect,
1815         margins: SideOffsets2D<Option<f32>, LayoutPixel>,
1816         vertical_offset_bounds: di::StickyOffsetBounds,
1817         horizontal_offset_bounds: di::StickyOffsetBounds,
1818         previously_applied_offset: LayoutVector2D,
1819     ) -> di::SpatialId {
1820         let id = self.generate_spatial_index();
1821         let item = di::DisplayItem::StickyFrame(di::StickyFrameDisplayItem {
1822             parent_spatial_id,
1823             id,
1824             bounds: frame_rect,
1825             margins,
1826             vertical_offset_bounds,
1827             horizontal_offset_bounds,
1828             previously_applied_offset,
1829         });
1830 
1831         self.push_item(&item);
1832         id
1833     }
1834 
push_iframe( &mut self, bounds: LayoutRect, clip_rect: LayoutRect, space_and_clip: &di::SpaceAndClipInfo, pipeline_id: PipelineId, ignore_missing_pipeline: bool )1835     pub fn push_iframe(
1836         &mut self,
1837         bounds: LayoutRect,
1838         clip_rect: LayoutRect,
1839         space_and_clip: &di::SpaceAndClipInfo,
1840         pipeline_id: PipelineId,
1841         ignore_missing_pipeline: bool
1842     ) {
1843         let item = di::DisplayItem::Iframe(di::IframeDisplayItem {
1844             bounds,
1845             clip_rect,
1846             space_and_clip: *space_and_clip,
1847             pipeline_id,
1848             ignore_missing_pipeline,
1849         });
1850         self.push_item(&item);
1851     }
1852 
push_shadow( &mut self, space_and_clip: &di::SpaceAndClipInfo, shadow: di::Shadow, should_inflate: bool, )1853     pub fn push_shadow(
1854         &mut self,
1855         space_and_clip: &di::SpaceAndClipInfo,
1856         shadow: di::Shadow,
1857         should_inflate: bool,
1858     ) {
1859         let item = di::DisplayItem::PushShadow(di::PushShadowDisplayItem {
1860             space_and_clip: *space_and_clip,
1861             shadow,
1862             should_inflate,
1863         });
1864         self.push_item(&item);
1865     }
1866 
pop_all_shadows(&mut self)1867     pub fn pop_all_shadows(&mut self) {
1868         self.push_item(&di::DisplayItem::PopAllShadows);
1869     }
1870 
start_item_group(&mut self)1871     pub fn start_item_group(&mut self) {
1872         debug_assert!(!self.writing_to_chunk);
1873         debug_assert!(self.pending_chunk.is_empty());
1874 
1875         self.writing_to_chunk = true;
1876     }
1877 
flush_pending_item_group(&mut self, key: di::ItemKey)1878     fn flush_pending_item_group(&mut self, key: di::ItemKey) {
1879         // Push RetainedItems-marker to extra_data section.
1880         self.push_retained_items(key);
1881 
1882         // Push pending chunk to extra_data section.
1883         self.extra_data.append(&mut self.pending_chunk);
1884 
1885         // Push ReuseItems-marker to data section.
1886         self.push_reuse_items(key);
1887     }
1888 
finish_item_group(&mut self, key: di::ItemKey) -> bool1889     pub fn finish_item_group(&mut self, key: di::ItemKey) -> bool {
1890         debug_assert!(self.writing_to_chunk);
1891         self.writing_to_chunk = false;
1892 
1893         if self.pending_chunk.is_empty() {
1894             return false;
1895         }
1896 
1897         self.flush_pending_item_group(key);
1898         true
1899     }
1900 
cancel_item_group(&mut self, discard: bool)1901     pub fn cancel_item_group(&mut self, discard: bool) {
1902         debug_assert!(self.writing_to_chunk);
1903         self.writing_to_chunk = false;
1904 
1905         if discard {
1906             self.pending_chunk.clear();
1907         } else {
1908             // Push pending chunk to data section.
1909             self.data.append(&mut self.pending_chunk);
1910         }
1911     }
1912 
push_reuse_items(&mut self, key: di::ItemKey)1913     pub fn push_reuse_items(&mut self, key: di::ItemKey) {
1914         self.push_item_to_section(
1915             &di::DisplayItem::ReuseItems(key),
1916             DisplayListSection::Data
1917         );
1918     }
1919 
push_retained_items(&mut self, key: di::ItemKey)1920     fn push_retained_items(&mut self, key: di::ItemKey) {
1921         self.push_item_to_section(
1922             &di::DisplayItem::RetainedItems(key),
1923             DisplayListSection::ExtraData
1924         );
1925     }
1926 
set_cache_size(&mut self, cache_size: usize)1927     pub fn set_cache_size(&mut self, cache_size: usize) {
1928         self.cache_size = cache_size;
1929     }
1930 
finalize(mut self) -> (PipelineId, LayoutSize, BuiltDisplayList)1931     pub fn finalize(mut self) -> (PipelineId, LayoutSize, BuiltDisplayList) {
1932         assert!(self.save_state.is_none(), "Finalized DisplayListBuilder with a pending save");
1933 
1934         if let Some(content) = self.serialized_content_buffer.take() {
1935             println!("-- WebRender display list for {:?} --\n{}",
1936                 self.pipeline_id, content);
1937         }
1938 
1939         // Add `DisplayItem::max_size` zone of zeroes to the end of display list
1940         // so there is at least this amount available in the display list during
1941         // serialization.
1942         ensure_red_zone::<di::DisplayItem>(&mut self.data);
1943 
1944         let extra_data_offset = self.data.len();
1945 
1946         if self.extra_data.len() > 0 {
1947             ensure_red_zone::<di::DisplayItem>(&mut self.extra_data);
1948             self.data.extend(self.extra_data);
1949         }
1950 
1951         let end_time = precise_time_ns();
1952         (
1953             self.pipeline_id,
1954             self.content_size,
1955             BuiltDisplayList {
1956                 descriptor: BuiltDisplayListDescriptor {
1957                     builder_start_time: self.builder_start_time,
1958                     builder_finish_time: end_time,
1959                     send_start_time: end_time,
1960                     total_clip_nodes: self.next_clip_index,
1961                     total_spatial_nodes: self.next_spatial_index,
1962                     cache_size: self.cache_size,
1963                     extra_data_offset,
1964                 },
1965                 data: self.data,
1966             },
1967         )
1968     }
1969 }
1970