1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * wmf.cpp -- Windows Metafile export plugin for dia
5 * Copyright (C) 2000, Hans Breuer, <Hans@Breuer.Org>
6 * based on dummy plug-in.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #include "diarenderer.h"
38 #include "dia_image.h"
44 #if defined HAVE_WINDOWS_H || defined G_OS_WIN32
46 // at least Rectangle conflicts ...
54 /* force linking with gdi32 */
55 #pragma comment( lib, "gdi32" )
60 typedef struct _PlaceableMetaHeader
62 guint32 Key
; /* Magic number (always 9AC6CDD7h) */
63 guint16 Handle
; /* Metafile HANDLE number (always 0) */
64 gint16 Left
; /* Left coordinate in metafile units */
65 gint16 Top
; /* Top coordinate in metafile units */
66 gint16 Right
; /* Right coordinate in metafile units */
67 gint16 Bottom
; /* Bottom coordinate in metafile units */
68 guint16 Inch
; /* Number of metafile units per inch */
69 guint32 Reserved
; /* Reserved (always 0) */
70 guint16 Checksum
; /* Checksum value for previous 10 WORDs */
71 } PLACEABLEMETAHEADER
;
73 /* --- the renderer --- */
76 #define WMF_TYPE_RENDERER (wmf_renderer_get_type ())
77 #define WMF_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WMF_TYPE_RENDERER, WmfRenderer))
78 #define WMF_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WMF_TYPE_RENDERER, WmfRendererClass))
79 #define WMF_IS_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WMF_TYPE_RENDERER))
80 #define WMF_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WMF_TYPE_RENDERER, WmfRendererClass))
82 GType
wmf_renderer_get_type (void) G_GNUC_CONST
;
84 typedef struct _WmfRenderer WmfRenderer
;
85 typedef struct _WmfRendererClass WmfRendererClass
;
89 DiaRenderer parent_instance
;
96 /* if applicable everything is scaled to 0.01 mm */
97 int nLineWidth
; /* need to cache these, because ... */
98 int fnPenStyle
; /* ... both are needed at the same time */
99 W32::HPEN hPen
; /* ugliness by concept, see DonePen() */
102 PLACEABLEMETAHEADER pmh
;
106 int nDashLen
; /* the scaled dash length */
107 gboolean platform_is_nt
; /* advanced line styles supported */
110 struct _WmfRendererClass
112 DiaRendererClass parent_class
;
120 #define W32COLOR(c) \
121 (W32::COLORREF)( 0xff * c->red + \
122 ((unsigned char)(0xff * c->green)) * 256 + \
123 ((unsigned char)(0xff * c->blue)) * 65536)
125 #define SC(a) ((int)((a)*renderer->scale))
126 #define SCX(a) ((int)(((a)+renderer->xoff)*renderer->scale))
127 #define SCY(a) ((int)(((a)+renderer->yoff)*renderer->scale))
133 UsePen(WmfRenderer
* renderer
, Color
* colour
)
137 W32::COLORREF rgb
= W32COLOR(colour
);
139 if (renderer
->platform_is_nt
&& renderer
->hPrintDC
) {
140 W32::LOGBRUSH logbrush
;
141 W32::DWORD dashes
[6];
143 int dashlen
= renderer
->nDashLen
;
144 int dotlen
= renderer
->nDashLen
/ 10;
146 logbrush
.lbStyle
= BS_SOLID
;
147 logbrush
.lbColor
= rgb
;
148 logbrush
.lbHatch
= 0;
150 switch (renderer
->fnPenStyle
& PS_STYLE_MASK
) {
158 dashes
[0] = dashes
[1] = dashlen
;
162 dashes
[1] = dashes
[3] = MAX((dashlen
- dotlen
) / 2, 1);
169 dashes
[1] = dashes
[3] = dashes
[5] = MAX((dashlen
- 2 * dotlen
)/3, 1);
170 dashes
[2] = dashes
[4] = dotlen
;
174 dashes
[0] = dashes
[1] = dotlen
;
177 g_assert_not_reached ();
180 renderer
->hPen
= W32::ExtCreatePen (
181 renderer
->fnPenStyle
& PS_SOLID
? renderer
->fnPenStyle
:
182 (renderer
->fnPenStyle
& ~(PS_STYLE_MASK
)) | (PS_GEOMETRIC
| PS_USERSTYLE
),
183 renderer
->nLineWidth
,
184 &logbrush
, num_dashes
, dashes
);
188 #endif /* G_OS_WIN32 */
190 renderer
->hPen
= W32::CreatePen(renderer
->fnPenStyle
,
191 renderer
->nLineWidth
,
195 renderer
->hPen
= (W32::HPEN
)W32::GetStockObject(NULL_PEN
);
197 hOldPen
= (W32::HPEN
)W32::SelectObject(renderer
->hFileDC
, renderer
->hPen
);
202 DonePen(WmfRenderer
* renderer
, W32::HPEN hPen
)
204 /* restore the OLD one ... */
206 W32::SelectObject(renderer
->hFileDC
, hPen
);
207 /* ... before deleting the last active */
210 W32::DeleteObject(renderer
->hPen
);
211 renderer
->hPen
= NULL
;
215 #define DIAG_NOTE /* my_log */
217 my_log(WmfRenderer
* renderer
, char* format
, ...)
222 g_return_if_fail (format
!= NULL
);
224 va_start (args
, format
);
225 string
= g_strdup_vprintf (format
, args
);
228 //fprintf(renderer->file, string);
235 * renderer interface implementation
238 begin_render(DiaRenderer
*self
)
240 WmfRenderer
*renderer
= WMF_RENDERER (self
);
242 DIAG_NOTE(renderer
, "begin_render\n");
244 /* FIXME: still not sure if the renderer output should be platform dependent */
245 if (renderer
->platform_is_nt
)
246 renderer
->fnPenStyle
= PS_GEOMETRIC
;
248 /* make unfilled the default */
249 W32::SelectObject(renderer
->hFileDC
,
250 W32::GetStockObject (HOLLOW_BRUSH
) );
254 end_render(DiaRenderer
*self
)
256 WmfRenderer
*renderer
= WMF_RENDERER (self
);
257 W32::HENHMETAFILE hEmf
;
259 W32::BYTE
* pData
= NULL
;
262 DIAG_NOTE(renderer
, "end_render\n");
263 hEmf
= W32::CloseEnhMetaFile(renderer
->hFileDC
);
266 /* Don't do it when printing */
267 if (renderer
->sFileName
&& strlen (renderer
->sFileName
)) {
269 W32::HDC hdc
= W32::GetDC(NULL
);
271 f
= fopen(renderer
->sFileName
, "wb");
273 /* write the placeable header */
274 fwrite(&renderer
->pmh
, 1, 22 /* NOT: sizeof(PLACEABLEMETAHEADER) */, f
);
277 nSize
= W32::GetWinMetaFileBits(hEmf
, 0, NULL
, MM_ANISOTROPIC
, hdc
);
278 pData
= g_new(W32::BYTE
, nSize
);
280 nSize
= W32::GetWinMetaFileBits(hEmf
, nSize
, pData
, MM_ANISOTROPIC
, hdc
);
283 fwrite(pData
,1,nSize
,f
);
290 W32::RECT r
= {0, 0, 0, 0};
291 r
.right
= W32::GetDeviceCaps (renderer
->hPrintDC
, PHYSICALWIDTH
);
292 r
.bottom
= W32::GetDeviceCaps (renderer
->hPrintDC
, PHYSICALHEIGHT
);
294 W32::PlayEnhMetaFile (renderer
->hPrintDC
, hEmf
, &r
);
297 g_free(renderer
->sFileName
);
300 W32::DeleteEnhMetaFile(hEmf
);
302 W32::DeleteObject(renderer
->hFont
);
306 set_linewidth(DiaRenderer
*self
, real linewidth
)
308 WmfRenderer
*renderer
= WMF_RENDERER (self
);
310 DIAG_NOTE(renderer
, "set_linewidth %f\n", linewidth
);
312 renderer
->nLineWidth
= SC(linewidth
);
316 set_linecaps(DiaRenderer
*self
, LineCaps mode
)
318 WmfRenderer
*renderer
= WMF_RENDERER (self
);
320 DIAG_NOTE(renderer
, "set_linecaps %d\n", mode
);
322 // all the advanced line rendering is unsupported on win9x
323 if (!renderer
->platform_is_nt
)
326 renderer
->fnPenStyle
&= ~(PS_ENDCAP_MASK
);
329 renderer
->fnPenStyle
|= PS_ENDCAP_FLAT
;
332 renderer
->fnPenStyle
|= PS_ENDCAP_ROUND
;
334 case LINECAPS_PROJECTING
:
335 renderer
->fnPenStyle
|= PS_ENDCAP_SQUARE
;
338 message_error("WmfRenderer : Unsupported fill mode specified!\n");
343 set_linejoin(DiaRenderer
*self
, LineJoin mode
)
345 WmfRenderer
*renderer
= WMF_RENDERER (self
);
347 DIAG_NOTE(renderer
, "set_join %d\n", mode
);
349 if (!renderer
->platform_is_nt
)
352 renderer
->fnPenStyle
&= ~(PS_JOIN_MASK
);
355 renderer
->fnPenStyle
|= PS_JOIN_MITER
;
358 renderer
->fnPenStyle
|= PS_JOIN_ROUND
;
361 renderer
->fnPenStyle
|= PS_JOIN_BEVEL
;
364 message_error("WmfRenderer : Unsupported fill mode specified!\n");
369 set_linestyle(DiaRenderer
*self
, LineStyle mode
)
371 WmfRenderer
*renderer
= WMF_RENDERER (self
);
373 DIAG_NOTE(renderer
, "set_linestyle %d\n", mode
);
376 renderer
->fnPenStyle
&= ~(PS_STYLE_MASK
);
378 case LINESTYLE_SOLID
:
379 renderer
->fnPenStyle
|= PS_SOLID
;
381 case LINESTYLE_DASHED
:
382 renderer
->fnPenStyle
|= PS_DASH
;
384 case LINESTYLE_DASH_DOT
:
385 renderer
->fnPenStyle
|= PS_DASHDOT
;
387 case LINESTYLE_DASH_DOT_DOT
:
388 renderer
->fnPenStyle
|= PS_DASHDOTDOT
;
390 case LINESTYLE_DOTTED
:
391 renderer
->fnPenStyle
|= PS_DOT
;
394 message_error("WmfRenderer : Unsupported fill mode specified!\n");
397 if (renderer
->platform_is_nt
)
400 /* Non-solid linestyles are only displayed if width <= 1.
401 * Better implementation will require custom linestyles
402 * not available on win9x ...
405 case LINESTYLE_DASHED
:
406 case LINESTYLE_DASH_DOT
:
407 case LINESTYLE_DASH_DOT_DOT
:
408 case LINESTYLE_DOTTED
:
409 renderer
->nLineWidth
= MIN(renderer
->nLineWidth
, 1);
415 set_dashlength(DiaRenderer
*self
, real length
)
417 WmfRenderer
*renderer
= WMF_RENDERER (self
);
419 DIAG_NOTE(renderer
, "set_dashlength %f\n", length
);
421 /* dot = 10% of len */
422 renderer
->nDashLen
= SC(length
);
426 set_fillstyle(DiaRenderer
*self
, FillStyle mode
)
428 WmfRenderer
*renderer
= WMF_RENDERER (self
);
430 DIAG_NOTE(renderer
, "set_fillstyle %d\n", mode
);
433 case FILLSTYLE_SOLID
:
436 message_error("WmfRenderer : Unsupported fill mode specified!\n");
441 set_font(DiaRenderer
*self
, DiaFont
*font
, real height
)
443 WmfRenderer
*renderer
= WMF_RENDERER (self
);
446 W32::DWORD dwItalic
= 0;
447 W32::DWORD dwWeight
= FW_DONTCARE
;
450 DIAG_NOTE(renderer
, "set_font %s %f\n",
451 dia_font_get_family (font
), height
);
453 W32::DeleteObject(renderer
->hFont
);
455 sFace
= dia_font_get_family (font
);
456 style
= dia_font_get_style(font
);
457 dwItalic
= DIA_FONT_STYLE_GET_SLANT(style
) != DIA_FONT_NORMAL
;
459 /* although there is a known algorithm avoid it for cleanness */
460 switch (DIA_FONT_STYLE_GET_WEIGHT(style
)) {
461 case DIA_FONT_ULTRALIGHT
: dwWeight
= FW_ULTRALIGHT
; break;
462 case DIA_FONT_LIGHT
: dwWeight
= FW_LIGHT
; break;
463 case DIA_FONT_MEDIUM
: dwWeight
= FW_MEDIUM
; break;
464 case DIA_FONT_DEMIBOLD
: dwWeight
= FW_DEMIBOLD
; break;
465 case DIA_FONT_BOLD
: dwWeight
= FW_BOLD
; break;
466 case DIA_FONT_ULTRABOLD
: dwWeight
= FW_ULTRABOLD
; break;
467 case DIA_FONT_HEAVY
: dwWeight
= FW_HEAVY
; break;
468 default : dwWeight
= FW_NORMAL
; break;
471 renderer
->hFont
= (W32::HFONT
)W32::CreateFont(
472 - SC (height
), // logical height of font
473 0, // logical average character width
474 0, // angle of escapement
475 0, // base-line orientation angle
476 dwWeight
, // font weight
477 dwItalic
, // italic attribute flag
478 0, // underline attribute flag
479 0, // strikeout attribute flag
480 DEFAULT_CHARSET
, // character set identifier
481 OUT_TT_PRECIS
, // output precision
482 CLIP_DEFAULT_PRECIS
, // clipping precision
483 PROOF_QUALITY
, // output quality
484 DEFAULT_PITCH
, // pitch and family
485 sFace
); // pointer to typeface name string
489 draw_line(DiaRenderer
*self
,
490 Point
*start
, Point
*end
,
493 WmfRenderer
*renderer
= WMF_RENDERER (self
);
497 DIAG_NOTE(renderer
, "draw_line %f,%f -> %f, %f\n",
498 start
->x
, start
->y
, end
->x
, end
->y
);
500 hPen
= UsePen(renderer
, line_colour
);
502 W32::MoveToEx(renderer
->hFileDC
, SCX(start
->x
), SCY(start
->y
), NULL
);
503 W32::LineTo(renderer
->hFileDC
, SCX(end
->x
), SCY(end
->y
));
505 DonePen(renderer
, hPen
);
509 draw_polyline(DiaRenderer
*self
,
510 Point
*points
, int num_points
,
513 WmfRenderer
*renderer
= WMF_RENDERER (self
);
519 DIAG_NOTE(renderer
, "draw_polyline n:%d %f,%f ...\n",
520 num_points
, points
->x
, points
->y
);
524 pts
= g_new (W32::POINT
, num_points
+1);
525 for (i
= 0; i
< num_points
; i
++)
527 pts
[i
].x
= SCX(points
[i
].x
);
528 pts
[i
].y
= SCY(points
[i
].y
);
531 hPen
= UsePen(renderer
, line_colour
);
532 W32::Polyline(renderer
->hFileDC
, pts
, num_points
);
533 DonePen(renderer
, hPen
);
539 draw_polygon(DiaRenderer
*self
,
540 Point
*points
, int num_points
,
543 WmfRenderer
*renderer
= WMF_RENDERER (self
);
549 DIAG_NOTE(renderer
, "draw_polygon n:%d %f,%f ...\n",
550 num_points
, points
->x
, points
->y
);
554 pts
= g_new (W32::POINT
, num_points
+1);
555 for (i
= 0; i
< num_points
; i
++)
557 pts
[i
].x
= SCX(points
[i
].x
);
558 pts
[i
].y
= SCY(points
[i
].y
);
561 hPen
= UsePen(renderer
, line_colour
);
563 W32::Polygon(renderer
->hFileDC
, pts
, num_points
);
565 DonePen(renderer
, hPen
);
571 fill_polygon(DiaRenderer
*self
,
572 Point
*points
, int num_points
,
575 WmfRenderer
*renderer
= WMF_RENDERER (self
);
577 W32::HBRUSH hBrush
, hBrOld
;
578 W32::COLORREF rgb
= W32COLOR(colour
);
580 DIAG_NOTE(renderer
, "fill_polygon n:%d %f,%f ...\n",
581 num_points
, points
->x
, points
->y
);
583 hBrush
= W32::CreateSolidBrush(rgb
);
584 hBrOld
= (W32::HBRUSH
)W32::SelectObject(renderer
->hFileDC
, hBrush
);
586 draw_polygon(self
, points
, num_points
, NULL
);
588 W32::SelectObject(renderer
->hFileDC
,
589 W32::GetStockObject(HOLLOW_BRUSH
) );
590 W32::DeleteObject(hBrush
);
594 draw_rect(DiaRenderer
*self
,
595 Point
*ul_corner
, Point
*lr_corner
,
598 WmfRenderer
*renderer
= WMF_RENDERER (self
);
602 DIAG_NOTE(renderer
, "draw_rect %f,%f -> %f,%f\n",
603 ul_corner
->x
, ul_corner
->y
, lr_corner
->x
, lr_corner
->y
);
605 hPen
= UsePen(renderer
, colour
);
607 W32::Rectangle(renderer
->hFileDC
,
608 SCX(ul_corner
->x
), SCY(ul_corner
->y
),
609 SCX(lr_corner
->x
), SCY(lr_corner
->y
));
611 DonePen(renderer
, hPen
);
615 fill_rect(DiaRenderer
*self
,
616 Point
*ul_corner
, Point
*lr_corner
,
619 WmfRenderer
*renderer
= WMF_RENDERER (self
);
620 W32::HGDIOBJ hBrush
, hBrOld
;
621 W32::COLORREF rgb
= W32COLOR(colour
);
623 DIAG_NOTE(renderer
, "fill_rect %f,%f -> %f,%f\n",
624 ul_corner
->x
, ul_corner
->y
, lr_corner
->x
, lr_corner
->y
);
626 hBrush
= W32::CreateSolidBrush(rgb
);
627 hBrOld
= W32::SelectObject(renderer
->hFileDC
, hBrush
);
629 draw_rect(self
, ul_corner
, lr_corner
, NULL
);
631 W32::SelectObject(renderer
->hFileDC
,
632 W32::GetStockObject (HOLLOW_BRUSH
) );
633 W32::DeleteObject(hBrush
);
637 draw_arc(DiaRenderer
*self
,
639 real width
, real height
,
640 real angle1
, real angle2
,
643 WmfRenderer
*renderer
= WMF_RENDERER (self
);
645 W32::POINT ptStart
, ptEnd
;
647 DIAG_NOTE(renderer
, "draw_arc %fx%f <%f,<%f @%f,%f\n",
648 width
, height
, angle1
, angle2
, center
->x
, center
->y
);
650 hPen
= UsePen(renderer
, colour
);
652 /* calculate start and end points of arc */
653 ptStart
.x
= SCX(center
->x
+ (width
/ 2.0) * cos((M_PI
/ 180.0) * angle1
));
654 ptStart
.y
= SCY(center
->y
- (height
/ 2.0) * sin((M_PI
/ 180.0) * angle1
));
655 ptEnd
.x
= SCX(center
->x
+ (width
/ 2.0) * cos((M_PI
/ 180.0) * angle2
));
656 ptEnd
.y
= SCY(center
->y
- (height
/ 2.0) * sin((M_PI
/ 180.0) * angle2
));
658 W32::MoveToEx(renderer
->hFileDC
, ptStart
.x
, ptStart
.y
, NULL
);
659 W32::Arc(renderer
->hFileDC
,
660 SCX(center
->x
- width
/ 2), /* bbox corners */
661 SCY(center
->y
- height
/ 2),
662 SCX(center
->x
+ width
/ 2),
663 SCY(center
->y
+ height
/ 2),
664 ptStart
.x
, ptStart
.y
, ptEnd
.x
, ptEnd
.y
);
666 DonePen(renderer
, hPen
);
670 fill_arc(DiaRenderer
*self
,
672 real width
, real height
,
673 real angle1
, real angle2
,
676 WmfRenderer
*renderer
= WMF_RENDERER (self
);
678 W32::HGDIOBJ hBrush
, hBrOld
;
679 W32::POINT ptStart
, ptEnd
;
680 W32::COLORREF rgb
= W32COLOR(colour
);
682 DIAG_NOTE(renderer
, "fill_arc %fx%f <%f,<%f @%f,%f\n",
683 width
, height
, angle1
, angle2
, center
->x
, center
->y
);
685 /* calculate start and end points of arc */
686 ptStart
.x
= SCX(center
->x
+ (width
/ 2.0) * cos((M_PI
/ 180.0) * angle1
));
687 ptStart
.y
= SCY(center
->y
- (height
/ 2.0) * sin((M_PI
/ 180.0) * angle1
));
688 ptEnd
.x
= SCX(center
->x
+ (width
/ 2.0) * cos((M_PI
/ 180.0) * angle2
));
689 ptEnd
.y
= SCY(center
->y
- (height
/ 2.0) * sin((M_PI
/ 180.0) * angle2
));
691 hPen
= UsePen(renderer
, NULL
); /* no border */
692 hBrush
= W32::CreateSolidBrush(rgb
);
693 hBrOld
= W32::SelectObject(renderer
->hFileDC
, hBrush
);
695 W32::Pie(renderer
->hFileDC
,
696 SCX(center
->x
- width
/ 2), /* bbox corners */
697 SCY(center
->y
- height
/ 2),
698 SCX(center
->x
+ width
/ 2),
699 SCY(center
->y
+ height
/ 2),
700 ptStart
.x
, ptStart
.y
, ptEnd
.x
, ptEnd
.y
);
702 W32::SelectObject(renderer
->hFileDC
,
703 W32::GetStockObject (HOLLOW_BRUSH
) );
704 W32::DeleteObject(hBrush
);
705 DonePen(renderer
, hPen
);
709 draw_ellipse(DiaRenderer
*self
,
711 real width
, real height
,
714 WmfRenderer
*renderer
= WMF_RENDERER (self
);
717 DIAG_NOTE(renderer
, "draw_ellipse %fx%f @ %f,%f\n",
718 width
, height
, center
->x
, center
->y
);
720 hPen
= UsePen(renderer
, colour
);
722 W32::Ellipse(renderer
->hFileDC
,
723 SCX(center
->x
- width
/ 2), /* bbox corners */
724 SCY(center
->y
- height
/ 2),
725 SCX(center
->x
+ width
/ 2),
726 SCY(center
->y
+ height
/ 2));
728 DonePen(renderer
, hPen
);
732 fill_ellipse(DiaRenderer
*self
,
734 real width
, real height
,
737 WmfRenderer
*renderer
= WMF_RENDERER (self
);
739 W32::HGDIOBJ hBrush
, hBrOld
;
740 W32::COLORREF rgb
= W32COLOR(colour
);
742 DIAG_NOTE(renderer
, "fill_ellipse %fx%f @ %f,%f\n",
743 width
, height
, center
->x
, center
->y
);
745 hBrush
= W32::CreateSolidBrush(rgb
);
746 hBrOld
= W32::SelectObject(renderer
->hFileDC
, hBrush
);
748 draw_ellipse(self
, center
, width
, height
, NULL
);
750 W32::SelectObject(renderer
->hFileDC
,
751 W32::GetStockObject (HOLLOW_BRUSH
) );
752 W32::DeleteObject(hBrush
);
756 draw_bezier(DiaRenderer
*self
,
761 WmfRenderer
*renderer
= WMF_RENDERER (self
);
766 DIAG_NOTE(renderer
, "draw_bezier n:%d %fx%f ...\n",
767 numpoints
, points
->p1
.x
, points
->p1
.y
);
769 pts
= g_new(W32::POINT
, (numpoints
-1) * 3 + 1);
771 pts
[0].x
= SCX(points
[0].p1
.x
);
772 pts
[0].y
= SCY(points
[0].p1
.y
);
774 for (i
= 1; i
< numpoints
; i
++)
776 switch(points
[i
].type
)
778 case _BezPoint::BEZ_MOVE_TO
:
779 g_warning("only first BezPoint can be a BEZ_MOVE_TO");
781 case _BezPoint::BEZ_LINE_TO
:
782 /* everyhing the same ?*/
783 pts
[i
*3-2].x
= pts
[i
*3-1].x
=
784 pts
[i
*3 ].x
= SCX(points
[i
].p1
.x
);
785 pts
[i
*3-2].y
= pts
[i
*3-1].y
=
786 pts
[i
*3 ].y
= SCY(points
[i
].p1
.y
);
788 case _BezPoint::BEZ_CURVE_TO
:
790 pts
[i
*3-2].x
= SCX(points
[i
].p1
.x
);
791 pts
[i
*3-2].y
= SCY(points
[i
].p1
.y
);
792 pts
[i
*3-1].x
= SCX(points
[i
].p2
.x
);
793 pts
[i
*3-1].y
= SCY(points
[i
].p2
.y
);
795 pts
[i
*3 ].x
= SCX(points
[i
].p3
.x
);
796 pts
[i
*3 ].y
= SCY(points
[i
].p3
.y
);
803 hPen
= UsePen(renderer
, colour
);
805 W32::PolyBezier(renderer
->hFileDC
,
806 pts
, (numpoints
-1)*3+1);
808 DonePen(renderer
, hPen
);
814 /* not defined in compatibility layer */
816 fill_bezier(DiaRenderer
*self
,
817 BezPoint
*points
, /* Last point must be same as first point */
821 WmfRenderer
*renderer
= WMF_RENDERER (self
);
822 W32::HGDIOBJ hBrush
, hBrOld
;
823 W32::COLORREF rgb
= W32COLOR(colour
);
825 DIAG_NOTE(renderer
, "fill_bezier n:%d %fx%f ...\n",
826 numpoints
, points
->p1
.x
, points
->p1
.y
);
828 hBrush
= W32::CreateSolidBrush(rgb
);
829 hBrOld
= W32::SelectObject(renderer
->hFileDC
, hBrush
);
831 W32::BeginPath (renderer
->hFileDC
);
832 draw_bezier(self
, points
, numpoints
, NULL
);
833 W32::EndPath (renderer
->hFileDC
);
834 W32::FillPath (renderer
->hFileDC
);
836 W32::SelectObject(renderer
->hFileDC
,
837 W32::GetStockObject (HOLLOW_BRUSH
) );
838 W32::DeleteObject(hBrush
);
843 draw_string(DiaRenderer
*self
,
845 Point
*pos
, Alignment alignment
,
848 WmfRenderer
*renderer
= WMF_RENDERER (self
);
851 W32::COLORREF rgb
= W32COLOR(colour
);
853 DIAG_NOTE(renderer
, "draw_string %f,%f %s\n",
854 pos
->x
, pos
->y
, text
);
856 W32::SetTextColor(renderer
->hFileDC
, rgb
);
860 W32::SetTextAlign(renderer
->hFileDC
, TA_LEFT
+TA_BASELINE
);
863 W32::SetTextAlign(renderer
->hFileDC
, TA_CENTER
+TA_BASELINE
);
866 W32::SetTextAlign(renderer
->hFileDC
, TA_RIGHT
+TA_BASELINE
);
869 /* work out size of first chunk of text */
872 hOld
= W32::SelectObject(renderer
->hFileDC
, renderer
->hFont
);
874 # if 0 // one way to go, but see below ...
876 gunichar2
* swc
= g_utf8_to_utf16 (text
, -1, NULL
, &wclen
, NULL
);
877 W32::TextOutW (renderer
->hFileDC
,
878 SCX(pos
->x
), SCY(pos
->y
),
882 // works with newest cvs and tml's "official" 2000-12-26 release
884 /* convert from utf8 to active codepage */
885 static char codepage
[10];
886 sprintf (codepage
, "CP%d", W32::GetACP ());
888 scp
= g_convert (text
, strlen (text
),
893 W32::TextOut(renderer
->hFileDC
,
894 SCX(pos
->x
), SCY(pos
->y
),
898 else // converson failed, write unconverted
899 W32::TextOut(renderer
->hFileDC
,
900 SCX(pos
->x
), SCY(pos
->y
),
901 text
, strlen (text
));
905 W32::SelectObject(renderer
->hFileDC
, hOld
);
909 draw_image(DiaRenderer
*self
,
911 real width
, real height
,
914 WmfRenderer
*renderer
= WMF_RENDERER (self
);
916 /* not yet supported in compatibility mode */
920 unsigned char* pData
= NULL
;
921 unsigned char* pImg
= NULL
;
923 DIAG_NOTE(renderer
, "draw_image %fx%f @%f,%f\n",
924 width
, height
, point
->x
, point
->y
);
926 iWidth
= dia_image_width(image
);
927 iHeight
= dia_image_height(image
);
928 pImg
= dia_image_rgb_data(image
);
930 #if 0 /* only working with 24 bit screen resolution */
931 if ((dia_image_width(image
)*3) % 4)
933 /* transform data to be DWORD aligned */
935 const unsigned char* pIn
= NULL
;
936 unsigned char* pOut
= NULL
;
938 pOut
= pData
= g_new(unsigned char, ((((iWidth
*3-1)/4)+1)*4)*iHeight
);
941 for (y
= 0; y
< iHeight
; y
++)
943 for (x
= 0; x
< iWidth
; x
++)
949 pOut
+= (4 - (iWidth
*3)%4);
952 hBmp
= W32::CreateBitmap ( iWidth
, iHeight
, 1, 24, pData
);
956 hBmp
= W32::CreateBitmap (
957 dia_image_width(image
), dia_image_height(image
),
960 W32::HDC hMemDC
= W32::CreateCompatibleDC (renderer
->hFileDC
);
962 W32::HDC hMemDC
= W32::CreateCompatibleDC (renderer
->hFileDC
);
964 memset (&bmi
, 0, sizeof (W32::BITMAPINFO
));
965 bmi
.bmiHeader
.biSize
= sizeof (W32::BITMAPINFOHEADER
);
966 bmi
.bmiHeader
.biWidth
= iWidth
;
967 bmi
.bmiHeader
.biHeight
= -iHeight
; // invert it
968 bmi
.bmiHeader
.biPlanes
= 1;
969 bmi
.bmiHeader
.biBitCount
= 24;
970 bmi
.bmiHeader
.biCompression
= BI_RGB
;
971 bmi
.bmiHeader
.biSizeImage
= 0;
972 bmi
.bmiHeader
.biXPelsPerMeter
= 0;
973 bmi
.bmiHeader
.biYPelsPerMeter
= 0;
974 bmi
.bmiHeader
.biClrUsed
= 0;
975 bmi
.bmiHeader
.biClrImportant
= 0;
977 hBmp
= W32::CreateDIBSection (hMemDC
, &bmi
, DIB_RGB_COLORS
,
978 (void**)&pData
, NULL
, 0);
979 /* copy data, always line by line */
980 for (int y
= 0; y
< iHeight
; y
++)
982 int line_offset
= dia_image_rowstride(image
) * y
;
983 for (int x
= 0; x
< iWidth
*3; x
+=3)
985 // change from RGB to BGR order
986 pData
[x
] = pImg
[line_offset
+ x
+2];
987 pData
[x
+1] = pImg
[line_offset
+ x
+1];
988 pData
[x
+2] = pImg
[line_offset
+ x
];
990 pData
+= (((3*iWidth
-1)/4)+1)*4;
992 pData
= NULL
; // don't free it below
994 W32::HBITMAP hOldBmp
= (W32::HBITMAP
)W32::SelectObject(hMemDC
, hBmp
);
995 //Hack to get SRCCOPY out of namespace W32
997 # define DWORD unsigned long
999 W32::StretchBlt(renderer
->hFileDC
, // destination
1000 SCX(point
->x
), SCY(point
->y
), SC(width
), SC(height
),
1002 0, 0, iWidth
, iHeight
, SRCCOPY
);
1004 W32::SelectObject (hMemDC
, hOldBmp
);
1005 W32::DeleteDC (hMemDC
);
1006 W32::DeleteObject (hBmp
);
1011 #endif /* SAVE_EMF */
1014 //XXX: use RoundRect
1016 /* GObject boiler plate */
1017 static void wmf_renderer_class_init (WmfRendererClass
*klass
);
1019 static gpointer parent_class
= NULL
;
1022 wmf_renderer_get_type (void)
1024 static GType object_type
= 0;
1028 static const GTypeInfo object_info
=
1030 sizeof (WmfRendererClass
),
1031 (GBaseInitFunc
) NULL
,
1032 (GBaseFinalizeFunc
) NULL
,
1033 (GClassInitFunc
) wmf_renderer_class_init
,
1034 NULL
, /* class_finalize */
1035 NULL
, /* class_data */
1036 sizeof (WmfRenderer
),
1037 0, /* n_preallocs */
1041 object_type
= g_type_register_static (DIA_TYPE_RENDERER
,
1043 &object_info
, (GTypeFlags
)0);
1050 wmf_renderer_finalize (GObject
*object
)
1052 WmfRenderer
*wmf_renderer
= WMF_RENDERER (object
);
1054 G_OBJECT_CLASS (parent_class
)->finalize (object
);
1058 wmf_renderer_class_init (WmfRendererClass
*klass
)
1060 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
1061 DiaRendererClass
*renderer_class
= DIA_RENDERER_CLASS (klass
);
1063 parent_class
= g_type_class_peek_parent (klass
);
1065 object_class
->finalize
= wmf_renderer_finalize
;
1067 /* renderer members */
1068 renderer_class
->begin_render
= begin_render
;
1069 renderer_class
->end_render
= end_render
;
1071 renderer_class
->set_linewidth
= set_linewidth
;
1072 renderer_class
->set_linecaps
= set_linecaps
;
1073 renderer_class
->set_linejoin
= set_linejoin
;
1074 renderer_class
->set_linestyle
= set_linestyle
;
1075 renderer_class
->set_dashlength
= set_dashlength
;
1076 renderer_class
->set_fillstyle
= set_fillstyle
;
1078 renderer_class
->set_font
= set_font
;
1080 renderer_class
->draw_line
= draw_line
;
1081 renderer_class
->fill_polygon
= fill_polygon
;
1082 renderer_class
->draw_rect
= draw_rect
;
1083 renderer_class
->fill_rect
= fill_rect
;
1084 renderer_class
->draw_arc
= draw_arc
;
1085 renderer_class
->fill_arc
= fill_arc
;
1086 renderer_class
->draw_ellipse
= draw_ellipse
;
1087 renderer_class
->fill_ellipse
= fill_ellipse
;
1089 renderer_class
->draw_string
= draw_string
;
1090 renderer_class
->draw_image
= draw_image
;
1092 /* medium level functions */
1093 renderer_class
->draw_rect
= draw_rect
;
1094 renderer_class
->draw_polyline
= draw_polyline
;
1095 renderer_class
->draw_polygon
= draw_polygon
;
1097 renderer_class
->draw_bezier
= draw_bezier
;
1099 renderer_class
->fill_bezier
= fill_bezier
;
1103 /* plug-in export api */
1105 export_data(DiagramData
*data
, const gchar
*filename
,
1106 const gchar
*diafilename
, void* user_data
)
1108 WmfRenderer
*renderer
;
1116 /* Bounding Box in .01-millimeter units ??? */
1119 if ( (data
->extents
.right
- data
->extents
.left
)
1120 > (data
->extents
.bottom
- data
->extents
.top
)) {
1121 scale
= floor (32000.0 / (data
->extents
.right
- data
->extents
.left
));
1124 scale
= floor (32000.0 / (data
->extents
.bottom
- data
->extents
.top
));
1126 bbox
.right
= (int)((data
->extents
.right
- data
->extents
.left
) * scale
);
1127 bbox
.bottom
= (int)((data
->extents
.bottom
- data
->extents
.top
) * scale
);
1129 file
= (W32::HDC
)W32::CreateEnhMetaFile(
1130 W32::GetDC(NULL
), // handle to a reference device context
1132 filename
, // pointer to a filename string
1136 &bbox
, // pointer to a bounding rectangle
1137 "Dia\0Diagram\0"); // pointer to an optional description string
1140 message_error(_("Couldn't open: '%s' for writing.\n"), filename
);
1144 renderer
= (WmfRenderer
*)g_object_new(WMF_TYPE_RENDERER
, NULL
);
1146 renderer
->hFileDC
= file
;
1147 renderer
->sFileName
= g_strdup(filename
);
1148 renderer
->hPrintDC
= (W32::HDC
)user_data
;
1150 /* printing is platform dependent */
1151 renderer
->platform_is_nt
= (W32::GetVersion () < 0x80000000);
1153 extent
= &data
->extents
;
1155 /* calculate offsets */
1156 renderer
->xoff
= - data
->extents
.left
;
1157 renderer
->yoff
= - data
->extents
.top
;
1158 renderer
->scale
= scale
/ 25.4; /* don't know why this is required ... */
1160 /* initialize placeable header */
1161 /* bounding box in twips 1/1440 of an inch */
1162 renderer
->pmh
.Key
= 0x9AC6CDD7;
1163 renderer
->pmh
.Handle
= 0;
1164 renderer
->pmh
.Left
= 0;
1165 renderer
->pmh
.Top
= 0;
1166 renderer
->pmh
.Right
= (gint16
)(SC(data
->extents
.right
- data
->extents
.left
) * 25.4);
1167 renderer
->pmh
.Bottom
= (gint16
)(SC(data
->extents
.bottom
- data
->extents
.top
) * 25.4);
1168 renderer
->pmh
.Inch
= 1440 * 10;
1169 renderer
->pmh
.Reserved
= 0;
1172 renderer
->pmh
.Checksum
= 0;
1173 for (ptr
= (guint16
*)&renderer
->pmh
; ptr
< (guint16
*)&(renderer
->pmh
.Checksum
); ptr
++)
1174 renderer
->pmh
.Checksum
^= *ptr
;
1177 /* write the placeable header */
1178 fwrite(&renderer
->pmh
, 1, 22 /* NOT: sizeof(PLACEABLEMETAHEADER) */, file
->file
);
1181 /* bounding box in device units */
1184 bbox
.right
= (int)(SC(data
->extents
.right
- data
->extents
.left
) * 25.4);
1185 bbox
.bottom
= (int)(SC(data
->extents
.bottom
- data
->extents
.top
) * 25.4);
1187 /* initialize drawing */
1188 W32::SetBkMode(renderer
->hFileDC
, TRANSPARENT
);
1189 W32::SetMapMode(renderer
->hFileDC
, MM_TEXT
);
1190 W32::IntersectClipRect(renderer
->hFileDC
,
1191 bbox
.left
, bbox
.top
,
1192 bbox
.right
, bbox
.bottom
);
1194 renderer
->scale
*= 0.95; /* just a little smaller ... */
1197 DIAG_NOTE(renderer
, "export_data extents %f,%f -> %f,%f\n",
1198 extent
->left
, extent
->top
, extent
->right
, extent
->bottom
);
1200 data_render(data
, DIA_RENDERER(renderer
), NULL
, NULL
, NULL
);
1202 g_object_unref(renderer
);
1205 static const gchar
*extensions
[] = { "wmf", NULL
};
1206 static DiaExportFilter my_export_filter
= {
1207 N_("Windows Meta File"),
1210 NULL
, /* user data */
1215 /* --- dia plug-in interface --- */
1217 DIA_PLUGIN_CHECK_INIT
1220 dia_plugin_init(PluginInfo
*info
)
1222 if (!dia_plugin_info_init(info
, "WMF",
1223 _("WMF export filter"),
1225 return DIA_PLUGIN_INIT_ERROR
;
1229 * On non windoze platforms this plug-in currently is only
1230 * useful at compile/develoment time. The output is broken
1231 * when processed by wmf_gdi.cpp ...
1233 filter_register_export(&my_export_filter
);
1236 return DIA_PLUGIN_INIT_OK
;