Bug 1606771 - Implement border-image-repeat: round in WebRender. r=jrmuizel,kvark

border-image-repeat: Round is equivalent to Repeat with the pattern size adjusted to fill the area with a whole number of repetitions. This is done by adjusting the segment's stretch_size in the shader so that it fits a whole number of times in the segment's size.

Differential Revision: https://phabricator.services.mozilla.com/D59370

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nicolas Silva 2020-01-23 14:24:11 +00:00
parent 7c24851526
commit 725d18b7cb
5 changed files with 64 additions and 40 deletions

View File

@ -112,7 +112,9 @@ void multi_brush_vs(
#define BRUSH_FLAG_SEGMENT_RELATIVE 2
#define BRUSH_FLAG_SEGMENT_REPEAT_X 4
#define BRUSH_FLAG_SEGMENT_REPEAT_Y 8
#define BRUSH_FLAG_TEXEL_RECT 16
#define BRUSH_FLAG_SEGMENT_REPEAT_X_ROUND 16
#define BRUSH_FLAG_SEGMENT_REPEAT_Y_ROUND 32
#define BRUSH_FLAG_TEXEL_RECT 64
#define INVALID_SEGMENT_INDEX 0xffff

View File

@ -103,20 +103,35 @@ void image_brush_vs(
uv0 = res.uv_rect.p0 + segment_data.xy * uv_size;
uv1 = res.uv_rect.p0 + segment_data.zw * uv_size;
#ifdef WR_FEATURE_REPETITION
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) {
stretch_size.x = local_rect.size.y / dy * dx;
}
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) {
stretch_size.y = local_rect.size.x / dx * dy;
}
#endif
} else {
#ifdef WR_FEATURE_REPETITION
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) {
stretch_size.x = dx;
}
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) {
stretch_size.y = dy;
}
#endif
}
#ifdef WR_FEATURE_REPETITION
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X_ROUND) != 0) {
float nx = max(1.0, round(segment_rect.size.x / stretch_size.x));
stretch_size.x = segment_rect.size.x / nx;
}
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y_ROUND) != 0) {
float ny = max(1.0, round(segment_rect.size.y / stretch_size.y));
stretch_size.y = segment_rect.size.y / ny;
}
#endif
}
float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0;

View File

@ -1351,8 +1351,9 @@ impl NinePatchDescriptor {
repeat_horizontal: RepeatMode,
repeat_vertical: RepeatMode
) {
if uv_rect.uv1.x > uv_rect.uv0.x &&
uv_rect.uv1.y > uv_rect.uv0.y {
if uv_rect.uv1.x < uv_rect.uv0.x || uv_rect.uv1.y < uv_rect.uv0.y {
return;
}
// Use segment relative interpolation for all
// instances in this primitive.
@ -1363,9 +1364,14 @@ impl NinePatchDescriptor {
// Enable repeat modes on the segment.
if repeat_horizontal == RepeatMode::Repeat {
brush_flags |= BrushFlags::SEGMENT_REPEAT_X;
} else if repeat_horizontal == RepeatMode::Round {
brush_flags |= BrushFlags::SEGMENT_REPEAT_X | BrushFlags::SEGMENT_REPEAT_X_ROUND;
}
if repeat_vertical == RepeatMode::Repeat {
brush_flags |= BrushFlags::SEGMENT_REPEAT_Y;
} else if repeat_vertical == RepeatMode::Round {
brush_flags |= BrushFlags::SEGMENT_REPEAT_Y | BrushFlags::SEGMENT_REPEAT_Y_ROUND;
}
let segment = BrushSegment::new(
@ -1383,7 +1389,6 @@ impl NinePatchDescriptor {
segments.push(segment);
}
}
// Build the list of image segments
let mut segments = Vec::new();

View File

@ -403,16 +403,20 @@ bitflags! {
#[derive(MallocSizeOf)]
pub struct BrushFlags: u8 {
/// Apply perspective interpolation to UVs
const PERSPECTIVE_INTERPOLATION = 0x1;
const PERSPECTIVE_INTERPOLATION = 1;
/// Do interpolation relative to segment rect,
/// rather than primitive rect.
const SEGMENT_RELATIVE = 0x2;
const SEGMENT_RELATIVE = 2;
/// Repeat UVs horizontally.
const SEGMENT_REPEAT_X = 0x4;
const SEGMENT_REPEAT_X = 4;
/// Repeat UVs vertically.
const SEGMENT_REPEAT_Y = 0x8;
const SEGMENT_REPEAT_Y = 8;
/// Horizontally follow border-image-repeat: round
const SEGMENT_REPEAT_X_ROUND = 16;
/// Vorizontally follow border-image-repeat: round
const SEGMENT_REPEAT_Y_ROUND = 32;
/// The extra segment data is a texel rect.
const SEGMENT_TEXEL_RECT = 0x10;
const SEGMENT_TEXEL_RECT = 64;
}
}

View File

@ -715,9 +715,7 @@ ImgDrawResult nsCSSRendering::CreateWebRenderCommandsForBorderWithStyleBorder(
return ImgDrawResult::NOT_SUPPORTED;
}
if (aStyleBorder.mBorderImageRepeatH == StyleBorderImageRepeat::Round ||
aStyleBorder.mBorderImageRepeatH == StyleBorderImageRepeat::Space ||
aStyleBorder.mBorderImageRepeatV == StyleBorderImageRepeat::Round ||
if (aStyleBorder.mBorderImageRepeatH == StyleBorderImageRepeat::Space ||
aStyleBorder.mBorderImageRepeatV == StyleBorderImageRepeat::Space) {
return ImgDrawResult::NOT_SUPPORTED;
}