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"
45 #include <pango/pango.h>
46 #include <pango/pangoft2.h>
49 static int get_width_pixels (DiaRenderer
*);
50 static int get_height_pixels (DiaRenderer
*);
52 static void begin_render (DiaRenderer
*);
53 static void end_render (DiaRenderer
*);
55 static void set_linewidth (DiaRenderer
*renderer
, real linewidth
);
56 static void set_linecaps (DiaRenderer
*renderer
, LineCaps mode
);
57 static void set_linejoin (DiaRenderer
*renderer
, LineJoin mode
);
58 static void set_linestyle (DiaRenderer
*renderer
, LineStyle mode
);
59 static void set_dashlength (DiaRenderer
*renderer
, real length
);
60 static void set_fillstyle (DiaRenderer
*renderer
, FillStyle mode
);
62 static void draw_line (DiaRenderer
*renderer
,
63 Point
*start
, Point
*end
,
65 static void fill_polygon (DiaRenderer
*renderer
,
66 Point
*points
, int num_points
,
68 static void draw_arc (DiaRenderer
*renderer
,
70 real width
, real height
,
71 real angle1
, real angle2
,
73 static void fill_arc (DiaRenderer
*renderer
,
75 real width
, real height
,
76 real angle1
, real angle2
,
78 static void draw_ellipse (DiaRenderer
*renderer
,
80 real width
, real height
,
82 static void fill_ellipse (DiaRenderer
*renderer
,
84 real width
, real height
,
86 static void draw_string (DiaRenderer
*renderer
,
91 static void draw_text_line (DiaRenderer
*renderer
,
95 static void draw_text (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
= draw_text
;
240 renderer_class
->draw_text_line
= draw_text_line
;
241 renderer_class
->draw_image
= draw_image
;
243 /* medium level functions */
244 renderer_class
->draw_rect
= draw_rect
;
245 renderer_class
->draw_polyline
= draw_polyline
;
246 renderer_class
->draw_polygon
= draw_polygon
;
247 renderer_class
->draw_object
= draw_object
;
249 /* Interactive functions */
250 renderer_class
->get_text_width
= get_text_width
;
253 /** Convert Dia color objects into GDK color objects.
254 * If the highlight color is set, that will be used instead. This allows
255 * rendering of an object to do highlight rendering.
256 * @param renderer The renderer to check for highlight color.
257 * @param col A color object to convert.
258 * @param gdk_col Resulting GDK convert.
261 renderer_color_convert(DiaGdkRenderer
*renderer
,
262 Color
*col
, GdkColor
*gdk_col
)
264 if (renderer
->highlight_color
!= NULL
) {
265 color_convert(renderer
->highlight_color
, gdk_col
);
267 color_convert(col
, gdk_col
);
272 begin_render (DiaRenderer
*object
)
277 end_render (DiaRenderer
*object
)
282 set_linewidth (DiaRenderer
*object
, real linewidth
)
284 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
286 if (renderer
->highlight_color
!= NULL
) {
287 /* 6 pixels wide -> 3 pixels beyond normal obj */
288 real border
= dia_untransform_length(renderer
->transform
, 6);
293 renderer
->line_width
=
294 dia_transform_length(renderer
->transform
, linewidth
);
296 if (renderer
->line_width
<=0)
297 renderer
->line_width
= 1; /* Minimum 1 pixel. */
299 gdk_gc_set_line_attributes(renderer
->gc
,
300 renderer
->line_width
,
301 renderer
->line_style
,
303 renderer
->join_style
);
307 set_linecaps (DiaRenderer
*object
, LineCaps mode
)
309 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
311 if (renderer
->highlight_color
!= NULL
) {
312 renderer
->cap_style
= GDK_CAP_ROUND
;
316 renderer
->cap_style
= GDK_CAP_BUTT
;
319 renderer
->cap_style
= GDK_CAP_ROUND
;
321 case LINECAPS_PROJECTING
:
322 renderer
->cap_style
= GDK_CAP_PROJECTING
;
327 gdk_gc_set_line_attributes(renderer
->gc
,
328 renderer
->line_width
,
329 renderer
->line_style
,
331 renderer
->join_style
);
335 set_linejoin (DiaRenderer
*object
, LineJoin mode
)
337 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
339 if (renderer
->highlight_color
!= NULL
) {
340 renderer
->join_style
= GDK_JOIN_ROUND
;
344 renderer
->join_style
= GDK_JOIN_MITER
;
347 renderer
->join_style
= GDK_JOIN_ROUND
;
350 renderer
->join_style
= GDK_JOIN_BEVEL
;
353 /* invalid mode, just here to set a breakpoint */
354 renderer
->join_style
= GDK_JOIN_ROUND
;
359 gdk_gc_set_line_attributes(renderer
->gc
,
360 renderer
->line_width
,
361 renderer
->line_style
,
363 renderer
->join_style
);
366 /** Set the dashes for this renderer.
367 * offset determines where in the pattern the dashes will start.
368 * It is used by the grid in particular to make the grid dashes line up.
371 dia_gdk_renderer_set_dashes(DiaGdkRenderer
*renderer
, int offset
)
377 switch(renderer
->saved_line_style
) {
378 case LINESTYLE_SOLID
:
380 case LINESTYLE_DASHED
:
381 dash_list
[0] = renderer
->dash_length
;
382 dash_list
[1] = renderer
->dash_length
;
383 pattern_length
= renderer
->dash_length
*2;
384 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 2);
386 case LINESTYLE_DASH_DOT
:
387 hole_width
= (renderer
->dash_length
- renderer
->dot_length
) / 2;
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 pattern_length
= renderer
->dash_length
+renderer
->dot_length
+2*hole_width
;
395 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 4);
397 case LINESTYLE_DASH_DOT_DOT
:
398 hole_width
= (renderer
->dash_length
- 2*renderer
->dot_length
) / 3;
401 dash_list
[0] = renderer
->dash_length
;
402 dash_list
[1] = hole_width
;
403 dash_list
[2] = renderer
->dot_length
;
404 dash_list
[3] = hole_width
;
405 dash_list
[4] = renderer
->dot_length
;
406 dash_list
[5] = hole_width
;
407 pattern_length
= renderer
->dash_length
+2*renderer
->dot_length
+3*hole_width
;
408 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 6);
410 case LINESTYLE_DOTTED
:
411 dash_list
[0] = renderer
->dot_length
;
412 dash_list
[1] = renderer
->dot_length
;
413 pattern_length
= renderer
->dot_length
;
414 gdk_gc_set_dashes(renderer
->gc
, offset
, dash_list
, 2);
421 set_linestyle (DiaRenderer
*object
, LineStyle mode
)
423 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
425 renderer
->saved_line_style
= mode
;
427 case LINESTYLE_SOLID
:
428 renderer
->line_style
= GDK_LINE_SOLID
;
430 case LINESTYLE_DASHED
:
431 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
432 dia_gdk_renderer_set_dashes(renderer
, 0);
434 case LINESTYLE_DASH_DOT
:
435 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
436 dia_gdk_renderer_set_dashes(renderer
, 0);
438 case LINESTYLE_DASH_DOT_DOT
:
439 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
440 dia_gdk_renderer_set_dashes(renderer
, 0);
442 case LINESTYLE_DOTTED
:
443 renderer
->line_style
= GDK_LINE_ON_OFF_DASH
;
444 dia_gdk_renderer_set_dashes(renderer
, 0);
447 gdk_gc_set_line_attributes(renderer
->gc
,
448 renderer
->line_width
,
449 renderer
->line_style
,
451 renderer
->join_style
);
455 set_dashlength (DiaRenderer
*object
, real length
)
457 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
458 /* dot = 10% of len */
462 dia_transform_length(renderer
->transform
, length
);
464 renderer
->dash_length
= (int)floor(ddisp_len
+0.5);
465 renderer
->dot_length
= (int)floor(ddisp_len
*0.1+0.5);
467 if (renderer
->dash_length
<=0)
468 renderer
->dash_length
= 1;
469 if (renderer
->dash_length
>255)
470 renderer
->dash_length
= 255;
471 if (renderer
->dot_length
<=0)
472 renderer
->dot_length
= 1;
473 if (renderer
->dot_length
>255)
474 renderer
->dot_length
= 255;
475 set_linestyle(object
, renderer
->saved_line_style
);
479 set_fillstyle (DiaRenderer
*object
, FillStyle mode
)
482 case FILLSTYLE_SOLID
:
485 message_error("gdk_renderer: Unsupported fill mode specified!\n");
490 draw_line (DiaRenderer
*object
, Point
*start
, Point
*end
, Color
*line_color
)
492 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
494 GdkGC
*gc
= renderer
->gc
;
498 dia_transform_coords(renderer
->transform
, start
->x
, start
->y
, &x1
, &y1
);
499 dia_transform_coords(renderer
->transform
, end
->x
, end
->y
, &x2
, &y2
);
501 renderer_color_convert(renderer
, line_color
, &color
);
502 gdk_gc_set_foreground(gc
, &color
);
504 gdk_draw_line(renderer
->pixmap
, gc
,
509 fill_polygon (DiaRenderer
*object
, Point
*points
, int num_points
, Color
*line_color
)
511 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
512 GdkGC
*gc
= renderer
->gc
;
514 GdkPoint
*gdk_points
;
517 gdk_points
= g_new(GdkPoint
, num_points
);
519 for (i
=0;i
<num_points
;i
++) {
520 dia_transform_coords(renderer
->transform
, points
[i
].x
, points
[i
].y
, &x
, &y
);
525 renderer_color_convert(renderer
, line_color
, &color
);
526 gdk_gc_set_foreground(gc
, &color
);
528 gdk_draw_polygon(renderer
->pixmap
, gc
, TRUE
, gdk_points
, num_points
);
533 draw_fill_arc (DiaRenderer
*object
,
535 real width
, real height
,
536 real angle1
, real angle2
,
540 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
541 GdkGC
*gc
= renderer
->gc
;
543 gint top
, left
, bottom
, right
;
546 dia_transform_coords(renderer
->transform
,
547 center
->x
- width
/2, center
->y
- height
/2,
549 dia_transform_coords(renderer
->transform
,
550 center
->x
+ width
/2, center
->y
+ height
/2,
553 if ((left
>right
) || (top
>bottom
))
556 renderer_color_convert(renderer
, color
, &gdkcolor
);
557 gdk_gc_set_foreground(gc
, &gdkcolor
);
559 dangle
= angle2
-angle1
;
563 gdk_draw_arc(renderer
->pixmap
,
565 left
, top
, right
-left
+(fill
?1:0), bottom
-top
+(fill
?1:0),
566 (int) (angle1
*64.0), (int) (dangle
*64.0));
569 draw_arc (DiaRenderer
*object
,
571 real width
, real height
,
572 real angle1
, real angle2
,
575 draw_fill_arc (object
, center
, width
, height
, angle1
, angle2
, color
, FALSE
);
579 fill_arc (DiaRenderer
*object
, Point
*center
,
580 real width
, real height
, real angle1
, real angle2
,
583 draw_fill_arc (object
, center
, width
, height
, angle1
, angle2
, color
, TRUE
);
587 draw_ellipse (DiaRenderer
*object
, Point
*center
,
588 real width
, real height
,
591 draw_arc(object
, center
, width
, height
, 0.0, 360.0, color
);
595 fill_ellipse (DiaRenderer
*object
, Point
*center
,
596 real width
, real height
, Color
*color
)
598 fill_arc(object
, center
, width
, height
, 0.0, 360.0, color
);
601 /* Draw a highlighted version of a string.
604 draw_highlighted_string(DiaGdkRenderer
*renderer
,
611 pango_layout_get_pixel_size(layout
, &width
, &height
);
613 gdk_gc_set_foreground(renderer
->gc
, color
);
615 gdk_draw_rectangle (renderer
->pixmap
,
622 draw_string (DiaRenderer
*object
,
623 const gchar
*text
, Point
*pos
, Alignment alignment
,
626 TextLine
*text_line
= text_line_new(text
, object
->font
, object
->font_height
);
627 Point realigned_pos
= *pos
;
628 realigned_pos
.x
-= text_line_get_alignment_adjustment(text_line
, alignment
);
629 draw_text_line(object
, text_line
, &realigned_pos
, color
);
634 initialize_ft_bitmap(FT_Bitmap
*ftbitmap
, int width
, int height
)
636 int rowstride
= 32*((width
+31)/31);
637 guint8
*graybitmap
= (guint8
*)g_new0(guint8
, height
*rowstride
);
639 ftbitmap
->rows
= height
;
640 ftbitmap
->width
= width
;
641 ftbitmap
->pitch
= rowstride
;
642 ftbitmap
->buffer
= graybitmap
;
643 ftbitmap
->num_grays
= 256;
644 ftbitmap
->pixel_mode
= ft_pixel_mode_grays
;
645 ftbitmap
->palette_mode
= 0;
646 ftbitmap
->palette
= 0;
649 typedef struct _FreetypeCacheData
{
658 free_freetype_cache_data(gpointer data
) {
659 FreetypeCacheData
*ftdata
= (FreetypeCacheData
*) data
;
661 g_object_unref(ftdata
->rgba
);
666 /** Draw a TextLine object.
667 * @param object The renderer object to use for transform and output
668 * @param text_line The TextLine to render, including font and height.
669 * @param pos The position to render it at.
670 * @param color The color to render it with.
673 draw_text_line (DiaRenderer
*object
, TextLine
*text_line
,
674 Point
*pos
, Color
*color
)
676 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
680 PangoLayout
* layout
= NULL
;
681 const gchar
*text
= text_line_get_string(text_line
);
683 real font_height
= text_line_get_height(text_line
);
684 real scale
= dia_transform_length(renderer
->transform
, 1.0);
686 if (text
== NULL
|| *text
== '\0') return; /* Don't render empty strings. */
688 point_copy(&start_pos
,pos
);
690 renderer_color_convert(renderer
, color
, &gdkcolor
);
692 height_pixels
= dia_transform_length(renderer
->transform
, font_height
);
693 if (height_pixels
< 2) { /* "Greeking" instead of making tiny font */
694 int width_pixels
= dia_transform_length(renderer
->transform
,
695 text_line_get_width(text_line
));
696 gdk_gc_set_foreground(renderer
->gc
, &gdkcolor
);
697 gdk_gc_set_dashes(renderer
->gc
, 0, "\1\2", 2);
698 dia_transform_coords(renderer
->transform
, start_pos
.x
, start_pos
.y
, &x
, &y
);
699 gdk_draw_line(renderer
->pixmap
, renderer
->gc
, x
, y
, x
+ width_pixels
, y
);
704 adjust
= text_line_get_ascent(text_line
);
705 start_pos
.y
-= adjust
;
707 dia_transform_coords(renderer
->transform
,
708 start_pos
.x
, start_pos
.y
, &x
, &y
);
711 /* The cache appears to work, but there's no gain from it yet, since
712 * nobody hangs on to textline objects long enough.
714 #ifdef USE_TEXTLINE_CACHE
715 FreetypeCacheData
*cache
= text_line_get_renderer_cache(text_line
,
719 gdk_draw_pixbuf(renderer
->pixmap
, renderer
->gc
, cache
->rgba
,
721 cache
->width
, cache
->height
, GDK_RGB_DITHER_NONE
, 0, 0);
727 layout
= dia_font_build_layout(text
, text_line
->font
,
728 dia_transform_length(renderer
->transform
, text_line
->height
)/20.0);
730 text_line_adjust_layout_line(text_line
, pango_layout_get_line(layout
, 0),
732 if (renderer
->highlight_color
!= NULL
) {
733 draw_highlighted_string(renderer
, layout
, x
, y
, &gdkcolor
);
735 #if defined HAVE_FREETYPE
739 GdkPixbuf
*rgba
= NULL
;
741 width
= dia_transform_length(renderer
->transform
,
742 text_line_get_width(text_line
));
743 height
= dia_transform_length(renderer
->transform
,
744 text_line_get_height(text_line
));
751 FreetypeCacheData
*cache
;
753 initialize_ft_bitmap(&ftbitmap
, width
, height
);
754 pango_ft2_render_layout(&ftbitmap
, layout
, 0, 0);
756 graybitmap
= ftbitmap
.buffer
;
758 rgba
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, TRUE
, 8, width
, height
);
759 stride
= gdk_pixbuf_get_rowstride(rgba
);
760 pixels
= gdk_pixbuf_get_pixels(rgba
);
761 for (i
= 0; i
< height
; i
++) {
762 for (j
= 0; j
< width
; j
++) {
763 pixels
[i
*stride
+j
*4] = gdkcolor
.red
>>8;
764 pixels
[i
*stride
+j
*4+1] = gdkcolor
.green
>>8;
765 pixels
[i
*stride
+j
*4+2] = gdkcolor
.blue
>>8;
766 pixels
[i
*stride
+j
*4+3] = graybitmap
[i
*ftbitmap
.pitch
+j
];
771 gdk_draw_pixbuf(renderer
->pixmap
, renderer
->gc
, rgba
, 0, 0, x
, y
, width
, height
, GDK_RGB_DITHER_NONE
, 0, 0);
772 #ifdef USE_TEXTLINE_CACHE
773 /* This is not exactly useful until textline objects start hanging
774 * around longer than the duration of draw_string(). Nor is it
775 * entirely debugged (i.e. it crashes:)
777 cache
= g_new(FreetypeCacheData
, 1);
779 cache
->width
= width
;
780 cache
->height
= height
;
781 text_line_set_renderer_cache(text_line
, object
,
782 free_freetype_cache_data
, scale
, cache
);
784 g_object_unref(G_OBJECT(rgba
));
789 gdk_gc_set_foreground(renderer
->gc
, &gdkcolor
);
791 gdk_draw_layout(renderer
->pixmap
, renderer
->gc
, x
, y
, layout
);
793 g_object_unref(G_OBJECT(layout
));
798 /** Caching Pango renderer */
800 draw_text(DiaRenderer
*renderer
, Text
*text
)
805 DIA_RENDERER_GET_CLASS(renderer
)->set_font(renderer
, text
->font
, text
->height
);
806 pos
= text
->position
;
808 for (i
=0;i
<text
->numlines
;i
++) {
809 DIA_RENDERER_GET_CLASS(renderer
)->draw_string(renderer
,
811 &pos
, text
->alignment
,
813 pos
.y
+= text
->height
;
818 /* Get the width of the given text in cm */
820 get_text_width(DiaRenderer
*object
,
821 const gchar
*text
, int length
)
823 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
827 if (length
!= strlen(text
)) {
830 /* A couple UTF8-chars: æblegrød Š Ť Ž ę ć ń уфхцНОПРЄ є Ґ Њ Ћ Џ */
831 ulen
= g_utf8_offset_to_pointer(text
, length
)-text
;
832 if (!g_utf8_validate(text
, ulen
, NULL
)) {
833 g_warning ("Text at char %d not valid\n", length
);
835 othertx
= g_strndup(text
, ulen
);
836 text_line
= text_line_new(othertx
, object
->font
, object
->font_height
);
838 text_line
= text_line_new(text
, object
->font
, object
->font_height
);
840 result
= text_line_get_width(text_line
);
841 text_line_destroy(text_line
);
846 draw_image (DiaRenderer
*object
,
848 real width
, real height
,
851 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
852 if (renderer
->highlight_color
!= NULL
) {
854 DiaRendererClass
*self_class
= DIA_RENDERER_GET_CLASS (object
);
859 self_class
->fill_rect(object
, point
, &lr
, renderer
->highlight_color
);
861 int real_width
, real_height
, real_x
, real_y
;
863 real_width
= dia_transform_length(renderer
->transform
, width
);
864 real_height
= dia_transform_length(renderer
->transform
, height
);
865 dia_transform_coords(renderer
->transform
, point
->x
, point
->y
,
868 dia_image_draw(image
, renderer
->pixmap
, real_x
, real_y
,
869 real_width
, real_height
);
874 * medium level functions
877 draw_fill_rect (DiaGdkRenderer
*renderer
,
878 Point
*ul_corner
, Point
*lr_corner
,
879 Color
*color
, gboolean fill
)
881 GdkGC
*gc
= renderer
->gc
;
883 gint top
, bottom
, left
, right
;
885 dia_transform_coords(renderer
->transform
,
886 ul_corner
->x
, ul_corner
->y
, &left
, &top
);
887 dia_transform_coords(renderer
->transform
,
888 lr_corner
->x
, lr_corner
->y
, &right
, &bottom
);
890 if ((left
>right
) || (top
>bottom
))
893 renderer_color_convert(renderer
, color
, &gdkcolor
);
894 gdk_gc_set_foreground(gc
, &gdkcolor
);
896 gdk_draw_rectangle (renderer
->pixmap
,
904 draw_rect (DiaRenderer
*object
,
905 Point
*ul_corner
, Point
*lr_corner
,
908 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
910 draw_fill_rect (renderer
, ul_corner
, lr_corner
, color
, FALSE
);
914 fill_rect (DiaRenderer
*object
,
915 Point
*ul_corner
, Point
*lr_corner
,
918 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
920 draw_fill_rect (renderer
, ul_corner
, lr_corner
, color
, TRUE
);
924 draw_polyline (DiaRenderer
*self
,
925 Point
*points
, int num_points
,
928 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (self
);
929 GdkGC
*gc
= renderer
->gc
;
931 GdkPoint
*gdk_points
;
934 gdk_points
= g_new(GdkPoint
, num_points
);
936 for (i
=0;i
<num_points
;i
++) {
937 dia_transform_coords(renderer
->transform
, points
[i
].x
, points
[i
].y
, &x
, &y
);
942 renderer_color_convert(renderer
, line_color
, &color
);
943 gdk_gc_set_foreground(gc
, &color
);
945 gdk_draw_lines(renderer
->pixmap
, gc
, gdk_points
, num_points
);
950 draw_polygon (DiaRenderer
*self
,
951 Point
*points
, int num_points
,
954 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (self
);
955 GdkGC
*gc
= renderer
->gc
;
957 GdkPoint
*gdk_points
;
960 gdk_points
= g_new(GdkPoint
, num_points
);
962 for (i
=0;i
<num_points
;i
++) {
963 dia_transform_coords(renderer
->transform
, points
[i
].x
, points
[i
].y
, &x
, &y
);
968 renderer_color_convert(renderer
, line_color
, &color
);
969 gdk_gc_set_foreground(gc
, &color
);
971 gdk_draw_polygon(renderer
->pixmap
, gc
, FALSE
, gdk_points
, num_points
);
976 draw_object (DiaRenderer
*renderer
, DiaObject
*object
)
978 if (renderer
->is_interactive
&&
979 object
->highlight_color
!= NULL
) {
980 DiaGdkRenderer
*gdk_rend
= DIA_GDK_RENDERER(renderer
);
981 gdk_rend
->highlight_color
= object
->highlight_color
;
982 object
->ops
->draw(object
, renderer
);
983 gdk_rend
->highlight_color
= NULL
;
985 object
->ops
->draw(object
, renderer
);
989 get_width_pixels (DiaRenderer
*object
)
991 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
994 if (renderer
->pixmap
)
995 gdk_drawable_get_size (GDK_DRAWABLE (renderer
->pixmap
), &width
, NULL
);
1001 get_height_pixels (DiaRenderer
*object
)
1003 DiaGdkRenderer
*renderer
= DIA_GDK_RENDERER (object
);
1006 if (renderer
->pixmap
)
1007 gdk_drawable_get_size (GDK_DRAWABLE (renderer
->pixmap
), NULL
, &height
);