1/2 pixel difference between x and y

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

1/2 pixel difference between x and y

hanrahan
I was testing the rasterization rules used by svg. To do this I tried
to draw a simple
grid. The grid was created with the following javascript program:

/**
 * gridtest.js:
 **/
var svgNS = "http://www.w3.org/2000/svg";

function createHLine( x1, x2, y ) {

    var line = document.createElementNS( svgNS, "rect" );

    line.setAttribute( "x", x1 );
    // offseting by a half fixes things ...
    // line.setAttribute( "y", y - 0.5 );
    line.setAttribute( "y", y );
    line.setAttribute( "width", x2-x1 );
    line.setAttribute( "height", 1 );
    line.setAttribute( "fill", "black" );
    line.setAttribute( "stroke", "none" );

    return line;
}

function createVLine( y1, y2, x ) {

    var line = document.createElementNS( svgNS, "rect" );

    line.setAttribute( "x", x );
    line.setAttribute( "y", y1 );
    line.setAttribute( "width", 1 );
    line.setAttribute( "height", y2-y1 );
    line.setAttribute( "fill", "black" );
    line.setAttribute( "stroke", "none" );

    return line;
}

function createGrid(w, h, dw, dh) {

    var group = document.createElementNS( svgNS, "g" );

    for(var x = 0; x <= w; x += dw) {
        var line = createVLine( 0, h, x );
        group.appendChild(line);
    }

    for(var y = 0; y <= h; y += dh) {
        var line = createHLine( 0, w, y );
        group.appendChild(line);
    }

    return group;
}

function makeChart() {

    var chart = document.createElementNS( svgNS, "svg" );
    chart.setAttribute("width", 512 );
    chart.setAttribute("height", 512 );

    grid = createGrid(512,512,128,128);
    chart.appendChild(grid);

    document.body.appendChild(chart);
}

The result can be viewed on

www.graphics.stanford.edu/~hanrahan/gridtest.html

If you look at the grid using a magnifier, you will see that the
horizontal lines are
two pixels thick, and the vertical lines are 1 pixel thick. Why are the
horizontal
and vertical lines different?

If you change the javascript so that the horizontall lines are offset
by -0.5,
then they are 1 pixel thick as expected. (But the top-most line is not
full black).

Any idea what is going on?

_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

Andreas Neumann
I am not a Mozilla SVG developer, and can't answer your question for
sure, but my guess is that the Mozilla SVG engine forwards the drawing
stuff to the underlying renderer (currently Cairo) and the differences
are caused by the renderer and the way it handles antialiasing.

One way to control this would be the "shape-rendering" attribute with
the values (auto | optimizeSpeed | crispEdges | geometricPrecision |
inherit) - but I don't know if this attribute is already implemented in
Mozilla SVG. Some viewers would render the graphics with different
antialiasing settings if the shape-rendering attribute is provided with
different values.

Andreas

_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

hanrahan
I'm also new to svg in firefox.

One test I also performed was write a similar program using pycairo
(version 1.0.2 of the cairo library on linux - I'm not sure what
version is used
in firefox 1.5). The linux cairo program works as I  expected (no
double
thickness horizontal lines).

I also tried various versions of the shape-rendering attribute and
as far as I can tell that is not the problem.

Thanks!

Pat

_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

Jonathan Watt-2
In reply to this post by hanrahan
Hi,

 From a quick look it seems that you're suffering from pixel smearing. There's
an explanation in the cairo FAQ (it uses the cairo interfaces but you should be
able to understand it fine):

   http://cairographics.org/FAQ#head-1e4c44156070bf4c097754b21ad0ef772874fd93

I have to ask though - why are you using rectangles to draw lines? There is a
<line> tag, although actually I'd recommend you use the <path> tag for drawing a
grid. Using a single <path> tag will be a lot more performant and easier to
build up with "move to A, draw line to B; move to C, draw line to D" commands.
For info on the syntax see:

   http://www.w3.org/TR/SVG/paths.html#PathDataGeneralInformation
   http://www.w3.org/TR/SVG/paths.html#PathDataMovetoCommands
   http://www.w3.org/TR/SVG/paths.html#PathDataLinetoCommands

