Re: [OpenJDK 2D-Dev] Various fixes to pisces stroke widening code

2010-07-13 Thread Jim Graham

Hi Denis,

float operations are pretty fast and they are usually done in a separate 
part of the processor so the compiler can schedule a lot of bookkeeping 
instructions to run in parallel with waiting for the results of the FP 
instruction.  In the end, they often end up being free if there are 
enough bookkeeping instructions (branches, fetching data, etc.) in 
amongst the data.


Given how many alternate instructions you are pointing out for the fixed 
point code it would be very likely that this would be a win.


The main reason that Pisces is implemented heavily in fixed point is 
that it was originally written for the mobile platform where there are 
no FP instructions.  We don't have to worry about that on the desktop 
(any more).


I strongly support you converting things to fp if you want to do it...

...jim

On 7/12/2010 8:05 AM, Denis Lila wrote:

Hello.

Is it ok if I do this? I already started working on it on Friday.
I think I should be done by tomorrow.

But yes, I agree that we should convert to floating point. As for
performance, there's also the fact that right now we're trading
one double multiplication for 2 casts to long, 1 long multiplication,
1 bit shift of a long, and 1 cast back to an int. I don't know much
about how these are done in hardware, but it doesn't seem like they'd
be faster than the double multiplication.

As for large coordinates, there's a bug report about it (one not
reported by me :) ) here: https://bugzilla.redhat.com/show_bug.cgi?id=597227
I submitted a matching bug report on bugs.sun.com (ID 6967436), but I
can't find it when I search for it.

Denis.

- Jim Grahamjames.gra...@oracle.com  wrote:


Sigh...

Pisces could really stand to upgrade to floats/doubles everywhere, for

several reasons:

- FPU ops are likely as fast if not faster on modern hardware due to
parallel execution of FP instructions alongside regular instructions.

- Don't have to worry about getting coordinates larger than 32K (I
don't
think this is well tested, but I imagine that Pisces will not deal
with
it very gracefully).

- Lots of code is greatly simplified not having to deal with the
semantics of how to do fixed point multiplies, divides, and
conversions.

I meant to do this during the original integration, but I wanted to
get
the task done as quickly as possible so that we could have an open
source alternative to the closed Ductus code so I left that task for a

later update.  But, now that a lot of work is being done on the code
to
fix it up, it might be better to do the float conversion now so that
the
maintenance is easier and before we end up creating a lot of new fixed

point code.

My plate is full right now, but hopefully I can interest someone else
in
doing a cleanup cycle?  (Donning my Tom Sawyer hat... ;-)

...jim


Re: [OpenJDK 2D-Dev] Various fixes to pisces stroke widening code

2010-07-13 Thread Denis Lila
Hello.

And, I just finished it. At least it compiled successfully. I'm sure there 
are a few runtime bugs. I'll try to have a webrev out by today.

Regards,
Denis.

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

 Hi Denis,
 
 float operations are pretty fast and they are usually done in a
 separate 
 part of the processor so the compiler can schedule a lot of
 bookkeeping 
 instructions to run in parallel with waiting for the results of the FP
 
 instruction.  In the end, they often end up being free if there are
 
 enough bookkeeping instructions (branches, fetching data, etc.) in 
 amongst the data.
 
 Given how many alternate instructions you are pointing out for the
 fixed 
 point code it would be very likely that this would be a win.
 
 The main reason that Pisces is implemented heavily in fixed point is 
 that it was originally written for the mobile platform where there are
 
 no FP instructions.  We don't have to worry about that on the desktop
 
 (any more).
 
 I strongly support you converting things to fp if you want to do
 it...
 
   ...jim
 
 On 7/12/2010 8:05 AM, Denis Lila wrote:
  Hello.
 
  Is it ok if I do this? I already started working on it on Friday.
  I think I should be done by tomorrow.
 
  But yes, I agree that we should convert to floating point. As for
  performance, there's also the fact that right now we're trading
  one double multiplication for 2 casts to long, 1 long
 multiplication,
  1 bit shift of a long, and 1 cast back to an int. I don't know much
  about how these are done in hardware, but it doesn't seem like
 they'd
  be faster than the double multiplication.
 
  As for large coordinates, there's a bug report about it (one not
  reported by me :) ) here:
 https://bugzilla.redhat.com/show_bug.cgi?id=597227
  I submitted a matching bug report on bugs.sun.com (ID 6967436), but
 I
  can't find it when I search for it.
 
  Denis.
 
  - Jim Grahamjames.gra...@oracle.com  wrote:
 
  Sigh...
 
  Pisces could really stand to upgrade to floats/doubles everywhere,
 for
 
  several reasons:
 
  - FPU ops are likely as fast if not faster on modern hardware due
 to
  parallel execution of FP instructions alongside regular
 instructions.
 
  - Don't have to worry about getting coordinates larger than 32K (I
  don't
  think this is well tested, but I imagine that Pisces will not deal
  with
  it very gracefully).
 
  - Lots of code is greatly simplified not having to deal with the
  semantics of how to do fixed point multiplies, divides, and
  conversions.
 
  I meant to do this during the original integration, but I wanted
 to
  get
  the task done as quickly as possible so that we could have an open
  source alternative to the closed Ductus code so I left that task
 for a
 
  later update.  But, now that a lot of work is being done on the
 code
  to
  fix it up, it might be better to do the float conversion now so
 that
  the
  maintenance is easier and before we end up creating a lot of new
 fixed
 
  point code.
 
  My plate is full right now, but hopefully I can interest someone
 else
  in
  doing a cleanup cycle?  (Donning my Tom Sawyer hat... ;-)
 
 ...jim


Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.

