Open typemytype opened 6 years ago
hm. It looks like Skia is splitting the cubic bezier curve at the inflection point. Maybe it's because we are using a function called Simplify
in order to remove the overlaps and splitting at inflection points could be part of its contract.. Or maybe skia needs to split at inflections in order to perform its operations.
I am not sure how we could prevent this from happening.
I think Cary is interested in seeing these bugs.
I think Cary is interested in seeing these bugs.
sure, I will notify him if we confirm that these are actually bugs, rather than intended behavior.
In this particular case, the splitting of the cubic curve seems to be done intentionally.
The SkOpEdgeBuilder
class (responsible for converting a SkPath into a set of contours and segments) is calling a method named ComplexBreak
; the inline comment says:
// Split complex cubics (such as self-intersecting curves or
// ones with difficult curvature) in two before proceeding.
// This can be required for intersection to succeed.
This method checks that the curve is monotonic (either increasing or decreasing) in both X and Y, otherwise it splits it to make it so:
So.. the monotonicity of the curves this seems to me like a requirement to make the curve-to-curve intersection algorithm to work properly.
I think we need to check for such "complex" curves upfront, and if we detect that they are still present after we called skia to remove the overlaps, try to re-join them.
I put a printf
immediately after the call to SkDCubic::ComplexBreak
and I can confirm that is what is happening for this particular glyph.
the most important part is: the extra point should not be there :)
from skimming the SkOpEdgeBuilder
code this feels like an intermediate state of the curves, not a final result. I guess this should be solved inside skia.
Your other proposal is very similar to what booleanOperation already does (for every kind of curve)
We can only communicate with Cary (I dont know him) through the skia bug tracking?
we can also use the mailing list https://groups.google.com/forum/#!forum/skia-discuss
this really feels like a bug, even what is a complex curve...
left: the source (as pasted below) middle: booleanOperations right: skia
the orange rects are the differences with the booleanOperation result
<?xml version="1.0" encoding="UTF-8"?>
it's consistent with what I noted above. In the first path, the complex curve is split at the infection point. In the second one, I'm not sure what are you pointing at. Is it the fact that an additional contour (moveTo in bold red/pink) is added?
the bottom part is also a complex curve to me: the question is what defines a complex curve, they both dont have self intersection parts and the off curves goes far beyond the inflection point.
yes, they are complex (probably no one will want to draw them like that), but what exactly is it that you don't like with the way the second path is being clipped by skia? That it is splitting off the small contour at the bottom-right while it's not doing the same at the top-right? Or the fact that it's adding the extra contour whereas in the result from booleanOperation (in the middle) keeps it as a single contour?
the bottom part is fine :) (with a complex curve) the top part is not oke: it should not add extra points where its not needed. Its clearly possible to draw that curve without that extra point. I know its not a good curve, but assume a drawing of rounded italic without extreme points...
The goal should be 'remove the overlap' not correct the contour, this is an other problem to solve. Its always possible to split an existing curve in parts without losing curve quality. So I dont see why that extra point should remain.
my visual drawbot test script: https://gist.github.com/typemytype/ada7589bd2a564cefac681f45c3374e5
thanks for sharing that!
Ok so currently Skia adds points at inflection points. We should ask Cary if that can be avoided.
left: the source (as pasted below) middle: booleanOperations right: skia
there is a point added which is not in the source, this needs to be solved