[ft-devel] more thoughts on cubic spline flattening

2010-09-03 Thread GRAHAM ASHER
David Bevan's citation of two papers on spline flattening 
(http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf
 and 
http://www.cis.usouthal.edu/~hain/general/Publications/Bezier/bezier%20cccg04%20paper.pdf)
 stimulated some more thoughts on the problem. To recapitulate some existing 
points, and ask some more questions, and point out another error in the current 
FreeType logic (point 6):

1. The ideal flattening criterion is the maximum deviation (sideways distance) 
of any point on the curve from the chord (straight line from p0 to p3; not the 
line segment, but the whole infinite line).

2. Hain's paper shows that this can be approximated (yielding an estimate that 
is never too small, and always quite close) by a quadratic equation based on 
the 
ratio between the deviations of the two control points from the chord. If the 
ratio (smaller deviation divided by larger) is v, the expression 0.072(v^2) + 
0.229v + 0.449, multiplied by the larger of the two deviations, gives this 
approximation.

3. Calculating the expression in (2) is quite expensive because square root 
operations are required to get the deviations of the two control points, and 
some fixed-point arithmetic is needed to avoid or at least minimise overflow. 
(I 
have coded this experimentally.)

4. There are a series of less accurate heuristics. The first relaxation is not 
to evaluate the expression in (2), but to use the value 0.75, which is the 
maximum value it can yield (v is always in the range 0...1, and v=1 yields 
0.75; 
smaller values of v give smaller results). However, this heuristic still 
requires calculation of the deviations of the control points. A second 
relaxation uses the maximum coordinate distance (max of dx and dy) of a control 
point from the middle of the chord, which cannot be less than the actual 
deviation.

5. Therefore a usable fast heuristic is the maximum coordinate distance from 
the 
middle of the chord, multiplied by 0.75.

6. Unfortunately the current logic in FreeType has another error. It assumes 
that the flattening criterion can be applied at the start, yielding the 
required 
number of bisections. That is, a ratio is calculated between the heuristic 
distance and a so-called 'cubic level'; and the number of bisections needed is 
calculated as the ceiling of the base-4 logarithm of the heuristic distance; in 
other words, there is an assumption that every bisection of a cubic spline 
increases its flatness fourfold.

7. Here is the proof that the assumption in (6) is wrong. A cubic spline with 
control points on different sides of the chord, symmetrically arranged, will be 
bisected at the point where it crosses the chord. The two halves will have 
exactly the same maximum deviation as the whole.

This leads to the big question. Is it possible to determine the minimum number 
of bisections needed at the start, using a formula that does not itself apply 
the bisections - that is, something simpler than the exhaustive calculation? 
(Perhaps flatness does increase fourfold if the control points are the same 
side 
of the chord, so all we need do is add one iteration for an initial contrary 
case.) I suspect that the answer is no, but I am sure David Bevan will want to 
comment. If the answer is no, then I shall need to code up a fix that estimates 
flatness efficiently on each iteration of the bisection loop.

Comments please.

Thanks in advance,

Graham

___
Freetype-devel mailing list
Freetype-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/freetype-devel


RE: [ft-devel] more thoughts on cubic spline flattening

2010-09-03 Thread David Bevan

Graham,

I finally had a brief chance to look at the code yesterday, and hope to be able 
to spend most of the rest of today on it too. (So far I have only looked at the 
pre-2.4.0 code.)
 
gray_render_cubic is a (non-recursive implementation of) a recursive algorithm 
for splitting the curve into 2^n line segments. This is forward differencing 
rather than recursive subdivision (which determine whether each subdivision 
is required independently).

At the moment I don't understand the basis for the calculation of n, though I 
presume that it is some standard heuristic. You point 7 below rather brings 
that into doubt though!

This was probably state-of-the-art when it was first implemented, but is 
probably quite inefficient in the number of line segments created.
 

I've added further comments inline below, and some queries at the end.


 -Original Message-
 From: freetype-devel-bounces+david.bevan=pb@nongnu.org
 [mailto:freetype-devel-bounces+david.bevan=pb@nongnu.org] On Behalf Of
 GRAHAM ASHER
 Sent: 3 September 2010 09:14
 To: FreeType
 Subject: [ft-devel] more thoughts on cubic spline flattening
 
 David Bevan's citation of two papers on spline flattening
 (http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-
 ready%20CISST02%202.pdf
  and
 http://www.cis.usouthal.edu/~hain/general/Publications/Bezier/bezier%20ccc
 g04%20paper.pdf)
  stimulated some more thoughts on the problem. To recapitulate some
 existing
 points, and ask some more questions, and point out another error in the
 current
 FreeType logic (point 6):
 
 1. The ideal flattening criterion is the maximum deviation (sideways
 distance)
 of any point on the curve from the chord (straight line from p0 to p3; not
 the
 line segment, but the whole infinite line).

