Backed out 7 changesets (bug 1429298) for xpcshell failures properties-db.js CLOSED TREE

Backed out changeset 48214a8e1b6b (bug 1429298)
Backed out changeset cc2785ab879e (bug 1429298)
Backed out changeset c217209a3b04 (bug 1429298)
Backed out changeset 196fc7b48b84 (bug 1429298)
Backed out changeset 761e9bb54adb (bug 1429298)
Backed out changeset 0b9ec0d707b5 (bug 1429298)
Backed out changeset 38ad1cc1b0c8 (bug 1429298)

--HG--
rename : testing/web-platform/tests/css/motion/offset-path-string-002.html => testing/web-platform/tests/css/motion/offset-path-string.html
This commit is contained in:
Ciure Andrei 2018-08-22 08:01:49 +03:00
Родитель c7eca6e1df
Коммит 40b18c41b7
45 изменённых файлов: 244 добавлений и 1425 удалений

Просмотреть файл

@ -210,7 +210,6 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
"min-block-size",
"-moz-min-font-size-ratio",
"min-inline-size",
"offset-path",
"padding-block-end",
"padding-block-start",
"padding-inline-end",

Просмотреть файл

@ -2949,7 +2949,6 @@ exports.CSS_PROPERTIES = {
"rotate",
"scale",
"translate",
"offset-path",
"scroll-behavior",
"scroll-snap-type-x",
"scroll-snap-type-y",
@ -7416,20 +7415,6 @@ exports.CSS_PROPERTIES = {
"unset"
]
},
"offset-path": {
"isInherited": false,
"subproperties": [
"offset-path"
],
"supports": [],
"values": [
"inherit",
"initial",
"none",
"path",
"unset"
]
},
"opacity": {
"isInherited": false,
"subproperties": [
@ -9346,10 +9331,6 @@ exports.PREFERENCES = [
"font-variation-settings",
"layout.css.font-variations.enabled"
],
[
"offset-path",
"layout.css.motion-path.enabled"
],
[
"rotate",
"layout.css.individual-transform.enabled"

Просмотреть файл

@ -26,41 +26,12 @@ using namespace mozilla;
using namespace mozilla::dom::SVGPathSeg_Binding;
using namespace mozilla::gfx;
static inline bool IsMoveto(uint16_t aSegType)
static bool IsMoveto(uint16_t aSegType)
{
return aSegType == PATHSEG_MOVETO_ABS ||
aSegType == PATHSEG_MOVETO_REL;
}
static inline bool
IsMoveto(StylePathCommand::Tag aSegType)
{
return aSegType == StylePathCommand::Tag::MoveTo;
}
static inline bool
IsValidType(uint16_t aSegType)
{
return SVGPathSegUtils::IsValidType(aSegType);
}
static inline bool
IsValidType(StylePathCommand::Tag aSegType)
{
return aSegType != StylePathCommand::Tag::Unknown;
}
static inline bool
IsClosePath(uint16_t aSegType) {
return aSegType == PATHSEG_CLOSEPATH;
}
static inline bool
IsClosePath(StylePathCommand::Tag aSegType)
{
return aSegType == StylePathCommand::Tag::ClosePath;
}
nsresult
SVGPathData::CopyFrom(const SVGPathData& rhs)
{
@ -291,18 +262,18 @@ ApproximateZeroLengthSubpathSquareCaps(PathBuilder* aPB,
aPB->MoveTo(aPoint);
}
#define MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT \
do { \
if (!subpathHasLength && hasLineCaps && aStrokeWidth > 0 && \
subpathContainsNonMoveTo && \
IsValidType(prevSegType) && \
(!IsMoveto(prevSegType) || IsClosePath(segType))) { \
ApproximateZeroLengthSubpathSquareCaps(aBuilder, segStart, aStrokeWidth);\
} \
#define MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT \
do { \
if (!subpathHasLength && hasLineCaps && aStrokeWidth > 0 && \
subpathContainsNonMoveTo && \
SVGPathSegUtils::IsValidType(prevSegType) && \
(!IsMoveto(prevSegType) || segType == PATHSEG_CLOSEPATH)) { \
ApproximateZeroLengthSubpathSquareCaps(builder, segStart, aStrokeWidth);\
} \
} while(0)
already_AddRefed<Path>
SVGPathData::BuildPath(PathBuilder* aBuilder,
SVGPathData::BuildPath(PathBuilder* builder,
uint8_t aStrokeLineCap,
Float aStrokeWidth) const
{
@ -338,20 +309,20 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
subpathContainsNonMoveTo = true;
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
segEnd = pathStart;
aBuilder->Close();
builder->Close();
break;
case PATHSEG_MOVETO_ABS:
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
pathStart = segEnd = Point(mData[i], mData[i+1]);
aBuilder->MoveTo(segEnd);
builder->MoveTo(segEnd);
subpathHasLength = false;
break;
case PATHSEG_MOVETO_REL:
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
pathStart = segEnd = segStart + Point(mData[i], mData[i+1]);
aBuilder->MoveTo(segEnd);
builder->MoveTo(segEnd);
subpathHasLength = false;
break;
@ -359,7 +330,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
segEnd = Point(mData[i], mData[i+1]);
if (segEnd != segStart) {
subpathHasLength = true;
aBuilder->LineTo(segEnd);
builder->LineTo(segEnd);
}
break;
@ -367,7 +338,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
segEnd = segStart + Point(mData[i], mData[i+1]);
if (segEnd != segStart) {
subpathHasLength = true;
aBuilder->LineTo(segEnd);
builder->LineTo(segEnd);
}
break;
@ -377,7 +348,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
segEnd = Point(mData[i+4], mData[i+5]);
if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
subpathHasLength = true;
aBuilder->BezierTo(cp1, cp2, segEnd);
builder->BezierTo(cp1, cp2, segEnd);
}
break;
@ -387,7 +358,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
segEnd = segStart + Point(mData[i+4], mData[i+5]);
if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
subpathHasLength = true;
aBuilder->BezierTo(cp1, cp2, segEnd);
builder->BezierTo(cp1, cp2, segEnd);
}
break;
@ -399,7 +370,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
tcp2 = cp1 + (segEnd - cp1) / 3;
if (segEnd != segStart || segEnd != cp1) {
subpathHasLength = true;
aBuilder->BezierTo(tcp1, tcp2, segEnd);
builder->BezierTo(tcp1, tcp2, segEnd);
}
break;
@ -411,7 +382,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
tcp2 = cp1 + (segEnd - cp1) / 3;
if (segEnd != segStart || segEnd != cp1) {
subpathHasLength = true;
aBuilder->BezierTo(tcp1, tcp2, segEnd);
builder->BezierTo(tcp1, tcp2, segEnd);
}
break;
@ -426,12 +397,12 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
if (segEnd != segStart) {
subpathHasLength = true;
if (radii.x == 0.0f || radii.y == 0.0f) {
aBuilder->LineTo(segEnd);
builder->LineTo(segEnd);
} else {
nsSVGArcConverter converter(segStart, segEnd, radii, mData[i+2],
mData[i+3] != 0, mData[i+4] != 0);
while (converter.GetNextSegment(&cp1, &cp2, &segEnd)) {
aBuilder->BezierTo(cp1, cp2, segEnd);
builder->BezierTo(cp1, cp2, segEnd);
}
}
}
@ -442,7 +413,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
segEnd = Point(mData[i], segStart.y);
if (segEnd != segStart) {
subpathHasLength = true;
aBuilder->LineTo(segEnd);
builder->LineTo(segEnd);
}
break;
@ -450,7 +421,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
segEnd = segStart + Point(mData[i], 0.0f);
if (segEnd != segStart) {
subpathHasLength = true;
aBuilder->LineTo(segEnd);
builder->LineTo(segEnd);
}
break;
@ -458,7 +429,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
segEnd = Point(segStart.x, mData[i]);
if (segEnd != segStart) {
subpathHasLength = true;
aBuilder->LineTo(segEnd);
builder->LineTo(segEnd);
}
break;
@ -466,7 +437,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
segEnd = segStart + Point(0.0f, mData[i]);
if (segEnd != segStart) {
subpathHasLength = true;
aBuilder->LineTo(segEnd);
builder->LineTo(segEnd);
}
break;
@ -476,7 +447,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
segEnd = Point(mData[i+2], mData[i+3]);
if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
subpathHasLength = true;
aBuilder->BezierTo(cp1, cp2, segEnd);
builder->BezierTo(cp1, cp2, segEnd);
}
break;
@ -486,7 +457,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
segEnd = segStart + Point(mData[i+2], mData[i+3]);
if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
subpathHasLength = true;
aBuilder->BezierTo(cp1, cp2, segEnd);
builder->BezierTo(cp1, cp2, segEnd);
}
break;
@ -498,7 +469,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
tcp2 = cp1 + (segEnd - cp1) / 3;
if (segEnd != segStart || segEnd != cp1) {
subpathHasLength = true;
aBuilder->BezierTo(tcp1, tcp2, segEnd);
builder->BezierTo(tcp1, tcp2, segEnd);
}
break;
@ -510,7 +481,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
tcp2 = cp1 + (segEnd - cp1) / 3;
if (segEnd != segStart || segEnd != cp1) {
subpathHasLength = true;
aBuilder->BezierTo(tcp1, tcp2, segEnd);
builder->BezierTo(tcp1, tcp2, segEnd);
}
break;
@ -532,7 +503,7 @@ SVGPathData::BuildPath(PathBuilder* aBuilder,
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
return aBuilder->Finish();
return builder->Finish();
}
already_AddRefed<Path>
@ -553,209 +524,6 @@ SVGPathData::BuildPathForMeasuring() const
return BuildPath(builder, NS_STYLE_STROKE_LINECAP_BUTT, 0);
}
// We could simplify this function because this is only used by CSS motion path
// and clip-path, which don't render the SVG Path. i.e. The returned path is
// used as a reference.
/* static */ already_AddRefed<Path>
SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
PathBuilder* aBuilder,
uint8_t aStrokeLineCap,
Float aStrokeWidth)
{
if (aPath.IsEmpty() || !aPath[0].IsMoveTo()) {
return nullptr; // paths without an initial moveto are invalid
}
auto toGfxPoint = [](const StyleCoordPair& aPair) {
return Point(aPair._0, aPair._1);
};
auto isCubicType = [](StylePathCommand::Tag aType) {
return aType == StylePathCommand::Tag::CurveTo ||
aType == StylePathCommand::Tag::SmoothCurveTo;
};
auto isQuadraticType = [](StylePathCommand::Tag aType) {
return aType == StylePathCommand::Tag::QuadBezierCurveTo ||
aType == StylePathCommand::Tag::SmoothQuadBezierCurveTo;
};
bool hasLineCaps = aStrokeLineCap != NS_STYLE_STROKE_LINECAP_BUTT;
bool subpathHasLength = false; // visual length
bool subpathContainsNonMoveTo = false;
StylePathCommand::Tag segType = StylePathCommand::Tag::Unknown;
StylePathCommand::Tag prevSegType = StylePathCommand::Tag::Unknown;
Point pathStart(0.0, 0.0); // start point of [sub]path
Point segStart(0.0, 0.0);
Point segEnd;
Point cp1, cp2; // previous bezier's control points
Point tcp1, tcp2; // temporaries
// Regarding cp1 and cp2: If the previous segment was a cubic bezier curve,
// then cp2 is its second control point. If the previous segment was a
// quadratic curve, then cp1 is its (only) control point.
for (const StylePathCommand& cmd: aPath) {
segType = cmd.tag;
switch (segType) {
case StylePathCommand::Tag::ClosePath:
// set this early to allow drawing of square caps for "M{x},{y} Z":
subpathContainsNonMoveTo = true;
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
segEnd = pathStart;
aBuilder->Close();
break;
case StylePathCommand::Tag::MoveTo: {
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
const Point& p = toGfxPoint(cmd.move_to.point);
pathStart = segEnd = cmd.move_to.absolute ? p : segStart + p;
aBuilder->MoveTo(segEnd);
subpathHasLength = false;
break;
}
case StylePathCommand::Tag::LineTo: {
const Point& p = toGfxPoint(cmd.line_to.point);
segEnd = cmd.line_to.absolute ? p : segStart + p;
if (segEnd != segStart) {
subpathHasLength = true;
aBuilder->LineTo(segEnd);
}
break;
}
case StylePathCommand::Tag::CurveTo:
cp1 = toGfxPoint(cmd.curve_to.control1);
cp2 = toGfxPoint(cmd.curve_to.control2);
segEnd = toGfxPoint(cmd.curve_to.point);
if (!cmd.curve_to.absolute) {
cp1 += segStart;
cp2 += segStart;
segEnd += segStart;
}
if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
subpathHasLength = true;
aBuilder->BezierTo(cp1, cp2, segEnd);
}
break;
case StylePathCommand::Tag::QuadBezierCurveTo:
cp1 = toGfxPoint(cmd.quad_bezier_curve_to.control1);
segEnd = toGfxPoint(cmd.quad_bezier_curve_to.point);
if (!cmd.quad_bezier_curve_to.absolute) {
cp1 += segStart;
segEnd += segStart; // set before setting tcp2!
}
// Convert quadratic curve to cubic curve:
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
tcp2 = cp1 + (segEnd - cp1) / 3;
if (segEnd != segStart || segEnd != cp1) {
subpathHasLength = true;
aBuilder->BezierTo(tcp1, tcp2, segEnd);
}
break;
case StylePathCommand::Tag::EllipticalArc: {
const auto& arc = cmd.elliptical_arc;
Point radii(arc.rx, arc.ry);
segEnd = toGfxPoint(arc.point);
if (!arc.absolute) {
segEnd += segStart;
}
if (segEnd != segStart) {
subpathHasLength = true;
if (radii.x == 0.0f || radii.y == 0.0f) {
aBuilder->LineTo(segEnd);
} else {
nsSVGArcConverter converter(segStart, segEnd, radii, arc.angle,
arc.large_arc_flag, arc.sweep_flag);
while (converter.GetNextSegment(&cp1, &cp2, &segEnd)) {
aBuilder->BezierTo(cp1, cp2, segEnd);
}
}
}
break;
}
case StylePathCommand::Tag::HorizontalLineTo:
if (cmd.horizontal_line_to.absolute) {
segEnd = Point(cmd.horizontal_line_to.x, segStart.y);
} else {
segEnd = segStart + Point(cmd.horizontal_line_to.x, 0.0f);
}
if (segEnd != segStart) {
subpathHasLength = true;
aBuilder->LineTo(segEnd);
}
break;
case StylePathCommand::Tag::VerticalLineTo:
if (cmd.vertical_line_to.absolute) {
segEnd = Point(segStart.x, cmd.vertical_line_to.y);
} else {
segEnd = segStart + Point(0.0f, cmd.vertical_line_to.y);
}
if (segEnd != segStart) {
subpathHasLength = true;
aBuilder->LineTo(segEnd);
}
break;
case StylePathCommand::Tag::SmoothCurveTo:
cp1 = isCubicType(prevSegType) ? segStart * 2 - cp2 : segStart;
cp2 = toGfxPoint(cmd.smooth_curve_to.control2);
segEnd = toGfxPoint(cmd.smooth_curve_to.point);
if (!cmd.smooth_curve_to.absolute) {
cp2 += segStart;
segEnd += segStart;
}
if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
subpathHasLength = true;
aBuilder->BezierTo(cp1, cp2, segEnd);
}
break;
case StylePathCommand::Tag::SmoothQuadBezierCurveTo: {
cp1 = isQuadraticType(prevSegType) ? segStart * 2 - cp1 : segStart;
// Convert quadratic curve to cubic curve:
tcp1 = segStart + (cp1 - segStart) * 2 / 3;
const Point& p = toGfxPoint(cmd.smooth_quad_bezier_curve_to.point);
// set before setting tcp2!
segEnd = cmd.smooth_quad_bezier_curve_to.absolute ? p : segStart + p;
tcp2 = cp1 + (segEnd - cp1) / 3;
if (segEnd != segStart || segEnd != cp1) {
subpathHasLength = true;
aBuilder->BezierTo(tcp1, tcp2, segEnd);
}
break;
}
case StylePathCommand::Tag::Unknown:
MOZ_ASSERT_UNREACHABLE("Unacceptable path segment type");
return nullptr;
}
subpathContainsNonMoveTo = !IsMoveto(segType);
prevSegType = segType;
segStart = segEnd;
}
MOZ_ASSERT(prevSegType == segType,
"prevSegType should be left at the final segType");
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS_TO_DT;
return aBuilder->Finish();
}
static double
AngleOfVector(const Point& aVector)
{

Просмотреть файл

@ -169,16 +169,6 @@ public:
already_AddRefed<Path> BuildPath(PathBuilder* aBuilder,
uint8_t aCapStyle,
Float aStrokeWidth) const;
/**
* This function tries to build the path by an array of StylePathCommand,
* which is generated by cbindgen from Rust (see ServoStyleConsts.h).
* Basically, this is a variant of the above BuildPath() functions.
*/
static already_AddRefed<Path>
BuildPath(const nsTArray<StylePathCommand>& aPath,
PathBuilder* aBuilder,
uint8_t aCapStyle,
Float aStrokeWidth);
const_iterator begin() const { return mData.Elements(); }
const_iterator end() const { return mData.Elements() + mData.Length(); }

Просмотреть файл

@ -81,7 +81,6 @@ EXPORTS.mozilla.dom += [
'SVGMatrix.h',
'SVGMetadataElement.h',
'SVGMPathElement.h',
'SVGPathData.h',
'SVGPathElement.h',
'SVGPatternElement.h',
'SVGPolygonElement.h',

Просмотреть файл

@ -76,7 +76,6 @@
#include "mozilla/dom/DOMRect.h"
#include "mozilla/dom/DOMStringList.h"
#include "mozilla/dom/KeyframeEffect.h"
#include "mozilla/dom/SVGPathData.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include "imgIRequest.h"
#include "nsIImageLoadingContent.h"
@ -10267,94 +10266,3 @@ nsLayoutUtils::StyleForScrollbar(nsIFrame* aScrollbarPart)
// held strongly by the element.
return style.get();
}
static float
ResolveTransformOrigin(const nsStyleCoord& aCoord,
TransformReferenceBox& aRefBox,
TransformReferenceBox::DimensionGetter aGetter)
{
float result = 0.0;
const float scale = mozilla::AppUnitsPerCSSPixel();
if (aCoord.GetUnit() == eStyleUnit_Calc) {
const nsStyleCoord::Calc *calc = aCoord.GetCalcValue();
result = NSAppUnitsToFloatPixels((aRefBox.*aGetter)(), scale) *
calc->mPercent +
NSAppUnitsToFloatPixels(calc->mLength, scale);
} else if (aCoord.GetUnit() == eStyleUnit_Percent) {
result = NSAppUnitsToFloatPixels((aRefBox.*aGetter)(), scale) *
aCoord.GetPercentValue();
} else {
MOZ_ASSERT(aCoord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
result = NSAppUnitsToFloatPixels(aCoord.GetCoordValue(), scale);
}
return result;
}
/* static */ Maybe<MotionPathData>
nsLayoutUtils::ResolveMotionPath(const nsIFrame* aFrame)
{
MOZ_ASSERT(aFrame);
const nsStyleDisplay* display = aFrame->StyleDisplay();
if (!display->mMotion || !display->mMotion->HasPath()) {
return Nothing();
}
const UniquePtr<StyleMotion>& motion = display->mMotion;
// Bug 1429299 - Implement offset-distance for motion path. For now, we use
// the default value, i.e. 0%.
float distance = 0.0;
float angle = 0.0;
Point point;
if (motion->OffsetPath().GetType() == StyleShapeSourceType::Path) {
// Build the path and compute the point and angle for creating the
// equivalent translate and rotate.
// Here we only need to build a valid path for motion path, so
// using the default values of stroke-width, stoke-linecap, and fill-rule
// is fine for now because what we want is get the point and its normal
// vector along the path, instead of rendering it.
// FIXME: Bug 1484780, we should cache the path to avoid rebuilding it here
// at every restyle. (Caching the path avoids the cost of flattening it
// again each time.)
RefPtr<DrawTarget> drawTarget =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
RefPtr<PathBuilder> builder =
drawTarget->CreatePathBuilder(FillRule::FILL_WINDING);
RefPtr<gfx::Path> gfxPath =
SVGPathData::BuildPath(motion->OffsetPath().GetPath()->Path(),
builder,
NS_STYLE_STROKE_LINECAP_BUTT,
0.0);
if (!gfxPath) {
return Nothing();
}
float pathLength = gfxPath->ComputeLength();
float computedDistance = distance * pathLength;
Point tangent;
point = gfxPath->ComputePointAtLength(computedDistance, &tangent);
// Bug 1429301 - Implement offset-rotate for motion path.
// After implement offset-rotate, |angle| will be adjusted more.
// For now, the default value of offset-rotate is "auto", so we use the
// directional tangent vector.
angle = atan2(tangent.y, tangent.x);
} else {
// Bug 1480665: Implement ray() function.
NS_WARNING("Unsupported offset-path value");
}
// Compute the offset for motion path translate.
// We need to resolve transform-origin here to calculate the correct path
// translate. (i.e. Center transform-origin on the path.)
TransformReferenceBox refBox(aFrame);
Point origin(
ResolveTransformOrigin(display->mTransformOrigin[0],
refBox,
&TransformReferenceBox::Width),
ResolveTransformOrigin(display->mTransformOrigin[1],
refBox,
&TransformReferenceBox::Height)
);
// Bug 1186329: the translate parameters will be adjusted more after we
// implement offset-position and offset-anchor.
return Some(MotionPathData { point - origin, angle });
}

Просмотреть файл

@ -119,11 +119,6 @@ struct DisplayPortMarginsPropertyData {
uint32_t mPriority;
};
struct MotionPathData {
gfx::Point mTranslate;
float mRotate;
};
} // namespace mozilla
// For GetDisplayPort
@ -3118,12 +3113,6 @@ public:
*/
static ComputedStyle* StyleForScrollbar(nsIFrame* aScrollbarPart);
/**
* Generate the motion path transform result.
**/
static mozilla::Maybe<mozilla::MotionPathData>
ResolveMotionPath(const nsIFrame* aFrame);
private:
static uint32_t sFontSizeInflationEmPerLine;
static uint32_t sFontSizeInflationMinTwips;

Просмотреть файл

@ -2409,10 +2409,6 @@ nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame,
MOZ_ASSERT_UNREACHABLE("shape-outside doesn't have URL source type!");
return;
case StyleShapeSourceType::Path:
MOZ_ASSERT_UNREACHABLE("shape-outside doesn't have Path source type!");
return;
case StyleShapeSourceType::Image: {
float shapeImageThreshold = styleDisplay->mShapeImageThreshold;
mShapeInfo = ShapeInfo::CreateImageShape(shapeOutside.GetShapeImage(),

Просмотреть файл

@ -249,30 +249,22 @@ static void
IncrementScaleRestyleCountIfNeeded(nsIFrame* aFrame, LayerActivity* aActivity)
{
const nsStyleDisplay* display = aFrame->StyleDisplay();
if (!display->mSpecifiedTransform &&
!display->HasIndividualTransform() &&
!(display->mMotion && display->mMotion->HasPath())) {
RefPtr<nsCSSValueSharedList> transformList = display->GetCombinedTransform();
if (!transformList) {
// The transform was removed.
aActivity->mPreviousTransformScale = Nothing();
IncrementMutationCount(
&aActivity->mRestyleCounts[LayerActivity::ACTIVITY_SCALE]);
IncrementMutationCount(&aActivity->mRestyleCounts[LayerActivity::ACTIVITY_SCALE]);
return;
}
// Compute the new scale due to the CSS transform property.
bool dummyBool;
nsStyleTransformMatrix::TransformReferenceBox refBox(aFrame);
Matrix4x4 transform = nsStyleTransformMatrix::ReadTransforms(
display->mIndividualTransform
? display->mIndividualTransform->mHead
: nullptr,
nsLayoutUtils::ResolveMotionPath(aFrame),
display->mSpecifiedTransform
? display->mSpecifiedTransform->mHead
: nullptr,
refBox,
AppUnitsPerCSSPixel(),
&dummyBool);
Matrix4x4 transform =
nsStyleTransformMatrix::ReadTransforms(transformList->mHead,
refBox,
AppUnitsPerCSSPixel(),
&dummyBool);
Matrix transform2D;
if (!transform.Is2D(&transform2D)) {
// We don't attempt to handle 3D transforms; just assume the scale changed.

Просмотреть файл

@ -7849,14 +7849,11 @@ nsDisplayTransform::ComputePerspectiveMatrix(const nsIFrame* aFrame,
return true;
}
nsDisplayTransform::FrameTransformProperties::FrameTransformProperties(
const nsIFrame* aFrame,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride)
nsDisplayTransform::FrameTransformProperties::FrameTransformProperties(const nsIFrame* aFrame,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride)
: mFrame(aFrame)
, mIndividualTransformList(aFrame->StyleDisplay()->mIndividualTransform)
, mMotion(nsLayoutUtils::ResolveMotionPath(aFrame))
, mTransformList(aFrame->StyleDisplay()->mSpecifiedTransform)
, mTransformList(aFrame->StyleDisplay()->GetCombinedTransform())
, mToTransformOrigin(GetDeltaToTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride))
{
}
@ -7925,16 +7922,10 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp
frame && frame->IsSVGTransformed(&svgTransform,
&parentsChildrenOnlyTransform);
/* Transformed frames always have a transform, or are preserving 3d (and might still have perspective!) */
if (aProperties.HasTransform()) {
result = nsStyleTransformMatrix::ReadTransforms(
aProperties.mIndividualTransformList
? aProperties.mIndividualTransformList->mHead
: nullptr,
aProperties.mMotion,
aProperties.mTransformList
? aProperties.mTransformList->mHead
: nullptr,
refBox, aAppUnitsPerPixel, &dummyBool);
if (aProperties.mTransformList) {
result = nsStyleTransformMatrix::ReadTransforms(aProperties.mTransformList->mHead,
refBox, aAppUnitsPerPixel,
&dummyBool);
} else if (hasSVGTransforms) {
// Correct the translation components for zoom:
float pixelsPerCSSPx = AppUnitsPerCSSPixel() /

Просмотреть файл

@ -68,7 +68,6 @@ enum class nsDisplayOwnLayerFlags;
namespace mozilla {
class FrameLayerBuilder;
struct MotionPathData;
namespace layers {
class Layer;
class ImageLayer;
@ -6578,11 +6577,6 @@ public:
FrameTransformProperties(const nsIFrame* aFrame,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride);
// This constructor is used on the compositor (for animations).
// Bug 1186329, Bug 1425837, If we want to support compositor animationsf
// or individual transforms and motion path, we may need to update this.
// For now, let mIndividualTransformList and mMotion as nullptr and
// Nothing().
FrameTransformProperties(RefPtr<const nsCSSValueSharedList>&&
aTransformList,
const Point3D& aToTransformOrigin)
@ -6591,14 +6585,7 @@ public:
, mToTransformOrigin(aToTransformOrigin)
{}
bool HasTransform() const
{
return mIndividualTransformList || mTransformList || mMotion.isSome();
}
const nsIFrame* mFrame;
const RefPtr<const nsCSSValueSharedList> mIndividualTransformList;
const mozilla::Maybe<mozilla::MotionPathData> mMotion;
const RefPtr<const nsCSSValueSharedList> mTransformList;
const Point3D mToTransformOrigin;
};

Просмотреть файл

@ -1950,35 +1950,6 @@ Gecko_NewShapeImage(mozilla::StyleShapeSource* aShape)
aShape->SetShapeImage(MakeUnique<nsStyleImage>());
}
void
Gecko_NewStyleSVGPath(mozilla::StyleShapeSource* aShape)
{
MOZ_ASSERT(aShape);
aShape->SetPath(MakeUnique<mozilla::StyleSVGPath>());
}
void
Gecko_SetStyleMotion(UniquePtr<mozilla::StyleMotion>* aMotion,
mozilla::StyleMotion* aValue)
{
MOZ_ASSERT(aMotion);
aMotion->reset(aValue);
}
mozilla::StyleMotion*
Gecko_NewStyleMotion()
{
return new StyleMotion();
}
void
Gecko_CopyStyleMotions(mozilla::UniquePtr<mozilla::StyleMotion>* aMotion,
const mozilla::StyleMotion* aOther)
{
MOZ_ASSERT(aMotion);
*aMotion = aOther ? MakeUnique<StyleMotion>(*aOther) : nullptr;
}
void
Gecko_ResetFilters(nsStyleEffects* effects, size_t new_len)
{

Просмотреть файл

@ -524,12 +524,6 @@ void Gecko_NewBasicShape(mozilla::StyleShapeSource* shape,
mozilla::StyleBasicShapeType type);
void Gecko_NewShapeImage(mozilla::StyleShapeSource* shape);
void Gecko_StyleShapeSource_SetURLValue(mozilla::StyleShapeSource* shape, mozilla::css::URLValue* uri);
void Gecko_NewStyleSVGPath(mozilla::StyleShapeSource* shape);
void Gecko_SetStyleMotion(mozilla::UniquePtr<mozilla::StyleMotion>* aMotion,
mozilla::StyleMotion* aValue);
mozilla::StyleMotion* Gecko_NewStyleMotion();
void Gecko_CopyStyleMotions(mozilla::UniquePtr<mozilla::StyleMotion>* motion,
const mozilla::StyleMotion* other);
void Gecko_ResetFilters(nsStyleEffects* effects, size_t new_len);
void Gecko_CopyFiltersFrom(nsStyleEffects* aSrc, nsStyleEffects* aDest);

Просмотреть файл

@ -473,7 +473,6 @@ structs-types = [
"mozilla::FontWeight",
"mozilla::MallocSizeOf",
"mozilla::OriginFlags",
"mozilla::StyleMotion",
"mozilla::UniquePtr",
"mozilla::StyleDisplayMode",
"ServoRawOffsetArc",

Просмотреть файл

@ -94,7 +94,6 @@ SERIALIZED_PREDEFINED_TYPES = [
"NonNegativeLength",
"NonNegativeLengthOrPercentage",
"ListStyleType",
"OffsetPath",
"Opacity",
"Resize",
"url::ImageUrlOrNone",

Просмотреть файл

@ -5048,11 +5048,6 @@ nsComputedDOMStyle::GetShapeSource(
SetValueToStyleImage(*aShapeSource.GetShapeImage(), val);
return val.forget();
}
case StyleShapeSourceType::Path: {
// Bug 1246764: we have to support this for clip-path. For now, no one
// uses this.
MOZ_ASSERT_UNREACHABLE("Unexpected SVG Path type.");
}
}
return nullptr;
}

Просмотреть файл

@ -198,7 +198,6 @@ enum class StyleShapeSourceType : uint8_t {
Image, // shape-outside only
Shape,
Box,
Path, // SVG path function
};
// -moz-stack-sizing

Просмотреть файл

@ -1039,9 +1039,6 @@ StyleShapeSource::operator==(const StyleShapeSource& aOther) const
case StyleShapeSourceType::Box:
return mReferenceBox == aOther.mReferenceBox;
case StyleShapeSourceType::Path:
return *mSVGPath == *aOther.mSVGPath;
}
MOZ_ASSERT_UNREACHABLE("Unexpected shape source type!");
@ -1093,15 +1090,6 @@ StyleShapeSource::SetBasicShape(UniquePtr<StyleBasicShape> aBasicShape,
mType = StyleShapeSourceType::Shape;
}
void
StyleShapeSource::SetPath(UniquePtr<StyleSVGPath> aPath)
{
MOZ_ASSERT(aPath);
DoDestroy();
new (&mSVGPath) UniquePtr<StyleSVGPath>(std::move(aPath));
mType = StyleShapeSourceType::Path;
}
void
StyleShapeSource::SetReferenceBox(StyleGeometryBox aReferenceBox)
{
@ -1135,10 +1123,6 @@ StyleShapeSource::DoCopy(const StyleShapeSource& aOther)
case StyleShapeSourceType::Box:
SetReferenceBox(aOther.GetReferenceBox());
break;
case StyleShapeSourceType::Path:
SetPath(MakeUnique<StyleSVGPath>(*aOther.GetPath()));
break;
}
}
@ -1153,9 +1137,6 @@ StyleShapeSource::DoDestroy()
case StyleShapeSourceType::URL:
mShapeImage.~UniquePtr<nsStyleImage>();
break;
case StyleShapeSourceType::Path:
mSVGPath.~UniquePtr<StyleSVGPath>();
break;
case StyleShapeSourceType::None:
case StyleShapeSourceType::Box:
// Not a union type, so do nothing.
@ -3636,10 +3617,7 @@ nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
, mSpecifiedRotate(aSource.mSpecifiedRotate)
, mSpecifiedTranslate(aSource.mSpecifiedTranslate)
, mSpecifiedScale(aSource.mSpecifiedScale)
, mIndividualTransform(aSource.mIndividualTransform)
, mMotion(aSource.mMotion
? MakeUnique<StyleMotion>(*aSource.mMotion)
: nullptr)
, mCombinedTransform(aSource.mCombinedTransform)
, mTransformOrigin{ aSource.mTransformOrigin[0],
aSource.mTransformOrigin[1],
aSource.mTransformOrigin[2] }
@ -3704,8 +3682,9 @@ nsStyleDisplay::~nsStyleDisplay()
mSpecifiedTranslate);
ReleaseSharedListOnMainThread("nsStyleDisplay::mSpecifiedScale",
mSpecifiedScale);
ReleaseSharedListOnMainThread("nsStyleDisplay::mIndividualTransform",
mIndividualTransform);
ReleaseSharedListOnMainThread("nsStyleDisplay::mCombinedTransform",
mCombinedTransform);
MOZ_COUNT_DTOR(nsStyleDisplay);
}
@ -3733,7 +3712,7 @@ nsStyleDisplay::FinishStyle(
}
}
GenerateCombinedIndividualTransform();
GenerateCombinedTransform();
}
static inline nsChangeHint
@ -3756,29 +3735,6 @@ CompareTransformValues(const RefPtr<nsCSSValueSharedList>& aList,
return result;
}
static inline nsChangeHint
CompareMotionValues(const StyleMotion* aMotion,
const StyleMotion* aNewMotion)
{
nsChangeHint result = nsChangeHint(0);
// TODO: Bug 1482737: This probably doesn't need to UpdateOverflow
// (or UpdateTransformLayer) if there's already a transform.
if (!aMotion != !aNewMotion ||
(aMotion && *aMotion != *aNewMotion)) {
// Set the same hints as what we use for transform because motion path is
// a kind of transform and will be combined with other transforms.
result |= nsChangeHint_UpdateTransformLayer;
if ((aMotion && aMotion->HasPath()) &&
(aNewMotion && aNewMotion->HasPath())) {
result |= nsChangeHint_UpdatePostTransformOverflow;
} else {
result |= nsChangeHint_UpdateOverflow;
}
}
return result;
}
nsChangeHint
nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
{
@ -3910,7 +3866,6 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
aNewData.mSpecifiedTranslate);
transformHint |= CompareTransformValues(mSpecifiedScale,
aNewData.mSpecifiedScale);
transformHint |= CompareMotionValues(mMotion.get(), aNewData.mMotion.get());
const nsChangeHint kUpdateOverflowAndRepaintHint =
nsChangeHint_UpdateOverflow | nsChangeHint_RepaintFrame;
@ -4030,17 +3985,17 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
}
void
nsStyleDisplay::GenerateCombinedIndividualTransform()
nsStyleDisplay::GenerateCombinedTransform()
{
// FIXME(emilio): This should probably be called from somewhere like what we
// do for image layers, instead of FinishStyle.
//
// This does and undoes the work a ton of times in Stylo.
mIndividualTransform = nullptr;
mCombinedTransform = nullptr;
// Follow the order defined in the spec to append transform functions.
// https://drafts.csswg.org/css-transforms-2/#ctm
AutoTArray<nsCSSValueSharedList*, 3> shareLists;
AutoTArray<nsCSSValueSharedList*, 4> shareLists;
if (mSpecifiedTranslate) {
shareLists.AppendElement(mSpecifiedTranslate.get());
}
@ -4050,20 +4005,24 @@ nsStyleDisplay::GenerateCombinedIndividualTransform()
if (mSpecifiedScale) {
shareLists.AppendElement(mSpecifiedScale.get());
}
if (mSpecifiedTransform) {
shareLists.AppendElement(mSpecifiedTransform.get());
}
if (shareLists.Length() == 0) {
return;
}
if (shareLists.Length() == 1) {
mIndividualTransform = shareLists[0];
mCombinedTransform = shareLists[0];
return;
}
// In common, we may have 3 transform functions:
// 1. one rotate function in mSpecifiedRotate,
// 2. one translate function in mSpecifiedTranslate,
// 3. one scale function in mSpecifiedScale.
AutoTArray<nsCSSValueList*, 3> valueLists;
// In common, we may have 3 transform functions(for rotate, translate and
// scale) in mSpecifiedTransform, one rotate function in mSpecifiedRotate,
// one translate function in mSpecifiedTranslate, and one scale function in
// mSpecifiedScale. So 6 slots are enough for the most cases.
AutoTArray<nsCSSValueList*, 6> valueLists;
for (auto list: shareLists) {
if (list) {
valueLists.AppendElement(list->mHead->Clone());
@ -4078,9 +4037,8 @@ nsStyleDisplay::GenerateCombinedIndividualTransform()
valueLists[i]->mNext = valueLists[i + 1];
}
mIndividualTransform = new nsCSSValueSharedList(valueLists[0]);
mCombinedTransform = new nsCSSValueSharedList(valueLists[0]);
}
// --------------------
// nsStyleVisibility
//

Просмотреть файл

@ -1971,27 +1971,6 @@ private:
nsStyleCorners mRadius;
};
struct StyleSVGPath final
{
const nsTArray<StylePathCommand>& Path() const
{
return mPath;
}
bool operator==(const StyleSVGPath& aOther) const
{
return mPath == aOther.mPath;
}
bool operator!=(const StyleSVGPath& aOther) const
{
return !(*this == aOther);
}
private:
nsTArray<StylePathCommand> mPath;
};
struct StyleShapeSource final
{
StyleShapeSource();
@ -2056,13 +2035,6 @@ struct StyleShapeSource final
void SetReferenceBox(StyleGeometryBox aReferenceBox);
const StyleSVGPath* GetPath() const
{
MOZ_ASSERT(mType == StyleShapeSourceType::Path, "Wrong shape source type!");
return mSVGPath.get();
}
void SetPath(UniquePtr<StyleSVGPath> aPath);
private:
void* operator new(size_t) = delete;
@ -2072,41 +2044,13 @@ private:
union {
mozilla::UniquePtr<StyleBasicShape> mBasicShape;
mozilla::UniquePtr<nsStyleImage> mShapeImage;
mozilla::UniquePtr<StyleSVGPath> mSVGPath;
// TODO: Bug 1429298, implement SVG Path function.
// TODO: Bug 1480665, implement ray() function.
};
StyleShapeSourceType mType = StyleShapeSourceType::None;
StyleGeometryBox mReferenceBox = StyleGeometryBox::NoBox;
};
struct StyleMotion final
{
bool operator==(const StyleMotion& aOther) const
{
return mOffsetPath == aOther.mOffsetPath;
}
bool operator!=(const StyleMotion& aOther) const
{
return !(*this == aOther);
}
const StyleShapeSource& OffsetPath() const
{
return mOffsetPath;
}
bool HasPath() const
{
// Bug 1186329: We have to check other acceptable types after supporting
// different values of offset-path. e.g. basic-shapes, ray.
return mOffsetPath.GetType() == StyleShapeSourceType::Path;
}
private:
StyleShapeSource mOffsetPath;
};
} // namespace mozilla
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
@ -2181,10 +2125,12 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
RefPtr<nsCSSValueSharedList> mSpecifiedRotate;
RefPtr<nsCSSValueSharedList> mSpecifiedTranslate;
RefPtr<nsCSSValueSharedList> mSpecifiedScale;
// Used to store the final combination of mSpecifiedRotate,
// mSpecifiedTranslate, and mSpecifiedScale.
RefPtr<nsCSSValueSharedList> mIndividualTransform;
mozilla::UniquePtr<mozilla::StyleMotion> mMotion;
// Used to store the final combination of mSpecifiedTranslate,
// mSpecifiedRotate, mSpecifiedScale and mSpecifiedTransform.
// Use GetCombinedTransform() to get the final transform, instead of
// accessing mCombinedTransform directly.
RefPtr<nsCSSValueSharedList> mCombinedTransform;
nsStyleCoord mTransformOrigin[3]; // percent, coord, calc, 3rd param is coord, calc only
nsStyleCoord mChildPerspective; // none, coord
@ -2434,8 +2380,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
return mSpecifiedTransform || mSpecifiedRotate || mSpecifiedTranslate ||
mSpecifiedScale ||
mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
(mWillChangeBitField & NS_STYLE_WILL_CHANGE_TRANSFORM) ||
(mMotion && mMotion->HasPath());
(mWillChangeBitField & NS_STYLE_WILL_CHANGE_TRANSFORM);
}
bool HasIndividualTransform() const {
@ -2525,17 +2470,21 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
inline bool IsFixedPosContainingBlockForTransformSupportingFrames() const;
/**
* Returns the final combined individual transform.
* Returns the final combined transform.
**/
already_AddRefed<nsCSSValueSharedList> GetCombinedTransform() const
{
return mIndividualTransform ? do_AddRef(mIndividualTransform) : nullptr;
already_AddRefed<nsCSSValueSharedList> GetCombinedTransform() const {
if (mCombinedTransform) {
return do_AddRef(mCombinedTransform);
}
// backward compatible to gecko-backed style system.
return mSpecifiedTransform ? do_AddRef(mSpecifiedTransform) : nullptr;
}
private:
// Helpers for above functions, which do some but not all of the tests
// for them (since transform must be tested separately for each).
void GenerateCombinedIndividualTransform();
void GenerateCombinedTransform();
};
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTable

Просмотреть файл

@ -926,12 +926,14 @@ SetIdentityMatrix(nsCSSValue::Array* aMatrix)
}
}
static void
ReadTransformsImpl(Matrix4x4& aMatrix,
const nsCSSValueList* aList,
TransformReferenceBox& aRefBox,
bool* aContains3dTransform)
Matrix4x4
ReadTransforms(const nsCSSValueList* aList,
TransformReferenceBox& aRefBox,
float aAppUnitsPerMatrixUnit,
bool* aContains3dTransform)
{
Matrix4x4 result;
for (const nsCSSValueList* curr = aList; curr != nullptr; curr = curr->mNext) {
const nsCSSValue &currElem = curr->mValue;
if (currElem.GetUnit() != eCSSUnit_Function) {
@ -945,55 +947,9 @@ ReadTransformsImpl(Matrix4x4& aMatrix,
"Incoming function is too short!");
/* Read in a single transform matrix. */
MatrixForTransformFunction(aMatrix, currElem.GetArrayValue(), aRefBox,
MatrixForTransformFunction(result, currElem.GetArrayValue(), aRefBox,
aContains3dTransform);
}
}
Matrix4x4
ReadTransforms(const nsCSSValueList* aList,
TransformReferenceBox& aRefBox,
float aAppUnitsPerMatrixUnit,
bool* aContains3dTransform)
{
Matrix4x4 result;
ReadTransformsImpl(result, aList, aRefBox, aContains3dTransform);
float scale = float(AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit;
result.PreScale(1/scale, 1/scale, 1/scale);
result.PostScale(scale, scale, scale);
return result;
}
Matrix4x4
ReadTransforms(const nsCSSValueList* aIndividualTransforms,
const Maybe<MotionPathData>& aMotion,
const nsCSSValueList* aTransform,
TransformReferenceBox& aRefBox,
float aAppUnitsPerMatrixUnit,
bool* aContains3dTransform)
{
Matrix4x4 result;
if (aIndividualTransforms) {
ReadTransformsImpl(result, aIndividualTransforms, aRefBox,
aContains3dTransform);
}
if (aMotion.isSome()) {
// Create the equivalent translate and rotate function, according to the
// order in spec. We combine the translate and then the rotate.
// https://drafts.fxtf.org/motion-1/#calculating-path-transform
result.PreTranslate(aMotion->mTranslate.x, aMotion->mTranslate.y, 0.0);
if (aMotion->mRotate != 0.0) {
result.RotateZ(aMotion->mRotate);
}
}
if (aTransform) {
ReadTransformsImpl(result, aTransform, aRefBox, aContains3dTransform);
}
float scale = float(AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit;
result.PreScale(1/scale, 1/scale, 1/scale);

Просмотреть файл

@ -24,10 +24,6 @@ class nsPresContext;
struct gfxQuaternion;
struct nsRect;
namespace mozilla {
struct MotionPathData;
}
/**
* A helper to generate gfxMatrixes from css transform functions.
*/
@ -204,16 +200,6 @@ namespace nsStyleTransformMatrix {
float aAppUnitsPerMatrixUnit,
bool* aContains3dTransform);
// Generate the gfx::Matrix for CSS Transform Module Level 2.
// https://drafts.csswg.org/css-transforms-2/#ctm
mozilla::gfx::Matrix4x4
ReadTransforms(const nsCSSValueList* aIndividualTransforms,
const mozilla::Maybe<mozilla::MotionPathData>& aMotion,
const nsCSSValueList* aTransform,
TransformReferenceBox& aRefBox,
float aAppUnitsPerMatrixUnit,
bool* aContains3dTransform);
/**
* Given two nsStyleCoord values, compute the 2d position with respect to the
* given TransformReferenceBox that these values describe, in device pixels.

Просмотреть файл

@ -8173,28 +8173,6 @@ if (IsCSSPropertyPrefEnabled("layout.css.scrollbar-width.enabled")) {
};
}
if (IsCSSPropertyPrefEnabled("layout.css.motion-path.enabled")) {
gCSSProperties["offset-path"] = {
domProp: "offsetPath",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
other_values: [
"path('M 10 10 20 20 H 90 V 90 Z')",
"path('M10 10 20,20H90V90Z')",
"path('M 10 10 C 20 20, 40 20, 50 10')",
"path('M 10 80 C 40 10, 65 10, 95 80 S 1.5e2 150, 180 80')",
"path('M 10 80 Q 95 10 180 80')",
"path('M 10 80 Q 52.5 10, 95 80 T 180 80')",
"path('M 80 80 A 45 45, 0, 0, 0, 1.25e2 1.25e2 L 125 80 Z')",
"path('M100-200h20z')",
"path('M10,10L20.6.5z')"
],
invalid_values: [ "path('')", "path()", "path(a)", "path('M 10 Z')" ,
"path('M 10-10 20')", "path('M 10 10 C 20 20 40 20')" ]
};
}
const OVERFLOW_MOZKWS = [
"-moz-scrollbars-none",
"-moz-scrollbars-horizontal",

Просмотреть файл

@ -3073,13 +3073,6 @@ pref("layout.css.ruby.intercharacter.enabled", false);
// Is support for overscroll-behavior enabled?
pref("layout.css.overscroll-behavior.enabled", true);
// Is support for motion-path enabled?
#ifdef RELEASE_OR_BETA
pref("layout.css.motion-path.enabled", false);
#else
pref("layout.css.motion-path.enabled", true);
#endif
// pref for which side vertical scrollbars should be on
// 0 = end-side in UI direction
// 1 = end-side in document/content direction

Просмотреть файл

@ -7,7 +7,6 @@ autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated usi
* a. Alternatively, you can clone `https://github.com/eqrion/cbindgen` and use a tagged release
* 2. Run `rustup run nightly cbindgen toolkit/library/rust/ --lockfile Cargo.lock --crate style -o layout/style/ServoStyleConsts.h`
*/"""
include_guard = "mozilla_ServoStyleConsts_h"
include_version = true
braces = "SameLine"
line_length = 80
@ -23,5 +22,5 @@ derive_helper_methods = true
[export]
prefix = "Style"
include = ["StyleDisplay", "StyleAppearance", "StyleDisplayMode", "StylePathCommand"]
item_types = ["enums", "structs", "typedefs"]
include = ["StyleDisplay", "StyleAppearance", "StyleDisplayMode"]
item_types = ["enums"]

Просмотреть файл

@ -638,7 +638,6 @@ pub mod basic_shape {
use values::computed::basic_shape::{BasicShape, ClippingShape, FloatAreaShape, ShapeRadius};
use values::computed::border::{BorderCornerRadius, BorderRadius};
use values::computed::length::LengthOrPercentage;
use values::computed::motion::OffsetPath;
use values::computed::position;
use values::computed::url::ComputedUrl;
use values::generics::basic_shape::{BasicShape as GenericBasicShape, InsetRect, Polygon};
@ -670,7 +669,6 @@ pub mod basic_shape {
Some(ShapeSource::Shape(shape, reference_box))
},
StyleShapeSourceType::URL | StyleShapeSourceType::Image => None,
StyleShapeSourceType::Path => None,
}
}
}
@ -712,29 +710,6 @@ pub mod basic_shape {
}
}
impl<'a> From<&'a StyleShapeSource> for OffsetPath {
fn from(other: &'a StyleShapeSource) -> Self {
use gecko_bindings::structs::StylePathCommand;
use values::specified::motion::{SVGPathData, PathCommand};
match other.mType {
StyleShapeSourceType::Path => {
let gecko_path = unsafe { &*other.__bindgen_anon_1.mSVGPath.as_ref().mPtr };
let result: Vec<PathCommand> =
gecko_path.mPath.iter().map(|gecko: &StylePathCommand| {
// unsafe: cbindgen ensures the representation is the same.
unsafe{ ::std::mem::transmute(*gecko) }
}).collect();
OffsetPath::Path(SVGPathData::new(result.into_boxed_slice()))
},
StyleShapeSourceType::None => OffsetPath::none(),
StyleShapeSourceType::Shape |
StyleShapeSourceType::Box |
StyleShapeSourceType::URL |
StyleShapeSourceType::Image => unreachable!("Unsupported offset-path type"),
}
}
}
impl<'a> From<&'a StyleBasicShape> for BasicShape {
fn from(other: &'a StyleBasicShape) -> Self {
match other.mType {

Просмотреть файл

@ -3053,7 +3053,7 @@ fn static_assert() {
scroll-snap-points-x scroll-snap-points-y
scroll-snap-type-x scroll-snap-type-y scroll-snap-coordinate
perspective-origin -moz-binding will-change
offset-path overscroll-behavior-x overscroll-behavior-y
overscroll-behavior-x overscroll-behavior-y
overflow-clip-box-inline overflow-clip-box-block
perspective-origin -moz-binding will-change
shape-outside contain touch-action translate
@ -3681,51 +3681,6 @@ fn static_assert() {
${impl_simple_copy("contain", "mContain")}
${impl_simple_type_with_conversion("touch_action")}
pub fn set_offset_path(&mut self, v: longhands::offset_path::computed_value::T) {
use gecko_bindings::bindings::{Gecko_NewStyleMotion, Gecko_NewStyleSVGPath};
use gecko_bindings::bindings::Gecko_SetStyleMotion;
use gecko_bindings::structs::StyleShapeSourceType;
use values::specified::OffsetPath;
let motion = unsafe { Gecko_NewStyleMotion().as_mut().unwrap() };
match v {
OffsetPath::None => motion.mOffsetPath.mType = StyleShapeSourceType::None,
OffsetPath::Path(servo_path) => {
motion.mOffsetPath.mType = StyleShapeSourceType::Path;
let gecko_path = unsafe {
let ref mut source = motion.mOffsetPath;
Gecko_NewStyleSVGPath(source);
&mut source.__bindgen_anon_1.mSVGPath.as_mut().mPtr.as_mut().unwrap().mPath
};
unsafe { gecko_path.set_len(servo_path.commands().len() as u32) };
debug_assert_eq!(gecko_path.len(), servo_path.commands().len());
for (servo, gecko) in servo_path.commands().iter().zip(gecko_path.iter_mut()) {
// unsafe: cbindgen ensures the representation is the same.
*gecko = unsafe { transmute(*servo) };
}
},
}
unsafe { Gecko_SetStyleMotion(&mut self.gecko.mMotion, motion) };
}
pub fn clone_offset_path(&self) -> longhands::offset_path::computed_value::T {
use values::specified::OffsetPath;
match unsafe { self.gecko.mMotion.mPtr.as_ref() } {
None => OffsetPath::none(),
Some(v) => (&v.mOffsetPath).into()
}
}
pub fn copy_offset_path_from(&mut self, other: &Self) {
use gecko_bindings::bindings::Gecko_CopyStyleMotions;
unsafe { Gecko_CopyStyleMotions(&mut self.gecko.mMotion, other.gecko.mMotion.mPtr) };
}
pub fn reset_offset_path(&mut self, other: &Self) {
self.copy_offset_path_from(other);
}
</%self:impl_trait>
<%def name="simple_image_array_property(name, shorthand, field_name)">

Просмотреть файл

@ -356,17 +356,6 @@ ${helpers.predefined_type(
servo_restyle_damage="reflow_out_of_flow"
)}
// Motion Path Module Level 1
${helpers.predefined_type(
"offset-path",
"OffsetPath",
"computed::OffsetPath::none()",
animation_value_type="none",
gecko_pref="layout.css.motion-path.enabled",
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
spec="https://drafts.fxtf.org/motion-1/#offset-path-property"
)}
// CSSOM View Module
// https://www.w3.org/TR/cssom-view-1/
${helpers.single_keyword("scroll-behavior",

Просмотреть файл

@ -65,7 +65,6 @@ pub use self::length::{NonNegativeLengthOrPercentage, NonNegativeLengthOrPercent
pub use self::list::Quotes;
#[cfg(feature = "gecko")]
pub use self::list::ListStyleType;
pub use self::motion::OffsetPath;
pub use self::outline::OutlineStyle;
pub use self::percentage::{Percentage, NonNegativePercentage};
pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, ZIndex};
@ -101,7 +100,6 @@ pub mod gecko;
pub mod image;
pub mod length;
pub mod list;
pub mod motion;
pub mod outline;
pub mod percentage;
pub mod position;

Просмотреть файл

@ -1,10 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Computed types for CSS values that are related to motion path.
/// A computed offset-path. The computed value is as specified value.
///
/// https://drafts.fxtf.org/motion-1/#offset-path-property
pub use values::specified::motion::OffsetPath as OffsetPath;

Просмотреть файл

@ -58,7 +58,6 @@ pub use self::length::{NonNegativeLengthOrPercentage, NonNegativeLengthOrPercent
pub use self::list::Quotes;
#[cfg(feature = "gecko")]
pub use self::list::ListStyleType;
pub use self::motion::OffsetPath;
pub use self::outline::OutlineStyle;
pub use self::rect::LengthOrNumberRect;
pub use self::resolution::Resolution;
@ -102,7 +101,6 @@ pub mod image;
pub mod length;
pub mod list;
pub mod outline;
pub mod motion;
pub mod percentage;
pub mod position;
pub mod rect;

Просмотреть файл

@ -1,558 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Specified types for CSS values that are related to motion path.
use cssparser::Parser;
use parser::{Parse, ParserContext};
use std::fmt::{self, Write};
use std::iter::Peekable;
use std::str::Chars;
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use style_traits::values::SequenceWriter;
use values::CSSFloat;
/// The offset-path value.
///
/// https://drafts.fxtf.org/motion-1/#offset-path-property
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
pub enum OffsetPath {
// We could merge SVGPathData into ShapeSource, so we could reuse them. However,
// we don't want to support other value for offset-path, so use SVGPathData only for now.
/// Path value for path(<string>).
#[css(function)]
Path(SVGPathData),
/// None value.
None,
// Bug 1186329: Implement ray(), <basic-shape>, <geometry-box>, and <url>.
}
impl OffsetPath {
/// Return None.
#[inline]
pub fn none() -> Self {
OffsetPath::None
}
}
impl Parse for OffsetPath {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>
) -> Result<Self, ParseError<'i>> {
// Parse none.
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
return Ok(OffsetPath::none());
}
// Parse possible functions.
let location = input.current_source_location();
let function = input.expect_function()?.clone();
input.parse_nested_block(move |i| {
match_ignore_ascii_case! { &function,
// Bug 1186329: Implement the parser for ray(), <basic-shape>, <geometry-box>,
// and <url>.
"path" => SVGPathData::parse(context, i).map(OffsetPath::Path),
_ => {
Err(location.new_custom_error(
StyleParseErrorKind::UnexpectedFunction(function.clone())
))
},
}
})
}
}
/// SVG Path parser.
struct PathParser<'a> {
chars: Peekable<Chars<'a>>,
path: Vec<PathCommand>,
}
macro_rules! parse_arguments {
(
$parser:ident,
$abs:ident,
$enum:ident,
[ $para:ident => $func:ident $(, $other_para:ident => $other_func:ident)* ]
) => {
{
loop {
let $para = $func(&mut $parser.chars)?;
$(
skip_comma_wsp(&mut $parser.chars);
let $other_para = $other_func(&mut $parser.chars)?;
)*
$parser.path.push(PathCommand::$enum { $para $(, $other_para)*, $abs });
// End of string or the next character is a possible new command.
if !skip_wsp(&mut $parser.chars) ||
$parser.chars.peek().map_or(true, |c| c.is_ascii_alphabetic()) {
break;
}
skip_comma_wsp(&mut $parser.chars);
}
Ok(())
}
}
}
impl<'a> PathParser<'a> {
/// Parse a sub-path.
fn parse_subpath(&mut self) -> Result<(), ()> {
// Handle "moveto" Command first. If there is no "moveto", this is not a valid sub-path
// (i.e. not a valid moveto-drawto-command-group).
self.parse_moveto()?;
// Handle other commands.
loop {
skip_wsp(&mut self.chars);
if self.chars.peek().map_or(true, |m| *m == 'M' || *m == 'm') {
break;
}
match self.chars.next() {
Some(command) => {
let abs = command.is_uppercase();
macro_rules! parse_command {
( $($($p:pat)|+ => $parse_func:ident,)* ) => {
match command {
$(
$($p)|+ => {
skip_wsp(&mut self.chars);
self.$parse_func(abs)?;
},
)*
_ => return Err(()),
}
}
}
parse_command!(
'Z' | 'z' => parse_closepath,
'L' | 'l' => parse_lineto,
'H' | 'h' => parse_h_lineto,
'V' | 'v' => parse_v_lineto,
'C' | 'c' => parse_curveto,
'S' | 's' => parse_smooth_curveto,
'Q' | 'q' => parse_quadratic_bezier_curveto,
'T' | 't' => parse_smooth_quadratic_bezier_curveto,
'A' | 'a' => parse_elliprical_arc,
);
},
_ => break, // no more commands.
}
}
Ok(())
}
/// Parse "moveto" command.
fn parse_moveto(&mut self) -> Result<(), ()> {
let command = match self.chars.next() {
Some(c) if c == 'M' || c == 'm' => c,
_ => return Err(()),
};
skip_wsp(&mut self.chars);
let point = parse_coord(&mut self.chars)?;
let absolute = command == 'M';
self.path.push(PathCommand::MoveTo { point, absolute } );
// End of string or the next character is a possible new command.
if !skip_wsp(&mut self.chars) ||
self.chars.peek().map_or(true, |c| c.is_ascii_alphabetic()) {
return Ok(());
}
skip_comma_wsp(&mut self.chars);
// If a moveto is followed by multiple pairs of coordinates, the subsequent
// pairs are treated as implicit lineto commands.
self.parse_lineto(absolute)
}
/// Parse "closepath" command.
fn parse_closepath(&mut self, _absolute: bool) -> Result<(), ()> {
self.path.push(PathCommand::ClosePath);
Ok(())
}
/// Parse "lineto" command.
fn parse_lineto(&mut self, absolute: bool) -> Result<(), ()> {
parse_arguments!(self, absolute, LineTo, [ point => parse_coord ])
}
/// Parse horizontal "lineto" command.
fn parse_h_lineto(&mut self, absolute: bool) -> Result<(), ()> {
parse_arguments!(self, absolute, HorizontalLineTo, [ x => parse_number ])
}
/// Parse vertical "lineto" command.
fn parse_v_lineto(&mut self, absolute: bool) -> Result<(), ()> {
parse_arguments!(self, absolute, VerticalLineTo, [ y => parse_number ])
}
/// Parse cubic Bézier curve command.
fn parse_curveto(&mut self, absolute: bool) -> Result<(), ()> {
parse_arguments!(self, absolute, CurveTo, [
control1 => parse_coord, control2 => parse_coord, point => parse_coord
])
}
/// Parse smooth "curveto" command.
fn parse_smooth_curveto(&mut self, absolute: bool) -> Result<(), ()> {
parse_arguments!(self, absolute, SmoothCurveTo, [
control2 => parse_coord, point => parse_coord
])
}
/// Parse quadratic Bézier curve command.
fn parse_quadratic_bezier_curveto(&mut self, absolute: bool) -> Result<(), ()> {
parse_arguments!(self, absolute, QuadBezierCurveTo, [
control1 => parse_coord, point => parse_coord
])
}
/// Parse smooth quadratic Bézier curveto command.
fn parse_smooth_quadratic_bezier_curveto(&mut self, absolute: bool) -> Result<(), ()> {
parse_arguments!(self, absolute, SmoothQuadBezierCurveTo, [ point => parse_coord ])
}
/// Parse elliptical arc curve command.
fn parse_elliprical_arc(&mut self, absolute: bool) -> Result<(), ()> {
// Parse a flag whose value is '0' or '1'; otherwise, return Err(()).
let parse_flag = |iter: &mut Peekable<Chars>| -> Result<bool, ()> {
let value = match iter.peek() {
Some(c) if *c == '0' || *c == '1' => *c == '1',
_ => return Err(()),
};
iter.next();
Ok(value)
};
parse_arguments!(self, absolute, EllipticalArc, [
rx => parse_number,
ry => parse_number,
angle => parse_number,
large_arc_flag => parse_flag,
sweep_flag => parse_flag,
point => parse_coord
])
}
}
/// The SVG path data.
///
/// https://www.w3.org/TR/SVG11/paths.html#PathData
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
pub struct SVGPathData(Box<[PathCommand]>);
impl SVGPathData {
/// Return SVGPathData by a slice of PathCommand.
#[inline]
pub fn new(cmd: Box<[PathCommand]>) -> Self {
debug_assert!(!cmd.is_empty());
SVGPathData(cmd)
}
/// Get the array of PathCommand.
#[inline]
pub fn commands(&self) -> &[PathCommand] {
debug_assert!(!self.0.is_empty());
&self.0
}
}
impl ToCss for SVGPathData {
#[inline]
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: fmt::Write
{
dest.write_char('"')?;
{
let mut writer = SequenceWriter::new(dest, " ");
for command in self.0.iter() {
writer.item(command)?;
}
}
dest.write_char('"')
}
}
impl Parse for SVGPathData {
// We cannot use cssparser::Parser to parse a SVG path string because the spec wants to make
// the SVG path string as compact as possible. (i.e. The whitespaces may be dropped.)
// e.g. "M100 200L100 200" is a valid SVG path string. If we use tokenizer, the first ident
// is "M100", instead of "M", and this is not correct. Therefore, we use a Peekable
// str::Char iterator to check each character.
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>
) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let path_string = input.expect_string()?.as_ref();
if path_string.is_empty() {
// Treat an empty string as invalid, so we will not set it.
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
// Parse the svg path string as multiple sub-paths.
let mut path_parser = PathParser {
chars: path_string.chars().peekable(),
path: Vec::new(),
};
while skip_wsp(&mut path_parser.chars) {
if path_parser.parse_subpath().is_err() {
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
}
Ok(SVGPathData::new(path_parser.path.into_boxed_slice()))
}
}
/// The SVG path command.
/// The fields of these commands are self-explanatory, so we skip the documents.
/// Note: the index of the control points, e.g. control1, control2, are mapping to the control
/// points of the Bézier curve in the spec.
///
/// https://www.w3.org/TR/SVG11/paths.html#PathData
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
#[allow(missing_docs)]
#[repr(C, u8)]
pub enum PathCommand {
/// The unknown type.
/// https://www.w3.org/TR/SVG/paths.html#__svg__SVGPathSeg__PATHSEG_UNKNOWN
Unknown,
/// The "moveto" command.
MoveTo { point: CoordPair, absolute: bool },
/// The "lineto" command.
LineTo { point: CoordPair, absolute: bool },
/// The horizontal "lineto" command.
HorizontalLineTo { x: CSSFloat, absolute: bool },
/// The vertical "lineto" command.
VerticalLineTo { y: CSSFloat, absolute: bool },
/// The cubic Bézier curve command.
CurveTo { control1: CoordPair, control2: CoordPair, point: CoordPair, absolute: bool },
/// The smooth curve command.
SmoothCurveTo { control2: CoordPair, point: CoordPair, absolute: bool },
/// The quadratic Bézier curve command.
QuadBezierCurveTo { control1: CoordPair, point: CoordPair, absolute: bool },
/// The smooth quadratic Bézier curve command.
SmoothQuadBezierCurveTo { point: CoordPair, absolute: bool },
/// The elliptical arc curve command.
EllipticalArc {
rx: CSSFloat,
ry: CSSFloat,
angle: CSSFloat,
large_arc_flag: bool,
sweep_flag: bool,
point: CoordPair,
absolute: bool
},
/// The "closepath" command.
ClosePath,
}
impl ToCss for PathCommand {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: fmt::Write
{
use self::PathCommand::*;
match *self {
Unknown => dest.write_str("X"),
ClosePath => dest.write_str("Z"),
MoveTo { point, absolute } => {
dest.write_char(if absolute { 'M' } else { 'm' })?;
dest.write_char(' ')?;
point.to_css(dest)
}
LineTo { point, absolute } => {
dest.write_char(if absolute { 'L' } else { 'l' })?;
dest.write_char(' ')?;
point.to_css(dest)
}
CurveTo { control1, control2, point, absolute } => {
dest.write_char(if absolute { 'C' } else { 'c' })?;
dest.write_char(' ')?;
control1.to_css(dest)?;
dest.write_char(' ')?;
control2.to_css(dest)?;
dest.write_char(' ')?;
point.to_css(dest)
},
QuadBezierCurveTo { control1, point, absolute } => {
dest.write_char(if absolute { 'Q' } else { 'q' })?;
dest.write_char(' ')?;
control1.to_css(dest)?;
dest.write_char(' ')?;
point.to_css(dest)
},
EllipticalArc { rx, ry, angle, large_arc_flag, sweep_flag, point, absolute } => {
dest.write_char(if absolute { 'A' } else { 'a' })?;
dest.write_char(' ')?;
rx.to_css(dest)?;
dest.write_char(' ')?;
ry.to_css(dest)?;
dest.write_char(' ')?;
angle.to_css(dest)?;
dest.write_char(' ')?;
(large_arc_flag as i32).to_css(dest)?;
dest.write_char(' ')?;
(sweep_flag as i32).to_css(dest)?;
dest.write_char(' ')?;
point.to_css(dest)
},
HorizontalLineTo { x, absolute } => {
dest.write_char(if absolute { 'H' } else { 'h' })?;
dest.write_char(' ')?;
x.to_css(dest)
},
VerticalLineTo { y, absolute } => {
dest.write_char(if absolute { 'V' } else { 'v' })?;
dest.write_char(' ')?;
y.to_css(dest)
},
SmoothCurveTo { control2, point, absolute } => {
dest.write_char(if absolute { 'S' } else { 's' })?;
dest.write_char(' ')?;
control2.to_css(dest)?;
dest.write_char(' ')?;
point.to_css(dest)
},
SmoothQuadBezierCurveTo { point, absolute } => {
dest.write_char(if absolute { 'T' } else { 't' })?;
dest.write_char(' ')?;
point.to_css(dest)
},
}
}
}
/// The path coord type.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
#[repr(C)]
pub struct CoordPair(CSSFloat, CSSFloat);
impl CoordPair {
/// Create a CoordPair.
#[inline]
pub fn new(x: CSSFloat, y: CSSFloat) -> Self {
CoordPair(x, y)
}
}
/// Parse a pair of numbers into CoordPair.
fn parse_coord(iter: &mut Peekable<Chars>) -> Result<CoordPair, ()> {
let x = parse_number(iter)?;
skip_comma_wsp(iter);
let y = parse_number(iter)?;
Ok(CoordPair::new(x, y))
}
/// This is a special version which parses the number for SVG Path. e.g. "M 0.6.5" should be parsed
/// as MoveTo with a coordinate of ("0.6", ".5"), instead of treating 0.6.5 as a non-valid floating
/// point number. In other words, the logic here is similar with that of
/// tokenizer::consume_numeric, which also consumes the number as many as possible, but here the
/// input is a Peekable and we only accept an integer of a floating point number.
///
/// The "number" syntax in https://www.w3.org/TR/SVG/paths.html#PathDataBNF
fn parse_number(iter: &mut Peekable<Chars>) -> Result<CSSFloat, ()> {
// 1. Check optional sign.
let sign = if iter.peek().map_or(false, |&sign: &char| sign == '+' || sign == '-') {
if iter.next().unwrap() == '-' { -1. } else { 1. }
} else {
1.
};
// 2. Check integer part.
let mut integral_part: f64 = 0.;
let got_dot = if !iter.peek().map_or(false, |&n: &char| n == '.') {
// If the first digit in integer part is neither a dot nor a digit, this is not a number.
if iter.peek().map_or(true, |n: &char| !n.is_ascii_digit()) {
return Err(());
}
while iter.peek().map_or(false, |n: &char| n.is_ascii_digit()) {
integral_part =
integral_part * 10. + iter.next().unwrap().to_digit(10).unwrap() as f64;
}
iter.peek().map_or(false, |&n: &char| n == '.')
} else {
true
};
// 3. Check fractional part.
let mut fractional_part: f64 = 0.;
if got_dot {
// Consume '.'.
iter.next();
// If the first digit in fractional part is not a digit, this is not a number.
if iter.peek().map_or(true, |n: &char| !n.is_ascii_digit()) {
return Err(());
}
let mut factor = 0.1;
while iter.peek().map_or(false, |n: &char| n.is_ascii_digit()) {
fractional_part += iter.next().unwrap().to_digit(10).unwrap() as f64 * factor;
factor *= 0.1;
}
}
let mut value = sign * (integral_part + fractional_part);
// 4. Check exp part. The segment name of SVG Path doesn't include 'E' or 'e', so it's ok to
// treat the numbers after 'E' or 'e' are in the exponential part.
if iter.peek().map_or(false, |&exp: &char| exp == 'E' || exp == 'e') {
// Consume 'E' or 'e'.
iter.next();
let exp_sign = if iter.peek().map_or(false, |&sign: &char| sign == '+' || sign == '-') {
if iter.next().unwrap() == '-' { -1. } else { 1. }
} else {
1.
};
let mut exp: f64 = 0.;
while iter.peek().map_or(false, |n: &char| n.is_ascii_digit()) {
exp = exp * 10. + iter.next().unwrap().to_digit(10).unwrap() as f64;
}
value *= f64::powf(10., exp * exp_sign);
}
if value.is_finite() {
Ok(value.min(::std::f32::MAX as f64).max(::std::f32::MIN as f64) as CSSFloat)
} else {
Err(())
}
}
/// Skip all svg whitespaces, and return true if |iter| hasn't finished.
#[inline]
fn skip_wsp(iter: &mut Peekable<Chars>) -> bool {
// Note: SVG 1.1 defines the whitespaces as \u{9}, \u{20}, \u{A}, \u{D}.
// However, SVG 2 has one extra whitespace: \u{C}.
// Therefore, we follow the newest spec for the definition of whitespace,
// i.e. \u{9}, \u{20}, \u{A}, \u{C}, \u{D}, by is_ascii_whitespace().
while iter.peek().map_or(false, |c: &char| c.is_ascii_whitespace()) {
iter.next();
}
iter.peek().is_some()
}
/// Skip all svg whitespaces and one comma, and return true if |iter| hasn't finished.
#[inline]
fn skip_comma_wsp(iter: &mut Peekable<Chars>) -> bool {
if !skip_wsp(iter) {
return false;
}
if *iter.peek().unwrap() != ',' {
return true;
}
iter.next();
skip_wsp(iter)
}

Просмотреть файл

@ -165103,21 +165103,9 @@
{}
]
],
"css/motion/offset-path-string-001.html": [
"css/motion/offset-path-string.html": [
[
"/css/motion/offset-path-string-001.html",
[
[
"/css/motion/offset-path-string-ref.html",
"=="
]
],
{}
]
],
"css/motion/offset-path-string-002.html": [
[
"/css/motion/offset-path-string-002.html",
"/css/motion/offset-path-string.html",
[
[
"/css/motion/offset-path-string-ref.html",
@ -568463,18 +568451,14 @@
"6c39e7b8f4cfafe05c07d166eb65570432912b7a",
"reftest"
],
"css/motion/offset-path-string-001.html": [
"79d957d82b8e3c603ed16598f461a805c90681dd",
"reftest"
],
"css/motion/offset-path-string-002.html": [
"0d2fcbbb661c2fe0e5b57ff780d78b2f8b6f627b",
"reftest"
],
"css/motion/offset-path-string-ref.html": [
"5c5ff5f6f2ddc4696f2d51266199fe052464d9e6",
"support"
],
"css/motion/offset-path-string.html": [
"79d957d82b8e3c603ed16598f461a805c90681dd",
"reftest"
],
"css/motion/offset-rotate-001.html": [
"55147698a7f2f02a57f0fe3adc8b33257d1e212f",
"reftest"
@ -568516,11 +568500,11 @@
"testharness"
],
"css/motion/parsing/offset-path-parsing-invalid.html": [
"7fbd06a508a322ac0969eb11c4299de50fd254e7",
"c0a32486922b4b1b482817f409571e1e6c4219f7",
"testharness"
],
"css/motion/parsing/offset-path-parsing-valid.html": [
"e7797686e4ac524ac9dc9f8525dbd5a24adeec29",
"c1e229e1a05a4c85845384ace9b884125f579415",
"testharness"
],
"css/motion/parsing/offset-position-parsing-invalid.html": [

Просмотреть файл

@ -1 +0,0 @@
prefs: [layout.css.motion-path.enabled:true]

Просмотреть файл

@ -1,4 +1,7 @@
[offset-path-interpolation-001.html]
["path('M 0 0 H 1 H 2')" and "path('M 0 0 H 3')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 0 0 H 1 H 2')" and "path('M 0 0 H 3')" at progress -1]
expected: FAIL
@ -17,6 +20,9 @@
[Animation between "path('M 0 0 H 1 H 2')" and "path('M 0 0 H 3')" at progress 2]
expected: FAIL
["path('M 1 2 L 3 4 Z')" and "none" are valid offset-path values]
expected: FAIL
[Animation between "path('M 1 2 L 3 4 Z')" and "none" at progress -1]
expected: FAIL
@ -26,6 +32,18 @@
[Animation between "path('M 1 2 L 3 4 Z')" and "none" at progress 0.125]
expected: FAIL
[Animation between "path('M 1 2 L 3 4 Z')" and "none" at progress 0.875]
expected: FAIL
[Animation between "path('M 1 2 L 3 4 Z')" and "none" at progress 1]
expected: FAIL
[Animation between "path('M 1 2 L 3 4 Z')" and "none" at progress 2]
expected: FAIL
["path('M 10 0 H 11')" and "path('M 20 0 V 2')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 10 0 H 11')" and "path('M 20 0 V 2')" at progress -1]
expected: FAIL
@ -44,6 +62,9 @@
[Animation between "path('M 10 0 H 11')" and "path('M 20 0 V 2')" at progress 2]
expected: FAIL
["path('M 1 2 L 4 6 Z')" and "path('M 1 2 H 4 V 6')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 1 2 L 4 6 Z')" and "path('M 1 2 H 4 V 6')" at progress -1]
expected: FAIL
@ -62,6 +83,9 @@
[Animation between "path('M 1 2 L 4 6 Z')" and "path('M 1 2 H 4 V 6')" at progress 2]
expected: FAIL
["path('M 0 0 Z')" and "path('M 0 0 Z')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 0 0 Z')" and "path('M 0 0 Z')" at progress -1]
expected: FAIL
@ -80,6 +104,9 @@
[Animation between "path('M 0 0 Z')" and "path('M 0 0 Z')" at progress 2]
expected: FAIL
["path('M 20 70')" and "path('M 100 30')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 20 70')" and "path('M 100 30')" at progress -1]
expected: FAIL
@ -98,6 +125,9 @@
[Animation between "path('M 20 70')" and "path('M 100 30')" at progress 2]
expected: FAIL
["path('m 20 70')" and "path('m 100 30')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 20 70')" and "path('m 100 30')" at progress -1]
expected: FAIL
@ -116,6 +146,9 @@
[Animation between "path('m 20 70')" and "path('m 100 30')" at progress 2]
expected: FAIL
["path('m 100 200 L 120 270')" and "path('m 100 200 L 200 230')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 100 200 L 120 270')" and "path('m 100 200 L 200 230')" at progress -1]
expected: FAIL
@ -134,6 +167,9 @@
[Animation between "path('m 100 200 L 120 270')" and "path('m 100 200 L 200 230')" at progress 2]
expected: FAIL
["path('m 100 200 l 20 70')" and "path('m 100 200 l 100 30')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 100 200 l 20 70')" and "path('m 100 200 l 100 30')" at progress -1]
expected: FAIL

Просмотреть файл

@ -1,4 +1,7 @@
[offset-path-interpolation-002.html]
["path('M 20 10 C 32 42 52 62 120 2200')" and "path('M 20 10 C 40 50 60 70 200 3000')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 20 10 C 32 42 52 62 120 2200')" and "path('M 20 10 C 40 50 60 70 200 3000')" at progress -1]
expected: FAIL
@ -17,6 +20,9 @@
[Animation between "path('M 20 10 C 32 42 52 62 120 2200')" and "path('M 20 10 C 40 50 60 70 200 3000')" at progress 2]
expected: FAIL
["path('m 20 10 c 12 32 32 52 100 2190')" and "path('m 20 10 c 20 40 40 60 180 2990')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 20 10 c 12 32 32 52 100 2190')" and "path('m 20 10 c 20 40 40 60 180 2990')" at progress -1]
expected: FAIL
@ -35,6 +41,9 @@
[Animation between "path('m 20 10 c 12 32 32 52 100 2190')" and "path('m 20 10 c 20 40 40 60 180 2990')" at progress 2]
expected: FAIL
["path('M 20 10 Q 32 42 120 2200')" and "path('M 20 10 Q 40 50 200 3000')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 20 10 Q 32 42 120 2200')" and "path('M 20 10 Q 40 50 200 3000')" at progress -1]
expected: FAIL
@ -53,6 +62,9 @@
[Animation between "path('M 20 10 Q 32 42 120 2200')" and "path('M 20 10 Q 40 50 200 3000')" at progress 2]
expected: FAIL
["path('m 20 10 q 12 32 100 2190')" and "path('m 20 10 q 20 40 180 2990')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 20 10 q 12 32 100 2190')" and "path('m 20 10 q 20 40 180 2990')" at progress -1]
expected: FAIL
@ -71,6 +83,9 @@
[Animation between "path('m 20 10 q 12 32 100 2190')" and "path('m 20 10 q 20 40 180 2990')" at progress 2]
expected: FAIL
["path('M 100 400 A 10 20 30 1 0 140 450')" and "path('M 300 200 A 50 60 70 0 1 380 290')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 100 400 A 10 20 30 1 0 140 450')" and "path('M 300 200 A 50 60 70 0 1 380 290')" at progress -1]
expected: FAIL
@ -89,6 +104,9 @@
[Animation between "path('M 100 400 A 10 20 30 1 0 140 450')" and "path('M 300 200 A 50 60 70 0 1 380 290')" at progress 2]
expected: FAIL
["path('m 100 400 a 10 20 30 1 0 40 50')" and "path('m 300 200 a 50 60 70 0 1 80 90')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 100 400 a 10 20 30 1 0 40 50')" and "path('m 300 200 a 50 60 70 0 1 80 90')" at progress -1]
expected: FAIL

Просмотреть файл

@ -1,4 +1,7 @@
[offset-path-interpolation-003.html]
["path('M 50 60 H 70')" and "path('M 10 140 H 270')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 50 60 H 70')" and "path('M 10 140 H 270')" at progress -1]
expected: FAIL
@ -17,6 +20,9 @@
[Animation between "path('M 50 60 H 70')" and "path('M 10 140 H 270')" at progress 2]
expected: FAIL
["path('m 50 60 h 20')" and "path('m 10 140 h 260')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 50 60 h 20')" and "path('m 10 140 h 260')" at progress -1]
expected: FAIL
@ -35,6 +41,9 @@
[Animation between "path('m 50 60 h 20')" and "path('m 10 140 h 260')" at progress 2]
expected: FAIL
["path('M 50 60 V 70')" and "path('M 10 140 V 270')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 50 60 V 70')" and "path('M 10 140 V 270')" at progress -1]
expected: FAIL
@ -53,6 +62,9 @@
[Animation between "path('M 50 60 V 70')" and "path('M 10 140 V 270')" at progress 2]
expected: FAIL
["path('m 50 60 v 10')" and "path('m 10 140 v 130')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 50 60 v 10')" and "path('m 10 140 v 130')" at progress -1]
expected: FAIL
@ -71,6 +83,9 @@
[Animation between "path('m 50 60 v 10')" and "path('m 10 140 v 130')" at progress 2]
expected: FAIL
["path('M 12 34 S 45 67 89 123')" and "path('M 20 26 S 61 51 113 99')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 12 34 S 45 67 89 123')" and "path('M 20 26 S 61 51 113 99')" at progress -1]
expected: FAIL
@ -89,6 +104,9 @@
[Animation between "path('M 12 34 S 45 67 89 123')" and "path('M 20 26 S 61 51 113 99')" at progress 2]
expected: FAIL
["path('m 12 34 s 33 33 77 89')" and "path('m 20 26 s 41 25 93 73')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 12 34 s 33 33 77 89')" and "path('m 20 26 s 41 25 93 73')" at progress -1]
expected: FAIL
@ -107,6 +125,9 @@
[Animation between "path('m 12 34 s 33 33 77 89')" and "path('m 20 26 s 41 25 93 73')" at progress 2]
expected: FAIL
["path('M 12 34 T 45 67')" and "path('M 20 26 T 61 51')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 12 34 T 45 67')" and "path('M 20 26 T 61 51')" at progress -1]
expected: FAIL
@ -125,6 +146,9 @@
[Animation between "path('M 12 34 T 45 67')" and "path('M 20 26 T 61 51')" at progress 2]
expected: FAIL
["path('m 12 34 t 33 33')" and "path('m 20 26 t 41 25')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 12 34 t 33 33')" and "path('m 20 26 t 41 25')" at progress -1]
expected: FAIL

Просмотреть файл

@ -1,4 +1,7 @@
[offset-path-interpolation-004.html]
["path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')" and "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 300 100 z')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')" and "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 300 100 z')" at progress -1]
expected: FAIL
@ -17,6 +20,9 @@
[Animation between "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')" and "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 300 100 z')" at progress 2]
expected: FAIL
["path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')" and "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 100 -100 z')" are valid offset-path values]
expected: FAIL
[Animation between "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')" and "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 100 -100 z')" at progress -1]
expected: FAIL
@ -35,6 +41,9 @@
[Animation between "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')" and "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 100 -100 z')" at progress 2]
expected: FAIL
["path('m 10 20 l 40 50 z l 40 60 z m 60 70 l 90 60 z t 70 130')" and "path('M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 10 20 l 40 50 z l 40 60 z m 60 70 l 90 60 z t 70 130')" and "path('M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220')" at progress -1]
expected: FAIL
@ -53,6 +62,9 @@
[Animation between "path('m 10 20 l 40 50 z l 40 60 z m 60 70 l 90 60 z t 70 130')" and "path('M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220')" at progress 2]
expected: FAIL
["path('m 10 20 c 40 50 30 60 80 70 c 120 130 170 140 110 160')" and "path('M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 10 20 c 40 50 30 60 80 70 c 120 130 170 140 110 160')" and "path('M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330')" at progress -1]
expected: FAIL
@ -71,6 +83,9 @@
[Animation between "path('m 10 20 c 40 50 30 60 80 70 c 120 130 170 140 110 160')" and "path('M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330')" at progress 2]
expected: FAIL
["path('m 10 20 q 30 60 40 50 q 110 80 90 80')" and "path('M 130 100 Q 120 160 130 150 Q 200 150 180 190')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 10 20 q 30 60 40 50 q 110 80 90 80')" and "path('M 130 100 Q 120 160 130 150 Q 200 150 180 190')" at progress -1]
expected: FAIL
@ -89,6 +104,9 @@
[Animation between "path('m 10 20 q 30 60 40 50 q 110 80 90 80')" and "path('M 130 100 Q 120 160 130 150 Q 200 150 180 190')" at progress 2]
expected: FAIL
["path('m 10 20 s 30 60 40 50 s 110 60 90 70')" and "path('M 130 140 S 120 160 130 150 S 200 170 140 180')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 10 20 s 30 60 40 50 s 110 60 90 70')" and "path('M 130 140 S 120 160 130 150 S 200 170 140 180')" at progress -1]
expected: FAIL
@ -107,6 +125,9 @@
[Animation between "path('m 10 20 s 30 60 40 50 s 110 60 90 70')" and "path('M 130 140 S 120 160 130 150 S 200 170 140 180')" at progress 2]
expected: FAIL
["path('m 10 20 h 30 v 60 h 10 v -10 l 110 60')" and "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 10 20 h 30 v 60 h 10 v -10 l 110 60')" and "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170')" at progress -1]
expected: FAIL
@ -125,6 +146,9 @@
[Animation between "path('m 10 20 h 30 v 60 h 10 v -10 l 110 60')" and "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170')" at progress 2]
expected: FAIL
["path('m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50')" and "path('M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80')" are valid offset-path values]
expected: FAIL
[Animation between "path('m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50')" and "path('M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80')" at progress -1]
expected: FAIL

Просмотреть файл

@ -32,9 +32,27 @@
[Animation between "ray(0deg closest-corner)" and "none" at progress 0.125]
expected: FAIL
[Animation between "ray(0deg closest-corner)" and "none" at progress 0.875]
expected: FAIL
[Animation between "ray(0deg closest-corner)" and "none" at progress 1]
expected: FAIL
[Animation between "ray(0deg closest-corner)" and "none" at progress 2]
expected: FAIL
["none" and "ray(20deg closest-side)" are valid offset-path values]
expected: FAIL
[Animation between "none" and "ray(20deg closest-side)" at progress -1]
expected: FAIL
[Animation between "none" and "ray(20deg closest-side)" at progress 0]
expected: FAIL
[Animation between "none" and "ray(20deg closest-side)" at progress 0.125]
expected: FAIL
[Animation between "none" and "ray(20deg closest-side)" at progress 0.875]
expected: FAIL

Просмотреть файл

@ -1,3 +0,0 @@
[offset-path-string-001.html]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1429299

Просмотреть файл

@ -0,0 +1,2 @@
[offset-path-string.html]
expected: FAIL

Просмотреть файл

@ -5,6 +5,12 @@
[Serialization should round-trip after setting e.style['offset-path'\] = "fill-box ellipse(50% 60%)"]
expected: FAIL
[e.style['offset-path'\] = "none" should set the property value]
expected: FAIL
[Serialization should round-trip after setting e.style['offset-path'\] = "none"]
expected: FAIL
[e.style['offset-path'\] = "ray(0rad closest-side)" should set the property value]
expected: FAIL
@ -38,6 +44,18 @@
[e.style['offset-path'\] = "ray(calc(180deg - 45deg) farthest-side)" should set the property value]
expected: FAIL
[e.style['offset-path'\] = "path('m 0 0 h -100')" should set the property value]
expected: FAIL
[Serialization should round-trip after setting e.style['offset-path'\] = "path('m 0 0 h -100')"]
expected: FAIL
[e.style['offset-path'\] = "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 300 300 Z')" should set the property value]
expected: FAIL
[Serialization should round-trip after setting e.style['offset-path'\] = "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 300 300 Z')"]
expected: FAIL
[e.style['offset-path'\] = "url(\\"http://www.example.com/index.html#polyline1\\")" should set the property value]
expected: FAIL

Просмотреть файл

@ -1,24 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>CSS Motion Path: path(string) paths</title>
<link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-path-property">
<link rel="match" href="offset-path-string-ref.html">
<meta name="assert" content="This tests that path(<string>) generates a rotation and translation.">
<style>
#target {
position: absolute;
left: 300px;
top: 0px;
width: 300px;
height: 200px;
background-color: lime;
transform-origin: 0px 0px;
offset-path: path('m 0 120 v 200');
}
</style>
</head>
<body>
<div id="target"></div>
</body>
</html>

Просмотреть файл

@ -14,7 +14,7 @@
<script>
// arc path segments must have at least 7 arguments.
// https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
test_invalid_value("offset-path", 'path("M 20 30 A 60 70 80")');
test_invalid_value("offset-path", "path('M 20 30 A 60 70 80')");
test_invalid_value("offset-path", "ray(0 sides)");
test_invalid_value("offset-path", "ray(0deg)");

Просмотреть файл

@ -21,8 +21,8 @@ test_valid_value("offset-path", "ray(270deg farthest-corner contain)");
test_valid_value("offset-path", "ray(-720deg sides)");
test_valid_value("offset-path", "ray(calc(180deg - 45deg) farthest-side)", "ray(calc(135deg) farthest-side)");
test_valid_value("offset-path", 'path("m 0 0 h -100")');
test_valid_value("offset-path", 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 300 300 Z")');
test_valid_value("offset-path", "path('m 0 0 h -100')");
test_valid_value("offset-path", "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 300 300 Z')");
test_valid_value("offset-path", 'url("http://www.example.com/index.html#polyline1")');