mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
layout: Port border-image
support for legacy layout (#32874)
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
29a4cca42d
commit
e23dc0bf6f
48 changed files with 295 additions and 338 deletions
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -1303,7 +1303,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "derive_common"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
|
@ -1471,7 +1471,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "dom"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
@ -4090,7 +4090,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "malloc_size_of"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"accountable-refcell",
|
||||
"app_units",
|
||||
|
@ -5761,7 +5761,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "selectors"
|
||||
version = "0.24.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"cssparser",
|
||||
|
@ -6050,7 +6050,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "servo_arc"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"stable_deref_trait",
|
||||
|
@ -6059,7 +6059,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "servo_atoms"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"string_cache",
|
||||
"string_cache_codegen",
|
||||
|
@ -6259,7 +6259,7 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
|||
[[package]]
|
||||
name = "size_of_test"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
@ -6400,7 +6400,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|||
[[package]]
|
||||
name = "static_prefs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
|
||||
[[package]]
|
||||
name = "strck"
|
||||
|
@ -6453,7 +6453,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "style"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"app_units",
|
||||
"arrayvec",
|
||||
|
@ -6512,7 +6512,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "style_config"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
@ -6520,7 +6520,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "style_derive"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"derive_common",
|
||||
|
@ -6551,7 +6551,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "style_traits"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"app_units",
|
||||
"bitflags 2.6.0",
|
||||
|
@ -6921,7 +6921,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "to_shmem"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"cssparser",
|
||||
"servo_arc",
|
||||
|
@ -6934,7 +6934,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "to_shmem_derive"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#eceb838e855e3b73a28df602b69494899f6d168b"
|
||||
source = "git+https://github.com/servo/stylo?branch=2024-07-16#ed09e046c8cc7654eb3a0c2e3ec789503f64ed74"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"derive_common",
|
||||
|
|
|
@ -8,7 +8,8 @@ use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode;
|
|||
use style::computed_values::text_decoration_style::T as ComputedTextDecorationStyle;
|
||||
use style::computed_values::transform_style::T as ComputedTransformStyle;
|
||||
use style::values::computed::Filter as ComputedFilter;
|
||||
use webrender_api::{units, FilterOp, LineStyle, MixBlendMode, Shadow, TransformStyle};
|
||||
use style::values::specified::border::BorderImageRepeatKeyword;
|
||||
use webrender_api::{units, FilterOp, LineStyle, MixBlendMode, RepeatMode, Shadow, TransformStyle};
|
||||
|
||||
use crate::geom::{PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize};
|
||||
|
||||
|
@ -128,3 +129,16 @@ impl ToWebRender for ComputedTextDecorationStyle {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToWebRender for BorderImageRepeatKeyword {
|
||||
type Type = RepeatMode;
|
||||
|
||||
fn to_webrender(&self) -> Self::Type {
|
||||
match *self {
|
||||
BorderImageRepeatKeyword::Stretch => RepeatMode::Stretch,
|
||||
BorderImageRepeatKeyword::Repeat => RepeatMode::Repeat,
|
||||
BorderImageRepeatKeyword::Round => RepeatMode::Round,
|
||||
BorderImageRepeatKeyword::Space => RepeatMode::Space,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use euclid::Size2D;
|
||||
use style::color::mix::ColorInterpolationMethod;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::image::{EndingShape, Gradient, LineDirection};
|
||||
|
@ -11,15 +12,25 @@ use style::values::computed::{
|
|||
use style::values::generics::image::{
|
||||
Circle, ColorStop, Ellipse, GradientFlags, GradientItem, ShapeExtent,
|
||||
};
|
||||
use webrender_api::{self as wr, units};
|
||||
use webrender_api::units::LayoutPixel;
|
||||
use webrender_api::{
|
||||
self as wr, units, ConicGradient as WebRenderConicGradient,
|
||||
Gradient as WebRenderLinearGradient, RadialGradient as WebRenderRadialGradient,
|
||||
};
|
||||
use wr::ColorF;
|
||||
|
||||
pub(super) enum WebRenderGradient {
|
||||
Linear(WebRenderLinearGradient),
|
||||
Radial(WebRenderRadialGradient),
|
||||
Conic(WebRenderConicGradient),
|
||||
}
|
||||
|
||||
pub(super) fn build(
|
||||
style: &ComputedValues,
|
||||
gradient: &Gradient,
|
||||
layer: &super::background::BackgroundLayer,
|
||||
size: Size2D<f32, LayoutPixel>,
|
||||
builder: &mut super::DisplayListBuilder,
|
||||
) {
|
||||
) -> WebRenderGradient {
|
||||
match gradient {
|
||||
Gradient::Linear {
|
||||
ref items,
|
||||
|
@ -33,7 +44,7 @@ pub(super) fn build(
|
|||
direction,
|
||||
color_interpolation_method,
|
||||
*flags,
|
||||
layer,
|
||||
size,
|
||||
builder,
|
||||
),
|
||||
Gradient::Radial {
|
||||
|
@ -50,7 +61,7 @@ pub(super) fn build(
|
|||
position,
|
||||
color_interpolation_method,
|
||||
*flags,
|
||||
layer,
|
||||
size,
|
||||
builder,
|
||||
),
|
||||
Gradient::Conic {
|
||||
|
@ -66,7 +77,7 @@ pub(super) fn build(
|
|||
*color_interpolation_method,
|
||||
items,
|
||||
*flags,
|
||||
layer,
|
||||
size,
|
||||
builder,
|
||||
),
|
||||
}
|
||||
|
@ -79,13 +90,12 @@ pub(super) fn build_linear(
|
|||
line_direction: &LineDirection,
|
||||
_color_interpolation_method: &ColorInterpolationMethod,
|
||||
flags: GradientFlags,
|
||||
layer: &super::background::BackgroundLayer,
|
||||
gradient_box: Size2D<f32, LayoutPixel>,
|
||||
builder: &mut super::DisplayListBuilder,
|
||||
) {
|
||||
) -> WebRenderGradient {
|
||||
use style::values::specified::position::HorizontalPositionKeyword::*;
|
||||
use style::values::specified::position::VerticalPositionKeyword::*;
|
||||
use units::LayoutVector2D as Vec2;
|
||||
let gradient_box = layer.tile_size;
|
||||
|
||||
// A vector of length 1.0 in the direction of the gradient line
|
||||
let direction = match line_direction {
|
||||
|
@ -168,16 +178,12 @@ pub(super) fn build_linear(
|
|||
} else {
|
||||
wr::ExtendMode::Clamp
|
||||
};
|
||||
let linear_gradient = builder
|
||||
.wr()
|
||||
.create_gradient(start_point, end_point, stops, extend_mode);
|
||||
builder.wr().push_gradient(
|
||||
&layer.common,
|
||||
layer.bounds,
|
||||
linear_gradient,
|
||||
layer.tile_size,
|
||||
layer.tile_spacing,
|
||||
)
|
||||
WebRenderGradient::Linear(builder.wr().create_gradient(
|
||||
start_point,
|
||||
end_point,
|
||||
stops,
|
||||
extend_mode,
|
||||
))
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/css-images-3/#radial-gradients>
|
||||
|
@ -189,10 +195,9 @@ pub(super) fn build_radial(
|
|||
center: &Position,
|
||||
_color_interpolation_method: &ColorInterpolationMethod,
|
||||
flags: GradientFlags,
|
||||
layer: &super::background::BackgroundLayer,
|
||||
gradient_box: Size2D<f32, LayoutPixel>,
|
||||
builder: &mut super::DisplayListBuilder,
|
||||
) {
|
||||
let gradient_box = layer.tile_size;
|
||||
) -> WebRenderGradient {
|
||||
let center = units::LayoutPoint::new(
|
||||
center
|
||||
.horizontal
|
||||
|
@ -277,16 +282,12 @@ pub(super) fn build_radial(
|
|||
} else {
|
||||
wr::ExtendMode::Clamp
|
||||
};
|
||||
let radial_gradient = builder
|
||||
.wr()
|
||||
.create_radial_gradient(center, radii, stops, extend_mode);
|
||||
builder.wr().push_radial_gradient(
|
||||
&layer.common,
|
||||
layer.bounds,
|
||||
radial_gradient,
|
||||
layer.tile_size,
|
||||
layer.tile_spacing,
|
||||
)
|
||||
WebRenderGradient::Radial(builder.wr().create_radial_gradient(
|
||||
center,
|
||||
radii,
|
||||
stops,
|
||||
extend_mode,
|
||||
))
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/css-images-4/#conic-gradients>
|
||||
|
@ -298,10 +299,9 @@ fn build_conic(
|
|||
_color_interpolation_method: ColorInterpolationMethod,
|
||||
items: &[GradientItem<Color, AngleOrPercentage>],
|
||||
flags: GradientFlags,
|
||||
layer: &super::background::BackgroundLayer,
|
||||
gradient_box: Size2D<f32, LayoutPixel>,
|
||||
builder: &mut super::DisplayListBuilder<'_>,
|
||||
) {
|
||||
let gradient_box = layer.tile_size;
|
||||
) -> WebRenderGradient {
|
||||
let center = units::LayoutPoint::new(
|
||||
center
|
||||
.horizontal
|
||||
|
@ -319,17 +319,12 @@ fn build_conic(
|
|||
} else {
|
||||
wr::ExtendMode::Clamp
|
||||
};
|
||||
let conic_gradient =
|
||||
builder
|
||||
.wr()
|
||||
.create_conic_gradient(center, angle.radians(), stops, extend_mode);
|
||||
builder.wr().push_conic_gradient(
|
||||
&layer.common,
|
||||
layer.bounds,
|
||||
conic_gradient,
|
||||
layer.tile_size,
|
||||
layer.tile_spacing,
|
||||
)
|
||||
WebRenderGradient::Conic(builder.wr().create_conic_gradient(
|
||||
center,
|
||||
angle.radians(),
|
||||
stops,
|
||||
extend_mode,
|
||||
))
|
||||
}
|
||||
|
||||
fn conic_gradient_items_to_color_stops(
|
||||
|
|
|
@ -9,21 +9,34 @@ use app_units::Au;
|
|||
use base::id::BrowsingContextId;
|
||||
use base::WebRenderEpochToU16;
|
||||
use embedder_traits::Cursor;
|
||||
use euclid::{Point2D, SideOffsets2D, Size2D};
|
||||
use euclid::{Point2D, SideOffsets2D, Size2D, UnknownUnit};
|
||||
use fnv::FnvHashMap;
|
||||
use fonts::GlyphStore;
|
||||
use gradient::WebRenderGradient;
|
||||
use net_traits::image_cache::UsePlaceholder;
|
||||
use servo_geometry::MaxRect;
|
||||
use style::color::{AbsoluteColor, ColorSpace};
|
||||
use style::computed_values::border_image_outset::T as BorderImageOutset;
|
||||
use style::computed_values::text_decoration_style::T as ComputedTextDecorationStyle;
|
||||
use style::dom::OpaqueNode;
|
||||
use style::properties::longhands::visibility::computed_value::T as Visibility;
|
||||
use style::properties::style_structs::Border;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{BorderStyle, Color, Length, LengthPercentage, OutlineStyle};
|
||||
use style::values::computed::image::Image;
|
||||
use style::values::computed::{
|
||||
BorderImageSideWidth, BorderImageWidth, BorderStyle, Color, Length, LengthPercentage,
|
||||
NonNegativeLengthOrNumber, NumberOrPercentage, OutlineStyle,
|
||||
};
|
||||
use style::values::generics::rect::Rect;
|
||||
use style::values::generics::NonNegative;
|
||||
use style::values::specified::text::TextDecorationLine;
|
||||
use style::values::specified::ui::CursorKind;
|
||||
use style_traits::CSSPixel;
|
||||
use webrender_api::{self as wr, units, BoxShadowClipMode, ClipChainId};
|
||||
use style_traits::{CSSPixel, DevicePixel};
|
||||
use webrender_api::units::LayoutPixel;
|
||||
use webrender_api::{
|
||||
self as wr, units, BorderDetails, BoxShadowClipMode, ClipChainId, CommonItemProperties,
|
||||
ImageRendering, NinePatchBorder, NinePatchBorderSource,
|
||||
};
|
||||
use webrender_traits::display_list::{
|
||||
CompositorDisplayListInfo, ScrollSensitivity, ScrollTreeNodeId,
|
||||
};
|
||||
|
@ -740,7 +753,6 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
builder: &mut DisplayListBuilder,
|
||||
painter: &BackgroundPainter,
|
||||
) {
|
||||
use style::values::computed::image::Image;
|
||||
let style = painter.style;
|
||||
let b = style.get_background();
|
||||
// Reverse because the property is top layer first, we want to paint bottom layer first.
|
||||
|
@ -749,10 +761,38 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
Image::None => {},
|
||||
Image::Gradient(ref gradient) => {
|
||||
let intrinsic = IntrinsicSizes::empty();
|
||||
if let Some(layer) =
|
||||
let Some(layer) =
|
||||
&background::layout_layer(self, painter, builder, index, intrinsic)
|
||||
{
|
||||
gradient::build(style, gradient, layer, builder)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
match gradient::build(style, gradient, layer.tile_size, builder) {
|
||||
WebRenderGradient::Linear(linear_gradient) => builder.wr().push_gradient(
|
||||
&layer.common,
|
||||
layer.bounds,
|
||||
linear_gradient,
|
||||
layer.tile_size,
|
||||
layer.tile_spacing,
|
||||
),
|
||||
WebRenderGradient::Radial(radial_gradient) => {
|
||||
builder.wr().push_radial_gradient(
|
||||
&layer.common,
|
||||
layer.bounds,
|
||||
radial_gradient,
|
||||
layer.tile_size,
|
||||
layer.tile_spacing,
|
||||
)
|
||||
},
|
||||
WebRenderGradient::Conic(conic_gradient) => {
|
||||
builder.wr().push_conic_gradient(
|
||||
&layer.common,
|
||||
layer.bounds,
|
||||
conic_gradient,
|
||||
layer.tile_size,
|
||||
layer.tile_spacing,
|
||||
)
|
||||
},
|
||||
}
|
||||
},
|
||||
Image::Url(ref image_url) => {
|
||||
|
@ -857,7 +897,12 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
return;
|
||||
}
|
||||
|
||||
// `border-image` replaces an element's border entirely.
|
||||
let common = builder.common_properties(self.border_rect, &self.fragment.style);
|
||||
if self.build_border_image(builder, &common, border, border_widths) {
|
||||
return;
|
||||
}
|
||||
|
||||
let details = wr::BorderDetails::Normal(wr::NormalBorder {
|
||||
top: self.build_border_side(border.border_top_style, border.border_top_color.clone()),
|
||||
right: self
|
||||
|
@ -876,6 +921,100 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
.push_border(&common, self.border_rect, border_widths, details)
|
||||
}
|
||||
|
||||
/// Add a display item for image borders if necessary.
|
||||
fn build_border_image(
|
||||
&self,
|
||||
builder: &mut DisplayListBuilder,
|
||||
common: &CommonItemProperties,
|
||||
border: &Border,
|
||||
border_widths: SideOffsets2D<f32, LayoutPixel>,
|
||||
) -> bool {
|
||||
let border_style_struct = self.fragment.style.get_border();
|
||||
let border_image_outset =
|
||||
resolve_border_image_outset(border_style_struct.border_image_outset, border_widths);
|
||||
let border_image_area = self.border_rect.to_rect().outer_rect(border_image_outset);
|
||||
let border_image_size = border_image_area.size;
|
||||
let border_image_widths = resolve_border_image_width(
|
||||
&border_style_struct.border_image_width,
|
||||
border_widths,
|
||||
border_image_size,
|
||||
);
|
||||
let border_image_repeat = &border_style_struct.border_image_repeat;
|
||||
let border_image_fill = border_style_struct.border_image_slice.fill;
|
||||
let border_image_slice = &border_style_struct.border_image_slice.offsets;
|
||||
|
||||
let stops = Vec::new();
|
||||
let mut width = border_image_size.width;
|
||||
let mut height = border_image_size.height;
|
||||
let source = match border.border_image_source {
|
||||
Image::Url(ref image_url) => {
|
||||
// FIXME: images won’t always have in intrinsic width or
|
||||
// height when support for SVG is added, or a WebRender
|
||||
// `ImageKey`, for that matter.
|
||||
//
|
||||
// FIXME: It feels like this should take into account the pseudo
|
||||
// element and not just the node.
|
||||
let Some(tag) = self.fragment.base.tag else {
|
||||
return false;
|
||||
};
|
||||
let Some(image_url) = image_url.url() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let Some(image_info) = builder.context.get_webrender_image_for_url(
|
||||
tag.node,
|
||||
image_url.clone().into(),
|
||||
UsePlaceholder::No,
|
||||
) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let Some(key) = image_info.key else {
|
||||
return false;
|
||||
};
|
||||
|
||||
width = image_info.width as f32;
|
||||
height = image_info.height as f32;
|
||||
NinePatchBorderSource::Image(key, ImageRendering::Auto)
|
||||
},
|
||||
Image::Gradient(ref gradient) => {
|
||||
match gradient::build(&self.fragment.style, gradient, border_image_size, builder) {
|
||||
WebRenderGradient::Linear(gradient) => {
|
||||
NinePatchBorderSource::Gradient(gradient)
|
||||
},
|
||||
WebRenderGradient::Radial(gradient) => {
|
||||
NinePatchBorderSource::RadialGradient(gradient)
|
||||
},
|
||||
WebRenderGradient::Conic(gradient) => {
|
||||
NinePatchBorderSource::ConicGradient(gradient)
|
||||
},
|
||||
}
|
||||
},
|
||||
Image::CrossFade(_) | Image::ImageSet(_) | Image::None | Image::PaintWorklet(_) => {
|
||||
return false
|
||||
},
|
||||
};
|
||||
|
||||
let size = euclid::Size2D::new(width as i32, height as i32);
|
||||
let details = BorderDetails::NinePatch(NinePatchBorder {
|
||||
source,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
slice: resolve_border_image_slice(border_image_slice, size),
|
||||
fill: border_image_fill,
|
||||
repeat_horizontal: border_image_repeat.0.to_webrender(),
|
||||
repeat_vertical: border_image_repeat.1.to_webrender(),
|
||||
});
|
||||
builder.wr().push_border(
|
||||
&common,
|
||||
border_image_area.to_box2d(),
|
||||
border_image_widths,
|
||||
details,
|
||||
);
|
||||
builder.wr().push_stops(&stops);
|
||||
true
|
||||
}
|
||||
|
||||
fn build_outline(&mut self, builder: &mut DisplayListBuilder) {
|
||||
let outline = self.fragment.style.get_outline();
|
||||
let width = outline.outline_width.to_f32_px();
|
||||
|
@ -1118,3 +1257,71 @@ fn create_clip_chain(
|
|||
.define_clip_chain(parent_clip_chain_id, [new_clip_id]),
|
||||
)
|
||||
}
|
||||
|
||||
/// Resolve the WebRender border-image outset area from the style values.
|
||||
fn resolve_border_image_outset(
|
||||
outset: BorderImageOutset,
|
||||
border: SideOffsets2D<f32, LayoutPixel>,
|
||||
) -> SideOffsets2D<f32, LayoutPixel> {
|
||||
fn image_outset_for_side(outset: NonNegativeLengthOrNumber, border_width: f32) -> f32 {
|
||||
match outset {
|
||||
NonNegativeLengthOrNumber::Length(length) => length.px(),
|
||||
NonNegativeLengthOrNumber::Number(factor) => border_width * factor.0,
|
||||
}
|
||||
}
|
||||
|
||||
SideOffsets2D::new(
|
||||
image_outset_for_side(outset.0, border.top),
|
||||
image_outset_for_side(outset.1, border.right),
|
||||
image_outset_for_side(outset.2, border.bottom),
|
||||
image_outset_for_side(outset.3, border.left),
|
||||
)
|
||||
}
|
||||
|
||||
/// Resolve the WebRender border-image width from the style values.
|
||||
fn resolve_border_image_width(
|
||||
width: &BorderImageWidth,
|
||||
border: SideOffsets2D<f32, LayoutPixel>,
|
||||
border_area: Size2D<f32, LayoutPixel>,
|
||||
) -> SideOffsets2D<f32, LayoutPixel> {
|
||||
fn image_width_for_side(
|
||||
border_image_width: &BorderImageSideWidth,
|
||||
border_width: f32,
|
||||
total_length: f32,
|
||||
) -> f32 {
|
||||
match border_image_width {
|
||||
BorderImageSideWidth::LengthPercentage(v) => {
|
||||
v.to_used_value(Au::from_f32_px(total_length)).to_f32_px()
|
||||
},
|
||||
BorderImageSideWidth::Number(x) => border_width * x.0,
|
||||
BorderImageSideWidth::Auto => border_width,
|
||||
}
|
||||
}
|
||||
|
||||
SideOffsets2D::new(
|
||||
image_width_for_side(&width.0, border.top, border_area.height),
|
||||
image_width_for_side(&width.1, border.right, border_area.width),
|
||||
image_width_for_side(&width.2, border.bottom, border_area.height),
|
||||
image_width_for_side(&width.3, border.left, border_area.width),
|
||||
)
|
||||
}
|
||||
|
||||
/// Resolve the WebRender border-image slice from the style values.
|
||||
fn resolve_border_image_slice(
|
||||
border_image_slice: &Rect<NonNegative<NumberOrPercentage>>,
|
||||
size: Size2D<i32, UnknownUnit>,
|
||||
) -> SideOffsets2D<i32, DevicePixel> {
|
||||
fn resolve_percentage(value: NonNegative<NumberOrPercentage>, length: i32) -> i32 {
|
||||
match value.0 {
|
||||
NumberOrPercentage::Percentage(p) => (p.0 * length as f32).round() as i32,
|
||||
NumberOrPercentage::Number(n) => n.round() as i32,
|
||||
}
|
||||
}
|
||||
|
||||
SideOffsets2D::new(
|
||||
resolve_percentage(border_image_slice.0, size.height),
|
||||
resolve_percentage(border_image_slice.1, size.width),
|
||||
resolve_percentage(border_image_slice.2, size.height),
|
||||
resolve_percentage(border_image_slice.3, size.width),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-002.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-003.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-004.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-006.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-007.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-012.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-013.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-017.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-018.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-019.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-020.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-calc.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-displayed-with-transparent-border-color.html]
|
||||
expected: FAIL
|
2
tests/wpt/meta/css/css-backgrounds/border-image-image-type-001.htm.ini
vendored
Normal file
2
tests/wpt/meta/css/css-backgrounds/border-image-image-type-001.htm.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[border-image-image-type-001.htm]
|
||||
expected: FAIL
|
2
tests/wpt/meta/css/css-backgrounds/border-image-image-type-002.htm.ini
vendored
Normal file
2
tests/wpt/meta/css/css-backgrounds/border-image-image-type-002.htm.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[border-image-image-type-002.htm]
|
||||
expected: FAIL
|
2
tests/wpt/meta/css/css-backgrounds/border-image-image-type-004.htm.ini
vendored
Normal file
2
tests/wpt/meta/css/css-backgrounds/border-image-image-type-004.htm.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[border-image-image-type-004.htm]
|
||||
expected: FAIL
|
2
tests/wpt/meta/css/css-backgrounds/border-image-image-type-005.htm.ini
vendored
Normal file
2
tests/wpt/meta/css/css-backgrounds/border-image-image-type-005.htm.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[border-image-image-type-005.htm]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-repeat-repeat-001.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-repeat-round-1.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-repeat-round-2.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-repeat-round.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-repeat-space-4-ref-1.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-repeat-space-4.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-repeat-space-5-ref-1.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-repeat-space-6.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-round-and-stretch.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-shorthand-002.htm]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-slice-001.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-slice-002.xht]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-slice-004.htm]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-slice-005.htm]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-slice-006.htm]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-slice-007.htm]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-slice-fill-001.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-slice-fill-002.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[border-image-slice-percentage.html]
|
||||
expected: FAIL
|
|
@ -1,3 +0,0 @@
|
|||
[border-image-slice-shorthand-reset.html]
|
||||
[Check that the border-image shorthand resets border-image-slice to its initial value.]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[css3-border-image-repeat-stretch.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[css3-border-image-source.html]
|
||||
expected: FAIL
|
|
@ -1,90 +0,0 @@
|
|||
[border-image-shorthand.sub.html]
|
||||
[e.style['border-image'\] = "1 2% 3 4% / 5% / 6" should set border-image-slice]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") fill 1 2% 3 4%" should set border-image-outset]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "repeat round" should set border-image-outset]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") 1 2 3 4 fill" should set border-image-width]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") 1 2 3 4 fill" should not set unrelated longhands]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") 1 2 3 4 fill" should set border-image-outset]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 2% 3 4% / 5% / 6" should set border-image-outset]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none" should set border-image-outset]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") fill 1 2% 3 4%" should set border-image-source]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 2% 3 4% / 5% / 6" should not set unrelated longhands]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "repeat round" should set border-image-repeat]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "repeat round" should not set unrelated longhands]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") fill 1 2% 3 4%" should set border-image-repeat]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") fill 1 2% 3 4%" should set border-image-slice]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "repeat round" should set border-image-source]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "repeat round" should set border-image-slice]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 2% 3 4% / 5% / 6" should set border-image-source]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") fill 1 2% 3 4%" should set border-image-width]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 2% 3 4% / 5% / 6" should set border-image-repeat]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 2% 3 4% / 5% / 6" should set border-image-width]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none" should not set unrelated longhands]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") 1 2 3 4 fill" should set border-image-repeat]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none" should set border-image-source]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none" should set border-image-width]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none" should set border-image-repeat]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none" should set border-image-slice]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") 1 2 3 4 fill" should set border-image-source]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") fill 1 2% 3 4%" should not set unrelated longhands]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "repeat round" should set border-image-width]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://web-platform.test/\\") 1 2 3 4 fill" should set border-image-slice]
|
||||
expected: FAIL
|
|
@ -1,90 +0,0 @@
|
|||
[border-image-valid.html]
|
||||
[e.style['border-image'\] = "url(\\"http://www.example.com/\\") 1 2% 3 4% fill / / 1px 2 3px 4" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 2% 3 4% fill / 3 / 1px 2 3px 4" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://www.example.com/\\") 1 2% 3 4%" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none 100% / 1 / 0 space" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none 100% / 1 / 0 stretch" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 / auto / 1px" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "fill 1 2% 3 4% / auto" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 2% 3 4% / 2% / 2" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none repeat round" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none 1 1 1 1" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none 1 / 1 / 0 stretch" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 2% 3 4% / / 2" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "space" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://www.example.com/\\")" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 2% 3 4% / 2%" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://www.example.com/\\") 1 2 3 4 fill / 1 / 0 stretch" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://www.example.com/\\") 1 2% 3 4% fill" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "repeat round" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "none space space" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 / 1px" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 / 1px 2% 3 auto" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 / 1px / 1px" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 2% 3 4% fill / 3" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://www.example.com/\\") fill 1 2% 3 4%" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "url(\\"http://www.example.com/\\") 1 2 3 4 fill" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 2% 3 4% / 1px 2% 3 auto / 2" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "1 / / 1px" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['border-image'\] = "stretch" should set the property value]
|
||||
expected: FAIL
|
2
tests/wpt/meta/css/css-images/image-orientation/image-orientation-border-image.html.ini
vendored
Normal file
2
tests/wpt/meta/css/css-images/image-orientation/image-orientation-border-image.html.ini
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[image-orientation-border-image.html]
|
||||
expected: FAIL
|
|
@ -1,15 +1,3 @@
|
|||
[shorthand-values.html]
|
||||
[The serialization of border: 1px; border-top: 2px; should be canonical.]
|
||||
expected: FAIL
|
||||
|
||||
[The serialization of list-style-type: circle; list-style-position: inside; list-style-image: initial; should be canonical.]
|
||||
expected: FAIL
|
||||
|
||||
[The serialization of border: 1px; border-top-color: red; should be canonical.]
|
||||
expected: FAIL
|
||||
|
||||
[The serialization of border: 1px; border-top: 1px !important; should be canonical.]
|
||||
expected: FAIL
|
||||
|
||||
[The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; border-image: none; should be canonical.]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
[get-computed-style-for-url.html]
|
||||
[getComputedStyle(elem) and elem.style for url() borderImage correctly return "none"]
|
||||
expected: FAIL
|
||||
|
||||
[getComputedStyle(elem) for url() borderImage uses the resolved URL and elem.style uses the original URL]
|
||||
expected: FAIL
|
Loading…
Add table
Add a link
Reference in a new issue