/* Dia -- an diagram creation/manipulation program * Copyright (C) 1998 Alexander Larsson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "render_gdk.h" #include "message.h" static void begin_render(RendererGdk *renderer, DiagramData *data); static void end_render(RendererGdk *renderer); static void set_linewidth(RendererGdk *renderer, real linewidth); static void set_linecaps(RendererGdk *renderer, LineCaps mode); static void set_linejoin(RendererGdk *renderer, LineJoin mode); static void set_linestyle(RendererGdk *renderer, LineStyle mode); static void set_dashlength(RendererGdk *renderer, real length); static void set_fillstyle(RendererGdk *renderer, FillStyle mode); static void set_font(RendererGdk *renderer, Font *font, real height); static void draw_line(RendererGdk *renderer, Point *start, Point *end, Color *line_color); static void draw_polyline(RendererGdk *renderer, Point *points, int num_points, Color *line_color); static void draw_polygon(RendererGdk *renderer, Point *points, int num_points, Color *line_color); static void fill_polygon(RendererGdk *renderer, Point *points, int num_points, Color *line_color); static void draw_rect(RendererGdk *renderer, Point *ul_corner, Point *lr_corner, Color *color); static void fill_rect(RendererGdk *renderer, Point *ul_corner, Point *lr_corner, Color *color); static void draw_arc(RendererGdk *renderer, Point *center, real width, real height, real angle1, real angle2, Color *color); static void fill_arc(RendererGdk *renderer, Point *center, real width, real height, real angle1, real angle2, Color *color); static void draw_ellipse(RendererGdk *renderer, Point *center, real width, real height, Color *color); static void fill_ellipse(RendererGdk *renderer, Point *center, real width, real height, Color *color); static void draw_bezier(RendererGdk *renderer, BezPoint *points, int numpoints, Color *color); static void fill_bezier(RendererGdk *renderer, BezPoint *points, /* Last point must be same as first point */ int numpoints, Color *color); static void draw_string(RendererGdk *renderer, const char *text, Point *pos, Alignment alignment, Color *color); static void draw_image(RendererGdk *renderer, Point *point, real width, real height, DiaImage image); static real get_text_width(RendererGdk *renderer, const char *text, int length); static void clip_region_clear(RendererGdk *renderer); static void clip_region_add_rect(RendererGdk *renderer, Rectangle *rect); static void draw_pixel_line(RendererGdk *renderer, int x1, int y1, int x2, int y2, Color *color); static void draw_pixel_rect(RendererGdk *renderer, int x, int y, int width, int height, Color *color); static void fill_pixel_rect(RendererGdk *renderer, int x, int y, int width, int height, Color *color); static RenderOps GdkRenderOps = { (BeginRenderFunc) begin_render, (EndRenderFunc) end_render, (SetLineWidthFunc) set_linewidth, (SetLineCapsFunc) set_linecaps, (SetLineJoinFunc) set_linejoin, (SetLineStyleFunc) set_linestyle, (SetDashLengthFunc) set_dashlength, (SetFillStyleFunc) set_fillstyle, (SetFontFunc) set_font, (DrawLineFunc) draw_line, (DrawPolyLineFunc) draw_polyline, (DrawPolygonFunc) draw_polygon, (FillPolygonFunc) fill_polygon, (DrawRectangleFunc) draw_rect, (FillRectangleFunc) fill_rect, (DrawArcFunc) draw_arc, (FillArcFunc) fill_arc, (DrawEllipseFunc) draw_ellipse, (FillEllipseFunc) fill_ellipse, (DrawBezierFunc) draw_bezier, (FillBezierFunc) fill_bezier, (DrawStringFunc) draw_string, (DrawImageFunc) draw_image, }; static InteractiveRenderOps GdkInteractiveRenderOps = { (GetTextWidthFunc) get_text_width, (ClipRegionClearFunc) clip_region_clear, (ClipRegionAddRectangleFunc) clip_region_add_rect, (DrawPixelLineFunc) draw_pixel_line, (DrawPixelRectangleFunc) draw_pixel_rect, (FillPixelRectangleFunc) fill_pixel_rect, }; RendererGdk * new_gdk_renderer(DDisplay *ddisp) { RendererGdk *renderer; renderer = g_new(RendererGdk, 1); renderer->renderer.ops = &GdkRenderOps; renderer->renderer.is_interactive = 1; renderer->renderer.interactive_ops = &GdkInteractiveRenderOps; renderer->ddisp = ddisp; renderer->render_gc = NULL; renderer->pixmap = NULL; renderer->renderer.pixel_width = 0; renderer->renderer.pixel_height = 0; renderer->clip_region = NULL; renderer->line_width = 1; renderer->line_style = GDK_LINE_SOLID; renderer->cap_style = GDK_CAP_BUTT; renderer->join_style = GDK_JOIN_MITER; renderer->saved_line_style = LINESTYLE_SOLID; renderer->dash_length = 10; renderer->dot_length = 2; return renderer; } void destroy_gdk_renderer(RendererGdk *renderer) { if (renderer->pixmap != NULL) gdk_pixmap_unref(renderer->pixmap); if (renderer->render_gc != NULL) gdk_gc_unref(renderer->render_gc); if (renderer->clip_region != NULL) gdk_region_destroy(renderer->clip_region); g_free(renderer); } void gdk_renderer_set_size(RendererGdk *renderer, GdkWindow *window, int width, int height) { if (renderer->pixmap != NULL) { gdk_pixmap_unref(renderer->pixmap); } renderer->pixmap = gdk_pixmap_new(window, width, height, -1); renderer->renderer.pixel_width = width; renderer->renderer.pixel_height = height; if (renderer->render_gc == NULL) { renderer->render_gc = gdk_gc_new(renderer->pixmap); gdk_gc_set_line_attributes(renderer->render_gc, renderer->line_width, renderer->line_style, renderer->cap_style, renderer->join_style); } } extern void renderer_gdk_copy_to_window(RendererGdk *renderer, GdkWindow *window, int x, int y, int width, int height) { static GdkGC *copy_gc = NULL; if (copy_gc == NULL) { copy_gc = gdk_gc_new(window); } gdk_draw_pixmap(window, copy_gc, renderer->pixmap, x, y, x, y, width, height); } static void begin_render(RendererGdk *renderer, DiagramData *data) { } static void end_render(RendererGdk *renderer) { } static void set_linewidth(RendererGdk *renderer, real linewidth) { /* 0 == hairline **/ renderer->line_width = ddisplay_transform_length(renderer->ddisp, linewidth); if (renderer->line_width<=0) renderer->line_width = 1; /* Minimum 1 pixel. */ gdk_gc_set_line_attributes(renderer->render_gc, renderer->line_width, renderer->line_style, renderer->cap_style, renderer->join_style); } static void set_linecaps(RendererGdk *renderer, LineCaps mode) { switch(mode) { case LINECAPS_BUTT: renderer->cap_style = GDK_CAP_BUTT; break; case LINECAPS_ROUND: renderer->cap_style = GDK_CAP_ROUND; break; case LINECAPS_PROJECTING: renderer->cap_style = GDK_CAP_PROJECTING; break; } gdk_gc_set_line_attributes(renderer->render_gc, renderer->line_width, renderer->line_style, renderer->cap_style, renderer->join_style); } static void set_linejoin(RendererGdk *renderer, LineJoin mode) { switch(mode) { case LINEJOIN_MITER: renderer->cap_style = GDK_JOIN_MITER; break; case LINEJOIN_ROUND: renderer->cap_style = GDK_JOIN_ROUND; break; case LINEJOIN_BEVEL: renderer->cap_style = GDK_JOIN_BEVEL; break; } gdk_gc_set_line_attributes(renderer->render_gc, renderer->line_width, renderer->line_style, renderer->cap_style, renderer->join_style); } static void set_linestyle(RendererGdk *renderer, LineStyle mode) { char dash_list[6]; int hole_width; renderer->saved_line_style = mode; switch(mode) { case LINESTYLE_SOLID: renderer->line_style = GDK_LINE_SOLID; break; case LINESTYLE_DASHED: renderer->line_style = GDK_LINE_ON_OFF_DASH; dash_list[0] = renderer->dash_length; dash_list[1] = renderer->dash_length; gdk_gc_set_dashes(renderer->render_gc, 0, dash_list, 2); break; case LINESTYLE_DASH_DOT: renderer->line_style = GDK_LINE_ON_OFF_DASH; hole_width = (renderer->dash_length - renderer->dot_length) / 2; if (hole_width==0) hole_width = 1; dash_list[0] = renderer->dash_length; dash_list[1] = hole_width; dash_list[2] = renderer->dot_length; dash_list[3] = hole_width; gdk_gc_set_dashes(renderer->render_gc, 0, dash_list, 4); break; case LINESTYLE_DASH_DOT_DOT: renderer->line_style = GDK_LINE_ON_OFF_DASH; hole_width = (renderer->dash_length - 2*renderer->dot_length) / 3; if (hole_width==0) hole_width = 1; dash_list[0] = renderer->dash_length; dash_list[1] = hole_width; dash_list[2] = renderer->dot_length; dash_list[3] = hole_width; dash_list[4] = renderer->dot_length; dash_list[5] = hole_width; gdk_gc_set_dashes(renderer->render_gc, 0, dash_list, 6); break; case LINESTYLE_DOTTED: renderer->line_style = GDK_LINE_ON_OFF_DASH; dash_list[0] = renderer->dot_length; dash_list[1] = renderer->dot_length; gdk_gc_set_dashes(renderer->render_gc, 0, dash_list, 2); break; } gdk_gc_set_line_attributes(renderer->render_gc, renderer->line_width, renderer->line_style, renderer->cap_style, renderer->join_style); } static void set_dashlength(RendererGdk *renderer, real length) { /* dot = 10% of len */ real ddisp_len; ddisp_len = ddisplay_transform_length(renderer->ddisp, length); renderer->dash_length = (int)floor(ddisp_len+0.5); renderer->dot_length = (int)floor(ddisp_len*0.1+0.5); if (renderer->dash_length<=0) renderer->dash_length = 1; if (renderer->dash_length>255) renderer->dash_length = 255; if (renderer->dot_length<=0) renderer->dot_length = 1; if (renderer->dot_length>255) renderer->dot_length = 255; set_linestyle(renderer, renderer->saved_line_style); } static void set_fillstyle(RendererGdk *renderer, FillStyle mode) { switch(mode) { case FILLSTYLE_SOLID: break; default: message_error("gdk_renderer: Unsupported fill mode specified!\n"); } } static void set_font(RendererGdk *renderer, Font *font, real height) { renderer->font_height = ddisplay_transform_length(renderer->ddisp, height); renderer->gdk_font = font_get_gdkfont(font, renderer->font_height); } static void draw_line(RendererGdk *renderer, Point *start, Point *end, Color *line_color) { DDisplay *ddisp = renderer->ddisp; GdkGC *gc = renderer->render_gc; GdkColor color; int x1,y1,x2,y2; ddisplay_transform_coords(ddisp, start->x, start->y, &x1, &y1); ddisplay_transform_coords(ddisp, end->x, end->y, &x2, &y2); color_convert(line_color, &color); gdk_gc_set_foreground(gc, &color); gdk_draw_line(renderer->pixmap, gc, x1, y1, x2, y2); } static void draw_polyline(RendererGdk *renderer, Point *points, int num_points, Color *line_color) { DDisplay *ddisp = renderer->ddisp; GdkGC *gc = renderer->render_gc; GdkColor color; GdkPoint *gdk_points; int i,x,y; gdk_points = g_new(GdkPoint, num_points); for (i=0;ipixmap, gc, gdk_points, num_points); g_free(gdk_points); } static void draw_polygon(RendererGdk *renderer, Point *points, int num_points, Color *line_color) { DDisplay *ddisp = renderer->ddisp; GdkGC *gc = renderer->render_gc; GdkColor color; GdkPoint *gdk_points; int i,x,y; gdk_points = g_new(GdkPoint, num_points); for (i=0;ipixmap, gc, FALSE, gdk_points, num_points); g_free(gdk_points); } static void fill_polygon(RendererGdk *renderer, Point *points, int num_points, Color *line_color) { DDisplay *ddisp = renderer->ddisp; GdkGC *gc = renderer->render_gc; GdkColor color; GdkPoint *gdk_points; int i,x,y; gdk_points = g_new(GdkPoint, num_points); for (i=0;ipixmap, gc, TRUE, gdk_points, num_points); g_free(gdk_points); } static void draw_rect(RendererGdk *renderer, Point *ul_corner, Point *lr_corner, Color *color) { DDisplay *ddisp = renderer->ddisp; GdkGC *gc = renderer->render_gc; GdkColor gdkcolor; gint top, bottom, left, right; ddisplay_transform_coords(ddisp, ul_corner->x, ul_corner->y, &left, &top); ddisplay_transform_coords(ddisp, lr_corner->x, lr_corner->y, &right, &bottom); if ((left>right) || (top>bottom)) return; color_convert(color, &gdkcolor); gdk_gc_set_foreground(gc, &gdkcolor); gdk_draw_rectangle (renderer->pixmap, gc, FALSE, left, top, right-left, bottom-top); } static void fill_rect(RendererGdk *renderer, Point *ul_corner, Point *lr_corner, Color *color) { DDisplay *ddisp = renderer->ddisp; GdkGC *gc = renderer->render_gc; GdkColor gdkcolor; gint top, bottom, left, right; ddisplay_transform_coords(ddisp, ul_corner->x, ul_corner->y, &left, &top); ddisplay_transform_coords(ddisp, lr_corner->x, lr_corner->y, &right, &bottom); if ((left>right) || (top>bottom)) return; color_convert(color, &gdkcolor); gdk_gc_set_foreground(gc, &gdkcolor); gdk_draw_rectangle (renderer->pixmap, gc, TRUE, left, top, right-left, bottom-top); } static void draw_arc(RendererGdk *renderer, Point *center, real width, real height, real angle1, real angle2, Color *color) { DDisplay *ddisp = renderer->ddisp; GdkGC *gc = renderer->render_gc; GdkColor gdkcolor; gint top, left, bottom, right; real dangle; ddisplay_transform_coords(ddisp, center->x - width/2, center->y - height/2, &left, &top); ddisplay_transform_coords(ddisp, center->x + width/2, center->y + height/2, &right, &bottom); if ((left>right) || (top>bottom)) return; color_convert(color, &gdkcolor); gdk_gc_set_foreground(gc, &gdkcolor); dangle = angle2-angle1; if (dangle<0) dangle += 360.0; gdk_draw_arc(renderer->pixmap, gc, FALSE, left, top, right-left, bottom-top, (int) (angle1*64.0), (int) (dangle*64.0)); } static void fill_arc(RendererGdk *renderer, Point *center, real width, real height, real angle1, real angle2, Color *color) { DDisplay *ddisp = renderer->ddisp; GdkGC *gc = renderer->render_gc; GdkColor gdkcolor; gint top, left, bottom, right; real dangle; ddisplay_transform_coords(ddisp, center->x - width/2, center->y - height/2, &left, &top); ddisplay_transform_coords(ddisp, center->x + width/2, center->y + height/2, &right, &bottom); if ((left>right) || (top>bottom)) return; color_convert(color, &gdkcolor); gdk_gc_set_foreground(gc, &gdkcolor); dangle = angle2-angle1; if (dangle<0) dangle += 360.0; gdk_draw_arc(renderer->pixmap, gc, TRUE, left, top, right-left, bottom-top, (int) (angle1*64), (int) (dangle*64)); } static void draw_ellipse(RendererGdk *renderer, Point *center, real width, real height, Color *color) { draw_arc(renderer, center, width, height, 0.0, 360.0, color); } static void fill_ellipse(RendererGdk *renderer, Point *center, real width, real height, Color *color) { fill_arc(renderer, center, width, height, 0.0, 360.0, color); } struct bezier_curve { GdkPoint *gdk_points; int numpoints; int currpoint; }; #define BEZIER_SUBDIVIDE_LIMIT 0.03 #define BEZIER_SUBDIVIDE_LIMIT_SQ (BEZIER_SUBDIVIDE_LIMIT*BEZIER_SUBDIVIDE_LIMIT) static void bezier_add_point(DDisplay *ddisp, struct bezier_curve *bezier, Point *point) { int x,y; /* Grow if needed: */ if (bezier->currpoint == bezier->numpoints) { bezier->numpoints += 40; bezier->gdk_points = g_realloc(bezier->gdk_points, bezier->numpoints*sizeof(GdkPoint)); } ddisplay_transform_coords(ddisp, point->x, point->y, &x, &y); bezier->gdk_points[bezier->currpoint].x = x; bezier->gdk_points[bezier->currpoint].y = y; bezier->currpoint++; } static void bezier_add_lines(DDisplay *ddisp, Point points[4], struct bezier_curve *bezier) { Point u, v, x, y; Point r[4]; Point s[4]; Point middle; coord delta; real v_len_sq; /* Check if almost flat: */ u = points[1]; point_sub(&u, &points[0]); v = points[3]; point_sub(&v, &points[0]); y = v; v_len_sq = point_dot(&v,&v); if (isnan(v_len_sq)) { g_warning("v_len_sq is NaN while calculating bezier curve!"); return; } if (v_len_sq < 0.000001) v_len_sq = 0.000001; point_scale(&y, point_dot(&u,&v)/v_len_sq); x = u; point_sub(&x,&y); delta = ddisplay_transform_length(ddisp, point_dot(&x,&x)); if (delta < BEZIER_SUBDIVIDE_LIMIT_SQ) { u = points[2]; point_sub(&u, &points[3]); v = points[0]; point_sub(&v, &points[3]); y = v; v_len_sq = point_dot(&v,&v); if (v_len_sq < 0.000001) v_len_sq = 0.000001; point_scale(&y, point_dot(&u,&v)/v_len_sq); x = u; point_sub(&x,&y); delta = ddisplay_transform_length(ddisp, point_dot(&x,&x)); if (delta < BEZIER_SUBDIVIDE_LIMIT_SQ) { /* Almost flat, draw a line */ bezier_add_point(ddisp, bezier, &points[3]); return; } } /* Subdivide into two bezier curves: */ middle = points[1]; point_add(&middle, &points[2]); point_scale(&middle, 0.5); r[0] = points[0]; r[1] = points[0]; point_add(&r[1], &points[1]); point_scale(&r[1], 0.5); r[2] = r[1]; point_add(&r[2], &middle); point_scale(&r[2], 0.5); s[3] = points[3]; s[2] = points[2]; point_add(&s[2], &points[3]); point_scale(&s[2], 0.5); s[1] = s[2]; point_add(&s[1], &middle); point_scale(&s[1], 0.5); r[3] = r[2]; point_add(&r[3], &s[1]); point_scale(&r[3], 0.5); s[0] = r[3]; bezier_add_lines(ddisp, r, bezier); bezier_add_lines(ddisp, s, bezier); } static void bezier_add_curve(DDisplay *ddisp, Point points[4], struct bezier_curve *bezier) { /* Is the bezier curve malformed? */ if ( (distance_point_point(&points[0], &points[1]) < 0.00001) && (distance_point_point(&points[2], &points[3]) < 0.00001) && (distance_point_point(&points[0], &points[3]) < 0.00001)) { bezier_add_point(ddisp, bezier, &points[3]); } bezier_add_lines(ddisp, points, bezier); } static struct bezier_curve bezier = { NULL, 0, 0 }; static void draw_bezier(RendererGdk *renderer, BezPoint *points, int numpoints, Color *color) { DDisplay *ddisp = renderer->ddisp; GdkGC *gc = renderer->render_gc; GdkColor gdk_color; Point curve[4]; int i; if (bezier.gdk_points == NULL) { bezier.numpoints = 30; bezier.gdk_points = g_malloc(bezier.numpoints*sizeof(GdkPoint)); } bezier.currpoint = 0; if (points[0].type != BEZ_MOVE_TO) g_warning("first BezPoint must be a BEZ_MOVE_TO"); curve[3] = points[0].p1; bezier_add_point(renderer->ddisp, &bezier, &points[0].p1); for (i = 1; i < numpoints; i++) switch (points[i].type) { case BEZ_MOVE_TO: g_warning("only first BezPoint can be a BEZ_MOVE_TO"); curve[3] = points[i].p1; break; case BEZ_LINE_TO: bezier_add_point(renderer->ddisp, &bezier, &points[i].p1); curve[3] = points[i].p1; break; case BEZ_CURVE_TO: curve[0] = curve[3]; curve[1] = points[i].p1; curve[2] = points[i].p2; curve[3] = points[i].p3; bezier_add_curve(ddisp, curve, &bezier); break; } color_convert(color, &gdk_color); gdk_gc_set_foreground(gc, &gdk_color); gdk_gc_set_line_attributes(renderer->render_gc, renderer->line_width, renderer->line_style, renderer->cap_style, GDK_JOIN_ROUND); gdk_draw_lines(renderer->pixmap, gc, bezier.gdk_points, bezier.currpoint); gdk_gc_set_line_attributes(renderer->render_gc, renderer->line_width, renderer->line_style, renderer->cap_style, renderer->join_style); } static void fill_bezier(RendererGdk *renderer, BezPoint *points, /* Last point must be same as first point */ int numpoints, /* numpoints = 4+3*n, n=>0 */ Color *color) { DDisplay *ddisp = renderer->ddisp; GdkGC *gc = renderer->render_gc; GdkColor gdk_color; Point curve[4]; int i; if (bezier.gdk_points == NULL) { bezier.numpoints = 30; bezier.gdk_points = g_malloc(bezier.numpoints*sizeof(GdkPoint)); } bezier.currpoint = 0; if (points[0].type != BEZ_MOVE_TO) g_warning("first BezPoint must be a BEZ_MOVE_TO"); curve[3] = points[0].p1; bezier_add_point(renderer->ddisp, &bezier, &points[0].p1); for (i = 1; i < numpoints; i++) switch (points[i].type) { case BEZ_MOVE_TO: g_warning("only first BezPoint can be a BEZ_MOVE_TO"); curve[3] = points[i].p1; break; case BEZ_LINE_TO: bezier_add_point(renderer->ddisp, &bezier, &points[i].p1); curve[3] = points[i].p1; break; case BEZ_CURVE_TO: curve[0] = curve[3]; curve[1] = points[i].p1; curve[2] = points[i].p2; curve[3] = points[i].p3; bezier_add_curve(ddisp, curve, &bezier); break; } color_convert(color, &gdk_color); gdk_gc_set_foreground(gc, &gdk_color); gdk_draw_polygon(renderer->pixmap, gc, TRUE, bezier.gdk_points, bezier.currpoint); } static void draw_string(RendererGdk *renderer, const char *text, Point *pos, Alignment alignment, Color *color) { DDisplay *ddisp = renderer->ddisp; GdkGC *gc = renderer->render_gc; GdkColor gdkcolor; int x,y; int iwidth; ddisplay_transform_coords(ddisp, pos->x, pos->y, &x, &y); iwidth = gdk_string_width(renderer->gdk_font, text); switch (alignment) { case ALIGN_LEFT: break; case ALIGN_CENTER: x -= iwidth/2; break; case ALIGN_RIGHT: x -= iwidth; break; } color_convert(color, &gdkcolor); gdk_gc_set_foreground(gc, &gdkcolor); gdk_draw_string(renderer->pixmap, renderer->gdk_font, gc, x,y, text); } static void draw_image(RendererGdk *renderer, Point *point, real width, real height, DiaImage image) { int real_width, real_height, real_x, real_y; real_width = ddisplay_transform_length(renderer->ddisp, width); real_height = ddisplay_transform_length(renderer->ddisp, height); ddisplay_transform_coords(renderer->ddisp, point->x, point->y, &real_x, &real_y); dia_image_draw(image, renderer->pixmap, real_x, real_y, real_width, real_height); } static real get_text_width(RendererGdk *renderer, const char *text, int length) { int iwidth; iwidth = gdk_text_width(renderer->gdk_font, text, length); return ddisplay_untransform_length(renderer->ddisp, (real) iwidth); } static void clip_region_clear(RendererGdk *renderer) { if (renderer->clip_region != NULL) gdk_region_destroy(renderer->clip_region); renderer->clip_region = gdk_region_new(); gdk_gc_set_clip_region(renderer->render_gc, renderer->clip_region); } static void clip_region_add_rect(RendererGdk *renderer, Rectangle *rect) { DDisplay *ddisp = renderer->ddisp; GdkRegion *old_reg; GdkRectangle clip_rect; int x1,y1; int x2,y2; ddisplay_transform_coords(ddisp, rect->left, rect->top, &x1, &y1); ddisplay_transform_coords(ddisp, rect->right, rect->bottom, &x2, &y2); clip_rect.x = x1; clip_rect.y = y1; clip_rect.width = x2 - x1 + 1; clip_rect.height = y2 - y1 + 1; old_reg = renderer->clip_region; renderer->clip_region = gdk_region_union_with_rect( renderer->clip_region, &clip_rect ); gdk_region_destroy(old_reg); gdk_gc_set_clip_region(renderer->render_gc, renderer->clip_region); } static void draw_pixel_line(RendererGdk *renderer, int x1, int y1, int x2, int y2, Color *color) { GdkGC *gc = renderer->render_gc; GdkColor gdkcolor; color_convert(color, &gdkcolor); gdk_gc_set_foreground(gc, &gdkcolor); gdk_draw_line(renderer->pixmap, gc, x1, y1, x2, y2); } static void draw_pixel_rect(RendererGdk *renderer, int x, int y, int width, int height, Color *color) { GdkGC *gc = renderer->render_gc; GdkColor gdkcolor; color_convert(color, &gdkcolor); gdk_gc_set_foreground(gc, &gdkcolor); gdk_draw_rectangle (renderer->pixmap, gc, FALSE, x, y, width, height); } static void fill_pixel_rect(RendererGdk *renderer, int x, int y, int width, int height, Color *color) { GdkGC *gc = renderer->render_gc; GdkColor gdkcolor; color_convert(color, &gdkcolor); gdk_gc_set_foreground(gc, &gdkcolor); gdk_draw_rectangle (renderer->pixmap, gc, TRUE, x, y, width, height); }