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

Make border image API more general #2724

Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -7,12 +7,12 @@ use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter, Cli
use api::{ClipId, ColorF, ComplexClipRegion, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use api::{DevicePixelScale, DeviceUintRect, DisplayItemRef, Epoch, ExtendMode, ExternalScrollId};
use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, GlyphRasterSpace, GradientStop};
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayoutPoint, LayoutPrimitiveInfo};
use api::{LayoutRect, LayoutVector2D, LayoutSize, LayoutTransform};
use api::{LineOrientation, LineStyle, LocalClip, PipelineId, PropertyBinding};
use api::{RepeatMode, ScrollFrameDisplayItem, ScrollPolicy, ScrollSensitivity, Shadow};
use api::{SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect, TileOffset};
use api::{TransformStyle, YuvColorSpace, YuvData};
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayoutPoint};
use api::{LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
use api::{LineOrientation, LineStyle, LocalClip, NinePatchBorderSource, PipelineId};
use api::{PropertyBinding, RepeatMode, ScrollFrameDisplayItem, ScrollPolicy, ScrollSensitivity};
use api::{Shadow, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
use api::{TileOffset, TransformStyle, YuvColorSpace, YuvData};
use app_units::Au;
use clip::{ClipRegion, ClipSource, ClipSources, ClipStore};
use clip_scroll_node::{ClipScrollNode, NodeType, StickyFrameInfo};
@@ -1637,7 +1637,7 @@ impl<'a> DisplayListFlattener<'a> {
};

match border_item.details {
BorderDetails::Image(ref border) => {
BorderDetails::NinePatch(ref border) => {
// Calculate the modified rect as specific by border-image-outset
let origin = LayoutPoint::new(
rect.origin.x - border.outset.left,
@@ -1651,14 +1651,14 @@ impl<'a> DisplayListFlattener<'a> {

// Calculate the local texel coords of the slices.
let px0 = 0.0;
let px1 = border.patch.slice.left as f32;
let px2 = border.patch.width as f32 - border.patch.slice.right as f32;
let px3 = border.patch.width as f32;
let px1 = border.slice.left as f32;
let px2 = border.width as f32 - border.slice.right as f32;
let px3 = border.width as f32;

let py0 = 0.0;
let py1 = border.patch.slice.top as f32;
let py2 = border.patch.height as f32 - border.patch.slice.bottom as f32;
let py3 = border.patch.height as f32;
let py1 = border.slice.top as f32;
let py2 = border.height as f32 - border.slice.bottom as f32;
let py3 = border.height as f32;

let tl_outer = LayoutPoint::new(rect.origin.x, rect.origin.y);
let tl_inner = tl_outer + vec2(border_item.widths.left, border_item.widths.top);
@@ -1802,25 +1802,22 @@ impl<'a> DisplayListFlattener<'a> {
clip_mask_kind: BrushClipMaskKind::Unknown,
};

let prim = BrushPrimitive::new(
BrushKind::Border {
request: ImageRequest {
key: border.image_key,
rendering: ImageRendering::Auto,
tile: None,
},
},
Some(descriptor),
);

let prim = PrimitiveContainer::Brush(prim);
let prim = PrimitiveContainer::Brush(match border.source {
NinePatchBorderSource::Image(image_key) => {
BrushPrimitive::new(
BrushKind::Border {
request: ImageRequest {
key: image_key,
rendering: ImageRendering::Auto,
tile: None,
},
},
Some(descriptor),
)
}
});

self.add_primitive(
clip_and_scroll,
info,
Vec::new(),
prim,
);
self.add_primitive(clip_and_scroll, info, Vec::new(), prim);
}
BorderDetails::Normal(ref border) => {
self.add_normal_border(info, border, &border_item.widths, clip_and_scroll);
@@ -268,42 +268,67 @@ pub enum RepeatMode {
Space,
}

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

#[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 struct RadialGradientBorder {
pub gradient: RadialGradient,
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>,
/// TODO(mrobinson): Currently only images are supported, but we will
/// eventually add support for Gradient and RadialGradient.
pub enum NinePatchBorderSource {
Image(ImageKey),
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct RadialGradientBorder {
pub gradient: RadialGradient,
pub struct NinePatchBorder {
/// Describes what to use as the 9-patch source image. If this is an image,
/// it will be stretched to fill the size given by width x height.
pub source: NinePatchBorderSource,

/// 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.

This comment has been minimized.

@Gankra

Gankra May 3, 2018

Contributor

css... why.......

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,

/// The outset for the border.
/// TODO(mrobinson): This should be removed and handled by the client.
pub outset: SideOffsets2D<f32>,
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum BorderDetails {
Normal(NormalBorder),
Image(ImageBorder),
NinePatch(NinePatchBorder),
Gradient(GradientBorder),
RadialGradient(RadialGradientBorder),
}
@@ -901,17 +901,15 @@ impl YamlFrameReader {
"space" => RepeatMode::Space,
s => panic!("Unknown box border image repeat mode {}", s),
};
Some(BorderDetails::Image(ImageBorder {
image_key,
patch: NinePatchDescriptor {
width: image_width as u32,
height: image_height as u32,
slice: SideOffsets2D::new(slice[0], slice[1], slice[2], slice[3]),
},
Some(BorderDetails::NinePatch(NinePatchBorder {
source: NinePatchBorderSource::Image(image_key),
width: image_width as u32,
height: image_height as u32,
slice: SideOffsets2D::new(slice[0], slice[1], slice[2], slice[3]),
fill,
outset: SideOffsets2D::new(outset[0], outset[1], outset[2], outset[3]),
repeat_horizontal,
repeat_vertical,
outset: SideOffsets2D::new(outset[0], outset[1], outset[2], outset[3]),
}))
}
"gradient" => {
@@ -865,7 +865,7 @@ impl YamlFrameWriter {
yaml_node(&mut v, "radius", radius_node);
}
}
BorderDetails::Image(ref details) => {
BorderDetails::NinePatch(ref details) => {
let widths: Vec<f32> = vec![
item.widths.top,
item.widths.right,
@@ -880,16 +880,22 @@ impl YamlFrameWriter {
];
yaml_node(&mut v, "width", f32_vec_yaml(&widths, true));
str_node(&mut v, "border-type", "image");
if let Some(path) = self.path_for_image(details.image_key) {
path_node(&mut v, "image", &path);

match details.source {
NinePatchBorderSource::Image(image_key) => {
if let Some(path) = self.path_for_image(image_key) {
path_node(&mut v, "image", &path);
}
}
}
u32_node(&mut v, "image-width", details.patch.width);
u32_node(&mut v, "image-height", details.patch.height);

u32_node(&mut v, "image-width", details.width);
u32_node(&mut v, "image-height", details.height);
let slice: Vec<u32> = vec![
details.patch.slice.top,
details.patch.slice.right,
details.patch.slice.bottom,
details.patch.slice.left,
details.slice.top,
details.slice.right,
details.slice.bottom,
details.slice.left,
];
yaml_node(&mut v, "slice", u32_vec_yaml(&slice, true));
yaml_node(&mut v, "outset", f32_vec_yaml(&outset, true));
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.