-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP Keep track of on-curve points in the original path #47
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -137,6 +137,7 @@ cdef class Path: | |
|
||
def __init__(self, other=None, fillType=None): | ||
cdef Path static_path | ||
self.originalOnCurvePoints = set() | ||
if other is not None: | ||
if isinstance(other, Path): | ||
static_path = other | ||
|
@@ -254,7 +255,7 @@ cdef class Path: | |
print(self._to_string(as_hex=as_hex)) # Python | ||
|
||
def _to_string(self, as_hex=False): | ||
# return a text repesentation as Python code | ||
# return a text representation as Python code | ||
if self.path.isEmpty(): | ||
return "" | ||
if as_hex: | ||
|
@@ -669,6 +670,12 @@ cdef class Path: | |
) | ||
cdef Path result = Path.__new__(Path) | ||
self.path.transform(matrix, &result.path) | ||
# TODO: figure out how to transform the original oncurve points using the matrix | ||
# result.originalOnCurvePoints = set( | ||
# transform_tuple_point(matrix, pt) | ||
# for pt in self.originalOnCurvePoints | ||
# ) | ||
result.originalOnCurvePoints = self.originalOnCurvePoints # FIXME: DUMMY just to make test pass | ||
return result | ||
|
||
|
||
|
@@ -753,6 +760,7 @@ cdef tuple CLOSE_PATH = ("closePath", NO_POINTS) | |
cdef class SegmentPenIterator: | ||
|
||
def __cinit__(self, Path path): | ||
self.originalOnCurvePoints = path.originalOnCurvePoints | ||
self.pa = _SkPointArray.create(path.path) | ||
self.pts = self.pa.data | ||
self.va = _VerbArray.create(path.path) | ||
|
@@ -850,7 +858,11 @@ cdef class SegmentPenIterator: | |
next_verb_ptr = verbs + 1 | ||
if next_verb_ptr != self.verb_stop: | ||
if next_verb_ptr[0] == kQuad_Verb: | ||
if is_middle_point(pts[0], pts[1], pts[2]): | ||
if ( | ||
is_middle_point(pts[0], pts[1], pts[2]) | ||
# Don't delete on-curve points that were present in the original curve | ||
and (pts[1].x(), pts[1].y()) not in self.originalOnCurvePoints | ||
): | ||
# skip TrueType "implied" on-curve point, and keep | ||
# evaluating the next quadratic segment | ||
verbs = next_verb_ptr | ||
|
@@ -887,20 +899,24 @@ cdef class PathPen: | |
|
||
cpdef moveTo(self, pt): | ||
self.path.moveTo(pt[0], pt[1]) | ||
self.path.originalOnCurvePoints.add(pt) | ||
|
||
cpdef lineTo(self, pt): | ||
self.path.lineTo(pt[0], pt[1]) | ||
self.path.originalOnCurvePoints.add(pt) | ||
|
||
cpdef curveTo(self, pt1, pt2, pt3): | ||
# support BasePen "super-beziers"? Nah. | ||
self.path.cubicTo( | ||
pt1[0], pt1[1], | ||
pt2[0], pt2[1], | ||
pt3[0], pt3[1]) | ||
self.path.originalOnCurvePoints.add(pt3) | ||
|
||
def qCurveTo(self, *points): | ||
for pt1, pt2 in _decompose_quadratic_segment(points): | ||
self._qCurveToOne(pt1, pt2) | ||
self.path.originalOnCurvePoints.add(points[-1]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I realize now that I could probably only keep track of the original on-curves at the end of qCurves, instead of all types of original on-curves? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, if we have to remember oncurve points, it's probably better to only do it for when we actually need it, i.e. for qCurve segments only where they can be "implied", the other segment types in pen protocol are all explicit |
||
|
||
cdef _qCurveToOne(self, pt1, pt2): | ||
self.path.quadTo(pt1[0], pt1[1], pt2[0], pt2[1]) | ||
|
@@ -922,6 +938,7 @@ cdef class PathPen: | |
cdef Path component_path = base_path.transform(*transformation) | ||
|
||
self.path.addPath(component_path) | ||
self.path.originalOnCurvePoints.update(component_path.originalOnCurvePoints) | ||
|
||
|
||
cdef double get_path_area(const SkPath& path) except? -1234567: | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -106,6 +106,30 @@ def test_decompose_join_quadratic_segments(self): | |||||
('qCurveTo', ((1.0, 1.0), (2.0, 2.0), (3.0, 3.0))), | ||||||
('closePath', ())] | ||||||
|
||||||
def test_decompose_join_quadratic_segments_preserve_original_oncurves(self): | ||||||
path = Path() | ||||||
pen = path.getPen() | ||||||
pen.moveTo((0, 0)) | ||||||
pen.qCurveTo((1, 1), (1.5, 1.5)) # This time the on-curve is explicit | ||||||
pen.qCurveTo((2, 2), (3, 3)) | ||||||
pen.closePath() | ||||||
|
||||||
items = list(path) | ||||||
assert len(items) == 4 | ||||||
# the TrueType quadratic spline with N off-curves is stored internally | ||||||
# as N atomic quadratic Bezier segments | ||||||
assert items[1][0] == PathVerb.QUAD | ||||||
assert items[1][1] == ((1.0, 1.0), (1.5, 1.5)) | ||||||
assert items[2][0] == PathVerb.QUAD | ||||||
assert items[2][1] == ((2.0, 2.0), (3.0, 3.0)) | ||||||
|
||||||
# when drawn back onto a SegmentPen, the implicit on-curves are omitted | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
assert list(path.segments) == [ | ||||||
('moveTo', ((0.0, 0.0),)), | ||||||
('qCurveTo', ((1.0, 1.0), (1.5, 1.5))), | ||||||
('qCurveTo', ((2.0, 2.0), (3.0, 3.0))), | ||||||
('closePath', ())] | ||||||
|
||||||
def test_last_implicit_lineTo(self): | ||||||
# https://github.com/fonttools/skia-pathops/issues/6 | ||||||
path = Path() | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SkMatrix
hasmapPoint
andmapPoints
(for array of SkPoints) methods:https://api.skia.org/classSkMatrix.html#a545fc5d678f0c07c40636bc4cb699017