I'd recommend that you use the absolute (uppercase letter) commands and not
relative (lowercase letter) commands since they are generally easier to
understand what's going on.

Jonathan

[hidden email] wrote:

> I was testing the rasterization rules used by svg. To do this I tried
> to draw a simple
> grid. The grid was created with the following javascript program:
>
> /**
>  * gridtest.js:
>  **/
> var svgNS = "http://www.w3.org/2000/svg";
>
> function createHLine( x1, x2, y ) {
>
>     var line = document.createElementNS( svgNS, "rect" );
>
>     line.setAttribute( "x", x1 );
>     // offseting by a half fixes things ...
>     // line.setAttribute( "y", y - 0.5 );
>     line.setAttribute( "y", y );
>     line.setAttribute( "width", x2-x1 );
>     line.setAttribute( "height", 1 );
>     line.setAttribute( "fill", "black" );
>     line.setAttribute( "stroke", "none" );
>
>     return line;
> }
>
> function createVLine( y1, y2, x ) {
>
>     var line = document.createElementNS( svgNS, "rect" );
>
>     line.setAttribute( "x", x );
>     line.setAttribute( "y", y1 );
>     line.setAttribute( "width", 1 );
>     line.setAttribute( "height", y2-y1 );
>     line.setAttribute( "fill", "black" );
>     line.setAttribute( "stroke", "none" );
>
>     return line;
> }
>
> function createGrid(w, h, dw, dh) {
>
>     var group = document.createElementNS( svgNS, "g" );
>
>     for(var x = 0; x <= w; x += dw) {
>         var line = createVLine( 0, h, x );
>         group.appendChild(line);
>     }
>
>     for(var y = 0; y <= h; y += dh) {
>         var line = createHLine( 0, w, y );
>         group.appendChild(line);
>     }
>
>     return group;
> }
>
> function makeChart() {
>
>     var chart = document.createElementNS( svgNS, "svg" );
>     chart.setAttribute("width", 512 );
>     chart.setAttribute("height", 512 );
>
>     grid = createGrid(512,512,128,128);
>     chart.appendChild(grid);
>
>     document.body.appendChild(chart);
> }
>
> The result can be viewed on
>
> www.graphics.stanford.edu/~hanrahan/gridtest.html
>
> If you look at the grid using a magnifier, you will see that the
> horizontal lines are
> two pixels thick, and the vertical lines are 1 pixel thick. Why are the
> horizontal
> and vertical lines different?
>
> If you change the javascript so that the horizontall lines are offset
> by -0.5,
> then they are 1 pixel thick as expected. (But the top-most line is not
> full black).
>
> Any idea what is going on?
>
_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

hanrahan
I read the FAQ that you mentioned. That all makes sense to me. I
understand
that pixel centers are at half-integers.

I've written a version of the program that uses the line tag. I offset
the lines by 1/2 a pixel
as suggested in the FAQ. But the problem persists. It seems like the y
coordinate
systems is shifted by half a pixel, and that there is some problem
drawing
at y=0.

The problem seems to go away if I use cairo directly.

Pat

_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

Jonathan Watt-2
Pat, can you put that version online?

[hidden email] wrote:

> I read the FAQ that you mentioned. That all makes sense to me. I
> understand
> that pixel centers are at half-integers.
>
> I've written a version of the program that uses the line tag. I offset
> the lines by 1/2 a pixel
> as suggested in the FAQ. But the problem persists. It seems like the y
> coordinate
> systems is shifted by half a pixel, and that there is some problem
> drawing
> at y=0.
>
> The problem seems to go away if I use cairo directly.
>
> Pat
>
_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

hanrahan
Yes, gladly!

I copied a new gridtest.js file. To run the test,

http://www.graphics.stanford.edu/~hanrahan/gridtest.html

To see the js

http://www.graphics.stanford.edu/~hanrahan/gridtest.js

I hope I am not doing anything too stupid!

Thanks for your help.

Pat

_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

