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 #![crate_name = "gfx_traits"]
6 #![crate_type = "rlib"]
7 
8 #![deny(unsafe_code)]
9 
10 extern crate malloc_size_of;
11 #[macro_use] extern crate malloc_size_of_derive;
12 #[macro_use] extern crate range;
13 #[macro_use] extern crate serde;
14 
15 pub mod print_tree;
16 
17 use range::RangeIndex;
18 use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
19 
20 /// A newtype struct for denoting the age of messages; prevents race conditions.
21 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
22 pub struct Epoch(pub u32);
23 
24 impl Epoch {
next(&mut self)25     pub fn next(&mut self) {
26         self.0 += 1;
27     }
28 }
29 
30 /// A unique ID for every stacking context.
31 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
32 pub struct StackingContextId(
33     /// The identifier for this StackingContext, derived from the Flow's memory address
34     /// and fragment type.  As a space optimization, these are combined into a single word.
35     pub u64
36 );
37 
38 impl StackingContextId {
39     /// Returns the stacking context ID for the outer document/layout root.
40     #[inline]
root() -> StackingContextId41     pub fn root() -> StackingContextId {
42         StackingContextId(0)
43     }
44 
next(&self) -> StackingContextId45     pub fn next(&self) -> StackingContextId {
46         let StackingContextId(id) = *self;
47         StackingContextId(id + 1)
48     }
49 }
50 
51 int_range_index! {
52     #[derive(Deserialize, Serialize)]
53     #[doc = "An index that refers to a byte offset in a text run. This could \
54              point to the middle of a glyph."]
55     #[derive(MallocSizeOf)]
56     struct ByteIndex(isize)
57 }
58 
59 /// The type of fragment that a scroll root is created for.
60 ///
61 /// This can only ever grow to maximum 4 entries. That's because we cram the value of this enum
62 /// into the lower 2 bits of the `ScrollRootId`, which otherwise contains a 32-bit-aligned
63 /// heap address.
64 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
65 pub enum FragmentType {
66     /// A StackingContext for the fragment body itself.
67     FragmentBody,
68     /// A StackingContext created to contain ::before pseudo-element content.
69     BeforePseudoContent,
70     /// A StackingContext created to contain ::after pseudo-element content.
71     AfterPseudoContent,
72 }
73 
74 /// The next ID that will be used for a special scroll root id.
75 ///
76 /// A special scroll root is a scroll root that is created for generated content.
77 static NEXT_SPECIAL_SCROLL_ROOT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
78 
79 /// If none of the bits outside this mask are set, the scroll root is a special scroll root.
80 /// Note that we assume that the top 16 bits of the address space are unused on the platform.
81 const SPECIAL_SCROLL_ROOT_ID_MASK: usize = 0xffff;
82 
83 /// Returns a new scroll root ID for a scroll root.
next_special_id() -> usize84 fn next_special_id() -> usize {
85     // We shift this left by 2 to make room for the fragment type ID.
86     ((NEXT_SPECIAL_SCROLL_ROOT_ID.fetch_add(1, Ordering::SeqCst) + 1) << 2) &
87         SPECIAL_SCROLL_ROOT_ID_MASK
88 }
89 
combine_id_with_fragment_type(id: usize, fragment_type: FragmentType) -> usize90 pub fn combine_id_with_fragment_type(id: usize, fragment_type: FragmentType) ->  usize {
91     debug_assert_eq!(id & (fragment_type as usize), 0);
92     if fragment_type == FragmentType::FragmentBody {
93         id
94     } else {
95         next_special_id() | (fragment_type as usize)
96     }
97 }
98 
node_id_from_scroll_id(id: usize) -> Option<usize>99 pub fn node_id_from_scroll_id(id: usize) -> Option<usize> {
100     if (id & !SPECIAL_SCROLL_ROOT_ID_MASK) != 0 {
101         return Some((id & !3) as usize);
102     }
103     None
104 }
105 
106 pub trait DisplayList {
107     /// Returns true if this display list contains meaningful content.
is_contentful(&self) -> bool108     fn is_contentful(&self) -> bool;
109 }
110