aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/context.rs
blob: ae1c75e89e67268802d60752b49b168ea8c3cc31 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* 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 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::local_image_cache::LocalImageCache;
use script::layout_interface::{Animation, LayoutChan};
use script_traits::UntrustedNodeAddress;
use std::boxed;
use std::cell::Cell;
use std::ptr;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use style::selector_matching::Stylist;
use url::Url;
use util::geometry::Au;

struct LocalLayoutContext {
    font_context: FontContext,
    applicable_declarations_cache: ApplicableDeclarationsCache,
    style_sharing_candidate_cache: StyleSharingCandidateCache,
}

thread_local!(static LOCAL_CONTEXT_KEY: Cell<*mut LocalLayoutContext> = Cell::new(ptr::null_mut()));

fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext)
                               -> *mut LocalLayoutContext {
    LOCAL_CONTEXT_KEY.with(|ref r| {
        if r.get().is_null() {
            let context = box LocalLayoutContext {
                font_context: FontContext::new(shared_layout_context.font_cache_task.clone()),
                applicable_declarations_cache: ApplicableDeclarationsCache::new(),
                style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
            };
            r.set(unsafe { boxed::into_raw(context) });
        } else if shared_layout_context.screen_size_changed {
            unsafe {
                (*r.get()).applicable_declarations_cache.evict_all();
            }
        }

        r.get()
    })
}

/// Layout information shared among all workers. This must be thread-safe.
pub struct SharedLayoutContext {
    /// The local image cache.
    pub image_cache: Arc<Mutex<LocalImageCache<UntrustedNodeAddress>>>,

    /// 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>,
}

pub struct SharedLayoutContextWrapper(pub *const SharedLayoutContext);

unsafe impl Send for SharedLayoutContextWrapper {}

pub struct LayoutContext<'a> {
    pub shared: &'a SharedLayoutContext,
    cached_local_layout_context: *mut 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<'b>(&'b self) -> &'b mut FontContext {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.font_context
        }
    }

    #[inline(always)]
    pub fn applicable_declarations_cache<'b>(&'b self) -> &'b mut ApplicableDeclarationsCache {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.applicable_declarations_cache
        }
    }

    #[inline(always)]
    pub fn style_sharing_candidate_cache<'b>(&'b self) -> &'b mut StyleSharingCandidateCache {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.style_sharing_candidate_cache
        }
    }
}