diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 77a64553c29..67979f75766 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -976,12 +976,23 @@ pub struct GradientBorder { pub outset: SideOffsets2D, } +/// A border that is made of radial gradient +#[derive(Clone, HeapSizeOf, Deserialize, Serialize)] +pub struct RadialGradientBorder { + /// The gradient info that this border uses, border-image-source. + pub gradient: RadialGradient, + + /// Outsets for the border, as per border-image-outset. + pub outset: SideOffsets2D, +} + /// Specifies the type of border #[derive(Clone, HeapSizeOf, Deserialize, Serialize)] pub enum BorderDetails { Normal(NormalBorder), Image(ImageBorder), Gradient(GradientBorder), + RadialGradient(RadialGradientBorder), } /// Paints a border. diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index ac3fb646b20..a91a1ce48da 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -1334,8 +1334,24 @@ impl FragmentDisplayListBuilding for Fragment { }), })); } - GradientKind::Radial(_, _) => { - // TODO(#16638): Handle border-image with radial gradient. + GradientKind::Radial(ref shape, ref center) => { + let grad = self.convert_radial_gradient(&bounds, + &gradient.items[..], + shape, + center, + gradient.repeating, + style); + state.add_display_item(DisplayItem::Border(box BorderDisplayItem { + base: base, + border_widths: border.to_physical(style.writing_mode), + details: BorderDetails::RadialGradient( + display_list::RadialGradientBorder { + gradient: grad, + + // TODO(gw): Support border-image-outset + outset: SideOffsets2D::zero(), + }), + })); } } } diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index 70479d43837..d498bc6067f 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -352,15 +352,35 @@ impl WebRenderDisplayItemConverter for DisplayItem { } } BorderDetails::Gradient(ref gradient) => { + let extend_mode = if gradient.gradient.repeating { + ExtendMode::Repeat + } else { + ExtendMode::Clamp + }; webrender_traits::BorderDetails::Gradient(webrender_traits::GradientBorder { gradient: builder.create_gradient( gradient.gradient.start_point.to_pointf(), gradient.gradient.end_point.to_pointf(), gradient.gradient.stops.clone(), - ExtendMode::Clamp), + extend_mode), outset: gradient.outset, }) } + BorderDetails::RadialGradient(ref gradient) => { + let extend_mode = if gradient.gradient.repeating { + ExtendMode::Repeat + } else { + ExtendMode::Clamp + }; + webrender_traits::BorderDetails::RadialGradient(webrender_traits::RadialGradientBorder { + gradient: builder.create_radial_gradient( + gradient.gradient.center.to_pointf(), + gradient.gradient.radius.to_sizef(), + gradient.gradient.stops.clone(), + extend_mode), + outset: gradient.outset, + }) + } }; builder.push_border(rect, clip, widths, details);