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

Jim Graham james.graham at oracle.com
Tue Sep 14 21:12:53 UTC 2010

On 9/14/2010 10:48 AM, Denis Lila wrote:
> Hello Jim.
>> sx1,sy1 have lost their way along the way somewhere.
> I think that was my fault:

Not entirely - see below.

>> I don't think you actually need sx1, sy1 - instead you need to buffer
>> and save aside the first set of dashes and I don't see that buffer
>> anywhere...
> sx1, sy1 were the buffer themselves, because we used to do flattening
> so there were no curves, and no need for an array. I did not see what

Actually then they were already buggy.  It isn't enough to save 2 
values.  If the first "on" dash length is fairly long, and there are, 
say, 50 segments of various types (though even when we were flattening 
there could be multiple segments in the first "dash", they'd just all be 
lines) then you need to save *all* of them aside and then spit them back 
out connected to the final set of dash segments.  If the old code was 
only saving 2 coordinates then it wasn't doing it right.

So, a buffer should have always been provided/used and sx1,sy1 should 
never have been sufficient (though they may have been a "broken" attempt 
to achieve the same goal).

> they were used for, so I did not implement a buffer to replace them.
> I have now. I also fixed a couple of bugs (one related to drawing square
> caps and the other related to drawing joins), and I have tried to
> fix the whitespace (please tell me if I missed anything).
> The link is the same:
> http://icedtea.classpath.org/~dlila/webrevs/noflatten/webrev/

I'll take a look at this if I can, but last minute JavaOne issues (like 
a rewrite of my slides - gulp) are starting to take over my life for the 
next couple of weeks.

> There are a few smallish issues I wanted to discuss:
> 1. To subdivide at arbitrary t, I use equations like (1-t)*p1 + t*p2.
> Should I use the more intuitive p1+t*(p2-p1)? It's clearer and should be
> faster since it has 1 fewer multiplication.

I like that other equation.  Both are find and equally understandable so 
use whatever makes the code flow or perform better for your cases.

> 2. When computing offset curves, I check for degenerate curves (i.e. equal
> control and end points). I don't use == for comparisons. I use a function
> that returns true if 2 floats are close to each other, for fear of
> catastrophic cancellation. Is this really a good idea? If so, how close
> should the numbers be before I return true?

That's a great question.  In device space I think a very small 
difference (like 1/256 of a pixel) could be enough to ignore the curve, 
but in user space it's harder to make a judgment call without knowing 
how much they'll be scaled up.  In cases like that I've sometimes used 
the Math.ulp() method to figure out how many "bits of error" we have. 
That method gives you the smallest increment for a given float or double 
so what it is telling you is the magnitude of an "off by 1 bit" error. 
If you allow differences less than 3*ulp(one of the values) then that is 
allowing 1 or 2 bits of precision error.  I'd use more than 2*ulp 
because the numbers you are comparing might be close to a cutoff where 
the binary exponent is increased.  You can also choose the largest 
(magnitude) of the values you are comparing and the ulp() of that value 
gives you a safer estimate of being "off by a bit or two", but that 
requires you to do a max() (and possibly an abs()) test just to find out 
how big of a difference to allow so I usually use a multiplier of at 
least 3 or so.

> 3. Should line 862 in Stroker be enabled (I give some reasons for wanting to
> in a comment below it).

That'll take me a day or two just to understand and figure out... 
<crosseyed smiley>


More information about the 2d-dev mailing list