Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Box-model Computations #507

Closed
wants to merge 26 commits into from
Closed
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
09292be
Update rust-geom
pcwalton May 29, 2013
11efed6
Implement the beginnings of the box model for render boxes
pcwalton May 29, 2013
43c83d2
Add horizontal borders, margins and padding. Broken until rust-css su…
May 30, 2013
c14a137
Update rust-geom
pcwalton May 29, 2013
233a204
Implement the beginnings of the box model for render boxes
pcwalton May 29, 2013
a1d1289
Add NSPR and NSS submodules
pcwalton May 29, 2013
0af3bbf
Add NSS and NSPR to the build
pcwalton May 29, 2013
2d1a00c
Don't clip layers to the screen area
pcwalton May 29, 2013
67eb533
Clamp scrolling to the page boundaries
pcwalton May 29, 2013
d97f002
Stop hammering on the compositor
pcwalton May 29, 2013
02c5772
Fix corrupted textures when resizing.
pcwalton May 30, 2013
dcfabb7
Don't try to remove whitespace twice if it's the only node.
pcwalton May 30, 2013
e2bcd36
Color links blue
pcwalton May 30, 2013
b6dd3f6
Refactor a bit and compute vertical margins as well.
May 30, 2013
2e4cecc
Add flows if requested to the display list info.
pcwalton May 30, 2013
25fb1e5
Add comments and compute heights properly
May 30, 2013
ea1a406
base and bounds methods for DisplayItem
May 25, 2013
f77eef5
Basic hit testing functionality
pcwalton May 31, 2013
facb707
Update rust-css and rust-netsurfcss
pcwalton May 31, 2013
d5e4793
Add horizontal borders, margins and padding. Broken until rust-css su…
May 30, 2013
4a2171c
Update border rendering
May 31, 2013
708f9b4
Fix method names and dynamic borrow check failures
pcwalton May 31, 2013
e3290a3
Merge
May 31, 2013
d6a9bc7
Fix merge problems
May 31, 2013
ff8d33e
Fix borrow-check and repo errors.
Jun 3, 2013
3e80e97
Compute percent widths/margins properly and fix numerous small visual…
Jun 4, 2013
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -88,3 +88,9 @@
[submodule "src/support/alert/rust-alert"]
path = src/support/alert/rust-alert
url = git://github.com/mozilla-servo/rust-alert.git
[submodule "src/support/nss/nss"]
path = src/support/nss/nss
url = git://github.com/mozilla-servo/nss.git
[submodule "src/support/nss/nspr"]
path = src/support/nss/nspr
url = git://github.com/mozilla-servo/nspr.git
@@ -411,6 +411,8 @@ CFG_SUBMODULES="\
support/libparserutils/libparserutils \
support/netsurfcss/libcss \
support/netsurfcss/rust-netsurfcss \
support/nss/nspr \
support/nss/nss \
support/opengles/rust-opengles \
support/sharegl/sharegl \
support/skia/skia \
@@ -21,6 +21,8 @@ NATIVE_BUILDS += \
libwapcaplet \
mozjs \
skia \
nss \
nspr \
$(NULL)

# NOTE: the make magic can only compute transitive build dependencies,
@@ -4,6 +4,7 @@

use azure::azure_hl::{DrawTarget};
use geom::rect::Rect;
use geom::size::Size2D;

