Re: [OpenJDK 2D-Dev] X11 uniform scaled wide lines and dashed lines; STROKE_CONTROL in Pisces

2010-10-19 Thread Denis Lila
Hi Jim.

If I haven't replied to a suggestion, that means I've implemented and
I thought it was a good idea, so I don't have anything to say about it.

 line 238: If X0,Y0,XL,COUNT were bumped up by 1 then you could just 
 reuse SLOPE from the linear indices - just a thought.

True, but I would like to preserve the naming differences. CURSLOPE
makes it clear that the slope will change.

 lines 521,527,533: Why are these executed twice?  You call these
 methods again after the initialize common fields code.  That seems like
 double the work just to maybe save 4 lines of shared code?  Maybe put the 4 
 lines of shared code in a helper function that all of the init()
 methods call?

Wow, I can't believe these slipped past me. What happened was that I used to
initialize the type specific fields first, to avoid having 2 switch statements.
However, that didn't work out (for reasons explained in the comment), so I 
needed
2 switches after all. I guess I just forgot to delete the init* calls in the 
first
one. I'm pretty sure that the init* calls in the first switch can just be 
deleted.
In fact, it might be a bug to leave them there, since init* calls the AFD 
iteration
function. If we have 2 init calls, the AFD function will be called twice, so 
this
is probably a bug.

 line 37: If it can't be instantiated, why does it take arguments?

Another mistake when cutting, pasting, and modifying old code.

 getTransformedPoints isn't used?
 getUntransformedPoints isn't used?
 fillWithIndxes(float) isn't used?
 evalQuad isn't used?  (Though it does provide symmetry with evalCubic
 which is used)
 getFlatness* aren't used?
 ptSegDistSq isn't used?

Should I get rid of these? I wanted to do it, but I wanted to wait until
just before pushing because I was afraid I'd start needing them again at
some point in the future.

 line 105: There is a closed form solution to cubic roots.  I 
 unfortunately used a bad version in CubicCurve2D.solveCubic and I
 don't remember if I ever went back and fixed it (it may even have been 
 Cardano's method for all I know).  There are versions out there
 which do work better.  The problem with the one in CC2D was that I copied it
 out of Numerical Recipes in C and apparently the author somehow
 assumed that all cubics would have 1 or 3 roots, but a cubic of the form 
 (x-a)(x-a)(x-b) has 2 roots.  D'oh!  While I did find other 
 implementations out there on the net, in the end fixing the closed
 form solution seemed wrought with issues since many of the tests would use
 radically different approaches depending on tiny changes in one of the
 intermediate results and so I worried about FP error even in doubles 
 possibly skewing the results.  I think you should leave your code in 
 there, but I wanted to fill you in on other possibities.

I looked around for a closed form solution but I only found variations
of the one on wikipedia. I decided not to implement it because it looked
like I was going to have to deal with complex numbers and I didn't want
to do that. It also didn't seem like it would be a lot faster than Newton's
method which actually does very few iterations (4-6 if I remember correctly).
But I'll keep this in mind, and if I find a good implementation of a closed
form formula, I'll use it.

 line 566: shouldn't horizontal lines be ignored?  they don't affect 
 rasterization.

They don't, but it's important to always update the current position, otherwise,
if we get something like: moveto(0,0),lineTo(100,0), lineTo(100,100), instead
of recording a vertical line from 100,0 to 100,100 we would record a diagonal
line from 0,0 to 100,100. The actual ignoring is done in the six lines following
these two.


The link is still
http://icedtea.classpath.org/~dlila/webrevs/noflatten2/webrev/
I thoroughly tested it yet, but Java2DDemo looks good.

Thanks,
Denis.

