[cairo] Repeating gradient patterns
Bertram Felgenhauer
bertram.felgenhauer at googlemail.com
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);
// ...
More information about the cairo
mailing list