aboutsummaryrefslogtreecommitdiffstats
path: root/components/shared/gfx
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2023-10-05 19:47:39 +0200
committerMartin Robinson <mrobinson@igalia.com>2023-11-03 15:38:18 +0000
commitf4d3af296c05260dfbb3deea4f8fa400cb6887d3 (patch)
tree169db2cc68e01a755b30500dd525f1a2ec2da861 /components/shared/gfx
parent863529d9622c68f0a9535225237eb5e5c5b8c757 (diff)
downloadservo-f4d3af296c05260dfbb3deea4f8fa400cb6887d3.tar.gz
servo-f4d3af296c05260dfbb3deea4f8fa400cb6887d3.zip
Move `*_traits` and other shared types to `shared`
This is the start of the organization of types that are in their own crates in order to break dependency cycles between other crates. The idea here is that putting these packages into their own directory is the first step toward cleaning them up. They have grown organically and it is difficult to explain to new folks where to put new shared types. Many of these crates contain more than traits or don't contain traits at all. Notably, `script_traits` isn't touched because it is vendored from Gecko. Eventually this will move to `third_party`.
Diffstat (limited to 'components/shared/gfx')
-rw-r--r--components/shared/gfx/Cargo.toml18
-rw-r--r--components/shared/gfx/lib.rs130
-rw-r--r--components/shared/gfx/print_tree.rs89
3 files changed, 237 insertions, 0 deletions
diff --git a/components/shared/gfx/Cargo.toml b/components/shared/gfx/Cargo.toml
new file mode 100644
index 00000000000..f94b5870c35
--- /dev/null
+++ b/components/shared/gfx/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "gfx_traits"
+version = "0.0.1"
+authors = ["The Servo Project Developers"]
+license = "MPL-2.0"
+edition = "2018"
+publish = false
+
+[lib]
+name = "gfx_traits"
+path = "lib.rs"
+
+[dependencies]
+malloc_size_of = { path = "../../malloc_size_of" }
+malloc_size_of_derive = { workspace = true }
+range = { path = "../../range" }
+serde = { workspace = true }
+webrender_api = { workspace = true }
diff --git a/components/shared/gfx/lib.rs b/components/shared/gfx/lib.rs
new file mode 100644
index 00000000000..7cac7ef1fb1
--- /dev/null
+++ b/components/shared/gfx/lib.rs
@@ -0,0 +1,130 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+#![crate_name = "gfx_traits"]
+#![crate_type = "rlib"]
+#![deny(unsafe_code)]
+
+pub mod print_tree;
+
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+use malloc_size_of_derive::MallocSizeOf;
+use range::{int_range_index, RangeIndex};
+use serde::{Deserialize, Serialize};
+use webrender_api::{Epoch as WebRenderEpoch, FontInstanceKey, FontKey, NativeFontHandle};
+
+/// A newtype struct for denoting the age of messages; prevents race conditions.
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
+pub struct Epoch(pub u32);
+
+impl Epoch {
+ pub fn next(&mut self) {
+ self.0 += 1;
+ }
+}
+
+impl Into<WebRenderEpoch> for Epoch {
+ fn into(self) -> WebRenderEpoch {
+ WebRenderEpoch(self.0)
+ }
+}
+
+pub trait WebRenderEpochToU16 {
+ fn as_u16(&self) -> u16;
+}
+
+impl WebRenderEpochToU16 for WebRenderEpoch {
+ /// The value of this [`Epoch`] as a u16 value. Note that if this Epoch's
+ /// value is more than u16::MAX, then the return value will be modulo
+ /// u16::MAX.
+ fn as_u16(&self) -> u16 {
+ (self.0 % u16::MAX as u32) as u16
+ }
+}
+
+/// A unique ID for every stacking context.
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, 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.
+ pub u64,
+);
+
+impl StackingContextId {
+ /// Returns the stacking context ID for the outer document/layout root.
+ #[inline]
+ pub fn root() -> StackingContextId {
+ StackingContextId(0)
+ }
+
+ pub fn next(&self) -> StackingContextId {
+ let StackingContextId(id) = *self;
+ StackingContextId(id + 1)
+ }
+}
+
+int_range_index! {
+ #[derive(Deserialize, MallocSizeOf, Serialize)]
+ /// An index that refers to a byte offset in a text run. This could
+ /// the middle of a glyph.
+ struct ByteIndex(isize)
+}
+
+/// The type of fragment that a scroll root is created for.
+///
+/// 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 `ScrollRootId`, which otherwise contains a 32-bit-aligned
+/// heap address.
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+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,
+}
+
+/// The next ID that will be used for a special scroll root id.
+///
+/// A special scroll root is a scroll root that is created for generated content.
+static NEXT_SPECIAL_SCROLL_ROOT_ID: AtomicUsize = AtomicUsize::new(0);
+
+/// If none of the bits outside this mask are set, the scroll root is a special scroll root.
+/// Note that we assume that the top 16 bits of the address space are unused on the platform.
+const SPECIAL_SCROLL_ROOT_ID_MASK: usize = 0xffff;
+
+/// Returns a new scroll root ID for a scroll root.
+fn next_special_id() -> usize {
+ // We shift this left by 2 to make room for the fragment type ID.
+ ((NEXT_SPECIAL_SCROLL_ROOT_ID.fetch_add(1, Ordering::SeqCst) + 1) << 2) &
+ SPECIAL_SCROLL_ROOT_ID_MASK
+}
+
+pub fn combine_id_with_fragment_type(id: usize, fragment_type: FragmentType) -> usize {
+ debug_assert_eq!(id & (fragment_type as usize), 0);
+ if fragment_type == FragmentType::FragmentBody {
+ id
+ } else {
+ next_special_id() | (fragment_type as usize)
+ }
+}
+
+pub fn node_id_from_scroll_id(id: usize) -> Option<usize> {
+ if (id & !SPECIAL_SCROLL_ROOT_ID_MASK) != 0 {
+ return Some((id & !3) as usize);
+ }
+ None
+}
+
+pub enum FontData {
+ Raw(Vec<u8>),
+ Native(NativeFontHandle),
+}
+
+pub trait WebrenderApi {
+ fn add_font_instance(&self, font_key: FontKey, size: f32) -> FontInstanceKey;
+ fn add_font(&self, data: FontData) -> FontKey;
+}
diff --git a/components/shared/gfx/print_tree.rs b/components/shared/gfx/print_tree.rs
new file mode 100644
index 00000000000..60201733c66
--- /dev/null
+++ b/components/shared/gfx/print_tree.rs
@@ -0,0 +1,89 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+/// A struct that makes it easier to print out a pretty tree of data, which
+/// can be visually scanned more easily.
+pub struct PrintTree {
+ /// The current level of recursion.
+ level: u32,
+
+ /// An item which is queued up, so that we can determine if we need
+ /// a mid-tree prefix or a branch ending prefix.
+ queued_item: Option<String>,
+}
+
+impl PrintTree {
+ pub fn new(title: String) -> PrintTree {
+ println!("\u{250c} {}", title);
+ PrintTree {
+ level: 1,
+ queued_item: None,
+ }
+ }
+
+ /// Descend one level in the tree with the given title string.
+ pub fn new_level(&mut self, queued_title: String) {
+ self.flush_queued_item("\u{251C}\u{2500}");
+
+ self.print_level_prefix();
+
+ let items: Vec<&str> = queued_title.split("\n").collect();
+ println!("\u{251C}\u{2500} {}", items[0]);
+ for i in 1..items.len() {
+ self.print_level_child_indentation();
+ print!("{}", items[i]);
+ if i < items.len() {
+ print!("\n");
+ }
+ }
+
+ self.level = self.level + 1;
+ }
+
+ /// Ascend one level in the tree.
+ pub fn end_level(&mut self) {
+ self.flush_queued_item("\u{2514}\u{2500}");
+ self.level -= 1;
+ }
+
+ /// Add an item to the current level in the tree.
+ pub fn add_item(&mut self, text: String) {
+ self.flush_queued_item("\u{251C}\u{2500}");
+ self.queued_item = Some(text);
+ }
+
+ fn print_level_prefix(&self) {
+ for _ in 0..self.level {
+ print!("\u{2502} ");
+ }
+ }
+
+ fn print_level_child_indentation(&self) {
+ for _ in 0..(self.level + 1) {
+ print!("\u{2502} ");
+ }
+ print!("{}", " ".repeat(7));
+ }
+
+ fn flush_queued_item(&mut self, prefix: &str) {
+ if let Some(queued_item) = self.queued_item.take() {
+ self.print_level_prefix();
+ let items: Vec<&str> = queued_item.split("\n").collect();
+ println!("{} {}", prefix, items[0]);
+ for i in 1..items.len() {
+ self.print_level_child_indentation();
+ print!("{}", items[i]);
+ if i < items.len() {
+ print!("\n");
+ }
+ }
+ }
+ }
+}
+
+impl Drop for PrintTree {
+ fn drop(&mut self) {
+ self.flush_queued_item("\u{2514}\u{2500}");
+ }
+}