зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1496540 - Handle overlapping border corners in webrender r=gw
When some of a border's corners have a border-radius, and that radius is larger than the sum of the border width and element size, then it results in the corners of the border overlapping. Webrender draws borders by rasterizing each segment individually in to the cache, then compositing them together. In this overlapping case, this has 2 problems: a) we composite overlapping segments on top of eachother b) corner segments are not correctly clipped to the curve of the overlapping adjacent corners This patch allows corner segments to be clipped by their adjacent corners. We provide the outer corner position and radii of the adjacent corners to the border shader, which then applies those clips, if required, along with the segment's own corner clip when rasterizing the segment. As the adjacent corners now affect the result of the cached segment, they are added to the cache key. We continue to rasterize the entire segment in to the cache as before, but now modify the local rect and texel rect of the BrushSegment so that it only composites the subportion of the corner segment which does not overlap with the opposite edges of the border. Differential Revision: https://phabricator.services.mozilla.com/D16872 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
b1600d426e
Коммит
74e9823383
|
@ -94,8 +94,15 @@ void brush_vs(
|
|||
|
||||
// If the extra data is a texel rect, modify the UVs.
|
||||
if ((brush_flags & BRUSH_FLAG_TEXEL_RECT) != 0) {
|
||||
uv0 = res.uv_rect.p0 + segment_data.xy;
|
||||
uv1 = res.uv_rect.p0 + segment_data.zw;
|
||||
vec2 uv_size = res.uv_rect.p1 - res.uv_rect.p0;
|
||||
uv0 = res.uv_rect.p0 + segment_data.xy * uv_size;
|
||||
uv1 = res.uv_rect.p0 + segment_data.zw * uv_size;
|
||||
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) {
|
||||
stretch_size.x = stretch_size.x * uv_size.x;
|
||||
}
|
||||
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) {
|
||||
stretch_size.y = stretch_size.y * uv_size.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ void brush_vs(
|
|||
if ((brush_flags & BRUSH_FLAG_SEGMENT_RELATIVE) != 0) {
|
||||
vPos = (vi.local_pos - segment_rect.p0) / segment_rect.size;
|
||||
vPos = vPos * (texel_rect.zw - texel_rect.xy) + texel_rect.xy;
|
||||
vPos = vPos * local_rect.size;
|
||||
} else {
|
||||
vPos = vi.local_pos - local_rect.p0;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ void brush_vs(
|
|||
if ((brush_flags & BRUSH_FLAG_SEGMENT_RELATIVE) != 0) {
|
||||
vPos = (vi.local_pos - segment_rect.p0) / segment_rect.size;
|
||||
vPos = vPos * (texel_rect.zw - texel_rect.xy) + texel_rect.xy;
|
||||
vPos = vPos * local_rect.size;
|
||||
} else {
|
||||
vPos = vi.local_pos - local_rect.p0;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,12 @@ flat varying vec4 vClipCenter_Sign;
|
|||
// corner clipping.
|
||||
flat varying vec4 vClipRadii;
|
||||
|
||||
// Position, scale, and radii of horizontally and vertically adjacent corner clips.
|
||||
flat varying vec4 vHorizontalClipCenter_Sign;
|
||||
flat varying vec2 vHorizontalClipRadii;
|
||||
flat varying vec4 vVerticalClipCenter_Sign;
|
||||
flat varying vec2 vVerticalClipRadii;
|
||||
|
||||
// Local space position
|
||||
varying vec2 vPos;
|
||||
|
||||
|
@ -46,6 +52,8 @@ in vec4 aColor1;
|
|||
in int aFlags;
|
||||
in vec2 aWidths;
|
||||
in vec2 aRadii;
|
||||
in vec4 aHorizontallyAdjacentCorner;
|
||||
in vec4 aVerticallyAdjacentCorner;
|
||||
|
||||
vec2 get_outer_corner_scale(int segment) {
|
||||
vec2 p;
|
||||
|
@ -102,6 +110,18 @@ void main(void) {
|
|||
vClipRadii = vec4(aRadii, max(aRadii - aWidths, 0.0));
|
||||
vColorLine = vec4(outer, aWidths.y * -clip_sign.y, aWidths.x * clip_sign.x);
|
||||
|
||||
vec2 horizontal_clip_sign = vec2(-clip_sign.x, clip_sign.y);
|
||||
vHorizontalClipCenter_Sign = vec4(aHorizontallyAdjacentCorner.xy +
|
||||
horizontal_clip_sign * aHorizontallyAdjacentCorner.zw,
|
||||
horizontal_clip_sign);
|
||||
vHorizontalClipRadii = aHorizontallyAdjacentCorner.zw;
|
||||
|
||||
vec2 vertical_clip_sign = vec2(clip_sign.x, -clip_sign.y);
|
||||
vVerticalClipCenter_Sign = vec4(aVerticallyAdjacentCorner.xy +
|
||||
vertical_clip_sign * aVerticallyAdjacentCorner.zw,
|
||||
vertical_clip_sign);
|
||||
vVerticalClipRadii = aVerticallyAdjacentCorner.zw;
|
||||
|
||||
gl_Position = uTransform * vec4(aTaskOrigin + aRect.xy + vPos, 0.0, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
@ -121,7 +141,7 @@ void main(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// Check if inside corner clip-region
|
||||
// Check if inside main corner clip-region
|
||||
vec2 clip_relative_pos = vPos - vClipCenter_Sign.xy;
|
||||
bool in_clip_region = all(lessThan(vClipCenter_Sign.zw * clip_relative_pos, vec2(0.0)));
|
||||
|
||||
|
@ -132,6 +152,22 @@ void main(void) {
|
|||
d = max(d_radii_a, -d_radii_b);
|
||||
}
|
||||
|
||||
// And again for horizontally-adjacent corner
|
||||
clip_relative_pos = vPos - vHorizontalClipCenter_Sign.xy;
|
||||
in_clip_region = all(lessThan(vHorizontalClipCenter_Sign.zw * clip_relative_pos, vec2(0.0)));
|
||||
if (in_clip_region) {
|
||||
float d_radii = distance_to_ellipse(clip_relative_pos, vHorizontalClipRadii.xy, aa_range);
|
||||
d = max(d_radii, d);
|
||||
}
|
||||
|
||||
// And finally for vertically-adjacent corner
|
||||
clip_relative_pos = vPos - vVerticalClipCenter_Sign.xy;
|
||||
in_clip_region = all(lessThan(vVerticalClipCenter_Sign.zw * clip_relative_pos, vec2(0.0)));
|
||||
if (in_clip_region) {
|
||||
float d_radii = distance_to_ellipse(clip_relative_pos, vVerticalClipRadii.xy, aa_range);
|
||||
d = max(d_radii, d);
|
||||
}
|
||||
|
||||
float alpha = do_aa ? distance_aa(aa_range, d) : 1.0;
|
||||
vec4 color = mix(vColor0, vColor1, mix_factor);
|
||||
oFragColor = color * alpha;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use api::{BorderRadius, BorderSide, BorderStyle, ColorF, ColorU, DeviceRect, DeviceSize};
|
||||
use api::{LayoutSideOffsets, LayoutSizeAu, LayoutPrimitiveInfo, LayoutToDeviceScale};
|
||||
use api::{DeviceVector2D, DevicePoint, LayoutRect, LayoutSize, DeviceIntSize};
|
||||
use api::{AuHelpers, LayoutPoint, RepeatMode, TexelRect, LayoutVector2D};
|
||||
use api::{AuHelpers, LayoutPoint, LayoutPointAu, RepeatMode, TexelRect, LayoutVector2D};
|
||||
use api::NormalBorder as ApiNormalBorder;
|
||||
use ellipse::Ellipse;
|
||||
use euclid::vec2;
|
||||
|
@ -158,6 +158,10 @@ pub struct BorderSegmentCacheKey {
|
|||
pub side1: BorderSideAu,
|
||||
pub segment: BorderSegment,
|
||||
pub do_aa: bool,
|
||||
pub h_adjacent_corner_outer: LayoutPointAu,
|
||||
pub h_adjacent_corner_radius: LayoutSizeAu,
|
||||
pub v_adjacent_corner_outer: LayoutPointAu,
|
||||
pub v_adjacent_corner_radius: LayoutSizeAu,
|
||||
}
|
||||
|
||||
pub fn ensure_no_corner_overlap(
|
||||
|
@ -764,12 +768,22 @@ pub fn create_border_segments(
|
|||
rect.origin.x + local_size_tl.width,
|
||||
rect.origin.y + local_size_tl.height,
|
||||
),
|
||||
LayoutRect::from_floats(
|
||||
rect.origin.x,
|
||||
rect.origin.y,
|
||||
rect.max_x() - widths.right,
|
||||
rect.max_y() - widths.bottom
|
||||
),
|
||||
border.left,
|
||||
border.top,
|
||||
LayoutSize::new(widths.left, widths.top),
|
||||
border.radius.top_left,
|
||||
BorderSegment::TopLeft,
|
||||
EdgeAaSegmentMask::TOP | EdgeAaSegmentMask::LEFT,
|
||||
rect.top_right(),
|
||||
border.radius.top_right,
|
||||
rect.bottom_left(),
|
||||
border.radius.bottom_left,
|
||||
brush_segments,
|
||||
border_segments,
|
||||
border.do_aa,
|
||||
|
@ -781,12 +795,22 @@ pub fn create_border_segments(
|
|||
rect.origin.x + rect.size.width,
|
||||
rect.origin.y + local_size_tr.height,
|
||||
),
|
||||
LayoutRect::from_floats(
|
||||
rect.origin.x + widths.left,
|
||||
rect.origin.y,
|
||||
rect.max_x(),
|
||||
rect.max_y() - widths.bottom,
|
||||
),
|
||||
border.top,
|
||||
border.right,
|
||||
LayoutSize::new(widths.right, widths.top),
|
||||
border.radius.top_right,
|
||||
BorderSegment::TopRight,
|
||||
EdgeAaSegmentMask::TOP | EdgeAaSegmentMask::RIGHT,
|
||||
rect.origin,
|
||||
border.radius.top_left,
|
||||
rect.bottom_right(),
|
||||
border.radius.bottom_right,
|
||||
brush_segments,
|
||||
border_segments,
|
||||
border.do_aa,
|
||||
|
@ -798,12 +822,22 @@ pub fn create_border_segments(
|
|||
rect.origin.x + rect.size.width,
|
||||
rect.origin.y + rect.size.height,
|
||||
),
|
||||
LayoutRect::from_floats(
|
||||
rect.origin.x + widths.left,
|
||||
rect.origin.y + widths.top,
|
||||
rect.max_x(),
|
||||
rect.max_y(),
|
||||
),
|
||||
border.right,
|
||||
border.bottom,
|
||||
LayoutSize::new(widths.right, widths.bottom),
|
||||
border.radius.bottom_right,
|
||||
BorderSegment::BottomRight,
|
||||
EdgeAaSegmentMask::BOTTOM | EdgeAaSegmentMask::RIGHT,
|
||||
rect.bottom_left(),
|
||||
border.radius.bottom_left,
|
||||
rect.top_right(),
|
||||
border.radius.top_right,
|
||||
brush_segments,
|
||||
border_segments,
|
||||
border.do_aa,
|
||||
|
@ -815,12 +849,22 @@ pub fn create_border_segments(
|
|||
rect.origin.x + local_size_bl.width,
|
||||
rect.origin.y + rect.size.height,
|
||||
),
|
||||
LayoutRect::from_floats(
|
||||
rect.origin.x,
|
||||
rect.origin.y + widths.top,
|
||||
rect.max_x() - widths.right,
|
||||
rect.max_y(),
|
||||
),
|
||||
border.bottom,
|
||||
border.left,
|
||||
LayoutSize::new(widths.left, widths.bottom),
|
||||
border.radius.bottom_left,
|
||||
BorderSegment::BottomLeft,
|
||||
EdgeAaSegmentMask::BOTTOM | EdgeAaSegmentMask::LEFT,
|
||||
rect.bottom_right(),
|
||||
border.radius.bottom_right,
|
||||
rect.origin,
|
||||
border.radius.top_left,
|
||||
brush_segments,
|
||||
border_segments,
|
||||
border.do_aa,
|
||||
|
@ -862,6 +906,10 @@ fn add_segment(
|
|||
widths: DeviceSize,
|
||||
radius: DeviceSize,
|
||||
do_aa: bool,
|
||||
h_adjacent_corner_outer: DevicePoint,
|
||||
h_adjacent_corner_radius: DeviceSize,
|
||||
v_adjacent_corner_outer: DevicePoint,
|
||||
v_adjacent_corner_radius: DeviceSize,
|
||||
) {
|
||||
let base_flags = (segment as i32) |
|
||||
((style0 as i32) << 8) |
|
||||
|
@ -916,7 +964,21 @@ fn add_segment(
|
|||
};
|
||||
|
||||
if dashed_or_dotted_corner.is_err() {
|
||||
instances.push(base_instance);
|
||||
let clip_params = [
|
||||
h_adjacent_corner_outer.x,
|
||||
h_adjacent_corner_outer.y,
|
||||
h_adjacent_corner_radius.width,
|
||||
h_adjacent_corner_radius.height,
|
||||
v_adjacent_corner_outer.x,
|
||||
v_adjacent_corner_outer.y,
|
||||
v_adjacent_corner_radius.width,
|
||||
v_adjacent_corner_radius.height,
|
||||
];
|
||||
|
||||
instances.push(BorderInstance {
|
||||
clip_params,
|
||||
..base_instance
|
||||
});
|
||||
}
|
||||
}
|
||||
BorderSegment::Top |
|
||||
|
@ -975,12 +1037,17 @@ fn add_segment(
|
|||
/// border segments for this primitive.
|
||||
fn add_corner_segment(
|
||||
image_rect: LayoutRect,
|
||||
non_overlapping_rect: LayoutRect,
|
||||
side0: BorderSide,
|
||||
side1: BorderSide,
|
||||
widths: LayoutSize,
|
||||
radius: LayoutSize,
|
||||
segment: BorderSegment,
|
||||
edge_flags: EdgeAaSegmentMask,
|
||||
h_adjacent_corner_outer: LayoutPoint,
|
||||
h_adjacent_corner_radius: LayoutSize,
|
||||
v_adjacent_corner_outer: LayoutPoint,
|
||||
v_adjacent_corner_radius: LayoutSize,
|
||||
brush_segments: &mut Vec<BrushSegment>,
|
||||
border_segments: &mut Vec<BorderSegmentInfo>,
|
||||
do_aa: bool,
|
||||
|
@ -997,20 +1064,95 @@ fn add_corner_segment(
|
|||
return;
|
||||
}
|
||||
|
||||
if image_rect.size.width <= 0. || image_rect.size.height <= 0. {
|
||||
let segment_rect = image_rect.intersection(&non_overlapping_rect)
|
||||
.unwrap_or(LayoutRect::zero());
|
||||
|
||||
if segment_rect.size.width <= 0. || segment_rect.size.height <= 0. {
|
||||
return;
|
||||
}
|
||||
|
||||
let texture_rect = segment_rect
|
||||
.translate(&-image_rect.origin.to_vector())
|
||||
.scale(1.0 / image_rect.size.width, 1.0 / image_rect.size.height);
|
||||
|
||||
brush_segments.push(
|
||||
BrushSegment::new(
|
||||
image_rect,
|
||||
segment_rect,
|
||||
/* may_need_clip_mask = */ true,
|
||||
edge_flags,
|
||||
[0.0; 4],
|
||||
BrushFlags::SEGMENT_RELATIVE,
|
||||
[texture_rect.min_x(), texture_rect.min_y(), texture_rect.max_x(), texture_rect.max_y()],
|
||||
BrushFlags::SEGMENT_RELATIVE | BrushFlags::SEGMENT_TEXEL_RECT,
|
||||
)
|
||||
);
|
||||
|
||||
// If the radii of the adjacent corners do not overlap with this segment,
|
||||
// then set the outer position to this segment's corner and the radii to zero.
|
||||
// That way the cache key is unaffected by non-overlapping corners, resulting
|
||||
// in fewer misses.
|
||||
let (h_corner_outer, h_corner_radius) = match segment {
|
||||
BorderSegment::TopLeft => {
|
||||
if h_adjacent_corner_outer.x - h_adjacent_corner_radius.width < image_rect.max_x() {
|
||||
(h_adjacent_corner_outer, h_adjacent_corner_radius)
|
||||
} else {
|
||||
(LayoutPoint::new(image_rect.max_x(), image_rect.min_y()), LayoutSize::zero())
|
||||
}
|
||||
}
|
||||
BorderSegment::TopRight => {
|
||||
if h_adjacent_corner_outer.x + h_adjacent_corner_radius.width > image_rect.min_x() {
|
||||
(h_adjacent_corner_outer, h_adjacent_corner_radius)
|
||||
} else {
|
||||
(LayoutPoint::new(image_rect.min_x(), image_rect.min_y()), LayoutSize::zero())
|
||||
}
|
||||
}
|
||||
BorderSegment::BottomRight => {
|
||||
if h_adjacent_corner_outer.x + h_adjacent_corner_radius.width > image_rect.min_x() {
|
||||
(h_adjacent_corner_outer, h_adjacent_corner_radius)
|
||||
} else {
|
||||
(LayoutPoint::new(image_rect.min_x(), image_rect.max_y()), LayoutSize::zero())
|
||||
}
|
||||
}
|
||||
BorderSegment::BottomLeft => {
|
||||
if h_adjacent_corner_outer.x - h_adjacent_corner_radius.width < image_rect.max_x() {
|
||||
(h_adjacent_corner_outer, h_adjacent_corner_radius)
|
||||
} else {
|
||||
(image_rect.bottom_right(), LayoutSize::zero())
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let (v_corner_outer, v_corner_radius) = match segment {
|
||||
BorderSegment::TopLeft => {
|
||||
if v_adjacent_corner_outer.y - v_adjacent_corner_radius.height < image_rect.max_y() {
|
||||
(v_adjacent_corner_outer, v_adjacent_corner_radius)
|
||||
} else {
|
||||
(LayoutPoint::new(image_rect.min_x(), image_rect.max_y()), LayoutSize::zero())
|
||||
}
|
||||
}
|
||||
BorderSegment::TopRight => {
|
||||
if v_adjacent_corner_outer.y - v_adjacent_corner_radius.height < image_rect.max_y() {
|
||||
(v_adjacent_corner_outer, v_adjacent_corner_radius)
|
||||
} else {
|
||||
(image_rect.bottom_right(), LayoutSize::zero())
|
||||
}
|
||||
}
|
||||
BorderSegment::BottomRight => {
|
||||
if v_adjacent_corner_outer.y + v_adjacent_corner_radius.height > image_rect.min_y() {
|
||||
(v_adjacent_corner_outer, v_adjacent_corner_radius)
|
||||
} else {
|
||||
(LayoutPoint::new(image_rect.max_x(), image_rect.min_y()), LayoutSize::zero())
|
||||
}
|
||||
}
|
||||
BorderSegment::BottomLeft => {
|
||||
if v_adjacent_corner_outer.y + v_adjacent_corner_radius.height > image_rect.min_y() {
|
||||
(v_adjacent_corner_outer, v_adjacent_corner_radius)
|
||||
} else {
|
||||
(LayoutPoint::new(image_rect.min_x(), image_rect.min_y()), LayoutSize::zero())
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
border_segments.push(BorderSegmentInfo {
|
||||
local_task_size: image_rect.size,
|
||||
cache_key: BorderSegmentCacheKey {
|
||||
|
@ -1020,6 +1162,10 @@ fn add_corner_segment(
|
|||
segment,
|
||||
radius: radius.to_au(),
|
||||
size: widths.to_au(),
|
||||
h_adjacent_corner_outer: (h_corner_outer - image_rect.origin).to_point().to_au(),
|
||||
h_adjacent_corner_radius: h_corner_radius.to_au(),
|
||||
v_adjacent_corner_outer: (v_corner_outer - image_rect.origin).to_point().to_au(),
|
||||
v_adjacent_corner_radius: v_corner_radius.to_au(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -1080,6 +1226,10 @@ fn add_edge_segment(
|
|||
radius: LayoutSizeAu::zero(),
|
||||
size: size.to_au(),
|
||||
segment,
|
||||
h_adjacent_corner_outer: LayoutPointAu::zero(),
|
||||
h_adjacent_corner_radius: LayoutSizeAu::zero(),
|
||||
v_adjacent_corner_outer: LayoutPointAu::zero(),
|
||||
v_adjacent_corner_radius: LayoutSizeAu::zero(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -1122,6 +1272,11 @@ pub fn build_border_instances(
|
|||
let widths = (LayoutSize::from_au(cache_key.size) * scale).ceil();
|
||||
let radius = (LayoutSize::from_au(cache_key.radius) * scale).ceil();
|
||||
|
||||
let h_corner_outer = (LayoutPoint::from_au(cache_key.h_adjacent_corner_outer) * scale).round();
|
||||
let h_corner_radius = (LayoutSize::from_au(cache_key.h_adjacent_corner_radius) * scale).ceil();
|
||||
let v_corner_outer = (LayoutPoint::from_au(cache_key.v_adjacent_corner_outer) * scale).round();
|
||||
let v_corner_radius = (LayoutSize::from_au(cache_key.v_adjacent_corner_radius) * scale).ceil();
|
||||
|
||||
add_segment(
|
||||
DeviceRect::new(DevicePoint::zero(), cache_size.to_f32()),
|
||||
style0,
|
||||
|
@ -1133,6 +1288,10 @@ pub fn build_border_instances(
|
|||
widths,
|
||||
radius,
|
||||
border.do_aa,
|
||||
h_corner_outer,
|
||||
h_corner_radius,
|
||||
v_corner_outer,
|
||||
v_corner_radius,
|
||||
);
|
||||
|
||||
instances
|
||||
|
@ -1161,14 +1320,14 @@ impl NinePatchDescriptor {
|
|||
|
||||
// Calculate the local texel coords of the slices.
|
||||
let px0 = 0.0;
|
||||
let px1 = self.slice.left as f32;
|
||||
let px2 = self.width as f32 - self.slice.right as f32;
|
||||
let px3 = self.width as f32;
|
||||
let px1 = self.slice.left as f32 / self.width as f32;
|
||||
let px2 = (self.width as f32 - self.slice.right as f32) / self.width as f32;
|
||||
let px3 = 1.0;
|
||||
|
||||
let py0 = 0.0;
|
||||
let py1 = self.slice.top as f32;
|
||||
let py2 = self.height as f32 - self.slice.bottom as f32;
|
||||
let py3 = self.height as f32;
|
||||
let py1 = self.slice.top as f32 / self.height as f32;
|
||||
let py2 = (self.height as f32 - self.slice.bottom as f32) / self.height as f32;
|
||||
let py3 = 1.0;
|
||||
|
||||
let tl_outer = LayoutPoint::new(rect.origin.x, rect.origin.y);
|
||||
let tl_inner = tl_outer + vec2(self.widths.left, self.widths.top);
|
||||
|
|
|
@ -16,3 +16,6 @@ root:
|
|||
repeat-vertical: stretch
|
||||
repeat-horizontal: stretch
|
||||
fill: true
|
||||
- type: rect
|
||||
bounds: [ 100, 100, 192, 192 ]
|
||||
color: white
|
||||
|
|
|
@ -16,3 +16,6 @@ root:
|
|||
repeat-vertical: stretch
|
||||
repeat-horizontal: stretch
|
||||
fill: true
|
||||
- type: rect
|
||||
bounds: [ 100, 100, 192, 192 ]
|
||||
color: white
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
root:
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 200, 200]
|
||||
items:
|
||||
- type: clip
|
||||
bounds: [ 0, 0, 200, 200 ]
|
||||
complex:
|
||||
- rect: [ 10, 10, 180, 180 ]
|
||||
radius:
|
||||
top-left: [180, 180]
|
||||
top-right: [0, 0]
|
||||
bottom-left: [0, 0]
|
||||
bottom-right: [180, 180]
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [ 0, 0, 200, 200 ]
|
||||
color: [ 0, 0, 255, 0.5 ]
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
root:
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 200, 200]
|
||||
items:
|
||||
- type: border
|
||||
bounds: [ 10, 10, 180, 180 ]
|
||||
width: 90
|
||||
border-type: normal
|
||||
style: solid
|
||||
radius:
|
||||
top-left: 180
|
||||
bottom-right: 180
|
||||
top-right: 0
|
||||
bottom-left: 0
|
||||
color: [ [0, 0, 255, 0.5] ]
|
Двоичные данные
gfx/wr/wrench/reftests/border/border-suite-2.png
Двоичные данные
gfx/wr/wrench/reftests/border/border-suite-2.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 48 KiB После Ширина: | Высота: | Размер: 48 KiB |
|
@ -5,6 +5,7 @@ platform(linux,mac) == border-gradient-nine-patch.yaml border-gradient-nine-patc
|
|||
platform(linux,mac) == border-radial-gradient-nine-patch.yaml border-radial-gradient-nine-patch.png
|
||||
== border-radii.yaml border-radii.png
|
||||
== border-none.yaml border-none-ref.yaml
|
||||
fuzzy(1,68) == border-overlapping.yaml border-overlapping-ref.yaml
|
||||
== border-invisible.yaml border-invisible-ref.yaml
|
||||
platform(linux,mac) == border-suite.yaml border-suite.png
|
||||
platform(linux,mac) fuzzy(8,8) == border-suite-2.yaml border-suite-2.png
|
||||
|
|
Двоичные данные
gfx/wr/wrench/reftests/clip/border-with-rounded-clip.png
Двоичные данные
gfx/wr/wrench/reftests/clip/border-with-rounded-clip.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 1.6 KiB После Ширина: | Высота: | Размер: 1.8 KiB |
|
@ -15,7 +15,7 @@ root:
|
|||
bounds: [10, 10, 100, 200]
|
||||
clip-and-scroll: 2
|
||||
type: border
|
||||
width: [300, 300, 300, 300]
|
||||
width: [100, 50, 100, 50]
|
||||
border-type: normal
|
||||
color: green
|
||||
style: solid
|
||||
|
|
|
@ -29,7 +29,7 @@ fuzzy-if(gtkWidget,0-14,0-280) fuzzy-if(cocoaWidget,0-4,0-582) fuzzy-if(Android,
|
|||
# Corners
|
||||
fuzzy-if(skiaContent,0-17,0-47) fuzzy-if(webrender,30-30,58-58) == corner-1.html corner-1-ref.svg # bottom corners different radius than top corners
|
||||
fuzzy-if(gtkWidget,0-23,0-5) fuzzy-if(winWidget&&!d2d,0-23,0-5) fuzzy-if(d2d,0-32,0-8) fuzzy-if(Android,0-10,0-8) fuzzy-if(skiaContent,0-18,0-49) fuzzy-if(webrender,30-30,57-57) == corner-2.html corner-2-ref.svg # right corners different radius than left corners; see bug 500804
|
||||
fuzzy-if(gtkWidget,0-3,0-10) fuzzy-if(winWidget&&!d2d,0-3,0-10) fuzzy-if(d2d,0-15,0-32) fuzzy-if(Android,0-3,0-15) fuzzy-if(skiaContent,0-18,0-90) fails-if(webrender) == corner-3.html corner-3-ref.svg
|
||||
fuzzy-if(gtkWidget,0-3,0-10) fuzzy-if(winWidget&&!d2d,0-3,0-10) fuzzy-if(d2d,0-15,0-32) fuzzy-if(Android,0-3,0-15) fuzzy-if(skiaContent,0-18,0-90) fuzzy-if(webrender,23-23,105-105) == corner-3.html corner-3-ref.svg
|
||||
fuzzy-if(skiaContent,0-13,0-83) fuzzy-if(webrender,13-13,104-104) == corner-4.html corner-4-ref.svg
|
||||
|
||||
# Test that radii too long are reduced
|
||||
|
|
Загрузка…
Ссылка в новой задаче