This isn't quite the whole story. The curve may extend outside the infinite 
strip perpendicular to the chord P0P3 as seen in Hain's Figure 2. Indeed it may 
do so even if the curve never deviates from the chord in the s-direction by 
more than the maximum acceptable deviation value (because both control points 
are very close to the line which extends the chord).

This is the reason for Hain's section 3.2 on the longitudinal deviation. 
However, there's a simple approach for handling this: if P0 or P3 is (more than 
the maximum acceptable deviation value) outside the strip, subdivide. Hain 
mentions this at the end of his section 1.


 2. Hain's paper shows that this can be approximated (yielding an estimate
 that
 is never too small, and always quite close) by a quadratic equation based
 on the
 ratio between the deviations of the two control points from the chord. If
 the
 ratio (smaller deviation divided by larger) is v, the expression
 0.072(v^2) +
 0.229v + 0.449, multiplied by the larger of the two deviations, gives this
 approximation.
 
 3. Calculating the expression in (2) is quite expensive because square
 root
 operations are required to get the deviations of the two control points,
 and
 some fixed-point arithmetic is needed to avoid or at least minimise
 overflow. (I
 have coded this experimentally.)

Perhaps I've missed something, but my reading of Hain's paper is that the 
evaluation of square roots is never actually needed.


 4. There are a series of less accurate heuristics. The first relaxation is
 not
 to evaluate the expression in (2), but to use the value 0.75, which is the
 maximum value it can yield (v is always in the range 0...1, and v=1 yields
 0.75;
 smaller values of v give smaller results). However, this heuristic still
 requires calculation of the deviations of the control points. A second
 relaxation uses the maximum coordinate distance (max of dx and dy) of a
 control
 point from the middle of the chord, which cannot be less than the actual
 deviation.

This looks like a variant of what Hain describes on pp1-2.


 5. Therefore a usable fast heuristic is the maximum coordinate distance
 from the
 middle of the chord, multiplied by 0.75.

I don't think that will work. A control point can be sqrt(2) x max(dx,dy) from 
the chord (if dx=dy), so we need to factor that into the calculation.

An example:

  P0: 0,0
  P1: 0,99
  P2: 1,100
  P3: 100,100

v = 1 so the max deviation = 0.75 * 99 / sqrt(2) ~= 52.50

But max(dx,dy) = 50, so the heuristic would give 0.75 * 50 = 37.5.

You would need to use a factor at least 0.75 * sqrt(2) ~= 1.06, rather than 
0.75. For this example it would give an estimate of ~53.03.


For sensible estimates, it is necessary to work in Hain's r-s coordinate system.


 6. Unfortunately the current logic in FreeType has another error. It
 assumes
 that the flattening criterion can be applied at the start, yielding the
 required
 number of bisections. That is, a ratio is calculated between the heuristic
 distance and a so-called 'cubic level'; and the number of bisections
 needed is
 calculated as the ceiling of the base-4 logarithm of the heuristic
 distance; in
 other words, there is an 

Re: [ft-devel] Re: render error after ftgrays: Speed up rendering of small cubic splines.

2010-09-03 Thread Werner LEMBERG

 It seems that this mail didn't came through...

Oops!  It's there already

  http://lists.gnu.org/archive/html/freetype-devel/2010-08/msg00031.html

Sorry for the duplicate.


Werner

___
Freetype-devel mailing list
Freetype-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/freetype-devel


Re: [ft-devel] more thoughts on cubic spline flattening

2010-09-03 Thread Werner LEMBERG

 C. Similarly, would it be possible to have a copy of the font that
 showed up the bug in the changed code (with similar details).

Here it is:

  http://lists.gnu.org/archive/html/freetype-devel/2010-08/msg00031.html


Werner

___
Freetype-devel mailing list
Freetype-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/freetype-devel


Re: [ft-devel] more thoughts on cubic spline flattening

2010-09-03 Thread Graham Asher

David,

you are of course correct that my point 5 is wrong. That is just 
carelessness on my part.


Some clarifications:

