tfont
tfont copied to clipboard
WIP: Implement qcurve handling in tfont
This makes the text tool work.
Todo: look at what's missing. Intersection to make ruler work.
TestFont.ufo
was cribbed from defcon. Had to change public.background
s A
to not be all-off-curves, otherwise UFOConverter would be stuck in an infinite loop trying to shuffle points around ;)
There is code for intersection here: https://github.com/trufont/trufont/blob/wx/src/trufont/util/bezierMath.py#L99
Neat! Any reason to have a bezierMath.py in Trufont and tfont?
Ugh. The TruFont function doesn't seem to work (aside from pc0 having a -
instead of a +
in it) or I'm confused. My trigonometry-fu is very weak. I found https://stackoverflow.com/questions/27664298/calculating-intersection-point-of-quadratic-bezier-curve but the math in there seems to work differently. E.g. in fontTools' solveQuadratic function, it computes DD = b * b - 4.0 * a * c
which turns DD negative with the example curve and line and therefore returns no root, whereas the JS example computes DD = b * b - 4.0 * c
and leaves out the / a
. in the root calculation. Debugging...
Ok, so this is a very rough implementation that works. I don't know why fontTools' solveQuadratic
works differently. I'd have to work out the math to avoid the _lerp()
. The previous way of computing s0
and s1
looked better.
And for some reason, depending on ufoLib2 does not pull in fontTools[ufo]. Ugh.
Still occasionally get
File "/home/nikolaus/Entwicklung/tfont/src/tfont/util/bezierMath.py", line 132, in qcurveIntersections
pc1 = (nx * bx + ny * by) / pc0
ZeroDivisionError: float division by zero
Just catch that and return []
?
https://pomax.github.io/bezierinfo/#what-about-curve-line-intersections- https://pomax.github.io/bezierinfo/#aligning
Hm :) Let's see.
I gave up and simply adapted curveIntersections
' math for quadratics. It werks! 🎉
splitSegment
is tricky I think, as we don't know which subsegment of the qcurve segment the t
belongs to :thinking:
I suppose I could change the return value of (q)curveIntersections
to include the starting point of the curve the t
belongs to, then it's just iterating over the implied subsegments until you hit the right starting point and splitting the subsegment.
Or the index of the segment. then it can be accessed directly https://github.com/trufont/trufont/blob/wx/src/trufont/objects/factories.py#L104
What is the reason cmp
is turned off for Point
?
What is the reason cmp is turned off for Point?
Comparison is based on identity so two different points with the same coordinates wouldn't hash to the same value.
I find this maddeningly tricky while it looks like there must be an easy solution.
@adrientetar So this mostly works, please advise on the segment list bookkeeping and what to return as newSegment
.
I have code like
points_inserted = len(points_to_insert) - 1
segments.insert(index, newSegment)
new_segments = []
index_start = start
for index, point in enumerate(points[start : start + points_inserted]):
if point.type is not None:
new_segments.append(Segment(points, index_start, index))
index_start += index + 1
segments[index:index+1] = new_segments
newSegment = new_segments[0]
for seg in segments[index + 1 :]:
seg._start += points_inserted
seg._end += points_inserted
But that likes to delete everything except one point under certain circumstances.
Even with the sledgehammer method in the PR, sometimes I can literally draw a cutting line through a glyph, deleting everything below it, if I cut a glyph just right...
Adding the fs
dependency directly is ugly, but specifying fonttools[ufo]
instead does not work...
Edit: alternative approach: always depend on fontools[ufo,lxml]
.