2010-07-13 Thread Jim Graham

Hi Denis,

In looking through this code, I can see where it emits the proper join 
for ccw turns, but it looks like it just emits a round join for cw 
turns.  Is that true?  Doesn't this mean that a cw path will always have 
round joins?  Or am I missing something?


My expectation was that the code would emit the proper joins for both 
ccw and cw turns, but it would either place it in the outgoing or the 
return path depending on whether the turn was ccw, no?  I don't see how 
that happens (but I haven't actually tested the code)...


...jim

Denis Lila wrote:

Hello Jim.

I'm terribly sorry about that.
I fixed it. Now the only highlighted lines in the webrev should be
lines I actually changed.
Please take another look at it.
(link is still the same: 
http://icedtea.classpath.org/~dlila/webrevs/bezierRoundJoins/webrev/)

Thanks,
Denis.

PS: I added a new method: emitReverse, that goes through the reverse list
and emits it. It's used in 2 methods which used to just do it themselves.

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


Hi Denis,

You moved some code around without modifying it.  This makes it hard
to 
see what changed and what didn't and verify that the changes are 
accurate.  Also, it adds diffs to the file that are unrelated to the 
fixing of the bug.  Was there a practical reason for why you moved the


code around?  In particular I refer to:

- the setup code that deals with if (joinStyle == JOIN_MITER)

- the setOutput method - which not only moved, but lost its javadocs

- computeMiter() and drawMiter()

All of that code appears to be unchanged at first glance, but it is

hard to tell from the webrevs.  Also, a couple of stylistic issues:

- you changed the declarations of isCCW which moved its arguments
over, 
but the continuation lines aren't indented to match


- The two flavors of emitCurveTo() should probably be next to each 
other (i.e. not have emitLineTo() between them or fall between the two


flavors of emitLineTo()).

In general I think the changes are OK, but I'm still reviewing them
and 
the above issues sprung to mind on a first pass (and/or they are 
complicating the contextual review) so I thought I'd mention them 
earlier than later...


...jim

Denis Lila wrote:

Hello.

I just noticed that approximation of circle arcs by bezier curves
had already been implemented in ArcIterator by Jim Graham. 


It computes the same control points as my solution, but it does so
more straightforwardly, without any rotation, so it is faster and
clearer. I have updated my solution to include this.

The link remains the same.

Thanks,
Denis.

- Denis Lila dl...@redhat.com wrote:


Hello.

I think I got this working. The webrev is at:


http://icedtea.classpath.org/~dlila/webrevs/bezierRoundJoins/webrev/

(NOTE: this is not a final version. I have included 2 versions
of 2 methods. Only one set should be kept. See below for more.)

My Changes:
---
1.
I've made LineSink into an interface, rather than an abstract
class,
because all of its methods were abstract, so it makes more sense

this

way.

2.
I've introduced a new interface that extends LineSink called
PathSink,
which allows the curveTo method, so there have been no changes to
Stroker's public interface. When someone wants to create a Stroker
with a PathSink output, it simply passes its constructor a

PathSink,

so the only changes outside of Stroker are in

PiscesRenderingEngine,

where the methods that handle Path2D and PathConsumer2D objects
create nameless PathSinks instead of nameless LineSinks.

3. In Stroker:
I've introduced a method called drawBezRoundJoin, analogous to
computeRoundJoin. In drawRoundJoin I detect whether the output is
a PathSink. If it is, I call drawBezRoundJoin, otherwise

everything

proceeds as it used to. drawBezRoundJoin uses computeBezierPoints

to

compute the control points. computeBezierPoints computes the

control

points
for an arc of t radians, starting at angle a, with radius r
by computing the control points of an arc of radius 1 of t radians
that
starts at angle -t/2. This is done by solving the equations

resulting

from the constraints that (P3-P2) and (P1-P0) must be parallel to

the

arc's tangents at P3 and P0 respectively, and that B(1/2)=(1,0).

Then

the
points are scaled by r, and rotated counter clockwise by a+t/2.
Then drawBezRoundJoin emits the curve.
All this is done in a loop which is used to break up large

arcs

into
more than one bezier curve. Through the iterations, the computed
control
points don't change - the only thing that changes is how they're
rotated.
So a good alternative approach would be to do the rotation

outside

of
computeBezierPoints, and call computeBezierPoints once outside of

the

loop,
so that the control points aren't recomputed unnecessarily.
I have included code for this in the methods computeBezierPoints2

and

drawBezRoundJoin2. This is my favoured approach, since it is


Re: [OpenJDK 2D-Dev] Fix for drawing round endcaps on scaled lines.

2010-07-13 Thread Jim Graham
Sorry, ignore this message.  I was misinterpreting the field 
internalJoins to mean joins on the inside of the path (!ccw).  It 
actually means implicit joins in the middle of a flattened curve and I 
can see why those are always done round, so the code makes sense now 
(naming of the variable notwithstanding)...


...jim

Jim Graham wrote:

Hi Denis,

In looking through this code, I can see where it emits the proper join 
for ccw turns, but it looks like it just emits a round join for cw 
turns.  Is that true?  Doesn't this mean that a cw path will always have 
round joins?  Or am I missing something?


My expectation was that the code would emit the proper joins for both 
ccw and cw turns, but it would either place it in the outgoing or the 
return path depending on whether the turn was ccw, no?  I don't see how 
that happens (but I haven't actually tested the code)...


...jim

Denis Lila wrote:

Hello Jim.

I'm terribly sorry about that.
I fixed it. Now the only highlighted lines in the webrev should be
lines I actually changed.
Please take another look at it.
(link is still the same: 
http://icedtea.classpath.org/~dlila/webrevs/bezierRoundJoins/webrev/)


Thanks,
Denis.

PS: I added a new method: emitReverse, that goes through the reverse list
and emits it. It's used in 2 methods which used to just do it themselves.

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


Hi Denis,

You moved some code around without modifying it.  This makes it hard
to see what changed and what didn't and verify that the changes are 
accurate.  Also, it adds diffs to the file that are unrelated to the 
fixing of the bug.  Was there a practical reason for why you moved the


code around?  In particular I refer to:

- the setup code that deals with if (joinStyle == JOIN_MITER)

- the setOutput method - which not only moved, but lost its javadocs

- computeMiter() and drawMiter()

All of that code appears to be unchanged at first glance, but it is

hard to tell from the webrevs.  Also, a couple of stylistic issues:

- you changed the declarations of isCCW which moved its arguments
over, but the continuation lines aren't indented to match

- The two flavors of emitCurveTo() should probably be next to each 
other (i.e. not have emitLineTo() between them or fall between the two


flavors of emitLineTo()).

In general I think the changes are OK, but I'm still reviewing them
and the above issues sprung to mind on a first pass (and/or they are 
complicating the contextual review) so I thought I'd mention them 
earlier than later...


...jim

Denis Lila wrote:

Hello.

I just noticed that approximation of circle arcs by bezier curves
had already been implemented in ArcIterator by Jim Graham.
It computes the same control points as my solution, but it does so
more straightforwardly, without any rotation, so it is faster and
clearer. I have updated my solution to include this.

The link remains the same.

Thanks,
Denis.

- Denis Lila dl...@redhat.com wrote:


Hello.

I think I got this working. The webrev is at:


http://icedtea.classpath.org/~dlila/webrevs/bezierRoundJoins/webrev/

(NOTE: this is not a final version. I have included 2 versions
of 2 methods. Only one set should be kept. See below for more.)

My Changes:
---
1.
I've made LineSink into an interface, rather than an abstract
class,
because all of its methods were abstract, so it makes more sense

this

way.

2.
I've introduced a new interface that extends LineSink called
PathSink,
which allows the curveTo method, so there have been no changes to
Stroker's public interface. When someone wants to create a Stroker
with a PathSink output, it simply passes its constructor a

PathSink,

so the only changes outside of Stroker are in

PiscesRenderingEngine,

where the methods that handle Path2D and PathConsumer2D objects
create nameless PathSinks instead of nameless LineSinks.

3. In Stroker:
I've introduced a method called drawBezRoundJoin, analogous to
computeRoundJoin. In drawRoundJoin I detect whether the output is
a PathSink. If it is, I call drawBezRoundJoin, otherwise

everything

proceeds as it used to. drawBezRoundJoin uses computeBezierPoints

to

compute the control points. computeBezierPoints computes the

control

points
for an arc of t radians, starting at angle a, with radius r
by computing the control points of an arc of radius 1 of t radians
that
starts at angle -t/2. This is done by solving the equations

resulting

from the constraints that (P3-P2) and (P1-P0) must be parallel to

the

arc's tangents at P3 and P0 respectively, and that B(1/2)=(1,0).

Then

the
points are scaled by r, and rotated counter clockwise by a+t/2.
Then drawBezRoundJoin emits the curve.
All this is done in a loop which is used to break up large

arcs

into
more than one bezier curve. Through the iterations, the computed
control
points don't change - the only thing that changes is how they're
rotated.
So a