You point out that p0 and p3 can have coordinates outside the range 
0...1 in Hain's r/s system. I deliberately ignore that, and I should 
have explained why in more explicit terms. The aim of FreeType is to 
rasterize the outline of a closed curve, and for this purpose I believe 
that, just as we can ignore deviations from the curve of greater than a 
certain tolerance, we can ignore spikes with maximum width less than 
that tolerance. P0 and P3 coordinates of this type create such spikes. 
But if we a heuristic based on the maximum distance of control point 
coordinates from the middle of the chord, the problem doesn't arise 
anyway. It arises only if we use Hain's algorithm fully.


You said my reading of Hain's paper is that the evaluation of square 
roots is never actually needed. To get the deviations of the control 
points we need to either (i) rotate the points into the r/s coordinate 
system, and the simplest way of creating a rotation transform requires 
square roots (convert chord vector to unit vector by dividing by vector 
length obtained by Pythagoras, then sine and cosine needed for transform 
are x and y coords of vector); or (ii) use the standard method of 
finding the distance of a point from a line, which again needs 
Pythagoras to get the lengths of vectors. I hope I've missed some 
simpler way of doing it, in which case please tell me.


In answer to your question A: the units are 64ths of a pixel, so 16 is a 
quarter pixel. That is for the normal case; FreeType can be configured 
to use different numbers of bits per pixel. The controlling macro is 
PIXEL_BITS in ftgrays.c


In answer to question B: I don't know; perhaps Werner can answer. I 
don't follow everything on the FreeType list, and have long periods when 
I haven't time to look at anything.


In answer to question C: yes, I posted the font and screen shots to the 
list a few days ago - and I see that Werner has just linked to it in his 
latest post.


Graham


David Bevan wrote:

Graham,

I finally had a brief chance to look at the code yesterday, and hope to be able 
to spend most of the rest of today on it too. (So far I have only looked at the 
pre-2.4.0 code.)
 
gray_render_cubic is a (non-recursive implementation of) a recursive algorithm for splitting the curve into 2^n line segments. This is forward differencing rather than recursive subdivision (which determine whether each subdivision is required independently).


At the moment I don't understand the basis for the calculation of n, though I 
presume that it is some standard heuristic. You point 7 below rather brings 
that into doubt though!

This was probably state-of-the-art when it was first implemented, but is 
probably quite inefficient in the number of line segments created.
 


I've added further comments inline below, and some queries at the end.


  

-Original Message-
From: freetype-devel-bounces+david.bevan=pb@nongnu.org
[mailto:freetype-devel-bounces+david.bevan=pb@nongnu.org] On Behalf Of
GRAHAM ASHER
Sent: 3 September 2010 09:14
To: FreeType
Subject: [ft-devel] more thoughts on cubic spline flattening

David Bevan's citation of two papers on spline flattening
(http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-
ready%20CISST02%202.pdf
 and
http://www.cis.usouthal.edu/~hain/general/Publications/Bezier/bezier%20ccc
g04%20paper.pdf)
 stimulated some more thoughts on the problem. To recapitulate some
existing
points, and ask some more questions, and point out another error in the
current
FreeType logic (point 6):

1. The ideal flattening criterion is the maximum deviation (sideways
distance)
of any point on the curve from the chord (straight line from p0 to p3; not
the
line segment, but the whole infinite line).



This isn't quite the whole story. The curve may extend outside the infinite 
strip perpendicular to the chord P0P3 as seen in Hain's Figure 2. Indeed it may 
do so even if the curve never deviates from the chord in the s-direction by 
more than the maximum acceptable deviation value (because both control points 
are very close to the line which extends the chord).

This is the reason for Hain's section 3.2 on the longitudinal deviation. 
However, there's a simple approach for handling this: if P0 or P3 is (more than 
the maximum acceptable deviation value) outside the strip, subdivide. Hain 
mentions this at the end of his section 1.


  

2. Hain's paper shows that this can be approximated (yielding an estimate
that
is never too small, and always quite close) by a quadratic equation based
on the
ratio between the deviations of the two control points from the chord. If
the
ratio (smaller deviation divided by larger) is v, the expression
0.072(v^2) +
0.229v + 0.449, multiplied by the larger of the two deviations, gives this
approximation.

3. Calculating the expression in (2) is 

RE: [ft-devel] more thoughts on cubic spline flattening

2010-09-03 Thread David Bevan

Some brief comments inline.