pub struct LayerBuffer {
draw_target: DrawTarget,
@@ -24,6 +25,6 @@ pub struct LayerBufferSet {
/// The interface used to by the renderer to acquire draw targets for each rendered frame and
/// submit them to be drawn to the display.
pub trait Compositor {
fn paint(&self, layer_buffer_set: LayerBufferSet);
fn paint(&self, layer_buffer_set: LayerBufferSet, new_size: Size2D<uint>);
}

@@ -19,27 +19,28 @@ use geometry::Au;
use render_context::RenderContext;
use text::SendableTextRun;

use core::cast::transmute_region;
use geom::{Point2D, Rect, Size2D};
use servo_net::image::base::Image;
use servo_util::range::Range;
use std::arc::ARC;
use std::arc;

/// A list of rendering operations to be performed.
pub struct DisplayList {
priv list: ~[DisplayItem]
pub struct DisplayList<E> {
list: ~[DisplayItem<E>]
}

impl DisplayList {
impl<E> DisplayList<E> {
/// Creates a new display list.
pub fn new() -> DisplayList {
pub fn new() -> DisplayList<E> {
DisplayList {
list: ~[]
}
}

/// Appends the given item to the display list.
pub fn append_item(&mut self, item: DisplayItem) {
pub fn append_item(&mut self, item: DisplayItem<E>) {
// FIXME(Issue #150): crashes
//debug!("Adding display item %u: %?", self.len(), item);
self.list.push(item)
@@ -58,51 +59,54 @@ impl DisplayList {
}

/// One drawing command in the list.
pub enum DisplayItem {
SolidColorDisplayItemClass(~SolidColorDisplayItem),
TextDisplayItemClass(~TextDisplayItem),
ImageDisplayItemClass(~ImageDisplayItem),
BorderDisplayItemClass(~BorderDisplayItem),
pub enum DisplayItem<E> {
SolidColorDisplayItemClass(~SolidColorDisplayItem<E>),
TextDisplayItemClass(~TextDisplayItem<E>),
ImageDisplayItemClass(~ImageDisplayItem<E>),
BorderDisplayItemClass(~BorderDisplayItem<E>),
}

/// Information common to all display items.
pub struct BaseDisplayItem {
pub struct BaseDisplayItem<E> {
/// The boundaries of the display item.
///
/// TODO: Which coordinate system should this use?
bounds: Rect<Au>,

/// Extra data: either the originating flow (for hit testing) or nothing (for rendering).
extra: E,
}

/// Renders a solid color.
pub struct SolidColorDisplayItem {
base: BaseDisplayItem,
pub struct SolidColorDisplayItem<E> {
base: BaseDisplayItem<E>,
color: Color,
}

/// Renders text.
pub struct TextDisplayItem {
base: BaseDisplayItem,
pub struct TextDisplayItem<E> {
base: BaseDisplayItem<E>,
text_run: ~SendableTextRun,
range: Range,
color: Color,
}

/// Renders an image.
pub struct ImageDisplayItem {
base: BaseDisplayItem,
pub struct ImageDisplayItem<E> {
base: BaseDisplayItem<E>,
image: ARC<~Image>,
}

/// Renders a border.
pub struct BorderDisplayItem {
base: BaseDisplayItem,
pub struct BorderDisplayItem<E> {
base: BaseDisplayItem<E>,
/// The width of the border.
width: Au,
/// The color of the border.
color: Color,
}

impl DisplayItem {
impl<E> DisplayItem<E> {
/// Renders this display item into the given render context.
fn draw_into_context(&self, render_context: &RenderContext) {
match *self {
@@ -148,5 +152,21 @@ impl DisplayItem {
}
}
}

fn base<'a>(&'a self) -> &'a BaseDisplayItem<E> {
// FIXME(tkuehn): Workaround for Rust region bug.
unsafe {
match *self {
SolidColorDisplayItemClass(ref solid_color) => transmute_region(&solid_color.base),
TextDisplayItemClass(ref text) => transmute_region(&text.base),
ImageDisplayItemClass(ref image_item) => transmute_region(&image_item.base),
BorderDisplayItemClass(ref border) => transmute_region(&border.base)
}
}
}

fn bounds(&self) -> Rect<Au> {
self.base().bounds
}
}

@@ -6,7 +6,7 @@ use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;

use core::num::NumCast;
use core::num::{NumCast, One, Zero};

pub struct Au(i32);

@@ -46,6 +46,17 @@ impl cmp::Eq for Au {
fn ne(&self, other: &Au) -> bool { **self != **other }
}

impl One for Au {
fn one() -> Au { Au(1) }
}

impl Zero for Au {
fn zero() -> Au { Au(0) }
fn is_zero(&self) -> bool { **self == 0 }
}

impl Num for Au {}

pub fn min(x: Au, y: Au) -> Au { if x < y { x } else { y } }
pub fn max(x: Au, y: Au) -> Au { if x > y { x } else { y } }

@@ -14,8 +14,12 @@ use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;

/// The type representing the lack of extra display list data. This is used when sending display
/// list data off to be rendered.
pub type Nothing = ();

pub struct RenderLayer {
display_list: DisplayList,
display_list: DisplayList<Nothing>,
size: Size2D<uint>
}

@@ -50,8 +54,6 @@ pub fn render_layers(layer_ref: *RenderLayer,
let width = right - x;
let height = bottom - y;

let tile_rect = Rect(Point2D(x, y), Size2D(width, height));

// Round the width up the nearest 32 pixels for DMA on the Mac.
let aligned_width = if width % 32 == 0 {
width
@@ -63,6 +65,8 @@ pub fn render_layers(layer_ref: *RenderLayer,

debug!("tile aligned_width %u", aligned_width);

let tile_rect = Rect(Point2D(x, y), Size2D(aligned_width, height));

let buffer;
// FIXME: Try harder to search for a matching tile.
// FIXME: Don't use shift; it's bad for perf. Maybe reverse and pop.
@@ -75,7 +79,7 @@ pub fn render_layers(layer_ref: *RenderLayer,

let size = Size2D(aligned_width as i32, height as i32);
// FIXME: This may not be always true.
let stride = size.width * 4;
let stride = (aligned_width as i32) * 4;

let mut data: ~[u8] = ~[0];
let offset;
@@ -162,7 +162,7 @@ impl<C: Compositor + Owned> Renderer<C> {
};

debug!("renderer: returning surface");
self.compositor.paint(layer_buffer_set);
self.compositor.paint(layer_buffer_set, render_layer.size);
}
}
}
@@ -4,12 +4,14 @@

use compositing::resize_rate_limiter::ResizeRateLimiter;
use platform::{Application, Window};
use script::script_task::{LoadMsg, ScriptMsg};
use script::script_task::{LoadMsg, ScriptMsg, SendEventMsg};
use windowing::{ApplicationMethods, WindowMethods};
use script::dom::event::ClickEvent;

use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods};
use core::cell::Cell;
use core::comm::{Chan, SharedChan, Port};
use core::num::Orderable;
use core::util;
use geom::matrix::identity;
use geom::point::Point2D;
@@ -59,8 +61,10 @@ impl CompositorTask {

/// Messages to the compositor.
pub enum Msg {
Paint(LayerBufferSet),
Exit
/// Requests that the compositor paint the given layer buffer set for the given page size.
Paint(LayerBufferSet, Size2D<uint>),
/// Requests that the compositor shut down.
Exit,
}

/// Azure surface wrapping to work with the layers infrastructure.
@@ -119,6 +123,8 @@ fn run_main_loop(port: Port<Msg>,
// applied to the layers themselves on a per-layer basis. However, this won't work until scroll
// positions are sent to content.
let world_offset = @mut Point2D(0f32, 0f32);
let page_size = @mut Size2D(0f32, 0f32);
let window_size = @mut Size2D(800, 600);

let check_for_messages: @fn() = || {
// Periodically check if the script task responded to our last resize event
@@ -129,15 +135,20 @@ fn run_main_loop(port: Port<Msg>,
match port.recv() {
Exit => *done = true,

Paint(new_layer_buffer_set) => {
Paint(new_layer_buffer_set, new_size) => {
debug!("osmain: received new frame");

*page_size = Size2D(new_size.width as f32, new_size.height as f32);

let mut new_layer_buffer_set = new_layer_buffer_set;

// Iterate over the children of the container layer.
let mut current_layer_child = root_layer.first_child;

// Replace the image layer data with the buffer data.
// Replace the image layer data with the buffer data. Also compute the page
// size here.
let buffers = util::replace(&mut new_layer_buffer_set.buffers, ~[]);

for buffers.each |buffer| {
let width = buffer.rect.size.width as uint;
let height = buffer.rect.size.height as uint;
@@ -172,9 +183,10 @@ fn run_main_loop(port: Port<Msg>,
Some(_) => fail!(~"found unexpected layer kind"),
};

let origin = buffer.rect.origin;
let origin = Point2D(origin.x as f32, origin.y as f32);

// Set the layer's transform.
let origin = Point2D(buffer.rect.origin.x as f32,
buffer.rect.origin.y as f32);
let transform = original_layer_transform.translate(origin.x,
origin.y,
0.0);
@@ -184,6 +196,8 @@ fn run_main_loop(port: Port<Msg>,

// TODO: Recycle the old buffers; send them back to the renderer to reuse if
// it wishes.

window.set_needs_display()
}
}
}
@@ -205,24 +219,45 @@ fn run_main_loop(port: Port<Msg>,
// Hook the windowing system's resize callback up to the resize rate limiter.
do window.set_resize_callback |width, height| {
debug!("osmain: window resized to %ux%u", width, height);
resize_rate_limiter.window_resized(width, height);
*window_size = Size2D(width, height);
resize_rate_limiter.window_resized(width, height)
}

let script_chan_clone = script_chan.clone();

// When the user enters a new URL, load it.
do window.set_load_url_callback |url_string| {
debug!("osmain: loading URL `%s`", url_string);
script_chan.send(LoadMsg(url::make_url(url_string.to_str(), None)))
script_chan_clone.send(LoadMsg(url::make_url(url_string.to_str(), None)))
}

let script_chan_clone = script_chan.clone();

// When the user clicks, perform hit testing
do window.set_click_callback |layer_click_point| {
let world_click_point = layer_click_point + *world_offset;
debug!("osmain: clicked at %?", world_click_point);

script_chan_clone.send(SendEventMsg(ClickEvent(world_click_point)));
}

// When the user scrolls, move the layer around.
do window.set_scroll_callback |delta| {
// FIXME (Rust #2528): Can't use `+=`.
// FIXME (Rust #2528): Can't use `-=`.
let world_offset_copy = *world_offset;
*world_offset = world_offset_copy + delta;
*world_offset = world_offset_copy - delta;

// Clamp the world offset to the screen size.
let max_x = (page_size.width - window_size.width as f32).max(&0.0);
world_offset.x = world_offset.x.clamp(&0.0, &max_x);
let max_y = (page_size.height - window_size.height as f32).max(&0.0);
world_offset.y = world_offset.y.clamp(&0.0, &max_y);

debug!("compositor: scrolled to %?", *world_offset);

root_layer.common.set_transform(identity().translate(world_offset.x, world_offset.y, 0.0));
root_layer.common.set_transform(identity().translate(-world_offset.x,
-world_offset.y,
0.0));

window.set_needs_display()
}
@@ -241,8 +276,8 @@ fn run_main_loop(port: Port<Msg>,

/// Implementation of the abstract `Compositor` interface.
impl Compositor for CompositorTask {
fn paint(&self, layer_buffer_set: LayerBufferSet) {
self.chan.send(Paint(layer_buffer_set))
fn paint(&self, layer_buffer_set: LayerBufferSet, new_size: Size2D<uint>) {
self.chan.send(Paint(layer_buffer_set, new_size))
}
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.