Sat Aug 23 13:58:25 PDT 2008

```J. Ali Harlow wrote:
> Guys,
>
> I'm trying to use repeating gradient patterns to draw the background
> for a matrix of 27x27 cells. Cells are labelled with two colours. I
> want to show these by placing the first colour in the top-left corner
> and the second colour in the bottom-right corner. The obvious way to do
> that in cairo seems to be to use a gradient pattern. However, I have
> two problems:
>
> * The period of the repeating patterns seems to be too small. If you
> just run your eye from the top-left cell down the diagonal to the
> bottom-right this is quite obvious.

This is a result of a rounding error, and a regression with the change
from 16.16 to 24.8 bits fixed point math - the rounding error was much
smaller before.

(The cairo_pattern_create_linear(0,0,1/27.0,1/27.0) call converts the
coordinates to fixed point before storing them in the pattern. As a result,
the 1/27.0 becomes 9/256 - which is about 1/28.4, and indeed we have about
one and a half repetitions of the pattern too many along the diagonal.)

> * Half the cells are drawn as expected with the colour stops in the
> corners. The other half have the colour stops in the middle.

This is expected. The pattern gets repeated diagonally.

+----+----+----+----+
|       .'        .'
|     .'        .'
+    +    +    +    +
|  .'        .'
|.'        .'
+    +    +    +    +

> I attach a test problem to show what I am doing as well as it's output
> (png). Any pointers as to what I'm doing wrong would be much
> appreciated.

You have to translate the pattern. The way that's easiest to understand is
probably this:

pattern=bg_from_label(label);
cairo_save(cr);
cairo_translate(cr, i/27.0, j/27.0);
cairo_set_source(cr,pattern);
cairo_pattern_destroy(pattern);
cairo_rectangle(cr,0,0,1/27.0,1/27.0);
cairo_fill(cr);
cairo_restore(cr);

i.e. set up the cairo transformation so that the origin is the top left
corner of the rectangle to be drawn, /then/ set the pattern source.

You won't need the CAIRO_EXTEND_REPEAT then.

HTH,

Bertram

P.S. You can also set the pattern's transformation matrix:

cairo_pattern_t *bg_from_label(int label)
{
cairo_pattern_t *pattern;
pattern=cairo_pattern_create_linear(0, 0, 1, 1);
// set color stops
return pattern; // oops, this is missing in the original
}

// ...
cairo_matrix_t transform;
label=get_label(i,j);
pattern=bg_from_label(label);

cairo_matrix_init_translate(&transform, -i, -j);
cairo_matrix_scale(&transform, 27.0, 27.0);
cairo_pattern_set_matrix(pattern, &transform);

cairo_set_source(cr,pattern);
cairo_pattern_destroy(pattern);
cairo_rectangle(cr, i/27.0, j/27.0, 1/27.0, 1/27.0);
cairo_fill(cr);
// ...
```