|
The render method is shared between GnomeCanvasRect and GnomeCanvasEllipse; all it does is
stamp the two paths created in the update method into the
RGB buffer:
static void
gnome_canvas_re_render (GnomeCanvasItem *item,
GnomeCanvasBuf *buf)
{
GnomeCanvasRE *re;
guint32 fg_color, bg_color;
re = GNOME_CANVAS_RE (item);
if (re->fill_svp != NULL) {
gnome_canvas_render_svp (buf, re->fill_svp, re->fill_color);
}
if (re->outline_svp != NULL) {
gnome_canvas_render_svp (buf, re->outline_svp, re->outline_color);
}
}
|
As you can see, most of the work takes place in gnome_canvas_render_svp(), another
function from
libgnomeui/gnome-canvas-util.h; here is its
implementation:
void
gnome_canvas_render_svp (GnomeCanvasBuf *buf, ArtSVP *svp, guint32 rgba)
{
guint32 fg_color, bg_color;
if (buf->is_bg) {
bg_color = buf->bg_color;
fg_color = rgba >> 8;
art_rgb_svp_aa (svp,
buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1,
fg_color, bg_color,
buf->buf, buf->buf_rowstride,
NULL);
buf->is_bg = 0;
buf->is_buf = 1;
} else {
art_rgb_svp_alpha (svp,
buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1,
rgba,
buf->buf, buf->buf_rowstride,
NULL);
}
}
|
To understand
gnome_canvas_render_svp(), or to do your own RGB
buffer drawing (without using
libart_lgpl), you will need to know what a GnomeCanvasBuf is:
typedef struct {
guchar *buf;
int buf_rowstride;
ArtIRect rect;
guint32 bg_color;
unsigned int is_bg : 1;
unsigned int is_buf : 1;
} GnomeCanvasBuf;
|
The buf member is an RGB
buffer, as explained in
the section called RGB Buffers in the chapter
called GDK Basics. The buf_rowstride is the buffer's
rowstride, also explained in the section called RGB
Buffers in the chapter called GDK Basics.
An ArtIRect is an integer
rectangle; rect defines
the redraw region in canvas pixel coordinates that this
buffer represents.
rect.x0 and
rect.y0 are the buffer offsets and correspond to
row 0, column 0 in the RGB buffer; you can convert from
canvas pixel coordinates to RGB buffer coordinates by
subtracting these values.
As an optimization, the canvas does not initialize the
RGB buffer with the background color, because the first
canvas item might cover the entire background anyway.
Thus, if your canvas item is the first one to render, you
must put some pixel value in every pixel of the redraw
region defined by the buffer's
rect. If your item does not cover a pixel, you
should fill that pixel with the
bg_color; bg_color
is a packed RGB value (no alpha). If you do this
manually, unpack an RGB value
rgb like this:
guchar r, g, b;
r = (rgb >> 16) & 0xff;
g = (rgb >> 8) & 0xff;
b = rgb & 0xff;
|
However, a convenience function is provided to fill a
GnomeCanvasBuf with its
bg_color:
void
gnome_canvas_buf_ensure_buf (GnomeCanvasBuf *buf)
{
guchar *bufptr;
int y;
if (!buf->is_buf) {
bufptr = buf->buf;
for (y = buf->rect.y0; y < buf->rect.y1; y++) {
art_rgb_fill_run (bufptr,
buf->bg_color >> 16,
(buf->bg_color >> 8) & 0xff,
buf->bg_color & 0xff,
buf->rect.x1 - buf->rect.x0);
bufptr += buf->buf_rowstride;
}
buf->is_buf = 1;
}
}
|
As you can see from the implementation of gnome_canvas_buf_ensure_buf(), is_bg is a flag indicating that
the RGB buffer still contains random memory garbage; it
has not been initialized with RGB pixels. is_buf indicates that the buffer has been initialized, and subsequent
items should only draw themselves, ignoring background
pixels. These two flags are mutually exclusive; if your
item receives a buffer with
is_bg set, it should take steps to fill the
buffer, unset is_bg, and
set is_buf:
if (buf->is_bg)
{
gnome_canvas_buf_ensure_buf(buf);
buf->is_bg = FALSE;
}
|
|
|