зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1786161
- Support rect() function. r=devtools-reviewers,emilio
Note that rect() computes to the equivalent inset() function as well. i.e. Given `rect(t r b l)`, the equivalent function is `inset(t calc(100% - r) calc(100% - b) l)`. The implementation is straightforward, and we don't have to change anything in cpp because it is always `inset()` when building the gfx::Path. The tests for clip-path will be added in the following patch. Differential Revision: https://phabricator.services.mozilla.com/D183528
This commit is contained in:
Родитель
2161f57ee1
Коммит
a0d6bab413
|
@ -1915,6 +1915,7 @@ exports.CSS_PROPERTIES = {
|
|||
"padding-box",
|
||||
"path",
|
||||
"polygon",
|
||||
"rect",
|
||||
"revert",
|
||||
"revert-layer",
|
||||
"stroke-box",
|
||||
|
@ -5869,6 +5870,7 @@ exports.CSS_PROPERTIES = {
|
|||
"padding-box",
|
||||
"path",
|
||||
"polygon",
|
||||
"rect",
|
||||
"revert",
|
||||
"revert-layer",
|
||||
"stroke-box",
|
||||
|
@ -9360,6 +9362,7 @@ exports.CSS_PROPERTIES = {
|
|||
"path",
|
||||
"polygon",
|
||||
"ray",
|
||||
"rect",
|
||||
"reverse",
|
||||
"revert",
|
||||
"revert-layer",
|
||||
|
@ -9425,6 +9428,7 @@ exports.CSS_PROPERTIES = {
|
|||
"path",
|
||||
"polygon",
|
||||
"ray",
|
||||
"rect",
|
||||
"revert",
|
||||
"revert-layer",
|
||||
"stroke-box",
|
||||
|
@ -11015,6 +11019,7 @@ exports.CSS_PROPERTIES = {
|
|||
"path",
|
||||
"polygon",
|
||||
"radial-gradient",
|
||||
"rect",
|
||||
"repeating-conic-gradient",
|
||||
"repeating-linear-gradient",
|
||||
"repeating-radial-gradient",
|
||||
|
|
|
@ -4,6 +4,7 @@ prefs =
|
|||
dom.animations-api.compositing.enabled=true
|
||||
dom.animations.mainthread-synchronization-with-geometric-animations=true
|
||||
gfx.omta.background-color=true
|
||||
layout.css.basic-shape-rect.enabled=true
|
||||
layout.css.basic-shape-xywh.enabled=true
|
||||
layout.css.individual-transform.enabled=true
|
||||
layout.css.motion-path.enabled=true
|
||||
|
|
|
@ -1260,6 +1260,19 @@ promise_test(async t => {
|
|||
'offset-path:xywh() animation should be running on the compositor');
|
||||
}, 'offset-path:xywh() animation runs on the compositor');
|
||||
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t);
|
||||
const animation = div.animate({ offsetPath: ['rect(0% 0% 10px 10px)',
|
||||
'rect(10% 10% 20px 20px)'] },
|
||||
100 * MS_PER_SEC);
|
||||
|
||||
await waitForAnimationReadyToRestyle(animation);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_running_on_compositor(animation,
|
||||
'offset-path:rect() animation should be running on the compositor');
|
||||
}, 'offset-path:rect() animation runs on the compositor');
|
||||
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t);
|
||||
const animation = div.animate({ offsetDistance: ['0%', '100%'] },
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[DEFAULT]
|
||||
prefs =
|
||||
layout.css.nesting.enabled=true
|
||||
layout.css.basic-shape-rect.enabled=true
|
||||
layout.css.basic-shape-xywh.enabled=true
|
||||
support-files =
|
||||
bug1202095.css
|
||||
|
|
|
@ -207,10 +207,10 @@ function do_test() {
|
|||
ok(testValues(values, expected), "property box-shadow's values");
|
||||
|
||||
// Regression test for bug 1255379.
|
||||
var expected = [ "inherit", "initial", "unset", "revert", "revert-layer", "none", "url",
|
||||
"polygon", "circle", "ellipse", "inset", "path", "xywh",
|
||||
"fill-box", "stroke-box", "view-box", "margin-box",
|
||||
"border-box", "padding-box", "content-box" ];
|
||||
var expected = [ "inherit", "initial", "unset", "revert", "revert-layer",
|
||||
"none", "url", "polygon", "circle", "ellipse", "inset",
|
||||
"path", "rect", "xywh", "fill-box", "stroke-box", "view-box",
|
||||
"margin-box", "border-box", "padding-box", "content-box" ];
|
||||
var values = InspectorUtils.getCSSValuesForProperty("clip-path");
|
||||
ok(testValues(values, expected), "property clip-path's values");
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ prefs =
|
|||
layout.css.scrollbar-gutter.enabled=true
|
||||
layout.css.linear-easing-function.enabled=true
|
||||
layout.css.animation-composition.enabled=true
|
||||
layout.css.basic-shape-rect.enabled=true
|
||||
layout.css.basic-shape-xywh.enabled=true
|
||||
support-files =
|
||||
animation_utils.js
|
||||
|
|
|
@ -1017,15 +1017,26 @@ var basicShapeUnbalancedValues = [
|
|||
"inset(1px 2px 3px 4px round 5px / 6px",
|
||||
];
|
||||
|
||||
var basicShapeXywhValues = [];
|
||||
var basicShapeXywhRectValues = [];
|
||||
if (IsCSSPropertyPrefEnabled("layout.css.basic-shape-xywh.enabled")) {
|
||||
basicShapeXywhValues = [
|
||||
basicShapeXywhRectValues.push(
|
||||
"xywh(1px 2% 3px 4em)",
|
||||
"xywh(1px 2% 3px 4em round 0px)",
|
||||
"xywh(1px 2% 3px 4em round 0px 1%)",
|
||||
"xywh(1px 2% 3px 4em round 0px 1% 2px)",
|
||||
"xywh(1px 2% 3px 4em round 0px 1% 2px 3em)",
|
||||
];
|
||||
"xywh(1px 2% 3px 4em round 0px 1% 2px 3em)"
|
||||
);
|
||||
}
|
||||
|
||||
if (IsCSSPropertyPrefEnabled("layout.css.basic-shape-rect.enabled")) {
|
||||
basicShapeXywhRectValues.push(
|
||||
"rect(auto auto auto auto)",
|
||||
"rect(1px 2% auto 4em)",
|
||||
"rect(1px 2% auto 4em round 0px)",
|
||||
"rect(1px 2% auto 4em round 0px 1%)",
|
||||
"rect(1px 2% auto 4em round 0px 1% 2px)",
|
||||
"rect(1px 2% auto 4em round 0px 1% 2px 3em)"
|
||||
);
|
||||
}
|
||||
|
||||
if (/* mozGradientsEnabled */ true) {
|
||||
|
@ -8727,7 +8738,7 @@ var gCSSProperties = {
|
|||
.concat(basicShapeSVGBoxValues)
|
||||
.concat(basicShapeOtherValues)
|
||||
.concat(basicShapeOtherValuesWithFillRule)
|
||||
.concat(basicShapeXywhValues),
|
||||
.concat(basicShapeXywhRectValues),
|
||||
invalid_values: [
|
||||
"path(nonzero)",
|
||||
"path(abs, 'M 10 10 L 10 10 z')",
|
||||
|
@ -13520,7 +13531,7 @@ if (IsCSSPropertyPrefEnabled("layout.css.motion-path.enabled")) {
|
|||
if (IsCSSPropertyPrefEnabled("layout.css.motion-path-basic-shapes.enabled")) {
|
||||
gCSSProperties["offset-path"]["other_values"].push(
|
||||
...basicShapeOtherValues,
|
||||
...basicShapeXywhValues
|
||||
...basicShapeXywhRectValues
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,9 +57,6 @@ class MOZ_STACK_CLASS CSSClipPathInstance {
|
|||
|
||||
already_AddRefed<Path> CreateClipPathPath(DrawTarget* aDrawTarget);
|
||||
|
||||
already_AddRefed<Path> CreateClipPathXywh(DrawTarget* aDrawTarget,
|
||||
const nsRect& aRefBox);
|
||||
|
||||
/**
|
||||
* The frame for the element that is currently being clipped.
|
||||
*/
|
||||
|
|
|
@ -8315,6 +8315,13 @@
|
|||
value: false
|
||||
mirror: always
|
||||
|
||||
# Is support for rect() enabled?
|
||||
- name: layout.css.basic-shape-rect.enabled
|
||||
type: RelaxedAtomicBool
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
rust: true
|
||||
|
||||
# Is support for xywh() enabled?
|
||||
- name: layout.css.basic-shape-xywh.enabled
|
||||
type: RelaxedAtomicBool
|
||||
|
|
|
@ -83,6 +83,24 @@ where
|
|||
// <first> <second> <third> <fourth>
|
||||
Ok(Self::new(first, second, third, fourth))
|
||||
}
|
||||
|
||||
/// Parses a new `Rect<T>` value which all components must be specified, with the given parse
|
||||
/// function.
|
||||
pub fn parse_all_components_with<'i, 't, Parse>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
parse: Parse,
|
||||
) -> Result<Self, ParseError<'i>>
|
||||
where
|
||||
Parse: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>,
|
||||
{
|
||||
let first = parse(context, input)?;
|
||||
let second = parse(context, input)?;
|
||||
let third = parse(context, input)?;
|
||||
let fourth = parse(context, input)?;
|
||||
// <first> <second> <third> <fourth>
|
||||
Ok(Self::new(first, second, third, fourth))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Parse for Rect<T>
|
||||
|
|
|
@ -15,6 +15,7 @@ use crate::values::generics::basic_shape::{Path, PolygonCoord};
|
|||
use crate::values::generics::rect::Rect;
|
||||
use crate::values::specified::border::BorderRadius;
|
||||
use crate::values::specified::image::Image;
|
||||
use crate::values::specified::length::LengthPercentageOrAuto;
|
||||
use crate::values::specified::position::{Position, PositionOrAuto};
|
||||
use crate::values::specified::url::SpecifiedUrl;
|
||||
use crate::values::specified::{LengthPercentage, NonNegativeLengthPercentage, SVGPathData};
|
||||
|
@ -79,6 +80,26 @@ pub struct Xywh {
|
|||
pub round: BorderRadius,
|
||||
}
|
||||
|
||||
/// Defines a rectangle via insets from the top and left edges of the reference box.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-rect
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToShmem)]
|
||||
#[repr(C)]
|
||||
pub struct ShapeRectFunction {
|
||||
/// The four <length-percentage>s define the position of the top, right, bottom, and left edges
|
||||
/// of a rectangle, respectively, as insets from the top edge of the reference box (for the
|
||||
/// first and third values) or the left edge of the reference box (for the second and fourth
|
||||
/// values).
|
||||
///
|
||||
/// An auto value makes the edge of the box coincide with the corresponding edge of the
|
||||
/// reference box: it’s equivalent to 0% as the first (top) or fourth (left) value, and
|
||||
/// equivalent to 100% as the second (right) or third (bottom) value.
|
||||
pub rect: Rect<LengthPercentageOrAuto>,
|
||||
/// The optional <border-radius> argument(s) define rounded corners for the inset rectangle
|
||||
/// using the border-radius shorthand syntax.
|
||||
pub round: BorderRadius,
|
||||
}
|
||||
|
||||
/// The specified value of <basic-shape-rect>.
|
||||
/// <basic-shape-rect> = <inset()> | <rect()> | <xywh()>
|
||||
///
|
||||
|
@ -90,7 +111,9 @@ pub enum BasicShapeRect {
|
|||
/// Defines a xywh function.
|
||||
#[css(function)]
|
||||
Xywh(Xywh),
|
||||
// TODO: Bug 1786161. Add rect().
|
||||
/// Defines a rect function.
|
||||
#[css(function)]
|
||||
Rect(ShapeRectFunction),
|
||||
}
|
||||
|
||||
/// For filled shapes, we use fill-rule, and store it for path() and polygon().
|
||||
|
@ -149,8 +172,8 @@ bitflags! {
|
|||
const INSET = 1 << 0;
|
||||
/// xywh().
|
||||
const XYWH = 1 << 1;
|
||||
// TODO: Bug 1786161. Add rect().
|
||||
// const RECT = 1 << 2;
|
||||
/// rect().
|
||||
const RECT = 1 << 2;
|
||||
/// circle().
|
||||
const CIRCLE = 1 << 3;
|
||||
/// ellipse().
|
||||
|
@ -166,6 +189,7 @@ bitflags! {
|
|||
const ALL =
|
||||
Self::INSET.bits |
|
||||
Self::XYWH.bits |
|
||||
Self::RECT.bits |
|
||||
Self::CIRCLE.bits |
|
||||
Self::ELLIPSE.bits |
|
||||
Self::POLYGON.bits |
|
||||
|
@ -299,6 +323,22 @@ impl BasicShape {
|
|||
.map(BasicShapeRect::Inset)
|
||||
.map(BasicShape::Rect)
|
||||
},
|
||||
"xywh"
|
||||
if flags.contains(AllowedBasicShapes::XYWH)
|
||||
&& static_prefs::pref!("layout.css.basic-shape-xywh.enabled") =>
|
||||
{
|
||||
Xywh::parse_function_arguments(context, i)
|
||||
.map(BasicShapeRect::Xywh)
|
||||
.map(BasicShape::Rect)
|
||||
},
|
||||
"rect"
|
||||
if flags.contains(AllowedBasicShapes::RECT)
|
||||
&& static_prefs::pref!("layout.css.basic-shape-rect.enabled") =>
|
||||
{
|
||||
ShapeRectFunction::parse_function_arguments(context, i)
|
||||
.map(BasicShapeRect::Rect)
|
||||
.map(BasicShape::Rect)
|
||||
},
|
||||
"circle" if flags.contains(AllowedBasicShapes::CIRCLE) => {
|
||||
Circle::parse_function_arguments(context, i, default_position)
|
||||
.map(BasicShape::Circle)
|
||||
|
@ -314,14 +354,6 @@ impl BasicShape {
|
|||
"path" if flags.contains(AllowedBasicShapes::PATH) => {
|
||||
Path::parse_function_arguments(i, shape_type).map(BasicShape::Path)
|
||||
},
|
||||
"xywh"
|
||||
if flags.contains(AllowedBasicShapes::XYWH)
|
||||
&& static_prefs::pref!("layout.css.basic-shape-xywh.enabled") =>
|
||||
{
|
||||
Xywh::parse_function_arguments(context, i)
|
||||
.map(BasicShapeRect::Xywh)
|
||||
.map(BasicShape::Rect)
|
||||
},
|
||||
_ => Err(location
|
||||
.new_custom_error(StyleParseErrorKind::UnexpectedFunction(function.clone()))),
|
||||
}
|
||||
|
@ -339,6 +371,20 @@ impl Parse for InsetRect {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_round<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<BorderRadius, ParseError<'i>> {
|
||||
if input
|
||||
.try_parse(|i| i.expect_ident_matching("round"))
|
||||
.is_ok()
|
||||
{
|
||||
return BorderRadius::parse(context, input);
|
||||
}
|
||||
|
||||
Ok(BorderRadius::zero())
|
||||
}
|
||||
|
||||
impl InsetRect {
|
||||
/// Parse the inner function arguments of `inset()`
|
||||
fn parse_function_arguments<'i, 't>(
|
||||
|
@ -346,14 +392,7 @@ impl InsetRect {
|
|||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let rect = Rect::parse_with(context, input, LengthPercentage::parse)?;
|
||||
let round = if input
|
||||
.try_parse(|i| i.expect_ident_matching("round"))
|
||||
.is_ok()
|
||||
{
|
||||
BorderRadius::parse(context, input)?
|
||||
} else {
|
||||
BorderRadius::zero()
|
||||
};
|
||||
let round = parse_round(context, input)?;
|
||||
Ok(generic::InsetRect { rect, round })
|
||||
}
|
||||
}
|
||||
|
@ -509,6 +548,17 @@ impl Path {
|
|||
}
|
||||
}
|
||||
|
||||
fn round_to_css<W>(round: &BorderRadius, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
if !round.is_zero() {
|
||||
dest.write_str(" round ")?;
|
||||
round.to_css(dest)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl ToCss for Xywh {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
|
@ -521,16 +571,12 @@ impl ToCss for Xywh {
|
|||
self.width.to_css(dest)?;
|
||||
dest.write_char(' ')?;
|
||||
self.height.to_css(dest)?;
|
||||
if !self.round.is_zero() {
|
||||
dest.write_str(" round ")?;
|
||||
self.round.to_css(dest)?;
|
||||
}
|
||||
Ok(())
|
||||
round_to_css(&self.round, dest)
|
||||
}
|
||||
}
|
||||
|
||||
impl Xywh {
|
||||
/// Parse the inner function arguments of `xywh()`
|
||||
/// Parse the inner function arguments of `xywh()`.
|
||||
fn parse_function_arguments<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
|
@ -539,15 +585,7 @@ impl Xywh {
|
|||
let y = LengthPercentage::parse(context, input)?;
|
||||
let width = NonNegativeLengthPercentage::parse(context, input)?;
|
||||
let height = NonNegativeLengthPercentage::parse(context, input)?;
|
||||
let round = if input
|
||||
.try_parse(|i| i.expect_ident_matching("round"))
|
||||
.is_ok()
|
||||
{
|
||||
BorderRadius::parse(context, input)?
|
||||
} else {
|
||||
BorderRadius::zero()
|
||||
};
|
||||
|
||||
let round = parse_round(context, input)?;
|
||||
Ok(Xywh {
|
||||
x,
|
||||
y,
|
||||
|
@ -558,12 +596,41 @@ impl Xywh {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToCss for ShapeRectFunction {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
self.rect.0.to_css(dest)?;
|
||||
dest.write_char(' ')?;
|
||||
self.rect.1.to_css(dest)?;
|
||||
dest.write_char(' ')?;
|
||||
self.rect.2.to_css(dest)?;
|
||||
dest.write_char(' ')?;
|
||||
self.rect.3.to_css(dest)?;
|
||||
round_to_css(&self.round, dest)
|
||||
}
|
||||
}
|
||||
|
||||
impl ShapeRectFunction {
|
||||
/// Parse the inner function arguments of `rect()`.
|
||||
fn parse_function_arguments<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let rect = Rect::parse_all_components_with(context, input, LengthPercentageOrAuto::parse)?;
|
||||
let round = parse_round(context, input)?;
|
||||
Ok(ShapeRectFunction { rect, round })
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for BasicShapeRect {
|
||||
type ComputedValue = ComputedInsetRect;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
use crate::values::computed::LengthPercentage;
|
||||
use crate::values::computed::LengthPercentageOrAuto;
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
|
||||
match self {
|
||||
|
@ -594,6 +661,42 @@ impl ToComputedValue for BasicShapeRect {
|
|||
round: xywh.round.to_computed_value(context),
|
||||
}
|
||||
},
|
||||
Self::Rect(ref rect) => {
|
||||
// Given `rect(t r b l)`, the equivalent function is
|
||||
// `inset(t calc(100% - r) calc(100% - b) l)`.
|
||||
//
|
||||
// https://drafts.csswg.org/css-shapes-1/#basic-shape-computed-values
|
||||
fn compute_top_or_left(v: LengthPercentageOrAuto) -> LengthPercentage {
|
||||
match v {
|
||||
// it’s equivalent to 0% as the first (top) or fourth (left) value.
|
||||
// https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-rect
|
||||
LengthPercentageOrAuto::Auto => LengthPercentage::zero_percent(),
|
||||
LengthPercentageOrAuto::LengthPercentage(lp) => lp,
|
||||
}
|
||||
}
|
||||
fn compute_bottom_or_right(v: LengthPercentageOrAuto) -> LengthPercentage {
|
||||
match v {
|
||||
// It's equivalent to 100% as the second (right) or third (bottom) value.
|
||||
// So calc(100% - 100%) = 0%.
|
||||
// https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-rect
|
||||
LengthPercentageOrAuto::Auto => LengthPercentage::zero_percent(),
|
||||
LengthPercentageOrAuto::LengthPercentage(lp) => {
|
||||
LengthPercentage::hundred_percent_minus(lp, AllowedNumericType::All)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
let round = rect.round.to_computed_value(context);
|
||||
let rect = rect.rect.to_computed_value(context);
|
||||
let rect = Rect::new(
|
||||
compute_top_or_left(rect.0),
|
||||
compute_bottom_or_right(rect.1),
|
||||
compute_bottom_or_right(rect.2),
|
||||
compute_top_or_left(rect.3),
|
||||
);
|
||||
|
||||
ComputedInsetRect { rect, round }
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
prefs: [layout.css.basic-shape-xywh.enabled:true]
|
||||
prefs: [layout.css.basic-shape-rect.enabled:false, layout.css.basic-shape-xywh.enabled:true]
|
||||
|
|
|
@ -1 +1 @@
|
|||
prefs: [layout.css.motion-path.enabled:true, layout.css.individual-transform.enabled:true, dom.animations-api.core.enabled:true, layout.css.motion-path-ray.enabled:true, layout.css.motion-path-offset-position.enabled:true, layout.css.motion-path-basic-shapes.enabled:true, layout.css.motion-path-coord-box.enabled:true, layout.css.basic-shape-xywh.enabled:true]
|
||||
prefs: [layout.css.motion-path.enabled:true, layout.css.individual-transform.enabled:true, dom.animations-api.core.enabled:true, layout.css.motion-path-ray.enabled:true, layout.css.motion-path-offset-position.enabled:true, layout.css.motion-path-basic-shapes.enabled:true, layout.css.motion-path-coord-box.enabled:true, layout.css.basic-shape-rect.enabled:true, layout.css.basic-shape-xywh.enabled:true]
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
[offset-path-interpolation-006.html]
|
||||
[CSS Transitions: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.5) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.6) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (1) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (1.5) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions with transition: all: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (-0.3) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions with transition: all: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions with transition: all: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.3) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions with transition: all: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.5) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions with transition: all: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.6) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions with transition: all: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (1) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions with transition: all: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (1.5) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (-0.3) should be [none\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0) should be [none\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.3) should be [none\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.5) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.6) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (1) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (1.5) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[Web Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (-0.3) should be [none\]]
|
||||
expected: FAIL
|
||||
|
||||
[Web Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0) should be [none\]]
|
||||
expected: FAIL
|
||||
|
||||
[Web Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.3) should be [none\]]
|
||||
expected: FAIL
|
||||
|
||||
[Web Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.5) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[Web Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.6) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[Web Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (1) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[Web Animations: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (1.5) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (-0.3) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
||||
|
||||
[CSS Transitions: property <offset-path> from [none\] to [rect(10px 10px 10px 10px)\] at (0.3) should be [rect(10px 10px 10px 10px)\]]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[offset-path-shape-rect-001.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[offset-path-shape-rect-002.html]
|
||||
expected: FAIL
|
|
@ -110,6 +110,32 @@
|
|||
{at: 2, expect: 'xywh(15px 15px 50% 50%)'},
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'offset-path',
|
||||
from: 'rect(10px 100px 50% 10%)',
|
||||
to: 'rect(50px 200px 90% 50%)'
|
||||
}, [
|
||||
{at: -1, expect: 'rect(-30px 0px 10% -30%)'},
|
||||
{at: 0, expect: 'rect(10px 100px 50% 10%)'},
|
||||
{at: 0.125, expect: 'rect(15px 112.5px 55% 15%)'},
|
||||
{at: 0.875, expect: 'rect(45px 187.5px 85% 45%)'},
|
||||
{at: 1, expect: 'rect(50px 200px 90% 50%)'},
|
||||
{at: 2, expect: 'rect(90px 300px 130% 90%)'},
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'offset-path',
|
||||
from: 'rect(auto auto auto auto)',
|
||||
to: 'rect(80% 20% 20% 80%)'
|
||||
}, [
|
||||
{at: -1, expect: 'inset(-80%)'},
|
||||
{at: 0, expect: 'inset(0%)'},
|
||||
{at: 0.125, expect: 'inset(10%)'},
|
||||
{at: 0.875, expect: 'inset(70%)'},
|
||||
{at: 1, expect: 'inset(80%)'},
|
||||
{at: 2, expect: 'inset(160%)'},
|
||||
]);
|
||||
|
||||
// All <basic-shape-rect>s compute to the equivalent inset() function, so
|
||||
// they are interpolatable.
|
||||
// https://drafts.csswg.org/css-shapes-1/#basic-shape-computed-values
|
||||
|
@ -129,6 +155,35 @@
|
|||
{at: 2, expect: 'inset(90px calc(-100% + 310px) calc(-100% + 210px) 90px)'},
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'offset-path',
|
||||
from: 'inset(10px)',
|
||||
// inset(50px calc(100% - 70px) 20% 20%).
|
||||
to: 'rect(50px 70px 80% 20%)',
|
||||
}, [
|
||||
{at: -1, expect: 'inset(-30px calc(-100% + 90px) calc(-20% + 20px) calc(-20% + 20px)'},
|
||||
{at: 0, expect: 'inset(10px calc(0% + 10px) calc(0% + 10px))'},
|
||||
{at: 0.125, expect: 'inset(15px 12.5% calc(2.5% + 8.75px) calc(2.5% + 8.75px))'},
|
||||
{at: 0.875, expect: 'inset(45px calc(87.5% - 60px) calc(17.5% + 1.25px) calc(17.5% + 1.25px))'},
|
||||
{at: 1, expect: 'inset(50px calc(100% - 70px) 20% 20%)'},
|
||||
{at: 2, expect: 'inset(90px calc(200% - 150px) calc(40% - 10px) calc(40% - 10px))'},
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'clip-path',
|
||||
// inset(10% calc(100% - 100px) 50% 0px round 20px).
|
||||
from: 'xywh(0px 10% 100px 40% round 20px)',
|
||||
// inset(20% 50% calc(100% - 200px) 20px).
|
||||
to: 'rect(20% 50% 200px 20px)',
|
||||
}, [
|
||||
{at: -1, expect: 'inset(0% calc(150% - 200px) calc(0% + 200px) -20px round 40px'},
|
||||
{at: 0, expect: 'inset(10% calc(100% - 100px) 50% 0px round 20px)'},
|
||||
{at: 0.125, expect: 'inset(11.25% calc(93.75% - 87.5px) calc(56.25% - 25px) 2.5px round 17.5px)'},
|
||||
{at: 0.875, expect: 'inset(18.75% calc(56.25% - 12.5px) calc(93.75% - 175px) 17.5px round 2.5px)'},
|
||||
{at: 1, expect: 'inset(20% 50% calc(100% - 200px) 20px)'},
|
||||
{at: 2, expect: 'inset(30% calc(0% + 100px) calc(150% - 400px) 40px)'},
|
||||
]);
|
||||
|
||||
// No interpolation between different radius keywords.
|
||||
test_no_interpolation({
|
||||
property: 'offset-path',
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#box {
|
||||
background-color: green;
|
||||
transform: translate(420.272px, 317.407px) rotate(161.625deg) translate(40px, 40px);
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Motion Path test: <basic-shape> rect() path with explicit arguments and radius</title>
|
||||
<meta name=fuzzy content="0-96;0-440">
|
||||
<link rel="author" title="Daniil Sakhapov" href="sakhapov@google.com">
|
||||
<link rel="match" href="offset-path-shape-rect-002-ref.html">
|
||||
<link rel="help" href="https://drafts.fxtf.org/motion/#valdef-offset-path-basic-shape">
|
||||
|
@ -19,6 +20,7 @@
|
|||
offset-path: rect(5px 95% 95% 5px round 30%);
|
||||
offset-distance: 45%;
|
||||
offset-anchor: 10% 10%;
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Motion Path test reference: offset-path:rect() path with explicit arguments and padding-box</title>
|
||||
|
||||
<style>
|
||||
#outer {
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
padding: 50px;
|
||||
border: 50px solid black;
|
||||
}
|
||||
#box {
|
||||
background-color: green;
|
||||
transform: translate(200px, -78px) rotate(90deg);
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="outer">
|
||||
<div id="box"></div>
|
||||
</div>
|
|
@ -0,0 +1,31 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Motion Path test: offset-path:rect() path with explicit arguments and padding-box</title>
|
||||
<link rel="match" href="offset-path-shape-rect-003-ref.html">
|
||||
<link rel="help" href="https://drafts.fxtf.org/motion/#valdef-offset-path-basic-shape">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-rect">
|
||||
|
||||
<style>
|
||||
#outer {
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
padding: 50px;
|
||||
border: 50px solid black;
|
||||
}
|
||||
#box {
|
||||
background-color: green;
|
||||
position: relative;
|
||||
offset-path: rect(auto auto 50% 10px) padding-box;
|
||||
offset-distance: 40%;
|
||||
border-radius: 50% 50% 0 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="outer">
|
||||
<div id="box"></div>
|
||||
</div>
|
|
@ -84,6 +84,8 @@ test_computed_value("offset-path", "polygon(1% 2%)");
|
|||
test_computed_value("offset-path", "polygon(1px 2px, 3% 4%)");
|
||||
|
||||
// All <basic-shape-rect> functions compute to the equivalent inset() function.
|
||||
// Given "xywh(x y w h)", the equivalent function is
|
||||
// "inset(y calc(100% - x - w) calc(100% - y - h) x)".
|
||||
// https://drafts.csswg.org/css-shapes-1/#basic-shape-computed-values
|
||||
// https://github.com/w3c/csswg-drafts/issues/9053
|
||||
test_computed_value("offset-path", "xywh(0 1% 2px 3em)", "inset(1% calc(100% - 2px) calc(99% - 48px) 0px)");
|
||||
|
@ -91,6 +93,14 @@ test_computed_value("offset-path", "xywh(0px 1% 2px 3em round 0)", "inset(1% cal
|
|||
test_computed_value("offset-path", "xywh(0px 1% 2px 3em round 0 1px)", "inset(1% calc(100% - 2px) calc(99% - 48px) 0px round 0px 1px)");
|
||||
test_computed_value("offset-path", "xywh(0px 1% 2px 3% round 0px 1px 2em)", "inset(1% calc(100% - 2px) 96% 0px round 0px 1px 32px)");
|
||||
test_computed_value("offset-path", "xywh(0px 1% 2px 3% round 0px 1px 2% 3px)", "inset(1% calc(100% - 2px) 96% 0px round 0px 1px 2% 3px)");
|
||||
// Given "rect(t r b l)", the equivalent function is
|
||||
// "inset(t calc(100% - r) calc(100% - b) l)".
|
||||
test_computed_value("offset-path", "rect(auto auto auto auto)", "inset(0%)");
|
||||
test_computed_value("offset-path", "rect(0 1% 2px 3em)", "inset(0px 99% calc(100% - 2px) 48px)");
|
||||
test_computed_value("offset-path", "rect(0px 1% auto 3em round 0)", "inset(0px 99% 0% 48px)");
|
||||
test_computed_value("offset-path", "rect(0px 1% auto 3% round 0 1px)", "inset(0px 99% 0% 3% round 0px 1px)");
|
||||
test_computed_value("offset-path", "rect(0px 1% auto 3% round 0px 1px 2em)", "inset(0px 99% 0% 3% round 0px 1px 32px)");
|
||||
test_computed_value("offset-path", "rect(0px 1% auto 3% round 0px 1px 2% 3px)", "inset(0px 99% 0% 3% round 0px 1px 2% 3px)");
|
||||
|
||||
test_computed_value("offset-path", "content-box");
|
||||
test_computed_value("offset-path", "border-box");
|
||||
|
|
|
@ -34,6 +34,10 @@ test_invalid_value("offset-path", "xywh(0px)");
|
|||
test_invalid_value("offset-path", "xywh(0px 1%)");
|
||||
test_invalid_value("offset-path", "xywh(0px 1% 2em)");
|
||||
|
||||
test_invalid_value("offset-path", "rect(0px)");
|
||||
test_invalid_value("offset-path", "rect(0px 1%)");
|
||||
test_invalid_value("offset-path", "rect(0px 1% auto)");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -82,6 +82,13 @@ test_valid_value("offset-path", "xywh(0px 1% 2px 3em round 0 1px)", "xywh(0px 1%
|
|||
test_valid_value("offset-path", "xywh(0px 1% 2px 3em round 0px 1px 2%)");
|
||||
test_valid_value("offset-path", "xywh(0px 1% 2px 3em round 0px 1px 2% 3em)");
|
||||
|
||||
test_valid_value("offset-path", "rect(0 100% 200px 4em)", "rect(0px 100% 200px 4em)");
|
||||
test_valid_value("offset-path", "rect(auto auto auto auto)");
|
||||
test_valid_value("offset-path", "rect(0px 100% auto 4em round 0)", "rect(0px 100% auto 4em)");
|
||||
test_valid_value("offset-path", "rect(0px 100% auto 4em round 0 1px)", "rect(0px 100% auto 4em round 0px 1px)");
|
||||
test_valid_value("offset-path", "rect(0px 100% auto 4em round 0px 1px 2%)");
|
||||
test_valid_value("offset-path", "rect(0px 100% auto 4em round 0px 1px 2% 3em)");
|
||||
|
||||
test_valid_value("offset-path", "content-box");
|
||||
test_valid_value("offset-path", "border-box");
|
||||
test_valid_value("offset-path", "view-box");
|
||||
|
|
Загрузка…
Ссылка в новой задаче