forked from mirrors/gecko-dev
		
	Bug 1823463 - Render clip-path:shape(). r=emilio
Update clip-path-shape-003.html and clip-path-shape-004.html because 1. Per SVG2 spec, we don't accept comma among commands, so I remove them. 2. Basically, these two tests want to test the result of `shape()` should be identical to the result of `path()`. However, I noticed the original tests which put a `clip-path:path()` with `position:absolutely` may have a fuzzy result if the path has some curves there. This may be caused by anti-alias together with absoultely positioned element (note: perhaps there are some floating point calculation in layout for this, so the final rendering coordinates may have some fractions). Therefore, I drop the absolutely positioned element, and just test that if the result of `shape()` is identical to the result of `path()`. Also, add two more tests for different reference-boxes together with the usage of `shape()` (to make sure we resolve percentage values properly). Differential Revision: https://phabricator.services.mozilla.com/D202884
This commit is contained in:
		
							parent
							
								
									6605350dc6
								
							
						
					
					
						commit
						86adb0bd63
					
				
					 19 changed files with 175 additions and 87 deletions
				
			
		|  | @ -556,11 +556,30 @@ already_AddRefed<Path> SVGPathData::BuildPathForMeasuring( | ||||||
|   return BuildPath(aPath, builder, StyleStrokeLinecap::Butt, 0); |   return BuildPath(aPath, builder, StyleStrokeLinecap::Butt, 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static inline StyleCSSFloat GetRotate(const StyleCSSFloat& aAngle) { | ||||||
|  |   return aAngle; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline StyleCSSFloat GetRotate(const StyleAngle& aAngle) { | ||||||
|  |   return aAngle.ToDegrees(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline StyleCSSFloat Resolve(const StyleCSSFloat& aValue, | ||||||
|  |                                     CSSCoord aBasis) { | ||||||
|  |   return aValue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline StyleCSSFloat Resolve(const LengthPercentage& aValue, | ||||||
|  |                                     CSSCoord aBasis) { | ||||||
|  |   return aValue.ResolveToCSSPixels(aBasis); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| template <typename Angle, typename LP> | template <typename Angle, typename LP> | ||||||
| static already_AddRefed<Path> BuildPathInternal( | static already_AddRefed<Path> BuildPathInternal( | ||||||
|     Span<const StyleGenericShapeCommand<Angle, LP>> aPath, |     Span<const StyleGenericShapeCommand<Angle, LP>> aPath, | ||||||
|     PathBuilder* aBuilder, StyleStrokeLinecap aStrokeLineCap, |     PathBuilder* aBuilder, StyleStrokeLinecap aStrokeLineCap, | ||||||
|     Float aStrokeWidth, const Point& aOffset, float aZoomFactor) { |     Float aStrokeWidth, const CSSSize& aPercentageBasis, const Point& aOffset, | ||||||
|  |     float aZoomFactor) { | ||||||
|   using Command = StyleGenericShapeCommand<Angle, LP>; |   using Command = StyleGenericShapeCommand<Angle, LP>; | ||||||
| 
 | 
 | ||||||
|   if (aPath.IsEmpty() || !aPath[0].IsMove()) { |   if (aPath.IsEmpty() || !aPath[0].IsMove()) { | ||||||
|  | @ -609,14 +628,14 @@ static already_AddRefed<Path> BuildPathInternal( | ||||||
|         break; |         break; | ||||||
|       case Command::Tag::Move: { |       case Command::Tag::Move: { | ||||||
|         maybeApproximateZeroLengthSubpathSquareCaps(prevSeg, seg); |         maybeApproximateZeroLengthSubpathSquareCaps(prevSeg, seg); | ||||||
|         const Point& p = cmd.move.point.ToGfxPoint(); |         const Point& p = cmd.move.point.ToGfxPoint(aPercentageBasis); | ||||||
|         pathStart = segEnd = cmd.move.by_to == StyleByTo::To ? p : segStart + p; |         pathStart = segEnd = cmd.move.by_to == StyleByTo::To ? p : segStart + p; | ||||||
|         aBuilder->MoveTo(scale(segEnd)); |         aBuilder->MoveTo(scale(segEnd)); | ||||||
|         subpathHasLength = false; |         subpathHasLength = false; | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|       case Command::Tag::Line: { |       case Command::Tag::Line: { | ||||||
|         const Point& p = cmd.line.point.ToGfxPoint(); |         const Point& p = cmd.line.point.ToGfxPoint(aPercentageBasis); | ||||||
|         segEnd = cmd.line.by_to == StyleByTo::To ? p : segStart + p; |         segEnd = cmd.line.by_to == StyleByTo::To ? p : segStart + p; | ||||||
|         if (segEnd != segStart) { |         if (segEnd != segStart) { | ||||||
|           subpathHasLength = true; |           subpathHasLength = true; | ||||||
|  | @ -625,9 +644,9 @@ static already_AddRefed<Path> BuildPathInternal( | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|       case Command::Tag::CubicCurve: |       case Command::Tag::CubicCurve: | ||||||
|         cp1 = cmd.cubic_curve.control1.ToGfxPoint(); |         cp1 = cmd.cubic_curve.control1.ToGfxPoint(aPercentageBasis); | ||||||
|         cp2 = cmd.cubic_curve.control2.ToGfxPoint(); |         cp2 = cmd.cubic_curve.control2.ToGfxPoint(aPercentageBasis); | ||||||
|         segEnd = cmd.cubic_curve.point.ToGfxPoint(); |         segEnd = cmd.cubic_curve.point.ToGfxPoint(aPercentageBasis); | ||||||
| 
 | 
 | ||||||
|         if (cmd.cubic_curve.by_to == StyleByTo::By) { |         if (cmd.cubic_curve.by_to == StyleByTo::By) { | ||||||
|           cp1 += segStart; |           cp1 += segStart; | ||||||
|  | @ -642,8 +661,8 @@ static already_AddRefed<Path> BuildPathInternal( | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|       case Command::Tag::QuadCurve: |       case Command::Tag::QuadCurve: | ||||||
|         cp1 = cmd.quad_curve.control1.ToGfxPoint(); |         cp1 = cmd.quad_curve.control1.ToGfxPoint(aPercentageBasis); | ||||||
|         segEnd = cmd.quad_curve.point.ToGfxPoint(); |         segEnd = cmd.quad_curve.point.ToGfxPoint(aPercentageBasis); | ||||||
| 
 | 
 | ||||||
|         if (cmd.quad_curve.by_to == StyleByTo::By) { |         if (cmd.quad_curve.by_to == StyleByTo::By) { | ||||||
|           cp1 += segStart; |           cp1 += segStart; | ||||||
|  | @ -662,8 +681,8 @@ static already_AddRefed<Path> BuildPathInternal( | ||||||
| 
 | 
 | ||||||
|       case Command::Tag::Arc: { |       case Command::Tag::Arc: { | ||||||
|         const auto& arc = cmd.arc; |         const auto& arc = cmd.arc; | ||||||
|         const Point& radii = arc.radii.ToGfxPoint(); |         const Point& radii = arc.radii.ToGfxPoint(aPercentageBasis); | ||||||
|         segEnd = arc.point.ToGfxPoint(); |         segEnd = arc.point.ToGfxPoint(aPercentageBasis); | ||||||
|         if (arc.by_to == StyleByTo::By) { |         if (arc.by_to == StyleByTo::By) { | ||||||
|           segEnd += segStart; |           segEnd += segStart; | ||||||
|         } |         } | ||||||
|  | @ -674,8 +693,9 @@ static already_AddRefed<Path> BuildPathInternal( | ||||||
|           } else { |           } else { | ||||||
|             const bool arc_is_large = arc.arc_size == StyleArcSize::Large; |             const bool arc_is_large = arc.arc_size == StyleArcSize::Large; | ||||||
|             const bool arc_is_cw = arc.arc_sweep == StyleArcSweep::Cw; |             const bool arc_is_cw = arc.arc_sweep == StyleArcSweep::Cw; | ||||||
|             SVGArcConverter converter(segStart, segEnd, radii, arc.rotate, |             SVGArcConverter converter(segStart, segEnd, radii, | ||||||
|                                       arc_is_large, arc_is_cw); |                                       GetRotate(arc.rotate), arc_is_large, | ||||||
|  |                                       arc_is_cw); | ||||||
|             while (converter.GetNextSegment(&cp1, &cp2, &segEnd)) { |             while (converter.GetNextSegment(&cp1, &cp2, &segEnd)) { | ||||||
|               aBuilder->BezierTo(scale(cp1), scale(cp2), scale(segEnd)); |               aBuilder->BezierTo(scale(cp1), scale(cp2), scale(segEnd)); | ||||||
|             } |             } | ||||||
|  | @ -683,11 +703,12 @@ static already_AddRefed<Path> BuildPathInternal( | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|       case Command::Tag::HLine: |       case Command::Tag::HLine: { | ||||||
|  |         const float x = Resolve(cmd.h_line.x, aPercentageBasis.width); | ||||||
|         if (cmd.h_line.by_to == StyleByTo::To) { |         if (cmd.h_line.by_to == StyleByTo::To) { | ||||||
|           segEnd = Point(cmd.h_line.x, segStart.y); |           segEnd = Point(x, segStart.y); | ||||||
|         } else { |         } else { | ||||||
|           segEnd = segStart + Point(cmd.h_line.x, 0.0f); |           segEnd = segStart + Point(x, 0.0f); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (segEnd != segStart) { |         if (segEnd != segStart) { | ||||||
|  | @ -695,12 +716,13 @@ static already_AddRefed<Path> BuildPathInternal( | ||||||
|           aBuilder->LineTo(scale(segEnd)); |           aBuilder->LineTo(scale(segEnd)); | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
| 
 |       } | ||||||
|       case Command::Tag::VLine: |       case Command::Tag::VLine: { | ||||||
|  |         const float y = Resolve(cmd.v_line.y, aPercentageBasis.height); | ||||||
|         if (cmd.v_line.by_to == StyleByTo::To) { |         if (cmd.v_line.by_to == StyleByTo::To) { | ||||||
|           segEnd = Point(segStart.x, cmd.v_line.y); |           segEnd = Point(segStart.x, y); | ||||||
|         } else { |         } else { | ||||||
|           segEnd = segStart + Point(0.0f, cmd.v_line.y); |           segEnd = segStart + Point(0.0f, y); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (segEnd != segStart) { |         if (segEnd != segStart) { | ||||||
|  | @ -708,11 +730,11 @@ static already_AddRefed<Path> BuildPathInternal( | ||||||
|           aBuilder->LineTo(scale(segEnd)); |           aBuilder->LineTo(scale(segEnd)); | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
| 
 |       } | ||||||
|       case Command::Tag::SmoothCubic: |       case Command::Tag::SmoothCubic: | ||||||
|         cp1 = prevSeg && prevSeg->IsCubicType() ? segStart * 2 - cp2 : segStart; |         cp1 = prevSeg && prevSeg->IsCubicType() ? segStart * 2 - cp2 : segStart; | ||||||
|         cp2 = cmd.smooth_cubic.control2.ToGfxPoint(); |         cp2 = cmd.smooth_cubic.control2.ToGfxPoint(aPercentageBasis); | ||||||
|         segEnd = cmd.smooth_cubic.point.ToGfxPoint(); |         segEnd = cmd.smooth_cubic.point.ToGfxPoint(aPercentageBasis); | ||||||
| 
 | 
 | ||||||
|         if (cmd.smooth_cubic.by_to == StyleByTo::By) { |         if (cmd.smooth_cubic.by_to == StyleByTo::By) { | ||||||
|           cp2 += segStart; |           cp2 += segStart; | ||||||
|  | @ -731,7 +753,7 @@ static already_AddRefed<Path> BuildPathInternal( | ||||||
|         // Convert quadratic curve to cubic curve:
 |         // Convert quadratic curve to cubic curve:
 | ||||||
|         tcp1 = segStart + (cp1 - segStart) * 2 / 3; |         tcp1 = segStart + (cp1 - segStart) * 2 / 3; | ||||||
| 
 | 
 | ||||||
|         const Point& p = cmd.smooth_quad.point.ToGfxPoint(); |         const Point& p = cmd.smooth_quad.point.ToGfxPoint(aPercentageBasis); | ||||||
|         // set before setting tcp2!
 |         // set before setting tcp2!
 | ||||||
|         segEnd = cmd.smooth_quad.by_to == StyleByTo::To ? p : segStart + p; |         segEnd = cmd.smooth_quad.by_to == StyleByTo::To ? p : segStart + p; | ||||||
|         tcp2 = cp1 + (segEnd - cp1) / 3; |         tcp2 = cp1 + (segEnd - cp1) / 3; | ||||||
|  | @ -756,16 +778,22 @@ static already_AddRefed<Path> BuildPathInternal( | ||||||
|   return aBuilder->Finish(); |   return aBuilder->Finish(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 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 */ | /* static */ | ||||||
| already_AddRefed<Path> SVGPathData::BuildPath( | already_AddRefed<Path> SVGPathData::BuildPath( | ||||||
|     Span<const StylePathCommand> aPath, PathBuilder* aBuilder, |     Span<const StylePathCommand> aPath, PathBuilder* aBuilder, | ||||||
|     StyleStrokeLinecap aStrokeLineCap, Float aStrokeWidth, |     StyleStrokeLinecap aStrokeLineCap, Float aStrokeWidth, | ||||||
|     const gfx::Point& aOffset, float aZoomFactor) { |     const CSSSize& aBasis, const gfx::Point& aOffset, float aZoomFactor) { | ||||||
|   return BuildPathInternal(aPath, aBuilder, aStrokeLineCap, aStrokeWidth, |   return BuildPathInternal(aPath, aBuilder, aStrokeLineCap, aStrokeWidth, | ||||||
|                            aOffset, aZoomFactor); |                            aBasis, aOffset, aZoomFactor); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* static */ | ||||||
|  | already_AddRefed<Path> SVGPathData::BuildPath( | ||||||
|  |     Span<const StyleShapeCommand> aShape, PathBuilder* aBuilder, | ||||||
|  |     StyleStrokeLinecap aStrokeLineCap, Float aStrokeWidth, | ||||||
|  |     const CSSSize& aBasis, const gfx::Point& aOffset, float aZoomFactor) { | ||||||
|  |   return BuildPathInternal(aShape, aBuilder, aStrokeLineCap, aStrokeWidth, | ||||||
|  |                            aBasis, aOffset, aZoomFactor); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static double AngleOfVector(const Point& aVector) { | static double AngleOfVector(const Point& aVector) { | ||||||
|  |  | ||||||
|  | @ -190,14 +190,22 @@ class SVGPathData { | ||||||
|       Span<const StylePathCommand> aPath); |       Span<const StylePathCommand> aPath); | ||||||
| 
 | 
 | ||||||
|   /**
 |   /**
 | ||||||
|    * This function tries to build the path from an array of StylePathCommand, |    * This function tries to build the path from an array of GenericShapeCommand, | ||||||
|    * which is generated by cbindgen from Rust (see ServoStyleConsts.h). |    * which is generated by cbindgen from Rust (see ServoStyleConsts.h). | ||||||
|    * Basically, this is a variant of the above BuildPath() functions. |    * Basically, this is a variant of the above BuildPath() functions. | ||||||
|  |    * Note: |StylePathCommand| doesn't accept percentage values, so its |aBasis| | ||||||
|  |    * is empty by default. | ||||||
|    */ |    */ | ||||||
|   static already_AddRefed<Path> BuildPath( |   static already_AddRefed<Path> BuildPath( | ||||||
|       Span<const StylePathCommand> aPath, PathBuilder* aBuilder, |       Span<const StylePathCommand> aPath, PathBuilder* aBuilder, | ||||||
|       StyleStrokeLinecap aStrokeLineCap, Float aStrokeWidth, |       StyleStrokeLinecap aStrokeLineCap, Float aStrokeWidth, | ||||||
|       const gfx::Point& aOffset = gfx::Point(), float aZoomFactor = 1.0); |       const CSSSize& aBasis = {}, const gfx::Point& aOffset = gfx::Point(), | ||||||
|  |       float aZoomFactor = 1.0); | ||||||
|  |   static already_AddRefed<Path> BuildPath( | ||||||
|  |       Span<const StyleShapeCommand> aShape, PathBuilder* aBuilder, | ||||||
|  |       StyleStrokeLinecap aStrokeLineCap, Float aStrokeWidth, | ||||||
|  |       const CSSSize& aBasis, const gfx::Point& aOffset = gfx::Point(), | ||||||
|  |       float aZoomFactor = 1.0); | ||||||
| 
 | 
 | ||||||
|   const_iterator begin() const { return mData.Elements(); } |   const_iterator begin() const { return mData.Elements(); } | ||||||
|   const_iterator end() const { return mData.Elements() + mData.Length(); } |   const_iterator end() const { return mData.Elements() + mData.Length(); } | ||||||
|  |  | ||||||
|  | @ -1202,10 +1202,19 @@ inline nsRect StyleZoom::Unzoom(const nsRect& aValue) const { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <> | template <> | ||||||
| inline gfx::Point StyleCoordinatePair<StyleCSSFloat>::ToGfxPoint() const { | inline gfx::Point StyleCoordinatePair<StyleCSSFloat>::ToGfxPoint( | ||||||
|  |     const CSSSize* aBasis) const { | ||||||
|   return gfx::Point(x, y); |   return gfx::Point(x, y); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template <> | ||||||
|  | inline gfx::Point StyleCoordinatePair<LengthPercentage>::ToGfxPoint( | ||||||
|  |     const CSSSize* aBasis) const { | ||||||
|  |   MOZ_ASSERT(aBasis); | ||||||
|  |   return gfx::Point(x.ResolveToCSSPixels(aBasis->Width()), | ||||||
|  |                     y.ResolveToCSSPixels(aBasis->Height())); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| }  // namespace mozilla
 | }  // namespace mozilla
 | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -66,7 +66,7 @@ bool CSSClipPathInstance::HitTestBasicShapeOrPathClip(nsIFrame* aFrame, | ||||||
|   RefPtr<Path> path = instance.CreateClipPath( |   RefPtr<Path> path = instance.CreateClipPath( | ||||||
|       drawTarget, SVGUtils::GetCSSPxToDevPxMatrix(aFrame)); |       drawTarget, SVGUtils::GetCSSPxToDevPxMatrix(aFrame)); | ||||||
|   float pixelRatio = float(AppUnitsPerCSSPixel()) / |   float pixelRatio = float(AppUnitsPerCSSPixel()) / | ||||||
|                      aFrame->PresContext()->AppUnitsPerDevPixel(); |                      float(aFrame->PresContext()->AppUnitsPerDevPixel()); | ||||||
|   return path && path->ContainsPoint(ToPoint(aPoint) * pixelRatio, Matrix()); |   return path && path->ContainsPoint(ToPoint(aPoint) * pixelRatio, Matrix()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -124,8 +124,7 @@ already_AddRefed<Path> CSSClipPathInstance::CreateClipPath( | ||||||
|     case StyleBasicShape::Tag::Path: |     case StyleBasicShape::Tag::Path: | ||||||
|       return CreateClipPathPath(aDrawTarget, r); |       return CreateClipPathPath(aDrawTarget, r); | ||||||
|     case StyleBasicShape::Tag::Shape: |     case StyleBasicShape::Tag::Shape: | ||||||
|       // TODO: Support shape() in this patch series.
 |       return CreateClipPathShape(aDrawTarget, r); | ||||||
|       return nullptr; |  | ||||||
|     default: |     default: | ||||||
|       MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected shape type"); |       MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected shape type"); | ||||||
|   } |   } | ||||||
|  | @ -183,13 +182,36 @@ already_AddRefed<Path> CSSClipPathInstance::CreateClipPathPath( | ||||||
|   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder( |   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder( | ||||||
|       path.fill == StyleFillRule::Nonzero ? FillRule::FILL_WINDING |       path.fill == StyleFillRule::Nonzero ? FillRule::FILL_WINDING | ||||||
|                                           : FillRule::FILL_EVEN_ODD); |                                           : FillRule::FILL_EVEN_ODD); | ||||||
|   nscoord appUnitsPerDevPixel = |   const nscoord appUnitsPerDevPixel = | ||||||
|       mTargetFrame->PresContext()->AppUnitsPerDevPixel(); |       mTargetFrame->PresContext()->AppUnitsPerDevPixel(); | ||||||
|   float scale = float(AppUnitsPerCSSPixel()) / appUnitsPerDevPixel; |   const Point offset = | ||||||
|   Point offset = Point(aRefBox.x, aRefBox.y) / appUnitsPerDevPixel; |       LayoutDevicePoint::FromAppUnits(aRefBox.TopLeft(), appUnitsPerDevPixel) | ||||||
|  |           .ToUnknownPoint(); | ||||||
|  |   const float scale = float(AppUnitsPerCSSPixel()) / float(appUnitsPerDevPixel); | ||||||
| 
 | 
 | ||||||
|   return SVGPathData::BuildPath(path.path._0.AsSpan(), builder, |   return SVGPathData::BuildPath(path.path._0.AsSpan(), builder, | ||||||
|                                 StyleStrokeLinecap::Butt, 0.0, offset, scale); |                                 StyleStrokeLinecap::Butt, 0.0, {}, offset, | ||||||
|  |                                 scale); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | already_AddRefed<Path> CSSClipPathInstance::CreateClipPathShape( | ||||||
|  |     DrawTarget* aDrawTarget, const nsRect& aRefBox) { | ||||||
|  |   const auto& shape = mClipPathStyle.AsShape()._0->AsShape(); | ||||||
|  | 
 | ||||||
|  |   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder( | ||||||
|  |       shape.fill == StyleFillRule::Nonzero ? FillRule::FILL_WINDING | ||||||
|  |                                            : FillRule::FILL_EVEN_ODD); | ||||||
|  |   const nscoord appUnitsPerDevPixel = | ||||||
|  |       mTargetFrame->PresContext()->AppUnitsPerDevPixel(); | ||||||
|  |   const CSSSize basis = CSSSize::FromAppUnits(aRefBox.Size()); | ||||||
|  |   const Point offset = | ||||||
|  |       LayoutDevicePoint::FromAppUnits(aRefBox.TopLeft(), appUnitsPerDevPixel) | ||||||
|  |           .ToUnknownPoint(); | ||||||
|  |   const float scale = float(AppUnitsPerCSSPixel()) / float(appUnitsPerDevPixel); | ||||||
|  | 
 | ||||||
|  |   return SVGPathData::BuildPath(shape.commands.AsSpan(), builder, | ||||||
|  |                                 StyleStrokeLinecap::Butt, 0.0, basis, offset, | ||||||
|  |                                 scale); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| }  // namespace mozilla
 | }  // namespace mozilla
 | ||||||
|  |  | ||||||
|  | @ -58,6 +58,9 @@ class MOZ_STACK_CLASS CSSClipPathInstance { | ||||||
|   already_AddRefed<Path> CreateClipPathPath(DrawTarget* aDrawTarget, |   already_AddRefed<Path> CreateClipPathPath(DrawTarget* aDrawTarget, | ||||||
|                                             const nsRect& aRefBox); |                                             const nsRect& aRefBox); | ||||||
| 
 | 
 | ||||||
|  |   already_AddRefed<Path> CreateClipPathShape(DrawTarget* aDrawTarget, | ||||||
|  |                                              const nsRect& aRefBox); | ||||||
|  | 
 | ||||||
|   /**
 |   /**
 | ||||||
|    * The frame for the element that is currently being clipped. |    * The frame for the element that is currently being clipped. | ||||||
|    */ |    */ | ||||||
|  |  | ||||||
|  | @ -214,6 +214,7 @@ include = [ | ||||||
|   "BasicShape", |   "BasicShape", | ||||||
|   "InsetRect", |   "InsetRect", | ||||||
|   "ShapeRadius", |   "ShapeRadius", | ||||||
|  |   "ShapeCommand", | ||||||
|   "ArcSlice", |   "ArcSlice", | ||||||
|   "ForgottenArcSlicePtr", |   "ForgottenArcSlicePtr", | ||||||
|   "HeaderWithLength", |   "HeaderWithLength", | ||||||
|  | @ -758,7 +759,10 @@ renaming_overrides_prefixing = true | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
| "CoordinatePair" = """ | "CoordinatePair" = """ | ||||||
|   inline gfx::Point ToGfxPoint() const; |   inline gfx::Point ToGfxPoint(const CSSSize* aBasis = nullptr) const; | ||||||
|  |   gfx::Point ToGfxPoint(const CSSSize& aBasis) const { | ||||||
|  |     return ToGfxPoint(&aBasis); | ||||||
|  |   }; | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
| "TextOverflow" = """ | "TextOverflow" = """ | ||||||
|  |  | ||||||
|  | @ -1,2 +0,0 @@ | ||||||
| [clip-path-shape-interpolation-001.html] |  | ||||||
|   expected: FAIL |  | ||||||
|  | @ -1,2 +0,0 @@ | ||||||
| [clip-path-shape-interpolation-002.html] |  | ||||||
|   expected: FAIL |  | ||||||
|  | @ -1,2 +0,0 @@ | ||||||
| [clip-path-shape-001.html] |  | ||||||
|   expected: FAIL |  | ||||||
|  | @ -1,2 +0,0 @@ | ||||||
| [clip-path-shape-002-units.html] |  | ||||||
|   expected: FAIL |  | ||||||
|  | @ -1,2 +0,0 @@ | ||||||
| [clip-path-shape-002.html] |  | ||||||
|   expected: FAIL |  | ||||||
|  | @ -1,2 +0,0 @@ | ||||||
| [clip-path-shape-003.html] |  | ||||||
|   expected: FAIL |  | ||||||
|  | @ -1,2 +0,0 @@ | ||||||
| [clip-path-shape-004.html] |  | ||||||
|   expected: FAIL |  | ||||||
|  | @ -8,15 +8,6 @@ | ||||||
| 	'shape()' for clipping. Test curves."> | 	'shape()' for clipping. Test curves."> | ||||||
| </head> | </head> | ||||||
| <style> | <style> | ||||||
|   div { |  | ||||||
|     width: 100px; |  | ||||||
|     height: 100px; |  | ||||||
|   } |  | ||||||
|   #ref { |  | ||||||
|     clip-path: path(nonzero, "M 10 10, Q 40 0 60 20, T 90 0, c 10 40 20 20 -20 60, s -10 70 -40 -10"); |  | ||||||
|     background-color: red; |  | ||||||
|     position: absolute; |  | ||||||
|   } |  | ||||||
|   #rect { |   #rect { | ||||||
|     width: 100px; |     width: 100px; | ||||||
|     height: 100px; |     height: 100px; | ||||||
|  | @ -29,8 +20,6 @@ | ||||||
|   } |   } | ||||||
| </style> | </style> | ||||||
| <body> | <body> | ||||||
|   <p>You should see no red.</p> |  | ||||||
|   <div id="ref"></div> |  | ||||||
|   <div id="rect"></div> |   <div id="rect"></div> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -8,15 +8,6 @@ | ||||||
| 	'shape()' for clipping. Test arcs."> | 	'shape()' for clipping. Test arcs."> | ||||||
| </head> | </head> | ||||||
| <style> | <style> | ||||||
|   div { |  | ||||||
|     width: 100px; |  | ||||||
|     height: 100px; |  | ||||||
|   } |  | ||||||
|   #ref { |  | ||||||
|     clip-path: path(nonzero, "M 20 20 A 25 12 0 0 1 80 20, a 33 33 120 1 1 -40 50, A 20 25 0 0 0 20 20"); |  | ||||||
|     background-color: red; |  | ||||||
|     position: absolute; |  | ||||||
|   } |  | ||||||
|   #rect { |   #rect { | ||||||
|     width: 100px; |     width: 100px; | ||||||
|     height: 100px; |     height: 100px; | ||||||
|  | @ -28,8 +19,6 @@ | ||||||
|   } |   } | ||||||
| </style> | </style> | ||||||
| <body> | <body> | ||||||
|   <p>You should see no red.</p> |  | ||||||
|   <div id="ref"></div> |  | ||||||
|   <div id="rect"></div> |   <div id="rect"></div> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,29 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <html> | ||||||
|  | <head> | ||||||
|  |   <title>CSS Masking: Test clip-path property and shape function with padding-box</title> | ||||||
|  |   <link rel="help" href="https://drafts.csswg.org/css-shapes-2/#funcdef-shape"> | ||||||
|  |   <link rel="match" href="reference/clip-path-path-001-ref.html"> | ||||||
|  |   <meta name="assert" content="The clip-path property takes the basic shape | ||||||
|  | 	'shape()' for clipping. Test the usage of the reference box. On pass you | ||||||
|  |     should see a green square."> | ||||||
|  | </head> | ||||||
|  | <style> | ||||||
|  |   #rect { | ||||||
|  |     /* The size of the padding-box is 100x100. */ | ||||||
|  |     width: 120px; | ||||||
|  |     height: 120px; | ||||||
|  |     padding: 10px; | ||||||
|  |     border: 10px solid red; | ||||||
|  |     box-sizing: border-box; | ||||||
|  |     background-color: green; | ||||||
|  |     clip-path: shape(from 0px 0px, | ||||||
|  |                      hline by 80px, vline by 80%, hline by -80%, close) | ||||||
|  |                padding-box; | ||||||
|  |   } | ||||||
|  | </style> | ||||||
|  | <body> | ||||||
|  |   <p>The test passes if there are a green filled rect.</p> | ||||||
|  |   <div id="rect"></div> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,29 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <html> | ||||||
|  | <head> | ||||||
|  |   <title>CSS Masking: Test clip-path property and shape function with content-box</title> | ||||||
|  |   <link rel="help" href="https://drafts.csswg.org/css-shapes-2/#funcdef-shape"> | ||||||
|  |   <link rel="match" href="reference/clip-path-path-001-ref.html"> | ||||||
|  |   <meta name="assert" content="The clip-path property takes the basic shape | ||||||
|  | 	'shape()' for clipping. Test the usage of the reference box. On pass you | ||||||
|  |     should see a green square."> | ||||||
|  | </head> | ||||||
|  | <style> | ||||||
|  |   #rect { | ||||||
|  |     width: 140px; | ||||||
|  |     height: 140px; | ||||||
|  |     padding: 10px; | ||||||
|  |     border: 10px solid red; | ||||||
|  |     box-sizing: border-box; | ||||||
|  |     background-color: green; | ||||||
|  |     /* The size of the content-box is 100x100. */ | ||||||
|  |     clip-path: shape(from -10px -10%, | ||||||
|  |                      hline by 80px, vline by 80%, hline by -80%, close) | ||||||
|  |                content-box; | ||||||
|  |   } | ||||||
|  | </style> | ||||||
|  | <body> | ||||||
|  |   <p>The test passes if there are a green filled rect.</p> | ||||||
|  |   <div id="rect"></div> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -5,18 +5,14 @@ | ||||||
|   <link rel="help" href="https://drafts.csswg.org/css-shapes-2/#funcdef-shape"> |   <link rel="help" href="https://drafts.csswg.org/css-shapes-2/#funcdef-shape"> | ||||||
| </head> | </head> | ||||||
| <style> | <style> | ||||||
|   div { |   #ref { | ||||||
|     width: 100px; |     width: 100px; | ||||||
|     height: 100px; |     height: 100px; | ||||||
|   } |  | ||||||
|   #ref { |  | ||||||
|     background-color: green; |     background-color: green; | ||||||
|     clip-path: path(nonzero, "M 10 10, Q 40 0 60 20, T 90 0, c 10 40 20 20 -20 60, s -10 70 -40 -10"); |     clip-path: path(nonzero, "M 10 10 Q 40 0 60 20 T 90 0 c 10 40 20 20 -20 60 s -10 70 -40 -10"); | ||||||
|     position: absolute; |  | ||||||
|   } |   } | ||||||
| </style> | </style> | ||||||
| <body> | <body> | ||||||
|   <p>You should see no red.</p> |  | ||||||
|   <div id="ref"></div> |   <div id="ref"></div> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -5,18 +5,14 @@ | ||||||
|   <link rel="help" href="https://drafts.csswg.org/css-shapes-2/#funcdef-shape"> |   <link rel="help" href="https://drafts.csswg.org/css-shapes-2/#funcdef-shape"> | ||||||
| </head> | </head> | ||||||
| <style> | <style> | ||||||
|   div { |   #ref { | ||||||
|     width: 100px; |     width: 100px; | ||||||
|     height: 100px; |     height: 100px; | ||||||
|   } |  | ||||||
|   #ref { |  | ||||||
|     background-color: green; |     background-color: green; | ||||||
|     clip-path: path(nonzero, "M 20 20 A 25 12 0 0 1 80 20, a 33 33 120 1 1 -40 50, A 20 25 0 0 0 20 20"); |     clip-path: path(nonzero, "M 20 20 A 25 12 0 0 1 80 20 a 33 33 120 1 1 -40 50 A 20 25 0 0 0 20 20"); | ||||||
|     position: absolute; |  | ||||||
|   } |   } | ||||||
| </style> | </style> | ||||||
| <body> | <body> | ||||||
|   <p>You should see no red.</p> |  | ||||||
|   <div id="ref"></div> |   <div id="ref"></div> | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Boris Chiou
						Boris Chiou