Scaling and round-off errors

The only way to avoid all round-off errors when scaling an SXG image is to:

  1. Use whole numbers for all coordinates in the SXG file.

  2. Use the smallest possible width and height.

  3. Set the widthfactor and heightfactor to be same as the width and height.

This results in the SXG image always getting scaled by a multiple of its original size, With simple SXG images containing only horizontal, vertical, and rectangular components, it might be possible to avoid using widthfactor and heightfactor, or perhaps setting them to some small power of 2, with tolerable rounding artifacts.

Defining a background color makes it possible to scale the SXG image smaller, but produce a final image with the requested size by filling the extra padding with a background color.

Scaling algorithm

When scaling pixel coordinates, each pixel coordinate represents the center of a virtual pixel. If, for example, the image is scaled to five times its virtual size, pixel coordinate (0, 0) becomes (2, 2). Each virtual pixel is now five pixels across and five pixels tall, with coordinate (2, 2) being its center (and virtual pixel (1, 0) becoming physical pixel (7, 2), and so on).

However, the fill element, for both pictures and pixmaps, as well as the picture clip and composite elements translate virtual X and Y coordinates to the top left corner of the corresponding physical pixels. If, for example, the image gets scaled to five times its nominal size, then

<fill>
  <x>0</x>
  <y>0</y>
  <width>4</width>
  <height4</height>
</fill>

ends up clearing pixels (0, 0) through (15, 15), and not (2, 2) through (17, 17).

In all other elements x and y have an optional attribute that adjust the default scaling of the coordinate to the pixel's center:

  <gc id="pixmap1_gc">

  <!-- -->

    <line>
      <point>
        <x orientation='beginning'>0</x>
        <y orientation='beginning'>0</y>
      </point>
      <point>
        <x orientation='ending'>5</x>
        <y orientation='ending'>5</y>
      </point>
    </line>

  <!-- -->

  </gc>

This example draws a line from the top-left corner of the scaled pixel (0, 0) to the bottom-right corner of the scaled pixel (5, 5), Normally each coordinate gets translated to the center of the scaled pixel. If this image gets scaled to three times it's original size, this draws a line from (0, 0) to (14, 14) instead of (1, 1) to (13, 13).

The orientation attribute's value is either centered, the default translation to the center of the scaled pixel; or beginning, which scales the coordinate to the starting point of the scaled pixel; or ending, the opposite of beginning, which scales the coordinate to the ending point of the scaled pixel, In this case, the coordinate gets scaled to (24, 24), and the logo pictures get center-aligned itself, over this coordinate.

  <!-- -->
    <line>
      <point>
	<x orientation="width">0</x>
	<y orientation="width">0</y>
      </point>

  <!-- -->

The width orientation is available only in lines. This orientation scales the coordinate as follows.

  • Use the centered orientation if the scaled line_width is 0.

  • Use the beginning orientation if the scaled line_width is not 0, then add line_width/2 to the computed coordinate.