More feedback from my investigations later.


 -Original Message-
 From: Graham Asher [mailto:graham.as...@btinternet.com]
 Sent: 3 September 2010 13:56
 To: David Bevan
 Cc: FreeType
 Subject: Re: [ft-devel] more thoughts on cubic spline flattening
 
 David,
 
 you are of course correct that my point 5 is wrong. That is just
 carelessness on my part.
 
 Some clarifications:
 
 You point out that p0 and p3 can have coordinates outside the range
 0...1 in Hain's r/s system. I deliberately ignore that, and I should
 have explained why in more explicit terms. The aim of FreeType is to
 rasterize the outline of a closed curve, and for this purpose I believe
 that, just as we can ignore deviations from the curve of greater than a
 certain tolerance, we can ignore spikes with maximum width less than
 that tolerance. P0 and P3 coordinates of this type create such spikes.

That does not follow the recommended PostScript Language scan-conversion rules 
for path fills (PLRM3 7.5.1) - a shape is scan-converted by painting any pixel 
whose square region intersects the shape, however small the intersection is.

Whether that rule should actually be applied to character shapes is another 
matter though (see the last paragraph of 7.5.1).


 But if we a heuristic based on the maximum distance of control point
 coordinates from the middle of the chord, the problem doesn't arise
 anyway. It arises only if we use Hain's algorithm fully.

That's a very good point.
 

 You said my reading of Hain's paper is that the evaluation of square
 roots is never actually needed. To get the deviations of the control
 points we need to either (i) rotate the points into the r/s coordinate
 system, and the simplest way of creating a rotation transform requires
 square roots (convert chord vector to unit vector by dividing by vector
 length obtained by Pythagoras, then sine and cosine needed for transform
 are x and y coords of vector); or (ii) use the standard method of
 finding the distance of a point from a line, which again needs
 Pythagoras to get the lengths of vectors. I hope I've missed some
 simpler way of doing it, in which case please tell me.

Hain explains how to do the calculations in section 3.

The rotation is simply achieved by using the equation for s (where the 
denominator of L^2 can be ignored as Hain further explains).

The last paragraph of section 3 then describes how to do the necessary 
comparison thereby avoiding a square root evaluation.


The challenge will be ensuring that we can use the widest range of integer 
values without overflow. Squaring the P0-P3 distance seems unavoidable. Using 
unsigned 32-bit values (which we should be able to use for values which are 
always positive) allows us up to 65536 = 1023 pixels = 1.7 at 600dpi.

However, there is one very simple heuristic solution to this: subdivide once 
automatically if the chord length is too great.


 In answer to your question A: the units are 64ths of a pixel, so 16 is a
 quarter pixel. That is for the normal case; FreeType can be configured
 to use different numbers of bits per pixel. The controlling macro is
 PIXEL_BITS in ftgrays.c

Thanks for the answer; obviously your previous email gave a big hint!


Regards,

David %^


___
Freetype-devel mailing list
Freetype-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/freetype-devel


RE: [ft-devel] more thoughts on cubic spline flattening

2010-09-03 Thread David Bevan

I've added some trace code to gray_render_cubic to report the average number of 
line segments created for a Bezier arc, and to calculate for each segment the 
(exact) deviation of the arc segment it replaces.

I've still only tested this with the pre-2.4.0 code. Here are the results with 
my test data: 

For screen resolutions, an average of about 9 segments are generated per arc, 
with an average deviation of about 1.5 (x 1/64 pel) and a maximum deviation of 
about 11 (x 1/64 pel).

For printer resolutions, an average of about 12 segments are generated per arc, 
with an average deviation of about 2.5 (x 1/64 pel) and a maximum deviation of 
about 20 (x 1/64 pel).

In both cases, about 20% of the segments have a deviation less that 0.5 (x 1/64 
pel).


Assuming I have the time, next week I'll attempt to implement something based 
on Hain's paper. I will also do some profiling (timing) of the code, so we can 
compare performance.


David %^


___
Freetype-devel mailing list
Freetype-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/freetype-devel


Re: [ft-devel] more thoughts on cubic spline flattening

2010-09-03 Thread Werner LEMBERG

 In answer to question B: I don't know; perhaps Werner can answer.  I
 don't follow everything on the FreeType list, and have long periods
 when I haven't time to look at anything.

If I understand David correctly, he wants you to present the details
which have motivated you to work on the flattening algorithm.  In
other words, do you have a font or test case which triggers an
excessive number of subdivisions with the old algorithm?


Werner

___
Freetype-devel mailing list
Freetype-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/freetype-devel


Re: [ft-devel] more thoughts on cubic spline flattening

2010-09-03 Thread Werner LEMBERG

 Some brief comments inline.
 
 More feedback from my investigations later.  [...]

BTW, thanks a lot to both of you for working on this!  Is there
something which I shall already commit to the repository?


Werner

___
Freetype-devel mailing list
Freetype-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/freetype-devel