* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkPathBuilder_DEFINED
#define SkPathBuilder_DEFINED
#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathIter.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSpan.h"
#include "include/core/SkTypes.h"
#include "include/private/SkPathRef.h"
#include "include/private/base/SkTArray.h"
#include <cstdint>
#include <optional>
#include <tuple>
class SkPathData;
class SkRRect;
struct SkPathRaw;
class SkString;
class SK_API SkPathBuilder {
public:
no weights. FillType is set to kWinding.
@return empty SkPathBuilder
*/
SkPathBuilder();
verbs, no SkPoint, and no weights.
@param fillType SkPathFillType to set on the SkPathBuilder.
@return empty SkPathBuilder
*/
explicit SkPathBuilder(SkPathFillType fillType);
Copies the FillType and replays all of the verbs from the SkPath into the SkPathBuilder.
@param path SkPath to copy
@return SkPathBuilder
*/
explicit SkPathBuilder(const SkPath& path);
SkPathBuilder(const SkPathBuilder&) = default;
~SkPathBuilder();
Copies the FillType and replays all of the verbs from the SkPath into the SkPathBuilder.
@param path SkPath to copy
@return SkPathBuilder
*/
SkPathBuilder& operator=(const SkPath&);
SkPathBuilder& operator=(const SkPathBuilder&) = default;
bool operator==(const SkPathBuilder&) const;
bool operator!=(const SkPathBuilder& o) const { return !(*this == o); }
@return current SkPathFillType setting
*/
SkPathFillType fillType() const { return fFillType; }
Returns (0, 0, 0, 0) if SkPathBuilder contains no points.
SkRect returned includes all SkPoint added to SkPathBuilder, including SkPoint associated
with kMove_Verb that define empty contours.
If any of the points are non-finite, returns {}.
@return bounds of all SkPoint in SkPoint array, or {}.
*/
std::optional<SkRect> computeFiniteBounds() const {
return SkRect::Bounds(fPts);
}
* segments, this computes the X/Y limits of the curve itself, not the curve's control
* point(s). For a polygon, this returns the same as computeFiniteBounds().
*/
std::optional<SkRect> computeTightBounds() const;
SkRect computeBounds() const {
if (auto bounds = this->computeFiniteBounds()) {
return *bounds;
}
return SkRect::MakeEmpty();
}
unchanged after returning the path.
@param mx if present, applied to the points after they are copied into the resulting path.
@return SkPath representing the current state of the builder.
*/
SkPath snapshot(const SkMatrix* mx = nullptr) const;
reset to empty after returning the path.
@param mx if present, applied to the points after they are copied into the resulting path.
@return SkPath representing the current state of the builder.
*/
SkPath detach(const SkMatrix* mx = nullptr);
sk_sp<SkPathData> snapshotData() const;
sk_sp<SkPathData> detachData();
check that ft is legal, values outside of SkPathFillType are not supported.
@param ft SkPathFillType to be used by SKPaths generated from this builder.
@return reference to SkPathBuilder
*/
SkPathBuilder& setFillType(SkPathFillType ft) { fFillType = ft; return *this; }
by the caller after it is drawn. SkPath by default have volatile set false, allowing
Skia to attach a cache of data which speeds repeated drawing.
Mark temporary paths, discarded or modified after use, as volatile
to inform Skia that the path need not be cached.
Mark animating SkPath volatile to improve performance.
Mark unchanging SkPath non-volatile to improve repeated rendering.
raster surface SkPath draws are affected by volatile for some shadows.
GPU surface SkPath draws are affected by volatile for some shadows and concave geometries.
@param isVolatile true if caller will alter SkPath after drawing
@return reference to SkPathBuilder
*/
SkPathBuilder& setIsVolatile(bool isVolatile) { fIsVolatile = isVolatile; return *this; }
Removes verb array, SkPoint array, and weights, and sets FillType to kWinding.
Internal storage associated with SkPathBuilder is preserved.
@return reference to SkPathBuilder
*/
SkPathBuilder& reset();
* then this just replaces the point value of that move, otherwise it appends a new
* "move" verb to the builder using the point.
*
* Thus, each contour can only have 1 move verb in it (the last one specified).
*/
SkPathBuilder& moveTo(SkPoint point);
SkPathBuilder& moveTo(SkScalar x, SkScalar y) {
return this->moveTo(SkPoint::Make(x, y));
}
kClose_Verb, last point is set to (0, 0) before adding line.
lineTo() first appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
lineTo() then appends kLine_Verb to verb array and SkPoint p to SkPoint array.
@param p end SkPoint of added line
@return reference to SkPathBuilder
*/
SkPathBuilder& lineTo(SkPoint pt);
kClose_Verb, last point is set to (0, 0) before adding line.
lineTo() appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
lineTo() then appends kLine_Verb to verb array and (x, y) to SkPoint array.
@param x end of added line on x-axis
@param y end of added line on y-axis
@return reference to SkPathBuilder
*/
SkPathBuilder& lineTo(SkScalar x, SkScalar y) { return this->lineTo(SkPoint::Make(x, y)); }
If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
before adding quad.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
then appends kQuad_Verb to verb array; and SkPoint p1, p2
to SkPoint array.
@param p1 control SkPoint of added quad
@param p2 end SkPoint of added quad
@return reference to SkPathBuilder
*/
SkPathBuilder& quadTo(SkPoint pt1, SkPoint pt2);
If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
before adding quad.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
then appends kQuad_Verb to verb array; and (x1, y1), (x2, y2)
to SkPoint array.
@param x1 control SkPoint of quad on x-axis
@param y1 control SkPoint of quad on y-axis
@param x2 end SkPoint of quad on x-axis
@param y2 end SkPoint of quad on y-axis
@return reference to SkPath
example: https://fiddle.skia.org/c/@Path_quadTo
*/
SkPathBuilder& quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
return this->quadTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2));
}
If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
before adding quad.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
then appends kQuad_Verb to verb array; and the SkPoints to SkPoint array.
@param pts control point and endpoint of added quad.
@return reference to SkPathBuilder
*/
SkPathBuilder& quadTo(const SkPoint pts[2]) { return this->quadTo(pts[0], pts[1]); }
If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
before adding conic.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
If w is finite and not one, appends kConic_Verb to verb array;
and pt1, pt2 to SkPoint array; and w to conic weights.
If w is one, appends kQuad_Verb to verb array, and
pt1, pt2 to SkPoint array.
If w is not finite, appends kLine_Verb twice to verb array, and
pt1, pt2 to SkPoint array.
@param pt1 control SkPoint of conic
@param pt2 end SkPoint of conic
@param w weight of added conic
@return reference to SkPathBuilder
*/
SkPathBuilder& conicTo(SkPoint pt1, SkPoint pt2, SkScalar w);
If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
before adding conic.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
If w is finite and not one, appends kConic_Verb to verb array;
and (x1, y1), (x2, y2) to SkPoint array; and w to conic weights.
If w is one, appends kQuad_Verb to verb array, and
(x1, y1), (x2, y2) to SkPoint array.
If w is not finite, appends kLine_Verb twice to verb array, and
(x1, y1), (x2, y2) to SkPoint array.
@param x1 control SkPoint of conic on x-axis
@param y1 control SkPoint of conic on y-axis
@param x2 end SkPoint of conic on x-axis
@param y2 end SkPoint of conic on y-axis
@param w weight of added conic
@return reference to SkPathBuilder
*/
SkPathBuilder& conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w) {
return this->conicTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), w);
}
If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
before adding conic.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
If w is finite and not one, appends kConic_Verb to verb array;
and SkPoint p1, p2 to SkPoint array; and w to conic weights.
If w is one, appends kQuad_Verb to verb array, and SkPoint p1, p2
to SkPoint array.
If w is not finite, appends kLine_Verb twice to verb array, and
SkPoint p1, p2 to SkPoint array.
@param p1 control SkPoint of added conic
@param p2 end SkPoint of added conic
@param w weight of added conic
@return reference to SkPathBuilder
*/
SkPathBuilder& conicTo(const SkPoint pts[2], SkScalar w) {
return this->conicTo(pts[0], pts[1], w);
}
SkPoint p3. If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is
set to (0, 0) before adding cubic.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
then appends kCubic_Verb to verb array; and SkPoint p1, p2, p3
to SkPoint array.
@param p1 first control SkPoint of cubic
@param p2 second control SkPoint of cubic
@param p3 end SkPoint of cubic
@return reference to SkPathBuilder
*/
SkPathBuilder& cubicTo(SkPoint pt1, SkPoint pt2, SkPoint pt3);
(x3, y3). If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is set
to (0, 0) before adding cubic.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
then appends kCubic_Verb to verb array; and (x1, y1), (x2, y2), (x3, y3)
to SkPoint array.
@param x1 first control SkPoint of cubic on x-axis
@param y1 first control SkPoint of cubic on y-axis
@param x2 second control SkPoint of cubic on x-axis
@param y2 second control SkPoint of cubic on y-axis
@param x3 end SkPoint of cubic on x-axis
@param y3 end SkPoint of cubic on y-axis
@return reference to SkPathBuilder
*/
SkPathBuilder& cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3) {
return this->cubicTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), SkPoint::Make(x3, y3));
}
the third. If SkPathBuilder is empty, or last SkPath::Verb is kClose_Verb, last point is
set to (0, 0) before adding cubic.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
then appends kCubic_Verb to verb array; and SkPoint p1, p2, p3
to SkPoint array.
@param pts first and second control SkPoints of cubic, and end SkPoint.
@return reference to SkPathBuilder
*/
SkPathBuilder& cubicTo(const SkPoint pts[3]) {
return this->cubicTo(pts[0], pts[1], pts[2]);
}
with line, forming a continuous loop. Open and closed contour draw the same
with SkPaint::kFill_Style. With SkPaint::kStroke_Style, open contour draws
SkPaint::Cap at contour start and end; closed contour draws
SkPaint::Join at contour start and end.
close() has no effect if SkPathBuilder is empty or last SkPath SkPath::Verb is kClose_Verb.
@return reference to SkPathBuilder
*/
SkPathBuilder& close();
@param pts span of SkPoint
@return reference to SkPathBuilder.
*/
SkPathBuilder& polylineTo(SkSpan<const SkPoint> pts);
If SkPathBuilder is empty, starts contour at (dx, dy).
Otherwise, start contour at last point offset by (dx, dy).
Function name stands for "relative move to".
@param pt vector offset from last point to contour start
@return reference to SkPathBuilder
example: https://fiddle.skia.org/c/@Path_rMoveTo
*/
SkPathBuilder& rMoveTo(SkVector pt);
If SkPathBuilder is empty, starts contour at (dx, dy).
Otherwise, start contour at last point offset by (dx, dy).
Function name stands for "relative move to".
@param dx offset from last point to contour start on x-axis
@param dy offset from last point to contour start on y-axis
@return reference to SkPathBuilder
example: https://fiddle.skia.org/c/@Path_rMoveTo
*/
SkPathBuilder& rMoveTo(SkScalar dx, SkScalar dy) { return this->rMoveTo({dx, dy}); }
SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding line.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
then appends kLine_Verb to verb array and line end to SkPoint array.
Line end is last point plus vector given by pt.
Function name stands for "relative line to".
@param pt vector offset from last point to line end
@return reference to SkPathBuilder
*/
SkPathBuilder& rLineTo(SkVector pt);
SkPath::Verb is kClose_Verb, last point is set to (0, 0) before adding line.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
then appends kLine_Verb to verb array and line end to SkPoint array.
Line end is last point plus vector (dx, dy).
Function name stands for "relative line to".
@param dx offset from last point to line end on x-axis
@param dy offset from last point to line end on y-axis
@return reference to SkPathBuilder
*/
SkPathBuilder& rLineTo(SkScalar dx, SkScalar dy) { return this->rLineTo({dx, dy}); }
If SkPathBuilder is empty, or last SkPath::Verb
is kClose_Verb, last point is set to (0, 0) before adding quad.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
if needed; then appends kQuad_Verb to verb array; and appends quad
control and quad end to SkPoint array.
Quad control is last point plus vector pt1.
Quad end is last point plus vector pt2.
Function name stands for "relative quad to".
@param pt1 offset vector from last point to quad control
@param pt2 offset vector from last point to quad end
@return reference to SkPathBuilder
*/
SkPathBuilder& rQuadTo(SkVector pt1, SkVector pt2);
If SkPathBuilder is empty, or last SkPath::Verb
is kClose_Verb, last point is set to (0, 0) before adding quad.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
if needed; then appends kQuad_Verb to verb array; and appends quad
control and quad end to SkPoint array.
Quad control is last point plus vector (dx1, dy1).
Quad end is last point plus vector (dx2, dy2).
Function name stands for "relative quad to".
@param dx1 offset from last point to quad control on x-axis
@param dy1 offset from last point to quad control on y-axis
@param dx2 offset from last point to quad end on x-axis
@param dy2 offset from last point to quad end on y-axis
@return reference to SkPathBuilder
*/
SkPathBuilder& rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2) {
return this->rQuadTo({dx1, dy1}, {dx2, dy2});
}
weighted by w. If SkPathBuilder is empty, or last SkPath::Verb
is kClose_Verb, last point is set to (0, 0) before adding conic.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
if needed.
If w is finite and not one, next appends kConic_Verb to verb array,
and w is recorded as conic weight; otherwise, if w is one, appends
kQuad_Verb to verb array; or if w is not finite, appends kLine_Verb
twice to verb array.
In all cases appends SkPoint control and end to SkPoint array.
control is last point plus vector p1.
end is last point plus vector p2.
Function name stands for "relative conic to".
@param p1 offset vector from last point to conic control
@param p2 offset vector from last point to conic end
@param w weight of added conic
@return reference to SkPathBuilder
*/
SkPathBuilder& rConicTo(SkVector p1, SkVector p2, SkScalar w);
weighted by w. If SkPathBuilder is empty, or last SkPath::Verb
is kClose_Verb, last point is set to (0, 0) before adding conic.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
if needed.
If w is finite and not one, next appends kConic_Verb to verb array,
and w is recorded as conic weight; otherwise, if w is one, appends
kQuad_Verb to verb array; or if w is not finite, appends kLine_Verb
twice to verb array.
In all cases appends SkPoint control and end to SkPoint array.
control is last point plus vector (dx1, dy1).
end is last point plus vector (dx2, dy2).
Function name stands for "relative conic to".
@param dx1 offset from last point to conic control on x-axis
@param dy1 offset from last point to conic control on y-axis
@param dx2 offset from last point to conic end on x-axis
@param dy2 offset from last point to conic end on y-axis
@param w weight of added conic
@return reference to SkPathBuilder
*/
SkPathBuilder& rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar w) {
return this->rConicTo({dx1, dy1}, {dx2, dy2}, w);
}
vector pt2, to vector pt3.
If SkPathBuilder is empty, or last SkPath::Verb
is kClose_Verb, last point is set to (0, 0) before adding cubic.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
if needed; then appends kCubic_Verb to verb array; and appends cubic
control and cubic end to SkPoint array.
Cubic control is last point plus vector (dx1, dy1).
Cubic end is last point plus vector (dx2, dy2).
Function name stands for "relative cubic to".
@param pt1 offset vector from last point to first cubic control
@param pt2 offset vector from last point to second cubic control
@param pt3 offset vector from last point to cubic end
@return reference to SkPathBuilder
*/
SkPathBuilder& rCubicTo(SkVector pt1, SkVector pt2, SkVector pt3);
vector (dx2, dy2), to vector (dx3, dy3).
If SkPathBuilder is empty, or last SkPath::Verb
is kClose_Verb, last point is set to (0, 0) before adding cubic.
Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
if needed; then appends kCubic_Verb to verb array; and appends cubic
control and cubic end to SkPoint array.
Cubic control is last point plus vector (dx1, dy1).
Cubic end is last point plus vector (dx2, dy2).
Function name stands for "relative cubic to".
@param dx1 offset from last point to first cubic control on x-axis
@param dy1 offset from last point to first cubic control on y-axis
@param dx2 offset from last point to second cubic control on x-axis
@param dy2 offset from last point to second cubic control on y-axis
@param dx3 offset from last point to cubic end on x-axis
@param dy3 offset from last point to cubic end on y-axis
@return reference to SkPathBuilder
*/
SkPathBuilder& rCubicTo(SkScalar dx1, SkScalar dy1,
SkScalar dx2, SkScalar dy2,
SkScalar dx3, SkScalar dy3) {
return this->rCubicTo({dx1, dy1}, {dx2, dy2}, {dx3, dy3});
}
enum ArcSize {
kSmall_ArcSize,
kLarge_ArcSize,
};
more conic, weighted to describe part of oval with radii (rx, ry) rotated by
xAxisRotate degrees. Arc curves from last SkPathBuilder SkPoint to relative end SkPoint:
(dx, dy), choosing one of four possible routes: clockwise or
counterclockwise, and smaller or larger. If SkPathBuilder is empty, the start arc SkPoint
is (0, 0).
Arc sweep is always less than 360 degrees. arcTo() appends line to end SkPoint
if either radii are zero, or if last SkPath SkPoint equals end SkPoint.
arcTo() scales radii (rx, ry) to fit last SkPath SkPoint and end SkPoint if both are
greater than zero but too small to describe an arc.
arcTo() appends up to four conic curves.
arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is
opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while
kCW_Direction cast to int is zero.
@param r radii on axes before x-axis rotation
@param xAxisRotate x-axis rotation in degrees; positive values are clockwise
@param largeArc chooses smaller or larger arc
@param sweep chooses clockwise or counterclockwise arc
@param dxdy offset end of arc from last SkPath point
@return reference to SkPath
*/
SkPathBuilder& rArcTo(SkPoint r, SkScalar xAxisRotate, ArcSize largeArc,
SkPathDirection sweep, SkVector dxdy);
bounded by oval, from startAngle through sweepAngle. Both startAngle and
sweepAngle are measured in degrees, where zero degrees is aligned with the
positive x-axis, and positive sweeps extends arc clockwise.
arcTo() adds line connecting the builder's last point to initial arc point if forceMoveTo
is false and the builder is not empty. Otherwise, added contour begins with first point
of arc. Angles greater than -360 and less than 360 are treated modulo 360.
@param oval bounds of ellipse containing arc
@param startAngleDeg starting angle of arc in degrees
@param sweepAngleDeg sweep, in degrees. Positive is clockwise; treated modulo 360
@param forceMoveTo true to start a new contour with arc
@return reference to the builder
*/
SkPathBuilder& arcTo(const SkRect& oval, SkScalar startAngleDeg, SkScalar sweepAngleDeg,
bool forceMoveTo);
weighted to describe part of circle. Arc is contained by tangent from
last SkPath point to p1, and tangent from p1 to p2. Arc
is part of circle sized to radius, positioned so it touches both tangent lines.
If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath.
The length of vector from p1 to p2 does not affect arc.
Arc sweep is always less than 180 degrees. If radius is zero, or if
tangents are nearly parallel, arcTo() appends line from last SkPath SkPoint to p1.
arcTo() appends at most one line and one conic.
arcTo() implements the functionality of PostScript arct and HTML Canvas arcTo.
@param p1 SkPoint common to pair of tangents
@param p2 end of second tangent
@param radius distance from arc to circle center
@return reference to SkPath
*/
SkPathBuilder& arcTo(SkPoint p1, SkPoint p2, SkScalar radius);
part of oval with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves
from last SkPath SkPoint to (xy.fX, xy.fY), choosing one of four possible routes:
clockwise or counterclockwise,
and smaller or larger.
Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either
radii are zero, or if last SkPath SkPoint equals (xy.fX, xy.fY). arcTo() scales radii r to
fit last SkPath SkPoint and xy if both are greater than zero but too small to describe
an arc.
arcTo() appends up to four conic curves.
arcTo() implements the functionality of SVG arc, although SVG sweep-flag value is
opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, while
kCW_Direction cast to int is zero.
@param r radii on axes before x-axis rotation
@param xAxisRotate x-axis rotation in degrees; positive values are clockwise
@param largeArc chooses smaller or larger arc
@param sweep chooses clockwise or counterclockwise arc
@param xy end of arc
@return reference to SkPath
*/
SkPathBuilder& arcTo(SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep,
SkPoint xy);
bounded by oval, from startAngle through sweepAngle. Both startAngle and
sweepAngle are measured in degrees, where zero degrees is aligned with the
positive x-axis, and positive sweeps extends arc clockwise.
If sweepAngle <= -360, or sweepAngle >= 360; and startAngle modulo 90 is nearly
zero, append oval instead of arc. Otherwise, sweepAngle values are treated
modulo 360, and arc may or may not draw depending on numeric rounding.
@param oval bounds of ellipse containing arc
@param startAngleDeg starting angle of arc in degrees
@param sweepAngleDeg sweep, in degrees. Positive is clockwise; treated modulo 360
@return reference to this builder
*/
SkPathBuilder& addArc(const SkRect& oval, SkScalar startAngleDeg, SkScalar sweepAngleDeg);
SkPathBuilder& addLine(SkPoint a, SkPoint b) {
return this->moveTo(a).lineTo(b);
}
specified direction. The verbs added to the path will be:
kMove, kLine, kLine, kLine, kClose
start specifies which corner to begin the contour:
0: upper-left corner
1: upper-right corner
2: lower-right corner
3: lower-left corner
This start point also acts as the implied beginning of the subsequent,
contour, if it does not have an explicit moveTo(). e.g.
path.addRect(...)
// if we don't say moveTo() here, we will use the rect's start point
path.lineTo(...)
@param rect SkRect to add as a closed contour
@param dir SkPath::Direction to orient the new contour
@param start initial corner of SkRect to add
@return reference to SkPathBuilder
*/
SkPathBuilder& addRect(const SkRect&, SkPathDirection, unsigned startIndex);
specified direction. The verbs added to the path will be:
kMove, kLine, kLine, kLine, kClose
The contour starts at the upper-left corner of the rect, which also acts as the implied
beginning of the subsequent contour, if it does not have an explicit moveTo(). e.g.
path.addRect(...)
// if we don't say moveTo() here, we will use the rect's upper-left corner
path.lineTo(...)
@param rect SkRect to add as a closed contour
@param dir SkPath::Direction to orient the new contour
@return reference to SkPathBuilder
*/
SkPathBuilder& addRect(const SkRect& rect, SkPathDirection dir = SkPathDirection::kDefault) {
return this->addRect(rect, dir, 0);
}
Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
and half oval height. Oval begins at (oval.fRight, oval.centerY()) and continues
clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.
@param oval bounds of ellipse added
@param dir SkPath::Direction to wind ellipse
@return reference to SkPathBuilder
*/
SkPathBuilder& addOval(const SkRect&, SkPathDirection, unsigned startIndex);
SkRRect winds clockwise. If dir is kCCW_Direction, SkRRect winds counterclockwise.
After appending, SkPathBuilder may be empty, or may contain: SkRect, oval, or SkRRect.
@param rrect SkRRect to add
@param dir SkPath::Direction to wind SkRRect
@param start index of initial point of SkRRect
@return reference to SkPathBuilder
*/
SkPathBuilder& addRRect(const SkRRect& rrect, SkPathDirection, unsigned start);
SkRRect starts at top-left of the lower-left corner and winds clockwise. If dir is
kCCW_Direction, SkRRect starts at the bottom-left of the upper-left corner and winds
counterclockwise.
After appending, SkPathBuilder may be empty, or may contain: SkRect, oval, or SkRRect.
@param rrect SkRRect to add
@param dir SkPath::Direction to wind SkRRect
@return reference to SkPathBuilder
*/
SkPathBuilder& addRRect(const SkRRect& rrect, SkPathDirection dir = SkPathDirection::kDefault) {
return this->addRRect(rrect, dir, dir == SkPathDirection::kCW ? 6 : 7);
}
Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
and half oval height. Oval begins at start and continues
clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.
@param oval bounds of ellipse added
@param dir SkPath::Direction to wind ellipse
@return reference to SkPath
example: https://fiddle.skia.org/c/@Path_addOval_2
*/
SkPathBuilder& addOval(const SkRect& oval, SkPathDirection dir = SkPathDirection::kDefault) {
return this->addOval(oval, dir, 1);
}
four kConic_Verb, and kClose_Verb. Circle begins at: (x + radius, y), continuing
clockwise if dir is kCW_Direction, and counterclockwise if dir is kCCW_Direction.
Has no effect if radius is zero or negative.
@param x center of circle
@param y center of circle
@param radius distance from center to edge
@param dir SkPath::Direction to wind circle
@return reference to SkPathBuilder
*/
SkPathBuilder& addCircle(SkScalar x, SkScalar y, SkScalar radius,
SkPathDirection dir = SkPathDirection::kDefault);
Contour added starts at pts[0], then adds a line for every additional SkPoint
in pts array. If close is true, appends kClose_Verb to SkPath, connecting
pts[count - 1] and pts[0].
@param pts array of line sharing end and start SkPoint
@param close true to add line connecting contour end and start
@return reference to SkPath
*/
SkPathBuilder& addPolygon(SkSpan<const SkPoint> pts, bool close);
If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
added unaltered. If mode is kExtend_AddPathMode, add line before appending
verbs, SkPoint, and conic weights.
@param src SkPath verbs, SkPoint, and conic weights to add
@param dx offset added to src SkPoint array x-axis coordinates
@param dy offset added to src SkPoint array y-axis coordinates
@param mode kAppend_AddPathMode or kExtend_AddPathMode
@return reference to SkPathBuilder
*/
SkPathBuilder& addPath(const SkPath& src, SkScalar dx, SkScalar dy,
SkPath::AddPathMode mode = SkPath::kAppend_AddPathMode);
If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
added unaltered. If mode is kExtend_AddPathMode, add line before appending
verbs, SkPoint, and conic weights.
@param src SkPath verbs, SkPoint, and conic weights to add
@param mode kAppend_AddPathMode or kExtend_AddPathMode
@return reference to SkPathBuilder
*/
SkPathBuilder& addPath(const SkPath& src,
SkPath::AddPathMode mode = SkPath::kAppend_AddPathMode) {
return this->addPath(src, SkMatrix::I(), mode);
}
verbs, SkPoint, and conic weights.
If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
added unaltered. If mode is kExtend_AddPathMode, add line before appending
verbs, SkPoint, and conic weights.
@param src SkPath verbs, SkPoint, and conic weights to add
@param matrix transform applied to src
@param mode kAppend_AddPathMode or kExtend_AddPathMode
@return reference to SkPathBuilder
*/
SkPathBuilder& addPath(const SkPath& src, const SkMatrix& matrix,
SkPath::AddPathMode mode = SkPath::AddPathMode::kAppend_AddPathMode);
May improve performance and use less memory by
reducing the number and size of allocations when creating SkPathBuilder.
@param extraPtCount number of additional SkPoint to allocate
@param extraVerbCount number of additional verbs
@param extraConicCount number of additional conic weights
*/
void incReserve(int extraPtCount, int extraVerbCount, int extraConicCount);
May improve performance and use less memory by
reducing the number and size of allocations when creating SkPathBuilder.
@param extraPtCount number of additional SkPoints and verbs to allocate
*/
void incReserve(int extraPtCount) {
this->incReserve(extraPtCount, extraPtCount, 0);
}
@param dx offset added to SkPoint array x-axis coordinates
@param dy offset added to SkPoint array y-axis coordinates
*/
SkPathBuilder& offset(SkScalar dx, SkScalar dy);
transform may change verbs and increase their number.
@param matrix SkMatrix to apply to SkPath
@param pc whether to apply perspective clipping
*/
SkPathBuilder& transform(const SkMatrix& matrix);
* Returns true if the builder is empty, or all of its points are finite.
*/
bool isFinite() const;
unmodified by the original SkPathFillType.
*/
SkPathBuilder& toggleInverseFillType() {
fFillType = SkPathFillType_ToggleInverse(fFillType);
return *this;
}
Empty SkPathBuilder may have FillType but has no SkPoint, SkPath::Verb, or conic weight.
SkPathBuilder() constructs empty SkPathBuilder; reset() and rewind() make SkPath empty.
@return true if the path contains no SkPath::Verb array
*/
bool isEmpty() const { return fVerbs.empty(); }
@return last SkPoint if SkPoint array contains one or more SkPoint, otherwise nullopt
example: https://fiddle.skia.org/c/@Path_getLastPt
*/
std::optional<SkPoint> getLastPt() const;
* If index is out of range, the call does nothing.
*
* @param index which point to replace
* @param p the new point value
*/
void setPoint(size_t index, SkPoint p);
verb array and append p to SkPoint array.
@param x x-value of last point
@param y y-value of last point
*/
void setLastPt(SkScalar x, SkScalar y);
SkPoint count is initially zero.
@return SkPathBuilder SkPoint array length
*/
int countPoints() const { return fPts.size(); }
extends indefinitely.
@return true if FillType is kInverseWinding or kInverseEvenOdd
*/
bool isInverseFillType() const { return SkPathFillType_IsInverse(fFillType); }
#ifdef SK_SUPPORT_UNSPANNED_APIS
SkPathBuilder& addPolygon(const SkPoint pts[], int count, bool close) {
return this->addPolygon({pts, count}, close);
}
SkPathBuilder& polylineTo(const SkPoint pts[], int count) {
return this->polylineTo({pts, count});
}
#endif
SkSpan<const SkPoint> points() const {
return fPts;
}
SkSpan<const SkPathVerb> verbs() const {
return fVerbs;
}
SkSpan<const float> conicWeights() const {
return fConicWeights;
}
SkPathBuilder& addRaw(const SkPathRaw&);
SkPathIter iter() const;
enum class DumpFormat {
kDecimal,
kHex,
};
SkString dumpToString(DumpFormat = DumpFormat::kDecimal) const;
void dump(DumpFormat) const;
void dump() const { this->dump(DumpFormat::kDecimal); }
bool contains(SkPoint) const;
private:
SkPathRef::PointsArray fPts;
SkPathRef::VerbsArray fVerbs;
SkPathRef::ConicWeightsArray fConicWeights;
SkPathFillType fFillType;
bool fIsVolatile;
SkPathConvexity fConvexity;
unsigned fSegmentMask;
int fLastMoveIndex;
SkPathIsAType fType = SkPathIsAType::kGeneral;
SkPathIsAData fIsA {};
void ensureMove() {
fType = SkPathIsAType::kGeneral;
if (fVerbs.empty()) {
this->moveTo({0, 0});
} else if (fVerbs.back() == SkPathVerb::kClose) {
this->moveTo(fPts[fLastMoveIndex]);
}
}
SkPath make(sk_sp<SkPathRef>) const;
bool isZeroLengthSincePoint(int startPtIndex) const;
SkPathBuilder& privateReverseAddPath(const SkPath&);
SkPathBuilder& privateReversePathTo(const SkPath&);
std::tuple<SkPoint*, SkScalar*> growForVerbsInPath(const SkPath& path);
friend class SkPathPriv;
friend class SkStroke;
friend class SkPathStroker;
};
#endif