static void begin_render(DiaRenderer *self) { DiaCairoInteractiveRenderer *renderer = DIA_CAIRO_INTERACTIVE_RENDERER (self); DiaCairoRenderer *base_renderer = DIA_CAIRO_RENDERER (self); g_return_if_fail (base_renderer->cr == NULL); #if GTK_CHECK_VERSION(2,8,0) base_renderer->cr = gdk_cairo_create(renderer->pixmap); #else base_renderer->surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, get_width_pixels (self), get_height_pixels (self)); base_renderer->cr = cairo_create (base_renderer->surface); #endif cairo_scale (base_renderer->cr, *renderer->zoom_factor, *renderer->zoom_factor); cairo_translate (base_renderer->cr, -renderer->visible->left, -renderer->visible->top); #ifdef HAVE_PANGOCAIRO_H base_renderer->layout = pango_cairo_create_layout (base_renderer->cr); #endif cairo_set_fill_rule (base_renderer->cr, CAIRO_FILL_RULE_EVEN_ODD); #if 0 /* should we set the background color? Or do nothing at all? */ /* if this is drawn you can see 'clipping in action', outside of the clip it gets yellow ;) */ cairo_set_source_rgba (base_renderer->cr, 1.0, 1.0, .8, 1.0); cairo_set_operator (base_renderer->cr, CAIRO_OPERATOR_OVER); cairo_rectangle (base_renderer->cr, 0, 0, renderer->width, renderer->height); cairo_fill (base_renderer->cr); #endif }
static void set_font(DiaRenderer *self, DiaFont *font, real height) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); /* pango/cairo wants the font size, not the (line-) height */ real size = dia_font_get_size (font) * (height / dia_font_get_height (font)); PangoFontDescription *pfd = pango_font_description_copy (dia_font_get_description (font)); DIAG_NOTE(g_message("set_font %f %s", height, dia_font_get_family(font))); #ifdef HAVE_PANGOCAIRO_H /* select font and size */ pango_font_description_set_absolute_size (pfd, (int)(size * PANGO_SCALE)); pango_layout_set_font_description (renderer->layout, pfd); pango_font_description_free (pfd); #else if (renderer->cr) { DiaFontStyle style = dia_font_get_style (font); const char *family_name = dia_font_get_family(font); cairo_select_font_face ( renderer->cr, family_name, DIA_FONT_STYLE_GET_SLANT(style) == DIA_FONT_NORMAL ? CAIRO_FONT_SLANT_NORMAL : CAIRO_FONT_SLANT_ITALIC, DIA_FONT_STYLE_GET_WEIGHT(style) < DIA_FONT_MEDIUM ? CAIRO_FONT_WEIGHT_NORMAL : CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size (renderer->cr, size); DIAG_STATE(renderer->cr) }
static void fill_arc(DiaRenderer *self, Point *center, real width, real height, real angle1, real angle2, Color *color) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); Point start; double a1, a2; DIAG_NOTE(g_message("draw_arc %fx%f <%f,<%f", width, height, angle1, angle2)); cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); cairo_new_path (renderer->cr); start.x = center->x + (width / 2.0) * cos((M_PI / 180.0) * angle1); start.y = center->y - (height / 2.0) * sin((M_PI / 180.0) * angle1); cairo_move_to (renderer->cr, center->x, center->y); cairo_line_to (renderer->cr, start.x, start.y); a1 = - (angle1 / 180.0) * G_PI; a2 = - (angle2 / 180.0) * G_PI; /* FIXME: to handle width != height some cairo_scale/cairo_translate would be needed */ cairo_arc_negative (renderer->cr, center->x, center->y, width > height ? height / 2.0 : width / 2.0, /* FIXME 2nd radius */ a1, a2); cairo_line_to (renderer->cr, center->x, center->y); cairo_close_path (renderer->cr); cairo_fill (renderer->cr); DIAG_STATE(renderer->cr) }
static void fill_pixel_rect(DiaRenderer *object, int x, int y, int width, int height, Color *color) { #if 1 /* if we do it with cairo there is something wrong with the clipping? */ DiaCairoInteractiveRenderer *renderer = DIA_CAIRO_INTERACTIVE_RENDERER (object); GdkGC *gc = renderer->gc; GdkColor gdkcolor; color_convert(color, &gdkcolor); gdk_gc_set_foreground(gc, &gdkcolor); gdk_draw_rectangle (renderer->pixmap, gc, TRUE, x, y, width, height); #else DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (object); double x1u = x + .5, y1u = y + .5, x2u = x + width + .5, y2u = y + height + .5; double lw[2]; lw[0] = 1; lw[1] = 0; cairo_device_to_user_distance (renderer->cr, &lw[0], &lw[1]); cairo_set_line_width (renderer->cr, lw[0]); cairo_device_to_user (renderer->cr, &x1u, &y1u); cairo_device_to_user (renderer->cr, &x2u, &y2u); cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); cairo_rectangle (renderer->cr, x1u, y1u, x2u - x1u, y2u - y1u); cairo_fill (renderer->cr); #endif }
static void _polygon(DiaRenderer *self, Point *points, int num_points, Color *color, gboolean fill) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); int i; DIAG_NOTE(g_message("%s_polygon n:%d %f,%f ...", fill ? "fill" : "draw", num_points, points->x, points->y)); g_return_if_fail(1 < num_points); cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); cairo_new_path (renderer->cr); /* point data */ cairo_move_to (renderer->cr, points[0].x, points[0].y); for (i = 1; i < num_points; i++) { cairo_line_to (renderer->cr, points[i].x, points[i].y); } cairo_line_to (renderer->cr, points[0].x, points[0].y); cairo_close_path (renderer->cr); if (fill) cairo_fill (renderer->cr); else cairo_stroke (renderer->cr); DIAG_STATE(renderer->cr) }
static void begin_print (GtkPrintOperation *operation, GtkPrintContext *context, PrintData *print_data) { DiaCairoRenderer *cairo_renderer; g_return_if_fail (print_data->renderer != NULL); cairo_renderer = DIA_CAIRO_RENDERER (print_data->renderer); g_return_if_fail (cairo_renderer->cr == NULL); /* the renderer wants it's own reference */ #if 0 /* no alpha with printers */ cairo_renderer->with_alpha = TRUE; #endif cairo_renderer->cr = cairo_reference (gtk_print_context_get_cairo_context (context)); cairo_renderer->dia = print_data->data; #if 0 /* needs some text size scaling ... */ cairo_renderer->layout = gtk_print_context_create_pango_layout (context); #endif /* scaling - as usual I don't get it, or do I? */ cairo_renderer->scale = ( gtk_page_setup_get_paper_width (gtk_print_context_get_page_setup (context), GTK_UNIT_MM) - gtk_page_setup_get_left_margin( gtk_print_context_get_page_setup (context), GTK_UNIT_MM) - gtk_page_setup_get_right_margin( gtk_print_context_get_page_setup (context), GTK_UNIT_MM) ) / print_data->data->paper.width; cairo_renderer->skip_show_page = TRUE; }
/*! * \brief Set the fill style * The fill style is one of the areas, where the cairo library offers a lot * more the Dia currently uses. Cairo can render repeating patterns as well * as linear and radial gradients. As of this writing Dia just uses solid * color fill. * \memberof _DiaCairoRenderer */ static void set_fillstyle(DiaRenderer *self, FillStyle mode) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DIAG_NOTE(g_message("set_fillstyle %d", mode)); switch(mode) { case FILLSTYLE_SOLID: /* FIXME: how to set _no_ pattern ? * cairo_set_pattern (renderer->cr, NULL); */ break; default: g_warning("DiaCairoRenderer : Unsupported fill mode specified!\n"); } DIAG_STATE(DIA_CAIRO_RENDERER (self)->cr) }
static void set_dashlength(DiaRenderer *self, real length) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DIAG_NOTE(g_message("set_dashlength %f", length)); renderer->dash_length = length; }
static void cairo_interactive_renderer_finalize (GObject *object) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (object); if (renderer->cr) cairo_destroy (renderer->cr); G_OBJECT_CLASS (parent_class)->finalize (object); }
static void end_render(DiaRenderer *self) { DiaCairoInteractiveRenderer *renderer = DIA_CAIRO_INTERACTIVE_RENDERER (self); DiaCairoRenderer *base_renderer = DIA_CAIRO_RENDERER (self); cairo_show_page (base_renderer->cr); cairo_destroy (base_renderer->cr); base_renderer->cr = NULL; }
/*! * \brief Remember the given pattern to use for consecutive fill * @param self explicit this pointer * @param pattern linear or radial gradient */ static void set_pattern (DiaRenderer *self, DiaPattern *pattern) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DiaPattern *prev = renderer->pattern; if (pattern) renderer->pattern = g_object_ref (pattern); else renderer->pattern = pattern; if (prev) g_object_unref (prev); }
static void _rounded_rect (DiaRenderer *self, Point *topleft, Point *bottomright, Color *color, real radius, gboolean fill) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); double rv[2]; radius = MIN(radius, (bottomright->x - topleft->x)/2); radius = MIN(radius, (bottomright->y - topleft->y)/2); /* ignore radius if it is smaller than the device unit, avoids anti-aliasing artifacts */ rv[0] = radius; rv[1] = 0.0; cairo_user_to_device_distance (renderer->cr, &rv[0], &rv[1]); if (rv[0] < 1.0 && rv[1] < 1.0) { _rect (self, topleft, bottomright, color, fill); return; } DIAG_NOTE(g_message("%s_rounded_rect %f,%f -> %f,%f, %f", fill ? "fill" : "draw", topleft->x, topleft->y, bottomright->x, bottomright->y, radius)); cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); cairo_new_path (renderer->cr); cairo_move_to (renderer->cr, /* north-west */ topleft->x + radius, topleft->y); cairo_line_to (renderer->cr, /* north-east */ bottomright->x - radius, topleft->y); cairo_arc (renderer->cr, bottomright->x - radius, topleft->y + radius, radius, -G_PI_2, 0); cairo_line_to (renderer->cr, /* south-east */ bottomright->x, bottomright->y - radius); cairo_arc (renderer->cr, bottomright->x - radius, bottomright->y - radius, radius, 0, G_PI_2); cairo_line_to (renderer->cr, /* south-west */ topleft->x + radius, bottomright->y); cairo_arc (renderer->cr, topleft->x + radius, bottomright->y - radius, radius, G_PI_2, G_PI); cairo_line_to (renderer->cr, /* north-west */ topleft->x, topleft->y + radius); cairo_arc (renderer->cr, topleft->x + radius, topleft->y + radius, radius, G_PI, -G_PI_2); if (fill) cairo_fill (renderer->cr); else cairo_stroke (renderer->cr); DIAG_STATE(renderer->cr) }
static void end_render(DiaRenderer *self) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DIAG_NOTE(g_message( "end_render")); if (!renderer->skip_show_page) cairo_show_page (renderer->cr); /* pop current state, so we can start from new with every page */ cairo_restore (renderer->cr); DIAG_STATE(renderer->cr) }
static void cairo_renderer_finalize (GObject *object) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (object); cairo_destroy (renderer->cr); #ifdef HAVE_PANGOCAIRO_H if (renderer->layout) g_object_unref (renderer->layout); #endif G_OBJECT_CLASS (parent_class)->finalize (object); }
static void end_render(DiaRenderer *self) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DIAG_NOTE(g_message( "end_render")); if (!renderer->skip_show_page) cairo_show_page (renderer->cr); DIAG_STATE(renderer->cr) if (renderer->surface) cairo_surface_destroy (renderer->surface); DIAG_STATE(renderer->cr) }
static void set_linewidth(DiaRenderer *self, real linewidth) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DIAG_NOTE(g_message("set_linewidth %f", linewidth)); /* make hairline? Everythnig below one device unit get the same width, * otherwise 0.0 may end up thicker than 0.0+epsilon */ ensure_minimum_one_device_unit(renderer, &linewidth); cairo_set_line_width (renderer->cr, linewidth); DIAG_STATE(renderer->cr) }
/*! * \brief Render the given object optionally transformed by matrix * @param self explicit this pointer * @param object the _DiaObject to draw * @param matrix the trnsformation matrix to use or NULL */ static void draw_object (DiaRenderer *self, DiaObject *object, DiaMatrix *matrix) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); cairo_matrix_t before; if (matrix) { cairo_get_matrix (renderer->cr, &before); g_assert (sizeof(cairo_matrix_t) == sizeof(DiaMatrix)); cairo_transform (renderer->cr, (cairo_matrix_t *)matrix); } object->ops->draw(object, DIA_RENDERER (renderer)); if (matrix) cairo_set_matrix (renderer->cr, &before); }
static void set_dashlength(DiaRenderer *self, real length) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DIAG_NOTE(g_message("set_dashlength %f", length)); /* this call does not make sense, the value is certainly bigger * than one device unit. But the side-effect seems to end the endless loop */ ensure_minimum_one_device_unit(renderer, &length); renderer->dash_length = length; /* updating the line style (potentially once more) make the real * style and it's length indepndent of the calling sequence */ set_linestyle(self, renderer->line_style); }
static void draw_line(DiaRenderer *self, Point *start, Point *end, Color *color) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DIAG_NOTE(g_message("draw_line %f,%f -> %f, %f", start->x, start->y, end->x, end->y)); cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); cairo_move_to (renderer->cr, start->x, start->y); cairo_line_to (renderer->cr, end->x, end->y); cairo_stroke (renderer->cr); DIAG_STATE(renderer->cr) }
static void set_linestyle(DiaRenderer *self, LineStyle mode) { /* dot = 10% of len */ DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); double dash[6]; DIAG_NOTE(g_message("set_linestyle %d", mode)); /* also stored for use in set_dashlength */ renderer->line_style = mode; /* line type */ switch (mode) { case LINESTYLE_SOLID: cairo_set_dash (renderer->cr, NULL, 0, 0); break; case LINESTYLE_DASHED: dash[0] = renderer->dash_length; dash[1] = renderer->dash_length; cairo_set_dash (renderer->cr, dash, 2, 0); break; case LINESTYLE_DASH_DOT: dash[0] = renderer->dash_length; dash[1] = renderer->dash_length * 0.45; dash[2] = renderer->dash_length * 0.1; dash[3] = renderer->dash_length * 0.45; cairo_set_dash (renderer->cr, dash, 4, 0); break; case LINESTYLE_DASH_DOT_DOT: dash[0] = renderer->dash_length; dash[1] = renderer->dash_length * (0.8/3); dash[2] = renderer->dash_length * 0.1; dash[3] = renderer->dash_length * (0.8/3); dash[4] = renderer->dash_length * 0.1; dash[5] = renderer->dash_length * (0.8/3); cairo_set_dash (renderer->cr, dash, 6, 0); break; case LINESTYLE_DOTTED: dash[0] = renderer->dash_length * 0.1; dash[1] = renderer->dash_length * 0.1; cairo_set_dash (renderer->cr, dash, 2, 0); break; default: g_warning("DiaCairoRenderer : Unsupported line style specified!\n"); } DIAG_STATE(renderer->cr) }
static void _ellipse(DiaRenderer *self, Point *center, real width, real height, Color *color, gboolean fill) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); double co; DIAG_NOTE(g_message("%s_ellipse %fx%f center @ %f,%f", fill ? "fill" : "draw", width, height, center->x, center->y)); cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); #if 1 cairo_save (renderer->cr); /* copied straight from cairo's documentation, and fixed the bug there */ cairo_translate (renderer->cr, center->x, center->y); cairo_scale (renderer->cr, width / 2., height / 2.); cairo_arc (renderer->cr, 0., 0., 1., 0., 2 * G_PI); cairo_restore (renderer->cr); #else /* FIXME: how to make a perfect ellipse from a bezier ? */ co = sqrt(pow(width,2)/4 + pow(height,2)/4); cairo_new_path (renderer->cr); cairo_move_to (renderer->cr, center->x, center->y - height/2); cairo_curve_to (renderer->cr, center->x + co, center->y - height/2, center->x + co, center->y + height/2, center->x, center->y + height/2); cairo_curve_to (renderer->cr, center->x - co, center->y + height/2, center->x - co, center->y - height/2, center->x, center->y - height/2); #endif if (fill) cairo_fill (renderer->cr); else cairo_stroke (renderer->cr); DIAG_STATE(renderer->cr) }
/*! * \brief Render the given object optionally transformed by matrix * @param self explicit this pointer * @param object the _DiaObject to draw * @param matrix the transformation matrix to use or NULL */ static void draw_object (DiaRenderer *self, DiaObject *object, DiaMatrix *matrix) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); cairo_matrix_t before; if (matrix) { /* at least in SVG the intent of an invalid matrix is not rendering */ if (!dia_matrix_is_invertible(matrix)) return; cairo_get_matrix (renderer->cr, &before); g_assert (sizeof(cairo_matrix_t) == sizeof(DiaMatrix)); cairo_transform (renderer->cr, (cairo_matrix_t *)matrix); } object->ops->draw(object, DIA_RENDERER (renderer)); if (matrix) cairo_set_matrix (renderer->cr, &before); }
static void _bezier(DiaRenderer *self, BezPoint *points, int numpoints, Color *color, gboolean fill) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); int i; DIAG_NOTE(g_message("%s_bezier n:%d %fx%f ...", fill ? "fill" : "draw", numpoints, points->p1.x, points->p1.y)); cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); cairo_new_path (renderer->cr); for (i = 0; i < numpoints; i++) { switch (points[i].type) { case BEZ_MOVE_TO: cairo_move_to (renderer->cr, points[i].p1.x, points[i].p1.y); break; case BEZ_LINE_TO: cairo_line_to (renderer->cr, points[i].p1.x, points[i].p1.y); break; case BEZ_CURVE_TO: cairo_curve_to (renderer->cr, points[i].p1.x, points[i].p1.y, points[i].p2.x, points[i].p2.y, points[i].p3.x, points[i].p3.y); break; default : g_assert_not_reached (); } } if (fill) cairo_fill (renderer->cr); else cairo_stroke (renderer->cr); DIAG_STATE(renderer->cr) }
static void set_linewidth(DiaRenderer *self, real linewidth) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DIAG_NOTE(g_message("set_linewidth %f", linewidth)); /* make hairline? */ if (linewidth == 0.0) { double ax = 0.0, ay = 0.0; double bx = 1.0, by = 0.0; cairo_device_to_user_distance (renderer->cr, &ax, &ay); cairo_device_to_user_distance (renderer->cr, &bx, &by); linewidth = sqrt ((bx - ax) * (bx - ax) + (by - ay) * (by - ay)); } cairo_set_line_width (renderer->cr, linewidth); DIAG_STATE(renderer->cr) }
static void draw_pixel_rect(DiaRenderer *object, int x, int y, int width, int height, Color *color) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (object); double x1u = x + .5, y1u = y + .5, x2u = x + width + .5, y2u = y + height + .5; double lw[2]; lw[0] = 1; lw[1] = 0; cairo_device_to_user_distance (renderer->cr, &lw[0], &lw[1]); cairo_set_line_width (renderer->cr, lw[0]); cairo_device_to_user (renderer->cr, &x1u, &y1u); cairo_device_to_user (renderer->cr, &x2u, &y2u); cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); cairo_rectangle (renderer->cr, x1u, y1u, x2u - x1u, y2u - y1u); cairo_stroke (renderer->cr); }
static void draw_pixel_line(DiaRenderer *object, int x1, int y1, int x2, int y2, Color *color) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (object); double x1u = x1 + .5, y1u = y1 + .5, x2u = x2 + .5, y2u = y2 + .5; double lw[2]; lw[0] = 1; lw[1] = 0; cairo_device_to_user_distance (renderer->cr, &lw[0], &lw[1]); cairo_set_line_width (renderer->cr, lw[0]); cairo_device_to_user (renderer->cr, &x1u, &y1u); cairo_device_to_user (renderer->cr, &x2u, &y2u); cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); cairo_move_to (renderer->cr, x1u, y1u); cairo_line_to (renderer->cr, x2u, y2u); cairo_stroke (renderer->cr); }
static void set_size(DiaRenderer *object, gpointer window, int width, int height) { DiaCairoInteractiveRenderer *renderer = DIA_CAIRO_INTERACTIVE_RENDERER (object); DiaCairoRenderer *base_renderer = DIA_CAIRO_RENDERER (object); renderer->width = width; renderer->height = height; if (renderer->pixmap != NULL) gdk_drawable_unref(renderer->pixmap); /* TODO: we can probably get rid of this extra pixmap and just draw directly to what gdk_cairo_create() gives us for the window */ renderer->pixmap = gdk_pixmap_new(GDK_WINDOW(window), width, height, -1); if (base_renderer->surface != NULL) cairo_surface_destroy(base_renderer->surface); if (renderer->gc == NULL) { renderer->gc = gdk_gc_new(renderer->pixmap); } }
static void set_linejoin(DiaRenderer *self, LineJoin mode) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DIAG_NOTE(g_message("set_join %d", mode)); switch(mode) { case LINEJOIN_MITER: cairo_set_line_join (renderer->cr, CAIRO_LINE_JOIN_MITER); break; case LINEJOIN_ROUND: cairo_set_line_join (renderer->cr, CAIRO_LINE_JOIN_ROUND); break; case LINEJOIN_BEVEL: cairo_set_line_join (renderer->cr, CAIRO_LINE_JOIN_BEVEL); break; default: g_warning("DiaCairoRenderer : Unsupported join mode specified!\n"); } DIAG_STATE(renderer->cr) }
static void set_linecaps(DiaRenderer *self, LineCaps mode) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DIAG_NOTE(g_message("set_linecaps %d", mode)); switch(mode) { case LINECAPS_BUTT: cairo_set_line_cap (renderer->cr, CAIRO_LINE_CAP_BUTT); break; case LINECAPS_ROUND: cairo_set_line_cap (renderer->cr, CAIRO_LINE_CAP_ROUND); break; case LINECAPS_PROJECTING: cairo_set_line_cap (renderer->cr, CAIRO_LINE_CAP_SQUARE); /* ?? */ break; default: g_warning("DiaCairoRenderer : Unsupported caps mode specified!\n"); } DIAG_STATE(renderer->cr) }
static void _rect(DiaRenderer *self, Point *ul_corner, Point *lr_corner, Color *color, gboolean fill) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); DIAG_NOTE(g_message("%s_rect %f,%f -> %f,%f", fill ? "fill" : "draw", ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y)); cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); cairo_rectangle (renderer->cr, ul_corner->x, ul_corner->y, lr_corner->x - ul_corner->x, lr_corner->y - ul_corner->y); if (fill) cairo_fill (renderer->cr); else cairo_stroke (renderer->cr); DIAG_STATE(renderer->cr) }