mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
style: Slim down SharedStyleContext.
This slims down SharedStyleContext, in preparation for a few things. First, I would like to eventually move the stylist to the document in Servo, in order for it to hold the StyleSheetSet. Also, this gets rid of a fair amount of overhead while creating it in stylo. Fixes bug 1363245.
This commit is contained in:
parent
f579405510
commit
ebd9bf8181
6 changed files with 104 additions and 85 deletions
|
@ -38,7 +38,6 @@ use style::logical_geometry::{WritingMode, BlockFlowDirection, InlineBaseDirecti
|
||||||
use style::properties::{style_structs, PropertyId, PropertyDeclarationId, LonghandId};
|
use style::properties::{style_structs, PropertyId, PropertyDeclarationId, LonghandId};
|
||||||
use style::properties::longhands::{display, position};
|
use style::properties::longhands::{display, position};
|
||||||
use style::selector_parser::PseudoElement;
|
use style::selector_parser::PseudoElement;
|
||||||
use style::stylist::Stylist;
|
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use style_traits::cursor::Cursor;
|
use style_traits::cursor::Cursor;
|
||||||
use webrender_traits::ClipId;
|
use webrender_traits::ClipId;
|
||||||
|
@ -54,9 +53,6 @@ pub struct LayoutThreadData {
|
||||||
/// The root stacking context.
|
/// The root stacking context.
|
||||||
pub display_list: Option<Arc<DisplayList>>,
|
pub display_list: Option<Arc<DisplayList>>,
|
||||||
|
|
||||||
/// Performs CSS selector matching and style resolution.
|
|
||||||
pub stylist: ::StyleArc<Stylist>,
|
|
||||||
|
|
||||||
/// A queued response for the union of the content boxes of a node.
|
/// A queued response for the union of the content boxes of a node.
|
||||||
pub content_box_response: Option<Rect<Au>>,
|
pub content_box_response: Option<Rect<Au>>,
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ use servo_config::resource_files::read_resource_file;
|
||||||
use servo_geometry::max_rect;
|
use servo_geometry::max_rect;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::hash::BuildHasherDefault;
|
use std::hash::BuildHasherDefault;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
@ -131,6 +132,9 @@ pub struct LayoutThread {
|
||||||
/// The URL of the pipeline that we belong to.
|
/// The URL of the pipeline that we belong to.
|
||||||
url: ServoUrl,
|
url: ServoUrl,
|
||||||
|
|
||||||
|
/// Performs CSS selector matching and style resolution.
|
||||||
|
stylist: ::StyleArc<Stylist>,
|
||||||
|
|
||||||
/// Is the current reflow of an iframe, as opposed to a root window?
|
/// Is the current reflow of an iframe, as opposed to a root window?
|
||||||
is_iframe: bool,
|
is_iframe: bool,
|
||||||
|
|
||||||
|
@ -165,7 +169,7 @@ pub struct LayoutThread {
|
||||||
font_cache_thread: FontCacheThread,
|
font_cache_thread: FontCacheThread,
|
||||||
|
|
||||||
/// Is this the first reflow in this LayoutThread?
|
/// Is this the first reflow in this LayoutThread?
|
||||||
first_reflow: bool,
|
first_reflow: Cell<bool>,
|
||||||
|
|
||||||
/// The workers that we use for parallel operation.
|
/// The workers that we use for parallel operation.
|
||||||
parallel_traversal: Option<rayon::ThreadPool>,
|
parallel_traversal: Option<rayon::ThreadPool>,
|
||||||
|
@ -175,7 +179,7 @@ pub struct LayoutThread {
|
||||||
|
|
||||||
/// Starts at zero, and increased by one every time a layout completes.
|
/// Starts at zero, and increased by one every time a layout completes.
|
||||||
/// This can be used to easily check for invalid stale data.
|
/// This can be used to easily check for invalid stale data.
|
||||||
generation: u32,
|
generation: Cell<u32>,
|
||||||
|
|
||||||
/// A channel on which new animations that have been triggered by style recalculation can be
|
/// A channel on which new animations that have been triggered by style recalculation can be
|
||||||
/// sent.
|
/// sent.
|
||||||
|
@ -188,7 +192,7 @@ pub struct LayoutThread {
|
||||||
outstanding_web_fonts: Arc<AtomicUsize>,
|
outstanding_web_fonts: Arc<AtomicUsize>,
|
||||||
|
|
||||||
/// The root of the flow tree.
|
/// The root of the flow tree.
|
||||||
root_flow: Option<FlowRef>,
|
root_flow: RefCell<Option<FlowRef>>,
|
||||||
|
|
||||||
/// The document-specific shared lock used for author-origin stylesheets
|
/// The document-specific shared lock used for author-origin stylesheets
|
||||||
document_shared_lock: Option<SharedRwLock>,
|
document_shared_lock: Option<SharedRwLock>,
|
||||||
|
@ -200,7 +204,7 @@ pub struct LayoutThread {
|
||||||
expired_animations: StyleArc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
expired_animations: StyleArc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
||||||
|
|
||||||
/// A counter for epoch messages
|
/// A counter for epoch messages
|
||||||
epoch: Epoch,
|
epoch: Cell<Epoch>,
|
||||||
|
|
||||||
/// The size of the viewport. This may be different from the size of the screen due to viewport
|
/// The size of the viewport. This may be different from the size of the screen due to viewport
|
||||||
/// constraints.
|
/// constraints.
|
||||||
|
@ -439,27 +443,27 @@ impl LayoutThread {
|
||||||
mem_profiler_chan: mem_profiler_chan,
|
mem_profiler_chan: mem_profiler_chan,
|
||||||
image_cache: image_cache.clone(),
|
image_cache: image_cache.clone(),
|
||||||
font_cache_thread: font_cache_thread,
|
font_cache_thread: font_cache_thread,
|
||||||
first_reflow: true,
|
first_reflow: Cell::new(true),
|
||||||
font_cache_receiver: font_cache_receiver,
|
font_cache_receiver: font_cache_receiver,
|
||||||
font_cache_sender: ipc_font_cache_sender,
|
font_cache_sender: ipc_font_cache_sender,
|
||||||
parallel_traversal: parallel_traversal,
|
parallel_traversal: parallel_traversal,
|
||||||
parallel_flag: true,
|
parallel_flag: true,
|
||||||
generation: 0,
|
generation: Cell::new(0),
|
||||||
new_animations_sender: new_animations_sender,
|
new_animations_sender: new_animations_sender,
|
||||||
new_animations_receiver: new_animations_receiver,
|
new_animations_receiver: new_animations_receiver,
|
||||||
outstanding_web_fonts: outstanding_web_fonts_counter,
|
outstanding_web_fonts: outstanding_web_fonts_counter,
|
||||||
root_flow: None,
|
root_flow: RefCell::new(None),
|
||||||
document_shared_lock: None,
|
document_shared_lock: None,
|
||||||
running_animations: StyleArc::new(RwLock::new(HashMap::new())),
|
running_animations: StyleArc::new(RwLock::new(HashMap::new())),
|
||||||
expired_animations: StyleArc::new(RwLock::new(HashMap::new())),
|
expired_animations: StyleArc::new(RwLock::new(HashMap::new())),
|
||||||
epoch: Epoch(0),
|
epoch: Cell::new(Epoch(0)),
|
||||||
viewport_size: Size2D::new(Au(0), Au(0)),
|
viewport_size: Size2D::new(Au(0), Au(0)),
|
||||||
webrender_api: webrender_api_sender.create_api(),
|
webrender_api: webrender_api_sender.create_api(),
|
||||||
|
stylist: stylist,
|
||||||
rw_data: Arc::new(Mutex::new(
|
rw_data: Arc::new(Mutex::new(
|
||||||
LayoutThreadData {
|
LayoutThreadData {
|
||||||
constellation_chan: constellation_chan,
|
constellation_chan: constellation_chan,
|
||||||
display_list: None,
|
display_list: None,
|
||||||
stylist: stylist,
|
|
||||||
content_box_response: None,
|
content_box_response: None,
|
||||||
content_boxes_response: Vec::new(),
|
content_boxes_response: Vec::new(),
|
||||||
client_rect_response: Rect::zero(),
|
client_rect_response: Rect::zero(),
|
||||||
|
@ -507,9 +511,8 @@ impl LayoutThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a layout context for use in building display lists, hit testing, &c.
|
// Create a layout context for use in building display lists, hit testing, &c.
|
||||||
fn build_layout_context<'a>(&self,
|
fn build_layout_context<'a>(&'a self,
|
||||||
guards: StylesheetGuards<'a>,
|
guards: StylesheetGuards<'a>,
|
||||||
rw_data: &LayoutThreadData,
|
|
||||||
request_images: bool,
|
request_images: bool,
|
||||||
snapshot_map: &'a SnapshotMap)
|
snapshot_map: &'a SnapshotMap)
|
||||||
-> LayoutContext<'a> {
|
-> LayoutContext<'a> {
|
||||||
|
@ -519,12 +522,12 @@ impl LayoutThread {
|
||||||
LayoutContext {
|
LayoutContext {
|
||||||
id: self.id,
|
id: self.id,
|
||||||
style_context: SharedStyleContext {
|
style_context: SharedStyleContext {
|
||||||
stylist: rw_data.stylist.clone(),
|
stylist: &self.stylist,
|
||||||
options: StyleSystemOptions::default(),
|
options: StyleSystemOptions::default(),
|
||||||
guards: guards,
|
guards: guards,
|
||||||
running_animations: self.running_animations.clone(),
|
running_animations: self.running_animations.clone(),
|
||||||
expired_animations: self.expired_animations.clone(),
|
expired_animations: self.expired_animations.clone(),
|
||||||
error_reporter: Box::new(self.error_reporter.clone()),
|
error_reporter: &self.error_reporter,
|
||||||
local_context_creation_data: Mutex::new(thread_local_style_context_creation_data),
|
local_context_creation_data: Mutex::new(thread_local_style_context_creation_data),
|
||||||
timer: self.timer.clone(),
|
timer: self.timer.clone(),
|
||||||
quirks_mode: self.quirks_mode.unwrap(),
|
quirks_mode: self.quirks_mode.unwrap(),
|
||||||
|
@ -605,7 +608,7 @@ impl LayoutThread {
|
||||||
Msg::AddStylesheet(style_info) => {
|
Msg::AddStylesheet(style_info) => {
|
||||||
self.handle_add_stylesheet(style_info, possibly_locked_rw_data)
|
self.handle_add_stylesheet(style_info, possibly_locked_rw_data)
|
||||||
}
|
}
|
||||||
Msg::SetQuirksMode(mode) => self.handle_set_quirks_mode(possibly_locked_rw_data, mode),
|
Msg::SetQuirksMode(mode) => self.handle_set_quirks_mode(mode),
|
||||||
Msg::GetRPC(response_chan) => {
|
Msg::GetRPC(response_chan) => {
|
||||||
response_chan.send(box LayoutRPCImpl(self.rw_data.clone()) as
|
response_chan.send(box LayoutRPCImpl(self.rw_data.clone()) as
|
||||||
Box<LayoutRPC + Send>).unwrap();
|
Box<LayoutRPC + Send>).unwrap();
|
||||||
|
@ -631,7 +634,7 @@ impl LayoutThread {
|
||||||
},
|
},
|
||||||
Msg::GetCurrentEpoch(sender) => {
|
Msg::GetCurrentEpoch(sender) => {
|
||||||
let _rw_data = possibly_locked_rw_data.lock();
|
let _rw_data = possibly_locked_rw_data.lock();
|
||||||
sender.send(self.epoch).unwrap();
|
sender.send(self.epoch.get()).unwrap();
|
||||||
},
|
},
|
||||||
Msg::AdvanceClockMs(how_many, do_tick) => {
|
Msg::AdvanceClockMs(how_many, do_tick) => {
|
||||||
self.handle_advance_clock_ms(how_many, possibly_locked_rw_data, do_tick);
|
self.handle_advance_clock_ms(how_many, possibly_locked_rw_data, do_tick);
|
||||||
|
@ -676,7 +679,7 @@ impl LayoutThread {
|
||||||
size: display_list.map_or(0, |sc| sc.heap_size_of_children()),
|
size: display_list.map_or(0, |sc| sc.heap_size_of_children()),
|
||||||
});
|
});
|
||||||
|
|
||||||
let stylist = rw_data.stylist.as_ref();
|
let stylist = self.stylist.as_ref();
|
||||||
reports.push(Report {
|
reports.push(Report {
|
||||||
path: path![formatted_url, "layout-thread", "stylist"],
|
path: path![formatted_url, "layout-thread", "stylist"],
|
||||||
kind: ReportKind::ExplicitJemallocHeapSize,
|
kind: ReportKind::ExplicitJemallocHeapSize,
|
||||||
|
@ -752,10 +755,10 @@ impl LayoutThread {
|
||||||
|
|
||||||
let rw_data = possibly_locked_rw_data.lock();
|
let rw_data = possibly_locked_rw_data.lock();
|
||||||
let guard = stylesheet.shared_lock.read();
|
let guard = stylesheet.shared_lock.read();
|
||||||
if stylesheet.is_effective_for_device(&rw_data.stylist.device, &guard) {
|
if stylesheet.is_effective_for_device(&self.stylist.device, &guard) {
|
||||||
add_font_face_rules(&*stylesheet,
|
add_font_face_rules(&*stylesheet,
|
||||||
&guard,
|
&guard,
|
||||||
&rw_data.stylist.device,
|
&self.stylist.device,
|
||||||
&self.font_cache_thread,
|
&self.font_cache_thread,
|
||||||
&self.font_cache_sender,
|
&self.font_cache_sender,
|
||||||
&self.outstanding_web_fonts);
|
&self.outstanding_web_fonts);
|
||||||
|
@ -776,12 +779,8 @@ impl LayoutThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets quirks mode for the document, causing the quirks mode stylesheet to be used.
|
/// Sets quirks mode for the document, causing the quirks mode stylesheet to be used.
|
||||||
fn handle_set_quirks_mode<'a, 'b>(&self,
|
fn handle_set_quirks_mode<'a, 'b>(&mut self, quirks_mode: QuirksMode) {
|
||||||
possibly_locked_rw_data: &mut RwData<'a, 'b>,
|
StyleArc::get_mut(&mut self.stylist).unwrap().set_quirks_mode(quirks_mode);
|
||||||
quirks_mode: QuirksMode) {
|
|
||||||
let mut rw_data = possibly_locked_rw_data.lock();
|
|
||||||
StyleArc::get_mut(&mut rw_data.stylist).unwrap().set_quirks_mode(quirks_mode);
|
|
||||||
possibly_locked_rw_data.block(rw_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_get_layout_root<N: LayoutNode>(&self, node: N) -> Option<FlowRef> {
|
fn try_get_layout_root<N: LayoutNode>(&self, node: N) -> Option<FlowRef> {
|
||||||
|
@ -843,7 +842,7 @@ impl LayoutThread {
|
||||||
|
|
||||||
/// Computes the stacking-relative positions of all flows and, if the painting is dirty and the
|
/// Computes the stacking-relative positions of all flows and, if the painting is dirty and the
|
||||||
/// reflow goal and query type need it, builds the display list.
|
/// reflow goal and query type need it, builds the display list.
|
||||||
fn compute_abs_pos_and_build_display_list(&mut self,
|
fn compute_abs_pos_and_build_display_list(&self,
|
||||||
data: &Reflow,
|
data: &Reflow,
|
||||||
query_type: Option<&ReflowQueryType>,
|
query_type: Option<&ReflowQueryType>,
|
||||||
document: Option<&ServoLayoutDocument>,
|
document: Option<&ServoLayoutDocument>,
|
||||||
|
@ -882,7 +881,7 @@ impl LayoutThread {
|
||||||
|
|
||||||
let root_size = {
|
let root_size = {
|
||||||
let root_flow = flow::base(layout_root);
|
let root_flow = flow::base(layout_root);
|
||||||
if rw_data.stylist.viewport_constraints().is_some() {
|
if self.stylist.viewport_constraints().is_some() {
|
||||||
root_flow.position.size.to_physical(root_flow.writing_mode)
|
root_flow.position.size.to_physical(root_flow.writing_mode)
|
||||||
} else {
|
} else {
|
||||||
root_flow.overflow.scroll.size
|
root_flow.overflow.scroll.size
|
||||||
|
@ -938,13 +937,14 @@ impl LayoutThread {
|
||||||
let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(),
|
let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(),
|
||||||
self.viewport_size.height.to_f32_px());
|
self.viewport_size.height.to_f32_px());
|
||||||
|
|
||||||
self.epoch.next();
|
let mut epoch = self.epoch.get();
|
||||||
let Epoch(epoch_number) = self.epoch;
|
epoch.next();
|
||||||
|
self.epoch.set(epoch);
|
||||||
|
|
||||||
let viewport_size = webrender_traits::LayoutSize::from_untyped(&viewport_size);
|
let viewport_size = webrender_traits::LayoutSize::from_untyped(&viewport_size);
|
||||||
self.webrender_api.set_display_list(
|
self.webrender_api.set_display_list(
|
||||||
Some(get_root_flow_background_color(layout_root)),
|
Some(get_root_flow_background_color(layout_root)),
|
||||||
webrender_traits::Epoch(epoch_number),
|
webrender_traits::Epoch(epoch.0),
|
||||||
viewport_size,
|
viewport_size,
|
||||||
builder.finalize(),
|
builder.finalize(),
|
||||||
true);
|
true);
|
||||||
|
@ -1038,11 +1038,11 @@ impl LayoutThread {
|
||||||
self.document_shared_lock = Some(document_shared_lock.clone());
|
self.document_shared_lock = Some(document_shared_lock.clone());
|
||||||
let author_guard = document_shared_lock.read();
|
let author_guard = document_shared_lock.read();
|
||||||
let device = Device::new(MediaType::Screen, initial_viewport);
|
let device = Device::new(MediaType::Screen, initial_viewport);
|
||||||
StyleArc::get_mut(&mut rw_data.stylist).unwrap()
|
StyleArc::get_mut(&mut self.stylist).unwrap()
|
||||||
.set_device(device, &author_guard, &data.document_stylesheets);
|
.set_device(device, &author_guard, &data.document_stylesheets);
|
||||||
|
|
||||||
self.viewport_size =
|
self.viewport_size =
|
||||||
rw_data.stylist.viewport_constraints().map_or(current_screen_size, |constraints| {
|
self.stylist.viewport_constraints().map_or(current_screen_size, |constraints| {
|
||||||
debug!("Viewport constraints: {:?}", constraints);
|
debug!("Viewport constraints: {:?}", constraints);
|
||||||
|
|
||||||
// other rules are evaluated against the actual viewport
|
// other rules are evaluated against the actual viewport
|
||||||
|
@ -1052,7 +1052,7 @@ impl LayoutThread {
|
||||||
|
|
||||||
let viewport_size_changed = self.viewport_size != old_viewport_size;
|
let viewport_size_changed = self.viewport_size != old_viewport_size;
|
||||||
if viewport_size_changed {
|
if viewport_size_changed {
|
||||||
if let Some(constraints) = rw_data.stylist.viewport_constraints() {
|
if let Some(constraints) = self.stylist.viewport_constraints() {
|
||||||
// let the constellation know about the viewport constraints
|
// let the constellation know about the viewport constraints
|
||||||
rw_data.constellation_chan
|
rw_data.constellation_chan
|
||||||
.send(ConstellationMsg::ViewportConstrained(self.id, constraints.clone()))
|
.send(ConstellationMsg::ViewportConstrained(self.id, constraints.clone()))
|
||||||
|
@ -1092,7 +1092,7 @@ impl LayoutThread {
|
||||||
let mut extra_data = ExtraStyleData {
|
let mut extra_data = ExtraStyleData {
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
};
|
};
|
||||||
let needs_dirtying = StyleArc::get_mut(&mut rw_data.stylist).unwrap().update(
|
let needs_dirtying = StyleArc::get_mut(&mut self.stylist).unwrap().update(
|
||||||
&data.document_stylesheets,
|
&data.document_stylesheets,
|
||||||
&guards,
|
&guards,
|
||||||
Some(ua_stylesheets),
|
Some(ua_stylesheets),
|
||||||
|
@ -1158,7 +1158,7 @@ impl LayoutThread {
|
||||||
|
|
||||||
// Create a layout context for use throughout the following passes.
|
// Create a layout context for use throughout the following passes.
|
||||||
let mut layout_context =
|
let mut layout_context =
|
||||||
self.build_layout_context(guards.clone(), &*rw_data, true, &map);
|
self.build_layout_context(guards.clone(), true, &map);
|
||||||
|
|
||||||
// NB: Type inference falls apart here for some reason, so we need to be very verbose. :-(
|
// NB: Type inference falls apart here for some reason, so we need to be very verbose. :-(
|
||||||
let traversal_driver = if self.parallel_flag && self.parallel_traversal.is_some() {
|
let traversal_driver = if self.parallel_flag && self.parallel_traversal.is_some() {
|
||||||
|
@ -1185,7 +1185,7 @@ impl LayoutThread {
|
||||||
|| {
|
|| {
|
||||||
// Perform CSS selector matching and flow construction.
|
// Perform CSS selector matching and flow construction.
|
||||||
if traversal_driver.is_parallel() {
|
if traversal_driver.is_parallel() {
|
||||||
let pool = self.parallel_traversal.as_mut().unwrap();
|
let pool = self.parallel_traversal.as_ref().unwrap();
|
||||||
// Parallel mode
|
// Parallel mode
|
||||||
parallel::traverse_dom::<ServoLayoutElement, RecalcStyleAndConstructFlows>(
|
parallel::traverse_dom::<ServoLayoutElement, RecalcStyleAndConstructFlows>(
|
||||||
&traversal, element, token, pool);
|
&traversal, element, token, pool);
|
||||||
|
@ -1208,7 +1208,7 @@ impl LayoutThread {
|
||||||
0);
|
0);
|
||||||
|
|
||||||
// Retrieve the (possibly rebuilt) root flow.
|
// Retrieve the (possibly rebuilt) root flow.
|
||||||
self.root_flow = self.try_get_layout_root(element.as_node());
|
*self.root_flow.borrow_mut() = self.try_get_layout_root(element.as_node());
|
||||||
}
|
}
|
||||||
|
|
||||||
for element in elements_with_snapshot {
|
for element in elements_with_snapshot {
|
||||||
|
@ -1229,7 +1229,7 @@ impl LayoutThread {
|
||||||
unsafe { layout_context.style_context.stylist.rule_tree.maybe_gc(); }
|
unsafe { layout_context.style_context.stylist.rule_tree.maybe_gc(); }
|
||||||
|
|
||||||
// Perform post-style recalculation layout passes.
|
// Perform post-style recalculation layout passes.
|
||||||
if let Some(mut root_flow) = self.root_flow.clone() {
|
if let Some(mut root_flow) = self.root_flow.borrow().clone() {
|
||||||
self.perform_post_style_recalc_layout_passes(&mut root_flow,
|
self.perform_post_style_recalc_layout_passes(&mut root_flow,
|
||||||
&data.reflow_info,
|
&data.reflow_info,
|
||||||
Some(&data.query_type),
|
Some(&data.query_type),
|
||||||
|
@ -1243,7 +1243,7 @@ impl LayoutThread {
|
||||||
&mut layout_context);
|
&mut layout_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn respond_to_query_if_necessary(&mut self,
|
fn respond_to_query_if_necessary(&self,
|
||||||
query_type: &ReflowQueryType,
|
query_type: &ReflowQueryType,
|
||||||
rw_data: &mut LayoutThreadData,
|
rw_data: &mut LayoutThreadData,
|
||||||
context: &mut LayoutContext) {
|
context: &mut LayoutContext) {
|
||||||
|
@ -1253,7 +1253,7 @@ impl LayoutThread {
|
||||||
};
|
};
|
||||||
rw_data.pending_images = pending_images;
|
rw_data.pending_images = pending_images;
|
||||||
|
|
||||||
let mut root_flow = match self.root_flow.clone() {
|
let mut root_flow = match self.root_flow.borrow().clone() {
|
||||||
Some(root_flow) => root_flow,
|
Some(root_flow) => root_flow,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
@ -1390,7 +1390,7 @@ impl LayoutThread {
|
||||||
println!("**** pipeline={}\tForDisplay\tSpecial\tAnimationTick", self.id);
|
println!("**** pipeline={}\tForDisplay\tSpecial\tAnimationTick", self.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut root_flow) = self.root_flow.clone() {
|
if let Some(mut root_flow) = self.root_flow.borrow().clone() {
|
||||||
let reflow_info = Reflow {
|
let reflow_info = Reflow {
|
||||||
goal: ReflowGoal::ForDisplay,
|
goal: ReflowGoal::ForDisplay,
|
||||||
page_clip_rect: max_rect(),
|
page_clip_rect: max_rect(),
|
||||||
|
@ -1407,7 +1407,6 @@ impl LayoutThread {
|
||||||
};
|
};
|
||||||
let snapshots = SnapshotMap::new();
|
let snapshots = SnapshotMap::new();
|
||||||
let mut layout_context = self.build_layout_context(guards,
|
let mut layout_context = self.build_layout_context(guards,
|
||||||
&*rw_data,
|
|
||||||
false,
|
false,
|
||||||
&snapshots);
|
&snapshots);
|
||||||
|
|
||||||
|
@ -1432,7 +1431,7 @@ impl LayoutThread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_post_style_recalc_layout_passes(&mut self,
|
fn perform_post_style_recalc_layout_passes(&self,
|
||||||
root_flow: &mut FlowRef,
|
root_flow: &mut FlowRef,
|
||||||
data: &Reflow,
|
data: &Reflow,
|
||||||
query_type: Option<&ReflowQueryType>,
|
query_type: Option<&ReflowQueryType>,
|
||||||
|
@ -1486,7 +1485,7 @@ impl LayoutThread {
|
||||||
|| {
|
|| {
|
||||||
let profiler_metadata = self.profiler_metadata();
|
let profiler_metadata = self.profiler_metadata();
|
||||||
|
|
||||||
if let (true, Some(traversal)) = (self.parallel_flag, self.parallel_traversal.as_mut()) {
|
if let (true, Some(traversal)) = (self.parallel_flag, self.parallel_traversal.as_ref()) {
|
||||||
// Parallel mode.
|
// Parallel mode.
|
||||||
LayoutThread::solve_constraints_parallel(traversal,
|
LayoutThread::solve_constraints_parallel(traversal,
|
||||||
FlowRef::deref_mut(root_flow),
|
FlowRef::deref_mut(root_flow),
|
||||||
|
@ -1515,31 +1514,31 @@ impl LayoutThread {
|
||||||
context);
|
context);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_post_main_layout_passes(&mut self,
|
fn perform_post_main_layout_passes(&self,
|
||||||
data: &Reflow,
|
data: &Reflow,
|
||||||
query_type: Option<&ReflowQueryType>,
|
query_type: Option<&ReflowQueryType>,
|
||||||
document: Option<&ServoLayoutDocument>,
|
document: Option<&ServoLayoutDocument>,
|
||||||
rw_data: &mut LayoutThreadData,
|
rw_data: &mut LayoutThreadData,
|
||||||
layout_context: &mut LayoutContext) {
|
layout_context: &mut LayoutContext) {
|
||||||
// Build the display list if necessary, and send it to the painter.
|
// Build the display list if necessary, and send it to the painter.
|
||||||
if let Some(mut root_flow) = self.root_flow.clone() {
|
if let Some(mut root_flow) = self.root_flow.borrow().clone() {
|
||||||
self.compute_abs_pos_and_build_display_list(data,
|
self.compute_abs_pos_and_build_display_list(data,
|
||||||
query_type,
|
query_type,
|
||||||
document,
|
document,
|
||||||
FlowRef::deref_mut(&mut root_flow),
|
FlowRef::deref_mut(&mut root_flow),
|
||||||
&mut *layout_context,
|
&mut *layout_context,
|
||||||
rw_data);
|
rw_data);
|
||||||
self.first_reflow = false;
|
self.first_reflow.set(false);
|
||||||
|
|
||||||
if opts::get().trace_layout {
|
if opts::get().trace_layout {
|
||||||
layout_debug::end_trace(self.generation);
|
layout_debug::end_trace(self.generation.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts::get().dump_flow_tree {
|
if opts::get().dump_flow_tree {
|
||||||
root_flow.print("Post layout flow tree".to_owned());
|
root_flow.print("Post layout flow tree".to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.generation += 1;
|
self.generation.set(self.generation.get() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1563,7 +1562,7 @@ impl LayoutThread {
|
||||||
} else {
|
} else {
|
||||||
TimerMetadataFrameType::RootWindow
|
TimerMetadataFrameType::RootWindow
|
||||||
},
|
},
|
||||||
incremental: if self.first_reflow {
|
incremental: if self.first_reflow.get() {
|
||||||
TimerMetadataReflowType::FirstReflow
|
TimerMetadataReflowType::FirstReflow
|
||||||
} else {
|
} else {
|
||||||
TimerMetadataReflowType::Incremental
|
TimerMetadataReflowType::Incremental
|
||||||
|
|
|
@ -399,6 +399,7 @@ impl PropertyAnimation {
|
||||||
//
|
//
|
||||||
// TODO(emilio): Take rid of this mutex splitting SharedLayoutContex into a
|
// TODO(emilio): Take rid of this mutex splitting SharedLayoutContex into a
|
||||||
// cloneable part and a non-cloneable part..
|
// cloneable part and a non-cloneable part..
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation>,
|
pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation>,
|
||||||
opaque_node: OpaqueNode,
|
opaque_node: OpaqueNode,
|
||||||
unsafe_node: UnsafeNode,
|
unsafe_node: UnsafeNode,
|
||||||
|
@ -755,6 +756,7 @@ pub fn update_style_for_animation(context: &SharedStyleContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the style in the node when it finishes.
|
/// Update the style in the node when it finishes.
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
pub fn complete_expired_transitions(node: OpaqueNode, style: &mut Arc<ComputedValues>,
|
pub fn complete_expired_transitions(node: OpaqueNode, style: &mut Arc<ComputedValues>,
|
||||||
context: &SharedStyleContext) -> bool {
|
context: &SharedStyleContext) -> bool {
|
||||||
let had_animations_to_expire;
|
let had_animations_to_expire;
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
|
|
||||||
//! The context within which style is calculated.
|
//! The context within which style is calculated.
|
||||||
|
|
||||||
use animation::{Animation, PropertyAnimation};
|
#[cfg(feature = "servo")] use animation::Animation;
|
||||||
|
use animation::PropertyAnimation;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use bit_vec::BitVec;
|
use bit_vec::BitVec;
|
||||||
use bloom::StyleBloom;
|
use bloom::StyleBloom;
|
||||||
|
@ -17,18 +18,18 @@ use fnv::FnvHashMap;
|
||||||
use font_metrics::FontMetricsProvider;
|
use font_metrics::FontMetricsProvider;
|
||||||
#[cfg(feature = "gecko")] use gecko_bindings::structs;
|
#[cfg(feature = "gecko")] use gecko_bindings::structs;
|
||||||
use matching::StyleSharingCandidateCache;
|
use matching::StyleSharingCandidateCache;
|
||||||
use parking_lot::RwLock;
|
#[cfg(feature = "servo")] use parking_lot::RwLock;
|
||||||
#[cfg(feature = "gecko")] use properties::ComputedValues;
|
#[cfg(feature = "gecko")] use properties::ComputedValues;
|
||||||
use selector_parser::SnapshotMap;
|
use selector_parser::SnapshotMap;
|
||||||
use selectors::matching::ElementSelectorFlags;
|
use selectors::matching::ElementSelectorFlags;
|
||||||
#[cfg(feature = "servo")] use servo_config::opts;
|
#[cfg(feature = "servo")] use servo_config::opts;
|
||||||
use shared_lock::StylesheetGuards;
|
use shared_lock::StylesheetGuards;
|
||||||
use std::collections::HashMap;
|
#[cfg(feature = "servo")] use std::collections::HashMap;
|
||||||
#[cfg(not(feature = "servo"))] use std::env;
|
#[cfg(feature = "gecko")] use std::env;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
use std::sync::Mutex;
|
#[cfg(feature = "servo")] use std::sync::Mutex;
|
||||||
use std::sync::mpsc::Sender;
|
#[cfg(feature = "servo")] use std::sync::mpsc::Sender;
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
use stylist::Stylist;
|
use stylist::Stylist;
|
||||||
use thread_state;
|
use thread_state;
|
||||||
|
@ -37,10 +38,12 @@ use timer::Timer;
|
||||||
use traversal::{DomTraversal, TraversalFlags};
|
use traversal::{DomTraversal, TraversalFlags};
|
||||||
|
|
||||||
/// This structure is used to create a local style context from a shared one.
|
/// This structure is used to create a local style context from a shared one.
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
pub struct ThreadLocalStyleContextCreationInfo {
|
pub struct ThreadLocalStyleContextCreationInfo {
|
||||||
new_animations_sender: Sender<Animation>,
|
new_animations_sender: Sender<Animation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
impl ThreadLocalStyleContextCreationInfo {
|
impl ThreadLocalStyleContextCreationInfo {
|
||||||
/// Trivially constructs a `ThreadLocalStyleContextCreationInfo`.
|
/// Trivially constructs a `ThreadLocalStyleContextCreationInfo`.
|
||||||
pub fn new(animations_sender: Sender<Animation>) -> Self {
|
pub fn new(animations_sender: Sender<Animation>) -> Self {
|
||||||
|
@ -106,7 +109,7 @@ impl Default for StyleSystemOptions {
|
||||||
/// shared among the worker threads.
|
/// shared among the worker threads.
|
||||||
pub struct SharedStyleContext<'a> {
|
pub struct SharedStyleContext<'a> {
|
||||||
/// The CSS selector stylist.
|
/// The CSS selector stylist.
|
||||||
pub stylist: Arc<Stylist>,
|
pub stylist: &'a Stylist,
|
||||||
|
|
||||||
/// Configuration options.
|
/// Configuration options.
|
||||||
pub options: StyleSystemOptions,
|
pub options: StyleSystemOptions,
|
||||||
|
@ -114,17 +117,8 @@ pub struct SharedStyleContext<'a> {
|
||||||
/// Guards for pre-acquired locks
|
/// Guards for pre-acquired locks
|
||||||
pub guards: StylesheetGuards<'a>,
|
pub guards: StylesheetGuards<'a>,
|
||||||
|
|
||||||
/// The animations that are currently running.
|
|
||||||
pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
|
||||||
|
|
||||||
/// The list of animations that have expired since the last style recalculation.
|
|
||||||
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
|
||||||
|
|
||||||
///The CSS error reporter for all CSS loaded in this layout thread
|
///The CSS error reporter for all CSS loaded in this layout thread
|
||||||
pub error_reporter: Box<ParseErrorReporter>,
|
pub error_reporter: &'a ParseErrorReporter,
|
||||||
|
|
||||||
/// Data needed to create the thread-local style context from the shared one.
|
|
||||||
pub local_context_creation_data: Mutex<ThreadLocalStyleContextCreationInfo>,
|
|
||||||
|
|
||||||
/// The current timer for transitions and animations. This is needed to test
|
/// The current timer for transitions and animations. This is needed to test
|
||||||
/// them.
|
/// them.
|
||||||
|
@ -138,6 +132,19 @@ pub struct SharedStyleContext<'a> {
|
||||||
|
|
||||||
/// A map with our snapshots in order to handle restyle hints.
|
/// A map with our snapshots in order to handle restyle hints.
|
||||||
pub snapshot_map: &'a SnapshotMap,
|
pub snapshot_map: &'a SnapshotMap,
|
||||||
|
|
||||||
|
/// The animations that are currently running.
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
||||||
|
|
||||||
|
/// The list of animations that have expired since the last style recalculation.
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
||||||
|
|
||||||
|
/// Data needed to create the thread-local style context from the shared one.
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
pub local_context_creation_data: Mutex<ThreadLocalStyleContextCreationInfo>,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SharedStyleContext<'a> {
|
impl<'a> SharedStyleContext<'a> {
|
||||||
|
@ -400,6 +407,7 @@ pub struct ThreadLocalStyleContext<E: TElement> {
|
||||||
pub bloom_filter: StyleBloom<E>,
|
pub bloom_filter: StyleBloom<E>,
|
||||||
/// A channel on which new animations that have been triggered by style
|
/// A channel on which new animations that have been triggered by style
|
||||||
/// recalculation can be sent.
|
/// recalculation can be sent.
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
pub new_animations_sender: Sender<Animation>,
|
pub new_animations_sender: Sender<Animation>,
|
||||||
/// A set of tasks to be run (on the parent thread) in sequential mode after
|
/// A set of tasks to be run (on the parent thread) in sequential mode after
|
||||||
/// the rest of the styling is complete. This is useful for infrequently-needed
|
/// the rest of the styling is complete. This is useful for infrequently-needed
|
||||||
|
@ -421,6 +429,7 @@ pub struct ThreadLocalStyleContext<E: TElement> {
|
||||||
|
|
||||||
impl<E: TElement> ThreadLocalStyleContext<E> {
|
impl<E: TElement> ThreadLocalStyleContext<E> {
|
||||||
/// Creates a new `ThreadLocalStyleContext` from a shared one.
|
/// Creates a new `ThreadLocalStyleContext` from a shared one.
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
pub fn new(shared: &SharedStyleContext) -> Self {
|
pub fn new(shared: &SharedStyleContext) -> Self {
|
||||||
ThreadLocalStyleContext {
|
ThreadLocalStyleContext {
|
||||||
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
|
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
|
||||||
|
@ -434,6 +443,20 @@ impl<E: TElement> ThreadLocalStyleContext<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
/// Creates a new `ThreadLocalStyleContext` from a shared one.
|
||||||
|
pub fn new(shared: &SharedStyleContext) -> Self {
|
||||||
|
ThreadLocalStyleContext {
|
||||||
|
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
|
||||||
|
bloom_filter: StyleBloom::new(),
|
||||||
|
tasks: Vec::new(),
|
||||||
|
selector_flags: SelectorFlagsMap::new(),
|
||||||
|
statistics: TraversalStatistics::default(),
|
||||||
|
current_element_info: None,
|
||||||
|
font_metrics_provider: E::FontMetricsProvider::create_from(shared),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Notes when the style system starts traversing an element.
|
/// Notes when the style system starts traversing an element.
|
||||||
pub fn begin_element(&mut self, element: E, data: &ElementData) {
|
pub fn begin_element(&mut self, element: E, data: &ElementData) {
|
||||||
debug_assert!(self.current_element_info.is_none());
|
debug_assert!(self.current_element_info.is_none());
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use Atom;
|
use Atom;
|
||||||
use animation::{self, Animation, PropertyAnimation};
|
|
||||||
use atomic_refcell::AtomicRefMut;
|
use atomic_refcell::AtomicRefMut;
|
||||||
use bit_vec::BitVec;
|
use bit_vec::BitVec;
|
||||||
use cache::{LRUCache, LRUCacheMutIterator};
|
use cache::{LRUCache, LRUCacheMutIterator};
|
||||||
|
@ -719,6 +718,8 @@ trait PrivateMatchMethods: TElement {
|
||||||
old_values: &mut Option<Arc<ComputedValues>>,
|
old_values: &mut Option<Arc<ComputedValues>>,
|
||||||
new_values: &mut Arc<ComputedValues>,
|
new_values: &mut Arc<ComputedValues>,
|
||||||
_primary_style: &ComputedStyle) {
|
_primary_style: &ComputedStyle) {
|
||||||
|
use animation;
|
||||||
|
|
||||||
let possibly_expired_animations =
|
let possibly_expired_animations =
|
||||||
&mut context.thread_local.current_element_info.as_mut().unwrap()
|
&mut context.thread_local.current_element_info.as_mut().unwrap()
|
||||||
.possibly_expired_animations;
|
.possibly_expired_animations;
|
||||||
|
@ -804,11 +805,14 @@ trait PrivateMatchMethods: TElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
fn update_animations_for_cascade(&self,
|
fn update_animations_for_cascade(&self,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
style: &mut Arc<ComputedValues>,
|
style: &mut Arc<ComputedValues>,
|
||||||
possibly_expired_animations: &mut Vec<PropertyAnimation>,
|
possibly_expired_animations: &mut Vec<::animation::PropertyAnimation>,
|
||||||
font_metrics: &FontMetricsProvider) {
|
font_metrics: &FontMetricsProvider) {
|
||||||
|
use animation::{self, Animation};
|
||||||
|
|
||||||
// Finish any expired transitions.
|
// Finish any expired transitions.
|
||||||
let this_opaque = self.as_node().opaque();
|
let this_opaque = self.as_node().opaque();
|
||||||
animation::complete_expired_transitions(this_opaque, style, context);
|
animation::complete_expired_transitions(this_opaque, style, context);
|
||||||
|
|
|
@ -11,9 +11,8 @@ use std::borrow::Cow;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::Mutex;
|
|
||||||
use style::context::{QuirksMode, SharedStyleContext, StyleContext};
|
use style::context::{QuirksMode, SharedStyleContext, StyleContext};
|
||||||
use style::context::{ThreadLocalStyleContext, ThreadLocalStyleContextCreationInfo};
|
use style::context::ThreadLocalStyleContext;
|
||||||
use style::data::{ElementData, ElementStyles, RestyleData};
|
use style::data::{ElementData, ElementStyles, RestyleData};
|
||||||
use style::dom::{AnimationOnlyDirtyDescendants, DirtyDescendants};
|
use style::dom::{AnimationOnlyDirtyDescendants, DirtyDescendants};
|
||||||
use style::dom::{ShowSubtreeData, TElement, TNode};
|
use style::dom::{ShowSubtreeData, TElement, TNode};
|
||||||
|
@ -148,24 +147,19 @@ unsafe fn dummy_url_data() -> &'static RefPtr<URLExtraData> {
|
||||||
RefPtr::from_ptr_ref(&DUMMY_URL_DATA)
|
RefPtr::from_ptr_ref(&DUMMY_URL_DATA)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DEFAULT_ERROR_REPORTER: RustLogReporter = RustLogReporter;
|
||||||
|
|
||||||
fn create_shared_context<'a>(global_style_data: &GlobalStyleData,
|
fn create_shared_context<'a>(global_style_data: &GlobalStyleData,
|
||||||
guard: &'a SharedRwLockReadGuard,
|
guard: &'a SharedRwLockReadGuard,
|
||||||
per_doc_data: &PerDocumentStyleDataImpl,
|
per_doc_data: &'a PerDocumentStyleDataImpl,
|
||||||
traversal_flags: TraversalFlags,
|
traversal_flags: TraversalFlags,
|
||||||
snapshot_map: &'a ServoElementSnapshotTable)
|
snapshot_map: &'a ServoElementSnapshotTable)
|
||||||
-> SharedStyleContext<'a> {
|
-> SharedStyleContext<'a> {
|
||||||
let local_context_data =
|
|
||||||
ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
|
|
||||||
|
|
||||||
SharedStyleContext {
|
SharedStyleContext {
|
||||||
stylist: per_doc_data.stylist.clone(),
|
stylist: &per_doc_data.stylist,
|
||||||
options: global_style_data.options.clone(),
|
options: global_style_data.options.clone(),
|
||||||
guards: StylesheetGuards::same(guard),
|
guards: StylesheetGuards::same(guard),
|
||||||
running_animations: per_doc_data.running_animations.clone(),
|
error_reporter: &DEFAULT_ERROR_REPORTER,
|
||||||
expired_animations: per_doc_data.expired_animations.clone(),
|
|
||||||
// FIXME(emilio): Stop boxing here.
|
|
||||||
error_reporter: Box::new(RustLogReporter),
|
|
||||||
local_context_creation_data: Mutex::new(local_context_data),
|
|
||||||
timer: Timer::new(),
|
timer: Timer::new(),
|
||||||
// FIXME Find the real QuirksMode information for this document
|
// FIXME Find the real QuirksMode information for this document
|
||||||
quirks_mode: QuirksMode::NoQuirks,
|
quirks_mode: QuirksMode::NoQuirks,
|
||||||
|
@ -2024,9 +2018,10 @@ pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't have the style ready. Go ahead and compute it as necessary.
|
// We don't have the style ready. Go ahead and compute it as necessary.
|
||||||
|
let data = doc_data.borrow();
|
||||||
let shared = create_shared_context(&global_style_data,
|
let shared = create_shared_context(&global_style_data,
|
||||||
&guard,
|
&guard,
|
||||||
&mut doc_data.borrow_mut(),
|
&data,
|
||||||
TraversalFlags::empty(),
|
TraversalFlags::empty(),
|
||||||
unsafe { &*snapshots });
|
unsafe { &*snapshots });
|
||||||
let mut tlc = ThreadLocalStyleContext::new(&shared);
|
let mut tlc = ThreadLocalStyleContext::new(&shared);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue