Auto merge of #20739 - pyfisch:border-image-outset, r=mbrubeck

Implement border-image-outset

Add an automatic test for border-image-outset with a gradient.
Convert two tests from UTF-8 LE with CRLF line endings to
UTF-8 with LF endings as the old files could not be viewed with servo.

Closes #16638

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20739)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-05-02 18:47:15 -04:00 committed by GitHub
commit eda59780e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 119 additions and 19 deletions

View file

@ -19,9 +19,11 @@ use model::{self, MaybeAuto};
use style::computed_values::background_attachment::single_value::T as BackgroundAttachment;
use style::computed_values::background_clip::single_value::T as BackgroundClip;
use style::computed_values::background_origin::single_value::T as BackgroundOrigin;
use style::computed_values::border_image_outset::T as BorderImageOutset;
use style::properties::style_structs::{self, Background};
use style::values::Either;
use style::values::computed::{Angle, GradientItem};
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
use style::values::computed::{LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
use style::values::computed::{NumberOrPercentage, Percentage, Position};
use style::values::computed::image::{EndingShape, LineDirection};
use style::values::generics::background::BackgroundSize;
@ -784,6 +786,7 @@ pub fn calculate_inner_border_radii(
pub fn build_image_border_details(
webrender_image: WebRenderImageInfo,
border_style_struct: &style_structs::Border,
outset: SideOffsets2D<f32>,
) -> Option<BorderDetails> {
let corners = &border_style_struct.border_image_slice.offsets;
let border_image_repeat = &border_style_struct.border_image_repeat;
@ -801,8 +804,7 @@ pub fn build_image_border_details(
),
},
fill: border_style_struct.border_image_slice.fill,
// TODO(gw): Support border-image-outset
outset: SideOffsets2D::zero(),
outset: outset,
repeat_horizontal: border_image_repeat.0.to_layout(),
repeat_vertical: border_image_repeat.1.to_layout(),
}))
@ -810,3 +812,25 @@ pub fn build_image_border_details(
None
}
}
fn calculate_border_image_outset_side(
outset: LengthOrNumber,
border_width: Au,
) -> Au {
match outset {
Either::First(length) => length.into(),
Either::Second(factor) => border_width.scale_by(factor),
}
}
pub fn calculate_border_image_outset(
outset: BorderImageOutset,
border: SideOffsets2D<Au>,
) -> SideOffsets2D<Au> {
SideOffsets2D::new(
calculate_border_image_outset_side(outset.0, border.top),
calculate_border_image_outset_side(outset.1, border.right),
calculate_border_image_outset_side(outset.2, border.bottom),
calculate_border_image_outset_side(outset.3, border.left),
)
}

View file

@ -16,9 +16,9 @@ use canvas_traits::canvas::{CanvasMsg, FromLayoutMsg};
use context::LayoutContext;
use display_list::ToLayout;
use display_list::background::{build_border_radius, build_image_border_details};
use display_list::background::{calculate_inner_border_radii, compute_background_placement};
use display_list::background::{convert_linear_gradient, convert_radial_gradient};
use display_list::background::{get_cyclic, simple_normal_border};
use display_list::background::{calculate_border_image_outset, calculate_inner_border_radii};
use display_list::background::{compute_background_placement, convert_linear_gradient};
use display_list::background::{convert_radial_gradient, get_cyclic, simple_normal_border};
use display_list::items::{BaseDisplayItem, BorderDetails, BorderDisplayItem, BLUR_INFLATION_FACTOR};
use display_list::items::{BoxShadowDisplayItem, ClipScrollNode};
use display_list::items::{ClipScrollNodeIndex, ClipScrollNodeType, ClippingAndScrolling};
@ -1264,6 +1264,18 @@ impl FragmentDisplayListBuilding for Fragment {
);
let border_radius = build_border_radius(&bounds, border_style_struct);
let border_widths = border.to_physical(style.writing_mode);
let outset = calculate_border_image_outset(
border_style_struct.border_image_outset,
border_widths
);
let outset_layout = SideOffsets2D::new(
outset.top.to_f32_px(),
outset.right.to_f32_px(),
outset.bottom.to_f32_px(),
outset.left.to_f32_px(),
);
let size = bounds.outer_rect(outset).size;
let details = match border_style_struct.border_image_source {
Either::First(_) => Some(BorderDetails::Normal(NormalBorder {
@ -1295,8 +1307,7 @@ impl FragmentDisplayListBuilding for Fragment {
angle_or_corner,
gradient.repeating,
),
// TODO(gw): Support border-image-outset
outset: SideOffsets2D::zero(),
outset: outset_layout,
})
},
GradientKind::Radial(shape, center, _angle) => {
@ -1308,17 +1319,14 @@ impl FragmentDisplayListBuilding for Fragment {
center,
gradient.repeating,
),
// TODO(gw): Support border-image-outset
outset: SideOffsets2D::zero(),
outset: outset_layout,
})
},
})
},
Either::Second(Image::PaintWorklet(ref paint_worklet)) => {
// TODO: this size should be increased by border-image-outset
let size = self.border_box.size.to_physical(style.writing_mode);
self.get_webrender_image_for_paint_worklet(state, style, paint_worklet, size)
.and_then(|image| build_image_border_details(image, border_style_struct))
.and_then(|image| build_image_border_details(image, border_style_struct, outset_layout))
},
Either::Second(Image::Rect(..)) => {
// TODO: Handle border-image with `-moz-image-rect`.
@ -1337,12 +1345,12 @@ impl FragmentDisplayListBuilding for Fragment {
UsePlaceholder::No,
)
})
.and_then(|image| build_image_border_details(image, border_style_struct)),
.and_then(|image| build_image_border_details(image, border_style_struct, outset_layout)),
};
if let Some(details) = details {
state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem {
base,
border_widths: border.to_physical(style.writing_mode).to_layout(),
border_widths: border_widths.to_layout(),
details,
})));
}