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.
31 #define PANGO_ENABLE_ENGINE
32 #include <pango/pango-engine.h>
33 #include <pango/pango.h>
35 #include "diagdkrenderer.h"
36 #include "dia_image.h"
47 #include <pango/pango.h>
48 #include <pango/pangoft2.h>
51 static int get_width_pixels (DiaRenderer
*);
52 static int get_height_pixels (DiaRenderer
*);
54 static void begin_render (DiaRenderer
*);
55 static void end_render (DiaRenderer
*);
57 static void set_linewidth (DiaRenderer
*renderer
, real linewidth
);
58 static void set_linecaps (DiaRenderer
*renderer
, LineCaps mode
);
59 static void set_linejoin (DiaRenderer
*renderer
, LineJoin mode
);
60 static void set_linestyle (DiaRenderer
*renderer
, LineStyle mode
);
61 static void set_dashlength (DiaRenderer
*renderer
, real length
);
62 static void set_fillstyle (DiaRenderer
*renderer
, FillStyle mode
);
64 static void draw_line (DiaRenderer
*renderer
,
65 Point
*start
, Point
*end
,
67 static void fill_polygon (DiaRenderer
*renderer
,
68 Point
*points
, int num_points
,
70 static void draw_arc (DiaRenderer
*renderer
,
72 real width
, real height
,
73 real angle1
, real angle2
,
75 static void fill_arc (DiaRenderer
*renderer
,
77 real width
, real height
,
78 real angle1
, real angle2
,
80 static void draw_ellipse (DiaRenderer
*renderer
,
82 real width
, real height
,
84 static void fill_ellipse (DiaRenderer
*renderer
,
86 real width
, real height
,
88 static void draw_string (DiaRenderer
*renderer
,
93 static void draw_text_line (DiaRenderer
*renderer
,
97 static void draw_image (DiaRenderer
*renderer
,
99 real width
, real height
,
102 static void draw_rect (DiaRenderer
*renderer
,
103 Point
*ul_corner
, Point
*lr_corner
,
105 static void fill_rect (DiaRenderer
*renderer
,
106 Point
*ul_corner
, Point
*lr_corner
,
108 static void draw_fill_rect (DiaGdkRenderer
*renderer
,
109 Point
*ul_corner
, Point
*lr_corner
,
110 Color
*color
, gboolean fill
);
111 static void draw_polyline (DiaRenderer
*renderer
,
112 Point
*points
, int num_points
,
114 static void draw_polygon (DiaRenderer
*renderer
,
115 Point
*points
, int num_points
,
117 static void draw_object (DiaRenderer
*renderer
, DiaObject
*object
);
119 static real
get_text_width (DiaRenderer
*renderer
,
120 const gchar
*text
, int length
);
122 static void dia_gdk_renderer_class_init (DiaGdkRendererClass
*klass
);
123 static void renderer_init (DiaGdkRenderer
*renderer
, void*);
125 static gpointer parent_class
= NULL
;
127 /** Get the type object for the GdkRenderer.
128 * @return A static GType object describing GdkRenderers.
131 dia_gdk_renderer_get_type(void)
133 static GType object_type
= 0;
137 static const GTypeInfo object_info
=
139 sizeof (DiaGdkRendererClass
),
140 (GBaseInitFunc
) NULL
,
141 (GBaseFinalizeFunc
) NULL
,
142 (GClassInitFunc
) dia_gdk_renderer_class_init
,
143 NULL
, /* class_finalize */
144 NULL
, /* class_data */
145 sizeof (DiaGdkRenderer
),
147 (GInstanceInitFunc
)renderer_init
/* init */
150 object_type
= g_type_register_static (DIA_TYPE_RENDERER
,
158 /** Initialize a renderer object.
159 * @param renderer A renderer object to initialize.
160 * @param p Ignored, purpose unknown.
163 renderer_init(DiaGdkRenderer
*renderer
, void* p
)
165 renderer
->line_width
= 1;
166 renderer
->line_style
= GDK_LINE_SOLID
;
167 renderer
->cap_style
= GDK_CAP_BUTT
;
168 renderer
->join_style
= GDK_JOIN_ROUND
;
170 renderer
->saved_line_style
= LINESTYLE_SOLID
;
171 renderer
->dash_length
= 10;
172 renderer
->dot_length
= 2;
174 renderer
->highlight_color
= NULL
;
177 /** Clean up a renderer object after use.
178 * @param object Renderer object to free subobjects from.
181 renderer_finalize(GObject
*object
)
183 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
185 if (renderer
->pixmap
!= NULL
)
186 gdk_pixmap_unref(renderer
->pixmap
);
188 if (renderer
->gc
!= NULL
)
189 gdk_gc_unref(renderer
->gc
);
191 if (renderer
->clip_region
!= NULL
)
192 gdk_region_destroy(renderer
->clip_region
);
194 if (renderer
->transform
)
195 g_object_unref (renderer
->transform
);
197 G_OBJECT_CLASS (parent_class
)->finalize (object
);
200 /** Initialize members of the renderer class object. This sets up a bunch
201 * of functions to call for various render functions.
202 * @param klass The class object to initialize.
205 dia_gdk_renderer_class_init(DiaGdkRendererClass
*klass
)
207 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
208 DiaRendererClass
*renderer_class
= DIA_RENDERER_CLASS (klass
);
210 parent_class
= g_type_class_peek_parent (klass
);
212 object_class
->finalize
= renderer_finalize
;
214 renderer_class
->get_width_pixels
= get_width_pixels
;
215 renderer_class
->get_height_pixels
= get_height_pixels
;
217 renderer_class
->begin_render
= begin_render
;
218 renderer_class
->end_render
= end_render
;
220 renderer_class
->set_linewidth
= set_linewidth
;
221 renderer_class
->set_linecaps
= set_linecaps
;
222 renderer_class
->set_linejoin
= set_linejoin
;
223 renderer_class
->set_linestyle
= set_linestyle
;
224 renderer_class
->set_dashlength
= set_dashlength
;
225 renderer_class
->set_fillstyle
= set_fillstyle
;
227 renderer_class
->draw_line
= draw_line
;
228 renderer_class
->fill_polygon
= fill_polygon
;
229 renderer_class
->draw_rect
= draw_rect
;
230 renderer_class
->fill_rect
= fill_rect
;
231 renderer_class
->draw_arc
= draw_arc
;
232 renderer_class
->fill_arc
= fill_arc
;
233 renderer_class
->draw_ellipse
= draw_ellipse
;
234 renderer_class
->fill_ellipse
= fill_ellipse
;
236 /* use <draw|fill>_bezier from DiaRenderer */
238 renderer_class
->draw_string
= draw_string
;
239 renderer_class
->draw_text_line
= draw_text_line
;
240 renderer_class
->draw_image
= draw_image
;
242 /* medium level functions */
243 renderer_class
->draw_rect
= draw_rect
;
244 renderer_class
->draw_polyline
= draw_polyline
;
245 renderer_class
->draw_polygon
= draw_polygon
;
246 renderer_class
->draw_object
= draw_object
;
248 /* Interactive functions */
249 renderer_class
->get_text_width
= get_text_width
;
252 /** Convert Dia color objects into GDK color objects.
253 * If the highlight color is set, that will be used instead. This allows
254 * rendering of an object to do highlight rendering.
255 * @param renderer The renderer to check for highlight color.
256 * @param col A color object to convert.
257 * @param gdk_col Resulting GDK convert.
260 renderer_color_convert(DiaGdkRenderer
*renderer
,
261 Color
*col
, GdkColor
*gdk_col
)
263 if (renderer
->highlight_color
!= NULL
) {
264 color_convert(renderer
->highlight_color
, gdk_col
);
266 color_convert(col
, gdk_col
);
271 begin_render (DiaRenderer
*object
)
276 end_render (DiaRenderer
*object
)
281 set_linewidth (DiaRenderer
*object
, real linewidth
)
283 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
285 if (renderer
->highlight_color
!= NULL
) {
286 /* 6 pixels wide -> 3 pixels beyond normal obj */
287 real border
= dia_untransform_length(renderer
->transform
, 6);
292 renderer
->line_width
=
293 dia_transform_length(renderer
->transform
, linewidth
);
295 if (renderer
->line_width
<=0)
296 renderer
->line_width
= 1; /* Minimum 1 pixel. */
298 gdk_gc_set_line_attributes(renderer
->gc
,
299 renderer
->line_width
,
300 renderer
->line_style
,
302 renderer
->join_style
);
306 set_linecaps (DiaRenderer
*object
, LineCaps mode
)
308 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
310 if (renderer
->highlight_color
!= NULL
) {
311 renderer
->cap_style
= GDK_CAP_ROUND
;
315 renderer
->cap_style
= GDK_CAP_BUTT
;
318 renderer
->cap_style
= GDK_CAP_ROUND
;
320 case LINECAPS_PROJECTING
:
321 renderer
->cap_style
= GDK_CAP_PROJECTING
;
326 gdk_gc_set_line_attributes(renderer
->gc
,
327 renderer
->line_width
,
328 renderer
->line_style
,
330 renderer
->join_style
);
334 set_linejoin (DiaRenderer
*object
, LineJoin mode
)
336 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
338 if (renderer
->highlight_color
!= NULL
) {
339 renderer
->join_style
= GDK_JOIN_ROUND
;
343 renderer
->join_style
= GDK_JOIN_MITER
;
346 renderer
->join_style
= GDK_JOIN_ROUND
;
349 renderer
->join_style
= GDK_JOIN_BEVEL
;
352 /* invalid mode, just here to set a breakpoint */
353 renderer
->join_style
= GDK_JOIN_ROUND
;
358 gdk_gc_set_line_attributes(renderer
->gc
,
359 renderer
->line_width
,
360 renderer
->line_style
,
362 renderer
->join_style
);
365 /** Set the dashes for this renderer.
366 * offset determines where in the pattern the dashes will start.
367 * It is used by the grid in particular to make the grid dashes line up.
370 dia_gdk_renderer_set_dashes(DiaGdkRenderer
*renderer
, int offset
)
376 switch(renderer
->saved_line_style
) {
377 case LINESTYLE_SOLID
:
379 case LINESTYLE_DASHED
:
380 dash_list
[0] = renderer
->dash_length
;
381 dash_list
[1] = renderer
->dash_length
;
382 pattern_length
= renderer
->dash_length
*2;
383 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 2);
385 case LINESTYLE_DASH_DOT
:
386 hole_width
= (renderer
->dash_length
- renderer
->dot_length
) / 2;
389 dash_list
[0] = renderer
->dash_length
;
390 dash_list
[1] = hole_width
;
391 dash_list
[2] = renderer
->dot_length
;
392 dash_list
[3] = hole_width
;
393 pattern_length
= renderer
->dash_length
+renderer
->dot_length
+2*hole_width
;
394 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 4);
396 case LINESTYLE_DASH_DOT_DOT
:
397 hole_width
= (renderer
->dash_length
- 2*renderer
->dot_length
) / 3;
400 dash_list
[0] = renderer
->dash_length
;
401 dash_list
[1] = hole_width
;
402 dash_list
[2] = renderer
->dot_length
;
403 dash_list
[3] = hole_width
;
404 dash_list
[4] = renderer
->dot_length
;
405 dash_list
[5] = hole_width
;
406 pattern_length
= renderer
->dash_length
+2*renderer
->dot_length
+3*hole_width
;
407 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 6);
409 case LINESTYLE_DOTTED
:
410 dash_list
[0] = renderer
->dot_length
;
411 dash_list
[1] = renderer
->dot_length
;
412 pattern_length
= renderer
->dot_length
;
413 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 2);
420 set_linestyle (DiaRenderer
*object
, LineStyle mode
)
422 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
424 renderer
->saved_line_style
= mode
;
426 case LINESTYLE_SOLID
:
427 renderer
->line_style
= GDK_LINE_SOLID
;
429 case LINESTYLE_DASHED
:
430 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
431 dia_gdk_renderer_set_dashes(renderer
, 0);
433 case LINESTYLE_DASH_DOT
:
434 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
435 dia_gdk_renderer_set_dashes(renderer
, 0);
437 case LINESTYLE_DASH_DOT_DOT
:
438 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
439 dia_gdk_renderer_set_dashes(renderer
, 0);
441 case LINESTYLE_DOTTED
:
442 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
443 dia_gdk_renderer_set_dashes(renderer
, 0);
446 gdk_gc_set_line_attributes(renderer
->gc
,
447 renderer
->line_width
,
448 renderer
->line_style
,
450 renderer
->join_style
);
454 set_dashlength (DiaRenderer
*object
, real length
)
456 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
457 /* dot = 10% of len */
461 dia_transform_length(renderer
->transform
, length
);
463 renderer
->dash_length
= (int)floor(ddisp_len
+0.5);
464 renderer
->dot_length
= (int)floor(ddisp_len
*0.1+0.5);
466 if (renderer
->dash_length
<=0)
467 renderer
->dash_length
= 1;
468 if (renderer
->dash_length
>255)
469 renderer
->dash_length
= 255;
470 if (renderer
->dot_length
<=0)
471 renderer
->dot_length
= 1;
472 if (renderer
->dot_length
>255)
473 renderer
->dot_length
= 255;
474 set_linestyle(object
, renderer
->saved_line_style
);
478 set_fillstyle (DiaRenderer
*object
, FillStyle mode
)
481 case FILLSTYLE_SOLID
:
484 message_error("gdk_renderer: Unsupported fill mode specified!\n");
489 draw_line (DiaRenderer
*object
, Point
*start
, Point
*end
, Color
*line_color
)
491 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
493 GdkGC
*gc
= renderer
->gc
;
497 dia_transform_coords(renderer
->transform
, start
->x
, start
->y
, &x1
, &y1
);
498 dia_transform_coords(renderer
->transform
, end
->x
, end
->y
, &x2
, &y2
);
500 renderer_color_convert(renderer
, line_color
, &color
);
501 gdk_gc_set_foreground(gc
, &color
);
503 gdk_draw_line(renderer
->pixmap
, gc
,
508 fill_polygon (DiaRenderer
*object
, Point
*points
, int num_points
, Color
*line_color
)
510 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
511 GdkGC
*gc
= renderer
->gc
;
513 GdkPoint
*gdk_points
;
516 gdk_points
= g_new(GdkPoint
, num_points
);
518 for (i
=0;i
<num_points
;i
++) {
519 dia_transform_coords(renderer
->transform
, points
[i
].x
, points
[i
].y
, &x
, &y
);
524 renderer_color_convert(renderer
, line_color
, &color
);
525 gdk_gc_set_foreground(gc
, &color
);
527 gdk_draw_polygon(renderer
->pixmap
, gc
, TRUE
, gdk_points
, num_points
);
532 draw_fill_arc (DiaRenderer
*object
,
534 real width
, real height
,
535 real angle1
, real angle2
,
539 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
540 GdkGC
*gc
= renderer
->gc
;
542 gint top
, left
, bottom
, right
;
545 dia_transform_coords(renderer
->transform
,
546 center
->x
- width
/2, center
->y
- height
/2,
548 dia_transform_coords(renderer
->transform
,
549 center
->x
+ width
/2, center
->y
+ height
/2,
552 if ((left
>right
) || (top
>bottom
))
555 renderer_color_convert(renderer
, color
, &gdkcolor
);
556 gdk_gc_set_foreground(gc
, &gdkcolor
);
558 dangle
= angle2
-angle1
;
562 gdk_draw_arc(renderer
->pixmap
,
564 left
, top
, right
-left
+(fill
?1:0), bottom
-top
+(fill
?1:0),
565 (int) (angle1
*64.0), (int) (dangle
*64.0));
568 draw_arc (DiaRenderer
*object
,
570 real width
, real height
,
571 real angle1
, real angle2
,
574 draw_fill_arc (object
, center
, width
, height
, angle1
, angle2
, color
, FALSE
);
578 fill_arc (DiaRenderer
*object
, Point
*center
,
579 real width
, real height
, real angle1
, real angle2
,
582 draw_fill_arc (object
, center
, width
, height
, angle1
, angle2
, color
, TRUE
);
586 draw_ellipse (DiaRenderer
*object
, Point
*center
,
587 real width
, real height
,
590 draw_arc(object
, center
, width
, height
, 0.0, 360.0, color
);
594 fill_ellipse (DiaRenderer
*object
, Point
*center
,
595 real width
, real height
, Color
*color
)
597 fill_arc(object
, center
, width
, height
, 0.0, 360.0, color
);
600 /* Draw a highlighted version of a string.
603 draw_highlighted_string(DiaGdkRenderer
*renderer
,
610 pango_layout_get_pixel_size(layout
, &width
, &height
);
612 gdk_gc_set_foreground(renderer
->gc
, color
);
614 gdk_draw_rectangle (renderer
->pixmap
,
621 draw_string (DiaRenderer
*object
,
622 const gchar
*text
, Point
*pos
, Alignment alignment
,
625 TextLine
*text_line
= text_line_new(text
, object
->font
, object
->font_height
);
626 Point realigned_pos
= *pos
;
627 realigned_pos
.x
-= text_line_get_alignment_adjustment(text_line
, alignment
);
628 draw_text_line(object
, text_line
, &realigned_pos
, color
);
633 initialize_ft_bitmap(FT_Bitmap
*ftbitmap
, int width
, int height
)
635 int rowstride
= 32*((width
+31)/31);
636 guint8
*graybitmap
= (guint8
*)g_new0(guint8
, height
*rowstride
);
638 ftbitmap
->rows
= height
;
639 ftbitmap
->width
= width
;
640 ftbitmap
->pitch
= rowstride
;
641 ftbitmap
->buffer
= graybitmap
;
642 ftbitmap
->num_grays
= 256;
643 ftbitmap
->pixel_mode
= ft_pixel_mode_grays
;
644 ftbitmap
->palette_mode
= 0;
645 ftbitmap
->palette
= 0;
648 typedef struct _FreetypeCacheData
{
657 free_freetype_cache_data(gpointer data
) {
658 FreetypeCacheData
*ftdata
= (FreetypeCacheData
*) data
;
660 g_object_unref(ftdata
->rgba
);
665 /** Draw a TextLine object.
666 * @param object The renderer object to use for transform and output
667 * @param text_line The TextLine to render, including font and height.
668 * @param pos The position to render it at.
669 * @param color The color to render it with.
672 draw_text_line (DiaRenderer
*object
, TextLine
*text_line
,
673 Point
*pos
, Color
*color
)
675 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
679 PangoLayout
* layout
= NULL
;
680 const gchar
*text
= text_line_get_string(text_line
);
682 real font_height
= text_line_get_height(text_line
);
683 real scale
= dia_transform_length(renderer
->transform
, 1.0);
685 if (text
== NULL
|| *text
== '\0') return; /* Don't render empty strings. */
687 point_copy(&start_pos
,pos
);
689 renderer_color_convert(renderer
, color
, &gdkcolor
);
691 height_pixels
= dia_transform_length(renderer
->transform
, font_height
);
692 if (height_pixels
< 2) { /* "Greeking" instead of making tiny font */
693 int width_pixels
= dia_transform_length(renderer
->transform
,
694 text_line_get_width(text_line
));
695 gdk_gc_set_foreground(renderer
->gc
, &gdkcolor
);
696 gdk_gc_set_dashes(renderer
->gc
, 0, "\1\2", 2);
697 dia_transform_coords(renderer
->transform
, start_pos
.x
, start_pos
.y
, &x
, &y
);
698 gdk_draw_line(renderer
->pixmap
, renderer
->gc
, x
, y
, x
+ width_pixels
, y
);
703 adjust
= text_line_get_ascent(text_line
);
704 start_pos
.y
-= adjust
;
706 dia_transform_coords(renderer
->transform
,
707 start_pos
.x
, start_pos
.y
, &x
, &y
);
710 /* The cache appears to work, but there's no gain from it yet, since
711 * nobody hangs on to textline objects long enough.
713 #ifdef USE_TEXTLINE_CACHE
714 FreetypeCacheData
*cache
= text_line_get_renderer_cache(text_line
,
718 gdk_draw_pixbuf(renderer
->pixmap
, renderer
->gc
, cache
->rgba
,
720 cache
->width
, cache
->height
, GDK_RGB_DITHER_NONE
, 0, 0);
726 layout
= dia_font_build_layout(text
, text_line
->font
,
727 dia_transform_length(renderer
->transform
, text_line
->height
)/20.0);
729 text_line_adjust_layout_line(text_line
, pango_layout_get_line(layout
, 0),
731 if (renderer
->highlight_color
!= NULL
) {
732 draw_highlighted_string(renderer
, layout
, x
, y
, &gdkcolor
);
734 #if defined HAVE_FREETYPE
738 GdkPixbuf
*rgba
= NULL
;
740 width
= dia_transform_length(renderer
->transform
,
741 text_line_get_width(text_line
));
742 height
= dia_transform_length(renderer
->transform
,
743 text_line_get_height(text_line
));
750 FreetypeCacheData
*cache
;
752 initialize_ft_bitmap(&ftbitmap
, width
, height
);
753 pango_ft2_render_layout(&ftbitmap
, layout
, 0, 0);
755 graybitmap
= ftbitmap
.buffer
;
757 rgba
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, TRUE
, 8, width
, height
);
758 stride
= gdk_pixbuf_get_rowstride(rgba
);
759 pixels
= gdk_pixbuf_get_pixels(rgba
);
760 for (i
= 0; i
< height
; i
++) {
761 for (j
= 0; j
< width
; j
++) {
762 pixels
[i
*stride
+j
*4] = gdkcolor
.red
>>8;
763 pixels
[i
*stride
+j
*4+1] = gdkcolor
.green
>>8;
764 pixels
[i
*stride
+j
*4+2] = gdkcolor
.blue
>>8;
765 pixels
[i
*stride
+j
*4+3] = graybitmap
[i
*ftbitmap
.pitch
+j
];
770 gdk_draw_pixbuf(renderer
->pixmap
, renderer
->gc
, rgba
, 0, 0, x
, y
, width
, height
, GDK_RGB_DITHER_NONE
, 0, 0);
771 #ifdef USE_TEXTLINE_CACHE
772 /* This is not exactly useful until textline objects start hanging
773 * around longer than the duration of draw_string(). Nor is it
774 * entirely debugged (i.e. it crashes:)
776 cache
= g_new(FreetypeCacheData
, 1);
778 cache
->width
= width
;
779 cache
->height
= height
;
780 text_line_set_renderer_cache(text_line
, object
,
781 free_freetype_cache_data
, scale
, cache
);
783 g_object_unref(G_OBJECT(rgba
));
788 gdk_gc_set_foreground(renderer
->gc
, &gdkcolor
);
790 gdk_draw_layout(renderer
->pixmap
, renderer
->gc
, x
, y
, layout
);
792 g_object_unref(G_OBJECT(layout
));
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
);
806 if (length
!= strlen(text
)) {
809 /* A couple UTF8-chars: æblegrød Š Ť Ž ę ć ń уфхцНОПРЄ є Ґ Њ Ћ Џ */
810 ulen
= g_utf8_offset_to_pointer(text
, length
)-text
;
811 if (!g_utf8_validate(text
, ulen
, NULL
)) {
812 g_warning ("Text at char %d not valid\n", length
);
814 othertx
= g_strndup(text
, ulen
);
815 text_line
= text_line_new(othertx
, object
->font
, object
->font_height
);
817 text_line
= text_line_new(text
, object
->font
, object
->font_height
);
819 result
= text_line_get_width(text_line
);
820 text_line_destroy(text_line
);
825 draw_image (DiaRenderer
*object
,
827 real width
, real height
,
830 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
831 if (renderer
->highlight_color
!= NULL
) {
833 DiaRendererClass
*self_class
= DIA_RENDERER_GET_CLASS (object
);
838 self_class
->fill_rect(object
, point
, &lr
, renderer
->highlight_color
);
840 int real_width
, real_height
, real_x
, real_y
;
842 real_width
= dia_transform_length(renderer
->transform
, width
);
843 real_height
= dia_transform_length(renderer
->transform
, height
);
844 dia_transform_coords(renderer
->transform
, point
->x
, point
->y
,
847 dia_image_draw(image
, renderer
->pixmap
, real_x
, real_y
,
848 real_width
, real_height
);
853 * medium level functions
856 draw_fill_rect (DiaGdkRenderer
*renderer
,
857 Point
*ul_corner
, Point
*lr_corner
,
858 Color
*color
, gboolean fill
)
860 GdkGC
*gc
= renderer
->gc
;
862 gint top
, bottom
, left
, right
;
864 dia_transform_coords(renderer
->transform
,
865 ul_corner
->x
, ul_corner
->y
, &left
, &top
);
866 dia_transform_coords(renderer
->transform
,
867 lr_corner
->x
, lr_corner
->y
, &right
, &bottom
);
869 if ((left
>right
) || (top
>bottom
))
872 renderer_color_convert(renderer
, color
, &gdkcolor
);
873 gdk_gc_set_foreground(gc
, &gdkcolor
);
875 gdk_draw_rectangle (renderer
->pixmap
,
883 draw_rect (DiaRenderer
*object
,
884 Point
*ul_corner
, Point
*lr_corner
,
887 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
889 draw_fill_rect (renderer
, ul_corner
, lr_corner
, color
, FALSE
);
893 fill_rect (DiaRenderer
*object
,
894 Point
*ul_corner
, Point
*lr_corner
,
897 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
899 draw_fill_rect (renderer
, ul_corner
, lr_corner
, color
, TRUE
);
903 draw_polyline (DiaRenderer
*self
,
904 Point
*points
, int num_points
,
907 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (self
);
908 GdkGC
*gc
= renderer
->gc
;
910 GdkPoint
*gdk_points
;
913 gdk_points
= g_new(GdkPoint
, num_points
);
915 for (i
=0;i
<num_points
;i
++) {
916 dia_transform_coords(renderer
->transform
, points
[i
].x
, points
[i
].y
, &x
, &y
);
921 renderer_color_convert(renderer
, line_color
, &color
);
922 gdk_gc_set_foreground(gc
, &color
);
924 gdk_draw_lines(renderer
->pixmap
, gc
, gdk_points
, num_points
);
929 draw_polygon (DiaRenderer
*self
,
930 Point
*points
, int num_points
,
933 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (self
);
934 GdkGC
*gc
= renderer
->gc
;
936 GdkPoint
*gdk_points
;
939 gdk_points
= g_new(GdkPoint
, num_points
);
941 for (i
=0;i
<num_points
;i
++) {
942 dia_transform_coords(renderer
->transform
, points
[i
].x
, points
[i
].y
, &x
, &y
);
947 renderer_color_convert(renderer
, line_color
, &color
);
948 gdk_gc_set_foreground(gc
, &color
);
950 gdk_draw_polygon(renderer
->pixmap
, gc
, FALSE
, gdk_points
, num_points
);
955 draw_object (DiaRenderer
*renderer
, DiaObject
*object
)
957 if (renderer
->is_interactive
&&
958 object
->highlight_color
!= NULL
) {
959 DiaGdkRenderer
*gdk_rend
= DIA_GDK_RENDERER(renderer
);
960 gdk_rend
->highlight_color
= object
->highlight_color
;
961 object
->ops
->draw(object
, renderer
);
962 gdk_rend
->highlight_color
= NULL
;
964 object
->ops
->draw(object
, renderer
);
968 get_width_pixels (DiaRenderer
*object
)
970 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
973 if (renderer
->pixmap
)
974 gdk_drawable_get_size (GDK_DRAWABLE (renderer
->pixmap
), &width
, NULL
);
980 get_height_pixels (DiaRenderer
*object
)
982 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
985 if (renderer
->pixmap
)
986 gdk_drawable_get_size (GDK_DRAWABLE (renderer
->pixmap
), NULL
, &height
);