Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Are Border Gradients Sufficiently Expressive? #1875

Closed
Gankra opened this issue Oct 13, 2017 · 4 comments
Closed

Are Border Gradients Sufficiently Expressive? #1875

Gankra opened this issue Oct 13, 2017 · 4 comments

Comments

@Gankra
Copy link
Contributor

@Gankra Gankra commented Oct 13, 2017

I'm still taking this all in, but here's a weird case that @mstange believes can't be captured with the arguments we pass to wr:

screen shot 2017-10-13 at 4 03 59 pm

<!DOCTYPE html>
<meta charset="utf-8">
<title>border-image with linear-gradient</title>
<style>

div {
  border: 30px solid;
  box-sizing: border-box;
  width: 200px;
  height: 200px;
  border-image: linear-gradient(45deg, red 50px, yellow 50px, yellow 150px, red 150px) 50;
}

</style>

<div></div>
@Gankra
Copy link
Contributor Author

@Gankra Gankra commented Oct 13, 2017

@mstange
Copy link
Contributor

@mstange mstange commented Oct 13, 2017

In particular I don't think the current API (or at least the part of the API that is exposed through wrench YAML) allows us to specify the intrinsic size of the gradient image.

For correct rendering of border-image gradients, the following pieces of information are necessary:

  • The size of the gradient image
  • The gradient color stops, with their positions as fractions relative to "gradient image" space
  • The slice insets in "gradient image" space
  • The size of the resulting rendering, in local space
  • The slice insets for the result, in local space
  • General border-image features like "should the middle of the 9-piece be filled" and "should I stretch, repeat or round the side parts"
@mstange
Copy link
Contributor

@mstange mstange commented Oct 15, 2017

Here's the relevant part of the API:

#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct NinePatchDescriptor {
    pub width: u32,
    pub height: u32,
    pub slice: SideOffsets2D<u32>,
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ImageBorder {
    pub image_key: ImageKey,
    pub patch: NinePatchDescriptor,
    /// Controls whether the center of the 9 patch image is
    /// rendered or ignored.
    pub fill: bool,
    pub outset: SideOffsets2D<f32>,
    pub repeat_horizontal: RepeatMode,
    pub repeat_vertical: RepeatMode,
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct GradientBorder {
    pub gradient: Gradient,
    pub outset: SideOffsets2D<f32>,
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct RadialGradientBorder {
    pub gradient: RadialGradient,
    pub outset: SideOffsets2D<f32>,
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum BorderDetails {
    Normal(NormalBorder),
    Image(ImageBorder),
    Gradient(GradientBorder),
    RadialGradient(RadialGradientBorder),
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct BorderDisplayItem {
    pub widths: BorderWidths,
    pub details: BorderDetails,
}

So NinePatchDescriptor, which is used by ImageBorder but not by the gradient borders, does have width and height properties that describe the source image size. These values will also be needed for gradient borders. Furthermore, these properties ofImageBorder are needed for the gradient variants as well:

    pub fill: bool,
    pub repeat_horizontal: RepeatMode,
    pub repeat_vertical: RepeatMode,

And I don't believe the outset property is even needed for ImageBorder; it's a layout thing that can be baked into the border rect and the border widths by the caller. So here's what I'd recommend as the new API:

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum NinePartBorderSource {
    Image(ImageKey),
    Gradient(Gradient),
    RadialGradient(RadialGradient),
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct NinePartBorder {
    /// Describes what to use as the 9-part source image. If this is an image,
    /// it will be stretched to fill the size given by width x height. If this
    /// is a type of gradient, the 9-part source image is obtained by rendering
    /// the gradient into a conceptual surface of dimensions width x height.
    pub source: NinePartBorderSource,
    /// The width of the 9-part image.
    pub width: u32,
    /// The height of the 9-part image.
    pub height: u32,
    /// Distances from each edge where the image should be sliced up. These
    /// values are in 9-part-image space (the same space as width and height),
    /// and the resulting image parts will be used to fill the corresponding
    /// parts of the border as given by the border widths. This can lead to
    /// stretching.
    /// Slices can be overlapping. In that case, the same pixels from the
    /// 9-part image will show up in multiple parts of the resulting border.
    pub slice: SideOffsets2D<u32>,
    /// Controls whether the center of the 9 patch image is rendered or
    /// ignored. The center is never rendered if the slices are overlapping.
    pub fill: bool,
    /// Determines what happens if the horizontal side parts of the 9-part
    /// image have a different size than the horizontal parts of the border.
    pub repeat_horizontal: RepeatMode,
    /// Determines what happens if the vertical side parts of the 9-part
    /// image have a different size than the vertical parts of the border.
    pub repeat_vertical: RepeatMode,
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum BorderDetails {
    Normal(NormalBorder),
    NinePart(NinePartBorder),
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct BorderDisplayItem {
    pub widths: BorderWidths,
    pub details: BorderDetails,
}
@glennw
Copy link
Member

@glennw glennw commented Oct 15, 2017

Thanks for doing that detailed write up, sounds good!

mrobinson added a commit to mrobinson/webrender that referenced this issue May 3, 2018
This is a preparatory patch to add support for nine-patch like
functionality to border gradients. The new API is based on mstage's
proposed API from servo#1875.
mrobinson added a commit to mrobinson/webrender that referenced this issue May 3, 2018
This is a preparatory patch to add support for nine-patch like
functionality to border gradients. The new API is based on mstage's
proposed API from servo#1875.
bors-servo added a commit that referenced this issue May 3, 2018
…e-patch-technology, r=Ganko

Make border image API more general

This is a preparatory patch to add support for nine-patch like
functionality to border gradients. The new API is based on mstage's
proposed API from #1875.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/2724)
<!-- Reviewable:end -->
mrobinson added a commit to mrobinson/webrender that referenced this issue Jun 26, 2018
This will allow border-gradients to support the full richness of the CSS
API. There are some areas where the implementation doesn't match what
CSS expects, but this should move us a good deal closer. We can
gradually fix those issues and turn this on in Gecko.

Fixes servo#1875.
mrobinson added a commit to mrobinson/webrender that referenced this issue Jun 27, 2018
This will allow border-gradients to support the full richness of the CSS
API. There are some areas where the implementation doesn't match what
CSS expects, but this should move us a good deal closer. We can
gradually fix those issues and turn this on in Gecko.

Fixes servo#1875.
bors-servo added a commit that referenced this issue Jun 27, 2018
Implement nine patch support for border gradients

This will allow border-gradients to support the full richness of the CSS
API. There are some areas where the implementation doesn't match what
CSS expects, but this should move us a good deal closer. We can
gradually fix those issues and turn this on in Gecko.

Fixes #1875.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/2848)
<!-- Reviewable:end -->
mrobinson added a commit to mrobinson/webrender that referenced this issue Jun 27, 2018
This will allow border-gradients to support the full richness of the CSS
API. There are some areas where the implementation doesn't match what
CSS expects, but this should move us a good deal closer. We can
gradually fix those issues and turn this on in Gecko.

Fixes servo#1875.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

4 participants
You can’t perform that action at this time.