servo/components/layout/context.rs
Corey Farwell 4f47b41fa7 Remove fnv & smallvec crate reexports from util
The util component specified fnv and smallvec as dependencies and publicly
reexported both of them. Several other components utilized these reexports,
presumably because fnv and smallvec used to live in the tree so reexporting
made the transition easier.

These indirect dependencies through the util component are unnecessary.

This commit removes the fnv & smallvec crate reexports in the util component.
It exchange, it adds fnv & smallvec as dependencies to non-util components
wherever needed. Finally, it removes the fnv dependency from util as it is not
utilized anywhere in the util component.
2015-06-10 07:14:55 -07:00

196 lines
7.5 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/. */
//! Data needed by the layout task.
#![allow(unsafe_code)]
use css::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};
use canvas_traits::CanvasMsg;
use msg::compositor_msg::LayerId;
use fnv::FnvHasher;
use geom::{Rect, Size2D};
use gfx::display_list::OpaqueNode;
use gfx::font_cache_task::FontCacheTask;
use gfx::font_context::FontContext;
use msg::constellation_msg::ConstellationChan;
use net_traits::image::base::Image;
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageResponse, ImageState};
use net_traits::image_cache_task::{UsePlaceholder};
use script::layout_interface::{Animation, LayoutChan, ReflowGoal};
use std::cell::{RefCell, RefMut};
use std::collections::HashMap;
use std::collections::hash_state::DefaultState;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender};
use style::selector_matching::Stylist;
use url::Url;
use util::geometry::Au;
use util::opts;
struct LocalLayoutContext {
font_context: RefCell<FontContext>,
applicable_declarations_cache: RefCell<ApplicableDeclarationsCache>,
style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache>,
}
thread_local!(static LOCAL_CONTEXT_KEY: RefCell<Option<Rc<LocalLayoutContext>>> = RefCell::new(None));
fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext)
-> Rc<LocalLayoutContext> {
LOCAL_CONTEXT_KEY.with(|r| {
let mut r = r.borrow_mut();
if let Some(context) = r.clone() {
if shared_layout_context.screen_size_changed {
context.applicable_declarations_cache.borrow_mut().evict_all();
}
context
} else {
let context = Rc::new(LocalLayoutContext {
font_context: RefCell::new(FontContext::new(shared_layout_context.font_cache_task.clone())),
applicable_declarations_cache: RefCell::new(ApplicableDeclarationsCache::new()),
style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()),
});
*r = Some(context.clone());
context
}
})
}
/// Layout information shared among all workers. This must be thread-safe.
pub struct SharedLayoutContext {
/// The shared image cache task.
pub image_cache_task: ImageCacheTask,
/// A channel for the image cache to send responses to.
pub image_cache_sender: ImageCacheChan,
/// The current screen size.
pub screen_size: Size2D<Au>,
/// Screen sized changed?
pub screen_size_changed: bool,
/// A channel up to the constellation.
pub constellation_chan: ConstellationChan,
/// A channel up to the layout task.
pub layout_chan: LayoutChan,
/// Interface to the font cache task.
pub font_cache_task: FontCacheTask,
/// The CSS selector stylist.
///
/// FIXME(#2604): Make this no longer an unsafe pointer once we have fast `RWArc`s.
pub stylist: *const Stylist,
/// The root node at which we're starting the layout.
pub reflow_root: Option<OpaqueNode>,
/// The URL.
pub url: Url,
/// The dirty rectangle, used during display list building.
pub dirty: Rect<Au>,
/// Starts at zero, and increased by one every time a layout completes.
/// This can be used to easily check for invalid stale data.
pub generation: u32,
/// A channel on which new animations that have been triggered by style recalculation can be
/// sent.
pub new_animations_sender: Sender<Animation>,
/// A channel to send canvas renderers to paint task, in order to correctly paint the layers
pub canvas_layers_sender: Sender<(LayerId, Option<Arc<Mutex<Sender<CanvasMsg>>>>)>,
/// The visible rects for each layer, as reported to us by the compositor.
pub visible_rects: Arc<HashMap<LayerId, Rect<Au>, DefaultState<FnvHasher>>>,
/// Why is this reflow occurring
pub goal: ReflowGoal,
}
pub struct SharedLayoutContextWrapper(pub *const SharedLayoutContext);
unsafe impl Send for SharedLayoutContextWrapper {}
pub struct LayoutContext<'a> {
pub shared: &'a SharedLayoutContext,
cached_local_layout_context: Rc<LocalLayoutContext>,
}
impl<'a> LayoutContext<'a> {
pub fn new(shared_layout_context: &'a SharedLayoutContext) -> LayoutContext<'a> {
let local_context = create_or_get_local_context(shared_layout_context);
LayoutContext {
shared: shared_layout_context,
cached_local_layout_context: local_context,
}
}
#[inline(always)]
pub fn font_context(&self) -> RefMut<FontContext> {
self.cached_local_layout_context.font_context.borrow_mut()
}
#[inline(always)]
pub fn applicable_declarations_cache(&self) -> RefMut<ApplicableDeclarationsCache> {
self.cached_local_layout_context.applicable_declarations_cache.borrow_mut()
}
#[inline(always)]
pub fn style_sharing_candidate_cache(&self) -> RefMut<StyleSharingCandidateCache> {
self.cached_local_layout_context.style_sharing_candidate_cache.borrow_mut()
}
pub fn get_or_request_image(&self, url: Url, use_placeholder: UsePlaceholder)
-> Option<Arc<Image>> {
// See if the image is already available
let result = self.shared.image_cache_task.get_image_if_available(url.clone(),
use_placeholder);
match result {
Ok(image) => Some(image),
Err(state) => {
// If we are emitting an output file, then we need to block on
// image load or we risk emitting an output file missing the image.
let is_sync = opts::get().output_file.is_some();
match (state, is_sync) {
// Image failed to load, so just return nothing
(ImageState::LoadError, _) => None,
// Not loaded, test mode - load the image synchronously
(_, true) => {
let (sync_tx, sync_rx) = channel();
self.shared.image_cache_task.request_image(url,
ImageCacheChan(sync_tx),
None);
match sync_rx.recv().unwrap().image_response {
ImageResponse::Loaded(image) |
ImageResponse::PlaceholderLoaded(image) => Some(image),
ImageResponse::None => None,
}
}
// Not yet requested, async mode - request image from the cache
(ImageState::NotRequested, false) => {
self.shared.image_cache_task.request_image(url,
self.shared.image_cache_sender.clone(),
None);
None
}
// Image has been requested, is still pending. Return no image
// for this paint loop. When the image loads it will trigger
// a reflow and/or repaint.
(ImageState::Pending, false) => None,
}
}
}
}
}