auto merge of #681 : metajack/servo/asymmetric-borders, r=pcwalton

This commit is contained in:
bors-servo 2013-08-07 16:33:32 -07:00
commit 6ecae7b8db
3 changed files with 86 additions and 59 deletions

View file

@ -20,7 +20,7 @@ use render_context::RenderContext;
use text::SendableTextRun; use text::SendableTextRun;
use std::cast::transmute_region; use std::cast::transmute_region;
use geom::{Point2D, Rect, Size2D}; use geom::{Point2D, Rect, Size2D, SideOffsets2D};
use servo_net::image::base::Image; use servo_net::image::base::Image;
use servo_util::range::Range; use servo_util::range::Range;
use extra::arc::ARC; use extra::arc::ARC;
@ -99,8 +99,10 @@ pub struct ImageDisplayItem<E> {
/// Renders a border. /// Renders a border.
pub struct BorderDisplayItem<E> { pub struct BorderDisplayItem<E> {
base: BaseDisplayItem<E>, base: BaseDisplayItem<E>,
/// The width of the border.
width: Au, /// The border widths
border: SideOffsets2D<Au>,
/// The color of the border. /// The color of the border.
color: Color, color: Color,
} }
@ -147,7 +149,9 @@ impl<E> DisplayItem<E> {
} }
BorderDisplayItemClass(ref border) => { BorderDisplayItemClass(ref border) => {
render_context.draw_border(&border.base.bounds, border.width, border.color) render_context.draw_border(&border.base.bounds,
border.border,
border.color)
} }
} }
} }

View file

