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.
22 #include <string.h> /* strlen */
24 #include "dialibartrenderer.h"
30 #include "dia_image.h"
35 #include <pango/pango.h>
36 #include <pango/pangoft2.h>
37 #elif defined G_OS_WIN32
38 /* ugly namespace clashes */
39 #define Rectangle Win32Rectangle
40 #include <pango/pango.h>
41 #include <pango/pangowin32.h>
45 #include <libart_lgpl/art_point.h>
46 #include <libart_lgpl/art_misc.h>
47 #include <libart_lgpl/art_affine.h>
48 #include <libart_lgpl/art_svp_vpath.h>
49 #include <libart_lgpl/art_bpath.h>
50 #include <libart_lgpl/art_vpath_bpath.h>
51 #include <libart_lgpl/art_rgb.h>
52 #include <libart_lgpl/art_rgb_svp.h>
53 #include <libart_lgpl/art_rgb_affine.h>
54 #include <libart_lgpl/art_rgb_rgba_affine.h>
55 #include <libart_lgpl/art_rgb_bitmap_affine.h>
56 #include <libart_lgpl/art_filterlevel.h>
59 color_to_abgr(Color
*col
)
64 rgba
|= (guint
)(0xFF*col
->blue
) << 16;
65 rgba
|= (guint
)(0xFF*col
->green
) << 8;
66 rgba
|= (guint
)(0xFF*col
->red
);
72 color_to_rgba(Color
*col
)
77 rgba
|= (guint
)(0xFF*col
->red
) << 24;
78 rgba
|= (guint
)(0xFF*col
->green
) << 16;
79 rgba
|= (guint
)(0xFF*col
->blue
) << 8;
85 get_width_pixels (DiaRenderer
*self
)
87 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
89 return renderer
->pixel_width
;
93 get_height_pixels (DiaRenderer
*self
)
95 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
97 return renderer
->pixel_height
;
101 begin_render(DiaRenderer
*self
)
103 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
105 /* pango_ft2_get_context API docs :
106 * ... Use of this function is discouraged, ...
108 * I don't see that at http://developer.gnome.org/doc/API/2.0/pango
111 dia_font_push_context(pango_ft2_get_context(10, 10));
112 # define FONT_SCALE (1.0)
113 #elif defined G_OS_WIN32
114 dia_font_push_context(pango_win32_get_context());
115 /* we need to scale but can't as simple as with ft2 */
116 # define FONT_SCALE (1.0 / 22.0)
121 end_render(DiaRenderer
*self
)
123 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
125 dia_font_pop_context();
131 set_linewidth(DiaRenderer
*self
, real linewidth
)
132 { /* 0 == hairline **/
133 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
135 renderer
->line_width
=
136 dia_transform_length(renderer
->transform
, linewidth
);
138 if (renderer
->line_width
<=0.5)
139 renderer
->line_width
= 0.5; /* Minimum 0.5 pixel. */
143 set_linecaps(DiaRenderer
*self
, LineCaps mode
)
145 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
149 renderer
->cap_style
= ART_PATH_STROKE_CAP_BUTT
;
152 renderer
->cap_style
= ART_PATH_STROKE_CAP_ROUND
;
154 case LINECAPS_PROJECTING
:
155 renderer
->cap_style
= ART_PATH_STROKE_CAP_SQUARE
;
161 set_linejoin(DiaRenderer
*self
, LineJoin mode
)
163 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
167 renderer
->cap_style
= ART_PATH_STROKE_JOIN_MITER
;
170 renderer
->cap_style
= ART_PATH_STROKE_JOIN_ROUND
;
173 renderer
->cap_style
= ART_PATH_STROKE_JOIN_BEVEL
;
179 set_linestyle(DiaRenderer
*self
, LineStyle mode
)
181 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
182 static double dash
[10];
185 renderer
->saved_line_style
= mode
;
187 case LINESTYLE_SOLID
:
188 renderer
->dash_enabled
= 0;
190 case LINESTYLE_DASHED
:
191 renderer
->dash_enabled
= 1;
192 renderer
->dash
.offset
= 0.0;
193 renderer
->dash
.n_dash
= 2;
194 renderer
->dash
.dash
= dash
;
195 dash
[0] = renderer
->dash_length
;
196 dash
[1] = renderer
->dash_length
;
198 case LINESTYLE_DASH_DOT
:
199 renderer
->dash_enabled
= 1;
200 renderer
->dash
.offset
= 0.0;
201 renderer
->dash
.n_dash
= 4;
202 renderer
->dash
.dash
= dash
;
203 hole_width
= (renderer
->dash_length
- renderer
->dot_length
) / 2.0;
206 dash
[0] = renderer
->dash_length
;
207 dash
[1] = hole_width
;
208 dash
[2] = renderer
->dot_length
;
209 dash
[3] = hole_width
;
211 case LINESTYLE_DASH_DOT_DOT
:
212 renderer
->dash_enabled
= 1;
213 renderer
->dash
.offset
= 0.0;
214 renderer
->dash
.n_dash
= 6;
215 renderer
->dash
.dash
= dash
;
216 hole_width
= (renderer
->dash_length
- 2*renderer
->dot_length
) / 3;
219 dash
[0] = renderer
->dash_length
;
220 dash
[1] = hole_width
;
221 dash
[2] = renderer
->dot_length
;
222 dash
[3] = hole_width
;
223 dash
[4] = renderer
->dot_length
;
224 dash
[5] = hole_width
;
226 case LINESTYLE_DOTTED
:
227 renderer
->dash_enabled
= 1;
228 renderer
->dash
.offset
= 0.0;
229 renderer
->dash
.n_dash
= 2;
230 renderer
->dash
.dash
= dash
;
231 dash
[0] = renderer
->dot_length
;
232 dash
[1] = renderer
->dot_length
;
238 set_dashlength(DiaRenderer
*self
, real length
)
239 { /* dot = 10% of len */
240 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
244 dia_transform_length(renderer
->transform
, length
);
246 renderer
->dash_length
= ddisp_len
;
247 renderer
->dot_length
= ddisp_len
*0.1;
249 if (renderer
->dash_length
<1.0)
250 renderer
->dash_length
= 1.0;
251 if (renderer
->dash_length
>255.0)
252 renderer
->dash_length
= 255.0;
253 if (renderer
->dot_length
<1.0)
254 renderer
->dot_length
= 1.0;
255 if (renderer
->dot_length
>255.0)
256 renderer
->dot_length
= 255.0;
257 set_linestyle(self
, renderer
->saved_line_style
);
261 set_fillstyle(DiaRenderer
*self
, FillStyle mode
)
263 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
266 case FILLSTYLE_SOLID
:
269 message_error(_("gdk_renderer: Unsupported fill mode specified!\n"));
274 set_font(DiaRenderer
*self
, DiaFont
*font
, real height
)
276 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
278 renderer
->font_height
= height
* FONT_SCALE
;
279 // ddisplay_transform_length(renderer->ddisp, height);
282 dia_font_unref(renderer
->font
);
283 renderer
->font
= dia_font_ref(font
);
287 draw_line(DiaRenderer
*self
,
288 Point
*start
, Point
*end
,
291 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
292 ArtVpath
*vpath
, *vpath_dashed
;
297 rgba
= color_to_rgba(line_color
);
299 vpath
= art_new (ArtVpath
, 3);
301 dia_transform_coords_double(renderer
->transform
, start
->x
, start
->y
, &x
, &y
);
302 vpath
[0].code
= ART_MOVETO
;
306 dia_transform_coords_double(renderer
->transform
, end
->x
, end
->y
, &x
, &y
);
307 vpath
[1].code
= ART_LINETO
;
311 vpath
[2].code
= ART_END
;
315 if (renderer
->dash_enabled
) {
316 vpath_dashed
= art_vpath_dash(vpath
, &renderer
->dash
);
318 vpath
= vpath_dashed
;
321 svp
= art_svp_vpath_stroke (vpath
,
322 renderer
->join_style
,
324 renderer
->line_width
,
330 art_rgb_svp_alpha (svp
,
332 renderer
->pixel_width
,
333 renderer
->pixel_height
,
335 renderer
->rgb_buffer
, renderer
->pixel_width
*3,
342 draw_polyline(DiaRenderer
*self
,
343 Point
*points
, int num_points
,
346 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
347 ArtVpath
*vpath
, *vpath_dashed
;
353 rgba
= color_to_rgba(line_color
);
355 vpath
= art_new (ArtVpath
, num_points
+1);
357 for (i
=0;i
<num_points
;i
++) {
358 dia_transform_coords_double(renderer
->transform
,
359 points
[i
].x
, points
[i
].y
,
361 vpath
[i
].code
= (i
==0)?ART_MOVETO
:ART_LINETO
;
365 vpath
[i
].code
= ART_END
;
369 if (renderer
->dash_enabled
) {
370 vpath_dashed
= art_vpath_dash(vpath
, &renderer
->dash
);
372 vpath
= vpath_dashed
;
375 svp
= art_svp_vpath_stroke (vpath
,
376 renderer
->join_style
,
378 renderer
->line_width
,
384 art_rgb_svp_alpha (svp
,
386 renderer
->pixel_width
,
387 renderer
->pixel_height
,
389 renderer
->rgb_buffer
, renderer
->pixel_width
*3,
396 draw_polygon(DiaRenderer
*self
,
397 Point
*points
, int num_points
,
400 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
401 ArtVpath
*vpath
, *vpath_dashed
;
407 rgba
= color_to_rgba(line_color
);
409 vpath
= art_new (ArtVpath
, num_points
+2);
411 for (i
=0;i
<num_points
;i
++) {
412 dia_transform_coords_double(renderer
->transform
,
413 points
[i
].x
, points
[i
].y
,
415 vpath
[i
].code
= (i
==0)?ART_MOVETO
:ART_LINETO
;
419 dia_transform_coords_double(renderer
->transform
,
420 points
[0].x
, points
[0].y
,
422 vpath
[i
].code
= ART_LINETO
;
425 vpath
[i
+1].code
= ART_END
;
429 if (renderer
->dash_enabled
) {
430 vpath_dashed
= art_vpath_dash(vpath
, &renderer
->dash
);
432 vpath
= vpath_dashed
;
435 svp
= art_svp_vpath_stroke (vpath
,
436 renderer
->join_style
,
438 renderer
->line_width
,
444 art_rgb_svp_alpha (svp
,
446 renderer
->pixel_width
,
447 renderer
->pixel_height
,
449 renderer
->rgb_buffer
, renderer
->pixel_width
*3,
456 fill_polygon(DiaRenderer
*self
,
457 Point
*points
, int num_points
,
460 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
467 rgba
= color_to_rgba(color
);
469 vpath
= art_new (ArtVpath
, num_points
+2);
471 for (i
=0;i
<num_points
;i
++) {
472 dia_transform_coords_double(renderer
->transform
,
473 points
[i
].x
, points
[i
].y
,
475 vpath
[i
].code
= (i
==0)?ART_MOVETO
:ART_LINETO
;
479 dia_transform_coords_double(renderer
->transform
,
480 points
[0].x
, points
[0].y
,
482 vpath
[i
].code
= ART_LINETO
;
485 vpath
[i
+1].code
= ART_END
;
489 svp
= art_svp_from_vpath (vpath
);
493 art_rgb_svp_alpha (svp
,
495 renderer
->pixel_width
,
496 renderer
->pixel_height
,
498 renderer
->rgb_buffer
, renderer
->pixel_width
*3,
505 draw_rect(DiaRenderer
*self
,
506 Point
*ul_corner
, Point
*lr_corner
,
509 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
510 ArtVpath
*vpath
, *vpath_dashed
;
513 double top
, bottom
, left
, right
;
515 dia_transform_coords_double(renderer
->transform
,
516 ul_corner
->x
, ul_corner
->y
, &left
, &top
);
517 dia_transform_coords_double(renderer
->transform
,
518 lr_corner
->x
, lr_corner
->y
, &right
, &bottom
);
520 if ((left
>right
) || (top
>bottom
))
523 rgba
= color_to_rgba(color
);
525 vpath
= art_new (ArtVpath
, 6);
527 vpath
[0].code
= ART_MOVETO
;
530 vpath
[1].code
= ART_LINETO
;
533 vpath
[2].code
= ART_LINETO
;
536 vpath
[3].code
= ART_LINETO
;
539 vpath
[4].code
= ART_LINETO
;
542 vpath
[5].code
= ART_END
;
546 if (renderer
->dash_enabled
) {
547 vpath_dashed
= art_vpath_dash(vpath
, &renderer
->dash
);
549 vpath
= vpath_dashed
;
552 svp
= art_svp_vpath_stroke (vpath
,
553 renderer
->join_style
,
555 renderer
->line_width
,
561 art_rgb_svp_alpha (svp
,
563 renderer
->pixel_width
,
564 renderer
->pixel_height
,
566 renderer
->rgb_buffer
, renderer
->pixel_width
*3,
573 fill_rect(DiaRenderer
*self
,
574 Point
*ul_corner
, Point
*lr_corner
,
577 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
581 double top
, bottom
, left
, right
;
583 dia_transform_coords_double(renderer
->transform
,
584 ul_corner
->x
, ul_corner
->y
, &left
, &top
);
585 dia_transform_coords_double(renderer
->transform
,
586 lr_corner
->x
, lr_corner
->y
, &right
, &bottom
);
588 if ((left
>right
) || (top
>bottom
))
591 rgba
= color_to_rgba(color
);
593 vpath
= art_new (ArtVpath
, 6);
595 vpath
[0].code
= ART_MOVETO
;
598 vpath
[1].code
= ART_LINETO
;
601 vpath
[2].code
= ART_LINETO
;
604 vpath
[3].code
= ART_LINETO
;
607 vpath
[4].code
= ART_LINETO
;
610 vpath
[5].code
= ART_END
;
614 svp
= art_svp_from_vpath (vpath
);
618 art_rgb_svp_alpha (svp
,
620 renderer
->pixel_width
,
621 renderer
->pixel_height
,
623 renderer
->rgb_buffer
, renderer
->pixel_width
*3,
630 draw_arc(DiaRenderer
*self
,
632 real width
, real height
,
633 real angle1
, real angle2
,
636 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
637 ArtVpath
*vpath
, *vpath_dashed
;
644 double theta
, dtheta
;
647 width
= dia_transform_length(renderer
->transform
, width
);
648 height
= dia_transform_length(renderer
->transform
, height
);
649 dia_transform_coords_double(renderer
->transform
,
650 center
->x
, center
->y
, &x
, &y
);
652 if ((width
<0.0) || (height
<0.0))
655 dangle
= angle2
-angle1
;
659 /* Over-approximate the circumference */
665 circ
*= dangle
/360.0;
667 #define LEN_PER_SEGMENT 3.0
669 num_points
= circ
/LEN_PER_SEGMENT
;
670 if (num_points
<5) /* Don't be too coarse */
673 rgba
= color_to_rgba(line_color
);
675 vpath
= art_new (ArtVpath
, num_points
+1);
677 theta
= M_PI
*angle1
/180.0;
678 dtheta
= (M_PI
*dangle
/180.0)/(num_points
-1);
679 for (i
=0;i
<num_points
;i
++) {
680 vpath
[i
].code
= (i
==0)?ART_MOVETO
:ART_LINETO
;
681 vpath
[i
].x
= x
+ width
/2.0*cos(theta
);
682 vpath
[i
].y
= y
- height
/2.0*sin(theta
);
685 vpath
[i
].code
= ART_END
;
689 if (renderer
->dash_enabled
) {
690 vpath_dashed
= art_vpath_dash(vpath
, &renderer
->dash
);
692 vpath
= vpath_dashed
;
695 svp
= art_svp_vpath_stroke (vpath
,
696 renderer
->join_style
,
698 renderer
->line_width
,
704 art_rgb_svp_alpha (svp
,
706 renderer
->pixel_width
,
707 renderer
->pixel_height
,
709 renderer
->rgb_buffer
, renderer
->pixel_width
*3,
716 fill_arc(DiaRenderer
*self
,
718 real width
, real height
,
719 real angle1
, real angle2
,
722 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
730 double theta
, dtheta
;
733 width
= dia_transform_length(renderer
->transform
, width
);
734 height
= dia_transform_length(renderer
->transform
, height
);
735 dia_transform_coords_double(renderer
->transform
,
736 center
->x
, center
->y
, &x
, &y
);
738 if ((width
<0.0) || (height
<0.0))
741 dangle
= angle2
-angle1
;
745 /* Over-approximate the circumference */
751 circ
*= dangle
/360.0;
753 #define LEN_PER_SEGMENT 3.0
755 num_points
= circ
/LEN_PER_SEGMENT
;
756 if (num_points
<5) /* Don't be too coarse */
759 rgba
= color_to_rgba(color
);
761 vpath
= art_new (ArtVpath
, num_points
+2+1);
763 vpath
[0].code
= ART_MOVETO
;
766 theta
= M_PI
*angle1
/180.0;
767 dtheta
= (M_PI
*dangle
/180.0)/(num_points
-1);
768 for (i
=0;i
<num_points
;i
++) {
769 vpath
[i
+1].code
= ART_LINETO
;
770 vpath
[i
+1].x
= x
+ width
/2.0*cos(theta
);
771 vpath
[i
+1].y
= y
- height
/2.0*sin(theta
);
774 vpath
[i
+1].code
= ART_LINETO
;
777 vpath
[i
+2].code
= ART_END
;
781 svp
= art_svp_from_vpath (vpath
);
785 art_rgb_svp_alpha (svp
,
787 renderer
->pixel_width
,
788 renderer
->pixel_height
,
790 renderer
->rgb_buffer
, renderer
->pixel_width
*3,
797 draw_ellipse(DiaRenderer
*self
,
799 real width
, real height
,
802 draw_arc(self
, center
, width
, height
, 0.0, 360.0, color
);
806 fill_ellipse(DiaRenderer
*self
,
808 real width
, real height
,
811 fill_arc(self
, center
, width
, height
, 0.0, 360.0, color
);
815 draw_bezier(DiaRenderer
*self
,
820 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
821 ArtVpath
*vpath
, *vpath_dashed
;
828 rgba
= color_to_rgba(line_color
);
830 bpath
= art_new (ArtBpath
, numpoints
+1);
832 for (i
=0;i
<numpoints
;i
++) {
833 switch(points
[i
].type
) {
835 dia_transform_coords_double(renderer
->transform
,
836 points
[i
].p1
.x
, points
[i
].p1
.y
,
838 bpath
[i
].code
= ART_MOVETO
;
843 dia_transform_coords_double(renderer
->transform
,
844 points
[i
].p1
.x
, points
[i
].p1
.y
,
846 bpath
[i
].code
= ART_LINETO
;
851 bpath
[i
].code
= ART_CURVETO
;
852 dia_transform_coords_double(renderer
->transform
,
853 points
[i
].p1
.x
, points
[i
].p1
.y
,
857 dia_transform_coords_double(renderer
->transform
,
858 points
[i
].p2
.x
, points
[i
].p2
.y
,
862 dia_transform_coords_double(renderer
->transform
,
863 points
[i
].p3
.x
, points
[i
].p3
.y
,
870 bpath
[i
].code
= ART_END
;
874 vpath
= art_bez_path_to_vec(bpath
, 0.25);
877 if (renderer
->dash_enabled
) {
878 vpath_dashed
= art_vpath_dash(vpath
, &renderer
->dash
);
880 vpath
= vpath_dashed
;
883 svp
= art_svp_vpath_stroke (vpath
,
884 renderer
->join_style
,
886 renderer
->line_width
,
892 art_rgb_svp_alpha (svp
,
894 renderer
->pixel_width
,
895 renderer
->pixel_height
,
897 renderer
->rgb_buffer
, renderer
->pixel_width
*3,
904 fill_bezier(DiaRenderer
*self
,
905 BezPoint
*points
, /* Last point must be same as first point */
909 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
917 rgba
= color_to_rgba(color
);
919 bpath
= art_new (ArtBpath
, numpoints
+1);
921 for (i
=0;i
<numpoints
;i
++) {
922 switch(points
[i
].type
) {
924 dia_transform_coords_double(renderer
->transform
,
925 points
[i
].p1
.x
, points
[i
].p1
.y
,
927 bpath
[i
].code
= ART_MOVETO
;
932 dia_transform_coords_double(renderer
->transform
,
933 points
[i
].p1
.x
, points
[i
].p1
.y
,
935 bpath
[i
].code
= ART_LINETO
;
940 bpath
[i
].code
= ART_CURVETO
;
941 dia_transform_coords_double(renderer
->transform
,
942 points
[i
].p1
.x
, points
[i
].p1
.y
,
946 dia_transform_coords_double(renderer
->transform
,
947 points
[i
].p2
.x
, points
[i
].p2
.y
,
951 dia_transform_coords_double(renderer
->transform
,
952 points
[i
].p3
.x
, points
[i
].p3
.y
,
959 bpath
[i
].code
= ART_END
;
963 vpath
= art_bez_path_to_vec(bpath
, 0.25);
966 svp
= art_svp_from_vpath (vpath
);
970 art_rgb_svp_alpha (svp
,
972 renderer
->pixel_width
,
973 renderer
->pixel_height
,
975 renderer
->rgb_buffer
, renderer
->pixel_width
*3,
983 draw_string (DiaRenderer
*self
,
985 Point
*pos
, Alignment alignment
,
988 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
989 /* Not working with Pango */
990 guint8
*bitmap
= NULL
;
998 double affine
[6], tmpaffine
[6];
1005 point_copy(&start_pos
,pos
);
1007 /* Something's screwed up with the zooming for fonts.
1008 It's like it zooms double. Yet removing some of the zooms
1009 don't seem to work, either.
1012 old_zoom = ddisp->zoom_factor;
1013 ddisp->zoom_factor = ddisp->zoom_factor;
1015 switch (alignment
) {
1019 start_pos
.x
-= dia_font_scaled_string_width(
1020 text
, renderer
->font
,
1021 renderer
->font_height
,
1022 dia_transform_length(renderer
->transform
, 1.0))/2;
1025 start_pos
.x
-= dia_font_scaled_string_width(
1026 text
, renderer
->font
,
1027 renderer
->font_height
,
1028 dia_transform_length(renderer
->transform
, 1.0));
1032 font_height
= dia_transform_length(renderer
->transform
, renderer
->font_height
);
1034 start_pos
.y
-= dia_font_scaled_ascent(text
, renderer
->font
,
1035 renderer
->font_height
,
1036 dia_transform_length(renderer
->transform
, 1.0));
1037 dia_transform_coords_double(renderer
->transform
,
1038 start_pos
.x
, start_pos
.y
, &x
, &y
);
1040 layout
= dia_font_scaled_build_layout(
1041 text
, renderer
->font
, renderer
->font_height
,
1042 dia_transform_length(renderer
->transform
, 1.0));
1044 ddisp->zoom_factor = old_zoom;
1047 pango_layout_get_pixel_size(layout
, &width
, &height
);
1048 /* Pango doesn't have a 'render to raw bits' function, so we have
1049 * to render based on what other engines are available.
1052 #ifdef HAVE_FREETYPE
1053 /* Freetype version */
1060 rowstride
= 32*((width
+31)/31);
1062 font
= pango_context_load_font(pango_ft2_get_context(10, 10),
1063 renderer
->font
->pfd
);
1064 face
= pango_ft2_font_get_face(font
);
1066 graybitmap
= (guint8
*)g_new0(guint8
, height
*rowstride
);
1068 ftbitmap
.rows
= height
;
1069 ftbitmap
.width
= width
;
1070 ftbitmap
.pitch
= rowstride
;
1071 ftbitmap
.buffer
= graybitmap
;
1072 ftbitmap
.num_grays
= 256;
1073 ftbitmap
.pixel_mode
= ft_pixel_mode_grays
;
1074 ftbitmap
.palette_mode
= 0;
1075 ftbitmap
.palette
= 0;
1076 pango_ft2_render_layout(&ftbitmap
, layout
, 0, 0);
1077 bitmap
= (guint8
*)g_new0(guint8
, height
*rowstride
*DEPTH
);
1078 for (i
= 0; i
< height
; i
++) {
1079 for (j
= 0; j
< width
; j
++) {
1080 bitmap
[DEPTH
*(i
*rowstride
+j
)] = color
->red
;
1081 bitmap
[DEPTH
*(i
*rowstride
+j
)+1] = color
->green
;
1082 bitmap
[DEPTH
*(i
*rowstride
+j
)+2] = color
->blue
;
1083 bitmap
[DEPTH
*(i
*rowstride
+j
)+3] = graybitmap
[i
*rowstride
+j
];
1085 // bitmap[4*i+3] = graybitmap[i];
1089 #elif defined G_OS_WIN32 && defined PANGO_WIN32_FUTURE
1090 /* duplicating from above, please let extending Pango be allowed, bug 94791 */
1092 PangoBitmap graybitmap
;
1093 rowstride
= 32*((width
+31)/31);
1095 graybitmap
.rows
= height
;
1096 graybitmap
.width
= width
;
1097 graybitmap
.pitch
= rowstride
;
1098 graybitmap
.buffer
= (guint8
*)g_new0(guint8
, height
*rowstride
);
1099 graybitmap
.num_grays
= 256;
1100 g_print("Rendering %s onto bitmap of size %dx%d row %d\n", text
, width
, height
, rowstride
);
1101 pango_win32_render_layout_to_bitmap(&graybitmap
, layout
, 0, 0);
1102 bitmap
= (guint8
*)g_new0(guint8
, height
*rowstride
*DEPTH
);
1103 for (i
= 0; i
< height
; i
++) {
1104 for (j
= 0; j
< width
; j
++) {
1105 bitmap
[DEPTH
*(i
*rowstride
+j
)] = color
->red
;
1106 bitmap
[DEPTH
*(i
*rowstride
+j
)+1] = color
->green
;
1107 bitmap
[DEPTH
*(i
*rowstride
+j
)+2] = color
->blue
;
1108 bitmap
[DEPTH
*(i
*rowstride
+j
)+3] = graybitmap
.buffer
[i
*rowstride
+j
];
1111 g_free(graybitmap
.buffer
);
1115 static int warned_no_text
= 0;
1116 if (!warned_no_text
) {
1117 message_warning(_("This Dia version is compiled without libart/text support."));
1123 /* abuse_layout_object(layout,text); */
1125 g_object_unref(G_OBJECT(layout
));
1127 rgba
= color_to_rgba(color
);
1129 art_affine_identity(affine
);
1130 art_affine_translate(tmpaffine
, x
, y
);
1131 art_affine_multiply(affine
, affine
, tmpaffine
);
1134 art_rgb_rgba_affine (renderer
->rgb_buffer
,
1136 renderer
->pixel_width
,
1137 renderer
->pixel_height
,
1138 renderer
->pixel_width
* 3,
1145 ART_FILTER_NEAREST
, NULL
);
1152 draw_image(DiaRenderer
*self
,
1154 real width
, real height
,
1157 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (self
);
1158 double real_width
, real_height
;
1160 int src_width
, src_height
;
1167 /* Todo: Handle some kind of clipping! */
1169 real_width
= dia_transform_length(renderer
->transform
, width
);
1170 real_height
= dia_transform_length(renderer
->transform
, height
);
1171 dia_transform_coords_double(renderer
->transform
,
1172 point
->x
, point
->y
, &x
, &y
);
1174 src_width
= dia_image_width(image
);
1175 src_height
= dia_image_height(image
);
1176 rowstride
= dia_image_rowstride(image
);
1178 affine
[0] = real_width
/(double)src_width
;
1181 affine
[3] = real_height
/(double)src_height
;
1185 img_data
= dia_image_rgba_data(image
);
1187 if (img_data
!= NULL
) {
1188 /* If there is an alpha channel, we can use it directly. */
1189 art_rgb_rgba_affine(renderer
->rgb_buffer
,
1191 renderer
->pixel_width
,
1192 renderer
->pixel_height
,
1193 renderer
->pixel_width
*3,
1194 img_data
, src_width
, src_height
,
1196 affine
, ART_FILTER_NEAREST
, NULL
);
1197 /* Note that dia_image_rgba_data doesn't copy */
1199 img_data
= dia_image_rgb_data(image
);
1201 art_rgb_affine(renderer
->rgb_buffer
,
1203 renderer
->pixel_width
,
1204 renderer
->pixel_height
,
1205 renderer
->pixel_width
*3,
1206 img_data
, src_width
, src_height
,
1208 affine
, ART_FILTER_NEAREST
, NULL
);
1216 renderer_init (DiaLibartRenderer
*renderer
, gpointer g_class
)
1218 renderer
->rgb_buffer
= NULL
;
1220 renderer
->line_width
= 1.0;
1221 renderer
->cap_style
= GDK_CAP_BUTT
;
1222 renderer
->join_style
= GDK_JOIN_MITER
;
1224 renderer
->saved_line_style
= LINESTYLE_SOLID
;
1225 renderer
->dash_enabled
= 0;
1226 renderer
->dash_length
= 10;
1227 renderer
->dot_length
= 1;
1229 renderer
->font
= NULL
;
1232 static void dia_libart_renderer_class_init (DiaLibartRendererClass
*klass
);
1233 static gpointer parent_class
= NULL
;
1236 renderer_finalize (GObject
*object
)
1238 DiaLibartRenderer
*renderer
= DIA_LIBART_RENDERER (object
);
1240 if (renderer
->rgb_buffer
!= NULL
)
1241 g_free(renderer
->rgb_buffer
);
1244 dia_font_unref(renderer
->font
);
1246 G_OBJECT_CLASS (parent_class
)->finalize (object
);
1250 dia_libart_renderer_get_type (void)
1252 static GType object_type
= 0;
1256 static const GTypeInfo object_info
=
1258 sizeof (DiaLibartRendererClass
),
1259 (GBaseInitFunc
) NULL
,
1260 (GBaseFinalizeFunc
) NULL
,
1261 (GClassInitFunc
) dia_libart_renderer_class_init
,
1262 NULL
, /* class_finalize */
1263 NULL
, /* class_data */
1264 sizeof (DiaLibartRenderer
),
1265 0, /* n_preallocs */
1266 (GInstanceInitFunc
)renderer_init
/* init */
1269 object_type
= g_type_register_static (DIA_TYPE_RENDERER
,
1270 "DiaLibartRenderer",
1278 dia_libart_renderer_class_init (DiaLibartRendererClass
*klass
)
1280 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
1281 DiaRendererClass
*renderer_class
= DIA_RENDERER_CLASS (klass
);
1283 /* Here we set the functions that we define for this renderer. */
1284 renderer_class
->get_width_pixels
= get_width_pixels
;
1285 renderer_class
->get_height_pixels
= get_height_pixels
;
1287 renderer_class
->begin_render
= begin_render
;
1288 renderer_class
->end_render
= end_render
;
1290 renderer_class
->set_linewidth
= set_linewidth
;
1291 renderer_class
->set_linecaps
= set_linecaps
;
1292 renderer_class
->set_linejoin
= set_linejoin
;
1293 renderer_class
->set_linestyle
= set_linestyle
;
1294 renderer_class
->set_dashlength
= set_dashlength
;
1295 renderer_class
->set_fillstyle
= set_fillstyle
;
1296 renderer_class
->set_font
= set_font
;
1298 renderer_class
->draw_line
= draw_line
;
1299 renderer_class
->draw_polyline
= draw_polyline
;
1301 renderer_class
->draw_polygon
= draw_polygon
;
1302 renderer_class
->fill_polygon
= fill_polygon
;
1304 renderer_class
->draw_rect
= draw_rect
;
1305 renderer_class
->fill_rect
= fill_rect
;
1307 renderer_class
->draw_arc
= draw_arc
;
1308 renderer_class
->fill_arc
= fill_arc
;
1310 renderer_class
->draw_ellipse
= draw_ellipse
;
1311 renderer_class
->fill_ellipse
= fill_ellipse
;
1313 renderer_class
->draw_bezier
= draw_bezier
;
1314 renderer_class
->fill_bezier
= fill_bezier
;
1316 renderer_class
->draw_string
= draw_string
;
1318 renderer_class
->draw_image
= draw_image
;