mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1246764 - Part 3: Layout part for |clip-path: path()|. r=jwatt
Create clip-path for the path function and reuse some APIs in nsCSSClipPathInstance, so we don't have to update the code flow. Differential Revision: https://phabricator.services.mozilla.com/D3635
This commit is contained in:
parent
a1909a88ff
commit
7ba34b6df6
@ -560,7 +560,8 @@ SVGPathData::BuildPathForMeasuring() const
|
||||
SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
PathBuilder* aBuilder,
|
||||
uint8_t aStrokeLineCap,
|
||||
Float aStrokeWidth)
|
||||
Float aStrokeWidth,
|
||||
float aZoomFactor)
|
||||
{
|
||||
if (aPath.IsEmpty() || !aPath[0].IsMoveTo()) {
|
||||
return nullptr; // paths without an initial moveto are invalid
|
||||
@ -592,6 +593,10 @@ SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
Point cp1, cp2; // previous bezier's control points
|
||||
Point tcp1, tcp2; // temporaries
|
||||
|
||||
auto scale = [aZoomFactor](const Point& p) {
|
||||
return Point(p.x * aZoomFactor, p.y * aZoomFactor);
|
||||
};
|
||||
|
||||
// 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.
|
||||
@ -610,7 +615,7 @@ SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
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);
|
||||
aBuilder->MoveTo(scale(segEnd));
|
||||
subpathHasLength = false;
|
||||
break;
|
||||
}
|
||||
@ -619,7 +624,7 @@ SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
segEnd = cmd.line_to.absolute ? p : segStart + p;
|
||||
if (segEnd != segStart) {
|
||||
subpathHasLength = true;
|
||||
aBuilder->LineTo(segEnd);
|
||||
aBuilder->LineTo(scale(segEnd));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -636,7 +641,7 @@ SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
|
||||
if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
|
||||
subpathHasLength = true;
|
||||
aBuilder->BezierTo(cp1, cp2, segEnd);
|
||||
aBuilder->BezierTo(scale(cp1), scale(cp2), scale(segEnd));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -655,7 +660,7 @@ SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
|
||||
if (segEnd != segStart || segEnd != cp1) {
|
||||
subpathHasLength = true;
|
||||
aBuilder->BezierTo(tcp1, tcp2, segEnd);
|
||||
aBuilder->BezierTo(scale(tcp1), scale(tcp2), scale(segEnd));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -669,12 +674,12 @@ SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
if (segEnd != segStart) {
|
||||
subpathHasLength = true;
|
||||
if (radii.x == 0.0f || radii.y == 0.0f) {
|
||||
aBuilder->LineTo(segEnd);
|
||||
aBuilder->LineTo(scale(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);
|
||||
aBuilder->BezierTo(scale(cp1), scale(cp2), scale(segEnd));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -689,7 +694,7 @@ SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
|
||||
if (segEnd != segStart) {
|
||||
subpathHasLength = true;
|
||||
aBuilder->LineTo(segEnd);
|
||||
aBuilder->LineTo(scale(segEnd));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -702,7 +707,7 @@ SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
|
||||
if (segEnd != segStart) {
|
||||
subpathHasLength = true;
|
||||
aBuilder->LineTo(segEnd);
|
||||
aBuilder->LineTo(scale(segEnd));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -718,7 +723,7 @@ SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
|
||||
if (segEnd != segStart || segEnd != cp1 || segEnd != cp2) {
|
||||
subpathHasLength = true;
|
||||
aBuilder->BezierTo(cp1, cp2, segEnd);
|
||||
aBuilder->BezierTo(scale(cp1), scale(cp2), scale(segEnd));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -734,7 +739,7 @@ SVGPathData::BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
|
||||
if (segEnd != segStart || segEnd != cp1) {
|
||||
subpathHasLength = true;
|
||||
aBuilder->BezierTo(tcp1, tcp2, segEnd);
|
||||
aBuilder->BezierTo(scale(tcp1), scale(tcp2), scale(segEnd));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -178,7 +178,8 @@ public:
|
||||
BuildPath(const nsTArray<StylePathCommand>& aPath,
|
||||
PathBuilder* aBuilder,
|
||||
uint8_t aCapStyle,
|
||||
Float aStrokeWidth);
|
||||
Float aStrokeWidth,
|
||||
float aZoomFactor = 1.0);
|
||||
|
||||
const_iterator begin() const { return mData.Elements(); }
|
||||
const_iterator end() const { return mData.Elements() + mData.Length(); }
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "mozilla/dom/SVGPathData.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
#include "mozilla/ShapeUtils.h"
|
||||
@ -33,8 +34,9 @@ nsCSSClipPathInstance::ApplyBasicShapeClip(gfxContext& aContext,
|
||||
#ifdef DEBUG
|
||||
StyleShapeSourceType type = clipPathStyle.GetType();
|
||||
MOZ_ASSERT(type == StyleShapeSourceType::Shape ||
|
||||
type == StyleShapeSourceType::Box,
|
||||
"This function is used with basic-shape and geometry-box only.");
|
||||
type == StyleShapeSourceType::Box ||
|
||||
type == StyleShapeSourceType::Path,
|
||||
"This is used with basic-shape, geometry-box, and path() only");
|
||||
#endif
|
||||
|
||||
nsCSSClipPathInstance instance(aFrame, clipPathStyle);
|
||||
@ -69,11 +71,13 @@ nsCSSClipPathInstance::HitTestBasicShapeClip(nsIFrame* aFrame,
|
||||
}
|
||||
|
||||
/* static */ Rect
|
||||
nsCSSClipPathInstance::GetBoundingRectForBasicShapeClip(nsIFrame* aFrame,
|
||||
nsCSSClipPathInstance::GetBoundingRectForBasicShapeClip(
|
||||
nsIFrame* aFrame,
|
||||
const StyleShapeSource& aClipPathStyle)
|
||||
{
|
||||
MOZ_ASSERT(aClipPathStyle.GetType() == StyleShapeSourceType::Shape ||
|
||||
aClipPathStyle.GetType() == StyleShapeSourceType::Box);
|
||||
aClipPathStyle.GetType() == StyleShapeSourceType::Box ||
|
||||
aClipPathStyle.GetType() == StyleShapeSourceType::Path);
|
||||
|
||||
nsCSSClipPathInstance instance(aFrame, aClipPathStyle);
|
||||
|
||||
@ -86,6 +90,10 @@ nsCSSClipPathInstance::GetBoundingRectForBasicShapeClip(nsIFrame* aFrame,
|
||||
already_AddRefed<Path>
|
||||
nsCSSClipPathInstance::CreateClipPath(DrawTarget* aDrawTarget)
|
||||
{
|
||||
if (mClipPathStyle.GetType() == StyleShapeSourceType::Path) {
|
||||
return CreateClipPathPath(aDrawTarget);
|
||||
}
|
||||
|
||||
nsRect r =
|
||||
nsLayoutUtils::ComputeGeometryBox(mTargetFrame,
|
||||
mClipPathStyle.GetReferenceBox());
|
||||
@ -213,3 +221,18 @@ nsCSSClipPathInstance::CreateClipPathInset(DrawTarget* aDrawTarget,
|
||||
}
|
||||
return builder->Finish();
|
||||
}
|
||||
|
||||
already_AddRefed<Path>
|
||||
nsCSSClipPathInstance::CreateClipPathPath(DrawTarget* aDrawTarget)
|
||||
{
|
||||
const StyleSVGPath* path = mClipPathStyle.GetPath();
|
||||
MOZ_ASSERT(path);
|
||||
|
||||
RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder(
|
||||
path->FillRule() == StyleFillRule::Nonzero ? FillRule::FILL_WINDING
|
||||
: FillRule::FILL_EVEN_ODD);
|
||||
float scale = float(AppUnitsPerCSSPixel()) /
|
||||
mTargetFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
return SVGPathData::BuildPath(
|
||||
path->Path(), builder, NS_STYLE_STROKE_LINECAP_BUTT, 0.0, scale);
|
||||
}
|
||||
|
@ -29,8 +29,10 @@ public:
|
||||
static bool HitTestBasicShapeClip(nsIFrame* aFrame,
|
||||
const gfxPoint& aPoint);
|
||||
|
||||
static Rect GetBoundingRectForBasicShapeClip(nsIFrame* aFrame,
|
||||
static Rect GetBoundingRectForBasicShapeClip(
|
||||
nsIFrame* aFrame,
|
||||
const StyleShapeSource& aClipPathStyle);
|
||||
|
||||
private:
|
||||
explicit nsCSSClipPathInstance(nsIFrame* aFrame,
|
||||
const StyleShapeSource aClipPathStyle)
|
||||
@ -53,6 +55,7 @@ private:
|
||||
already_AddRefed<Path> CreateClipPathInset(DrawTarget* aDrawTarget,
|
||||
const nsRect& aRefBox);
|
||||
|
||||
already_AddRefed<Path> CreateClipPathPath(DrawTarget* aDrawTarget);
|
||||
|
||||
/**
|
||||
* The frame for the element that is currently being clipped.
|
||||
|
@ -523,6 +523,7 @@ nsSVGUtils::DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity,
|
||||
break;
|
||||
case StyleShapeSourceType::Shape:
|
||||
case StyleShapeSourceType::Box:
|
||||
case StyleShapeSourceType::Path:
|
||||
aUsage.shouldApplyBasicShape = true;
|
||||
break;
|
||||
case StyleShapeSourceType::None:
|
||||
|
Loading…
Reference in New Issue
Block a user