[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-2d-dev
Subject:    [OpenJDK 2D-Dev] X11 uniform scaled wide lines and dashed lines; STROKE_CONTROL in Pisces
From:       james.graham () oracle ! com (Jim Graham)
Date:       2010-07-13 19:27:27
Message-ID: 4C3CBE1F.4060309 () oracle ! com
[Download RAW message or body]

The main issue is the extra overhead of another set of methods to call 
"through" when getting the geometry.  I don't have any gut feel on that 
other than implementing it and doing performance testing...

			...jim

On 7/12/2010 7:50 AM, Denis Lila wrote:
> Hello Jim.
>
> I think the second way would be better because there would be no
> repeated code, and it would be easier to implement.
> Do you think there will be any performance benefit from the first way?
>
> Regards,
> Denis.
>
> ----- "Jim Graham"<james.graham at oracle.com>  wrote:
>
>> Hi Denis,
>>
>> It would be ill-advised to normalize the coordinates after flattening.
>>
>> The quality would be really bad.
>>
>> Perhaps this is a good reason to start looking at updating Pisces to
>> take curves and flatten at the lowest level?
>>
>> Or, I suppose we could get a non-flattened iterator from the source
>> path, send it through a "normalizing" filter, and then through a
>> flattening filter (the way many of the existing objects do flattening
>> is
>> to just get their regular iterator and run it through an instance of
>> FlatteningPathIterator so we could do this manually with an
>> intervening
>> "NormalizingPathIterator" if normalization is needed)...
>>
>> 			...jim
>>
>> Denis Lila wrote:
>>> Hello Jim.
>>>
>>> Thanks for that. I'll get to work on implementing it.
>>>
>>> One thing though, about normalizing the control points of bezier
>>> curves: pisces never gets any bezier curves as input. It only gets
>>> lines that are the product of flattening bezier curves.
>>>
>>> Pisces receives its input from flattening path iterators which get
>> it
>>> from other path iterators. Of course we can't require these to send
>> out
>>> normalized points. In order to normalize the control points we need
>> to
>>> be able to look at the bezier curves in Pisces, so we can't just
>> take
>>> all the input from the flattener. However, pisces can't handle
>> curves
>>> (yet, hopefully), so after the normalization, they must be
>> flattened, and
>>> this is the problem. I think it's a pretty good idea to do this by
>>> storing the input form the iterator into pisces (after
>> normalization),
>>> creating a nameless path iterator that just iterates through all
>> that,
>>> and using this iterator to create a flattening iterator, which then
>>> is used as before.
>>>
>>> Does anyone have any other ideas?
>>>
>>> Thank you,
>>> Denis.
>>>
>>>
>>> ----- "Jim Graham"<james.graham at oracle.com>  wrote:
>>>
>>>> For AA this is exactly what we do (round to nearest pixel centers
>> for
>>>>
>>>> strokes).  Note that this is done prior to any line widening code
>> is
>>>> executed.
>>>>
>>>> For non-AA we normalize coordinates to, I believe the (0.25, 0.25)
>>
>>>> sub-pixel location.  This is so that the transitions between
>> widening
>>>> of
>>>> lines occurs evenly (particularly for horizontal and vertical wide
>>
>>>> lines).  If you round to pixel edges then you have the following
>>>> progression (note that the line width grows by half on either side
>> of
>>>>
>>>> the original geometry so you have to consider the "line widths"
>> where
>>>>
>>>> you encounter the pixel centers to your left and right (or above
>> and
>>>> below) which govern when that column (or row) of pixels first
>> turns
>>>> on):
>>>>
>>>> width 0.00 =>  0.99      nothing drawn (except we kludge this)
>>>> width 1.00 =>  1.00      1 pixel wide (col to left turns on)
>>>> width 1.01 =>  2.99      2 pixels wide (col to right turns on)
>>>> width 3.00 =>  3.00      3 pixels wide (etc.)
>>>> width 3.01 =>  4.99      4 pixels wide
>>>>
>>>> Note that it is nearly impossible to get an odd-width line.  You
>>>> basically have to have exactly an integer width to get an odd-width
>>
>>>> line.  This is because at the odd widths you reach the "half pixel"
>>
>>>> locations on both sides of the line at the same time.  Due to the
>>>> "half-open" insideness rules only one of the pixels will be chosen
>> to
>>>> be
>>>> inside this path.  Just below these sizes and you fail to hit
>> either
>>>> pixel center.  Just at the integer size you reach both pixel
>> centers
>>>> at
>>>> the same time.  Just slightly larger than that width and now you've
>>
>>>> fully enclosed both pixel centers and the line width has to
>> increase
>>>> by
>>>> nearly 2.0 until you reach the next pixel centers.
>>>>
>>>> (The kludge I talk about above is that we set a minimum pen width
>> so
>>>> that we never fail to draw a line even if the line width is set to
>>>> 0.0,
>>>> but the above table was a theoretical description of the absolute
>>>> rules.)
>>>>
>>>> If we rounded them to pixel centers, then the transitions look
>> like
>>>> this:
>>>>
>>>> width 0.00 =>  0.00      nothing drawn (modulo kludge)
>>>> width 0.01 =>  1.99      1 pixel wide (column you are in turns on)
>>>> width 2.00 =>  2.00      2 pixels wide (column to left turns on)
>>>> width 2.01 =>  3.99      3 pixels wide (column to right turns on)
>>>> width 4.00 =>  4.00      4 pixels wide (etc.)
>>>> width 4.01 =>  5.99      5 pixels wide
>>>>
>>>> We have a similar effect as above, but biased towards making even
>> line
>>>>
>>>> widths harder.
>>>>
>>>> So, by locating lines at (0.25, 0.25) subpixel location we end up
>> with
>>>> a
>>>>    very even progression:
>>>>
>>>> width 0.00 =>  0.50      nothing drawn (modulo kludge)
>>>> width 0.51 =>  1.50      1 pixel wide (column you are in turns on)
>>>> width 1.51 =>  2.50      2 pixel wide (column to left gets added)
>>>> width 2.51 =>  3.50      3 pixel wide (column to right gets added)
>>>> width 3.51 =>  4.50      4 pixel wide (etc.)
>>>>
>>>> This gives us nice even and gradual widening of the lines as we
>>>> increase
>>>> the line width by sub-pixel amounts and the line widths are fairly
>>
>>>> stable around integer widths.
>>>>
>>>> Also, note that we don't say "when stroking" as you might want to
>>>> normalize both strokes and fills so that they continue to match.  I
>>
>>>> believe that we normalize both strokes and fills for non-AA and we
>>>> only
>>>> normalize strokes for AA (and leave AA fills as "pure").  AA is
>> less
>>>> problematic with respect to creating gaps if your stroke and fill
>>>> normalization are not consistent.
>>>>
>>>> The rounding equations are along the lines of:
>>>>
>>>> 	v = Math.floor(v + rval) + aval;
>>>>
>>>> For center of pixel you use (rval=0.0, aval=0.5)
>>>> For 0.25,0.25 rounding use  (rval=0.25, aval=0.25)
>>>> For edge of pixel you use   (rval=0.5, aval=0.0)
>>>>
>>>> Also, we came up with an interesting way of adjusting the control
>>>> points
>>>> of quads and cubics if we adjusted their end points, but I don't
>> know
>>>> if
>>>> what we did was really the best idea.  For quads we adjust the
>> control
>>>>
>>>> point by the average of the adjustments that we applied to its 2
>> end
>>>> points.  For cubics, we move the first control point by the same
>>>> amount
>>>> as we moved the starting endpoint and the second control point by
>> the
>>>>
>>>> amount we moved the final endpoint.  The jury is out on whether
>> that
>>>> is
>>>> the most aesthetic technique...
>>>>
>>>> 			...jim
>>>>
>>>> Denis Lila wrote:
>>>>> Regarding VALUE_STROKE_NORMALIZE the API says:
>>>>>                  Stroke normalization control hint value --
>> geometry
>>>> should
>>>>>                  be normalized to improve uniformity or spacing of
>>>> lines and
>>>>>                  overall aesthetics. Note that different
>>>> normalization
>>>>>                  algorithms may be more successful than others for
>>>> given
>>>>>                  input paths.
>>>>>
>>>>> I can only think of one example where VALUE_STROKE_NORMALIZE makes
>> a
>>>> visible
>>>>> difference between the closed source implementation and OpenJDK:
>>>>> when drawing anti-aliased horizontal or vertical lines of width
>> 1,
>>>> Pisces
>>>>> draws a 2 pixel wide line with half intensity (because integer
>>>> coordinates
>>>>> are between pixels). Sun's jdk with VALUE_SROKE_NORMALIZE turned
>> on
>>>> draws
>>>>> a 1 pixel line with full intensity. This could to achieved by
>> just
>>>>> checking for normalization and rounding coordinates to the
>> nearest
>>>> half
>>>>> pixel, but this solution seems too simple, and I'm not sure
>> whether
>>>> I'm missing
>>>>> anything. It would also probably cause problems when drawing
>>>> anti-aliased
>>>>> short lines (which is done when drawing any sort of curve)
>>>>> Unless, of course, this rounding was restricted to just
>> horizontal
>>>> and
>>>>> vertical lines.
>>>>>
>>>>> Regards,
>>>>> Denis.

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic