1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * diagdkrenderer.c - refactoring of the render to gdk facility
5 * Copyright (C) 2002 Hans Breuer
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #define PANGO_ENABLE_ENGINE
30 #include <pango/pango-engine.h>
31 #include <pango/pango.h>
33 #include "diagdkrenderer.h"
34 #include "dia_image.h"
43 #include <pango/pango.h>
44 #include <pango/pangoft2.h>
47 static int get_width_pixels (DiaRenderer
*);
48 static int get_height_pixels (DiaRenderer
*);
50 static void begin_render (DiaRenderer
*);
51 static void end_render (DiaRenderer
*);
53 static void set_linewidth (DiaRenderer
*renderer
, real linewidth
);
54 static void set_linecaps (DiaRenderer
*renderer
, LineCaps mode
);
55 static void set_linejoin (DiaRenderer
*renderer
, LineJoin mode
);
56 static void set_linestyle (DiaRenderer
*renderer
, LineStyle mode
);
57 static void set_dashlength (DiaRenderer
*renderer
, real length
);
58 static void set_fillstyle (DiaRenderer
*renderer
, FillStyle mode
);
60 static void draw_line (DiaRenderer
*renderer
,
61 Point
*start
, Point
*end
,
63 static void fill_polygon (DiaRenderer
*renderer
,
64 Point
*points
, int num_points
,
66 static void draw_arc (DiaRenderer
*renderer
,
68 real width
, real height
,
69 real angle1
, real angle2
,
71 static void fill_arc (DiaRenderer
*renderer
,
73 real width
, real height
,
74 real angle1
, real angle2
,
76 static void draw_ellipse (DiaRenderer
*renderer
,
78 real width
, real height
,
80 static void fill_ellipse (DiaRenderer
*renderer
,
82 real width
, real height
,
84 static void draw_string (DiaRenderer
*renderer
,
89 static void draw_text (DiaRenderer
*renderer
,
91 static void draw_image (DiaRenderer
*renderer
,
93 real width
, real height
,
96 static void draw_rect (DiaRenderer
*renderer
,
97 Point
*ul_corner
, Point
*lr_corner
,
99 static void fill_rect (DiaRenderer
*renderer
,
100 Point
*ul_corner
, Point
*lr_corner
,
102 static void draw_fill_rect (DiaGdkRenderer
*renderer
,
103 Point
*ul_corner
, Point
*lr_corner
,
104 Color
*color
, gboolean fill
);
105 static void draw_polyline (DiaRenderer
*renderer
,
106 Point
*points
, int num_points
,
108 static void draw_polygon (DiaRenderer
*renderer
,
109 Point
*points
, int num_points
,
111 static void draw_object (DiaRenderer
*renderer
, DiaObject
*object
);
113 static real
get_text_width (DiaRenderer
*renderer
,
114 const gchar
*text
, int length
);
116 static void dia_gdk_renderer_class_init (DiaGdkRendererClass
*klass
);
117 static void renderer_init (DiaGdkRenderer
*renderer
, void*);
119 static gpointer parent_class
= NULL
;
121 /** Get the type object for the GdkRenderer.
122 * @return A static GType object describing GdkRenderers.
125 dia_gdk_renderer_get_type(void)
127 static GType object_type
= 0;
131 static const GTypeInfo object_info
=
133 sizeof (DiaGdkRendererClass
),
134 (GBaseInitFunc
) NULL
,
135 (GBaseFinalizeFunc
) NULL
,
136 (GClassInitFunc
) dia_gdk_renderer_class_init
,
137 NULL
, /* class_finalize */
138 NULL
, /* class_data */
139 sizeof (DiaGdkRenderer
),
141 (GInstanceInitFunc
)renderer_init
/* init */
144 object_type
= g_type_register_static (DIA_TYPE_RENDERER
,
152 /** Initialize a renderer object.
153 * @param renderer A renderer object to initialize.
154 * @param p Ignored, purpose unknown.
157 renderer_init(DiaGdkRenderer
*renderer
, void* p
)
159 renderer
->line_width
= 1;
160 renderer
->line_style
= GDK_LINE_SOLID
;
161 renderer
->cap_style
= GDK_CAP_BUTT
;
162 renderer
->join_style
= GDK_JOIN_ROUND
;
164 renderer
->saved_line_style
= LINESTYLE_SOLID
;
165 renderer
->dash_length
= 10;
166 renderer
->dot_length
= 2;
168 renderer
->highlight_color
= NULL
;
171 /** Clean up a renderer object after use.
172 * @param object Renderer object to free subobjects from.
175 renderer_finalize(GObject
*object
)
177 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
179 if (renderer
->pixmap
!= NULL
)
180 gdk_pixmap_unref(renderer
->pixmap
);
182 if (renderer
->gc
!= NULL
)
183 gdk_gc_unref(renderer
->gc
);
185 if (renderer
->clip_region
!= NULL
)
186 gdk_region_destroy(renderer
->clip_region
);
188 if (renderer
->transform
)
189 g_object_unref (renderer
->transform
);
191 G_OBJECT_CLASS (parent_class
)->finalize (object
);
194 /** Initialize members of the renderer class object. This sets up a bunch
195 * of functions to call for various render functions.
196 * @param klass The class object to initialize.
199 dia_gdk_renderer_class_init(DiaGdkRendererClass
*klass
)
201 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
202 DiaRendererClass
*renderer_class
= DIA_RENDERER_CLASS (klass
);
204 parent_class
= g_type_class_peek_parent (klass
);
206 object_class
->finalize
= renderer_finalize
;
208 renderer_class
->get_width_pixels
= get_width_pixels
;
209 renderer_class
->get_height_pixels
= get_height_pixels
;
211 renderer_class
->begin_render
= begin_render
;
212 renderer_class
->end_render
= end_render
;
214 renderer_class
->set_linewidth
= set_linewidth
;
215 renderer_class
->set_linecaps
= set_linecaps
;
216 renderer_class
->set_linejoin
= set_linejoin
;
217 renderer_class
->set_linestyle
= set_linestyle
;
218 renderer_class
->set_dashlength
= set_dashlength
;
219 renderer_class
->set_fillstyle
= set_fillstyle
;
221 renderer_class
->draw_line
= draw_line
;
222 renderer_class
->fill_polygon
= fill_polygon
;
223 renderer_class
->draw_rect
= draw_rect
;
224 renderer_class
->fill_rect
= fill_rect
;
225 renderer_class
->draw_arc
= draw_arc
;
226 renderer_class
->fill_arc
= fill_arc
;
227 renderer_class
->draw_ellipse
= draw_ellipse
;
228 renderer_class
->fill_ellipse
= fill_ellipse
;
230 /* use <draw|fill>_bezier from DiaRenderer */
232 renderer_class
->draw_string
= draw_string
;
233 renderer_class
->draw_text
= draw_text
;
234 renderer_class
->draw_image
= draw_image
;
236 /* medium level functions */
237 renderer_class
->draw_rect
= draw_rect
;
238 renderer_class
->draw_polyline
= draw_polyline
;
239 renderer_class
->draw_polygon
= draw_polygon
;
240 renderer_class
->draw_object
= draw_object
;
242 /* Interactive functions */
243 renderer_class
->get_text_width
= get_text_width
;
246 /** Convert Dia color objects into GDK color objects.
247 * If the highlight color is set, that will be used instead. This allows
248 * rendering of an object to do highlight rendering.
249 * @param renderer The renderer to check for highlight color.
250 * @param col A color object to convert.
251 * @param gdk_col Resulting GDK convert.
254 renderer_color_convert(DiaGdkRenderer
*renderer
,
255 Color
*col
, GdkColor
*gdk_col
)
257 if (renderer
->highlight_color
!= NULL
) {
258 color_convert(renderer
->highlight_color
, gdk_col
);
260 color_convert(col
, gdk_col
);
265 begin_render (DiaRenderer
*object
)
270 end_render (DiaRenderer
*object
)
275 set_linewidth (DiaRenderer
*object
, real linewidth
)
277 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
279 if (renderer
->highlight_color
!= NULL
) {
280 /* 6 pixels wide -> 3 pixels beyond normal obj */
281 real border
= dia_untransform_length(renderer
->transform
, 6);
286 renderer
->line_width
=
287 dia_transform_length(renderer
->transform
, linewidth
);
289 if (renderer
->line_width
<=0)
290 renderer
->line_width
= 1; /* Minimum 1 pixel. */
292 gdk_gc_set_line_attributes(renderer
->gc
,
293 renderer
->line_width
,
294 renderer
->line_style
,
296 renderer
->join_style
);
300 set_linecaps (DiaRenderer
*object
, LineCaps mode
)
302 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
304 if (renderer
->highlight_color
!= NULL
) {
305 renderer
->cap_style
= GDK_CAP_ROUND
;
309 renderer
->cap_style
= GDK_CAP_BUTT
;
312 renderer
->cap_style
= GDK_CAP_ROUND
;
314 case LINECAPS_PROJECTING
:
315 renderer
->cap_style
= GDK_CAP_PROJECTING
;
320 gdk_gc_set_line_attributes(renderer
->gc
,
321 renderer
->line_width
,
322 renderer
->line_style
,
324 renderer
->join_style
);
328 set_linejoin (DiaRenderer
*object
, LineJoin mode
)
330 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
332 if (renderer
->highlight_color
!= NULL
) {
333 renderer
->join_style
= GDK_JOIN_ROUND
;
337 renderer
->join_style
= GDK_JOIN_MITER
;
340 renderer
->join_style
= GDK_JOIN_ROUND
;
343 renderer
->join_style
= GDK_JOIN_BEVEL
;
348 gdk_gc_set_line_attributes(renderer
->gc
,
349 renderer
->line_width
,
350 renderer
->line_style
,
352 renderer
->join_style
);
355 /** Set the dashes for this renderer.
356 * offset determines where in the pattern the dashes will start.
357 * It is used by the grid in particular to make the grid dashes line up.
360 dia_gdk_renderer_set_dashes(DiaGdkRenderer
*renderer
, int offset
)
366 switch(renderer
->saved_line_style
) {
367 case LINESTYLE_SOLID
:
369 case LINESTYLE_DASHED
:
370 dash_list
[0] = renderer
->dash_length
;
371 dash_list
[1] = renderer
->dash_length
;
372 pattern_length
= renderer
->dash_length
*2;
373 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 2);
375 case LINESTYLE_DASH_DOT
:
376 hole_width
= (renderer
->dash_length
- renderer
->dot_length
) / 2;
379 dash_list
[0] = renderer
->dash_length
;
380 dash_list
[1] = hole_width
;
381 dash_list
[2] = renderer
->dot_length
;
382 dash_list
[3] = hole_width
;
383 pattern_length
= renderer
->dash_length
+renderer
->dot_length
+2*hole_width
;
384 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 4);
386 case LINESTYLE_DASH_DOT_DOT
:
387 hole_width
= (renderer
->dash_length
- 2*renderer
->dot_length
) / 3;
390 dash_list
[0] = renderer
->dash_length
;
391 dash_list
[1] = hole_width
;
392 dash_list
[2] = renderer
->dot_length
;
393 dash_list
[3] = hole_width
;
394 dash_list
[4] = renderer
->dot_length
;
395 dash_list
[5] = hole_width
;
396 pattern_length
= renderer
->dash_length
+2*renderer
->dot_length
+3*hole_width
;
397 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 6);
399 case LINESTYLE_DOTTED
:
400 dash_list
[0] = renderer
->dot_length
;
401 dash_list
[1] = renderer
->dot_length
;
402 pattern_length
= renderer
->dot_length
;
403 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 2);
410 set_linestyle (DiaRenderer
*object
, LineStyle mode
)
412 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
414 renderer
->saved_line_style
= mode
;
416 case LINESTYLE_SOLID
:
417 renderer
->line_style
= GDK_LINE_SOLID
;
419 case LINESTYLE_DASHED
:
420 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
421 dia_gdk_renderer_set_dashes(renderer
, 0);
423 case LINESTYLE_DASH_DOT
:
424 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
425 dia_gdk_renderer_set_dashes(renderer
, 0);
427 case LINESTYLE_DASH_DOT_DOT
:
428 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
429 dia_gdk_renderer_set_dashes(renderer
, 0);
431 case LINESTYLE_DOTTED
:
432 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
433 dia_gdk_renderer_set_dashes(renderer
, 0);
436 gdk_gc_set_line_attributes(renderer
->gc
,
437 renderer
->line_width
,
438 renderer
->line_style
,
440 renderer
->join_style
);
444 set_dashlength (DiaRenderer
*object
, real length
)
446 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
447 /* dot = 10% of len */
451 dia_transform_length(renderer
->transform
, length
);
453 renderer
->dash_length
= (int)floor(ddisp_len
+0.5);
454 renderer
->dot_length
= (int)floor(ddisp_len
*0.1+0.5);
456 if (renderer
->dash_length
<=0)
457 renderer
->dash_length
= 1;
458 if (renderer
->dash_length
>255)
459 renderer
->dash_length
= 255;
460 if (renderer
->dot_length
<=0)
461 renderer
->dot_length
= 1;
462 if (renderer
->dot_length
>255)
463 renderer
->dot_length
= 255;
464 set_linestyle(object
, renderer
->saved_line_style
);
468 set_fillstyle (DiaRenderer
*object
, FillStyle mode
)
471 case FILLSTYLE_SOLID
:
474 message_error("gdk_renderer: Unsupported fill mode specified!\n");
479 draw_line (DiaRenderer
*object
, Point
*start
, Point
*end
, Color
*line_color
)
481 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
483 GdkGC
*gc
= renderer
->gc
;
487 dia_transform_coords(renderer
->transform
, start
->x
, start
->y
, &x1
, &y1
);
488 dia_transform_coords(renderer
->transform
, end
->x
, end
->y
, &x2
, &y2
);
490 renderer_color_convert(renderer
, line_color
, &color
);
491 gdk_gc_set_foreground(gc
, &color
);
493 gdk_draw_line(renderer
->pixmap
, gc
,
498 fill_polygon (DiaRenderer
*object
, Point
*points
, int num_points
, Color
*line_color
)
500 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
501 GdkGC
*gc
= renderer
->gc
;
503 GdkPoint
*gdk_points
;
506 gdk_points
= g_new(GdkPoint
, num_points
);
508 for (i
=0;i
<num_points
;i
++) {
509 dia_transform_coords(renderer
->transform
, points
[i
].x
, points
[i
].y
, &x
, &y
);
514 renderer_color_convert(renderer
, line_color
, &color
);
515 gdk_gc_set_foreground(gc
, &color
);
517 gdk_draw_polygon(renderer
->pixmap
, gc
, TRUE
, gdk_points
, num_points
);
522 draw_fill_arc (DiaRenderer
*object
,
524 real width
, real height
,
525 real angle1
, real angle2
,
529 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
530 GdkGC
*gc
= renderer
->gc
;
532 gint top
, left
, bottom
, right
;
535 dia_transform_coords(renderer
->transform
,
536 center
->x
- width
/2, center
->y
- height
/2,
538 dia_transform_coords(renderer
->transform
,
539 center
->x
+ width
/2, center
->y
+ height
/2,
542 if ((left
>right
) || (top
>bottom
))
545 renderer_color_convert(renderer
, color
, &gdkcolor
);
546 gdk_gc_set_foreground(gc
, &gdkcolor
);
548 dangle
= angle2
-angle1
;
552 gdk_draw_arc(renderer
->pixmap
,
554 left
, top
, right
-left
+(fill
?1:0), bottom
-top
+(fill
?1:0),
555 (int) (angle1
*64.0), (int) (dangle
*64.0));
558 draw_arc (DiaRenderer
*object
,
560 real width
, real height
,
561 real angle1
, real angle2
,
564 draw_fill_arc (object
, center
, width
, height
, angle1
, angle2
, color
, FALSE
);
568 fill_arc (DiaRenderer
*object
, Point
*center
,
569 real width
, real height
, real angle1
, real angle2
,
572 draw_fill_arc (object
, center
, width
, height
, angle1
, angle2
, color
, TRUE
);
576 draw_ellipse (DiaRenderer
*object
, Point
*center
,
577 real width
, real height
,
580 draw_arc(object
, center
, width
, height
, 0.0, 360.0, color
);
584 fill_ellipse (DiaRenderer
*object
, Point
*center
,
585 real width
, real height
, Color
*color
)
587 fill_arc(object
, center
, width
, height
, 0.0, 360.0, color
);
591 get_layout_first_baseline(PangoLayout
* layout
)
593 PangoLayoutIter
* iter
= pango_layout_get_iter(layout
);
594 gint result
= pango_layout_iter_get_baseline(iter
) / PANGO_SCALE
;
595 pango_layout_iter_free(iter
);
599 /** Return the x adjustment needed for this text and alignment */
601 get_alignment_adjustment(DiaRenderer
*object
,
605 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
612 dia_font_scaled_string_width(text
, object
->font
,
614 dia_transform_length(renderer
->transform
, 10.0)/10.0)/2;
618 dia_font_scaled_string_width(text
, object
->font
,
620 dia_transform_length(renderer
->transform
, 10.0)/10.0);
626 /* Draw a highlighted version of a string.
629 draw_highlighted_string(DiaGdkRenderer
*renderer
,
636 pango_layout_get_pixel_size(layout
, &width
, &height
);
638 gdk_gc_set_foreground(renderer
->gc
, color
);
640 gdk_draw_rectangle (renderer
->pixmap
,
647 draw_string (DiaRenderer
*object
,
648 const gchar
*text
, Point
*pos
, Alignment alignment
,
651 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
656 PangoLayout
* layout
= NULL
;
658 if (text
== NULL
|| *text
== '\0') return; /* Don't render empty strings. */
660 point_copy(&start_pos
,pos
);
662 renderer_color_convert(renderer
, color
, &gdkcolor
);
664 start_pos
.x
-= get_alignment_adjustment(object
, text
, alignment
);
667 int height_pixels
= dia_transform_length(renderer
->transform
, object
->font_height
);
668 if (height_pixels
< 2) { /* "Greeking" instead of making tiny font */
669 int width_pixels
= dia_transform_length(
671 dia_font_string_width(text
, object
->font
, object
->font_height
));
672 gdk_gc_set_foreground(renderer
->gc
, &gdkcolor
);
673 gdk_gc_set_dashes(renderer
->gc
, 0, "\1\2", 2);
674 dia_transform_coords(renderer
->transform
, start_pos
.x
, start_pos
.y
, &x
, &y
);
675 gdk_draw_line(renderer
->pixmap
, renderer
->gc
, x
, y
, x
+ width_pixels
, y
);
680 /* My apologies for adding more #hell, but the alternative is an abhorrent
683 #if defined HAVE_FREETYPE
689 GdkPixbuf
*rgba
= NULL
;
693 dia_font_scaled_ascent(text
, object
->font
,
695 dia_transform_length(renderer
->transform
, 1.0));
697 dia_transform_coords(renderer
->transform
,
698 start_pos
.x
, start_pos
.y
, &x
, &y
);
700 layout
= dia_font_scaled_build_layout(text
, object
->font
,
702 dia_transform_length(renderer
->transform
, 1.0));
703 if (renderer
->highlight_color
!= NULL
) {
704 draw_highlighted_string(renderer
, layout
, x
, y
, &gdkcolor
);
706 /* y -= get_layout_first_baseline(layout); */
707 pango_layout_get_pixel_size(layout
, &width
, &height
);
710 rowstride
= 32*((width
+31)/31);
712 graybitmap
= (guint8
*)g_new0(guint8
, height
*rowstride
);
714 ftbitmap
.rows
= height
;
715 ftbitmap
.width
= width
;
716 ftbitmap
.pitch
= rowstride
;
717 ftbitmap
.buffer
= graybitmap
;
718 ftbitmap
.num_grays
= 256;
719 ftbitmap
.pixel_mode
= ft_pixel_mode_grays
;
720 ftbitmap
.palette_mode
= 0;
721 ftbitmap
.palette
= 0;
722 pango_ft2_render_layout(&ftbitmap
, layout
, 0, 0);
728 rgba
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, TRUE
, 8, width
, height
);
729 stride
= gdk_pixbuf_get_rowstride(rgba
);
730 pixels
= gdk_pixbuf_get_pixels(rgba
);
731 for (i
= 0; i
< height
; i
++) {
732 for (j
= 0; j
< width
; j
++) {
733 pixels
[i
*stride
+j
*4] = gdkcolor
.red
>>8;
734 pixels
[i
*stride
+j
*4+1] = gdkcolor
.green
>>8;
735 pixels
[i
*stride
+j
*4+2] = gdkcolor
.blue
>>8;
736 pixels
[i
*stride
+j
*4+3] = graybitmap
[i
*rowstride
+j
];
742 if (rgba
!= NULL
) { /* Non-null width */
743 gdk_draw_pixbuf(renderer
->pixmap
, renderer
->gc
, rgba
, 0, 0, x
, y
, width
, height
, GDK_RGB_DITHER_NONE
, 0, 0);
744 g_object_unref(G_OBJECT(rgba
));
747 gdk_gc_set_function(gc, GDK_COPY_INVERT);
748 gdk_draw_gray_image(renderer->pixmap, gc, x, y, width, height,
749 GDK_RGB_DITHER_NONE, graybitmap, rowstride);
750 gdk_gc_set_function(gc, GDK_COPY);
756 GdkGC
*gc
= renderer
->gc
;
757 gdk_gc_set_foreground(gc
, &gdkcolor
);
758 dia_transform_coords(renderer
->transform
, start_pos
.x
, start_pos
.y
, &x
, &y
);
760 layout
= dia_font_scaled_build_layout(
763 dia_transform_length (renderer
->transform
, 10.0) / 10.0);
764 y
-= get_layout_first_baseline(layout
);
765 if (renderer
->highlight_color
!= NULL
) {
766 draw_highlighted_string(renderer
, layout
, x
, y
, &gdkcolor
);
768 gdk_draw_layout(renderer
->pixmap
,gc
,x
,y
,layout
);
773 /* abuse_layout_object(layout,text); */
775 g_object_unref(G_OBJECT(layout
));
778 /** Caching Pango renderer */
780 draw_text(DiaRenderer
*renderer
, Text
*text
) {
784 DIA_RENDERER_GET_CLASS(renderer
)->set_font(renderer
, text
->font
, text
->height
);
785 pos
= text
->position
;
787 for (i
=0;i
<text
->numlines
;i
++) {
788 DIA_RENDERER_GET_CLASS(renderer
)->draw_string(renderer
,
790 &pos
, text
->alignment
,
792 pos
.y
+= text
->height
;
797 /* Get the width of the given text in cm */
799 get_text_width(DiaRenderer
*object
,
800 const gchar
*text
, int length
)
802 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
805 if (length
!= strlen(text
)) {
808 /* A couple UTF8-chars: æblegrød Š Ť Ž ę ć ń уфхцНОПРЄ є Ґ Њ Ћ Џ */
809 ulen
= g_utf8_offset_to_pointer(text
, length
)-text
;
810 if (!g_utf8_validate(text
, ulen
, NULL
)) {
811 g_warning ("Text at char %d not valid\n", length
);
813 othertx
= g_strndup(text
, ulen
);
814 result
= dia_font_scaled_string_width(
815 othertx
,object
->font
,
817 dia_transform_length (renderer
->transform
, 10.0) / 10.0);
821 dia_font_scaled_string_width(
824 dia_transform_length (renderer
->transform
, 10.0) / 10.0);
830 draw_image (DiaRenderer
*object
,
832 real width
, real height
,
835 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
836 if (renderer
->highlight_color
!= NULL
) {
838 DiaRendererClass
*self_class
= DIA_RENDERER_GET_CLASS (object
);
843 self_class
->fill_rect(object
, point
, &lr
, renderer
->highlight_color
);
845 int real_width
, real_height
, real_x
, real_y
;
847 real_width
= dia_transform_length(renderer
->transform
, width
);
848 real_height
= dia_transform_length(renderer
->transform
, height
);
849 dia_transform_coords(renderer
->transform
, point
->x
, point
->y
,
852 dia_image_draw(image
, renderer
->pixmap
, real_x
, real_y
,
853 real_width
, real_height
);
858 * medium level functions
861 draw_fill_rect (DiaGdkRenderer
*renderer
,
862 Point
*ul_corner
, Point
*lr_corner
,
863 Color
*color
, gboolean fill
)
865 GdkGC
*gc
= renderer
->gc
;
867 gint top
, bottom
, left
, right
;
869 dia_transform_coords(renderer
->transform
,
870 ul_corner
->x
, ul_corner
->y
, &left
, &top
);
871 dia_transform_coords(renderer
->transform
,
872 lr_corner
->x
, lr_corner
->y
, &right
, &bottom
);
874 if ((left
>right
) || (top
>bottom
))
877 renderer_color_convert(renderer
, color
, &gdkcolor
);
878 gdk_gc_set_foreground(gc
, &gdkcolor
);
880 gdk_draw_rectangle (renderer
->pixmap
,
888 draw_rect (DiaRenderer
*object
,
889 Point
*ul_corner
, Point
*lr_corner
,
892 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
894 draw_fill_rect (renderer
, ul_corner
, lr_corner
, color
, FALSE
);
898 fill_rect (DiaRenderer
*object
,
899 Point
*ul_corner
, Point
*lr_corner
,
902 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
904 draw_fill_rect (renderer
, ul_corner
, lr_corner
, color
, TRUE
);
908 draw_polyline (DiaRenderer
*self
,
909 Point
*points
, int num_points
,
912 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (self
);
913 GdkGC
*gc
= renderer
->gc
;
915 GdkPoint
*gdk_points
;
918 gdk_points
= g_new(GdkPoint
, num_points
);
920 for (i
=0;i
<num_points
;i
++) {
921 dia_transform_coords(renderer
->transform
, points
[i
].x
, points
[i
].y
, &x
, &y
);
926 renderer_color_convert(renderer
, line_color
, &color
);
927 gdk_gc_set_foreground(gc
, &color
);
929 gdk_draw_lines(renderer
->pixmap
, gc
, gdk_points
, num_points
);
934 draw_polygon (DiaRenderer
*self
,
935 Point
*points
, int num_points
,
938 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (self
);
939 GdkGC
*gc
= renderer
->gc
;
941 GdkPoint
*gdk_points
;
944 gdk_points
= g_new(GdkPoint
, num_points
);
946 for (i
=0;i
<num_points
;i
++) {
947 dia_transform_coords(renderer
->transform
, points
[i
].x
, points
[i
].y
, &x
, &y
);
952 renderer_color_convert(renderer
, line_color
, &color
);
953 gdk_gc_set_foreground(gc
, &color
);
955 gdk_draw_polygon(renderer
->pixmap
, gc
, FALSE
, gdk_points
, num_points
);
960 draw_object (DiaRenderer
*renderer
, DiaObject
*object
)
962 if (object
->highlight_color
!= NULL
) {
963 DiaGdkRenderer
*gdk_rend
= DIA_GDK_RENDERER(renderer
);
964 gdk_rend
->highlight_color
= object
->highlight_color
;
965 object
->ops
->draw(object
, renderer
);
966 gdk_rend
->highlight_color
= NULL
;
968 object
->ops
->draw(object
, renderer
);
972 get_width_pixels (DiaRenderer
*object
)
974 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
977 if (renderer
->pixmap
)
978 gdk_drawable_get_size (GDK_DRAWABLE (renderer
->pixmap
), &width
, NULL
);
984 get_height_pixels (DiaRenderer
*object
)
986 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
989 if (renderer
->pixmap
)
990 gdk_drawable_get_size (GDK_DRAWABLE (renderer
->pixmap
), NULL
, &height
);