Jonathan Watt-2
The cause seems to be the vertical distance the HTML content pushes down the
SVG. You can see this by setting the line-height for the <h1> to different
values. I'm not sure there's going to be a good solution to this problem. You
could find the absolute position of the svg element and adjust it, but it could
change as the window is resized (number of lines changes due to line wrapping
etc.). I guess it depends on how much trouble you're willing to go to for the
sake of crisp lines etc.

[hidden email] wrote:

> Yes, gladly!
>
> I copied a new gridtest.js file. To run the test,
>
> http://www.graphics.stanford.edu/~hanrahan/gridtest.html
>
> To see the js
>
> http://www.graphics.stanford.edu/~hanrahan/gridtest.js
>
> I hope I am not doing anything too stupid!
>
> Thanks for your help.
>
> Pat
>
_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

hanrahan
I see. I changed the line-height for h1 to be 24.5 (or any half-value)
and it now works as expected.

It would be nice to be able to make sure that the svg element was
snapped
to the pixel grid. But I can certainly work around this problem.

Thanks again.

Pat

_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

Jonas Sicking
Hmm.. this seems bad. Can't we align all toplevel svg elements to a
whole pixel? What is the argument for not doing that?

/ Sicking

[hidden email] wrote:

> I see. I changed the line-height for h1 to be 24.5 (or any half-value)
> and it now works as expected.
>
> It would be nice to be able to make sure that the svg element was
> snapped
> to the pixel grid. But I can certainly work around this problem.
>
> Thanks again.
>
> Pat
>
_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

Jonathan Watt-2
I think this is just what happens, not what we decided should happen. I'd be for
making that change (both horizontally and vertically).

Jonathan

Jonas Sicking wrote:

> Hmm.. this seems bad. Can't we align all toplevel svg elements to a
> whole pixel? What is the argument for not doing that?
>
> / Sicking
>
> [hidden email] wrote:
>> I see. I changed the line-height for h1 to be 24.5 (or any half-value)
>> and it now works as expected.
>>
>> It would be nice to be able to make sure that the svg element was
>> snapped
>> to the pixel grid. But I can certainly work around this problem.
>>
>> Thanks again.
>>
>> Pat
>>
_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

Jonas Sicking
We could align toplevel <svg> frames to to whole pixels, we do for some
other frames so there is precedent.

DBaron, roc? Any opinions on if we should/could do this? See
http://www.graphics.stanford.edu/~hanrahan/gridtest.html
for the result of not doing it (vertical lines look different from
horizontal).

/ Sicking

Jonathan Watt wrote:

> I think this is just what happens, not what we decided should happen.
> I'd be for making that change (both horizontally and vertically).
>
> Jonathan
>
> Jonas Sicking wrote:
>> Hmm.. this seems bad. Can't we align all toplevel svg elements to a
>> whole pixel? What is the argument for not doing that?
>>
>> / Sicking
>>
>> [hidden email] wrote:
>>> I see. I changed the line-height for h1 to be 24.5 (or any half-value)
>>> and it now works as expected.
>>>
>>> It would be nice to be able to make sure that the svg element was
>>> snapped
>>> to the pixel grid. But I can certainly work around this problem.
>>>
>>> Thanks again.
>>>
>>> Pat
>>>
_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg
Reply | Threaded
Open this post in threaded view
|

Re: 1/2 pixel difference between x and y

Robert O'Callahan-2
In reply to this post by Jonas Sicking
We don't adjust layout coordinates to position elements at whole-pixel
boundaries, because that would create situations where N adjacent
elements each K units in size (where K units is not a multiple of the
pixel size) are not the same size as a single element of size N*K
units. This could create large layout differences, for example, a line
wrapping when it shouldn't.

We *could* adjust the rendering of various elements so that certain
rectilinear elements have their rendering origin aligned to pixel
boundaries. I can't think of any reason to object to that. Jonathan or
Tim could do this for SVG; it sounds like a good idea.

Rob

_______________________________________________
Mozilla-svg mailing list
[hidden email]
http://mail.mozilla.org/listinfo/mozilla-svg