@ -14,6 +14,7 @@ use std::libc::types::common::c99::uint16_t;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use geom::side_offsets::SideOffsets2D;
use servo_net::image::base::Image; use servo_net::image::base::Image;
use extra::arc::ARC; use extra::arc::ARC;
@ -33,21 +34,47 @@ impl<'self> RenderContext<'self> {
self.canvas.draw_target.fill_rect(&bounds.to_azure_rect(), &ColorPattern(color)); self.canvas.draw_target.fill_rect(&bounds.to_azure_rect(), &ColorPattern(color));
} }
pub fn draw_border(&self, bounds: &Rect<Au>, width: Au, color: Color) { pub fn draw_border(&self,
bounds: &Rect<Au>,
border: SideOffsets2D<Au>,
color: Color) {
let pattern = ColorPattern(color); let pattern = ColorPattern(color);
let stroke_fields = 2; // CAP_SQUARE
let width_px = width.to_px();
let rect = if width_px % 2 == 0 {
bounds.to_azure_rect()
} else {
bounds.to_azure_snapped_rect()
};
let stroke_opts = StrokeOptions(width_px as AzFloat, 10 as AzFloat, stroke_fields);
let draw_opts = DrawOptions(1 as AzFloat, 0 as uint16_t); let draw_opts = DrawOptions(1 as AzFloat, 0 as uint16_t);
let stroke_fields = 2; // CAP_SQUARE
let mut stroke_opts = StrokeOptions(0 as AzFloat, 10 as AzFloat, stroke_fields);
let rect = bounds.to_azure_rect();
let border = border.to_float_px();
self.canvas.draw_target.make_current(); self.canvas.draw_target.make_current();
self.canvas.draw_target.stroke_rect(&rect, &pattern, &stroke_opts, &draw_opts);
// draw top border
stroke_opts.line_width = border.top;
let y = rect.origin.y + border.top * 0.5;
let start = Point2D(rect.origin.x, y);
let end = Point2D(rect.origin.x + rect.size.width, y);
self.canvas.draw_target.stroke_line(start, end, &pattern, &stroke_opts, &draw_opts);
// draw bottom border
stroke_opts.line_width = border.bottom;
let y = rect.origin.y + rect.size.height - border.bottom * 0.5;
let start = Point2D(rect.origin.x, y);
let end = Point2D(rect.origin.x + rect.size.width, y);
self.canvas.draw_target.stroke_line(start, end, &pattern, &stroke_opts, &draw_opts);
// draw left border
stroke_opts.line_width = border.left;
let x = rect.origin.x + border.left * 0.5;
let start = Point2D(x, rect.origin.y);
let end = Point2D(x, rect.origin.y + rect.size.height);
self.canvas.draw_target.stroke_line(start, end, &pattern, &stroke_opts, &draw_opts);
// draw right border
stroke_opts.line_width = border.right;
let x = rect.origin.x + rect.size.width - border.right * 0.5;
let start = Point2D(x, rect.origin.y);
let end = Point2D(x, rect.origin.y + rect.size.height);
self.canvas.draw_target.stroke_line(start, end, &pattern, &stroke_opts, &draw_opts);
} }
pub fn draw_image(&self, bounds: Rect<Au>, image: ARC<~Image>) { pub fn draw_image(&self, bounds: Rect<Au>, image: ARC<~Image>) {
@ -94,7 +121,6 @@ impl to_float for u8 {
trait ToAzureRect { trait ToAzureRect {
fn to_azure_rect(&self) -> Rect<AzFloat>; fn to_azure_rect(&self) -> Rect<AzFloat>;
fn to_azure_snapped_rect(&self) -> Rect<AzFloat>;
} }
impl ToAzureRect for Rect<Au> { impl ToAzureRect for Rect<Au> {
@ -102,11 +128,17 @@ impl ToAzureRect for Rect<Au> {
Rect(Point2D(self.origin.x.to_px() as AzFloat, self.origin.y.to_px() as AzFloat), Rect(Point2D(self.origin.x.to_px() as AzFloat, self.origin.y.to_px() as AzFloat),
Size2D(self.size.width.to_px() as AzFloat, self.size.height.to_px() as AzFloat)) Size2D(self.size.width.to_px() as AzFloat, self.size.height.to_px() as AzFloat))
} }
}
fn to_azure_snapped_rect(&self) -> Rect<AzFloat> { trait ToSideOffsetsPx {
Rect(Point2D(self.origin.x.to_px() as AzFloat + 0.5f as AzFloat, fn to_float_px(&self) -> SideOffsets2D<AzFloat>;
self.origin.y.to_px() as AzFloat + 0.5f as AzFloat), }
Size2D(self.size.width.to_px() as AzFloat,
self.size.height.to_px() as AzFloat)) impl ToSideOffsetsPx for SideOffsets2D<Au> {
fn to_float_px(&self) -> SideOffsets2D<AzFloat> {
SideOffsets2D::new(self.top.to_px() as AzFloat,
self.right.to_px() as AzFloat,
self.bottom.to_px() as AzFloat,
self.left.to_px() as AzFloat)
} }
} }

View file

@ -16,7 +16,7 @@ use std::cmp::ApproxEq;
use std::managed; use std::managed;
use std::num::Zero; use std::num::Zero;
use std::uint; use std::uint;
use geom::{Point2D, Rect, Size2D}; use geom::{Point2D, Rect, Size2D, SideOffsets2D};
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass}; use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
use gfx::display_list::{DisplayList, ImageDisplayItem, ImageDisplayItemClass}; use gfx::display_list::{DisplayList, ImageDisplayItem, ImageDisplayItemClass};
use gfx::display_list::{SolidColorDisplayItem, SolidColorDisplayItemClass, TextDisplayItem}; use gfx::display_list::{SolidColorDisplayItem, SolidColorDisplayItemClass, TextDisplayItem};
@ -629,13 +629,17 @@ impl RenderBox {
// should have a real `SERVO_DEBUG` system. // should have a real `SERVO_DEBUG` system.
debug!("%?", { debug!("%?", {
// Compute the text box bounds and draw a border surrounding them. // Compute the text box bounds and draw a border surrounding them.
let debug_border = SideOffsets2D::new(Au::from_px(1),
Au::from_px(1),
Au::from_px(1),
Au::from_px(1));
do list.with_mut_ref |list| { do list.with_mut_ref |list| {
let border_display_item = ~BorderDisplayItem { let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: absolute_box_bounds, bounds: absolute_box_bounds,
extra: ExtraDisplayListData::new(*self), extra: ExtraDisplayListData::new(*self),
}, },
width: Au::from_px(1), border: debug_border,
color: rgb(0, 0, 200).to_gfx_color(), color: rgb(0, 0, 200).to_gfx_color(),
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) list.append_item(BorderDisplayItemClass(border_display_item))
@ -655,7 +659,7 @@ impl RenderBox {
bounds: baseline, bounds: baseline,
extra: ExtraDisplayListData::new(*self), extra: ExtraDisplayListData::new(*self),
}, },
width: Au::from_px(1), border: debug_border,
color: rgb(0, 200, 0).to_gfx_color(), color: rgb(0, 200, 0).to_gfx_color(),
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) list.append_item(BorderDisplayItemClass(border_display_item))
@ -672,13 +676,18 @@ impl RenderBox {
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We // FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
// should have a real `SERVO_DEBUG` system. // should have a real `SERVO_DEBUG` system.
debug!("%?", { debug!("%?", {
let debug_border = SideOffsets2D::new(Au::from_px(1),
Au::from_px(1),
Au::from_px(1),
Au::from_px(1));
do list.with_mut_ref |list| { do list.with_mut_ref |list| {
let border_display_item = ~BorderDisplayItem { let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: absolute_box_bounds, bounds: absolute_box_bounds,
extra: ExtraDisplayListData::new(*self), extra: ExtraDisplayListData::new(*self),
}, },
width: Au::from_px(1), border: debug_border,
color: rgb(0, 0, 200).to_gfx_color(), color: rgb(0, 0, 200).to_gfx_color(),
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) list.append_item(BorderDisplayItemClass(border_display_item))
@ -896,43 +905,25 @@ impl RenderBox {
return return
} }
// Are all the widths equal? // FIXME: all colors set to top color. this is obviously not right.
// let top_color = self.style().border_top_color();
// FIXME(pcwalton): Obviously this is wrong. let color = top_color.to_gfx_color();
let borders = [ border.top, border.right, border.bottom ];
if borders.iter().all(|a| *a == border.left) { // Append the border to the display list.
let border_width = border.top; do list.with_mut_ref |list| {
let bounds = Rect { let border_display_item = ~BorderDisplayItem {
origin: Point2D { base: BaseDisplayItem {
x: abs_bounds.origin.x + border_width.scale_by(0.5), bounds: *abs_bounds,
y: abs_bounds.origin.y + border_width.scale_by(0.5), extra: ExtraDisplayListData::new(*self),
}, },
size: Size2D { border: SideOffsets2D::new(border.top,
width: abs_bounds.size.width - border_width, border.right,
height: abs_bounds.size.height - border_width border.bottom,
} border.left),
color: color,
}; };
let top_color = self.style().border_top_color(); list.append_item(BorderDisplayItemClass(border_display_item))
let color = top_color.to_gfx_color(); // FIXME
// Append the border to the display list.
do list.with_mut_ref |list| {
let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem {
bounds: bounds,
extra: ExtraDisplayListData::new(*self),
},
width: border_width,
color: color,
};
list.append_item(BorderDisplayItemClass(border_display_item))
}
} else {
warn!("ignoring unimplemented border widths");
} }
} }
} }