From 9d7f78ac79b142bcf4c004c93375859ca578d83e Mon Sep 17 00:00:00 2001 From: Joel Feenstra Date: Wed, 29 May 2013 17:53:23 -0400 Subject: [PATCH 1/8] Add initial support for the line-height property. Line height is only based on the tallest box in each line and does not factor in the vertical-alignment. Improves whitespace handling by passing the whitespace state between function invocations. --- .gitignore | 12 +- src/components/gfx/platform/linux/font.rs | 2 +- src/components/gfx/platform/macos/font.rs | 12 +- src/components/gfx/text/util.rs | 73 ++++++++--- src/components/main/layout/box.rs | 53 ++++++-- src/components/main/layout/inline.rs | 153 +++++++++++----------- src/test/html/lineheight-simple.css | 10 ++ src/test/html/lineheight-simple.html | 10 ++ 8 files changed, 211 insertions(+), 114 deletions(-) create mode 100644 src/test/html/lineheight-simple.css create mode 100644 src/test/html/lineheight-simple.html diff --git a/.gitignore b/.gitignore index edb4c58ce5d..f6085e25031 100644 --- a/.gitignore +++ b/.gitignore @@ -17,9 +17,9 @@ config.mk config.stamp config.tmp parser.out -src/components/servo/dom/bindings/codegen/*.rs -src/components/servo/dom/bindings/codegen/_cache/ -src/components/servo/dom/bindings/codegen/test/*.rs -src/components/servo/dom/bindings/codegen/PrototypeList.h -src/components/servo/dom/bindings/codegen/UnionTypes.h -src/components/servo/dom/bindings/codegen/UnionConversions.h +src/components/script/dom/bindings/codegen/*.rs +src/components/script/dom/bindings/codegen/PrototypeList.h +src/components/script/dom/bindings/codegen/UnionConversions.h +src/components/script/dom/bindings/codegen/UnionTypes.h +src/components/script/dom/bindings/codegen/_cache/ +src/components/script/dom/bindings/codegen/test/*.rs diff --git a/src/components/gfx/platform/linux/font.rs b/src/components/gfx/platform/linux/font.rs index 1eddd68677b..f6b4b453da5 100644 --- a/src/components/gfx/platform/linux/font.rs +++ b/src/components/gfx/platform/linux/font.rs @@ -219,7 +219,7 @@ impl FontHandleMethods for FontHandle { x_height: geometry::from_pt(0.0), //FIXME em_size: em_size, ascent: ascent, - descent: descent, + descent: -descent, max_advance: max_advance } } diff --git a/src/components/gfx/platform/macos/font.rs b/src/components/gfx/platform/macos/font.rs index dbdbc2a0324..d510aa627ac 100644 --- a/src/components/gfx/platform/macos/font.rs +++ b/src/components/gfx/platform/macos/font.rs @@ -150,13 +150,17 @@ impl FontHandleMethods for FontHandle { &glyphs[0], ptr::null(), 1); - Some(advance as FractionalPixel) + // TODO; On mac the font spacing looks a little small. Need to figure out why. + Some(advance * 1.08f as FractionalPixel) } fn get_metrics(&self) -> FontMetrics { let bounding_rect: CGRect = self.ctfont.bounding_box(); let ascent = Au::from_pt(self.ctfont.ascent() as float); let descent = Au::from_pt(self.ctfont.descent() as float); + let em_size = Au::from_frac_px(self.ctfont.pt_size() as float); + + let scale = (self.ctfont.pt_size() as float * 72f / 96f) / (self.ctfont.ascent() as float + self.ctfont.descent() as float); let metrics = FontMetrics { underline_size: Au::from_pt(self.ctfont.underline_thickness() as float), @@ -168,9 +172,9 @@ impl FontHandleMethods for FontHandle { underline_offset: Au::from_pt(self.ctfont.underline_position() as float), leading: Au::from_pt(self.ctfont.leading() as float), x_height: Au::from_pt(self.ctfont.x_height() as float), - em_size: ascent + descent, - ascent: ascent, - descent: descent, + em_size: em_size, + ascent: ascent.scale_by(scale), + descent: descent.scale_by(scale), max_advance: Au::from_pt(bounding_rect.size.width as float) }; diff --git a/src/components/gfx/text/util.rs b/src/components/gfx/text/util.rs index 1ce4d4b4ff8..3938f8c3fb4 100644 --- a/src/components/gfx/text/util.rs +++ b/src/components/gfx/text/util.rs @@ -28,15 +28,15 @@ impl Eq for CompressionMode { // // High level TODOs: // -// * Issue #113: consider incoming text state (preceding spaces, arabic, etc) +// * Issue #113: consider incoming text state (arabic, etc) // and propogate outgoing text state (dual of above) // // * Issue #114: record skipped and kept chars for mapping original to new text // // * Untracked: various edge cases for bidi, CJK, etc. -pub fn transform_text(text: &str, mode: CompressionMode) -> ~str { +pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bool) -> (~str, bool) { let mut out_str: ~str = ~""; - match mode { + let out_whitespace = match mode { CompressNone | DiscardNewline => { for str::each_char(text) |ch: char| { if is_discardable_char(ch, mode) { @@ -49,18 +49,14 @@ pub fn transform_text(text: &str, mode: CompressionMode) -> ~str { str::push_char(&mut out_str, ch); } } + text.len() > 0 && is_in_whitespace(text.char_at_reverse(0), mode) }, CompressWhitespace | CompressWhitespaceNewline => { - let mut in_whitespace: bool = false; + let mut in_whitespace: bool = incoming_whitespace; for str::each_char(text) |ch: char| { // TODO: discard newlines between CJK chars - let mut next_in_whitespace: bool = match (ch, mode) { - (' ', _) => true, - ('\t', _) => true, - ('\n', CompressWhitespaceNewline) => true, - (_, _) => false - }; + let mut next_in_whitespace: bool = is_in_whitespace(ch, mode); if !next_in_whitespace { if is_always_discardable_char(ch) { @@ -82,10 +78,20 @@ pub fn transform_text(text: &str, mode: CompressionMode) -> ~str { // save whitespace context for next char in_whitespace = next_in_whitespace; } /* /for str::each_char */ + in_whitespace } - } + }; - return out_str; + return (out_str, out_whitespace); + + fn is_in_whitespace(ch: char, mode: CompressionMode) -> bool { + match (ch, mode) { + (' ', _) => true, + ('\t', _) => true, + ('\n', CompressWhitespaceNewline) => true, + (_, _) => false + } + } fn is_discardable_char(ch: char, mode: CompressionMode) -> bool { if is_always_discardable_char(ch) { @@ -143,7 +149,8 @@ fn test_transform_compress_none() { let mode = CompressNone; for uint::range(0, test_strs.len()) |i| { - assert!(transform_text(test_strs[i], mode) == test_strs[i]); + (trimmed_str, out) = transform_text(test_strs[i], mode, true); + assert!(trimmed_str == test_strs[i]) } } @@ -170,7 +177,8 @@ fn test_transform_discard_newline() { let mode = DiscardNewline; for uint::range(0, test_strs.len()) |i| { - assert!(transform_text(test_strs[i], mode) == oracle_strs[i]); + (trimmed_str, out) = transform_text(test_strs[i], mode, true); + assert!(trimmed_str == oracle_strs[i]) } } @@ -196,7 +204,8 @@ fn test_transform_compress_whitespace() { let mode = CompressWhitespace; for uint::range(0, test_strs.len()) |i| { - assert!(transform_text(test_strs[i], mode) == oracle_strs[i]); + (trimmed_str, out) = transform_text(test_strs[i], mode, true); + assert!(trimmed_str == oracle_strs[i]) } } @@ -210,7 +219,7 @@ fn test_transform_compress_whitespace_newline() { ~"foo bar baz", ~"foobarbaz\n\n"]; - let oracle_strs : ~[~str] = ~[~" foo bar", + let oracle_strs : ~[~str] = ~[~"foo bar", ~"foo bar ", ~"foo bar", ~"foo bar", @@ -222,6 +231,36 @@ fn test_transform_compress_whitespace_newline() { let mode = CompressWhitespaceNewline; for uint::range(0, test_strs.len()) |i| { - assert!(transform_text(test_strs[i], mode) == oracle_strs[i]); + (trimmed_str, out) = transform_text(test_strs[i], mode, true); + assert!(trimmed_str == oracle_strs[i]) + } +} + +#[test] +fn test_transform_compress_whitespace_newline() { + let test_strs : ~[~str] = ~[~" foo bar", + ~"\nfoo bar", + ~"foo bar ", + ~"foo\n bar", + ~"foo \nbar", + ~" foo bar \nbaz", + ~"foo bar baz", + ~"foobarbaz\n\n"]; + + let oracle_strs : ~[~str] = ~[~" foo bar", + ~" foo bar", + ~"foo bar ", + ~"foo bar", + ~"foo bar", + ~" foo bar baz", + ~"foo bar baz", + ~"foobarbaz "]; + + assert!(test_strs.len() == oracle_strs.len()); + let mode = CompressWhitespaceNewline; + + for uint::range(0, test_strs.len()) |i| { + (trimmed_str, out) = transform_text(test_strs[i], mode, false); + assert!(trimmed_str == oracle_strs[i]) } } diff --git a/src/components/main/layout/box.rs b/src/components/main/layout/box.rs index a9f834f4d9c..ad1ebe46f35 100644 --- a/src/components/main/layout/box.rs +++ b/src/components/main/layout/box.rs @@ -27,7 +27,7 @@ use newcss::units::{Cursive, Em, Fantasy, Monospace, Pt, Px, SansSerif, Serif}; use newcss::values::{CSSBorderWidthLength, CSSBorderWidthMedium}; use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily}; use newcss::values::{CSSFontSizeLength, CSSFontStyleItalic, CSSFontStyleNormal}; -use newcss::values::{CSSFontStyleOblique, CSSTextAlign, CSSTextDecoration}; +use newcss::values::{CSSFontStyleOblique, CSSTextAlign, CSSTextDecoration, CSSLineHeight}; use newcss::values::{CSSTextDecorationNone, CSSFloatNone, CSSPositionStatic}; use newcss::values::{CSSDisplayInlineBlock, CSSDisplayInlineTable}; use script::dom::node::{AbstractNode, LayoutView}; @@ -560,12 +560,10 @@ pub impl RenderBox { return; } - // Add the background to the list, if applicable. - self.paint_background_if_applicable(list, &absolute_box_bounds); - match *self { UnscannedTextRenderBoxClass(*) => fail!(~"Shouldn't see unscanned boxes here."), TextRenderBoxClass(text_box) => { + let nearest_ancestor_element = self.nearest_ancestor_element(); let color = nearest_ancestor_element.style().color().to_gfx_color(); @@ -623,10 +621,34 @@ pub impl RenderBox { () }); }, + GenericRenderBoxClass(_) => { - GenericRenderBoxClass(_) => {} + // Add the background to the list, if applicable. + self.paint_background_if_applicable(list, &absolute_box_bounds); + // FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We + // should have a real `SERVO_DEBUG` system. + debug!("%?", { + do list.with_mut_ref |list| { + let border_display_item = ~BorderDisplayItem { + base: BaseDisplayItem { + bounds: absolute_box_bounds, + }, + width: Au::from_px(1), + color: rgb(0, 0, 200).to_gfx_color(), + }; + list.append_item(BorderDisplayItemClass(border_display_item)) + } + + () + }); + + }, ImageRenderBoxClass(image_box) => { + + // Add the background to the list, if applicable. + self.paint_background_if_applicable(list, &absolute_box_bounds); + match image_box.image.get_image() { Some(image) => { debug!("(building display list) building image box"); @@ -752,6 +774,9 @@ pub impl RenderBox { fn font_style(&self) -> FontStyle { let my_style = self.nearest_ancestor_element().style(); + debug!("(font style) start: %?", self.nearest_ancestor_element().type_id()); + self.dump(); + // FIXME: Too much allocation here. let font_families = do my_style.font_family().map |family| { match *family { @@ -767,12 +792,12 @@ pub impl RenderBox { debug!("(font style) font families: `%s`", font_families); let font_size = match my_style.font_size() { - CSSFontSizeLength(Px(length)) | - CSSFontSizeLength(Pt(length)) | - CSSFontSizeLength(Em(length)) => length, - _ => 16.0 + CSSFontSizeLength(Px(length)) => length * 72f / 96f, + CSSFontSizeLength(Pt(length)) => length, + CSSFontSizeLength(Em(length)) => length * 16f, + _ => 12f // pt units }; - debug!("(font style) font size: `%f`", font_size); + debug!("(font style) font size: `%fpt`", font_size); let (italic, oblique) = match my_style.font_style() { CSSFontStyleNormal => (false, false), @@ -781,7 +806,7 @@ pub impl RenderBox { }; FontStyle { - pt_size: font_size, + pt_size: font_size * 96f / 72f, // TODO: scale to pt weight: FontWeight300, italic: italic, oblique: oblique, @@ -795,6 +820,10 @@ pub impl RenderBox { self.nearest_ancestor_element().style().text_align() } + fn line_height(&self) -> CSSLineHeight { + self.nearest_ancestor_element().style().line_height() + } + /// Returns the text decoration of the computed style of the nearest `Element` node fn text_decoration(&self) -> CSSTextDecoration { /// Computes the propagated value of text-decoration, as specified in CSS 2.1 § 16.3.1 @@ -862,7 +891,7 @@ pub impl RenderBox { text_box.range.length())) } UnscannedTextRenderBoxClass(text_box) => { - fmt!("UnscannedTextRenderBox(%s)", text_box.text) + fmt!("UnscannedTextRenderBox(%?, %s)", text_box.base.node.type_id(), text_box.text) } }; diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs index 3db7e23e34e..fde9052657d 100644 --- a/src/components/main/layout/inline.rs +++ b/src/components/main/layout/inline.rs @@ -20,6 +20,12 @@ use gfx::text::util::*; use newcss::values::{CSSTextAlignCenter, CSSTextAlignJustify, CSSTextAlignLeft}; use newcss::values::{CSSTextAlignRight, CSSTextDecoration, CSSTextDecorationUnderline}; use script::dom::node::{AbstractNode, LayoutView}; +use newcss::values::{CSSTextAlignRight}; +use newcss::values::CSSTextDecorationUnderline; +use newcss::values::CSSTextDecoration; +use newcss::units::{Em, Px, Pt}; +use newcss::values::{CSSLineHeightNormal, CSSLineHeightNumber, CSSLineHeightLength, CSSLineHeightPercentage}; + use servo_util::range::Range; use std::deque::Deque; @@ -191,17 +197,18 @@ impl TextRunScanner { assert!(inline.boxes.len() > 0); debug!("TextRunScanner: scanning %u boxes for text runs...", inline.boxes.len()); + let mut last_whitespace = true; let mut out_boxes = ~[]; for uint::range(0, flow.inline().boxes.len()) |box_i| { debug!("TextRunScanner: considering box: %?", flow.inline().boxes[box_i].debug_str()); if box_i > 0 && !can_coalesce_text_nodes(flow.inline().boxes, box_i-1, box_i) { - self.flush_clump_to_list(ctx, flow, &mut out_boxes); + last_whitespace = self.flush_clump_to_list(ctx, flow, last_whitespace, &mut out_boxes); } self.clump.extend_by(1); } // handle remaining clumps if self.clump.length() > 0 { - self.flush_clump_to_list(ctx, flow, &mut out_boxes); + self.flush_clump_to_list(ctx, flow, last_whitespace, &mut out_boxes); } debug!("TextRunScanner: swapping out boxes."); @@ -238,7 +245,8 @@ impl TextRunScanner { fn flush_clump_to_list(&mut self, ctx: &mut LayoutContext, flow: FlowContext, - out_boxes: &mut ~[RenderBox]) { + last_whitespace: bool, + out_boxes: &mut ~[RenderBox]) -> bool { let inline = &mut *flow.inline(); let in_boxes = &inline.boxes; @@ -258,6 +266,8 @@ impl TextRunScanner { _ => false }; + let mut new_whitespace = last_whitespace; + match (is_singleton, is_text_clump) { (false, false) => { fail!(~"WAT: can't coalesce non-text nodes in flush_clump_to_list()!") @@ -275,35 +285,42 @@ impl TextRunScanner { // TODO(#115): Use the actual CSS `white-space` property of the relevant style. let compression = CompressWhitespaceNewline; - let transformed_text = transform_text(text, compression); + let (transformed_text, whitespace) = transform_text(text, compression, last_whitespace); + new_whitespace = whitespace; - // TODO(#177): Text run creation must account for the renderability of text by - // font group fonts. This is probably achieved by creating the font group above - // and then letting `FontGroup` decide which `Font` to stick into the text run. - let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&font_style); - let run = @fontgroup.create_textrun(transformed_text, underline); + if transformed_text.len() > 0 { + // TODO(#177): Text run creation must account for the renderability of text by + // font group fonts. This is probably achieved by creating the font group above + // and then letting `FontGroup` decide which `Font` to stick into the text run. + let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&font_style); + let run = @fontgroup.create_textrun(transformed_text, underline); - debug!("TextRunScanner: pushing single text box in range: %?", self.clump); - let new_box = do old_box.with_imm_base |old_box_base| { - let range = Range::new(0, run.char_len()); - @mut adapt_textbox_with_range(*old_box_base, run, range) - }; + debug!("TextRunScanner: pushing single text box in range: %?", self.clump); + let new_box = do old_box.with_imm_base |old_box_base| { + let range = Range::new(0, run.char_len()); + @mut adapt_textbox_with_range(*old_box_base, run, range) + }; - out_boxes.push(TextRenderBoxClass(new_box)); + out_boxes.push(TextRenderBoxClass(new_box)); + } }, (false, true) => { // TODO(#115): Use the actual CSS `white-space` property of the relevant style. let compression = CompressWhitespaceNewline; // First, transform/compress text of all the nodes. + let mut last_whitespace = true; let transformed_strs: ~[~str] = do vec::from_fn(self.clump.length()) |i| { // TODO(#113): We should be passing the compression context between calls to // `transform_text`, so that boxes starting and/or ending with whitespace can // be compressed correctly with respect to the text run. let idx = i + self.clump.begin(); - transform_text(in_boxes[idx].raw_text(), compression) + let (new_str, new_whitespace) = transform_text(in_boxes[idx].raw_text(), compression, last_whitespace); + last_whitespace = new_whitespace; + new_str }; - + new_whitespace = last_whitespace; + // Next, concatenate all of the transformed strings together, saving the new // character indices. let mut run_str: ~str = ~""; @@ -328,7 +345,7 @@ impl TextRunScanner { // TextRuns contain a cycle which is usually resolved by the teardown // sequence. If no clump takes ownership, however, it will leak. let clump = self.clump; - let run = if clump.length() != 0 { + let run = if clump.length() != 0 && run_str.len() > 0 { Some(@TextRun::new(fontgroup.fonts[0], run_str, underline)) } else { None @@ -373,6 +390,8 @@ impl TextRunScanner { let end = self.clump.end(); // FIXME: borrow checker workaround self.clump.reset(end, 0); + + new_whitespace } // End of `flush_clump_to_list`. } @@ -748,7 +767,6 @@ impl InlineFlowData { // TODO(#226): Get the CSS `line-height` property from each non-replaced inline element to // determine its height for computing linebox height. - let line_height = Au::from_px(20); let mut cur_y = Au(0); for self.lines.eachi |i, line_span| { @@ -756,64 +774,64 @@ impl InlineFlowData { // These coordinates are relative to the left baseline. let mut linebox_bounding_box = Au::zero_rect(); + let mut linebox_height = Au(0); + let mut baseline_offset = Au(0); + let boxes = &mut self.boxes; + for line_span.eachi |box_i| { let cur_box = boxes[box_i]; // FIXME: borrow checker workaround - // Compute the height of each box. - match cur_box { + // Compute the height and bounding box of each box. + let bounding_box = match cur_box { ImageRenderBoxClass(image_box) => { let size = image_box.image.get_size(); let height = Au::from_px(size.get_or_default(Size2D(0, 0)).height); image_box.base.position.size.height = height; + + image_box.base.position.translate(&Point2D(Au(0), -height)) } - TextRenderBoxClass(*) => { - // Text boxes are preinitialized. + TextRenderBoxClass(text_box) => { + + let range = &text_box.range; + let run = &text_box.run; + + // Compute the height based on the line-height and font size + let text_bounds = run.metrics_for_range(range).bounding_box; + let em_size = text_bounds.size.height; + let line_height = match cur_box.line_height() { + CSSLineHeightNormal => em_size.scale_by(1.14f), + CSSLineHeightNumber(l) => em_size.scale_by(l), + CSSLineHeightLength(Em(l)) => em_size.scale_by(l), + CSSLineHeightLength(Px(l)) => Au::from_frac_px(l), + CSSLineHeightLength(Pt(l)) => Au::from_pt(l), + CSSLineHeightPercentage(p) => em_size.scale_by(p / 100.0f) + }; + + // If this is the current tallest box then use it for baseline + // calculations. + // TODO: this will need to take into account type of line-height + // and the vertical-align value. + if line_height > linebox_height { + linebox_height = line_height; + // Offset from the top of the linebox + baseline_offset = text_box.run.font.metrics.ascent + + (linebox_height - em_size).scale_by(0.5f); + } + text_bounds.translate(&Point2D(text_box.base.position.origin.x, Au(0))) } GenericRenderBoxClass(generic_box) => { // TODO(Issue #225): There will be different cases here for `inline-block` // and other replaced content. // FIXME(pcwalton): This seems clownshoes; can we remove? generic_box.position.size.height = Au::from_px(30); + generic_box.position } // FIXME(pcwalton): This isn't very type safe! _ => { fail!(fmt!("Tried to assign height to unknown Box variant: %s", cur_box.debug_str())) } - } - - // Compute the bounding rect with the left baseline as origin. Determining line box - // height is a matter of lining up ideal baselines and then taking the union of all - // these rects. - let bounding_box = match cur_box { - // Adjust to baseline coordinates. - // - // TODO(#227): Use left/right margins, border, padding for nonreplaced content, - // and also use top/bottom margins, border, padding for replaced or - // inline-block content. - // - // TODO(#225): Use height, width for `inline-block` and other replaced content. - ImageRenderBoxClass(*) | GenericRenderBoxClass(*) => { - let height = cur_box.position().size.height; - cur_box.position().translate(&Point2D(Au(0), -height)) - }, - - // Adjust the bounding box metric to the box's horizontal offset. - // - // TODO: We can use font metrics directly instead of re-measuring for the - // bounding box. - TextRenderBoxClass(text_box) => { - let range = &text_box.range; - let run = &text_box.run; - let text_bounds = run.metrics_for_range(range).bounding_box; - text_bounds.translate(&Point2D(text_box.base.position.origin.x, Au(0))) - }, - - _ => { - fail!(fmt!("Tried to compute bounding box of unknown Box variant: %s", - cur_box.debug_str())) - } }; debug!("assign_height_inline: bounding box for box b%d = %?", @@ -825,9 +843,6 @@ impl InlineFlowData { debug!("assign_height_inline: linebox bounding box = %?", linebox_bounding_box); } - let linebox_height = linebox_bounding_box.size.height; - let baseline_offset = -linebox_bounding_box.origin.y; - // Now go back and adjust the Y coordinates to match the baseline we determined. for line_span.eachi |box_i| { let cur_box = boxes[box_i]; @@ -835,30 +850,20 @@ impl InlineFlowData { // TODO(#226): This is completely wrong. We need to use the element's `line-height` // when calculating line box height. Then we should go back over and set Y offsets // according to the `vertical-align` property of the containing block. - let halfleading = match cur_box { + let offset = match cur_box { TextRenderBoxClass(text_box) => { - //ad is the AD height as defined by CSS 2.1 § 10.8.1 - let ad = text_box.run.font.metrics.ascent + text_box.run.font.metrics.descent; - (line_height - ad).scale_by(0.5) + baseline_offset - text_box.run.font.metrics.ascent }, _ => Au(0), }; - //FIXME: when line-height is set on an inline element, the half leading - //distance can be negative. - let halfleading = Au::max(halfleading, Au(0)); - - let height = match cur_box { - TextRenderBoxClass(text_box) => text_box.run.font.metrics.ascent, - _ => cur_box.position().size.height - }; - do cur_box.with_mut_base |base| { - base.position.origin.y = cur_y + halfleading + baseline_offset - height; + let height = base.position.size.height; + base.position.origin.y = offset + cur_y; } } - cur_y += Au::max(line_height, linebox_height); + cur_y += linebox_height; } // End of `lines.each` loop. self.common.position.size.height = cur_y; diff --git a/src/test/html/lineheight-simple.css b/src/test/html/lineheight-simple.css new file mode 100644 index 00000000000..bd8510f8061 --- /dev/null +++ b/src/test/html/lineheight-simple.css @@ -0,0 +1,10 @@ +#larger1 { + font-size: 20px; + line-height: 2; +} + +#larger2 { + font-size: 30px; + line-height: 1; +} + diff --git a/src/test/html/lineheight-simple.html b/src/test/html/lineheight-simple.html new file mode 100644 index 00000000000..ed18ccdac80 --- /dev/null +++ b/src/test/html/lineheight-simple.html @@ -0,0 +1,10 @@ + + + + + + +
Regular font Even larger with line-height 2
+
Large line 2!
+ + From c07a2be6e76f777a266d988cdc8fd976b21ce8a3 Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Mon, 17 Jun 2013 10:01:45 -0600 Subject: [PATCH 2/8] Propagate debug flag in Makefiles. --- Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.in b/Makefile.in index dad52716089..90adb878799 100644 --- a/Makefile.in +++ b/Makefile.in @@ -49,6 +49,7 @@ endif export CFG_RUSTC export CFG_RUSTC_FLAGS export CFG_LOCAL_RUSTC +export CFG_ENABLE_DEBUG export RUSTC=$(CFG_RUSTC) export RUSTFLAGS=$(CFG_RUSTC_FLAGS) From 1eea39a808df8a2cd37030b32fded7c3e900bd68 Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Mon, 17 Jun 2013 10:02:29 -0600 Subject: [PATCH 3/8] Adding renderer drawing category to profiler. --- src/components/util/time.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/util/time.rs b/src/components/util/time.rs index 95bdc207e34..deaec504286 100644 --- a/src/components/util/time.rs +++ b/src/components/util/time.rs @@ -37,6 +37,7 @@ pub enum ProfilerCategory { LayoutShapingCategory, LayoutDispListBuildCategory, GfxRegenAvailableFontsCategory, + RenderingDrawingCategory, RenderingPrepBuffCategory, RenderingWaitSubtasksCategory, RenderingCategory, @@ -81,6 +82,7 @@ impl ProfilerCategory { vec.push((LayoutShapingCategory, ~[])); vec.push((LayoutDispListBuildCategory, ~[])); vec.push((GfxRegenAvailableFontsCategory, ~[])); + vec.push((RenderingDrawingCategory, ~[])); vec.push((RenderingPrepBuffCategory, ~[])); vec.push((RenderingWaitSubtasksCategory, ~[])); vec.push((RenderingCategory, ~[])); From ece8791c26134d359c6a9466cf45214445b8a01a Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Mon, 17 Jun 2013 13:54:42 -0600 Subject: [PATCH 4/8] Warning police. --- src/components/gfx/display_list.rs | 1 - src/components/main/compositing/mod.rs | 9 +++------ src/components/main/layout/aux.rs | 12 ++++++------ .../main/platform/common/glut_windowing.rs | 5 +++-- src/components/script/script_task.rs | 2 +- src/support/azure/rust-azure | 2 +- src/support/netsurfcss/libcss | 2 +- src/support/skia/skia | 2 +- 8 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/components/gfx/display_list.rs b/src/components/gfx/display_list.rs index 8a7d5135242..508bd32a013 100644 --- a/src/components/gfx/display_list.rs +++ b/src/components/gfx/display_list.rs @@ -24,7 +24,6 @@ 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 { diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs index ba32b706c41..7e6a83c373c 100644 --- a/src/components/main/compositing/mod.rs +++ b/src/components/main/compositing/mod.rs @@ -3,15 +3,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use platform::{Application, Window}; +use script::dom::event::{Event, ClickEvent, MouseDownEvent, MouseUpEvent, ResizeEvent}; use script::script_task::{LoadMsg, SendEventMsg}; +use script::layout_interface::{LayoutChan, RouteScriptMsg}; +use script::compositor_interface::{ReadyState, ScriptListener}; use windowing::{ApplicationMethods, WindowMethods, WindowMouseEvent, WindowClickEvent}; use windowing::{WindowMouseDownEvent, WindowMouseUpEvent}; - -use script::dom::event::{Event, ClickEvent, MouseDownEvent, MouseUpEvent, ResizeEvent}; -use script::compositor_interface::{ReadyState, ScriptListener}; -use script::script_task::{ScriptChan, SendEventMsg}; -use script::layout_interface::{LayoutChan, RouteScriptMsg}; - use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods, current_gl_context}; use azure::azure::AzGLContext; use core::cell::Cell; diff --git a/src/components/main/layout/aux.rs b/src/components/main/layout/aux.rs index 59682ef20b7..11a878246ea 100644 --- a/src/components/main/layout/aux.rs +++ b/src/components/main/layout/aux.rs @@ -42,19 +42,19 @@ pub trait LayoutAuxMethods { impl LayoutAuxMethods for AbstractNode { // FIXME (Rust #3080): These unsafe blocks are *not* unused! pub fn layout_data(self) -> @mut LayoutData { - unsafe { + /*unsafe {*/ self.unsafe_layout_data() - } + /*}*/ } pub fn has_layout_data(self) -> bool { - unsafe { + /*unsafe {*/ self.unsafe_has_layout_data() - } + /*}*/ } pub fn set_layout_data(self, data: @mut LayoutData) { - unsafe { + /*unsafe {*/ self.unsafe_set_layout_data(data) - } + /*}*/ } /// If none exists, creates empty layout data for the node (the reader-auxiliary diff --git a/src/components/main/platform/common/glut_windowing.rs b/src/components/main/platform/common/glut_windowing.rs index 50e67d6e541..d633bb55056 100644 --- a/src/components/main/platform/common/glut_windowing.rs +++ b/src/components/main/platform/common/glut_windowing.rs @@ -59,7 +59,8 @@ impl WindowMethods for Window { /// Creates a new window. pub fn new(_: &Application) -> @mut Window { // Create the GLUT window. - unsafe { glut::bindgen::glutInitWindowSize(800, 600); } + // FIXME (Rust #3080): These unsafe blocks are *not* unused! + /*unsafe { */glut::bindgen::glutInitWindowSize(800, 600);/* }*/ let glut_window = glut::create_window(~"Servo"); // Create our window object. @@ -117,7 +118,7 @@ impl WindowMethods for Window { window.handle_mouse(button, state, x, y); } } - do glut::mouse_wheel_func |wheel, direction, x, y| { + do glut::mouse_wheel_func |wheel, direction, _x, _y| { let delta = if HAVE_PRECISE_MOUSE_WHEEL { (direction as f32) / 10000.0 } else { diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 39ef337b2f1..6eddd9d6335 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -546,7 +546,7 @@ impl ScriptContext { } } - ClickEvent(button, point) => { + ClickEvent(_button, point) => { debug!("ClickEvent: clicked at %?", point); let root = match self.root_frame { Some(ref frame) => frame.document.root, diff --git a/src/support/azure/rust-azure b/src/support/azure/rust-azure index 04976e3fae0..b754fd3d16f 160000 --- a/src/support/azure/rust-azure +++ b/src/support/azure/rust-azure @@ -1 +1 @@ -Subproject commit 04976e3fae0ef0332036082ab8770fb1ad2c10ca +Subproject commit b754fd3d16f6acc80ae2252a310f8c71070366c3 diff --git a/src/support/netsurfcss/libcss b/src/support/netsurfcss/libcss index d722188de38..da248d3f5b3 160000 --- a/src/support/netsurfcss/libcss +++ b/src/support/netsurfcss/libcss @@ -1 +1 @@ -Subproject commit d722188de3876ed748382965eb4f300fc1b78bf8 +Subproject commit da248d3f5b3ed6d9e804c543563be8e34baf1673 diff --git a/src/support/skia/skia b/src/support/skia/skia index 7415c2829e7..5c00e2b7f47 160000 --- a/src/support/skia/skia +++ b/src/support/skia/skia @@ -1 +1 @@ -Subproject commit 7415c2829e77812411a2ae9cf448c0e288035463 +Subproject commit 5c00e2b7f471e70a892aeae36b4c77b78227823f From a9e1354118341b3b74399171e222eace676252d2 Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Mon, 17 Jun 2013 14:17:06 -0600 Subject: [PATCH 5/8] Refactor renderer into single function. This removes the task per tile rendering and instead renders tiles serially. This also unwraps the rendering into a single function so that it's much clearer. --- src/components/gfx/gfx.rc | 1 - src/components/gfx/render_layers.rs | 113 ----------------- src/components/gfx/render_task.rs | 145 +++++++++++----------- src/components/main/layout/layout_task.rs | 3 +- src/components/util/time.rs | 2 - 5 files changed, 75 insertions(+), 189 deletions(-) delete mode 100644 src/components/gfx/render_layers.rs diff --git a/src/components/gfx/gfx.rc b/src/components/gfx/gfx.rc index eae2328152a..c96e4e4b8da 100644 --- a/src/components/gfx/gfx.rc +++ b/src/components/gfx/gfx.rc @@ -42,7 +42,6 @@ pub mod color; pub mod compositor; pub mod display_list; pub mod geometry; -pub mod render_layers; pub mod render_task; pub mod surface; diff --git a/src/components/gfx/render_layers.rs b/src/components/gfx/render_layers.rs deleted file mode 100644 index fd8bdb03e86..00000000000 --- a/src/components/gfx/render_layers.rs +++ /dev/null @@ -1,113 +0,0 @@ -/* 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/. */ - -use compositor::{LayerBuffer, LayerBufferSet}; -use display_list::DisplayList; -use opts::Opts; -use servo_util::time; -use servo_util::time::ProfilerChan; - -use azure::azure_hl::{B8G8R8A8, DrawTarget}; -use azure::azure::{AzGLContext}; -use core::comm::Chan; -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, - size: Size2D -} - -type RenderFn<'self> = &'self fn(layer: *RenderLayer, - buffer: LayerBuffer, - return_buffer: Chan); - -/// Given a layer and a buffer, either reuses the buffer (if it's of the right size and format) -/// or creates a new buffer (if it's not of the appropriate size and format) and invokes the -/// given callback with the render layer and the buffer. Returns the resulting layer buffer (which -/// might be the old layer buffer if it had the appropriate size and format). -pub fn render_layers(layer_ref: *RenderLayer, - opts: &Opts, - prof_chan: ProfilerChan, - share_gl_context: AzGLContext, - f: RenderFn) - -> LayerBufferSet { - let tile_size = opts.tile_size; - let scale = opts.zoom; - - // FIXME: Try not to create a new array here. - let mut new_buffer_ports = ~[]; - - // Divide up the layer into tiles. - do time::profile(time::RenderingPrepBuffCategory, prof_chan.clone()) { - let layer: &RenderLayer = unsafe { cast::transmute(layer_ref) }; - let mut y = 0; - while y < layer.size.height * scale { - let mut x = 0; - while x < layer.size.width * scale { - // Figure out the dimension of this tile. - let right = uint::min(x + tile_size, layer.size.width * scale); - let bottom = uint::min(y + tile_size, layer.size.height * scale); - let width = right - x; - let height = bottom - y; - - let tile_rect = Rect(Point2D(x / scale, y / scale), Size2D(width, height)); //change this - let screen_rect = Rect(Point2D(x, y), Size2D(width, height)); //change this - - 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. - /*if buffers.len() != 0 && buffers[0].rect == tile_rect { - debug!("reusing tile, (%u, %u)", x, y); - buffer = buffers.shift(); - } else {*/ - // Create a new buffer. - debug!("creating tile, (%u, %u)", x, y); - - // FIXME: This may not be always true. - let stride = width * 4; - - buffer = LayerBuffer { - draw_target: DrawTarget::new_with_fbo(opts.render_backend, - share_gl_context, - Size2D(width as i32, height as i32), - B8G8R8A8), - rect: tile_rect, - screen_pos: screen_rect, - stride: stride as uint - }; - //} - - // Create a port and channel pair to receive the new buffer. - let (new_buffer_port, new_buffer_chan) = comm::stream(); - - // Send the buffer to the child. - f(layer_ref, buffer, new_buffer_chan); - - // Enqueue the port. - new_buffer_ports.push(new_buffer_port); - - x += tile_size; - } - y += tile_size; - } - } - - let mut new_buffers = ~[]; - do time::profile(time::RenderingWaitSubtasksCategory, prof_chan.clone()) { - for new_buffer_ports.each |new_buffer_port| { - new_buffers.push(new_buffer_port.recv()); - } - } - - LayerBufferSet { - buffers: new_buffers, - } -} - diff --git a/src/components/gfx/render_task.rs b/src/components/gfx/render_task.rs index 8cb63f885f1..07c530bf2e1 100644 --- a/src/components/gfx/render_task.rs +++ b/src/components/gfx/render_task.rs @@ -5,23 +5,28 @@ // The task that handles all rendering/painting. use azure::{AzFloat, AzGLContext}; -use compositor::{RenderListener, IdleRenderState, RenderingRenderState}; +use azure::azure_hl::{B8G8R8A8, DrawTarget}; +use compositor::{RenderListener, IdleRenderState, RenderingRenderState, LayerBuffer, LayerBufferSet}; +use display_list::DisplayList; use font_context::FontContext; use geom::matrix2d::Matrix2D; +use geom::point::Point2D; +use geom::size::Size2D; +use geom::rect::Rect; use opts::Opts; use render_context::RenderContext; -use render_layers::{RenderLayer, render_layers}; use core::cell::Cell; use core::comm::{Chan, Port, SharedChan}; -use core::task::SingleThreaded; -use std::task_pool::TaskPool; - -use servo_net::util::spawn_listener; use servo_util::time::{ProfilerChan, profile}; use servo_util::time; +pub struct RenderLayer { + display_list: DisplayList<()>, + size: Size2D +} + pub enum Msg { AttachCompositorMsg(C), RenderMsg(RenderLayer), @@ -62,38 +67,17 @@ pub fn create_render_task(port: Port>, do spawn { let compositor = compositor_cell.take(); let share_gl_context = compositor.get_gl_context(); - - // FIXME: Annoying three-cell dance here. We need one-shot closures. let opts = opts_cell.with_ref(|o| copy *o); - let n_threads = opts.n_render_threads; - let new_opts_cell = Cell(opts); - let profiler_chan = profiler_chan.clone(); let profiler_chan_copy = profiler_chan.clone(); - let thread_pool = do TaskPool::new(n_threads, Some(SingleThreaded)) { - let opts_cell = Cell(new_opts_cell.with_ref(|o| copy *o)); - let profiler_chan = Cell(profiler_chan.clone()); - - let f: ~fn(uint) -> ThreadRenderContext = |thread_index| { - let opts = opts_cell.with_ref(|opts| copy *opts); - - ThreadRenderContext { - thread_index: thread_index, - font_ctx: @mut FontContext::new(opts.render_backend, - false, - profiler_chan.take()), - opts: opts, - } - }; - f - }; - // FIXME: rust/#5967 let mut renderer = Renderer { port: port.take(), compositor: compositor, - thread_pool: thread_pool, + font_ctx: @mut FontContext::new(opts.render_backend, + false, + profiler_chan), opts: opts_cell.take(), profiler_chan: profiler_chan_copy, share_gl_context: share_gl_context, @@ -103,17 +87,10 @@ pub fn create_render_task(port: Port>, } } -/// Data that needs to be kept around for each render thread. -priv struct ThreadRenderContext { - thread_index: uint, - font_ctx: @mut FontContext, - opts: Opts, -} - priv struct Renderer { port: Port>, compositor: C, - thread_pool: TaskPool, + font_ctx: @mut FontContext, opts: Opts, /// A channel to the profiler. @@ -142,48 +119,74 @@ impl Renderer { debug!("renderer: rendering"); self.compositor.set_render_state(RenderingRenderState); do profile(time::RenderingCategory, self.profiler_chan.clone()) { - let layer_buffer_set = do render_layers(&render_layer, - &self.opts, - self.profiler_chan.clone(), - self.share_gl_context) |render_layer_ref, - layer_buffer, - buffer_chan| { - let layer_buffer_cell = Cell(layer_buffer); - do self.thread_pool.execute |thread_render_context| { - do layer_buffer_cell.with_ref |layer_buffer| { - // Build the render context. - let ctx = RenderContext { - canvas: layer_buffer, - font_ctx: thread_render_context.font_ctx, - opts: &thread_render_context.opts + let tile_size = self.opts.tile_size; + let scale = self.opts.zoom; + + // FIXME: Try not to create a new array here. + let mut new_buffers = ~[]; + + // Divide up the layer into tiles. + do time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone()) { + let mut y = 0; + while y < render_layer.size.height * scale { + let mut x = 0; + while x < render_layer.size.width * scale { + // Figure out the dimension of this tile. + let right = uint::min(x + tile_size, render_layer.size.width * scale); + let bottom = uint::min(y + tile_size, render_layer.size.height * scale); + let width = right - x; + let height = bottom - y; + + let tile_rect = Rect(Point2D(x / scale, y / scale), Size2D(width, height)); //change this + let screen_rect = Rect(Point2D(x, y), Size2D(width, height)); //change this + + let buffer = LayerBuffer { + draw_target: DrawTarget::new_with_fbo(self.opts.render_backend, + self.share_gl_context, + Size2D(width as i32, height as i32), + B8G8R8A8), + rect: tile_rect, + screen_pos: screen_rect, + stride: (width * 4) as uint }; - // Apply the translation to render the tile we want. - let matrix: Matrix2D = Matrix2D::identity(); - let scale = thread_render_context.opts.zoom as f32; + { + // Build the render context. + let ctx = RenderContext { + canvas: &buffer, + font_ctx: self.font_ctx, + opts: &self.opts + }; - let matrix = matrix.scale(scale as AzFloat, scale as AzFloat); - let matrix = matrix.translate(-(layer_buffer.rect.origin.x as f32) as AzFloat, - -(layer_buffer.rect.origin.y as f32) as AzFloat); + // Apply the translation to render the tile we want. + let matrix: Matrix2D = Matrix2D::identity(); + let matrix = matrix.scale(scale as AzFloat, scale as AzFloat); + let matrix = matrix.translate(-(buffer.rect.origin.x as f32) as AzFloat, + -(buffer.rect.origin.y as f32) as AzFloat); - layer_buffer.draw_target.set_transform(&matrix); + ctx.canvas.draw_target.set_transform(&matrix); - // Clear the buffer. - ctx.clear(); - + // Clear the buffer. + ctx.clear(); - // Draw the display list. - let render_layer: &RenderLayer = unsafe { - cast::transmute(render_layer_ref) - }; - - render_layer.display_list.draw_into_context(&ctx); - ctx.canvas.draw_target.flush(); + // Draw the display list. + do profile(time::RenderingDrawingCategory, self.profiler_chan.clone()) { + render_layer.display_list.draw_into_context(&ctx); + ctx.canvas.draw_target.flush(); + } + } + + new_buffers.push(buffer); + + x += tile_size; } - // Send back the buffer. - buffer_chan.send(layer_buffer_cell.take()); + y += tile_size; } + } + + let layer_buffer_set = LayerBufferSet { + buffers: new_buffers, }; debug!("renderer: returning surface"); diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index fcdc8cc6b24..0389f7135ce 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -25,8 +25,7 @@ use gfx::display_list::DisplayList; use gfx::font_context::FontContext; use gfx::geometry::Au; use gfx::opts::Opts; -use gfx::render_layers::RenderLayer; -use gfx::render_task::{RenderMsg, RenderChan}; +use gfx::render_task::{RenderMsg, RenderChan, RenderLayer}; use newcss::select::SelectCtx; use newcss::stylesheet::Stylesheet; use newcss::types::OriginAuthor; diff --git a/src/components/util/time.rs b/src/components/util/time.rs index deaec504286..d5312bc58fa 100644 --- a/src/components/util/time.rs +++ b/src/components/util/time.rs @@ -39,7 +39,6 @@ pub enum ProfilerCategory { GfxRegenAvailableFontsCategory, RenderingDrawingCategory, RenderingPrepBuffCategory, - RenderingWaitSubtasksCategory, RenderingCategory, // hackish but helps prevent errors when adding new categories NUM_BUCKETS, @@ -84,7 +83,6 @@ impl ProfilerCategory { vec.push((GfxRegenAvailableFontsCategory, ~[])); vec.push((RenderingDrawingCategory, ~[])); vec.push((RenderingPrepBuffCategory, ~[])); - vec.push((RenderingWaitSubtasksCategory, ~[])); vec.push((RenderingCategory, ~[])); ProfilerCategory::check_order(vec); From 318b2cf745115a114a59ae50ce2498e90a0f0514 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 19 Jun 2013 16:02:33 -0700 Subject: [PATCH 6/8] Add LRU cache and use it for fonts and font groups --- src/components/gfx/font_context.rs | 77 +++++++++++++++------- src/components/util/cache.rs | 100 +++++++++++++++++++++++++++-- 2 files changed, 147 insertions(+), 30 deletions(-) diff --git a/src/components/gfx/font_context.rs b/src/components/gfx/font_context.rs index 310b75944e5..4ac07bed4fd 100644 --- a/src/components/gfx/font_context.rs +++ b/src/components/gfx/font_context.rs @@ -2,11 +2,12 @@ * 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/. */ -use font::{Font, FontDescriptor, FontGroup, FontStyle, SelectorPlatformIdentifier}; +use font::{Font, FontDescriptor, FontGroup, FontHandleMethods, FontStyle, + SelectorPlatformIdentifier}; use font::{SpecifiedFontStyle, UsedFontStyle}; use font_list::FontList; use servo_util::cache::Cache; -use servo_util::cache::MonoCache; +use servo_util::cache::LRUCache; use servo_util::time::ProfilerChan; use platform::font::FontHandle; @@ -35,8 +36,9 @@ pub trait FontContextHandleMethods { #[allow(non_implicitly_copyable_typarams)] pub struct FontContext { - instance_cache: MonoCache, + instance_cache: LRUCache, font_list: Option, // only needed by layout + group_cache: LRUCache, handle: FontContextHandle, backend: BackendType, generic_fonts: HashMap<~str,~str>, @@ -63,10 +65,9 @@ pub impl<'self> FontContext { generic_fonts.insert(~"monospace", ~"Menlo"); FontContext { - // TODO(Rust #3902): remove extraneous type parameters once they are inferred correctly. - instance_cache: - Cache::new::>(10), + instance_cache: LRUCache::new(10), font_list: font_list, + group_cache: LRUCache::new(10), handle: handle, backend: backend, generic_fonts: generic_fonts, @@ -78,15 +79,29 @@ pub impl<'self> FontContext { self.font_list.get_ref() } - fn get_resolved_font_for_style(@mut self, style: &SpecifiedFontStyle) -> @FontGroup { - // TODO(Issue #178, E): implement a cache of FontGroup instances. - self.create_font_group(style) + fn get_resolved_font_for_style(&mut self, style: &SpecifiedFontStyle) -> @FontGroup { + match self.group_cache.find(style) { + Some(fg) => { + debug!("font group cache hit"); + fg + }, + None => { + debug!("font group cache miss"); + let fg = self.create_font_group(style); + self.group_cache.insert(style, fg); + fg + } + } } fn get_font_by_descriptor(&mut self, desc: &FontDescriptor) -> Result<@mut Font, ()> { match self.instance_cache.find(desc) { - Some(f) => Ok(f), + Some(f) => { + debug!("font cache hit"); + Ok(f) + }, None => { + debug!("font cache miss"); let result = self.create_font_instance(desc); match result { Ok(font) => { @@ -108,27 +123,34 @@ pub impl<'self> FontContext { } } - // TODO:(Issue #196): cache font groups on the font context. - priv fn create_font_group(@mut self, style: &SpecifiedFontStyle) -> @FontGroup { + priv fn create_font_group(&mut self, style: &SpecifiedFontStyle) -> @FontGroup { let mut fonts = ~[]; debug!("(create font group) --- starting ---"); - let list = self.get_font_list(); - // TODO(Issue #193): make iteration over 'font-family' more robust. for str::each_split_char(style.families, ',') |family| { let family_name = str::trim(family); let transformed_family_name = self.transform_family(family_name); debug!("(create font group) transformed family is `%s`", transformed_family_name); - let result = list.find_font_in_family(transformed_family_name, style); + let result = match self.font_list { + Some(ref fl) => { + fl.find_font_in_family(transformed_family_name, style) + }, + None => None, + }; + let mut found = false; for result.each |font_entry| { found = true; - // TODO(Issue #203): route this instantion through FontContext's Font instance cache. - let instance = Font::new_from_existing_handle(self, &font_entry.handle, style, self.backend, - self.profiler_chan.clone()); + + let font_id = + SelectorPlatformIdentifier(font_entry.handle.face_identifier()); + let font_desc = FontDescriptor::new(copy *style, font_id); + + let instance = self.get_font_by_descriptor(&font_desc); + do result::iter(&instance) |font: &@mut Font| { fonts.push(*font); } }; @@ -140,13 +162,20 @@ pub impl<'self> FontContext { let last_resort = FontList::get_last_resort_font_families(); for last_resort.each |family| { - let result = list.find_font_in_family(*family,style); + let result = match self.font_list { + Some(ref fl) => { + fl.find_font_in_family(*family, style) + }, + None => None, + }; + for result.each |font_entry| { - let instance = Font::new_from_existing_handle(self, - &font_entry.handle, - style, - self.backend, - self.profiler_chan.clone()); + let font_id = + SelectorPlatformIdentifier(font_entry.handle.face_identifier()); + let font_desc = FontDescriptor::new(copy *style, font_id); + + let instance = self.get_font_by_descriptor(&font_desc); + do result::iter(&instance) |font: &@mut Font| { fonts.push(*font); } diff --git a/src/components/util/cache.rs b/src/components/util/cache.rs index d6c46065ee7..eb2be31afcf 100644 --- a/src/components/util/cache.rs +++ b/src/components/util/cache.rs @@ -3,9 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ pub trait Cache { - fn new(size: uint) -> Self; fn insert(&mut self, key: &K, value: V); - fn find(&self, key: &K) -> Option; + fn find(&mut self, key: &K) -> Option; fn find_or_create(&mut self, key: &K, blk: &fn(&K) -> V) -> V; fn evict_all(&mut self); } @@ -14,16 +13,18 @@ pub struct MonoCache { entry: Option<(K,V)>, } -impl Cache for MonoCache { +pub impl MonoCache { fn new(_size: uint) -> MonoCache { MonoCache { entry: None } } +} +impl Cache for MonoCache { fn insert(&mut self, key: &K, value: V) { self.entry = Some((copy *key, value)); } - fn find(&self, key: &K) -> Option { + fn find(&mut self, key: &K) -> Option { match self.entry { None => None, Some((ref k,v)) => if *k == *key { Some(v) } else { None } @@ -47,8 +48,7 @@ impl Cache for MonoCache { #[test] fn test_monocache() { - // TODO: this is hideous because of Rust Issue #3902 - let cache = cache::new::>(10); + let cache = MonoCache::new(10); let one = @"one"; let two = @"two"; cache.insert(&1, one); @@ -59,3 +59,91 @@ fn test_monocache() { assert!(cache.find(&2).is_some()); assert!(cache.find(&1).is_none()); } + +pub struct LRUCache { + entries: ~[(K, V)], + cache_size: uint, +} + +pub impl LRUCache { + fn new(size: uint) -> LRUCache { + LRUCache { + entries: ~[], + cache_size: size, + } + } + + fn touch(&mut self, pos: uint) -> V { + let (key, val) = copy self.entries[pos]; + if pos != self.cache_size { + self.entries.remove(pos); + self.entries.push((key, val)); + } + val + } +} + +impl Cache for LRUCache { + fn insert(&mut self, key: &K, val: V) { + if self.entries.len() == self.cache_size { + self.entries.remove(0); + } + self.entries.push((copy *key, val)); + } + + fn find(&mut self, key: &K) -> Option { + match self.entries.position(|&(k, _)| k == *key) { + Some(pos) => Some(self.touch(pos)), + None => None, + } + } + + fn find_or_create(&mut self, key: &K, blk: &fn(&K) -> V) -> V { + match self.entries.position(|&(k, _)| k == *key) { + Some(pos) => self.touch(pos), + None => { + let val = blk(key); + self.insert(key, val); + val + } + } + } + + fn evict_all(&mut self) { + self.entries.clear(); + } +} + +#[test] +fn test_lru_cache() { + let one = @"one"; + let two = @"two"; + let three = @"three"; + let four = @"four"; + + // Test normal insertion. + let cache = LRUCache::new(2); // (_, _) (cache is empty) + cache.insert(&1, one); // (1, _) + cache.insert(&2, two); // (1, 2) + cache.insert(&3, three); // (2, 3) + + assert!(cache.find(&1).is_none()); // (2, 3) (no change) + assert!(cache.find(&3).is_some()); // (2, 3) + assert!(cache.find(&2).is_some()); // (3, 2) + + // Test that LRU works (this insertion should replace 3, not 2). + cache.insert(&4, four); // (2, 4) + + assert!(cache.find(&1).is_none()); // (2, 4) (no change) + assert!(cache.find(&2).is_some()); // (4, 2) + assert!(cache.find(&3).is_none()); // (4, 2) (no change) + assert!(cache.find(&4).is_some()); // (2, 4) (no change) + + // Test find_or_create. + do cache.find_or_create(&1) |_| { one } // (4, 1) + + assert!(cache.find(&1).is_some()); // (4, 1) (no change) + assert!(cache.find(&2).is_none()); // (4, 1) (no change) + assert!(cache.find(&3).is_none()); // (4, 1) (no change) + assert!(cache.find(&4).is_some()); // (1, 4) +} From 73ed0c6cbfe22971111d6aa0f9e57889e67a8c60 Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Wed, 19 Jun 2013 19:54:01 -0600 Subject: [PATCH 7/8] Update nss to fix build issues. --- src/support/nss/nss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/support/nss/nss b/src/support/nss/nss index 8ba903a1af2..0824ca28956 160000 --- a/src/support/nss/nss +++ b/src/support/nss/nss @@ -1 +1 @@ -Subproject commit 8ba903a1af20ce461d4f4033ec1092a229bc7482 +Subproject commit 0824ca2895668b6ac1751871d7360bc484afb930 From 2253365735fa93768d83f06b4a799b9f3d61f780 Mon Sep 17 00:00:00 2001 From: Tim Kuehn Date: Wed, 19 Jun 2013 21:02:23 -0700 Subject: [PATCH 8/8] libmsg crate for message interfaces to compositor and engine --- Makefile.in | 22 ++++++++++++++----- configure | 1 + mk/clean.mk | 3 +++ src/components/gfx/gfx.rc | 2 +- src/components/gfx/render_context.rs | 2 +- src/components/gfx/render_task.rs | 3 ++- src/components/main/compositing/mod.rs | 5 +++-- src/components/main/engine.rs | 4 ++-- .../main/platform/common/glut_windowing.rs | 4 ++-- src/components/main/servo.rc | 3 ++- src/components/main/windowing.rs | 3 +-- src/components/{gfx => msg}/compositor.rs | 14 ++++++++++++ .../engine_interface.rs => msg/engine.rs} | 0 src/components/msg/msg.rc | 18 +++++++++++++++ src/components/script/compositor_interface.rs | 21 ------------------ src/components/script/script.rc | 3 +-- src/components/script/script_task.rs | 4 ++-- src/support/azure/rust-azure | 2 +- src/support/skia/skia | 2 +- 19 files changed, 71 insertions(+), 45 deletions(-) rename src/components/{gfx => msg}/compositor.rs (67%) rename src/components/{script/engine_interface.rs => msg/engine.rs} (100%) create mode 100644 src/components/msg/msg.rc delete mode 100644 src/components/script/compositor_interface.rs diff --git a/Makefile.in b/Makefile.in index 90adb878799..b2ad90cb475 100644 --- a/Makefile.in +++ b/Makefile.in @@ -186,28 +186,35 @@ DONE_net = $(B)src/components/net/libnet.dummy DEPS_net = $(CRATE_net) $(SRC_net) $(DONE_SUBMODULES) $(DONE_util) -RFLAGS_gfx = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/net +RFLAGS_msg = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) +SRC_msg = $(call rwildcard,$(S)src/components/msg/,*.rs) +CRATE_msg = $(S)src/components/msg/msg.rc +DONE_msg = $(B)src/components/msg/libmsg.dummy + +DEPS_msg = $(CRATE_msg) $(SRC_msg) $(DONE_SUBMODULES) + +RFLAGS_gfx = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/msg SRC_gfx = $(call rwildcard,$(S)src/components/gfx/,*.rs) CRATE_gfx = $(S)src/components/gfx/gfx.rc DONE_gfx = $(B)src/components/gfx/libgfx.dummy -DEPS_gfx = $(CRATE_gfx) $(SRC_gfx) $(DONE_SUBMODULES) $(DONE_util) $(DONE_net) +DEPS_gfx = $(CRATE_gfx) $(SRC_gfx) $(DONE_SUBMODULES) $(DONE_util) $(DONE_net) $(DONE_msg) -RFLAGS_script = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/gfx +RFLAGS_script = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/gfx -L $(B)src/components/msg WEBIDL_script = $(call rwildcard,$(S)src/components/script/,*.webidl) AUTOGEN_SRC_script = $(patsubst %.webidl, %Binding.rs, $(WEBIDL_script)) SRC_script = $(call rwildcard,$(S)src/components/script/,*.rs) $(AUTOGEN_SRC_script) CRATE_script = $(S)src/components/script/script.rc DONE_script = $(B)src/components/script/libscript.dummy -DEPS_script = $(CRATE_script) $(SRC_script) $(DONE_SUBMODULES) $(DONE_util) $(DONE_net) $(DONE_gfx) +DEPS_script = $(CRATE_script) $(SRC_script) $(DONE_SUBMODULES) $(DONE_util) $(DONE_net) $(DONE_gfx) $(DONE_msg) -RFLAGS_servo = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script +RFLAGS_servo = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script -L $(B)src/components/msg SRC_servo = $(call rwildcard,$(S)src/components/main/,*.rs) CRATE_servo = $(S)src/components/main/servo.rc -DEPS_servo = $(CRATE_servo) $(SRC_servo) $(DONE_SUBMODULES) $(DONE_util) $(DONE_gfx) $(DONE_script) $(DONE_net) +DEPS_servo = $(CRATE_servo) $(SRC_servo) $(DONE_SUBMODULES) $(DONE_util) $(DONE_gfx) $(DONE_script) $(DONE_net) $(DONE_msg) # rules that depend on having correct meta-target vars (DEPS_CLEAN, DEPS_servo, etc) include $(S)mk/check.mk @@ -225,6 +232,9 @@ $(DONE_util): $(DEPS_util) $(DONE_net): $(DEPS_net) $(RUSTC) $(RFLAGS_net) -o $@ $< && touch $@ +$(DONE_msg): $(DEPS_msg) + $(RUSTC) $(RFLAGS_msg) -o $@ $< && touch $@ + $(DONE_gfx): $(DEPS_gfx) $(RUSTC) $(RFLAGS_gfx) -o $@ $< && touch $@ diff --git a/configure b/configure index 8d39cb8788a..4fde268cc26 100755 --- a/configure +++ b/configure @@ -452,6 +452,7 @@ do done make_dir ${CFG_BUILD_DIR}src/components/util +make_dir ${CFG_BUILD_DIR}src/components/msg make_dir ${CFG_BUILD_DIR}src/components/net make_dir ${CFG_BUILD_DIR}src/components/gfx make_dir ${CFG_BUILD_DIR}src/components/script diff --git a/mk/clean.mk b/mk/clean.mk index c08d51e9709..db92a5df392 100644 --- a/mk/clean.mk +++ b/mk/clean.mk @@ -28,6 +28,9 @@ clean-fast: $(DEPS_CLEAN_TARGETS_FAST) clean-servo clean-util: cd $(B)/src/components/util/ && rm -rf libutil*.dylib $(DONE_util) +clean-msg: + cd $(B)/src/components/msg/ && rm -rf libmsg*.dylib $(DONE_msg) + clean-net: cd $(B)/src/components/net/ && rm -rf libnet*.dylib $(DONE_net) diff --git a/src/components/gfx/gfx.rc b/src/components/gfx/gfx.rc index c96e4e4b8da..9d3fd2a20d9 100644 --- a/src/components/gfx/gfx.rc +++ b/src/components/gfx/gfx.rc @@ -15,6 +15,7 @@ extern mod stb_image; extern mod std; extern mod servo_net (name = "net"); extern mod servo_util (name = "util"); +extern mod servo_msg (name = "msg"); // Eventually we would like the shaper to be pluggable, as many operating systems have their own // shapers. For now, however, this is a hard dependency. @@ -39,7 +40,6 @@ priv mod render_context; // Rendering pub mod color; -pub mod compositor; pub mod display_list; pub mod geometry; pub mod render_task; diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs index aef6e85c9ec..8b3c9954f5e 100644 --- a/src/components/gfx/render_context.rs +++ b/src/components/gfx/render_context.rs @@ -2,7 +2,7 @@ * 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/. */ -use compositor::LayerBuffer; +use servo_msg::compositor::LayerBuffer; use font_context::FontContext; use geometry::Au; use opts::Opts; diff --git a/src/components/gfx/render_task.rs b/src/components/gfx/render_task.rs index 07c530bf2e1..a0b54d8dd9e 100644 --- a/src/components/gfx/render_task.rs +++ b/src/components/gfx/render_task.rs @@ -6,8 +6,9 @@ use azure::{AzFloat, AzGLContext}; use azure::azure_hl::{B8G8R8A8, DrawTarget}; -use compositor::{RenderListener, IdleRenderState, RenderingRenderState, LayerBuffer, LayerBufferSet}; use display_list::DisplayList; +use servo_msg::compositor::{RenderListener, IdleRenderState, RenderingRenderState, LayerBuffer}; +use servo_msg::compositor::LayerBufferSet; use font_context::FontContext; use geom::matrix2d::Matrix2D; use geom::point::Point2D; diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs index 7e6a83c373c..5eb82234e0b 100644 --- a/src/components/main/compositing/mod.rs +++ b/src/components/main/compositing/mod.rs @@ -6,9 +6,11 @@ use platform::{Application, Window}; use script::dom::event::{Event, ClickEvent, MouseDownEvent, MouseUpEvent, ResizeEvent}; use script::script_task::{LoadMsg, SendEventMsg}; use script::layout_interface::{LayoutChan, RouteScriptMsg}; -use script::compositor_interface::{ReadyState, ScriptListener}; use windowing::{ApplicationMethods, WindowMethods, WindowMouseEvent, WindowClickEvent}; use windowing::{WindowMouseDownEvent, WindowMouseUpEvent}; +use servo_msg::compositor::{RenderListener, LayerBufferSet, RenderState}; +use servo_msg::compositor::{ReadyState, ScriptListener}; + use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods, current_gl_context}; use azure::azure::AzGLContext; use core::cell::Cell; @@ -18,7 +20,6 @@ use core::util; use geom::matrix::identity; use geom::point::Point2D; use geom::size::Size2D; -use gfx::compositor::{RenderListener, LayerBufferSet, RenderState}; use layers::layers::{ARGB32Format, ContainerLayer, ContainerLayerKind, Format}; use layers::layers::{ImageData, WithDataFn}; use layers::layers::{TextureLayerKind, TextureLayer, TextureManager}; diff --git a/src/components/main/engine.rs b/src/components/main/engine.rs index 1abc00537c4..3da355a08c7 100644 --- a/src/components/main/engine.rs +++ b/src/components/main/engine.rs @@ -10,8 +10,8 @@ use core::comm::Port; use gfx::opts::Opts; use gfx::render_task::RenderChan; use gfx::render_task; -use script::compositor_interface::{ScriptListener, ReadyState}; -use script::engine_interface::{EngineChan, ExitMsg, LoadUrlMsg, Msg}; +use servo_msg::compositor::{ScriptListener, ReadyState}; +use servo_msg::engine::{EngineChan, ExitMsg, LoadUrlMsg, Msg}; use script::layout_interface::LayoutChan; use script::layout_interface; use script::script_task::{ExecuteMsg, LoadMsg, ScriptMsg, ScriptContext, ScriptChan}; diff --git a/src/components/main/platform/common/glut_windowing.rs b/src/components/main/platform/common/glut_windowing.rs index d633bb55056..72487539fb9 100644 --- a/src/components/main/platform/common/glut_windowing.rs +++ b/src/components/main/platform/common/glut_windowing.rs @@ -15,11 +15,11 @@ use alert::{Alert, AlertMethods}; use core::libc::c_int; use geom::point::Point2D; use geom::size::Size2D; -use gfx::compositor::{IdleRenderState, RenderState, RenderingRenderState}; +use servo_msg::compositor::{IdleRenderState, RenderState, RenderingRenderState}; +use servo_msg::compositor::{FinishedLoading, Loading, PerformingLayout, ReadyState}; use glut::glut::{ACTIVE_CTRL, DOUBLE, HAVE_PRECISE_MOUSE_WHEEL, WindowHeight, WindowWidth}; use glut::glut; use glut::machack; -use script::compositor_interface::{FinishedLoading, Loading, PerformingLayout, ReadyState}; static THROBBER: [char, ..8] = [ '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷' ]; diff --git a/src/components/main/servo.rc b/src/components/main/servo.rc index 8357d4136d1..99073d701a6 100755 --- a/src/components/main/servo.rc +++ b/src/components/main/servo.rc @@ -23,6 +23,7 @@ extern mod newcss (name = "css"); extern mod opengles; extern mod script; extern mod servo_net (name = "net"); +extern mod servo_msg (name = "msg"); extern mod servo_util (name = "util"); extern mod sharegl; extern mod stb_image; @@ -35,7 +36,7 @@ extern mod core_text; use compositing::{CompositorChan, CompositorTask}; use engine::Engine; -use script::engine_interface::{ExitMsg, LoadUrlMsg}; +use servo_msg::engine::{ExitMsg, LoadUrlMsg}; use gfx::opts; use servo_net::image_cache_task::ImageCacheTask; diff --git a/src/components/main/windowing.rs b/src/components/main/windowing.rs index 888851cbbf1..56a6cbcb0ab 100644 --- a/src/components/main/windowing.rs +++ b/src/components/main/windowing.rs @@ -6,8 +6,7 @@ use geom::point::Point2D; use geom::size::Size2D; -use gfx::compositor::RenderState; -use script::compositor_interface::ReadyState; +use servo_msg::compositor::{ReadyState, RenderState}; pub enum WindowMouseEvent { WindowClickEvent(uint, Point2D), diff --git a/src/components/gfx/compositor.rs b/src/components/msg/compositor.rs similarity index 67% rename from src/components/gfx/compositor.rs rename to src/components/msg/compositor.rs index 46e09800685..1cd50843449 100644 --- a/src/components/gfx/compositor.rs +++ b/src/components/msg/compositor.rs @@ -40,3 +40,17 @@ pub trait RenderListener { fn set_render_state(&self, render_state: RenderState); } +pub enum ReadyState { + /// Informs the compositor that a page is loading. Used for setting status + Loading, + /// Informs the compositor that a page is performing layout. Used for setting status + PerformingLayout, + /// Informs the compositor that a page is finished loading. Used for setting status + FinishedLoading, +} + +/// The interface used by the script task to tell the compositor to update its ready state, +/// which is used in displaying the appropriate message in the window's title. +pub trait ScriptListener : Clone { + fn set_ready_state(&self, ReadyState); +} diff --git a/src/components/script/engine_interface.rs b/src/components/msg/engine.rs similarity index 100% rename from src/components/script/engine_interface.rs rename to src/components/msg/engine.rs diff --git a/src/components/msg/msg.rc b/src/components/msg/msg.rc new file mode 100644 index 00000000000..12dac1c1d4c --- /dev/null +++ b/src/components/msg/msg.rc @@ -0,0 +1,18 @@ +/* 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/. */ + +#[link(name = "msg", + vers = "0.1", + uuid = "4c6054e4-2a7b-4fae-b0c8-6d04416b2bf2", + url = "http://servo.org/")]; +#[crate_type = "lib"]; + + +extern mod azure; +extern mod core; +extern mod geom; +extern mod std; + +pub mod compositor; +pub mod engine; diff --git a/src/components/script/compositor_interface.rs b/src/components/script/compositor_interface.rs deleted file mode 100644 index b0041e49298..00000000000 --- a/src/components/script/compositor_interface.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* 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/. */ - -//! The high-level interface from script to compositor. Using this abstract interface helps reduce -/// coupling between these two components - -pub enum ReadyState { - /// Informs the compositor that a page is loading. Used for setting status - Loading, - /// Informs the compositor that a page is performing layout. Used for setting status - PerformingLayout, - /// Informs the compositor that a page is finished loading. Used for setting status - FinishedLoading, -} - -/// The interface used by the script task to tell the compositor to update its ready state, -/// which is used in displaying the appropriate message in the window's title. -pub trait ScriptListener : Clone { - fn set_ready_state(&self, ReadyState); -} diff --git a/src/components/script/script.rc b/src/components/script/script.rc index 2d608e4d25b..4b90ee1f0b2 100644 --- a/src/components/script/script.rc +++ b/src/components/script/script.rc @@ -19,6 +19,7 @@ extern mod netsurfcss; extern mod newcss (name = "css"); extern mod servo_net (name = "net"); extern mod servo_util (name = "util"); +extern mod servo_msg (name = "msg"); extern mod std; pub mod dom { @@ -64,8 +65,6 @@ pub mod html { pub mod hubbub_html_parser; } -pub mod compositor_interface; -pub mod engine_interface; pub mod layout_interface; pub mod script_task; diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 6eddd9d6335..ec655dc2984 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -5,7 +5,7 @@ /// The script task is the task that owns the DOM in memory, runs JavaScript, and spawns parsing /// and layout tasks. -use compositor_interface::{ReadyState, Loading, PerformingLayout, FinishedLoading}; +use servo_msg::compositor::{ReadyState, Loading, PerformingLayout, FinishedLoading}; use dom::bindings::utils::GlobalStaticData; use dom::document::Document; use dom::element::Element; @@ -17,7 +17,7 @@ use layout_interface::{HitTestResponse, LayoutQuery, LayoutResponse, LayoutChan} use layout_interface::{MatchSelectorsDocumentDamage, QueryMsg, Reflow, ReflowDocumentDamage}; use layout_interface::{ReflowForDisplay, ReflowForScriptQuery, ReflowGoal, ReflowMsg}; use layout_interface; -use engine_interface::{EngineChan, LoadUrlMsg}; +use servo_msg::engine::{EngineChan, LoadUrlMsg}; use core::cast::transmute; use core::cell::Cell; diff --git a/src/support/azure/rust-azure b/src/support/azure/rust-azure index b754fd3d16f..cf5641f5b0b 160000 --- a/src/support/azure/rust-azure +++ b/src/support/azure/rust-azure @@ -1 +1 @@ -Subproject commit b754fd3d16f6acc80ae2252a310f8c71070366c3 +Subproject commit cf5641f5b0b7720e3841518ab7fbfafb4d2443a4 diff --git a/src/support/skia/skia b/src/support/skia/skia index 5c00e2b7f47..3f41e98925b 160000 --- a/src/support/skia/skia +++ b/src/support/skia/skia @@ -1 +1 @@ -Subproject commit 5c00e2b7f471e70a892aeae36b4c77b78227823f +Subproject commit 3f41e98925b9d4c0d4074046388e73f0e0032ab9