mirror of
https://github.com/servo/servo.git
synced 2025-06-28 19:13:41 +01:00
249 lines
8.2 KiB
Rust
249 lines
8.2 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#![feature(custom_derive, plugin, proc_macro, rustc_attrs, structural_match)]
|
|
#![plugin(heapsize_plugin, plugins)]
|
|
|
|
#![crate_name = "gfx_traits"]
|
|
#![crate_type = "rlib"]
|
|
|
|
#![deny(unsafe_code)]
|
|
|
|
extern crate azure;
|
|
extern crate heapsize;
|
|
#[macro_use]
|
|
extern crate range;
|
|
extern crate rustc_serialize;
|
|
extern crate serde;
|
|
#[macro_use]
|
|
extern crate serde_derive;
|
|
|
|
pub mod print_tree;
|
|
|
|
use range::RangeIndex;
|
|
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
|
|
|
|
/// The next ID that will be used for a special stacking context.
|
|
///
|
|
/// A special stacking context is a stacking context that is one of (a) the outer stacking context
|
|
/// of an element with `overflow: scroll`; (b) generated content; (c) both (a) and (b).
|
|
static NEXT_SPECIAL_STACKING_CONTEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
|
|
|
|
/// If none of the bits outside this mask are set, the stacking context is a special stacking
|
|
/// context.
|
|
///
|
|
/// Note that we assume that the top 16 bits of the address space are unused on the platform.
|
|
const SPECIAL_STACKING_CONTEXT_ID_MASK: usize = 0xffff;
|
|
|
|
// Units for use with euclid::length and euclid::scale_factor.
|
|
|
|
/// One hardware pixel.
|
|
///
|
|
/// This unit corresponds to the smallest addressable element of the display hardware.
|
|
#[derive(Copy, Clone, RustcEncodable, Debug)]
|
|
pub enum DevicePixel {}
|
|
|
|
/// One pixel in layer coordinate space.
|
|
///
|
|
/// This unit corresponds to a "pixel" in layer coordinate space, which after scaling and
|
|
/// transformation becomes a device pixel.
|
|
#[derive(Copy, Clone, RustcEncodable, Debug)]
|
|
pub enum LayerPixel {}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub enum LayerKind {
|
|
NoTransform,
|
|
HasTransform,
|
|
}
|
|
|
|
#[derive(Clone, PartialEq, Eq, Copy, Hash, Deserialize, Serialize, HeapSizeOf)]
|
|
pub enum LayerType {
|
|
/// A layer for the fragment body itself.
|
|
FragmentBody,
|
|
/// An extra layer created for a DOM fragments with overflow:scroll.
|
|
OverflowScroll,
|
|
/// A layer created to contain ::before pseudo-element content.
|
|
BeforePseudoContent,
|
|
/// A layer created to contain ::after pseudo-element content.
|
|
AfterPseudoContent,
|
|
}
|
|
|
|
/// The scrolling policy of a layer.
|
|
#[derive(Clone, PartialEq, Eq, Copy, Deserialize, Serialize, Debug, HeapSizeOf)]
|
|
pub enum ScrollPolicy {
|
|
/// These layers scroll when the parent receives a scrolling message.
|
|
Scrollable,
|
|
/// These layers do not scroll when the parent receives a scrolling message.
|
|
FixedPosition,
|
|
}
|
|
|
|
/// A newtype struct for denoting the age of messages; prevents race conditions.
|
|
#[derive(PartialEq, Eq, Debug, Copy, Clone, PartialOrd, Ord, Deserialize, Serialize)]
|
|
pub struct Epoch(pub u32);
|
|
|
|
impl Epoch {
|
|
pub fn next(&mut self) {
|
|
self.0 += 1;
|
|
}
|
|
}
|
|
|
|
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
|
pub struct FrameTreeId(pub u32);
|
|
|
|
impl FrameTreeId {
|
|
pub fn next(&mut self) {
|
|
self.0 += 1;
|
|
}
|
|
}
|
|
|
|
/// A unique ID for every stacking context.
|
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, PartialEq, Serialize)]
|
|
pub struct StackingContextId(
|
|
/// The identifier for this StackingContext, derived from the Flow's memory address
|
|
/// and fragment type. As a space optimization, these are combined into a single word.
|
|
usize
|
|
);
|
|
|
|
impl StackingContextId {
|
|
#[inline]
|
|
pub fn new(id: usize) -> StackingContextId {
|
|
StackingContextId::new_of_type(id, FragmentType::FragmentBody)
|
|
}
|
|
|
|
/// Returns a new stacking context ID for a special stacking context.
|
|
fn next_special_id() -> usize {
|
|
// We shift this left by 2 to make room for the fragment type ID.
|
|
((NEXT_SPECIAL_STACKING_CONTEXT_ID.fetch_add(1, Ordering::SeqCst) + 1) << 2) &
|
|
SPECIAL_STACKING_CONTEXT_ID_MASK
|
|
}
|
|
|
|
#[inline]
|
|
pub fn new_of_type(id: usize, fragment_type: FragmentType) -> StackingContextId {
|
|
debug_assert_eq!(id & (fragment_type as usize), 0);
|
|
if fragment_type == FragmentType::FragmentBody {
|
|
StackingContextId(id)
|
|
} else {
|
|
StackingContextId(StackingContextId::next_special_id() | (fragment_type as usize))
|
|
}
|
|
}
|
|
|
|
/// Returns an ID for the stacking context that forms the outer stacking context of an element
|
|
/// with `overflow: scroll`.
|
|
#[inline(always)]
|
|
pub fn new_outer(fragment_type: FragmentType) -> StackingContextId {
|
|
StackingContextId(StackingContextId::next_special_id() | (fragment_type as usize))
|
|
}
|
|
|
|
#[inline]
|
|
pub fn fragment_type(&self) -> FragmentType {
|
|
FragmentType::from_usize(self.0 & 3)
|
|
}
|
|
|
|
#[inline]
|
|
pub fn id(&self) -> usize {
|
|
self.0 & !3
|
|
}
|
|
|
|
/// Returns the stacking context ID for the outer document/layout root.
|
|
#[inline]
|
|
pub fn root() -> StackingContextId {
|
|
StackingContextId(0)
|
|
}
|
|
|
|
/// Returns true if this is a special stacking context.
|
|
///
|
|
/// A special stacking context is a stacking context that is one of (a) the outer stacking
|
|
/// context of an element with `overflow: scroll`; (b) generated content; (c) both (a) and (b).
|
|
#[inline]
|
|
pub fn is_special(&self) -> bool {
|
|
(self.0 & !SPECIAL_STACKING_CONTEXT_ID_MASK) == 0
|
|
}
|
|
}
|
|
|
|
/// A unique ID for every scrolling root.
|
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, PartialEq, Serialize)]
|
|
pub struct ScrollRootId(
|
|
/// The identifier for this StackingContext, derived from the Flow's memory address
|
|
/// and fragment type. As a space optimization, these are combined into a single word.
|
|
pub usize
|
|
);
|
|
|
|
impl ScrollRootId {
|
|
/// Returns a new stacking context ID for a special stacking context.
|
|
fn next_special_id() -> usize {
|
|
// We shift this left by 2 to make room for the fragment type ID.
|
|
((NEXT_SPECIAL_STACKING_CONTEXT_ID.fetch_add(1, Ordering::SeqCst) + 1) << 2) &
|
|
SPECIAL_STACKING_CONTEXT_ID_MASK
|
|
}
|
|
|
|
#[inline]
|
|
pub fn new_of_type(id: usize, fragment_type: FragmentType) -> ScrollRootId {
|
|
debug_assert_eq!(id & (fragment_type as usize), 0);
|
|
if fragment_type == FragmentType::FragmentBody {
|
|
ScrollRootId(id)
|
|
} else {
|
|
ScrollRootId(ScrollRootId::next_special_id() | (fragment_type as usize))
|
|
}
|
|
}
|
|
|
|
/// Returns the stacking context ID for the outer document/layout root.
|
|
#[inline]
|
|
pub fn root() -> ScrollRootId {
|
|
ScrollRootId(0)
|
|
}
|
|
|
|
/// Returns true if this is a special stacking context.
|
|
///
|
|
/// A special stacking context is a stacking context that is one of (a) the outer stacking
|
|
/// context of an element with `overflow: scroll`; (b) generated content; (c) both (a) and (b).
|
|
#[inline]
|
|
pub fn is_special(&self) -> bool {
|
|
(self.0 & !SPECIAL_STACKING_CONTEXT_ID_MASK) == 0
|
|
}
|
|
|
|
#[inline]
|
|
pub fn id(&self) -> usize {
|
|
self.0 & !3
|
|
}
|
|
|
|
#[inline]
|
|
pub fn fragment_type(&self) -> FragmentType {
|
|
FragmentType::from_usize(self.0 & 3)
|
|
}
|
|
}
|
|
|
|
/// The type of fragment that a stacking context represents.
|
|
///
|
|
/// This can only ever grow to maximum 4 entries. That's because we cram the value of this enum
|
|
/// into the lower 2 bits of the `StackingContextId`, which otherwise contains a 32-bit-aligned
|
|
/// heap address.
|
|
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Deserialize, Serialize, HeapSizeOf)]
|
|
pub enum FragmentType {
|
|
/// A StackingContext for the fragment body itself.
|
|
FragmentBody,
|
|
/// A StackingContext created to contain ::before pseudo-element content.
|
|
BeforePseudoContent,
|
|
/// A StackingContext created to contain ::after pseudo-element content.
|
|
AfterPseudoContent,
|
|
}
|
|
|
|
impl FragmentType {
|
|
#[inline]
|
|
pub fn from_usize(n: usize) -> FragmentType {
|
|
debug_assert!(n < 3);
|
|
match n {
|
|
0 => FragmentType::FragmentBody,
|
|
1 => FragmentType::BeforePseudoContent,
|
|
_ => FragmentType::AfterPseudoContent,
|
|
}
|
|
}
|
|
}
|
|
|
|
int_range_index! {
|
|
#[derive(Deserialize, Serialize, RustcEncodable)]
|
|
#[doc = "An index that refers to a byte offset in a text run. This could \
|
|
point to the middle of a glyph."]
|
|
#[derive(HeapSizeOf)]
|
|
struct ByteIndex(isize)
|
|
}
|