- Jim Graham james.gra...@oracle.com wrote:

 Round 3...
 
 On 10/6/2010 1:36 PM, Denis Lila wrote:
 
  webrev:
  http://icedtea.classpath.org/~dlila/webrevs/noflatten/webrev/
 
 I'm going to set the rest of Stroker.java aside for a moment and focus
 
 on other areas where I have some better knowledge...
 
 Renderer.java:
 
 lines 83, 91, 99: can't these be folded into the prior loops?  You can
 
 update their Y while searching for the [eqc]hi value.
 
 lines 178,192: indent to the preceding (?  (Also, I'm a big fan of 
 moving the { to a line by itself if an conditional or argument list
 
 was wrapped to more than 1 line - the 2D team tends to use that style
 
 everywhere in the 2D code...)
 
 line 193: add fieldForCmp here instead of every time in the loop? 
 (The 
 compiler will probably/hopefully do that anyway)
 
 line 574: indentation?
 
 line 612: delete?  Or will this be making a comeback sometime?
 
 lines 624,626: indentation?
 
 lines 724,725: doesn't the assert false omit these?  I usually throw
 an 
 InternalError in cases like this with a description of what went
 wrong.
 
 I've read up through the use of the cache in 

Re: [OpenJDK 2D-Dev] X11 uniform scaled wide lines and dashed lines; STROKE_CONTROL in Pisces

2010-10-19 Thread Jim Graham

On 10/19/2010 10:38 AM, Denis Lila wrote:

Hi Jim.

If I haven't replied to a suggestion, that means I've implemented and
I thought it was a good idea, so I don't have anything to say about it.


That's mostly true too for me, but there are a couple that I might go 
back to - I'll let you know when I think I've reached a 100% coverage 
(getting close).



getTransformedPoints isn't used?
getUntransformedPoints isn't used?
fillWithIndxes(float) isn't used?
evalQuad isn't used?  (Though it does provide symmetry with evalCubic
which is used)
getFlatness* aren't used?
ptSegDistSq isn't used?


Should I get rid of these? I wanted to do it, but I wanted to wait until
just before pushing because I was afraid I'd start needing them again at
some point in the future.


OK, use your best judgment.  If they are small and they add to symmetry 
of services (like evalQuad) or they might be used later, then it isn't a 
big deal, but dead code in private APIs shouldn't be just left laying 
around if we can help it.


...jim


Re: [OpenJDK 2D-Dev] X11 uniform scaled wide lines and dashed lines; STROKE_CONTROL in Pisces

2010-10-19 Thread Jim Graham

Hi Denis,

On 10/19/2010 10:40 AM, Denis Lila wrote:

ROCsq - I looked at the wikipedia article and it wasn't clear how it
directly related to your function since the article is dealing with
the curvature of a function graphed against its own t, but you are dealing
with 2 parametric equations combined and graphed against each other.
I think I'm going to have to just trust you on this one for now.  :-(


http://en.wikipedia.org/wiki/Radius_of_curvature_%28applications%29
Did you look at the above wikipedia article? When researching I came across
2 of them, and one of them only mentions natural parameterizations, but
the above has the general equation for a R-Rn function, then below that
they have the special case where n=2, x(t)=t, and y(t)=f(t). I used the
first equation on that page.
Actually, I wrote a simple program to make sure the radius of curvature
function was correct. I have attached it. It's not a proof, but I think
it is convincing. Just hold down the mouse button and move it horizontally.
This will change the t value on the curve and the circle drawn will have
radius equal to Math.sqrt(ROCsq). You can also change the control points of
the curve. There's a bug where when you run it the window is really tiny, so
you have to manually resize it and maximize it.


I actually did read that article, but I wasn't seeing the fact that it 
was a multiple parametric equation and that the || were distance 
calculations rather than simply absolute values.  Now I see it. 
Plugging those concepts in to the first equation the mapping is very direct.


One thing that confused me when I was proof-reading it was that the 
numerator seemed to be dx2dy2 squared when it should be cubed.  Then I 
spotted the final *dx2dy2 term at the end which makes it cubed.  I 
wasn't sure why you isolated that term out there instead of just 
grouping it with the rest of the numerator - is there a danger of 
overflow if you multiply it before you do the division?  If so, then 
that is fine since it doesn't actually affect the number of fp ops so it 
should be the same performance.



lines 621-626 and 643-646 - I'm not sure what the derivation of these
lines are.  I tried to do my own equations, but I seem to be heading
in a different direction than you used and it didn't seem like I was
going to converge.  What equations did you set up to solve to get these
calculations?  From what I can see we have:
- new p1,p4 are calculated
- new p(0.5) is calculated
- the corresponding dx,dy at t=0,0.5,1 (gives slopes)
- slopes at t=0, 0.5 and 1 should be the same for all curves
and what you are trying to compute are two scaling constants c1 and c2
that represent how much to scale the dx1,dy1 and dx4,dy4 values to get
a curve that interpolates both position and slope at t=0.5.  A comment
might help here...  :-(


I see how (dxm,dym) was confusing. The only reason for computing the slope
at t=0.5 is to get the point of the offset curve at t=0.5. We don't make
the computed curve and the input curve have equal slopes at t=0.5 because
this would give us an overdetermined system. What we're trying to do in this
function is to approximate an ideal offset curve (call it I) of the input
curve B using a bezier curve Bp. The constraints I use to get the equations are:


It does help *a lot*, though, so thank you for writing it up.  I would 
move it closer to the code in question since the function has such a 
long preamble that separates the comment from the code that implements 
it (also method comments are usually reserved for API documentation 
purposes).


lines 544,559 - I'd remove the line numbers from the comment.  They are 
already wrong and they won't survive any more edits any better.  ;-)


In #2, you have a bunch of I'() || B'() which I read as the slope of 
the derivative (i.e. acceleration) is equal, don't you really mean I() 
|| B() which would mean the original curves should be parallel? 
Otherwise you could say I'() == B'(), but I think you want to show 
parallels because that shows how you can use the dxy1,dxy4 values as the 
parallel equivalents.


I would rename det43 to invdet43 to indicate that it is the inverse of 
the determinant.  I kept looking at it and thinking he has the 
determinant in the wrong side until I noticed that it was in the 
denominator of det43 (which is hard to read in parenthesized C-math).


One side note.  At first glance I would have thought that the final 
equations would have subtracted the c2*dxy4 terms rather than adding 
them (since dxy4 represent p4-p3, not p3-p4 and so the linear 
interpolation equation looks backwards), but that isn't true because 
you did all of your math looking to find the c2 that belongs in this 
equation (as backwards as it seems) and so you got that answer. 
Interestingly if you look at the effect on the results if you calculate 
the dxy4 terms the other way around, they are simply negated and the 
impact would be that c1 would be unaffected (both num and