added gas bottle shape
[dia.git] / app / render_gdk.c
blob2dd4791be9a9846339bc4015510797eb6f73ca3e
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include <math.h>
20 #include <gdk/gdk.h>
22 #include "render_gdk.h"
23 #include "message.h"
25 static void begin_render(RendererGdk *renderer, DiagramData *data);
26 static void end_render(RendererGdk *renderer);
27 static void set_linewidth(RendererGdk *renderer, real linewidth);
28 static void set_linecaps(RendererGdk *renderer, LineCaps mode);
29 static void set_linejoin(RendererGdk *renderer, LineJoin mode);
30 static void set_linestyle(RendererGdk *renderer, LineStyle mode);
31 static void set_dashlength(RendererGdk *renderer, real length);
32 static void set_fillstyle(RendererGdk *renderer, FillStyle mode);
33 static void set_font(RendererGdk *renderer, Font *font, real height);
34 static void draw_line(RendererGdk *renderer,
35 Point *start, Point *end,
36 Color *line_color);
37 static void draw_polyline(RendererGdk *renderer,
38 Point *points, int num_points,
39 Color *line_color);
40 static void draw_polygon(RendererGdk *renderer,
41 Point *points, int num_points,
42 Color *line_color);
43 static void fill_polygon(RendererGdk *renderer,
44 Point *points, int num_points,
45 Color *line_color);
46 static void draw_rect(RendererGdk *renderer,
47 Point *ul_corner, Point *lr_corner,
48 Color *color);
49 static void fill_rect(RendererGdk *renderer,
50 Point *ul_corner, Point *lr_corner,
51 Color *color);
52 static void draw_arc(RendererGdk *renderer,
53 Point *center,
54 real width, real height,
55 real angle1, real angle2,
56 Color *color);
57 static void fill_arc(RendererGdk *renderer,
58 Point *center,
59 real width, real height,
60 real angle1, real angle2,
61 Color *color);
62 static void draw_ellipse(RendererGdk *renderer,
63 Point *center,
64 real width, real height,
65 Color *color);
66 static void fill_ellipse(RendererGdk *renderer,
67 Point *center,
68 real width, real height,
69 Color *color);
70 static void draw_bezier(RendererGdk *renderer,
71 BezPoint *points,
72 int numpoints,
73 Color *color);
74 static void fill_bezier(RendererGdk *renderer,
75 BezPoint *points, /* Last point must be same as first point */
76 int numpoints,
77 Color *color);
78 static void draw_string(RendererGdk *renderer,
79 const char *text,
80 Point *pos, Alignment alignment,
81 Color *color);
82 static void draw_image(RendererGdk *renderer,
83 Point *point,
84 real width, real height,
85 DiaImage image);
87 static real get_text_width(RendererGdk *renderer,
88 const char *text, int length);
90 static void clip_region_clear(RendererGdk *renderer);
91 static void clip_region_add_rect(RendererGdk *renderer,
92 Rectangle *rect);
94 static void draw_pixel_line(RendererGdk *renderer,
95 int x1, int y1,
96 int x2, int y2,
97 Color *color);
98 static void draw_pixel_rect(RendererGdk *renderer,
99 int x, int y,
100 int width, int height,
101 Color *color);
102 static void fill_pixel_rect(RendererGdk *renderer,
103 int x, int y,
104 int width, int height,
105 Color *color);
107 static RenderOps GdkRenderOps = {
108 (BeginRenderFunc) begin_render,
109 (EndRenderFunc) end_render,
111 (SetLineWidthFunc) set_linewidth,
112 (SetLineCapsFunc) set_linecaps,
113 (SetLineJoinFunc) set_linejoin,
114 (SetLineStyleFunc) set_linestyle,
115 (SetDashLengthFunc) set_dashlength,
116 (SetFillStyleFunc) set_fillstyle,
117 (SetFontFunc) set_font,
119 (DrawLineFunc) draw_line,
120 (DrawPolyLineFunc) draw_polyline,
122 (DrawPolygonFunc) draw_polygon,
123 (FillPolygonFunc) fill_polygon,
125 (DrawRectangleFunc) draw_rect,
126 (FillRectangleFunc) fill_rect,
128 (DrawArcFunc) draw_arc,
129 (FillArcFunc) fill_arc,
131 (DrawEllipseFunc) draw_ellipse,
132 (FillEllipseFunc) fill_ellipse,
134 (DrawBezierFunc) draw_bezier,
135 (FillBezierFunc) fill_bezier,
137 (DrawStringFunc) draw_string,
139 (DrawImageFunc) draw_image,
142 static InteractiveRenderOps GdkInteractiveRenderOps = {
143 (GetTextWidthFunc) get_text_width,
145 (ClipRegionClearFunc) clip_region_clear,
146 (ClipRegionAddRectangleFunc) clip_region_add_rect,
148 (DrawPixelLineFunc) draw_pixel_line,
149 (DrawPixelRectangleFunc) draw_pixel_rect,
150 (FillPixelRectangleFunc) fill_pixel_rect,
153 RendererGdk *
154 new_gdk_renderer(DDisplay *ddisp)
156 RendererGdk *renderer;
158 renderer = g_new(RendererGdk, 1);
159 renderer->renderer.ops = &GdkRenderOps;
160 renderer->renderer.is_interactive = 1;
161 renderer->renderer.interactive_ops = &GdkInteractiveRenderOps;
162 renderer->ddisp = ddisp;
163 renderer->render_gc = NULL;
165 renderer->pixmap = NULL;
166 renderer->renderer.pixel_width = 0;
167 renderer->renderer.pixel_height = 0;
168 renderer->clip_region = NULL;
170 renderer->line_width = 1;
171 renderer->line_style = GDK_LINE_SOLID;
172 renderer->cap_style = GDK_CAP_BUTT;
173 renderer->join_style = GDK_JOIN_MITER;
175 renderer->saved_line_style = LINESTYLE_SOLID;
176 renderer->dash_length = 10;
177 renderer->dot_length = 2;
179 return renderer;
182 void
183 destroy_gdk_renderer(RendererGdk *renderer)
185 if (renderer->pixmap != NULL)
186 gdk_pixmap_unref(renderer->pixmap);
188 if (renderer->render_gc != NULL)
189 gdk_gc_unref(renderer->render_gc);
191 if (renderer->clip_region != NULL)
192 gdk_region_destroy(renderer->clip_region);
194 g_free(renderer);
197 void
198 gdk_renderer_set_size(RendererGdk *renderer, GdkWindow *window,
199 int width, int height)
202 if (renderer->pixmap != NULL) {
203 gdk_pixmap_unref(renderer->pixmap);
206 renderer->pixmap = gdk_pixmap_new(window, width, height, -1);
207 renderer->renderer.pixel_width = width;
208 renderer->renderer.pixel_height = height;
210 if (renderer->render_gc == NULL) {
211 renderer->render_gc = gdk_gc_new(renderer->pixmap);
213 gdk_gc_set_line_attributes(renderer->render_gc,
214 renderer->line_width,
215 renderer->line_style,
216 renderer->cap_style,
217 renderer->join_style);
221 extern void
222 renderer_gdk_copy_to_window(RendererGdk *renderer, GdkWindow *window,
223 int x, int y, int width, int height)
225 static GdkGC *copy_gc = NULL;
227 if (copy_gc == NULL) {
228 copy_gc = gdk_gc_new(window);
231 gdk_draw_pixmap(window,
232 copy_gc,
233 renderer->pixmap,
234 x, y,
235 x, y,
236 width, height);
239 static void
240 begin_render(RendererGdk *renderer, DiagramData *data)
244 static void
245 end_render(RendererGdk *renderer)
251 static void
252 set_linewidth(RendererGdk *renderer, real linewidth)
253 { /* 0 == hairline **/
254 renderer->line_width =
255 ddisplay_transform_length(renderer->ddisp, linewidth);
257 if (renderer->line_width<=0)
258 renderer->line_width = 1; /* Minimum 1 pixel. */
260 gdk_gc_set_line_attributes(renderer->render_gc,
261 renderer->line_width,
262 renderer->line_style,
263 renderer->cap_style,
264 renderer->join_style);
267 static void
268 set_linecaps(RendererGdk *renderer, LineCaps mode)
270 switch(mode) {
271 case LINECAPS_BUTT:
272 renderer->cap_style = GDK_CAP_BUTT;
273 break;
274 case LINECAPS_ROUND:
275 renderer->cap_style = GDK_CAP_ROUND;
276 break;
277 case LINECAPS_PROJECTING:
278 renderer->cap_style = GDK_CAP_PROJECTING;
279 break;
282 gdk_gc_set_line_attributes(renderer->render_gc,
283 renderer->line_width,
284 renderer->line_style,
285 renderer->cap_style,
286 renderer->join_style);
289 static void
290 set_linejoin(RendererGdk *renderer, LineJoin mode)
292 switch(mode) {
293 case LINEJOIN_MITER:
294 renderer->cap_style = GDK_JOIN_MITER;
295 break;
296 case LINEJOIN_ROUND:
297 renderer->cap_style = GDK_JOIN_ROUND;
298 break;
299 case LINEJOIN_BEVEL:
300 renderer->cap_style = GDK_JOIN_BEVEL;
301 break;
304 gdk_gc_set_line_attributes(renderer->render_gc,
305 renderer->line_width,
306 renderer->line_style,
307 renderer->cap_style,
308 renderer->join_style);
311 static void
312 set_linestyle(RendererGdk *renderer, LineStyle mode)
314 char dash_list[6];
315 int hole_width;
317 renderer->saved_line_style = mode;
318 switch(mode) {
319 case LINESTYLE_SOLID:
320 renderer->line_style = GDK_LINE_SOLID;
321 break;
322 case LINESTYLE_DASHED:
323 renderer->line_style = GDK_LINE_ON_OFF_DASH;
324 dash_list[0] = renderer->dash_length;
325 dash_list[1] = renderer->dash_length;
326 gdk_gc_set_dashes(renderer->render_gc, 0, dash_list, 2);
327 break;
328 case LINESTYLE_DASH_DOT:
329 renderer->line_style = GDK_LINE_ON_OFF_DASH;
330 hole_width = (renderer->dash_length - renderer->dot_length) / 2;
331 if (hole_width==0)
332 hole_width = 1;
333 dash_list[0] = renderer->dash_length;
334 dash_list[1] = hole_width;
335 dash_list[2] = renderer->dot_length;
336 dash_list[3] = hole_width;
337 gdk_gc_set_dashes(renderer->render_gc, 0, dash_list, 4);
338 break;
339 case LINESTYLE_DASH_DOT_DOT:
340 renderer->line_style = GDK_LINE_ON_OFF_DASH;
341 hole_width = (renderer->dash_length - 2*renderer->dot_length) / 3;
342 if (hole_width==0)
343 hole_width = 1;
344 dash_list[0] = renderer->dash_length;
345 dash_list[1] = hole_width;
346 dash_list[2] = renderer->dot_length;
347 dash_list[3] = hole_width;
348 dash_list[4] = renderer->dot_length;
349 dash_list[5] = hole_width;
350 gdk_gc_set_dashes(renderer->render_gc, 0, dash_list, 6);
351 break;
352 case LINESTYLE_DOTTED:
353 renderer->line_style = GDK_LINE_ON_OFF_DASH;
354 dash_list[0] = renderer->dot_length;
355 dash_list[1] = renderer->dot_length;
356 gdk_gc_set_dashes(renderer->render_gc, 0, dash_list, 2);
357 break;
359 gdk_gc_set_line_attributes(renderer->render_gc,
360 renderer->line_width,
361 renderer->line_style,
362 renderer->cap_style,
363 renderer->join_style);
366 static void
367 set_dashlength(RendererGdk *renderer, real length)
368 { /* dot = 10% of len */
369 real ddisp_len;
371 ddisp_len =
372 ddisplay_transform_length(renderer->ddisp, length);
374 renderer->dash_length = (int)floor(ddisp_len+0.5);
375 renderer->dot_length = (int)floor(ddisp_len*0.1+0.5);
377 if (renderer->dash_length<=0)
378 renderer->dash_length = 1;
379 if (renderer->dash_length>255)
380 renderer->dash_length = 255;
381 if (renderer->dot_length<=0)
382 renderer->dot_length = 1;
383 if (renderer->dot_length>255)
384 renderer->dot_length = 255;
385 set_linestyle(renderer, renderer->saved_line_style);
388 static void
389 set_fillstyle(RendererGdk *renderer, FillStyle mode)
391 switch(mode) {
392 case FILLSTYLE_SOLID:
393 break;
394 default:
395 message_error("gdk_renderer: Unsupported fill mode specified!\n");
399 static void
400 set_font(RendererGdk *renderer, Font *font, real height)
402 renderer->font_height =
403 ddisplay_transform_length(renderer->ddisp, height);
405 renderer->gdk_font = font_get_gdkfont(font, renderer->font_height);
408 static void
409 draw_line(RendererGdk *renderer,
410 Point *start, Point *end,
411 Color *line_color)
413 DDisplay *ddisp = renderer->ddisp;
414 GdkGC *gc = renderer->render_gc;
415 GdkColor color;
416 int x1,y1,x2,y2;
418 ddisplay_transform_coords(ddisp, start->x, start->y, &x1, &y1);
419 ddisplay_transform_coords(ddisp, end->x, end->y, &x2, &y2);
421 color_convert(line_color, &color);
422 gdk_gc_set_foreground(gc, &color);
424 gdk_draw_line(renderer->pixmap, gc,
425 x1, y1, x2, y2);
428 static void
429 draw_polyline(RendererGdk *renderer,
430 Point *points, int num_points,
431 Color *line_color)
433 DDisplay *ddisp = renderer->ddisp;
434 GdkGC *gc = renderer->render_gc;
435 GdkColor color;
436 GdkPoint *gdk_points;
437 int i,x,y;
439 gdk_points = g_new(GdkPoint, num_points);
441 for (i=0;i<num_points;i++) {
442 ddisplay_transform_coords(ddisp, points[i].x, points[i].y, &x, &y);
443 gdk_points[i].x = x;
444 gdk_points[i].y = y;
447 color_convert(line_color, &color);
448 gdk_gc_set_foreground(gc, &color);
450 gdk_draw_lines(renderer->pixmap, gc, gdk_points, num_points);
451 g_free(gdk_points);
454 static void
455 draw_polygon(RendererGdk *renderer,
456 Point *points, int num_points,
457 Color *line_color)
459 DDisplay *ddisp = renderer->ddisp;
460 GdkGC *gc = renderer->render_gc;
461 GdkColor color;
462 GdkPoint *gdk_points;
463 int i,x,y;
465 gdk_points = g_new(GdkPoint, num_points);
467 for (i=0;i<num_points;i++) {
468 ddisplay_transform_coords(ddisp, points[i].x, points[i].y, &x, &y);
469 gdk_points[i].x = x;
470 gdk_points[i].y = y;
473 color_convert(line_color, &color);
474 gdk_gc_set_foreground(gc, &color);
476 gdk_draw_polygon(renderer->pixmap, gc, FALSE, gdk_points, num_points);
477 g_free(gdk_points);
480 static void
481 fill_polygon(RendererGdk *renderer,
482 Point *points, int num_points,
483 Color *line_color)
485 DDisplay *ddisp = renderer->ddisp;
486 GdkGC *gc = renderer->render_gc;
487 GdkColor color;
488 GdkPoint *gdk_points;
489 int i,x,y;
491 gdk_points = g_new(GdkPoint, num_points);
493 for (i=0;i<num_points;i++) {
494 ddisplay_transform_coords(ddisp, points[i].x, points[i].y, &x, &y);
495 gdk_points[i].x = x;
496 gdk_points[i].y = y;
499 color_convert(line_color, &color);
500 gdk_gc_set_foreground(gc, &color);
502 gdk_draw_polygon(renderer->pixmap, gc, TRUE, gdk_points, num_points);
503 g_free(gdk_points);
506 static void
507 draw_rect(RendererGdk *renderer,
508 Point *ul_corner, Point *lr_corner,
509 Color *color)
511 DDisplay *ddisp = renderer->ddisp;
512 GdkGC *gc = renderer->render_gc;
513 GdkColor gdkcolor;
514 gint top, bottom, left, right;
516 ddisplay_transform_coords(ddisp, ul_corner->x, ul_corner->y,
517 &left, &top);
518 ddisplay_transform_coords(ddisp, lr_corner->x, lr_corner->y,
519 &right, &bottom);
521 if ((left>right) || (top>bottom))
522 return;
524 color_convert(color, &gdkcolor);
525 gdk_gc_set_foreground(gc, &gdkcolor);
527 gdk_draw_rectangle (renderer->pixmap,
528 gc, FALSE,
529 left, top,
530 right-left,
531 bottom-top);
534 static void
535 fill_rect(RendererGdk *renderer,
536 Point *ul_corner, Point *lr_corner,
537 Color *color)
539 DDisplay *ddisp = renderer->ddisp;
540 GdkGC *gc = renderer->render_gc;
541 GdkColor gdkcolor;
542 gint top, bottom, left, right;
544 ddisplay_transform_coords(ddisp, ul_corner->x, ul_corner->y,
545 &left, &top);
546 ddisplay_transform_coords(ddisp, lr_corner->x, lr_corner->y,
547 &right, &bottom);
549 if ((left>right) || (top>bottom))
550 return;
552 color_convert(color, &gdkcolor);
553 gdk_gc_set_foreground(gc, &gdkcolor);
555 gdk_draw_rectangle (renderer->pixmap,
556 gc, TRUE,
557 left, top,
558 right-left,
559 bottom-top);
562 static void
563 draw_arc(RendererGdk *renderer,
564 Point *center,
565 real width, real height,
566 real angle1, real angle2,
567 Color *color)
569 DDisplay *ddisp = renderer->ddisp;
570 GdkGC *gc = renderer->render_gc;
571 GdkColor gdkcolor;
572 gint top, left, bottom, right;
573 real dangle;
575 ddisplay_transform_coords(ddisp,
576 center->x - width/2, center->y - height/2,
577 &left, &top);
578 ddisplay_transform_coords(ddisp,
579 center->x + width/2, center->y + height/2,
580 &right, &bottom);
582 if ((left>right) || (top>bottom))
583 return;
585 color_convert(color, &gdkcolor);
586 gdk_gc_set_foreground(gc, &gdkcolor);
588 dangle = angle2-angle1;
589 if (dangle<0)
590 dangle += 360.0;
592 gdk_draw_arc(renderer->pixmap,
593 gc, FALSE,
594 left, top, right-left, bottom-top,
595 (int) (angle1*64.0), (int) (dangle*64.0));
598 static void
599 fill_arc(RendererGdk *renderer,
600 Point *center,
601 real width, real height,
602 real angle1, real angle2,
603 Color *color)
605 DDisplay *ddisp = renderer->ddisp;
606 GdkGC *gc = renderer->render_gc;
607 GdkColor gdkcolor;
608 gint top, left, bottom, right;
609 real dangle;
611 ddisplay_transform_coords(ddisp,
612 center->x - width/2, center->y - height/2,
613 &left, &top);
614 ddisplay_transform_coords(ddisp,
615 center->x + width/2, center->y + height/2,
616 &right, &bottom);
618 if ((left>right) || (top>bottom))
619 return;
621 color_convert(color, &gdkcolor);
622 gdk_gc_set_foreground(gc, &gdkcolor);
624 dangle = angle2-angle1;
625 if (dangle<0)
626 dangle += 360.0;
628 gdk_draw_arc(renderer->pixmap,
629 gc, TRUE,
630 left, top, right-left, bottom-top,
631 (int) (angle1*64), (int) (dangle*64));
634 static void
635 draw_ellipse(RendererGdk *renderer,
636 Point *center,
637 real width, real height,
638 Color *color)
640 draw_arc(renderer, center, width, height, 0.0, 360.0, color);
643 static void
644 fill_ellipse(RendererGdk *renderer,
645 Point *center,
646 real width, real height,
647 Color *color)
649 fill_arc(renderer, center, width, height, 0.0, 360.0, color);
652 struct bezier_curve {
653 GdkPoint *gdk_points;
654 int numpoints;
655 int currpoint;
658 #define BEZIER_SUBDIVIDE_LIMIT 0.03
659 #define BEZIER_SUBDIVIDE_LIMIT_SQ (BEZIER_SUBDIVIDE_LIMIT*BEZIER_SUBDIVIDE_LIMIT)
661 static void
662 bezier_add_point(DDisplay *ddisp,
663 struct bezier_curve *bezier,
664 Point *point)
666 int x,y;
668 /* Grow if needed: */
669 if (bezier->currpoint == bezier->numpoints) {
670 bezier->numpoints += 40;
671 bezier->gdk_points = g_realloc(bezier->gdk_points,
672 bezier->numpoints*sizeof(GdkPoint));
675 ddisplay_transform_coords(ddisp, point->x, point->y, &x, &y);
677 bezier->gdk_points[bezier->currpoint].x = x;
678 bezier->gdk_points[bezier->currpoint].y = y;
680 bezier->currpoint++;
683 static void
684 bezier_add_lines(DDisplay *ddisp,
685 Point points[4],
686 struct bezier_curve *bezier)
688 Point u, v, x, y;
689 Point r[4];
690 Point s[4];
691 Point middle;
692 coord delta;
693 real v_len_sq;
695 /* Check if almost flat: */
696 u = points[1];
697 point_sub(&u, &points[0]);
698 v = points[3];
699 point_sub(&v, &points[0]);
700 y = v;
701 v_len_sq = point_dot(&v,&v);
702 if (isnan(v_len_sq)) {
703 g_warning("v_len_sq is NaN while calculating bezier curve!");
704 return;
706 if (v_len_sq < 0.000001)
707 v_len_sq = 0.000001;
708 point_scale(&y, point_dot(&u,&v)/v_len_sq);
709 x = u;
710 point_sub(&x,&y);
711 delta = ddisplay_transform_length(ddisp, point_dot(&x,&x));
712 if (delta < BEZIER_SUBDIVIDE_LIMIT_SQ) {
713 u = points[2];
714 point_sub(&u, &points[3]);
715 v = points[0];
716 point_sub(&v, &points[3]);
717 y = v;
718 v_len_sq = point_dot(&v,&v);
719 if (v_len_sq < 0.000001)
720 v_len_sq = 0.000001;
721 point_scale(&y, point_dot(&u,&v)/v_len_sq);
722 x = u;
723 point_sub(&x,&y);
724 delta = ddisplay_transform_length(ddisp, point_dot(&x,&x));
725 if (delta < BEZIER_SUBDIVIDE_LIMIT_SQ) { /* Almost flat, draw a line */
726 bezier_add_point(ddisp, bezier, &points[3]);
727 return;
730 /* Subdivide into two bezier curves: */
732 middle = points[1];
733 point_add(&middle, &points[2]);
734 point_scale(&middle, 0.5);
736 r[0] = points[0];
738 r[1] = points[0];
739 point_add(&r[1], &points[1]);
740 point_scale(&r[1], 0.5);
742 r[2] = r[1];
743 point_add(&r[2], &middle);
744 point_scale(&r[2], 0.5);
746 s[3] = points[3];
748 s[2] = points[2];
749 point_add(&s[2], &points[3]);
750 point_scale(&s[2], 0.5);
752 s[1] = s[2];
753 point_add(&s[1], &middle);
754 point_scale(&s[1], 0.5);
756 r[3] = r[2];
757 point_add(&r[3], &s[1]);
758 point_scale(&r[3], 0.5);
760 s[0] = r[3];
762 bezier_add_lines(ddisp, r, bezier);
763 bezier_add_lines(ddisp, s, bezier);
766 static void
767 bezier_add_curve(DDisplay *ddisp,
768 Point points[4],
769 struct bezier_curve *bezier)
771 /* Is the bezier curve malformed? */
772 if ( (distance_point_point(&points[0], &points[1]) < 0.00001) &&
773 (distance_point_point(&points[2], &points[3]) < 0.00001) &&
774 (distance_point_point(&points[0], &points[3]) < 0.00001)) {
775 bezier_add_point(ddisp, bezier, &points[3]);
778 bezier_add_lines(ddisp, points, bezier);
782 static struct bezier_curve bezier = { NULL, 0, 0 };
784 static void
785 draw_bezier(RendererGdk *renderer,
786 BezPoint *points,
787 int numpoints,
788 Color *color)
790 DDisplay *ddisp = renderer->ddisp;
791 GdkGC *gc = renderer->render_gc;
792 GdkColor gdk_color;
793 Point curve[4];
794 int i;
796 if (bezier.gdk_points == NULL) {
797 bezier.numpoints = 30;
798 bezier.gdk_points = g_malloc(bezier.numpoints*sizeof(GdkPoint));
801 bezier.currpoint = 0;
803 if (points[0].type != BEZ_MOVE_TO)
804 g_warning("first BezPoint must be a BEZ_MOVE_TO");
805 curve[3] = points[0].p1;
806 bezier_add_point(renderer->ddisp, &bezier, &points[0].p1);
807 for (i = 1; i < numpoints; i++)
808 switch (points[i].type) {
809 case BEZ_MOVE_TO:
810 g_warning("only first BezPoint can be a BEZ_MOVE_TO");
811 curve[3] = points[i].p1;
812 break;
813 case BEZ_LINE_TO:
814 bezier_add_point(renderer->ddisp, &bezier, &points[i].p1);
815 curve[3] = points[i].p1;
816 break;
817 case BEZ_CURVE_TO:
818 curve[0] = curve[3];
819 curve[1] = points[i].p1;
820 curve[2] = points[i].p2;
821 curve[3] = points[i].p3;
822 bezier_add_curve(ddisp, curve, &bezier);
823 break;
826 color_convert(color, &gdk_color);
827 gdk_gc_set_foreground(gc, &gdk_color);
829 gdk_gc_set_line_attributes(renderer->render_gc,
830 renderer->line_width,
831 renderer->line_style,
832 renderer->cap_style,
833 GDK_JOIN_ROUND);
835 gdk_draw_lines(renderer->pixmap, gc, bezier.gdk_points, bezier.currpoint);
837 gdk_gc_set_line_attributes(renderer->render_gc,
838 renderer->line_width,
839 renderer->line_style,
840 renderer->cap_style,
841 renderer->join_style);
844 static void
845 fill_bezier(RendererGdk *renderer,
846 BezPoint *points, /* Last point must be same as first point */
847 int numpoints, /* numpoints = 4+3*n, n=>0 */
848 Color *color)
850 DDisplay *ddisp = renderer->ddisp;
851 GdkGC *gc = renderer->render_gc;
852 GdkColor gdk_color;
853 Point curve[4];
854 int i;
856 if (bezier.gdk_points == NULL) {
857 bezier.numpoints = 30;
858 bezier.gdk_points = g_malloc(bezier.numpoints*sizeof(GdkPoint));
861 bezier.currpoint = 0;
863 if (points[0].type != BEZ_MOVE_TO)
864 g_warning("first BezPoint must be a BEZ_MOVE_TO");
865 curve[3] = points[0].p1;
866 bezier_add_point(renderer->ddisp, &bezier, &points[0].p1);
867 for (i = 1; i < numpoints; i++)
868 switch (points[i].type) {
869 case BEZ_MOVE_TO:
870 g_warning("only first BezPoint can be a BEZ_MOVE_TO");
871 curve[3] = points[i].p1;
872 break;
873 case BEZ_LINE_TO:
874 bezier_add_point(renderer->ddisp, &bezier, &points[i].p1);
875 curve[3] = points[i].p1;
876 break;
877 case BEZ_CURVE_TO:
878 curve[0] = curve[3];
879 curve[1] = points[i].p1;
880 curve[2] = points[i].p2;
881 curve[3] = points[i].p3;
882 bezier_add_curve(ddisp, curve, &bezier);
883 break;
886 color_convert(color, &gdk_color);
887 gdk_gc_set_foreground(gc, &gdk_color);
889 gdk_draw_polygon(renderer->pixmap, gc, TRUE,
890 bezier.gdk_points, bezier.currpoint);
893 static void
894 draw_string(RendererGdk *renderer,
895 const char *text,
896 Point *pos, Alignment alignment,
897 Color *color)
899 DDisplay *ddisp = renderer->ddisp;
900 GdkGC *gc = renderer->render_gc;
901 GdkColor gdkcolor;
902 int x,y;
903 int iwidth;
905 ddisplay_transform_coords(ddisp, pos->x, pos->y,
906 &x, &y);
908 iwidth = gdk_string_width(renderer->gdk_font, text);
910 switch (alignment) {
911 case ALIGN_LEFT:
912 break;
913 case ALIGN_CENTER:
914 x -= iwidth/2;
915 break;
916 case ALIGN_RIGHT:
917 x -= iwidth;
918 break;
921 color_convert(color, &gdkcolor);
922 gdk_gc_set_foreground(gc, &gdkcolor);
924 gdk_draw_string(renderer->pixmap,
925 renderer->gdk_font, gc,
926 x,y, text);
929 static void
930 draw_image(RendererGdk *renderer,
931 Point *point,
932 real width, real height,
933 DiaImage image)
935 int real_width, real_height, real_x, real_y;
937 real_width = ddisplay_transform_length(renderer->ddisp, width);
938 real_height = ddisplay_transform_length(renderer->ddisp, height);
939 ddisplay_transform_coords(renderer->ddisp, point->x, point->y,
940 &real_x, &real_y);
942 dia_image_draw(image, renderer->pixmap, real_x, real_y,
943 real_width, real_height);
946 static real
947 get_text_width(RendererGdk *renderer,
948 const char *text, int length)
950 int iwidth;
952 iwidth = gdk_text_width(renderer->gdk_font, text, length);
954 return ddisplay_untransform_length(renderer->ddisp, (real) iwidth);
958 static void
959 clip_region_clear(RendererGdk *renderer)
961 if (renderer->clip_region != NULL)
962 gdk_region_destroy(renderer->clip_region);
964 renderer->clip_region = gdk_region_new();
966 gdk_gc_set_clip_region(renderer->render_gc, renderer->clip_region);
969 static void
970 clip_region_add_rect(RendererGdk *renderer,
971 Rectangle *rect)
973 DDisplay *ddisp = renderer->ddisp;
974 GdkRegion *old_reg;
975 GdkRectangle clip_rect;
976 int x1,y1;
977 int x2,y2;
979 ddisplay_transform_coords(ddisp, rect->left, rect->top, &x1, &y1);
980 ddisplay_transform_coords(ddisp, rect->right, rect->bottom, &x2, &y2);
982 clip_rect.x = x1;
983 clip_rect.y = y1;
984 clip_rect.width = x2 - x1 + 1;
985 clip_rect.height = y2 - y1 + 1;
987 old_reg = renderer->clip_region;
989 renderer->clip_region =
990 gdk_region_union_with_rect( renderer->clip_region, &clip_rect );
992 gdk_region_destroy(old_reg);
994 gdk_gc_set_clip_region(renderer->render_gc, renderer->clip_region);
997 static void
998 draw_pixel_line(RendererGdk *renderer,
999 int x1, int y1,
1000 int x2, int y2,
1001 Color *color)
1003 GdkGC *gc = renderer->render_gc;
1004 GdkColor gdkcolor;
1006 color_convert(color, &gdkcolor);
1007 gdk_gc_set_foreground(gc, &gdkcolor);
1009 gdk_draw_line(renderer->pixmap, gc, x1, y1, x2, y2);
1012 static void
1013 draw_pixel_rect(RendererGdk *renderer,
1014 int x, int y,
1015 int width, int height,
1016 Color *color)
1018 GdkGC *gc = renderer->render_gc;
1019 GdkColor gdkcolor;
1021 color_convert(color, &gdkcolor);
1022 gdk_gc_set_foreground(gc, &gdkcolor);
1024 gdk_draw_rectangle (renderer->pixmap, gc, FALSE,
1025 x, y, width, height);
1028 static void
1029 fill_pixel_rect(RendererGdk *renderer,
1030 int x, int y,
1031 int width, int height,
1032 Color *color)
1034 GdkGC *gc = renderer->render_gc;
1035 GdkColor gdkcolor;
1037 color_convert(color, &gdkcolor);
1038 gdk_gc_set_foreground(gc, &gdkcolor);
1040 gdk_draw_rectangle (renderer->pixmap, gc, TRUE,
1041 x, y, width, height);