Merge pull request #3182 from glennw/inline-text-border

Add support for borders on inline elements
This commit is contained in:
Patrick Walton 2014-09-03 08:16:53 -07:00
commit 603f7c9770
10 changed files with 101 additions and 17 deletions

View file

@ -65,6 +65,7 @@ pub extern "C" fn cef_run_message_loop() {
hard_fail: false, hard_fail: false,
bubble_inline_sizes_separately: false, bubble_inline_sizes_separately: false,
show_debug_borders: false, show_debug_borders: false,
enable_text_antialiasing: true,
}; };
native::start(0, 0 as *const *const u8, proc() { native::start(0, 0 as *const *const u8, proc() {
servo::run(opts); servo::run(opts);

View file

@ -63,7 +63,8 @@ trait ScaledFontExtensionMethods {
run: &Box<TextRun>, run: &Box<TextRun>,
range: &Range<CharIndex>, range: &Range<CharIndex>,
baseline_origin: Point2D<Au>, baseline_origin: Point2D<Au>,
color: Color); color: Color,
antialias: bool);
} }
impl ScaledFontExtensionMethods for ScaledFont { impl ScaledFontExtensionMethods for ScaledFont {
@ -72,8 +73,9 @@ impl ScaledFontExtensionMethods for ScaledFont {
run: &Box<TextRun>, run: &Box<TextRun>,
range: &Range<CharIndex>, range: &Range<CharIndex>,
baseline_origin: Point2D<Au>, baseline_origin: Point2D<Au>,
color: Color) { color: Color,
use libc::types::common::c99::{uint16_t, uint32_t}; antialias: bool) {
use libc::types::common::c99::uint32_t;
use azure::{struct__AzDrawOptions, use azure::{struct__AzDrawOptions,
struct__AzGlyph, struct__AzGlyph,
struct__AzGlyphBuffer, struct__AzGlyphBuffer,
@ -85,9 +87,15 @@ impl ScaledFontExtensionMethods for ScaledFont {
let azure_pattern = pattern.azure_color_pattern; let azure_pattern = pattern.azure_color_pattern;
assert!(azure_pattern.is_not_null()); assert!(azure_pattern.is_not_null());
let fields = if antialias {
0x0200
} else {
0
};
let mut options = struct__AzDrawOptions { let mut options = struct__AzDrawOptions {
mAlpha: 1f64 as AzFloat, mAlpha: 1f64 as AzFloat,
fields: 0x0200 as uint16_t fields: fields,
}; };
let mut origin = baseline_origin.clone(); let mut origin = baseline_origin.clone();
@ -633,7 +641,8 @@ impl DisplayItem {
&*text.text_run, &*text.text_run,
&text.range, &text.range,
baseline_origin, baseline_origin,
text.text_color text.text_color,
render_context.opts.enable_text_antialiasing
); );
// Undo the transform, only when we did one. // Undo the transform, only when we did one.

View file

@ -150,7 +150,7 @@ impl FontHandleMethods for FontHandle {
let em_size = Au::from_frac_px(self.ctfont.pt_size() as f64); let em_size = Au::from_frac_px(self.ctfont.pt_size() as f64);
let leading = self.ctfont.leading() as f64; let leading = self.ctfont.leading() as f64;
let scale = px_to_pt(self.ctfont.pt_size() as f64) / (self.ctfont.ascent() as f64 + self.ctfont.descent() as f64); let scale = px_to_pt(self.ctfont.pt_size() as f64) / (ascent + descent);
let line_gap = (ascent + descent + leading + 0.5).floor(); let line_gap = (ascent + descent + leading + 0.5).floor();
let metrics = FontMetrics { let metrics = FontMetrics {
@ -166,12 +166,11 @@ impl FontHandleMethods for FontHandle {
leading: Au::from_pt(leading), leading: Au::from_pt(leading),
x_height: Au::from_pt(self.ctfont.x_height() as f64), x_height: Au::from_pt(self.ctfont.x_height() as f64),
em_size: em_size, em_size: em_size,
ascent: Au::from_pt(ascent).scale_by(scale), ascent: Au::from_pt(ascent * scale),
descent: Au::from_pt(descent).scale_by(scale), descent: Au::from_pt(descent * scale),
max_advance: Au::from_pt(bounding_rect.size.width as f64), max_advance: Au::from_pt(bounding_rect.size.width as f64),
line_gap: Au::from_frac_px(line_gap), line_gap: Au::from_frac_px(line_gap),
}; };
debug!("Font metrics (@{:f} pt): {:?}", self.ctfont.pt_size() as f64, metrics); debug!("Font metrics (@{:f} pt): {:?}", self.ctfont.pt_size() as f64, metrics);
return metrics; return metrics;
} }

View file

@ -756,16 +756,15 @@ impl Fragment {
/// Adds the display items necessary to paint the borders of this fragment to a display list if /// Adds the display items necessary to paint the borders of this fragment to a display list if
/// necessary. /// necessary.
pub fn build_display_list_for_borders_if_applicable(&self, pub fn build_display_list_for_borders_if_applicable(&self,
style: &ComputedValues,
list: &mut DisplayList, list: &mut DisplayList,
abs_bounds: &Rect<Au>, abs_bounds: &Rect<Au>,
level: StackingLevel) { level: StackingLevel) {
// Fast path. let border = style.logical_border_width();
let border = self.border_width();
if border.is_zero() { if border.is_zero() {
return return
} }
let style = self.style();
let top_color = style.resolve_color(style.get_border().border_top_color); let top_color = style.resolve_color(style.get_border().border_top_color);
let right_color = style.resolve_color(style.get_border().border_right_color); let right_color = style.resolve_color(style.get_border().border_right_color);
let bottom_color = style.resolve_color(style.get_border().border_bottom_color); let bottom_color = style.resolve_color(style.get_border().border_bottom_color);
@ -774,7 +773,7 @@ impl Fragment {
// Append the border to the display list. // Append the border to the display list.
let border_display_item = box BorderDisplayItem { let border_display_item = box BorderDisplayItem {
base: BaseDisplayItem::new(*abs_bounds, self.node, level), base: BaseDisplayItem::new(*abs_bounds, self.node, level),
border: border.to_physical(self.style.writing_mode), border: border.to_physical(style.writing_mode),
color: SideOffsets2D::new(top_color.to_gfx_color(), color: SideOffsets2D::new(top_color.to_gfx_color(),
right_color.to_gfx_color(), right_color.to_gfx_color(),
bottom_color.to_gfx_color(), bottom_color.to_gfx_color(),
@ -922,9 +921,22 @@ impl Fragment {
// Add a border, if applicable. // Add a border, if applicable.
// //
// TODO: Outlines. // TODO: Outlines.
self.build_display_list_for_borders_if_applicable(display_list, match self.inline_context {
&absolute_fragment_bounds, Some(ref inline_context) => {
level); for style in inline_context.styles.iter().rev() {
self.build_display_list_for_borders_if_applicable(&**style,
display_list,
&absolute_fragment_bounds,
level);
}
}
None => {
self.build_display_list_for_borders_if_applicable(&*self.style,
display_list,
&absolute_fragment_bounds,
level);
}
}
} }
let content_box = self.content_box(); let content_box = self.content_box();

View file

@ -219,7 +219,7 @@ impl Au {
#[inline] #[inline]
pub fn from_pt(pt: f64) -> Au { pub fn from_pt(pt: f64) -> Au {
from_px(pt_to_px(pt) as int) from_frac_px(pt_to_px(pt))
} }
#[inline] #[inline]

View file

@ -73,6 +73,11 @@ pub struct Opts {
/// True if we should show borders on all layers and tiles for /// True if we should show borders on all layers and tiles for
/// debugging purposes (`--show-debug-borders`). /// debugging purposes (`--show-debug-borders`).
pub show_debug_borders: bool, pub show_debug_borders: bool,
/// If set with --disable-text-aa, disable antialiasing on fonts. This is primarily useful for reftests
/// where pixel perfect results are required when using fonts such as the Ahem
/// font for layout tests.
pub enable_text_antialiasing: bool,
} }
fn print_usage(app: &str, opts: &[getopts::OptGroup]) { fn print_usage(app: &str, opts: &[getopts::OptGroup]) {
@ -105,6 +110,7 @@ pub fn from_cmdline_args(args: &[String]) -> Option<Opts> {
getopts::optflag("f", "hard-fail", "Exit on task failure instead of displaying about:failure"), getopts::optflag("f", "hard-fail", "Exit on task failure instead of displaying about:failure"),
getopts::optflag("b", "bubble-widths", "Bubble intrinsic widths separately like other engines"), getopts::optflag("b", "bubble-widths", "Bubble intrinsic widths separately like other engines"),
getopts::optflag("", "show-debug-borders", "Show debugging borders on layers and tiles."), getopts::optflag("", "show-debug-borders", "Show debugging borders on layers and tiles."),
getopts::optflag("", "disable-text-aa", "Disable antialiasing for text rendering."),
getopts::optflag("h", "help", "Print this message") getopts::optflag("h", "help", "Print this message")
); );
@ -194,6 +200,7 @@ pub fn from_cmdline_args(args: &[String]) -> Option<Opts> {
hard_fail: opt_match.opt_present("f"), hard_fail: opt_match.opt_present("f"),
bubble_inline_sizes_separately: opt_match.opt_present("b"), bubble_inline_sizes_separately: opt_match.opt_present("b"),
show_debug_borders: opt_match.opt_present("show-debug-borders"), show_debug_borders: opt_match.opt_present("show-debug-borders"),
enable_text_antialiasing: !opt_match.opt_present("disable-text-aa"),
}) })
} }

View file

@ -219,6 +219,8 @@ fn capture(reftest: &Reftest, side: uint) -> (u32, u32, Vec<u8>) {
if reftest.experimental { if reftest.experimental {
args.push("--experimental".to_string()); args.push("--experimental".to_string());
} }
// Allows pixel perfect rendering of Ahem font for reftests.
args.push("--disable-text-aa".to_string());
args.push_all(["-f".to_string(), "-o".to_string(), filename.clone(), args.push_all(["-f".to_string(), "-o".to_string(), filename.clone(),
reftest.files[side].clone()]); reftest.files[side].clone()]);

View file

@ -106,3 +106,4 @@ experimental == vertical-lr-blocks.html vertical-lr-blocks_ref.html
flaky_gpu,flaky_linux == acid2_noscroll.html acid2_ref_broken.html flaky_gpu,flaky_linux == acid2_noscroll.html acid2_ref_broken.html
!= inline_background_a.html inline_background_ref.html != inline_background_a.html inline_background_ref.html
== inline_element_border_a.html inline_element_border_ref.html

View file

@ -0,0 +1,24 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">
@font-face {
font-family: 'ahem';
src: url(fonts/ahem/ahem.ttf);
}
.large-border {
border-left: 100px solid red;
border-right: 100px solid blue;
}
.green {
color: green;
}
body {
font-family: 'ahem';
font-size: 100px;
margin: 0;
}
</style>
</head>
<body><span class="large-border green">X</span></body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">
.red {
background-color: red;
}
.green {
background-color: green;
}
.blue {
background-color: blue;
}
div {
width: 100px;
height: 100px;
float: left;
}
body {
margin: 0;
}
</style>
</head>
<body>
<div class="red"></div>
<div class="green"></div>
<div class="blue"></div>
</body>
</html>