• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

作図ソフト dia の改良版


Commit MetaInfo

修訂a45b01acbb81b3dbc162ba69a9290df6ed522992 (tree)
時間2000-06-07 18:05:44
作者James Henstridge <james@daa....>
CommiterJames Henstridge

Log Message

set some table packing options to make it look a little nicer.

2000-06-07 James Henstridge <james@daa.com.au>

* app/plugin-manager.c (get_plugin_manager): set some table
packing options to make it look a little nicer.

* plug-ins/hpgl/Makefile.am, plug-ins/wpg/Makefile.am: added
makefiles for these plug-ins.

* plug-ins/{hpgl,wmf,wpg}/*: removed dos style cariage returns.

* configure.in: added hpgl and wpg directories to build. Added
note about whether gnome-print support was enabled, and noted that
it is not recommended.

Change Summary

差異

--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
1+2000-06-07 James Henstridge <james@daa.com.au>
2+
3+ * app/plugin-manager.c (get_plugin_manager): set some table
4+ packing options to make it look a little nicer.
5+
6+ * plug-ins/hpgl/Makefile.am, plug-ins/wpg/Makefile.am: added
7+ makefiles for these plug-ins.
8+
9+ * plug-ins/{hpgl,wmf,wpg}/*: removed dos style cariage returns.
10+
11+ * configure.in: added hpgl and wpg directories to build. Added
12+ note about whether gnome-print support was enabled, and noted that
13+ it is not recommended.
14+
115 2000-06-06 James Henstridge <james@daa.com.au>
216
317 * plug-ins/{hpgl,wmf,wpg}/*: Hans Breuer's plug-ins. They still need
--- a/app/plugin-manager.c
+++ b/app/plugin-manager.c
@@ -187,7 +187,7 @@ get_plugin_manager(void)
187187 pm.name_label = gtk_label_new("");
188188 gtk_misc_set_alignment(GTK_MISC(pm.name_label), 0.0, 0.5);
189189 gtk_table_attach(GTK_TABLE(table), pm.name_label, 1,2, 0,1,
190- GTK_FILL, GTK_FILL|GTK_EXPAND, 0, 0);
190+ GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
191191 gtk_widget_show(pm.name_label);
192192
193193 label = gtk_label_new(_("File name:"));
@@ -199,7 +199,7 @@ get_plugin_manager(void)
199199 pm.file_label = gtk_label_new("");
200200 gtk_misc_set_alignment(GTK_MISC(pm.file_label), 0.0, 0.5);
201201 gtk_table_attach(GTK_TABLE(table), pm.file_label, 1,2, 1,2,
202- GTK_FILL, GTK_FILL|GTK_EXPAND, 0, 0);
202+ GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
203203 gtk_widget_show(pm.file_label);
204204
205205 label = gtk_label_new(_("Description:"));
@@ -213,7 +213,7 @@ get_plugin_manager(void)
213213 gtk_label_set_justify(GTK_LABEL(pm.description_label), GTK_JUSTIFY_LEFT);
214214 gtk_label_set_line_wrap(GTK_LABEL(pm.description_label), TRUE);
215215 gtk_table_attach(GTK_TABLE(table), pm.description_label, 1,2, 2,3,
216- GTK_FILL, GTK_FILL|GTK_EXPAND, 0, 0);
216+ GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
217217 gtk_widget_show(pm.description_label);
218218
219219 label = gtk_label_new(_("Loaded:"));
@@ -225,7 +225,7 @@ get_plugin_manager(void)
225225 pm.loaded_label = gtk_label_new("");
226226 gtk_misc_set_alignment(GTK_MISC(pm.loaded_label), 0.0, 0.5);
227227 gtk_table_attach(GTK_TABLE(table), pm.loaded_label, 1,2, 3,4,
228- GTK_FILL, GTK_FILL|GTK_EXPAND, 0, 0);
228+ GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
229229 gtk_widget_show(pm.loaded_label);
230230
231231 pm.autoload_cbutton = gtk_check_button_new_with_label(
--- a/configure.in
+++ b/configure.in
@@ -256,6 +256,8 @@ plug-ins/Makefile
256256 plug-ins/cgm/Makefile
257257 plug-ins/pstricks/Makefile
258258 plug-ins/dxf/Makefile
259+plug-ins/hpgl/Makefile
260+plug-ins/wpg/Makefile
259261 )
260262
261263 echo "
@@ -269,5 +271,6 @@ Configuration:
269271
270272 Gnome support: ${GNOME}
271273 Build bonobo component (not supported): ${enable_bonobo}
274+ Gnome-print support (not recommended): ${enable_gnome_print}
272275
273276 Now type make to build dia."
--- a/plug-ins/Makefile.am
+++ b/plug-ins/Makefile.am
@@ -1 +1 @@
1-SUBDIRS = cgm pstricks dxf
1+SUBDIRS = cgm pstricks dxf hpgl wpg
--- /dev/null
+++ b/plug-ins/hpgl/.cvsignore
@@ -0,0 +1,9 @@
1+.cvsignore
2+.deps
3+.libs
4+Makefile
5+Makefile.in
6+*.lo
7+*.la
8+*.pyc
9+
--- /dev/null
+++ b/plug-ins/hpgl/Makefile.am
@@ -0,0 +1,8 @@
1+pkglib_LTLIBRARIES = libhpgl_filter.la
2+
3+libhpgl_filter_la_SOURCES = hpgl.c
4+libhpgl_filter_la_LDFLAGS = -export-dynamic -module -avoid-version
5+libhpgl_filter_la_LIBADD = $(GTK_LIBS)
6+
7+INCLUDES = -I$(top_srcdir)/intl -I$(top_srcdir)/lib \
8+ $(GTK_CFLAGS) $(GNOME_CFLAGS)
--- a/plug-ins/hpgl/hpgl.c
+++ b/plug-ins/hpgl/hpgl.c
@@ -1,631 +1,631 @@
1-/* Dia -- an diagram creation/manipulation program
2- * Copyright (C) 1998 Alexander Larsson
3- *
4- * hpgl.c -- HPGL export plugin for dia
5- * Copyright (C) 2000, Hans Breuer, <Hans@Breuer.Org>
6- * based on dummy.c
7- * based on CGM plug-in Copyright (C) 1999 James Henstridge.
8- *
9- * This program is free software; you can redistribute it and/or modify
10- * it under the terms of the GNU General Public License as published by
11- * the Free Software Foundation; either version 2 of the License, or
12- * (at your option) any later version.
13- *
14- * This program is distributed in the hope that it will be useful,
15- * but WITHOUT ANY WARRANTY; without even the implied warranty of
16- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17- * GNU General Public License for more details.
18- *
19- * You should have received a copy of the GNU General Public License
20- * along with this program; if not, write to the Free Software
21- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22- */
23-
24-/*
25- * ToDo:
26- * - provide more rendering functions like "render_draw_ellipse_by_arc"
27- * to be used by simple format renderers; move them to libdia?
28- */
29-
30-#include <stdio.h>
31-#include <string.h>
32-#include <math.h>
33-#include <glib.h>
34-
35-#include "config.h"
36-#include "intl.h"
37-#include "message.h"
38-#include "geometry.h"
39-#include "render.h"
40-#include "filter.h"
41-#include "plug-ins.h"
42-
43-/* format specific */
44-#define HPGL_MAX_PENS 8
45-
46-/* --- the renderer --- */
47-#define MY_RENDERER_NAME "HPGL"
48-
49-#define PEN_HAS_COLOR (1 << 0)
50-#define PEN_HAS_WIDTH (1 << 1)
51-
52-typedef struct _MyRenderer MyRenderer;
53-struct _MyRenderer {
54- Renderer renderer;
55-
56- FILE *file;
57-
58- /*
59- * The number of pens is limited. This is used to select one.
60- */
61- struct {
62- Color color;
63- float width;
64- int has_it;
65- } pen[HPGL_MAX_PENS];
66- int last_pen;
67- real dash_length;
68- real font_height;
69-
70- Point size; /* extent size */
71- real scale;
72- real offset; /* in dia units */
73-};
74-
75-/* include function declares and render object "vtable" */
76-#include "../renderer.inc"
77-
78-#define DIAG_NOTE /* my_log */
79-void
80-my_log(MyRenderer* renderer, char* format, ...)
81-{
82- gchar *string;
83- va_list args;
84-
85- g_return_if_fail (format != NULL);
86-
87- va_start (args, format);
88- string = g_strdup_vprintf (format, args);
89- va_end (args);
90-
91- g_print(string);
92-
93- g_free(string);
94-}
95-
96-/* hpgl helpers */
97-void hpgl_select_pen(MyRenderer* renderer, Color* color, real width)
98-{
99- int nPen = 0;
100- int i;
101- /* look if this pen is defined already */
102- if (0.0 != width) {
103- /* either width ... */
104- for (i = 0; i < HPGL_MAX_PENS; i++) {
105- if (!(renderer->pen[i].has_it & PEN_HAS_WIDTH)) {
106- nPen = i;
107- break;
108- }
109- if (width == renderer->pen[i].width) {
110- nPen = i;
111- break;
112- }
113- }
114- }
115-
116- if (NULL != color) {
117- for (i = nPen; i < HPGL_MAX_PENS; i++) {
118- if (!(renderer->pen[i].has_it & PEN_HAS_COLOR)) {
119- nPen = i;
120- break;
121- }
122- if ( (color->red == renderer->pen[i].color.red)
123- && (color->green == renderer->pen[i].color.green)
124- && (color->blue == renderer->pen[i].color.blue)) {
125- nPen = i;
126- break;
127- }
128- }
129- }
130- /* "create" new pen ... */
131- if ((nPen < HPGL_MAX_PENS) && (-1 < nPen)) {
132- if (0.0 != width) {
133- renderer->pen[nPen].width = width;
134- renderer->pen[nPen].has_it |= PEN_HAS_WIDTH;
135- }
136- if (NULL != color) {
137- renderer->pen[nPen].color = *color;
138- renderer->pen[nPen].has_it |= PEN_HAS_COLOR;
139- }
140- }
141- /* ... or use best fitting one */
142- else if (-1 == nPen) {
143- nPen = 0; /* TODO: */
144- }
145-
146- if (renderer->last_pen != nPen)
147- fprintf(renderer->file, "SP%d;\n", nPen+1);
148- renderer->last_pen = nPen;
149-}
150-
151-int
152-hpgl_scale(MyRenderer *renderer, real val)
153-{
154- return (int)((val + renderer->offset) * renderer->scale);
155-}
156-
157-/* render functions */
158-static void
159-begin_render(MyRenderer *renderer, DiagramData *data)
160-{
161- int i;
162-
163- DIAG_NOTE(renderer, "begin_render\n");
164-
165- /* initialize pens */
166- for (i = 0; i < HPGL_MAX_PENS; i++) {
167- renderer->pen[i].color = color_black;
168- renderer->pen[i].width = 0.0;
169- renderer->pen[i].has_it = 0;
170- }
171- renderer->last_pen = -1;
172- renderer->dash_length = 0.0;
173-}
174-
175-static void
176-end_render(MyRenderer *renderer)
177-{
178- DIAG_NOTE(renderer, "end_render\n");
179- fclose(renderer->file);
180-}
181-
182-static void
183-set_linewidth(MyRenderer *renderer, real linewidth)
184-{
185- DIAG_NOTE(renderer, "set_linewidth %f\n", linewidth);
186-
187- hpgl_select_pen(renderer, NULL, linewidth);
188-}
189-
190-static void
191-set_linecaps(MyRenderer *renderer, LineCaps mode)
192-{
193- DIAG_NOTE(renderer, "set_linecaps %d\n", mode);
194-
195- switch(mode) {
196- case LINECAPS_BUTT:
197- break;
198- case LINECAPS_ROUND:
199- break;
200- case LINECAPS_PROJECTING:
201- break;
202- default:
203- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
204- }
205-}
206-
207-static void
208-set_linejoin(MyRenderer *renderer, LineJoin mode)
209-{
210- DIAG_NOTE(renderer, "set_join %d\n", mode);
211-
212- switch(mode) {
213- case LINEJOIN_MITER:
214- break;
215- case LINEJOIN_ROUND:
216- break;
217- case LINEJOIN_BEVEL:
218- break;
219- default:
220- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
221- }
222-}
223-
224-static void
225-set_linestyle(MyRenderer *renderer, LineStyle mode)
226-{
227- DIAG_NOTE(renderer, "set_linestyle %d\n", mode);
228-
229- /* line type */
230- switch (mode) {
231- case LINESTYLE_SOLID:
232- fprintf(renderer->file, "LT;\n");
233- break;
234- case LINESTYLE_DASHED:
235- if (renderer->dash_length > 0.5) /* ??? unit of dash_lenght ? */
236- fprintf(renderer->file, "LT2;\n"); /* short */
237- else
238- fprintf(renderer->file, "LT3;\n"); /* long */
239- break;
240- case LINESTYLE_DASH_DOT:
241- fprintf(renderer->file, "LT4;\n");
242- break;
243- case LINESTYLE_DASH_DOT_DOT:
244- fprintf(renderer->file, "LT5;\n"); /* ??? Mittellinie? */
245- break;
246- case LINESTYLE_DOTTED:
247- fprintf(renderer->file, "LT1;\n");
248- break;
249- default:
250- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
251- }
252-}
253-
254-static void
255-set_dashlength(MyRenderer *renderer, real length)
256-{
257- DIAG_NOTE(renderer, "set_dashlength %f\n", length);
258-
259- /* dot = 20% of len */
260- renderer->dash_length = length;
261-}
262-
263-static void
264-set_fillstyle(MyRenderer *renderer, FillStyle mode)
265-{
266- DIAG_NOTE(renderer, "set_fillstyle %d\n", mode);
267-
268- switch(mode) {
269- case FILLSTYLE_SOLID:
270- break;
271- default:
272- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
273- }
274-}
275-
276-static void
277-set_font(MyRenderer *renderer, Font *font, real height)
278-{
279- DIAG_NOTE(renderer, "set_font %f\n", height);
280- renderer->font_height = height;
281-}
282-
283-/* Need to translate coord system:
284- *
285- * Dia x,y -> Hpgl x,-y
286- *
287- * doing it before scaling.
288- */
289-static void
290-draw_line(MyRenderer *renderer,
291- Point *start, Point *end,
292- Color *line_colour)
293-{
294- DIAG_NOTE(renderer, "draw_line %f,%f -> %f, %f\n",
295- start->x, start->y, end->x, end->y);
296- hpgl_select_pen(renderer, line_colour, 0.0);
297- fprintf (renderer->file,
298- "PU%d,%d;PD%d,%d;\n",
299- hpgl_scale(renderer, start->x), hpgl_scale(renderer, -start->y),
300- hpgl_scale(renderer, end->x), hpgl_scale(renderer, -end->y));
301-}
302-
303-static void
304-draw_polyline(MyRenderer *renderer,
305- Point *points, int num_points,
306- Color *line_colour)
307-{
308- int i;
309-
310- DIAG_NOTE(renderer, "draw_polyline n:%d %f,%f ...\n",
311- num_points, points->x, points->y);
312-
313- g_return_if_fail(1 < num_points);
314-
315- hpgl_select_pen(renderer, line_colour, 0.0);
316- fprintf (renderer->file, "PU%d,%d;PD;PA",
317- hpgl_scale(renderer, points[0].x),
318- hpgl_scale(renderer, -points[0].y));
319- /* absolute movement */
320- for (i = 1; i < num_points-1; i++)
321- fprintf(renderer->file, "%d,%d,",
322- hpgl_scale(renderer, points[i].x),
323- hpgl_scale(renderer, -points[i].y));
324- i = num_points - 1;
325- fprintf(renderer->file, "%d,%d;\n",
326- hpgl_scale(renderer, points[i].x),
327- hpgl_scale(renderer, -points[i].y));
328-}
329-
330-static void
331-draw_polygon(MyRenderer *renderer,
332- Point *points, int num_points,
333- Color *line_colour)
334-{
335- DIAG_NOTE(renderer, "draw_polygon n:%d %f,%f ...\n",
336- num_points, points->x, points->y);
337- draw_polyline(renderer,points,num_points,line_colour);
338- /* last to first */
339- draw_line(renderer, &points[num_points-1], &points[0], line_colour);
340-}
341-
342-static void
343-fill_polygon(MyRenderer *renderer,
344- Point *points, int num_points,
345- Color *colour)
346-{
347- DIAG_NOTE(renderer, "fill_polygon n:%d %f,%f ...\n",
348- num_points, points->x, points->y);
349- draw_polyline(renderer,points,num_points,colour);
350-}
351-
352-static void
353-draw_rect(MyRenderer *renderer,
354- Point *ul_corner, Point *lr_corner,
355- Color *colour)
356-{
357- DIAG_NOTE(renderer, "draw_rect %f,%f -> %f,%f\n",
358- ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
359- hpgl_select_pen(renderer, colour, 0.0);
360- fprintf (renderer->file, "PU%d,%d;PD;EA%d,%d;\n",
361- hpgl_scale(renderer, ul_corner->x),
362- hpgl_scale(renderer, -ul_corner->y),
363- hpgl_scale(renderer, lr_corner->x),
364- hpgl_scale(renderer, -lr_corner->y));
365-}
366-
367-static void
368-fill_rect(MyRenderer *renderer,
369- Point *ul_corner, Point *lr_corner,
370- Color *colour)
371-{
372- DIAG_NOTE(renderer, "fill_rect %f,%f -> %f,%f\n",
373- ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
374-#if 0
375- hpgl_select_pen(renderer, colour, 0.0);
376- fprintf (renderer->file, "PU%d,%d;PD;RA%d,%d;\n",
377- hpgl_scale(renderer, ul_corner->x),
378- hpgl_scale(renderer, -ul_corner->y),
379- hpgl_scale(renderer, lr_corner->x),
380- hpgl_scale(renderer, -lr_corner->y));
381-#else
382- /* the fill modes aren't really compatible ... */
383- draw_rect(renderer, ul_corner, lr_corner, colour);
384-#endif
385-}
386-
387-static void
388-draw_arc(MyRenderer *renderer,
389- Point *center,
390- real width, real height,
391- real angle1, real angle2,
392- Color *colour)
393-{
394- Point start;
395-
396- DIAG_NOTE(renderer, "draw_arc %fx%f <%f,<%f\n",
397- width, height, angle1, angle2);
398- hpgl_select_pen(renderer, colour, 0.0);
399-
400- /* move to start point */
401- start.x = center->x + (width / 2.0) * cos((M_PI / 180.0) * angle1);
402- start.y = - center->y + (height / 2.0) * sin((M_PI / 180.0) * angle1);
403- fprintf (renderer->file, "PU%d,%d;PD;",
404- hpgl_scale(renderer, start.x),
405- hpgl_scale(renderer, start.y));
406- /* Arc Absolute - around center */
407- fprintf (renderer->file, "AA%d,%d,%d;",
408- hpgl_scale(renderer, center->x),
409- hpgl_scale(renderer, - center->y),
410- (int)floor(360.0 - angle1 + angle2));
411-}
412-
413-static void
414-fill_arc(MyRenderer *renderer,
415- Point *center,
416- real width, real height,
417- real angle1, real angle2,
418- Color *colour)
419-{
420- DIAG_NOTE(renderer, "fill_arc %fx%f <%f,<%f\n",
421- width, height, angle1, angle2);
422- g_assert (width == height);
423-
424- /* move to center */
425- fprintf (renderer->file, "PU%d,%d;PD;",
426- hpgl_scale(renderer, center->x),
427- hpgl_scale(renderer, -center->y));
428- /* Edge Wedge */
429- fprintf (renderer->file, "EW%d,%d,%d;",
430- hpgl_scale(renderer, width),
431- (int)angle1, (int)(angle2-angle1));
432-}
433-
434-static void
435-draw_ellipse(MyRenderer *renderer,
436- Point *center,
437- real width, real height,
438- Color *colour)
439-{
440- DIAG_NOTE(renderer, "draw_ellipse %fx%f center @ %f,%f\n",
441- width, height, center->x, center->y);
442-
443- if (width != height)
444- {
445- renderer_draw_ellipse_by_arc(renderer, center, width, height, colour);
446- }
447- else
448- {
449- hpgl_select_pen(renderer, colour, 0.0);
450-
451- fprintf (renderer->file, "PU%d,%d;CI%d;\n",
452- hpgl_scale(renderer, center->x),
453- hpgl_scale(renderer, -center->y),
454- hpgl_scale(renderer, width / 2.0));
455- }
456-}
457-
458-static void
459-fill_ellipse(MyRenderer *renderer,
460- Point *center,
461- real width, real height,
462- Color *colour)
463-{
464- DIAG_NOTE(renderer, "fill_ellipse %fx%f center @ %f,%f\n",
465- width, height, center->x, center->y);
466-}
467-
468-static void
469-draw_bezier(MyRenderer *renderer,
470- BezPoint *points,
471- int numpoints,
472- Color *colour)
473-{
474- DIAG_NOTE(renderer, "draw_bezier n:%d %fx%f ...\n",
475- numpoints, points->p1.x, points->p1.y);
476-
477- /* @todo: provide bezier rendering by simple render function callback like:
478- *
479- * renderer_draw_bezier_by_line(renderer, points, numpoints, colour);
480- */
481-}
482-
483-static void
484-fill_bezier(MyRenderer *renderer,
485- BezPoint *points, /* Last point must be same as first point */
486- int numpoints,
487- Color *colour)
488-{
489- DIAG_NOTE(renderer, "fill_bezier n:%d %fx%f ...\n",
490- numpoints, points->p1.x, points->p1.y);
491-}
492-
493-static void
494-draw_string(MyRenderer *renderer,
495- const char *text,
496- Point *pos, Alignment alignment,
497- Color *colour)
498-{
499- float height, width;
500-
501- DIAG_NOTE(renderer, "draw_string %f,%f %s\n",
502- pos->x, pos->y, text);
503-
504- /* set position */
505- fprintf(renderer->file, "PU%d,%d;",
506- hpgl_scale(renderer, pos->x), hpgl_scale(renderer, -pos->y));
507-
508- switch (alignment) {
509- case ALIGN_LEFT:
510- fprintf (renderer->file, "LO1;\n");
511- break;
512- case ALIGN_CENTER:
513- fprintf (renderer->file, "LO4;\n");
514- break;
515- case ALIGN_RIGHT:
516- fprintf (renderer->file, "LO7;\n");
517- break;
518- }
519- hpgl_select_pen(renderer,colour,0.0);
520-
521-#if 0
522- /*
523- * SR - Relative Character Size >0.0 ... 127.999
524- * set the capital letter box width and height as a percentage of
525- * P2X-P1X and P2Y-P1Y
526- */
527- height = (127.999 * renderer->font_height * renderer->scale) / renderer->size.y;
528- width = 0.75 * height; /* FIXME: */
529- fprintf(renderer->file, "SR%.3f,%.3f;", width, height);
530-#else
531- /*
532- * SI - character size absolute
533- * size needed in centimeters
534- */
535- fprintf(renderer->file, "SI%.3f,%.3f;",
536- renderer->font_height * renderer->scale * 0.75 * 0.0025,
537- renderer->font_height * renderer->scale * 0.0025);
538-
539-#endif
540- fprintf(renderer->file, "DT\003;" /* Terminator */
541- "LB%s\003;\n", text);
542-}
543-
544-static void
545-draw_image(MyRenderer *renderer,
546- Point *point,
547- real width, real height,
548- DiaImage image)
549-{
550- DIAG_NOTE(renderer, "draw_image %fx%f @%f,%f\n",
551- width, height, point->x, point->y);
552- g_warning("HPGL: images unsupported!");
553-}
554-
555-static void
556-export_data(DiagramData *data, const gchar *filename, const gchar *diafilename)
557-{
558- MyRenderer *renderer;
559- FILE *file;
560- Rectangle *extent;
561- gint len;
562- real width, height;
563-
564- file = fopen(filename, "w"); /* "wb" for binary! */
565-
566- if (file == NULL) {
567- message_error(_("Couldn't open: '%s' for writing.\n"), filename);
568- return;
569- }
570-
571- renderer = g_new(MyRenderer, 1);
572- renderer->renderer.ops = &MyRenderOps;
573- renderer->renderer.is_interactive = 0;
574- renderer->renderer.interactive_ops = NULL;
575-
576- renderer->file = file;
577-
578- extent = &data->extents;
579-
580- /* use extents */
581- DIAG_NOTE(renderer, "export_data extents %f,%f -> %f,%f\n",
582- extent->left, extent->top, extent->right, extent->bottom);
583-
584- width = extent->right - extent->left;
585- height = extent->bottom - extent->top;
586- renderer->scale = 0.001;
587- if (width > height)
588- while (renderer->scale * width < 3276.7) renderer->scale *= 10.0;
589- else
590- while (renderer->scale * height < 3276.7) renderer->scale *= 10.0;
591- renderer->offset = 0.0; /* just to have one */
592-
593- renderer->size.x = width * renderer->scale;
594- renderer->size.y = height * renderer->scale;
595-#if 0
596- /* OR: set page size and scale */
597- fprintf(renderer->file, "PS0;SC%d,%d,%d,%d;\n",
598- hpgl_scale(renderer, extent->left),
599- hpgl_scale(renderer, extent->right),
600- hpgl_scale(renderer, extent->bottom),
601- hpgl_scale(renderer, extent->top));
602-#endif
603- data_render(data, (Renderer *)renderer, NULL, NULL, NULL);
604-
605- g_free(renderer);
606-}
607-
608-static const gchar *extensions[] = { "plt", "hpgl", NULL };
609-static DiaExportFilter my_export_filter = {
610- N_(MY_RENDERER_NAME),
611- extensions,
612- export_data
613-};
614-
615-
616-/* --- dia plug-in interface --- */
617-
618-DIA_PLUGIN_CHECK_INIT
619-
620-PluginInitResult
621-dia_plugin_init(PluginInfo *info)
622-{
623- if (!dia_plugin_info_init(info, "HPGL",
624- _("HP Graphics Language export filter"),
625- NULL, NULL))
626- return DIA_PLUGIN_INIT_ERROR;
627-
628- filter_register_export(&my_export_filter);
629-
630- return DIA_PLUGIN_INIT_OK;
631-}
1+/* Dia -- an diagram creation/manipulation program
2+ * Copyright (C) 1998 Alexander Larsson
3+ *
4+ * hpgl.c -- HPGL export plugin for dia
5+ * Copyright (C) 2000, Hans Breuer, <Hans@Breuer.Org>
6+ * based on dummy.c
7+ * based on CGM plug-in Copyright (C) 1999 James Henstridge.
8+ *
9+ * This program is free software; you can redistribute it and/or modify
10+ * it under the terms of the GNU General Public License as published by
11+ * the Free Software Foundation; either version 2 of the License, or
12+ * (at your option) any later version.
13+ *
14+ * This program is distributed in the hope that it will be useful,
15+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+ * GNU General Public License for more details.
18+ *
19+ * You should have received a copy of the GNU General Public License
20+ * along with this program; if not, write to the Free Software
21+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22+ */
23+
24+/*
25+ * ToDo:
26+ * - provide more rendering functions like "render_draw_ellipse_by_arc"
27+ * to be used by simple format renderers; move them to libdia?
28+ */
29+
30+#include <stdio.h>
31+#include <string.h>
32+#include <math.h>
33+#include <glib.h>
34+
35+#include "config.h"
36+#include "intl.h"
37+#include "message.h"
38+#include "geometry.h"
39+#include "render.h"
40+#include "filter.h"
41+#include "plug-ins.h"
42+
43+/* format specific */
44+#define HPGL_MAX_PENS 8
45+
46+/* --- the renderer --- */
47+#define MY_RENDERER_NAME "HPGL"
48+
49+#define PEN_HAS_COLOR (1 << 0)
50+#define PEN_HAS_WIDTH (1 << 1)
51+
52+typedef struct _MyRenderer MyRenderer;
53+struct _MyRenderer {
54+ Renderer renderer;
55+
56+ FILE *file;
57+
58+ /*
59+ * The number of pens is limited. This is used to select one.
60+ */
61+ struct {
62+ Color color;
63+ float width;
64+ int has_it;
65+ } pen[HPGL_MAX_PENS];
66+ int last_pen;
67+ real dash_length;
68+ real font_height;
69+
70+ Point size; /* extent size */
71+ real scale;
72+ real offset; /* in dia units */
73+};
74+
75+/* include function declares and render object "vtable" */
76+#include "../renderer.inc"
77+
78+#define DIAG_NOTE /* my_log */
79+void
80+my_log(MyRenderer* renderer, char* format, ...)
81+{
82+ gchar *string;
83+ va_list args;
84+
85+ g_return_if_fail (format != NULL);
86+
87+ va_start (args, format);
88+ string = g_strdup_vprintf (format, args);
89+ va_end (args);
90+
91+ g_print(string);
92+
93+ g_free(string);
94+}
95+
96+/* hpgl helpers */
97+void hpgl_select_pen(MyRenderer* renderer, Color* color, real width)
98+{
99+ int nPen = 0;
100+ int i;
101+ /* look if this pen is defined already */
102+ if (0.0 != width) {
103+ /* either width ... */
104+ for (i = 0; i < HPGL_MAX_PENS; i++) {
105+ if (!(renderer->pen[i].has_it & PEN_HAS_WIDTH)) {
106+ nPen = i;
107+ break;
108+ }
109+ if (width == renderer->pen[i].width) {
110+ nPen = i;
111+ break;
112+ }
113+ }
114+ }
115+
116+ if (NULL != color) {
117+ for (i = nPen; i < HPGL_MAX_PENS; i++) {
118+ if (!(renderer->pen[i].has_it & PEN_HAS_COLOR)) {
119+ nPen = i;
120+ break;
121+ }
122+ if ( (color->red == renderer->pen[i].color.red)
123+ && (color->green == renderer->pen[i].color.green)
124+ && (color->blue == renderer->pen[i].color.blue)) {
125+ nPen = i;
126+ break;
127+ }
128+ }
129+ }
130+ /* "create" new pen ... */
131+ if ((nPen < HPGL_MAX_PENS) && (-1 < nPen)) {
132+ if (0.0 != width) {
133+ renderer->pen[nPen].width = width;
134+ renderer->pen[nPen].has_it |= PEN_HAS_WIDTH;
135+ }
136+ if (NULL != color) {
137+ renderer->pen[nPen].color = *color;
138+ renderer->pen[nPen].has_it |= PEN_HAS_COLOR;
139+ }
140+ }
141+ /* ... or use best fitting one */
142+ else if (-1 == nPen) {
143+ nPen = 0; /* TODO: */
144+ }
145+
146+ if (renderer->last_pen != nPen)
147+ fprintf(renderer->file, "SP%d;\n", nPen+1);
148+ renderer->last_pen = nPen;
149+}
150+
151+int
152+hpgl_scale(MyRenderer *renderer, real val)
153+{
154+ return (int)((val + renderer->offset) * renderer->scale);
155+}
156+
157+/* render functions */
158+static void
159+begin_render(MyRenderer *renderer, DiagramData *data)
160+{
161+ int i;
162+
163+ DIAG_NOTE(renderer, "begin_render\n");
164+
165+ /* initialize pens */
166+ for (i = 0; i < HPGL_MAX_PENS; i++) {
167+ renderer->pen[i].color = color_black;
168+ renderer->pen[i].width = 0.0;
169+ renderer->pen[i].has_it = 0;
170+ }
171+ renderer->last_pen = -1;
172+ renderer->dash_length = 0.0;
173+}
174+
175+static void
176+end_render(MyRenderer *renderer)
177+{
178+ DIAG_NOTE(renderer, "end_render\n");
179+ fclose(renderer->file);
180+}
181+
182+static void
183+set_linewidth(MyRenderer *renderer, real linewidth)
184+{
185+ DIAG_NOTE(renderer, "set_linewidth %f\n", linewidth);
186+
187+ hpgl_select_pen(renderer, NULL, linewidth);
188+}
189+
190+static void
191+set_linecaps(MyRenderer *renderer, LineCaps mode)
192+{
193+ DIAG_NOTE(renderer, "set_linecaps %d\n", mode);
194+
195+ switch(mode) {
196+ case LINECAPS_BUTT:
197+ break;
198+ case LINECAPS_ROUND:
199+ break;
200+ case LINECAPS_PROJECTING:
201+ break;
202+ default:
203+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
204+ }
205+}
206+
207+static void
208+set_linejoin(MyRenderer *renderer, LineJoin mode)
209+{
210+ DIAG_NOTE(renderer, "set_join %d\n", mode);
211+
212+ switch(mode) {
213+ case LINEJOIN_MITER:
214+ break;
215+ case LINEJOIN_ROUND:
216+ break;
217+ case LINEJOIN_BEVEL:
218+ break;
219+ default:
220+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
221+ }
222+}
223+
224+static void
225+set_linestyle(MyRenderer *renderer, LineStyle mode)
226+{
227+ DIAG_NOTE(renderer, "set_linestyle %d\n", mode);
228+
229+ /* line type */
230+ switch (mode) {
231+ case LINESTYLE_SOLID:
232+ fprintf(renderer->file, "LT;\n");
233+ break;
234+ case LINESTYLE_DASHED:
235+ if (renderer->dash_length > 0.5) /* ??? unit of dash_lenght ? */
236+ fprintf(renderer->file, "LT2;\n"); /* short */
237+ else
238+ fprintf(renderer->file, "LT3;\n"); /* long */
239+ break;
240+ case LINESTYLE_DASH_DOT:
241+ fprintf(renderer->file, "LT4;\n");
242+ break;
243+ case LINESTYLE_DASH_DOT_DOT:
244+ fprintf(renderer->file, "LT5;\n"); /* ??? Mittellinie? */
245+ break;
246+ case LINESTYLE_DOTTED:
247+ fprintf(renderer->file, "LT1;\n");
248+ break;
249+ default:
250+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
251+ }
252+}
253+
254+static void
255+set_dashlength(MyRenderer *renderer, real length)
256+{
257+ DIAG_NOTE(renderer, "set_dashlength %f\n", length);
258+
259+ /* dot = 20% of len */
260+ renderer->dash_length = length;
261+}
262+
263+static void
264+set_fillstyle(MyRenderer *renderer, FillStyle mode)
265+{
266+ DIAG_NOTE(renderer, "set_fillstyle %d\n", mode);
267+
268+ switch(mode) {
269+ case FILLSTYLE_SOLID:
270+ break;
271+ default:
272+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
273+ }
274+}
275+
276+static void
277+set_font(MyRenderer *renderer, Font *font, real height)
278+{
279+ DIAG_NOTE(renderer, "set_font %f\n", height);
280+ renderer->font_height = height;
281+}
282+
283+/* Need to translate coord system:
284+ *
285+ * Dia x,y -> Hpgl x,-y
286+ *
287+ * doing it before scaling.
288+ */
289+static void
290+draw_line(MyRenderer *renderer,
291+ Point *start, Point *end,
292+ Color *line_colour)
293+{
294+ DIAG_NOTE(renderer, "draw_line %f,%f -> %f, %f\n",
295+ start->x, start->y, end->x, end->y);
296+ hpgl_select_pen(renderer, line_colour, 0.0);
297+ fprintf (renderer->file,
298+ "PU%d,%d;PD%d,%d;\n",
299+ hpgl_scale(renderer, start->x), hpgl_scale(renderer, -start->y),
300+ hpgl_scale(renderer, end->x), hpgl_scale(renderer, -end->y));
301+}
302+
303+static void
304+draw_polyline(MyRenderer *renderer,
305+ Point *points, int num_points,
306+ Color *line_colour)
307+{
308+ int i;
309+
310+ DIAG_NOTE(renderer, "draw_polyline n:%d %f,%f ...\n",
311+ num_points, points->x, points->y);
312+
313+ g_return_if_fail(1 < num_points);
314+
315+ hpgl_select_pen(renderer, line_colour, 0.0);
316+ fprintf (renderer->file, "PU%d,%d;PD;PA",
317+ hpgl_scale(renderer, points[0].x),
318+ hpgl_scale(renderer, -points[0].y));
319+ /* absolute movement */
320+ for (i = 1; i < num_points-1; i++)
321+ fprintf(renderer->file, "%d,%d,",
322+ hpgl_scale(renderer, points[i].x),
323+ hpgl_scale(renderer, -points[i].y));
324+ i = num_points - 1;
325+ fprintf(renderer->file, "%d,%d;\n",
326+ hpgl_scale(renderer, points[i].x),
327+ hpgl_scale(renderer, -points[i].y));
328+}
329+
330+static void
331+draw_polygon(MyRenderer *renderer,
332+ Point *points, int num_points,
333+ Color *line_colour)
334+{
335+ DIAG_NOTE(renderer, "draw_polygon n:%d %f,%f ...\n",
336+ num_points, points->x, points->y);
337+ draw_polyline(renderer,points,num_points,line_colour);
338+ /* last to first */
339+ draw_line(renderer, &points[num_points-1], &points[0], line_colour);
340+}
341+
342+static void
343+fill_polygon(MyRenderer *renderer,
344+ Point *points, int num_points,
345+ Color *colour)
346+{
347+ DIAG_NOTE(renderer, "fill_polygon n:%d %f,%f ...\n",
348+ num_points, points->x, points->y);
349+ draw_polyline(renderer,points,num_points,colour);
350+}
351+
352+static void
353+draw_rect(MyRenderer *renderer,
354+ Point *ul_corner, Point *lr_corner,
355+ Color *colour)
356+{
357+ DIAG_NOTE(renderer, "draw_rect %f,%f -> %f,%f\n",
358+ ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
359+ hpgl_select_pen(renderer, colour, 0.0);
360+ fprintf (renderer->file, "PU%d,%d;PD;EA%d,%d;\n",
361+ hpgl_scale(renderer, ul_corner->x),
362+ hpgl_scale(renderer, -ul_corner->y),
363+ hpgl_scale(renderer, lr_corner->x),
364+ hpgl_scale(renderer, -lr_corner->y));
365+}
366+
367+static void
368+fill_rect(MyRenderer *renderer,
369+ Point *ul_corner, Point *lr_corner,
370+ Color *colour)
371+{
372+ DIAG_NOTE(renderer, "fill_rect %f,%f -> %f,%f\n",
373+ ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
374+#if 0
375+ hpgl_select_pen(renderer, colour, 0.0);
376+ fprintf (renderer->file, "PU%d,%d;PD;RA%d,%d;\n",
377+ hpgl_scale(renderer, ul_corner->x),
378+ hpgl_scale(renderer, -ul_corner->y),
379+ hpgl_scale(renderer, lr_corner->x),
380+ hpgl_scale(renderer, -lr_corner->y));
381+#else
382+ /* the fill modes aren't really compatible ... */
383+ draw_rect(renderer, ul_corner, lr_corner, colour);
384+#endif
385+}
386+
387+static void
388+draw_arc(MyRenderer *renderer,
389+ Point *center,
390+ real width, real height,
391+ real angle1, real angle2,
392+ Color *colour)
393+{
394+ Point start;
395+
396+ DIAG_NOTE(renderer, "draw_arc %fx%f <%f,<%f\n",
397+ width, height, angle1, angle2);
398+ hpgl_select_pen(renderer, colour, 0.0);
399+
400+ /* move to start point */
401+ start.x = center->x + (width / 2.0) * cos((M_PI / 180.0) * angle1);
402+ start.y = - center->y + (height / 2.0) * sin((M_PI / 180.0) * angle1);
403+ fprintf (renderer->file, "PU%d,%d;PD;",
404+ hpgl_scale(renderer, start.x),
405+ hpgl_scale(renderer, start.y));
406+ /* Arc Absolute - around center */
407+ fprintf (renderer->file, "AA%d,%d,%d;",
408+ hpgl_scale(renderer, center->x),
409+ hpgl_scale(renderer, - center->y),
410+ (int)floor(360.0 - angle1 + angle2));
411+}
412+
413+static void
414+fill_arc(MyRenderer *renderer,
415+ Point *center,
416+ real width, real height,
417+ real angle1, real angle2,
418+ Color *colour)
419+{
420+ DIAG_NOTE(renderer, "fill_arc %fx%f <%f,<%f\n",
421+ width, height, angle1, angle2);
422+ g_assert (width == height);
423+
424+ /* move to center */
425+ fprintf (renderer->file, "PU%d,%d;PD;",
426+ hpgl_scale(renderer, center->x),
427+ hpgl_scale(renderer, -center->y));
428+ /* Edge Wedge */
429+ fprintf (renderer->file, "EW%d,%d,%d;",
430+ hpgl_scale(renderer, width),
431+ (int)angle1, (int)(angle2-angle1));
432+}
433+
434+static void
435+draw_ellipse(MyRenderer *renderer,
436+ Point *center,
437+ real width, real height,
438+ Color *colour)
439+{
440+ DIAG_NOTE(renderer, "draw_ellipse %fx%f center @ %f,%f\n",
441+ width, height, center->x, center->y);
442+
443+ if (width != height)
444+ {
445+ renderer_draw_ellipse_by_arc(renderer, center, width, height, colour);
446+ }
447+ else
448+ {
449+ hpgl_select_pen(renderer, colour, 0.0);
450+
451+ fprintf (renderer->file, "PU%d,%d;CI%d;\n",
452+ hpgl_scale(renderer, center->x),
453+ hpgl_scale(renderer, -center->y),
454+ hpgl_scale(renderer, width / 2.0));
455+ }
456+}
457+
458+static void
459+fill_ellipse(MyRenderer *renderer,
460+ Point *center,
461+ real width, real height,
462+ Color *colour)
463+{
464+ DIAG_NOTE(renderer, "fill_ellipse %fx%f center @ %f,%f\n",
465+ width, height, center->x, center->y);
466+}
467+
468+static void
469+draw_bezier(MyRenderer *renderer,
470+ BezPoint *points,
471+ int numpoints,
472+ Color *colour)
473+{
474+ DIAG_NOTE(renderer, "draw_bezier n:%d %fx%f ...\n",
475+ numpoints, points->p1.x, points->p1.y);
476+
477+ /* @todo: provide bezier rendering by simple render function callback like:
478+ *
479+ * renderer_draw_bezier_by_line(renderer, points, numpoints, colour);
480+ */
481+}
482+
483+static void
484+fill_bezier(MyRenderer *renderer,
485+ BezPoint *points, /* Last point must be same as first point */
486+ int numpoints,
487+ Color *colour)
488+{
489+ DIAG_NOTE(renderer, "fill_bezier n:%d %fx%f ...\n",
490+ numpoints, points->p1.x, points->p1.y);
491+}
492+
493+static void
494+draw_string(MyRenderer *renderer,
495+ const char *text,
496+ Point *pos, Alignment alignment,
497+ Color *colour)
498+{
499+ float height, width;
500+
501+ DIAG_NOTE(renderer, "draw_string %f,%f %s\n",
502+ pos->x, pos->y, text);
503+
504+ /* set position */
505+ fprintf(renderer->file, "PU%d,%d;",
506+ hpgl_scale(renderer, pos->x), hpgl_scale(renderer, -pos->y));
507+
508+ switch (alignment) {
509+ case ALIGN_LEFT:
510+ fprintf (renderer->file, "LO1;\n");
511+ break;
512+ case ALIGN_CENTER:
513+ fprintf (renderer->file, "LO4;\n");
514+ break;
515+ case ALIGN_RIGHT:
516+ fprintf (renderer->file, "LO7;\n");
517+ break;
518+ }
519+ hpgl_select_pen(renderer,colour,0.0);
520+
521+#if 0
522+ /*
523+ * SR - Relative Character Size >0.0 ... 127.999
524+ * set the capital letter box width and height as a percentage of
525+ * P2X-P1X and P2Y-P1Y
526+ */
527+ height = (127.999 * renderer->font_height * renderer->scale) / renderer->size.y;
528+ width = 0.75 * height; /* FIXME: */
529+ fprintf(renderer->file, "SR%.3f,%.3f;", width, height);
530+#else
531+ /*
532+ * SI - character size absolute
533+ * size needed in centimeters
534+ */
535+ fprintf(renderer->file, "SI%.3f,%.3f;",
536+ renderer->font_height * renderer->scale * 0.75 * 0.0025,
537+ renderer->font_height * renderer->scale * 0.0025);
538+
539+#endif
540+ fprintf(renderer->file, "DT\003;" /* Terminator */
541+ "LB%s\003;\n", text);
542+}
543+
544+static void
545+draw_image(MyRenderer *renderer,
546+ Point *point,
547+ real width, real height,
548+ DiaImage image)
549+{
550+ DIAG_NOTE(renderer, "draw_image %fx%f @%f,%f\n",
551+ width, height, point->x, point->y);
552+ g_warning("HPGL: images unsupported!");
553+}
554+
555+static void
556+export_data(DiagramData *data, const gchar *filename, const gchar *diafilename)
557+{
558+ MyRenderer *renderer;
559+ FILE *file;
560+ Rectangle *extent;
561+ gint len;
562+ real width, height;
563+
564+ file = fopen(filename, "w"); /* "wb" for binary! */
565+
566+ if (file == NULL) {
567+ message_error(_("Couldn't open: '%s' for writing.\n"), filename);
568+ return;
569+ }
570+
571+ renderer = g_new(MyRenderer, 1);
572+ renderer->renderer.ops = &MyRenderOps;
573+ renderer->renderer.is_interactive = 0;
574+ renderer->renderer.interactive_ops = NULL;
575+
576+ renderer->file = file;
577+
578+ extent = &data->extents;
579+
580+ /* use extents */
581+ DIAG_NOTE(renderer, "export_data extents %f,%f -> %f,%f\n",
582+ extent->left, extent->top, extent->right, extent->bottom);
583+
584+ width = extent->right - extent->left;
585+ height = extent->bottom - extent->top;
586+ renderer->scale = 0.001;
587+ if (width > height)
588+ while (renderer->scale * width < 3276.7) renderer->scale *= 10.0;
589+ else
590+ while (renderer->scale * height < 3276.7) renderer->scale *= 10.0;
591+ renderer->offset = 0.0; /* just to have one */
592+
593+ renderer->size.x = width * renderer->scale;
594+ renderer->size.y = height * renderer->scale;
595+#if 0
596+ /* OR: set page size and scale */
597+ fprintf(renderer->file, "PS0;SC%d,%d,%d,%d;\n",
598+ hpgl_scale(renderer, extent->left),
599+ hpgl_scale(renderer, extent->right),
600+ hpgl_scale(renderer, extent->bottom),
601+ hpgl_scale(renderer, extent->top));
602+#endif
603+ data_render(data, (Renderer *)renderer, NULL, NULL, NULL);
604+
605+ g_free(renderer);
606+}
607+
608+static const gchar *extensions[] = { "plt", "hpgl", NULL };
609+static DiaExportFilter my_export_filter = {
610+ N_(MY_RENDERER_NAME),
611+ extensions,
612+ export_data
613+};
614+
615+
616+/* --- dia plug-in interface --- */
617+
618+DIA_PLUGIN_CHECK_INIT
619+
620+PluginInitResult
621+dia_plugin_init(PluginInfo *info)
622+{
623+ if (!dia_plugin_info_init(info, "HPGL",
624+ _("HP Graphics Language export filter"),
625+ NULL, NULL))
626+ return DIA_PLUGIN_INIT_ERROR;
627+
628+ filter_register_export(&my_export_filter);
629+
630+ return DIA_PLUGIN_INIT_OK;
631+}
--- a/plug-ins/renderer.inc
+++ b/plug-ins/renderer.inc
@@ -1,163 +1,163 @@
1-/* Dia -- an diagram creation/manipulation program
2- * Copyright (C) 1998 Alexander Larsson
3- *
4- * renderer.inc - The Dia renderer interface as include file
5- * to be used with export filters
6- * and
7- * renderer functions to construct complex
8- * geometric forms by simple drawing commands
9- */
10-
11-/* --- the renderer --- */
12-#if !defined(MY_RENDERER_NAME)
13-#error You need to define your private name and renderer struct before including this file!
14-#endif
15-
16-static void begin_render(MyRenderer *renderer, DiagramData *data);
17-static void end_render(MyRenderer *renderer);
18-static void set_linewidth(MyRenderer *renderer, real linewidth);
19-static void set_linecaps(MyRenderer *renderer, LineCaps mode);
20-static void set_linejoin(MyRenderer *renderer, LineJoin mode);
21-static void set_linestyle(MyRenderer *renderer, LineStyle mode);
22-static void set_dashlength(MyRenderer *renderer, real length);
23-static void set_fillstyle(MyRenderer *renderer, FillStyle mode);
24-static void set_font(MyRenderer *renderer, Font *font, real height);
25-static void draw_line(MyRenderer *renderer,
26- Point *start, Point *end,
27- Color *line_colour);
28-static void draw_polyline(MyRenderer *renderer,
29- Point *points, int num_points,
30- Color *line_colour);
31-static void draw_polygon(MyRenderer *renderer,
32- Point *points, int num_points,
33- Color *line_colour);
34-static void fill_polygon(MyRenderer *renderer,
35- Point *points, int num_points,
36- Color *line_colour);
37-static void draw_rect(MyRenderer *renderer,
38- Point *ul_corner, Point *lr_corner,
39- Color *colour);
40-static void fill_rect(MyRenderer *renderer,
41- Point *ul_corner, Point *lr_corner,
42- Color *colour);
43-static void draw_arc(MyRenderer *renderer,
44- Point *center,
45- real width, real height,
46- real angle1, real angle2,
47- Color *colour);
48-static void fill_arc(MyRenderer *renderer,
49- Point *center,
50- real width, real height,
51- real angle1, real angle2,
52- Color *colour);
53-static void draw_ellipse(MyRenderer *renderer,
54- Point *center,
55- real width, real height,
56- Color *colour);
57-static void fill_ellipse(MyRenderer *renderer,
58- Point *center,
59- real width, real height,
60- Color *colour);
61-static void draw_bezier(MyRenderer *renderer,
62- BezPoint *points,
63- int numpoints,
64- Color *colour);
65-static void fill_bezier(MyRenderer *renderer,
66- BezPoint *points, /* Last point must be same as first point */
67- int numpoints,
68- Color *colour);
69-static void draw_string(MyRenderer *renderer,
70- const char *text,
71- Point *pos, Alignment alignment,
72- Color *colour);
73-static void draw_image(MyRenderer *renderer,
74- Point *point,
75- real width, real height,
76- DiaImage image);
77-
78-static RenderOps MyRenderOps = {
79- (BeginRenderFunc) begin_render,
80- (EndRenderFunc) end_render,
81-
82- (SetLineWidthFunc) set_linewidth,
83- (SetLineCapsFunc) set_linecaps,
84- (SetLineJoinFunc) set_linejoin,
85- (SetLineStyleFunc) set_linestyle,
86- (SetDashLengthFunc) set_dashlength,
87- (SetFillStyleFunc) set_fillstyle,
88- (SetFontFunc) set_font,
89-
90- (DrawLineFunc) draw_line,
91- (DrawPolyLineFunc) draw_polyline,
92-
93- (DrawPolygonFunc) draw_polygon,
94- (FillPolygonFunc) fill_polygon,
95-
96- (DrawRectangleFunc) draw_rect,
97- (FillRectangleFunc) fill_rect,
98-
99- (DrawArcFunc) draw_arc,
100- (FillArcFunc) fill_arc,
101-
102- (DrawEllipseFunc) draw_ellipse,
103- (FillEllipseFunc) fill_ellipse,
104-
105- (DrawBezierFunc) draw_bezier,
106- (FillBezierFunc) fill_bezier,
107-
108- (DrawStringFunc) draw_string,
109-
110- (DrawImageFunc) draw_image,
111-};
112-
113-/* Draw an ellipse approximation consisting out of
114- * four arcs.
115- */
116-void
117-renderer_draw_ellipse_by_arc(
118- MyRenderer *renderer,
119- Point *center,
120- real width, real height,
121- Color *colour)
122-{
123- real a, b, e, d, alpha, c, x, y;
124- real g, gamma, r;
125- Point pt;
126- real angle;
127-
128- a = width / 2;
129- b = height / 2;
130- e = sqrt(a*a - b*b);
131-
132- alpha = 0.25*M_PI - asin((e/a) * sin(0.75*M_PI));
133- d = 2*a*sin(alpha);
134-
135- c = (sin(0.25*M_PI) * (2*e + d)) / sin(0.75*M_PI - alpha);
136-
137- y = c * sin (alpha);
138- x = c * cos (alpha) - e;
139-
140- /* draw arcs */
141- g = sqrt((a-x)*(a-x) + y*y);
142- gamma = acos((a-x)/g);
143- r = (sin(gamma) * g) / sin(M_PI-2*gamma);
144-
145- pt.y = center->y;
146- angle = (180 * (M_PI-2*gamma)) / M_PI;
147- pt.x = center->x + a - r; /* right */
148- draw_arc(renderer, &pt, 2*r, 2*r, 360-angle, angle, colour);
149- pt.x = center->x - a + r; /* left */
150- draw_arc(renderer, &pt, 2*r, 2*r, 180-angle, 180+angle, colour);
151-
152-
153- g = sqrt((b-y)*(b-y) + x*x);
154- gamma = acos((b-y)/g);
155- r = (sin(gamma) * g) / sin(M_PI-2*gamma);
156-
157- pt.x = center->x;
158- angle = (180 * (M_PI-2*gamma)) / M_PI;
159- pt.y = center->y - b + r; /* top */
160- draw_arc(renderer, &pt, 2*r, 2*r, 90-angle, 90+angle, colour);
161- pt.y = center->y + b - r; /* bottom */
162- draw_arc(renderer, &pt, 2*r, 2*r, 270-angle, 270+angle, colour);
1+/* Dia -- an diagram creation/manipulation program
2+ * Copyright (C) 1998 Alexander Larsson
3+ *
4+ * renderer.inc - The Dia renderer interface as include file
5+ * to be used with export filters
6+ * and
7+ * renderer functions to construct complex
8+ * geometric forms by simple drawing commands
9+ */
10+
11+/* --- the renderer --- */
12+#if !defined(MY_RENDERER_NAME)
13+#error You need to define your private name and renderer struct before including this file!
14+#endif
15+
16+static void begin_render(MyRenderer *renderer, DiagramData *data);
17+static void end_render(MyRenderer *renderer);
18+static void set_linewidth(MyRenderer *renderer, real linewidth);
19+static void set_linecaps(MyRenderer *renderer, LineCaps mode);
20+static void set_linejoin(MyRenderer *renderer, LineJoin mode);
21+static void set_linestyle(MyRenderer *renderer, LineStyle mode);
22+static void set_dashlength(MyRenderer *renderer, real length);
23+static void set_fillstyle(MyRenderer *renderer, FillStyle mode);
24+static void set_font(MyRenderer *renderer, Font *font, real height);
25+static void draw_line(MyRenderer *renderer,
26+ Point *start, Point *end,
27+ Color *line_colour);
28+static void draw_polyline(MyRenderer *renderer,
29+ Point *points, int num_points,
30+ Color *line_colour);
31+static void draw_polygon(MyRenderer *renderer,
32+ Point *points, int num_points,
33+ Color *line_colour);
34+static void fill_polygon(MyRenderer *renderer,
35+ Point *points, int num_points,
36+ Color *line_colour);
37+static void draw_rect(MyRenderer *renderer,
38+ Point *ul_corner, Point *lr_corner,
39+ Color *colour);
40+static void fill_rect(MyRenderer *renderer,
41+ Point *ul_corner, Point *lr_corner,
42+ Color *colour);
43+static void draw_arc(MyRenderer *renderer,
44+ Point *center,
45+ real width, real height,
46+ real angle1, real angle2,
47+ Color *colour);
48+static void fill_arc(MyRenderer *renderer,
49+ Point *center,
50+ real width, real height,
51+ real angle1, real angle2,
52+ Color *colour);
53+static void draw_ellipse(MyRenderer *renderer,
54+ Point *center,
55+ real width, real height,
56+ Color *colour);
57+static void fill_ellipse(MyRenderer *renderer,
58+ Point *center,
59+ real width, real height,
60+ Color *colour);
61+static void draw_bezier(MyRenderer *renderer,
62+ BezPoint *points,
63+ int numpoints,
64+ Color *colour);
65+static void fill_bezier(MyRenderer *renderer,
66+ BezPoint *points, /* Last point must be same as first point */
67+ int numpoints,
68+ Color *colour);
69+static void draw_string(MyRenderer *renderer,
70+ const char *text,
71+ Point *pos, Alignment alignment,
72+ Color *colour);
73+static void draw_image(MyRenderer *renderer,
74+ Point *point,
75+ real width, real height,
76+ DiaImage image);
77+
78+static RenderOps MyRenderOps = {
79+ (BeginRenderFunc) begin_render,
80+ (EndRenderFunc) end_render,
81+
82+ (SetLineWidthFunc) set_linewidth,
83+ (SetLineCapsFunc) set_linecaps,
84+ (SetLineJoinFunc) set_linejoin,
85+ (SetLineStyleFunc) set_linestyle,
86+ (SetDashLengthFunc) set_dashlength,
87+ (SetFillStyleFunc) set_fillstyle,
88+ (SetFontFunc) set_font,
89+
90+ (DrawLineFunc) draw_line,
91+ (DrawPolyLineFunc) draw_polyline,
92+
93+ (DrawPolygonFunc) draw_polygon,
94+ (FillPolygonFunc) fill_polygon,
95+
96+ (DrawRectangleFunc) draw_rect,
97+ (FillRectangleFunc) fill_rect,
98+
99+ (DrawArcFunc) draw_arc,
100+ (FillArcFunc) fill_arc,
101+
102+ (DrawEllipseFunc) draw_ellipse,
103+ (FillEllipseFunc) fill_ellipse,
104+
105+ (DrawBezierFunc) draw_bezier,
106+ (FillBezierFunc) fill_bezier,
107+
108+ (DrawStringFunc) draw_string,
109+
110+ (DrawImageFunc) draw_image,
111+};
112+
113+/* Draw an ellipse approximation consisting out of
114+ * four arcs.
115+ */
116+void
117+renderer_draw_ellipse_by_arc(
118+ MyRenderer *renderer,
119+ Point *center,
120+ real width, real height,
121+ Color *colour)
122+{
123+ real a, b, e, d, alpha, c, x, y;
124+ real g, gamma, r;
125+ Point pt;
126+ real angle;
127+
128+ a = width / 2;
129+ b = height / 2;
130+ e = sqrt(a*a - b*b);
131+
132+ alpha = 0.25*M_PI - asin((e/a) * sin(0.75*M_PI));
133+ d = 2*a*sin(alpha);
134+
135+ c = (sin(0.25*M_PI) * (2*e + d)) / sin(0.75*M_PI - alpha);
136+
137+ y = c * sin (alpha);
138+ x = c * cos (alpha) - e;
139+
140+ /* draw arcs */
141+ g = sqrt((a-x)*(a-x) + y*y);
142+ gamma = acos((a-x)/g);
143+ r = (sin(gamma) * g) / sin(M_PI-2*gamma);
144+
145+ pt.y = center->y;
146+ angle = (180 * (M_PI-2*gamma)) / M_PI;
147+ pt.x = center->x + a - r; /* right */
148+ draw_arc(renderer, &pt, 2*r, 2*r, 360-angle, angle, colour);
149+ pt.x = center->x - a + r; /* left */
150+ draw_arc(renderer, &pt, 2*r, 2*r, 180-angle, 180+angle, colour);
151+
152+
153+ g = sqrt((b-y)*(b-y) + x*x);
154+ gamma = acos((b-y)/g);
155+ r = (sin(gamma) * g) / sin(M_PI-2*gamma);
156+
157+ pt.x = center->x;
158+ angle = (180 * (M_PI-2*gamma)) / M_PI;
159+ pt.y = center->y - b + r; /* top */
160+ draw_arc(renderer, &pt, 2*r, 2*r, 90-angle, 90+angle, colour);
161+ pt.y = center->y + b - r; /* bottom */
162+ draw_arc(renderer, &pt, 2*r, 2*r, 270-angle, 270+angle, colour);
163163 }
\ No newline at end of file
--- /dev/null
+++ b/plug-ins/wmf/.cvsignore
@@ -0,0 +1,9 @@
1+.cvsignore
2+.deps
3+.libs
4+Makefile
5+Makefile.in
6+*.lo
7+*.la
8+*.pyc
9+
--- a/plug-ins/wmf/wmf.cpp
+++ b/plug-ins/wmf/wmf.cpp
@@ -1,788 +1,788 @@
1-/* Dia -- an diagram creation/manipulation program
2- * Copyright (C) 1998 Alexander Larsson
3- *
4- * wmf.cpp -- Windows Metafile export plugin for dia
5- * Copyright (C) 2000, Hans Breuer, <Hans@Breuer.Org>
6- * based on dummy plug-in.
7- *
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.
12- *
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.
17- *
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.
21- */
22-
23-#include <stdio.h>
24-#include <string.h>
25-#include <math.h>
26-#include <glib.h>
27-
28-#ifdef __cplusplus
29-extern "C" {
30-#endif
31-#include "config.h"
32-#include "intl.h"
33-#include "message.h"
34-#include "geometry.h"
35-#include "render.h"
36-#include "filter.h"
37-#include "plug-ins.h"
38-
39-#ifdef __cplusplus
40-}
41-#endif
42-
43-namespace W32 {
44-// at least Rectangle conflicts ...
45-#include <windows.h>
46-}
47-
48-/* force linking with gdi32 */
49-#pragma comment( lib, "gdi32" )
50-
51-
52-// #define SAVE_EMF
53-
54-/* --- the renderer --- */
55-#define MY_RENDERER_NAME "WMF"
56-
57-typedef struct _MyRenderer MyRenderer;
58-struct _MyRenderer {
59- Renderer renderer;
60-
61- W32::HDC hFileDC;
62- gchar* sFileName;
63-
64- /* if applicable everything is scaled to 0.01 mm */
65- int nLineWidth; /* need to cache these, because ... */
66- int fnPenStyle; /* ... both are needed at the same time */
67- W32::HPEN hPen; /* ugliness by concept, see DonePen() */
68-
69- W32::HFONT hFont;
70-};
71-
72-/* include function declares and render object "vtable" */
73-#include "../renderer.inc"
74-
75-/*
76- * helper macros
77- */
78-#define W32COLOR(c) \
79- 0xff * c->red + \
80- ((unsigned char)(0xff * c->green)) * 256 + \
81- ((unsigned char)(0xff * c->blue)) * 65536;
82-
83-#define WMF_SCALE 100.0
84-#define SC(a) ((a)*WMF_SCALE)
85-
86-/*
87- * helper functions
88- */
89-static W32::HGDIOBJ
90-UsePen(MyRenderer* renderer, Color* colour)
91-{
92- W32::HPEN hOldPen;
93- W32::COLORREF rgb = W32COLOR(colour);
94-
95- renderer->hPen = W32::CreatePen( renderer->fnPenStyle,
96- renderer->nLineWidth,
97- rgb);
98- hOldPen = W32::SelectObject(renderer->hFileDC, renderer->hPen);
99- return hOldPen;
100-}
101-
102-static void
103-DonePen(MyRenderer* renderer, W32::HPEN hPen)
104-{
105- /* restore the OLD one ... */
106- if (hPen) W32::SelectObject(renderer->hFileDC, hPen);
107- /* ... before deleting the last active */
108- if (renderer->hPen)
109- {
110- W32::DeleteObject(renderer->hPen);
111- renderer->hPen = NULL;
112- }
113-}
114-
115-#define DIAG_NOTE my_log
116-void
117-my_log(MyRenderer* renderer, char* format, ...)
118-{
119- gchar *string;
120- va_list args;
121-
122- g_return_if_fail (format != NULL);
123-
124- va_start (args, format);
125- string = g_strdup_vprintf (format, args);
126- va_end (args);
127-
128- //fprintf(renderer->file, string);
129- g_print(string);
130-
131- g_free(string);
132-}
133-
134-/*
135- * renderer interface implementation
136- */
137-static void
138-begin_render(MyRenderer *renderer, DiagramData *data)
139-{
140- DIAG_NOTE(renderer, "begin_render\n");
141-
142- /* make unfilled the default */
143- W32::SelectObject(renderer->hFileDC,
144- W32::GetStockObject (HOLLOW_BRUSH) );
145-}
146-
147-static void
148-end_render(MyRenderer *renderer)
149-{
150- W32::HENHMETAFILE hEmf;
151- W32::UINT nSize;
152- W32::BYTE* pData = NULL;
153- FILE* f;
154-
155- DIAG_NOTE(renderer, "end_render\n");
156- hEmf = W32::CloseEnhMetaFile(renderer->hFileDC);
157-
158-#ifndef SAVE_EMF
159- /* get size */
160- nSize = W32::GetWinMetaFileBits(hEmf, 0, NULL, MM_ANISOTROPIC, W32::GetDC(NULL));
161- pData = g_new(W32::BYTE, nSize);
162- /* get data */
163- nSize = W32::GetWinMetaFileBits(hEmf, nSize, pData, MM_ANISOTROPIC, W32::GetDC(NULL));
164-
165- /* write file */
166- f = fopen(renderer->sFileName, "wb");
167- fwrite(pData,1,nSize,f);
168- fclose(f);
169-
170- g_free(pData);
171-#endif
172- g_free(renderer->sFileName);
173-
174- if (hEmf)
175- W32::DeleteEnhMetaFile(hEmf);
176- if (renderer->hFont)
177- W32::DeleteObject(renderer->hFont);
178-}
179-
180-static void
181-set_linewidth(MyRenderer *renderer, real linewidth)
182-{
183- DIAG_NOTE(renderer, "set_linewidth %f\n", linewidth);
184-
185- renderer->nLineWidth = SC(linewidth);
186-}
187-
188-static void
189-set_linecaps(MyRenderer *renderer, LineCaps mode)
190-{
191- DIAG_NOTE(renderer, "set_linecaps %d\n", mode);
192-
193- switch(mode) {
194- case LINECAPS_BUTT:
195- break;
196- case LINECAPS_ROUND:
197- break;
198- case LINECAPS_PROJECTING:
199- break;
200- default:
201- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
202- }
203-}
204-
205-static void
206-set_linejoin(MyRenderer *renderer, LineJoin mode)
207-{
208- DIAG_NOTE(renderer, "set_join %d\n", mode);
209-
210- switch(mode) {
211- case LINEJOIN_MITER:
212- break;
213- case LINEJOIN_ROUND:
214- break;
215- case LINEJOIN_BEVEL:
216- break;
217- default:
218- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
219- }
220-}
221-
222-static void
223-set_linestyle(MyRenderer *renderer, LineStyle mode)
224-{
225- DIAG_NOTE(renderer, "set_linestyle %d\n", mode);
226-
227- /* line type */
228- switch (mode) {
229- case LINESTYLE_SOLID:
230- renderer->fnPenStyle = PS_SOLID;
231- break;
232- case LINESTYLE_DASHED:
233- renderer->fnPenStyle = PS_DASH;
234- break;
235- case LINESTYLE_DASH_DOT:
236- renderer->fnPenStyle = PS_DASHDOT;
237- break;
238- case LINESTYLE_DASH_DOT_DOT:
239- renderer->fnPenStyle = PS_DASHDOTDOT;
240- break;
241- case LINESTYLE_DOTTED:
242- renderer->fnPenStyle = PS_DOT;
243- break;
244- default:
245- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
246- }
247-}
248-
249-static void
250-set_dashlength(MyRenderer *renderer, real length)
251-{
252- DIAG_NOTE(renderer, "set_dashlength %f\n", length);
253-
254- /* dot = 20% of len */
255-}
256-
257-static void
258-set_fillstyle(MyRenderer *renderer, FillStyle mode)
259-{
260- DIAG_NOTE(renderer, "set_fillstyle %d\n", mode);
261-
262- switch(mode) {
263- case FILLSTYLE_SOLID:
264- break;
265- default:
266- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
267- }
268-}
269-
270-static void
271-set_font(MyRenderer *renderer, Font *font, real height)
272-{
273- W32::LPCTSTR sFace;
274- W32::DWORD dwItalic = 0;
275- W32::DWORD dwWeight = FW_DONTCARE;
276-
277- DIAG_NOTE(renderer, "set_font %s %f\n", font->name, height);
278- if (renderer->hFont)
279- W32::DeleteObject(renderer->hFont);
280-
281- /* An ugly hack to map font names. It has to be
282- * changed if Dia's fonts ever get changed.
283- * See: lib/font.c
284- *
285- * Wouldn't it be better to provide this info in
286- * a Font field ?
287- */
288- if (strstr(font->name, "Courier"))
289- sFace = "Courier New";
290- else if (strstr(font->name, "Times"))
291- sFace = "Times New Roman";
292- else
293- sFace = "Arial";
294-
295- dwItalic = !!( strstr(font->name, "Italic")
296- || strstr(font->name, "Oblique")); //?
297- if (strstr(font->name, "Bold"))
298- dwWeight = FW_BOLD;
299- else if (strstr(font->name, "Demi"))
300- dwWeight = FW_DEMIBOLD;
301- else if (strstr(font->name, "Light"))
302- dwWeight = FW_LIGHT;
303-
304- renderer->hFont = (W32::HFONT)W32::CreateFont(
305- -(height * WMF_SCALE), // logical height of font
306- 0, // logical average character width
307- 0, // angle of escapement
308- 0, // base-line orientation angle
309- dwWeight, // font weight
310- dwItalic, // italic attribute flag
311- 0, // underline attribute flag
312- 0, // strikeout attribute flag
313- ANSI_CHARSET, // character set identifier
314- OUT_TT_PRECIS, // output precision
315- CLIP_DEFAULT_PRECIS, // clipping precision
316- PROOF_QUALITY, // output quality
317- DEFAULT_PITCH, // pitch and family
318- sFace); // pointer to typeface name string
319-}
320-
321-static void
322-draw_line(MyRenderer *renderer,
323- Point *start, Point *end,
324- Color *line_colour)
325-{
326- W32::HGDIOBJ hPen;
327-
328- DIAG_NOTE(renderer, "draw_line %f,%f -> %f, %f\n",
329- start->x, start->y, end->x, end->y);
330-
331- hPen = UsePen(renderer, line_colour);
332-
333- W32::MoveToEx(renderer->hFileDC, SC(start->x), SC(start->y), NULL);
334- W32::LineTo(renderer->hFileDC, SC(end->x), SC(end->y));
335-
336- DonePen(renderer, hPen);
337-}
338-
339-static void
340-draw_polyline(MyRenderer *renderer,
341- Point *points, int num_points,
342- Color *line_colour)
343-{
344- W32::HGDIOBJ hPen;
345- W32::POINT* pts;
346- int i;
347-
348- DIAG_NOTE(renderer, "draw_polyline n:%d %f,%f ...\n",
349- num_points, points->x, points->y);
350-
351- if (num_points < 2)
352- return;
353- pts = g_new (W32::POINT, num_points+1);
354- for (i = 0; i < num_points; i++)
355- {
356- pts[i].x = SC(points[i].x);
357- pts[i].y = SC(points[i].y);
358- }
359-
360- hPen = UsePen(renderer, line_colour);
361- W32::Polyline(renderer->hFileDC, pts, num_points);
362- DonePen(renderer, hPen);
363-
364- g_free(pts);
365-}
366-
367-static void
368-draw_polygon(MyRenderer *renderer,
369- Point *points, int num_points,
370- Color *line_colour)
371-{
372- W32::HGDIOBJ hPen;
373- W32::POINT* pts;
374- int i;
375-
376- DIAG_NOTE(renderer, "draw_polygon n:%d %f,%f ...\n",
377- num_points, points->x, points->y);
378-
379- if (num_points < 2)
380- return;
381- pts = g_new (W32::POINT, num_points+1);
382- for (i = 0; i < num_points; i++)
383- {
384- pts[i].x = SC(points[i].x);
385- pts[i].y = SC(points[i].y);
386- }
387-
388- hPen = UsePen(renderer, line_colour);
389-
390- W32::Polygon(renderer->hFileDC, pts, num_points);
391-
392- DonePen(renderer, hPen);
393-
394- g_free(pts);
395-}
396-
397-static void
398-fill_polygon(MyRenderer *renderer,
399- Point *points, int num_points,
400- Color *colour)
401-{
402- W32::HBRUSH hBrush, hBrOld;
403- W32::COLORREF rgb = W32COLOR(colour);
404-
405- DIAG_NOTE(renderer, "fill_polygon n:%d %f,%f ...\n",
406- num_points, points->x, points->y);
407-
408- hBrush = W32::CreateSolidBrush(rgb);
409- hBrOld = W32::SelectObject(renderer->hFileDC, hBrush);
410-
411- draw_polygon(renderer, points, num_points, colour);
412-
413- W32::SelectObject(renderer->hFileDC,
414- W32::GetStockObject (HOLLOW_BRUSH) );
415- W32::DeleteObject(hBrush);
416-}
417-
418-static void
419-draw_rect(MyRenderer *renderer,
420- Point *ul_corner, Point *lr_corner,
421- Color *colour)
422-{
423- W32::HGDIOBJ hPen;
424-
425- DIAG_NOTE(renderer, "draw_rect %f,%f -> %f,%f\n",
426- ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
427-
428- hPen = UsePen(renderer, colour);
429-
430- W32::Rectangle(renderer->hFileDC,
431- SC(ul_corner->x), SC(ul_corner->y),
432- SC(lr_corner->x), SC(lr_corner->y));
433-
434- DonePen(renderer, hPen);
435-}
436-
437-static void
438-fill_rect(MyRenderer *renderer,
439- Point *ul_corner, Point *lr_corner,
440- Color *colour)
441-{
442- W32::HGDIOBJ hBrush, hBrOld;
443- W32::COLORREF rgb = W32COLOR(colour);
444-
445- DIAG_NOTE(renderer, "fill_rect %f,%f -> %f,%f\n",
446- ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
447-
448- hBrush = W32::CreateSolidBrush(rgb);
449- hBrOld = W32::SelectObject(renderer->hFileDC, hBrush);
450-
451- draw_rect(renderer, ul_corner, lr_corner, colour);
452-
453- W32::SelectObject(renderer->hFileDC,
454- W32::GetStockObject (HOLLOW_BRUSH) );
455- W32::DeleteObject(hBrush);
456-}
457-
458-static void
459-draw_arc(MyRenderer *renderer,
460- Point *center,
461- real width, real height,
462- real angle1, real angle2,
463- Color *colour)
464-{
465- W32::HGDIOBJ hPen;
466- W32::POINT ptStart, ptEnd;
467-
468- DIAG_NOTE(renderer, "draw_arc %fx%f <%f,<%f @%f,%f\n",
469- width, height, angle1, angle2, center->x, center->y);
470-
471- hPen = UsePen(renderer, colour);
472-
473- /* calculate start and end points of arc */
474- ptStart.x = SC(center->x + (width / 2.0) * cos((M_PI / 180.0) * angle1));
475- ptStart.y = SC(center->y - (height / 2.0) * sin((M_PI / 180.0) * angle1));
476- ptEnd.x = SC(center->x + (width / 2.0) * cos((M_PI / 180.0) * angle2));
477- ptEnd.y = SC(center->y - (height / 2.0) * sin((M_PI / 180.0) * angle2));
478-
479- W32::MoveToEx(renderer->hFileDC, ptStart.x, ptStart.y, NULL);
480- W32::Arc(renderer->hFileDC,
481- SC(center->x - width / 2), /* bbox corners */
482- SC(center->y - height / 2),
483- SC(center->x + width / 2),
484- SC(center->y + height / 2),
485- ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
486-
487- DonePen(renderer, hPen);
488-}
489-
490-static void
491-fill_arc(MyRenderer *renderer,
492- Point *center,
493- real width, real height,
494- real angle1, real angle2,
495- Color *colour)
496-{
497- W32::HGDIOBJ hPen;
498-
499- DIAG_NOTE(renderer, "fill_arc %fx%f <%f,<%f @%f,%f\n",
500- width, height, angle1, angle2, center->x, center->y);
501-
502- hPen = UsePen(renderer, colour);
503-
504- DonePen(renderer, hPen);
505-}
506-
507-static void
508-draw_ellipse(MyRenderer *renderer,
509- Point *center,
510- real width, real height,
511- Color *colour)
512-{
513- W32::HGDIOBJ hPen;
514-
515- DIAG_NOTE(renderer, "draw_ellipse %fx%f @ %f,%f\n",
516- width, height, center->x, center->y);
517-
518- hPen = UsePen(renderer, colour);
519-
520- W32::Ellipse(renderer->hFileDC,
521- SC(center->x - width / 2), /* bbox corners */
522- SC(center->y - height / 2),
523- SC(center->x + width / 2),
524- SC(center->y + height / 2));
525-
526- DonePen(renderer, hPen);
527-}
528-
529-static void
530-fill_ellipse(MyRenderer *renderer,
531- Point *center,
532- real width, real height,
533- Color *colour)
534-{
535- W32::HGDIOBJ hPen;
536- W32::HGDIOBJ hBrush, hBrOld;
537- W32::COLORREF rgb = W32COLOR(colour);
538-
539- DIAG_NOTE(renderer, "fill_ellipse %fx%f @ %f,%f\n",
540- width, height, center->x, center->y);
541-
542- hBrush = W32::CreateSolidBrush(rgb);
543- hBrOld = W32::SelectObject(renderer->hFileDC, hBrush);
544-
545- draw_ellipse(renderer, center, width, height, colour);
546-
547- W32::SelectObject(renderer->hFileDC,
548- W32::GetStockObject (HOLLOW_BRUSH) );
549- W32::DeleteObject(hBrush);
550-}
551-
552-static void
553-draw_bezier(MyRenderer *renderer,
554- BezPoint *points,
555- int numpoints,
556- Color *colour)
557-{
558- W32::HGDIOBJ hPen;
559- W32::POINT * pts;
560- int i;
561-
562- DIAG_NOTE(renderer, "draw_bezier n:%d %fx%f ...\n",
563- numpoints, points->p1.x, points->p1.y);
564-
565- pts = g_new(W32::POINT, (numpoints-1) * 3 + 1);
566-
567- pts[0].x = SC(points[0].p1.x);
568- pts[0].y = SC(points[0].p1.y);
569-
570- for (i = 1; i < numpoints; i++)
571- {
572- switch(points[i].type)
573- {
574- case _BezPoint::BEZ_MOVE_TO:
575- g_warning("only first BezPoint can be a BEZ_MOVE_TO");
576- break;
577- case _BezPoint::BEZ_LINE_TO:
578- /* everyhing the same ?*/
579- pts[i*3-2].x = pts[i*3-1].x =
580- pts[i*3 ].x = SC(points[i].p1.x);
581- pts[i*3-2].y = pts[i*3-1].y =
582- pts[i*3 ].y = SC(points[i].p1.y);
583- break;
584- case _BezPoint::BEZ_CURVE_TO:
585- /* control points */
586- pts[i*3-2].x = SC(points[i].p1.x);
587- pts[i*3-2].y = SC(points[i].p1.y);
588- pts[i*3-1].x = SC(points[i].p2.x);
589- pts[i*3-1].y = SC(points[i].p2.y);
590- /* end point */
591- pts[i*3 ].x = SC(points[i].p3.x);
592- pts[i*3 ].y = SC(points[i].p3.y);
593- break;
594- default:
595- break;
596- }
597- }
598-
599- hPen = UsePen(renderer, colour);
600-
601- W32::PolyBezier(renderer->hFileDC,
602- pts, (numpoints-1)*3+1);
603-
604- DonePen(renderer, hPen);
605-
606- g_free(pts);
607-}
608-
609-static void
610-fill_bezier(MyRenderer *renderer,
611- BezPoint *points, /* Last point must be same as first point */
612- int numpoints,
613- Color *colour)
614-{
615- W32::HGDIOBJ hPen;
616-
617- DIAG_NOTE(renderer, "fill_bezier n:%d %fx%f ...\n",
618- numpoints, points->p1.x, points->p1.y);
619-}
620-
621-static void
622-draw_string(MyRenderer *renderer,
623- const char *text,
624- Point *pos, Alignment alignment,
625- Color *colour)
626-{
627- int len;
628- W32::HGDIOBJ hOld;
629-
630- DIAG_NOTE(renderer, "draw_string %f,%f %s\n",
631- pos->x, pos->y, text);
632-
633- switch (alignment) {
634- case ALIGN_LEFT:
635- W32::SetTextAlign(renderer->hFileDC, TA_LEFT+TA_BASELINE);
636- break;
637- case ALIGN_CENTER:
638- W32::SetTextAlign(renderer->hFileDC, TA_CENTER+TA_BASELINE);
639- break;
640- case ALIGN_RIGHT:
641- W32::SetTextAlign(renderer->hFileDC, TA_RIGHT+TA_BASELINE);
642- break;
643- }
644- /* work out size of first chunk of text */
645- len = strlen(text);
646-
647- hOld = W32::SelectObject(renderer->hFileDC, renderer->hFont);
648- W32::TextOut(renderer->hFileDC,
649- SC(pos->x), SC(pos->y),
650- text, len);
651- W32::SelectObject(renderer->hFileDC, hOld);
652-}
653-
654-static void
655-draw_image(MyRenderer *renderer,
656- Point *point,
657- real width, real height,
658- DiaImage image)
659-{
660- W32::HBITMAP hBmp;
661- int iWidth, iHeight;
662- unsigned char* pData = NULL;
663-
664- DIAG_NOTE(renderer, "draw_image %fx%f @%f,%f\n",
665- width, height, point->x, point->y);
666-
667- iWidth = dia_image_width(image);
668- iHeight = dia_image_height(image);
669-
670- if ((dia_image_width(image)*3) % 4)
671- {
672- /* transform data to be DWORD aligned */
673- int x, y;
674- const unsigned char* pIn = NULL;
675- unsigned char* pOut = NULL;
676-
677- pOut = pData = g_new(unsigned char, ((((iWidth*3-1)/4)+1)*4)*iHeight);
678-
679- pIn = dia_image_rgb_data(image);
680- for (y = 0; y < iHeight; y++)
681- {
682- for (x = 0; x < iWidth; x++)
683- {
684- *pOut++ = *pIn++;
685- *pOut++ = *pIn++;
686- *pOut++ = *pIn++;
687- }
688- pOut += (4 - (iWidth*3)%4);
689- }
690-
691- hBmp = W32::CreateBitmap ( iWidth, iHeight, 1, 24, pData);
692- }
693- else
694- {
695- hBmp = W32::CreateBitmap (
696- dia_image_width(image), dia_image_height(image),
697- 1, 24, dia_image_rgb_data(image));
698- }
699-
700- W32::SelectObject(renderer->hFileDC, hBmp);
701- //Hack to get SRCCOPY out of namespace W32
702-# ifndef DWORD
703-# define DWORD unsigned long
704-# endif
705- W32::BitBlt(renderer->hFileDC, // destination
706- SC(point->x), SC(point->y), SC(width), SC(height),
707- renderer->hFileDC, // source
708- 0, 0, SRCCOPY);
709-
710- W32::DeleteObject(hBmp);
711- if (pData)
712- g_free(pData);
713-}
714-
715-static void
716-export_data(DiagramData *data, const gchar *filename, const gchar *diafilename)
717-{
718- MyRenderer *renderer;
719- W32::HDC file;
720- Rectangle *extent;
721- gint len;
722-
723- W32::RECT bbox;
724-
725- bbox.top = SC(data->extents.top);
726- bbox.left = SC(data->extents.left);
727- bbox.right = SC(data->extents.right);
728- bbox.bottom = SC(data->extents.bottom);
729-
730- file = (W32::HDC)W32::CreateEnhMetaFile(
731- W32::GetDC(NULL), // handle to a reference device context
732-#ifdef SAVE_EMF
733- filename, // pointer to a filename string
734-#else
735- NULL, // in memory
736-#endif
737- &bbox, // pointer to a bounding rectangle
738- "Dia\0Diagram\0"); // pointer to an optional description string
739-
740- if (file == NULL) {
741- message_error(_("Couldn't open: '%s' for writing.\n"), filename);
742- return;
743- }
744-
745- renderer = g_new(MyRenderer, 1);
746- renderer->renderer.ops = &MyRenderOps;
747- renderer->renderer.is_interactive = 0;
748- renderer->renderer.interactive_ops = NULL;
749-
750- renderer->hFileDC = file;
751- renderer->sFileName = g_strdup(filename);
752-
753- extent = &data->extents;
754-
755- /* write extents */
756- DIAG_NOTE(renderer, "export_data extents %f,%f -> %f,%f\n",
757- extent->left, extent->top, extent->right, extent->bottom);
758-
759-
760- data_render(data, (Renderer *)renderer, NULL, NULL, NULL);
761-
762- g_free(renderer);
763-}
764-
765-static const gchar *extensions[] = { "wmf", NULL };
766-static DiaExportFilter my_export_filter = {
767- N_("Windows Meta File"),
768- extensions,
769- export_data
770-};
771-
772-
773-/* --- dia plug-in interface --- */
774-
775-DIA_PLUGIN_CHECK_INIT
776-
777-PluginInitResult
778-dia_plugin_init(PluginInfo *info)
779-{
780- if (!dia_plugin_info_init(info, "WMF",
781- _("WMF export filter"),
782- NULL, NULL))
783- return DIA_PLUGIN_INIT_ERROR;
784-
785- filter_register_export(&my_export_filter);
786-
787- return DIA_PLUGIN_INIT_OK;
788-}
1+/* Dia -- an diagram creation/manipulation program
2+ * Copyright (C) 1998 Alexander Larsson
3+ *
4+ * wmf.cpp -- Windows Metafile export plugin for dia
5+ * Copyright (C) 2000, Hans Breuer, <Hans@Breuer.Org>
6+ * based on dummy plug-in.
7+ *
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.
12+ *
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.
17+ *
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.
21+ */
22+
23+#include <stdio.h>
24+#include <string.h>
25+#include <math.h>
26+#include <glib.h>
27+
28+#ifdef __cplusplus
29+extern "C" {
30+#endif
31+#include "config.h"
32+#include "intl.h"
33+#include "message.h"
34+#include "geometry.h"
35+#include "render.h"
36+#include "filter.h"
37+#include "plug-ins.h"
38+
39+#ifdef __cplusplus
40+}
41+#endif
42+
43+namespace W32 {
44+// at least Rectangle conflicts ...
45+#include <windows.h>
46+}
47+
48+/* force linking with gdi32 */
49+#pragma comment( lib, "gdi32" )
50+
51+
52+// #define SAVE_EMF
53+
54+/* --- the renderer --- */
55+#define MY_RENDERER_NAME "WMF"
56+
57+typedef struct _MyRenderer MyRenderer;
58+struct _MyRenderer {
59+ Renderer renderer;
60+
61+ W32::HDC hFileDC;
62+ gchar* sFileName;
63+
64+ /* if applicable everything is scaled to 0.01 mm */
65+ int nLineWidth; /* need to cache these, because ... */
66+ int fnPenStyle; /* ... both are needed at the same time */
67+ W32::HPEN hPen; /* ugliness by concept, see DonePen() */
68+
69+ W32::HFONT hFont;
70+};
71+
72+/* include function declares and render object "vtable" */
73+#include "../renderer.inc"
74+
75+/*
76+ * helper macros
77+ */
78+#define W32COLOR(c) \
79+ 0xff * c->red + \
80+ ((unsigned char)(0xff * c->green)) * 256 + \
81+ ((unsigned char)(0xff * c->blue)) * 65536;
82+
83+#define WMF_SCALE 100.0
84+#define SC(a) ((a)*WMF_SCALE)
85+
86+/*
87+ * helper functions
88+ */
89+static W32::HGDIOBJ
90+UsePen(MyRenderer* renderer, Color* colour)
91+{
92+ W32::HPEN hOldPen;
93+ W32::COLORREF rgb = W32COLOR(colour);
94+
95+ renderer->hPen = W32::CreatePen( renderer->fnPenStyle,
96+ renderer->nLineWidth,
97+ rgb);
98+ hOldPen = W32::SelectObject(renderer->hFileDC, renderer->hPen);
99+ return hOldPen;
100+}
101+
102+static void
103+DonePen(MyRenderer* renderer, W32::HPEN hPen)
104+{
105+ /* restore the OLD one ... */
106+ if (hPen) W32::SelectObject(renderer->hFileDC, hPen);
107+ /* ... before deleting the last active */
108+ if (renderer->hPen)
109+ {
110+ W32::DeleteObject(renderer->hPen);
111+ renderer->hPen = NULL;
112+ }
113+}
114+
115+#define DIAG_NOTE my_log
116+void
117+my_log(MyRenderer* renderer, char* format, ...)
118+{
119+ gchar *string;
120+ va_list args;
121+
122+ g_return_if_fail (format != NULL);
123+
124+ va_start (args, format);
125+ string = g_strdup_vprintf (format, args);
126+ va_end (args);
127+
128+ //fprintf(renderer->file, string);
129+ g_print(string);
130+
131+ g_free(string);
132+}
133+
134+/*
135+ * renderer interface implementation
136+ */
137+static void
138+begin_render(MyRenderer *renderer, DiagramData *data)
139+{
140+ DIAG_NOTE(renderer, "begin_render\n");
141+
142+ /* make unfilled the default */
143+ W32::SelectObject(renderer->hFileDC,
144+ W32::GetStockObject (HOLLOW_BRUSH) );
145+}
146+
147+static void
148+end_render(MyRenderer *renderer)
149+{
150+ W32::HENHMETAFILE hEmf;
151+ W32::UINT nSize;
152+ W32::BYTE* pData = NULL;
153+ FILE* f;
154+
155+ DIAG_NOTE(renderer, "end_render\n");
156+ hEmf = W32::CloseEnhMetaFile(renderer->hFileDC);
157+
158+#ifndef SAVE_EMF
159+ /* get size */
160+ nSize = W32::GetWinMetaFileBits(hEmf, 0, NULL, MM_ANISOTROPIC, W32::GetDC(NULL));
161+ pData = g_new(W32::BYTE, nSize);
162+ /* get data */
163+ nSize = W32::GetWinMetaFileBits(hEmf, nSize, pData, MM_ANISOTROPIC, W32::GetDC(NULL));
164+
165+ /* write file */
166+ f = fopen(renderer->sFileName, "wb");
167+ fwrite(pData,1,nSize,f);
168+ fclose(f);
169+
170+ g_free(pData);
171+#endif
172+ g_free(renderer->sFileName);
173+
174+ if (hEmf)
175+ W32::DeleteEnhMetaFile(hEmf);
176+ if (renderer->hFont)
177+ W32::DeleteObject(renderer->hFont);
178+}
179+
180+static void
181+set_linewidth(MyRenderer *renderer, real linewidth)
182+{
183+ DIAG_NOTE(renderer, "set_linewidth %f\n", linewidth);
184+
185+ renderer->nLineWidth = SC(linewidth);
186+}
187+
188+static void
189+set_linecaps(MyRenderer *renderer, LineCaps mode)
190+{
191+ DIAG_NOTE(renderer, "set_linecaps %d\n", mode);
192+
193+ switch(mode) {
194+ case LINECAPS_BUTT:
195+ break;
196+ case LINECAPS_ROUND:
197+ break;
198+ case LINECAPS_PROJECTING:
199+ break;
200+ default:
201+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
202+ }
203+}
204+
205+static void
206+set_linejoin(MyRenderer *renderer, LineJoin mode)
207+{
208+ DIAG_NOTE(renderer, "set_join %d\n", mode);
209+
210+ switch(mode) {
211+ case LINEJOIN_MITER:
212+ break;
213+ case LINEJOIN_ROUND:
214+ break;
215+ case LINEJOIN_BEVEL:
216+ break;
217+ default:
218+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
219+ }
220+}
221+
222+static void
223+set_linestyle(MyRenderer *renderer, LineStyle mode)
224+{
225+ DIAG_NOTE(renderer, "set_linestyle %d\n", mode);
226+
227+ /* line type */
228+ switch (mode) {
229+ case LINESTYLE_SOLID:
230+ renderer->fnPenStyle = PS_SOLID;
231+ break;
232+ case LINESTYLE_DASHED:
233+ renderer->fnPenStyle = PS_DASH;
234+ break;
235+ case LINESTYLE_DASH_DOT:
236+ renderer->fnPenStyle = PS_DASHDOT;
237+ break;
238+ case LINESTYLE_DASH_DOT_DOT:
239+ renderer->fnPenStyle = PS_DASHDOTDOT;
240+ break;
241+ case LINESTYLE_DOTTED:
242+ renderer->fnPenStyle = PS_DOT;
243+ break;
244+ default:
245+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
246+ }
247+}
248+
249+static void
250+set_dashlength(MyRenderer *renderer, real length)
251+{
252+ DIAG_NOTE(renderer, "set_dashlength %f\n", length);
253+
254+ /* dot = 20% of len */
255+}
256+
257+static void
258+set_fillstyle(MyRenderer *renderer, FillStyle mode)
259+{
260+ DIAG_NOTE(renderer, "set_fillstyle %d\n", mode);
261+
262+ switch(mode) {
263+ case FILLSTYLE_SOLID:
264+ break;
265+ default:
266+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
267+ }
268+}
269+
270+static void
271+set_font(MyRenderer *renderer, Font *font, real height)
272+{
273+ W32::LPCTSTR sFace;
274+ W32::DWORD dwItalic = 0;
275+ W32::DWORD dwWeight = FW_DONTCARE;
276+
277+ DIAG_NOTE(renderer, "set_font %s %f\n", font->name, height);
278+ if (renderer->hFont)
279+ W32::DeleteObject(renderer->hFont);
280+
281+ /* An ugly hack to map font names. It has to be
282+ * changed if Dia's fonts ever get changed.
283+ * See: lib/font.c
284+ *
285+ * Wouldn't it be better to provide this info in
286+ * a Font field ?
287+ */
288+ if (strstr(font->name, "Courier"))
289+ sFace = "Courier New";
290+ else if (strstr(font->name, "Times"))
291+ sFace = "Times New Roman";
292+ else
293+ sFace = "Arial";
294+
295+ dwItalic = !!( strstr(font->name, "Italic")
296+ || strstr(font->name, "Oblique")); //?
297+ if (strstr(font->name, "Bold"))
298+ dwWeight = FW_BOLD;
299+ else if (strstr(font->name, "Demi"))
300+ dwWeight = FW_DEMIBOLD;
301+ else if (strstr(font->name, "Light"))
302+ dwWeight = FW_LIGHT;
303+
304+ renderer->hFont = (W32::HFONT)W32::CreateFont(
305+ -(height * WMF_SCALE), // logical height of font
306+ 0, // logical average character width
307+ 0, // angle of escapement
308+ 0, // base-line orientation angle
309+ dwWeight, // font weight
310+ dwItalic, // italic attribute flag
311+ 0, // underline attribute flag
312+ 0, // strikeout attribute flag
313+ ANSI_CHARSET, // character set identifier
314+ OUT_TT_PRECIS, // output precision
315+ CLIP_DEFAULT_PRECIS, // clipping precision
316+ PROOF_QUALITY, // output quality
317+ DEFAULT_PITCH, // pitch and family
318+ sFace); // pointer to typeface name string
319+}
320+
321+static void
322+draw_line(MyRenderer *renderer,
323+ Point *start, Point *end,
324+ Color *line_colour)
325+{
326+ W32::HGDIOBJ hPen;
327+
328+ DIAG_NOTE(renderer, "draw_line %f,%f -> %f, %f\n",
329+ start->x, start->y, end->x, end->y);
330+
331+ hPen = UsePen(renderer, line_colour);
332+
333+ W32::MoveToEx(renderer->hFileDC, SC(start->x), SC(start->y), NULL);
334+ W32::LineTo(renderer->hFileDC, SC(end->x), SC(end->y));
335+
336+ DonePen(renderer, hPen);
337+}
338+
339+static void
340+draw_polyline(MyRenderer *renderer,
341+ Point *points, int num_points,
342+ Color *line_colour)
343+{
344+ W32::HGDIOBJ hPen;
345+ W32::POINT* pts;
346+ int i;
347+
348+ DIAG_NOTE(renderer, "draw_polyline n:%d %f,%f ...\n",
349+ num_points, points->x, points->y);
350+
351+ if (num_points < 2)
352+ return;
353+ pts = g_new (W32::POINT, num_points+1);
354+ for (i = 0; i < num_points; i++)
355+ {
356+ pts[i].x = SC(points[i].x);
357+ pts[i].y = SC(points[i].y);
358+ }
359+
360+ hPen = UsePen(renderer, line_colour);
361+ W32::Polyline(renderer->hFileDC, pts, num_points);
362+ DonePen(renderer, hPen);
363+
364+ g_free(pts);
365+}
366+
367+static void
368+draw_polygon(MyRenderer *renderer,
369+ Point *points, int num_points,
370+ Color *line_colour)
371+{
372+ W32::HGDIOBJ hPen;
373+ W32::POINT* pts;
374+ int i;
375+
376+ DIAG_NOTE(renderer, "draw_polygon n:%d %f,%f ...\n",
377+ num_points, points->x, points->y);
378+
379+ if (num_points < 2)
380+ return;
381+ pts = g_new (W32::POINT, num_points+1);
382+ for (i = 0; i < num_points; i++)
383+ {
384+ pts[i].x = SC(points[i].x);
385+ pts[i].y = SC(points[i].y);
386+ }
387+
388+ hPen = UsePen(renderer, line_colour);
389+
390+ W32::Polygon(renderer->hFileDC, pts, num_points);
391+
392+ DonePen(renderer, hPen);
393+
394+ g_free(pts);
395+}
396+
397+static void
398+fill_polygon(MyRenderer *renderer,
399+ Point *points, int num_points,
400+ Color *colour)
401+{
402+ W32::HBRUSH hBrush, hBrOld;
403+ W32::COLORREF rgb = W32COLOR(colour);
404+
405+ DIAG_NOTE(renderer, "fill_polygon n:%d %f,%f ...\n",
406+ num_points, points->x, points->y);
407+
408+ hBrush = W32::CreateSolidBrush(rgb);
409+ hBrOld = W32::SelectObject(renderer->hFileDC, hBrush);
410+
411+ draw_polygon(renderer, points, num_points, colour);
412+
413+ W32::SelectObject(renderer->hFileDC,
414+ W32::GetStockObject (HOLLOW_BRUSH) );
415+ W32::DeleteObject(hBrush);
416+}
417+
418+static void
419+draw_rect(MyRenderer *renderer,
420+ Point *ul_corner, Point *lr_corner,
421+ Color *colour)
422+{
423+ W32::HGDIOBJ hPen;
424+
425+ DIAG_NOTE(renderer, "draw_rect %f,%f -> %f,%f\n",
426+ ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
427+
428+ hPen = UsePen(renderer, colour);
429+
430+ W32::Rectangle(renderer->hFileDC,
431+ SC(ul_corner->x), SC(ul_corner->y),
432+ SC(lr_corner->x), SC(lr_corner->y));
433+
434+ DonePen(renderer, hPen);
435+}
436+
437+static void
438+fill_rect(MyRenderer *renderer,
439+ Point *ul_corner, Point *lr_corner,
440+ Color *colour)
441+{
442+ W32::HGDIOBJ hBrush, hBrOld;
443+ W32::COLORREF rgb = W32COLOR(colour);
444+
445+ DIAG_NOTE(renderer, "fill_rect %f,%f -> %f,%f\n",
446+ ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
447+
448+ hBrush = W32::CreateSolidBrush(rgb);
449+ hBrOld = W32::SelectObject(renderer->hFileDC, hBrush);
450+
451+ draw_rect(renderer, ul_corner, lr_corner, colour);
452+
453+ W32::SelectObject(renderer->hFileDC,
454+ W32::GetStockObject (HOLLOW_BRUSH) );
455+ W32::DeleteObject(hBrush);
456+}
457+
458+static void
459+draw_arc(MyRenderer *renderer,
460+ Point *center,
461+ real width, real height,
462+ real angle1, real angle2,
463+ Color *colour)
464+{
465+ W32::HGDIOBJ hPen;
466+ W32::POINT ptStart, ptEnd;
467+
468+ DIAG_NOTE(renderer, "draw_arc %fx%f <%f,<%f @%f,%f\n",
469+ width, height, angle1, angle2, center->x, center->y);
470+
471+ hPen = UsePen(renderer, colour);
472+
473+ /* calculate start and end points of arc */
474+ ptStart.x = SC(center->x + (width / 2.0) * cos((M_PI / 180.0) * angle1));
475+ ptStart.y = SC(center->y - (height / 2.0) * sin((M_PI / 180.0) * angle1));
476+ ptEnd.x = SC(center->x + (width / 2.0) * cos((M_PI / 180.0) * angle2));
477+ ptEnd.y = SC(center->y - (height / 2.0) * sin((M_PI / 180.0) * angle2));
478+
479+ W32::MoveToEx(renderer->hFileDC, ptStart.x, ptStart.y, NULL);
480+ W32::Arc(renderer->hFileDC,
481+ SC(center->x - width / 2), /* bbox corners */
482+ SC(center->y - height / 2),
483+ SC(center->x + width / 2),
484+ SC(center->y + height / 2),
485+ ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
486+
487+ DonePen(renderer, hPen);
488+}
489+
490+static void
491+fill_arc(MyRenderer *renderer,
492+ Point *center,
493+ real width, real height,
494+ real angle1, real angle2,
495+ Color *colour)
496+{
497+ W32::HGDIOBJ hPen;
498+
499+ DIAG_NOTE(renderer, "fill_arc %fx%f <%f,<%f @%f,%f\n",
500+ width, height, angle1, angle2, center->x, center->y);
501+
502+ hPen = UsePen(renderer, colour);
503+
504+ DonePen(renderer, hPen);
505+}
506+
507+static void
508+draw_ellipse(MyRenderer *renderer,
509+ Point *center,
510+ real width, real height,
511+ Color *colour)
512+{
513+ W32::HGDIOBJ hPen;
514+
515+ DIAG_NOTE(renderer, "draw_ellipse %fx%f @ %f,%f\n",
516+ width, height, center->x, center->y);
517+
518+ hPen = UsePen(renderer, colour);
519+
520+ W32::Ellipse(renderer->hFileDC,
521+ SC(center->x - width / 2), /* bbox corners */
522+ SC(center->y - height / 2),
523+ SC(center->x + width / 2),
524+ SC(center->y + height / 2));
525+
526+ DonePen(renderer, hPen);
527+}
528+
529+static void
530+fill_ellipse(MyRenderer *renderer,
531+ Point *center,
532+ real width, real height,
533+ Color *colour)
534+{
535+ W32::HGDIOBJ hPen;
536+ W32::HGDIOBJ hBrush, hBrOld;
537+ W32::COLORREF rgb = W32COLOR(colour);
538+
539+ DIAG_NOTE(renderer, "fill_ellipse %fx%f @ %f,%f\n",
540+ width, height, center->x, center->y);
541+
542+ hBrush = W32::CreateSolidBrush(rgb);
543+ hBrOld = W32::SelectObject(renderer->hFileDC, hBrush);
544+
545+ draw_ellipse(renderer, center, width, height, colour);
546+
547+ W32::SelectObject(renderer->hFileDC,
548+ W32::GetStockObject (HOLLOW_BRUSH) );
549+ W32::DeleteObject(hBrush);
550+}
551+
552+static void
553+draw_bezier(MyRenderer *renderer,
554+ BezPoint *points,
555+ int numpoints,
556+ Color *colour)
557+{
558+ W32::HGDIOBJ hPen;
559+ W32::POINT * pts;
560+ int i;
561+
562+ DIAG_NOTE(renderer, "draw_bezier n:%d %fx%f ...\n",
563+ numpoints, points->p1.x, points->p1.y);
564+
565+ pts = g_new(W32::POINT, (numpoints-1) * 3 + 1);
566+
567+ pts[0].x = SC(points[0].p1.x);
568+ pts[0].y = SC(points[0].p1.y);
569+
570+ for (i = 1; i < numpoints; i++)
571+ {
572+ switch(points[i].type)
573+ {
574+ case _BezPoint::BEZ_MOVE_TO:
575+ g_warning("only first BezPoint can be a BEZ_MOVE_TO");
576+ break;
577+ case _BezPoint::BEZ_LINE_TO:
578+ /* everyhing the same ?*/
579+ pts[i*3-2].x = pts[i*3-1].x =
580+ pts[i*3 ].x = SC(points[i].p1.x);
581+ pts[i*3-2].y = pts[i*3-1].y =
582+ pts[i*3 ].y = SC(points[i].p1.y);
583+ break;
584+ case _BezPoint::BEZ_CURVE_TO:
585+ /* control points */
586+ pts[i*3-2].x = SC(points[i].p1.x);
587+ pts[i*3-2].y = SC(points[i].p1.y);
588+ pts[i*3-1].x = SC(points[i].p2.x);
589+ pts[i*3-1].y = SC(points[i].p2.y);
590+ /* end point */
591+ pts[i*3 ].x = SC(points[i].p3.x);
592+ pts[i*3 ].y = SC(points[i].p3.y);
593+ break;
594+ default:
595+ break;
596+ }
597+ }
598+
599+ hPen = UsePen(renderer, colour);
600+
601+ W32::PolyBezier(renderer->hFileDC,
602+ pts, (numpoints-1)*3+1);
603+
604+ DonePen(renderer, hPen);
605+
606+ g_free(pts);
607+}
608+
609+static void
610+fill_bezier(MyRenderer *renderer,
611+ BezPoint *points, /* Last point must be same as first point */
612+ int numpoints,
613+ Color *colour)
614+{
615+ W32::HGDIOBJ hPen;
616+
617+ DIAG_NOTE(renderer, "fill_bezier n:%d %fx%f ...\n",
618+ numpoints, points->p1.x, points->p1.y);
619+}
620+
621+static void
622+draw_string(MyRenderer *renderer,
623+ const char *text,
624+ Point *pos, Alignment alignment,
625+ Color *colour)
626+{
627+ int len;
628+ W32::HGDIOBJ hOld;
629+
630+ DIAG_NOTE(renderer, "draw_string %f,%f %s\n",
631+ pos->x, pos->y, text);
632+
633+ switch (alignment) {
634+ case ALIGN_LEFT:
635+ W32::SetTextAlign(renderer->hFileDC, TA_LEFT+TA_BASELINE);
636+ break;
637+ case ALIGN_CENTER:
638+ W32::SetTextAlign(renderer->hFileDC, TA_CENTER+TA_BASELINE);
639+ break;
640+ case ALIGN_RIGHT:
641+ W32::SetTextAlign(renderer->hFileDC, TA_RIGHT+TA_BASELINE);
642+ break;
643+ }
644+ /* work out size of first chunk of text */
645+ len = strlen(text);
646+
647+ hOld = W32::SelectObject(renderer->hFileDC, renderer->hFont);
648+ W32::TextOut(renderer->hFileDC,
649+ SC(pos->x), SC(pos->y),
650+ text, len);
651+ W32::SelectObject(renderer->hFileDC, hOld);
652+}
653+
654+static void
655+draw_image(MyRenderer *renderer,
656+ Point *point,
657+ real width, real height,
658+ DiaImage image)
659+{
660+ W32::HBITMAP hBmp;
661+ int iWidth, iHeight;
662+ unsigned char* pData = NULL;
663+
664+ DIAG_NOTE(renderer, "draw_image %fx%f @%f,%f\n",
665+ width, height, point->x, point->y);
666+
667+ iWidth = dia_image_width(image);
668+ iHeight = dia_image_height(image);
669+
670+ if ((dia_image_width(image)*3) % 4)
671+ {
672+ /* transform data to be DWORD aligned */
673+ int x, y;
674+ const unsigned char* pIn = NULL;
675+ unsigned char* pOut = NULL;
676+
677+ pOut = pData = g_new(unsigned char, ((((iWidth*3-1)/4)+1)*4)*iHeight);
678+
679+ pIn = dia_image_rgb_data(image);
680+ for (y = 0; y < iHeight; y++)
681+ {
682+ for (x = 0; x < iWidth; x++)
683+ {
684+ *pOut++ = *pIn++;
685+ *pOut++ = *pIn++;
686+ *pOut++ = *pIn++;
687+ }
688+ pOut += (4 - (iWidth*3)%4);
689+ }
690+
691+ hBmp = W32::CreateBitmap ( iWidth, iHeight, 1, 24, pData);
692+ }
693+ else
694+ {
695+ hBmp = W32::CreateBitmap (
696+ dia_image_width(image), dia_image_height(image),
697+ 1, 24, dia_image_rgb_data(image));
698+ }
699+
700+ W32::SelectObject(renderer->hFileDC, hBmp);
701+ //Hack to get SRCCOPY out of namespace W32
702+# ifndef DWORD
703+# define DWORD unsigned long
704+# endif
705+ W32::BitBlt(renderer->hFileDC, // destination
706+ SC(point->x), SC(point->y), SC(width), SC(height),
707+ renderer->hFileDC, // source
708+ 0, 0, SRCCOPY);
709+
710+ W32::DeleteObject(hBmp);
711+ if (pData)
712+ g_free(pData);
713+}
714+
715+static void
716+export_data(DiagramData *data, const gchar *filename, const gchar *diafilename)
717+{
718+ MyRenderer *renderer;
719+ W32::HDC file;
720+ Rectangle *extent;
721+ gint len;
722+
723+ W32::RECT bbox;
724+
725+ bbox.top = SC(data->extents.top);
726+ bbox.left = SC(data->extents.left);
727+ bbox.right = SC(data->extents.right);
728+ bbox.bottom = SC(data->extents.bottom);
729+
730+ file = (W32::HDC)W32::CreateEnhMetaFile(
731+ W32::GetDC(NULL), // handle to a reference device context
732+#ifdef SAVE_EMF
733+ filename, // pointer to a filename string
734+#else
735+ NULL, // in memory
736+#endif
737+ &bbox, // pointer to a bounding rectangle
738+ "Dia\0Diagram\0"); // pointer to an optional description string
739+
740+ if (file == NULL) {
741+ message_error(_("Couldn't open: '%s' for writing.\n"), filename);
742+ return;
743+ }
744+
745+ renderer = g_new(MyRenderer, 1);
746+ renderer->renderer.ops = &MyRenderOps;
747+ renderer->renderer.is_interactive = 0;
748+ renderer->renderer.interactive_ops = NULL;
749+
750+ renderer->hFileDC = file;
751+ renderer->sFileName = g_strdup(filename);
752+
753+ extent = &data->extents;
754+
755+ /* write extents */
756+ DIAG_NOTE(renderer, "export_data extents %f,%f -> %f,%f\n",
757+ extent->left, extent->top, extent->right, extent->bottom);
758+
759+
760+ data_render(data, (Renderer *)renderer, NULL, NULL, NULL);
761+
762+ g_free(renderer);
763+}
764+
765+static const gchar *extensions[] = { "wmf", NULL };
766+static DiaExportFilter my_export_filter = {
767+ N_("Windows Meta File"),
768+ extensions,
769+ export_data
770+};
771+
772+
773+/* --- dia plug-in interface --- */
774+
775+DIA_PLUGIN_CHECK_INIT
776+
777+PluginInitResult
778+dia_plugin_init(PluginInfo *info)
779+{
780+ if (!dia_plugin_info_init(info, "WMF",
781+ _("WMF export filter"),
782+ NULL, NULL))
783+ return DIA_PLUGIN_INIT_ERROR;
784+
785+ filter_register_export(&my_export_filter);
786+
787+ return DIA_PLUGIN_INIT_OK;
788+}
--- /dev/null
+++ b/plug-ins/wpg/.cvsignore
@@ -0,0 +1,9 @@
1+.cvsignore
2+.deps
3+.libs
4+Makefile
5+Makefile.in
6+*.lo
7+*.la
8+*.pyc
9+
--- /dev/null
+++ b/plug-ins/wpg/Makefile.am
@@ -0,0 +1,8 @@
1+pkglib_LTLIBRARIES = libwpg_filter.la
2+
3+libwpg_filter_la_SOURCES = wpg.c wpg_defs.h
4+libwpg_filter_la_LDFLAGS = -export-dynamic -module -avoid-version
5+libwpg_filter_la_LIBADD = $(GTK_LIBS)
6+
7+INCLUDES = -I$(top_srcdir)/intl -I$(top_srcdir)/lib \
8+ $(GTK_CFLAGS) $(GNOME_CFLAGS)
--- a/plug-ins/wpg/wpg.c
+++ b/plug-ins/wpg/wpg.c
@@ -1,1202 +1,1202 @@
1-/* Dia -- an diagram creation/manipulation program
2- * Copyright (C) 1998 Alexander Larsson
3- *
4- * wpg.c -- HPGL export plugin for dia
5- * Copyright (C) 2000, Hans Breuer, <Hans@Breuer.Org>
6- * based on dummy.c
7- *
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.
12- *
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.
17- *
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.
21- */
22-
23-/*
24- * ToDo:
25- * - if helper points - like arc centers - are not in Dia's extent box
26- * their clipping produces unpredictable results
27- * - the font setting needs improvement (maybe on Dia's side)
28- * - bezier curves are not correctly converted to WPG's poly curve
29- * (two point beziers are)
30- *
31- * MayBe:
32- * - full featured import (IMO Dia's import support should be improved
33- * before / on the way ...)
34- */
35-
36-#include <stdio.h>
37-#include <string.h>
38-#include <math.h>
39-#include <glib.h>
40-
41-#include "config.h"
42-#include "intl.h"
43-#include "message.h"
44-#include "geometry.h"
45-#include "render.h"
46-#include "filter.h"
47-#include "plug-ins.h"
48-
49-/* format specific */
50-#include "wpg_defs.h"
51-
52-/* Import is not yet finished but only implemented to check the
53- * export capabilities and to investigate other programs WPG
54- * formats.
55- * The following is not the reason for <en/dis>abling import,
56- * but it should do it for now ...
57- */
58-#define WPG_WITH_IMPORT defined (_MSC_VER)
59-
60-/*
61- * helper macros
62- */
63-#define SC(a) ((a) * renderer->Scale)
64-
65-/* --- the renderer --- */
66-#define MY_RENDERER_NAME "WPG"
67-
68-typedef struct _MyRenderer MyRenderer;
69-struct _MyRenderer {
70- Renderer renderer;
71-
72- FILE *file;
73-
74- real Scale;
75-
76- real dash_length;
77-
78- WPGStartData Box;
79- WPGFillAttr FillAttr;
80- WPGLineAttr LineAttr;
81- WPGTextStyle TextStyle;
82-
83- WPGColorRGB* pPal;
84-};
85-
86-/* include function declares and render object "vtable" */
87-#include "../renderer.inc"
88-
89-#define DIAG_NOTE my_log /* */
90-void
91-my_log(MyRenderer* renderer, char* format, ...)
92-{
93- gchar *string;
94- va_list args;
95-
96- g_return_if_fail (format != NULL);
97-
98- va_start (args, format);
99- string = g_strdup_vprintf (format, args);
100- va_end (args);
101-
102- g_print(string);
103-
104- g_free(string);
105-}
106-
107-#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
108-/* shortcut if testing of indirection isn't needed anymore */
109-#pragma message("LITTLE_ENDIAN: disabling fwrite_le")
110-#define fwrite_le(a,b,c,d) fwrite(a,b,c,d)
111-#else
112-static size_t
113-fwrite_le(void* buf, size_t size, size_t count, FILE* f)
114-{
115- size_t n = 0;
116- guint i;
117-
118- g_assert((1 == size) || (2 == size) || (4 == size));
119-
120- if (4 == size)
121- {
122- gint32 i32;
123-
124- for (i = 0; i < count; i++)
125- {
126- i32 = GINT32_TO_LE(((gint32*)buf)[i]);
127- n += fwrite(&i32, sizeof(gint32), 1, f);
128- }
129- }
130- else if (2 == size)
131- {
132- gint16 i16;
133-
134- for (i = 0; i < count; i++)
135- {
136- i16 = GINT16_TO_LE(((gint16*)buf)[i]);
137- n += fwrite(&i16, sizeof(gint16), 1, f);
138- }
139- }
140- else
141- n = fwrite(buf, size, count, f);
142-
143- return n;
144-}
145-#endif
146-
147-/*
148- * color cube len, WPG is limited to 256 colors. To get simple
149- * color reduction algorithms only 216 = 6^3 of them are used.
150- */
151-#define CC_LEN 6
152-
153-/*
154- * "To avoid problems with WPC products the first 16 colors of
155- * the color map should never be changed".
156- * Define WPG_NUM_DEF_COLORS to 0 ignore this statement (It
157- * appears to work more reliable; tested with WinWord 97 and
158- * Designer 4.1 - the latter does not respect the color maps
159- * start color).
160- */
161-#define WPG_NUM_DEF_COLORS 0 /* 16 */
162-
163-/*
164- * helper functions
165- */
166-guint8
167-LookupColor(MyRenderer *renderer, Color* colour)
168-{
169- /* find nearest color in the renderers color map */
170- /* the following hack does only work with a correctly
171- sorted color map */
172- unsigned long i = (int)floor(colour->red * (CC_LEN - 1))
173- + (int)floor(colour->green * (CC_LEN - 1)) * CC_LEN
174- + (int)floor(colour->blue * (CC_LEN - 1)) * CC_LEN * CC_LEN;
175- DIAG_NOTE(renderer, "LookupColor %d.\n", i);
176- if (i >= CC_LEN * CC_LEN * CC_LEN)
177- return CC_LEN * CC_LEN * CC_LEN - 1 + WPG_NUM_DEF_COLORS;
178- else
179- return i + WPG_NUM_DEF_COLORS;
180-}
181-
182-void
183-WriteRecHead(MyRenderer *renderer, WPG_Type Type, guint32 Size)
184-{
185- if (Size < 255)
186- {
187- WPGHead8 rh;
188- rh.Type = (guint8)Type;
189- rh.Size = (guint8)Size;
190- fwrite(&rh, sizeof(guint8), 2, renderer->file);
191- }
192- else if (Size < 32768)
193- {
194- WPGHead16 rh;
195- rh.Type = (guint8)Type;
196- rh.Dummy = 0xFF;
197- rh.Size = (guint16)Size;
198- fwrite(&rh, sizeof(guint8), 2, renderer->file);
199- fwrite_le(&(rh.Size), sizeof(guint16), 1, renderer->file);
200- }
201- else
202- {
203- WPGHead32 rh;
204- rh.Type = (guint8)Type;
205- rh.Dummy = 0xFF;
206- rh.Size = Size;
207-
208- /* To avoid problems with stucture packing this struct
209- * is written in parts ...
210- */
211- fwrite(&rh, sizeof(guint8), 2, renderer->file);
212- fwrite_le(&rh.Size, sizeof(guint32), 1, renderer->file);
213- }
214-}
215-
216-void
217-WriteLineAttr(MyRenderer *renderer, Color* colour)
218-{
219- g_assert(4 == sizeof(WPGLineAttr));
220-
221- WriteRecHead(renderer, WPG_LINEATTR, sizeof(WPGLineAttr));
222- renderer->LineAttr.Color = LookupColor(renderer, colour);
223- fwrite(&renderer->LineAttr, sizeof(guint8), 2, renderer->file);
224- fwrite_le(&renderer->LineAttr.Width, sizeof(guint16), 1, renderer->file);
225-}
226-
227-void
228-WriteFillAttr(MyRenderer *renderer, Color* colour, gboolean bFill)
229-{
230- g_assert(2 == sizeof(WPGFillAttr));
231-
232- WriteRecHead(renderer, WPG_FILLATTR, sizeof(WPGFillAttr));
233- if (bFill)
234- {
235- renderer->FillAttr.Color = LookupColor(renderer, colour);
236- fwrite(&renderer->FillAttr, sizeof(WPGFillAttr), 1, renderer->file);
237- }
238- else
239- {
240- WPGFillAttr fa;
241- fa.Color = LookupColor(renderer, colour);
242- fa.Type = WPG_FA_HOLLOW;
243- fwrite(&fa, sizeof(WPGFillAttr), 1, renderer->file);
244- }
245-}
246-
247-/*
248- * render functions
249- */
250-static void
251-begin_render(MyRenderer *renderer, DiagramData *data)
252-{
253-#if 0
254- const WPGFileHead wpgFileHead = { "\377WPC", 16,
255- 1, 22,
256- 1, 0, /* Version */
257- 0, 0};
258-#else
259- /* static conversion to little endian */
260- const char wpgFileHead[16] = {255, 'W', 'P', 'C', 16, 0, 0, 0,
261- 1, 22, 1, 0, 0, 0, 0, 0};
262-#endif
263-
264- gint16 i;
265- guint8* pPal;
266- Color color = {1, 1, 1};
267-
268- DIAG_NOTE(renderer, "begin_render\n");
269-
270- fwrite(&wpgFileHead, 1, 16, renderer->file);
271-
272- /* bounding box */
273- WriteRecHead(renderer, WPG_START, sizeof(WPGStartData));
274-#if 0
275- fwrite(&renderer->Box, sizeof(WPGStartData), 1, renderer->file);
276-#else
277- g_assert(6 == sizeof(WPGStartData));
278- fwrite(&renderer->Box, sizeof(guint8), 2, renderer->file);
279- fwrite_le(&renderer->Box.Width, sizeof(guint16), 2, renderer->file);
280-#endif
281- /* initialize a well known colormap, see LookupColor */
282- pPal = g_new(gint8, CC_LEN*CC_LEN*CC_LEN*3);
283- for (i = 0; i < CC_LEN * CC_LEN * CC_LEN; i++)
284- {
285- pPal[3*i ] = ((i % CC_LEN) * 255) / (CC_LEN - 1); /* red */
286- pPal[3*i+1] = (((i / CC_LEN) % CC_LEN) * 255) / (CC_LEN - 1); /* green */
287- pPal[3*i+2] = ((i / (CC_LEN * CC_LEN)) * 255) / (CC_LEN - 1); /* blue varies least */
288- /*
289- g_print("%d\t%d\t%d\n", pPal[3*i ], pPal[3*i+1], pPal[3*i+2]);
290- */
291- }
292-
293- WriteRecHead(renderer, WPG_COLORMAP, CC_LEN*CC_LEN*CC_LEN*3 + 2*sizeof(guint16));
294- i = WPG_NUM_DEF_COLORS; /* start color */
295- fwrite_le(&i, sizeof(gint16), 1, renderer->file);
296- i = CC_LEN*CC_LEN*CC_LEN;
297- fwrite_le(&i, sizeof(gint16), 1, renderer->file);
298- fwrite(pPal, 1, CC_LEN*CC_LEN*CC_LEN*3, renderer->file);
299-
300- /* FIXME: following 3 lines needed to make filling work !? */
301- renderer->FillAttr.Type = WPG_FA_SOLID;
302- WriteFillAttr(renderer, &color, TRUE);
303- WriteFillAttr(renderer, &color, FALSE);
304-
305- g_free(pPal);
306-}
307-
308-static void
309-end_render(MyRenderer *renderer)
310-{
311- DIAG_NOTE(renderer, "end_render\n");
312-
313- WriteRecHead(renderer, WPG_END, 0); /* no data following */
314- fclose(renderer->file);
315-}
316-
317-static void
318-set_linewidth(MyRenderer *renderer, real linewidth)
319-{
320- DIAG_NOTE(renderer, "set_linewidth %f\n", linewidth);
321-
322- renderer->LineAttr.Width = SC(linewidth);
323-}
324-
325-static void
326-set_linecaps(MyRenderer *renderer, LineCaps mode)
327-{
328- DIAG_NOTE(renderer, "set_linecaps %d\n", mode);
329-
330- switch(mode) {
331- case LINECAPS_BUTT:
332- break;
333- case LINECAPS_ROUND:
334- break;
335- case LINECAPS_PROJECTING:
336- break;
337- default:
338- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
339- }
340-}
341-
342-static void
343-set_linejoin(MyRenderer *renderer, LineJoin mode)
344-{
345- DIAG_NOTE(renderer, "set_join %d\n", mode);
346-
347- switch(mode) {
348- case LINEJOIN_MITER:
349- break;
350- case LINEJOIN_ROUND:
351- break;
352- case LINEJOIN_BEVEL:
353- break;
354- default:
355- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
356- }
357-}
358-
359-static void
360-set_linestyle(MyRenderer *renderer, LineStyle mode)
361-{
362- DIAG_NOTE(renderer, "set_linestyle %d\n", mode);
363-
364- /* line type */
365- switch (mode) {
366- case LINESTYLE_SOLID:
367- renderer->LineAttr.Type = WPG_LA_SOLID;
368- break;
369- case LINESTYLE_DASHED:
370- if (renderer->dash_length < 0.5)
371- renderer->LineAttr.Type = WPG_LA_SHORTDASH;
372- else
373- renderer->LineAttr.Type = WPG_LA_MEDIUMDASH;
374- break;
375- case LINESTYLE_DASH_DOT:
376- renderer->LineAttr.Type = WPG_LA_DASHDOT;
377- break;
378- case LINESTYLE_DASH_DOT_DOT:
379- renderer->LineAttr.Type = WPG_LA_DASHDOTDOT;
380- break;
381- case LINESTYLE_DOTTED:
382- renderer->LineAttr.Type = WPG_LA_DOTS;
383- break;
384- default:
385- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
386- }
387-}
388-
389-static void
390-set_dashlength(MyRenderer *renderer, real length)
391-{
392- DIAG_NOTE(renderer, "set_dashlength %f\n", length);
393-
394- /* dot = 20% of len */
395- renderer->dash_length = length;
396-}
397-
398-static void
399-set_fillstyle(MyRenderer *renderer, FillStyle mode)
400-{
401- DIAG_NOTE(renderer, "set_fillstyle %d\n", mode);
402-
403- switch(mode) {
404- case FILLSTYLE_SOLID:
405- renderer->FillAttr.Type = WPG_FA_SOLID;
406- break;
407- default:
408- message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
409- }
410-}
411-
412-static void
413-set_font(MyRenderer *renderer, Font *font, real height)
414-{
415- DIAG_NOTE(renderer, "set_font %f %s\n", height, font->name);
416- renderer->TextStyle.Height = SC(height);
417-
418- if (strstr(font->name, "Courier"))
419- renderer->TextStyle.Font = 0x0DF0;
420- else if (strstr(font->name, "Times"))
421- renderer->TextStyle.Font = 0x1950;
422- else
423- renderer->TextStyle.Font = 0x1150; /* Helv */
424-}
425-
426-/* Need to translate coord system:
427- *
428- * Dia x,y -> Wpg x,-y
429- *
430- * doing it before scaling.
431- */
432-static void
433-draw_line(MyRenderer *renderer,
434- Point *start, Point *end,
435- Color *line_colour)
436-{
437- gint16 pData[4];
438-
439- DIAG_NOTE(renderer, "draw_line %f,%f -> %f, %f\n",
440- start->x, start->y, end->x, end->y);
441-
442- WriteLineAttr(renderer, line_colour);
443- WriteRecHead(renderer, WPG_LINE, 4 * sizeof(gint16));
444-
445- /* point data */
446- pData[0] = SC(start->x);
447- pData[1] = SC(-start->y);
448- pData[2] = SC(end->x);
449- pData[3] = SC(-end->y);
450-
451- fwrite_le(pData, sizeof(gint16), 4, renderer->file);
452-}
453-
454-static void
455-draw_polyline(MyRenderer *renderer,
456- Point *points, int num_points,
457- Color *line_colour)
458-{
459- int i;
460- gint16* pData;
461-
462- DIAG_NOTE(renderer, "draw_polyline n:%d %f,%f ...\n",
463- num_points, points->x, points->y);
464-
465- g_return_if_fail(1 < num_points);
466-
467- WriteLineAttr(renderer, line_colour);
468- WriteRecHead(renderer, WPG_POLYLINE, num_points * 2 * sizeof(gint16) + sizeof(gint16));
469-
470- pData = g_new(gint16, num_points * 2);
471-
472- /* number of points */
473- pData[0] = num_points;
474- fwrite_le(pData, sizeof(gint16), 1, renderer->file);
475-
476- /* point data */
477- for (i = 0; i < num_points; i++)
478- {
479- pData[2*i] = SC(points[i].x);
480- pData[2*i+1] = SC(-points[i].y);
481- }
482-
483- fwrite_le(pData, sizeof(gint16), num_points*2, renderer->file);
484-
485- g_free(pData);
486-}
487-
488-static void
489-draw_polygon(MyRenderer *renderer,
490- Point *points, int num_points,
491- Color *line_colour)
492-{
493- gint16* pData;
494- int i;
495-
496- DIAG_NOTE(renderer, "draw_polygon n:%d %f,%f ...\n",
497- num_points, points->x, points->y);
498-
499- WriteLineAttr(renderer, line_colour);
500- WriteRecHead(renderer, WPG_POLYGON, (num_points * 2 + 1) * sizeof(gint16));
501-
502- pData = g_new(gint16, num_points * 2);
503-
504- /* number of vertices */
505- pData[0] = num_points;
506- fwrite_le(pData, sizeof(gint16), 1, renderer->file);
507-
508- /* point data */
509- for (i = 0; i < num_points; i++)
510- {
511- pData[2*i] = SC(points[i].x);
512- pData[2*i+1] = SC(-points[i].y);
513- }
514-
515- fwrite_le(pData, sizeof(gint16), num_points*2, renderer->file);
516-
517- g_free(pData);
518-}
519-
520-static void
521-fill_polygon(MyRenderer *renderer,
522- Point *points, int num_points,
523- Color *colour)
524-{
525- DIAG_NOTE(renderer, "fill_polygon n:%d %f,%f ...\n",
526- num_points, points->x, points->y);
527-
528- WriteFillAttr(renderer, colour, TRUE);
529- draw_polygon(renderer,points,num_points,colour);
530- WriteFillAttr(renderer, colour, FALSE);
531-}
532-
533-static void
534-draw_rect(MyRenderer *renderer,
535- Point *ul_corner, Point *lr_corner,
536- Color *colour)
537-{
538- gint16* pData;
539- DIAG_NOTE(renderer, "draw_rect %f,%f -> %f,%f\n",
540- ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
541-
542- WriteLineAttr(renderer, colour);
543- WriteRecHead(renderer, WPG_RECTANGLE, 4*sizeof(gint16));
544-
545- pData = g_new(gint16, 4);
546- pData[0] = SC(ul_corner->x); /* lower left corner ! */
547- pData[1] = SC(-lr_corner->y);
548- pData[2] = SC(lr_corner->x - ul_corner->x); /* width */
549- pData[3] = SC(lr_corner->y - ul_corner->y); /* height */
550-
551- fwrite_le(pData, sizeof(gint16), 4, renderer->file);
552-
553- g_free(pData);
554-}
555-
556-static void
557-fill_rect(MyRenderer *renderer,
558- Point *ul_corner, Point *lr_corner,
559- Color *colour)
560-{
561- DIAG_NOTE(renderer, "fill_rect %f,%f -> %f,%f\n",
562- ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
563-
564- WriteFillAttr(renderer, colour, TRUE);
565- draw_rect(renderer, ul_corner, lr_corner, colour);
566- WriteFillAttr(renderer, colour, FALSE);
567-}
568-
569-static void
570-draw_arc(MyRenderer *renderer,
571- Point *center,
572- real width, real height,
573- real angle1, real angle2,
574- Color *colour)
575-{
576- WPGEllipse ell;
577-
578- DIAG_NOTE(renderer, "draw_arc %fx%f <%f,<%f\n",
579- width, height, angle1, angle2);
580-
581- ell.x = SC(center->x);
582- ell.y = SC(-center->y);
583- ell.RotAngle = 0;
584- ell.rx = SC(width / 2.0);
585- ell.ry = SC(height / 2.0);
586-
587- ell.StartAngle = angle1;
588- ell.EndAngle = angle2;
589- ell.Flags = 0;
590-
591- WriteLineAttr(renderer, colour);
592- WriteRecHead(renderer, WPG_ELLIPSE, sizeof(WPGEllipse));
593-
594- g_assert(16 == sizeof(WPGEllipse));
595- fwrite_le(&ell, sizeof(guint16), sizeof(WPGEllipse) / sizeof(guint16), renderer->file);
596-}
597-
598-static void
599-fill_arc(MyRenderer *renderer,
600- Point *center,
601- real width, real height,
602- real angle1, real angle2,
603- Color *colour)
604-{
605- WPGEllipse ell;
606-
607- DIAG_NOTE(renderer, "fill_arc %fx%f <%f,<%f\n",
608- width, height, angle1, angle2);
609-
610- ell.x = SC(center->x);
611- ell.y = SC(-center->y);
612- ell.RotAngle = 0;
613- ell.rx = SC(width / 2.0);
614- ell.ry = SC(height / 2.0);
615-
616- ell.StartAngle = angle1;
617- ell.EndAngle = angle2;
618- ell.Flags = 0; /* 0: connect to center; 1: connect start and end */
619-
620- WriteLineAttr(renderer, colour);
621- WriteFillAttr(renderer, colour, TRUE);
622- WriteRecHead(renderer, WPG_ELLIPSE, sizeof(WPGEllipse));
623-
624- g_assert(16 == sizeof(WPGEllipse));
625- fwrite_le(&ell, sizeof(guint16), sizeof(WPGEllipse) / sizeof(guint16), renderer->file);
626- WriteFillAttr(renderer, colour, FALSE);
627-}
628-
629-static void
630-draw_ellipse(MyRenderer *renderer,
631- Point *center,
632- real width, real height,
633- Color *colour)
634-{
635- WPGEllipse ell;
636-
637- DIAG_NOTE(renderer, "draw_ellipse %fx%f center @ %f,%f\n",
638- width, height, center->x, center->y);
639-
640- ell.x = SC(center->x);
641- ell.y = SC(-center->y);
642- ell.RotAngle = 0;
643- ell.rx = SC(width / 2.0);
644- ell.ry = SC(height / 2.0);
645-
646- ell.StartAngle = 0;
647- ell.EndAngle = 360;
648- ell.Flags = 0;
649-
650- WriteLineAttr(renderer, colour);
651- WriteRecHead(renderer, WPG_ELLIPSE, sizeof(WPGEllipse));
652-
653- g_assert(16 == sizeof(WPGEllipse));
654- fwrite_le(&ell, sizeof(guint16), sizeof(WPGEllipse) / sizeof(guint16), renderer->file);
655-}
656-
657-static void
658-fill_ellipse(MyRenderer *renderer,
659- Point *center,
660- real width, real height,
661- Color *colour)
662-{
663- DIAG_NOTE(renderer, "fill_ellipse %fx%f center @ %f,%f\n",
664- width, height, center->x, center->y);
665-
666- WriteFillAttr(renderer, colour, TRUE);
667- draw_ellipse(renderer,center,width,height,colour);
668- WriteFillAttr(renderer, colour, FALSE);
669-}
670-
671-static void
672-draw_bezier(MyRenderer *renderer,
673- BezPoint *points,
674- int numpoints,
675- Color *colour)
676-{
677- gint16* pData;
678- int i;
679-
680- DIAG_NOTE(renderer, "draw_bezier n:%d %fx%f ...\n",
681- numpoints, points->p1.x, points->p1.y);
682-
683- WriteLineAttr(renderer, colour);
684- WriteRecHead(renderer, WPG_POLYCURVE, (numpoints * 2) * 2 * sizeof(gint16) + 3 * sizeof(gint16));
685-
686- pData = g_new(gint16, numpoints * 6);
687-
688- /* ??? size of equivalent data in pre5.1 files ? */
689-#if 1
690- memset(pData, 0, sizeof(gint16)*2);
691-#else
692- /* try first point instead */
693- pData[0] = SC(points[0].p1.x);
694- pData[1] = SC(-points[0].p1.y);
695-#endif
696- fwrite_le(pData, sizeof(gint16), 2, renderer->file);
697-
698- pData[0] = numpoints * 2;
699- fwrite_le(pData, sizeof(gint16), 1, renderer->file);
700-
701- /* WPG's Poly Curve is not quite the same as DIA's Bezier.
702- * There is only one Control Point per Point and I can't
703- * get it right, but at least they are read without error.
704- */
705- for (i = 0; i < numpoints; i++)
706- {
707- switch (points[i].type)
708- {
709- case BEZ_MOVE_TO:
710- case BEZ_LINE_TO:
711- /* real point */
712- pData[4*i ] = SC( points[i].p1.x);
713- pData[4*i+1] = SC(-points[i].p1.y);
714-
715- /* control point (1st from next point) */
716- if (i+1 < numpoints) {
717- pData[4*i+2] = SC( points[i+1].p1.x);
718- pData[4*i+3] = SC(-points[i+1].p1.y);
719- }
720- else {
721- pData[4*i+2] = SC( points[i].p1.x);
722- pData[4*i+3] = SC(-points[i].p1.y);
723- }
724- break;
725- case BEZ_CURVE_TO:
726- if (0 && (i+1 < numpoints)) {
727- /* real point ?? */
728- pData[4*i ] = SC( points[i].p3.x);
729- pData[4*i+1] = SC(-points[i].p3.y);
730- /* control point (1st from next point) */
731- pData[4*i+2] = SC( points[i+1].p1.x);
732- pData[4*i+3] = SC(-points[i+1].p1.y);
733- }
734- else {
735- /* need to swap these ?? */
736- /* real point ?? */
737- pData[4*i ] = SC( points[i].p2.x);
738- pData[4*i+1] = SC(-points[i].p2.y);
739-
740- /* control point ?? */
741- pData[4*i+2] = SC( points[i].p3.x);
742- pData[4*i+3] = SC(-points[i].p3.y);
743- }
744- break;
745- }
746- }
747-
748- fwrite_le(pData, sizeof(gint16), numpoints*4, renderer->file);
749- g_free(pData);
750-}
751-
752-static void
753-fill_bezier(MyRenderer *renderer,
754- BezPoint *points, /* Last point must be same as first point */
755- int numpoints,
756- Color *colour)
757-{
758- DIAG_NOTE(renderer, "fill_bezier n:%d %fx%f ...\n",
759- numpoints, points->p1.x, points->p1.y);
760-
761-}
762-
763-static void
764-draw_string(MyRenderer *renderer,
765- const char *text,
766- Point *pos, Alignment alignment,
767- Color *colour)
768-{
769- gint16 len;
770- WPGPoint pt;
771-
772- len = strlen(text);
773-
774- DIAG_NOTE(renderer, "draw_string(%d) %f,%f %s\n",
775- len, pos->x, pos->y, text);
776-
777- if (len < 1) return;
778-
779- renderer->TextStyle.YAlign = 3; /* bottom ??? */
780-
781- switch (alignment) {
782- case ALIGN_LEFT:
783- renderer->TextStyle.XAlign = 0;
784- break;
785- case ALIGN_CENTER:
786- renderer->TextStyle.XAlign = 1;
787- break;
788- case ALIGN_RIGHT:
789- renderer->TextStyle.XAlign = 2;
790- break;
791- }
792-
793- renderer->TextStyle.Color = LookupColor(renderer, colour);
794- renderer->TextStyle.Angle = 0;
795-
796- renderer->TextStyle.Width = renderer->TextStyle.Height * 0.6; /* ??? */
797-
798- WriteRecHead(renderer, WPG_TEXTSTYLE, sizeof(WPGTextStyle));
799-
800-#if 0
801- fwrite(&renderer->TextStyle, sizeof(WPGTextStyle), 1, renderer->file);
802-#else
803- g_assert(22 == sizeof(WPGTextStyle));
804- fwrite_le(&renderer->TextStyle.Width, sizeof(guint16), 1, renderer->file);
805- fwrite_le(&renderer->TextStyle.Height, sizeof(guint16), 1, renderer->file);
806- fwrite(&renderer->TextStyle.Reserved, 1, sizeof(renderer->TextStyle.Reserved), renderer->file);
807- fwrite_le(&renderer->TextStyle.Font, sizeof(guint16), 1, renderer->file);
808- fwrite(&renderer->TextStyle.Reserved2, sizeof(guint8), 1, renderer->file);
809- fwrite(&renderer->TextStyle.XAlign, 1, 1, renderer->file);
810- fwrite(&renderer->TextStyle.YAlign, 1, 1, renderer->file);
811- fwrite(&renderer->TextStyle.Color, 1, 1, renderer->file);
812- fwrite_le(&renderer->TextStyle.Angle, sizeof(guint16), 1, renderer->file);
813-#endif
814- pt.x = SC(pos->x);
815- pt.y = SC(-pos->y);
816-
817- WriteRecHead(renderer, WPG_TEXT, 3*sizeof(gint16) + len);
818- fwrite_le(&len, sizeof(gint16), 1, renderer->file);
819- fwrite_le(&pt.x, sizeof(guint16), 1, renderer->file);
820- fwrite_le(&pt.y, sizeof(guint16), 1, renderer->file);
821- fwrite(text, 1, len, renderer->file);
822-}
823-
824-static void
825-draw_image(MyRenderer *renderer,
826- Point *point,
827- real width, real height,
828- DiaImage image)
829-{
830- WPGBitmap2 bmp;
831- guint8 * pDiaImg = NULL, * pOut = NULL, * pIn = NULL, * p = NULL;
832- guint8 b_1, b, cnt;
833- int x, y;
834-
835- bmp.Angle = 0;
836- bmp.Left = SC(point->x);
837- bmp.Top = SC(-point->y - height);
838- bmp.Right = SC(point->x + width);
839- bmp.Bottom = SC(-point->y);
840-
841- bmp.Width = dia_image_width(image);
842- bmp.Height = dia_image_height(image);
843- bmp.Depth = 8; /* maximum allowed */
844-
845- bmp.Xdpi = 72; /* ??? */
846- bmp.Ydpi = 72;
847-
848- DIAG_NOTE(renderer, "draw_image %fx%f [%d,%d] @%f,%f\n",
849- width, height, bmp.Width, bmp.Height, point->x, point->y);
850-
851- pDiaImg = pIn = dia_image_rgb_data(image);
852- pOut = g_new(guint8, bmp.Width * bmp.Height * 2); /* space for worst case RLE */
853- p = pOut;
854-
855- pIn += (3* bmp.Width * (bmp.Height - 1)); /* last line */
856- for (y = 0; y < bmp.Height; y++)
857- {
858- cnt = 0; /* reset with every line */
859- for (x = 0; x < bmp.Width; x ++)
860- {
861- /* simple color reduction to default palette */
862- b = (((CC_LEN - 1) * pIn[0]) / 255) /* red */
863- + (((CC_LEN - 1) * pIn[1]) / 255) * CC_LEN /* green */
864- + (((CC_LEN - 1) * pIn[2]) / 255) * CC_LEN * CC_LEN /* blue */
865- + WPG_NUM_DEF_COLORS;
866-
867- pIn += 3; /* increase read pointer */
868-
869- if (cnt > 0)
870- {
871- if ((b == b_1) && (cnt < 127))
872- cnt++; /* increase counter*/
873- else
874- {
875- *p++ = (cnt | 0x80); /* write run length and value */
876- *p++ = b_1;
877- cnt = 1; /* reset */
878- b_1 = b;
879- }
880- }
881- else
882- {
883- b_1 = b;
884- cnt = 1;
885- }
886- }
887- *p++ = (cnt | 0x80); /* write last value(s) */
888- *p++ = b;
889- pIn -= (3 * bmp.Width * 2); /* start of previous line */
890- }
891- DIAG_NOTE(renderer, "Width x Height: %d RLE: %d\n", bmp.Width * bmp.Height, p - pOut);
892-
893- if ((p - pOut) > 32767) {
894- g_warning(MY_RENDERER_NAME ": Bitmap size exceeds blocksize. Ignored.");
895- }
896- else {
897- WriteRecHead(renderer, WPG_BITMAP2, sizeof(WPGBitmap2) + (p - pOut));
898-#if 0
899- fwrite(&bmp, sizeof(WPGBitmap2), 1, renderer->file);
900-#else
901- g_assert(20 == sizeof(WPGBitmap2));
902- fwrite(&bmp, sizeof(guint16), sizeof(WPGBitmap2) / sizeof(guint16), renderer->file);
903-#endif
904- fwrite(pOut, sizeof(guint8), p - pOut, renderer->file);
905- }
906-#if 1
907- /* RLE diagnose */
908- {
909- FILE* f;
910- int i, j;
911- f = fopen("c:\\temp\\wpg_bmp.raw", "wb");
912- j = p - pOut;
913- for (i = 0; i < j; i+=2)
914- {
915- for (x = 0; x < (pOut[i] & 0x7F); x++)
916- fwrite(&pOut[i+1], 1, 1, f);
917- }
918- fclose(f);
919- }
920-#endif
921- g_free(pDiaImg);
922- g_free(pOut);
923-}
924-
925-static void
926-export_data(DiagramData *data, const gchar *filename, const gchar *diafilename)
927-{
928- MyRenderer *renderer;
929- FILE *file;
930- Rectangle *extent;
931- gint len;
932- real width, height;
933-
934- file = fopen(filename, "wb"); /* "wb" for binary! */
935-
936- if (file == NULL) {
937- message_error(_("Couldn't open: '%s' for writing.\n"), filename);
938- return;
939- }
940-
941- renderer = g_new0(MyRenderer, 1);
942- renderer->renderer.ops = &MyRenderOps;
943- renderer->renderer.is_interactive = 0;
944- renderer->renderer.interactive_ops = NULL;
945-
946- renderer->file = file;
947-
948- extent = &data->extents;
949-
950- /* use extents */
951- DIAG_NOTE(renderer, "export_data extents %f,%f -> %f,%f\n",
952- extent->left, extent->top, extent->right, extent->bottom);
953-
954- width = extent->right - extent->left;
955- height = extent->bottom - extent->top;
956- renderer->Scale = 0.001;
957- if (width > height)
958- while (renderer->Scale * width < 3276.7) renderer->Scale *= 10.0;
959- else
960- while (renderer->Scale * height < 3276.7) renderer->Scale *= 10.0;
961-
962- renderer->Box.Width = width * renderer->Scale;
963- renderer->Box.Height = height * renderer->Scale;
964- renderer->Box.Flag = 0;
965- renderer->Box.Version = 0;
966-
967- data_render(data, (Renderer *)renderer, NULL, NULL, NULL);
968-
969- g_free(renderer);
970-}
971-
972-#if WPG_WITH_IMPORT
973-/*
974- * Import (under construction)
975- */
976-static void
977-import_object(MyRenderer* renderer, DiagramData *dia,
978- WPG_Type type, int iSize, guchar* pData)
979-{
980- WPGPoint* pts = NULL;
981- gint16* pInt16 = NULL;
982- int iNum = 0;
983- gint32 iPre51 = 0;
984-
985- switch (type) {
986- case WPG_LINE:
987- iNum = 2;
988- pts = (WPGPoint*)pData;
989- break;
990- case WPG_POLYLINE:
991- pInt16 = (gint16*)pData;
992- iNum = pInt16[0];
993- pts = (WPGPoint*)(pData + sizeof(gint16));
994- break;
995- case WPG_RECTANGLE:
996- iNum = 2;
997- pts = (WPGPoint*)pData;
998- break;
999- case WPG_POLYGON:
1000- pInt16 = (gint16*)pData;
1001- iNum = pInt16[0];
1002- pts = (WPGPoint*)(pData + sizeof(gint16));
1003- break;
1004- case WPG_ELLIPSE:
1005- {
1006- WPGEllipse* pEll;
1007- pEll = (WPGEllipse*)pData;
1008- }
1009- break;
1010- case WPG_POLYCURVE:
1011- iPre51 = *((gint32*)pData);
1012- pInt16 = (gint16*)pData;
1013- iNum = pInt16[2];
1014- pts = (WPGPoint*)(pData + 3*sizeof(gint16));
1015- DIAG_NOTE(renderer, "POLYCURVE Num pts %d Pre51 %d\n", iNum, iPre51);
1016- break;
1017- } /* switch */
1018- DIAG_NOTE(renderer, "Type %d Num pts %d Size %d\n", type, iNum, iSize);
1019-}
1020-
1021-static gboolean
1022-import_data (const gchar *filename, DiagramData *dia)
1023-{
1024- FILE* f;
1025- gboolean bRet;
1026- WPGHead8 rh;
1027-
1028- f = fopen(filename, "rb");
1029-
1030- if (NULL == f) {
1031- message_error(_("Couldn't open: '%s' for reading.\n"), filename);
1032- bRet = FALSE;
1033- }
1034-
1035- /* check header */
1036- if (bRet) {
1037- WPGFileHead fhead;
1038- bRet = ( (1 == fread(&fhead, sizeof(WPGFileHead), 1, f))
1039- && fhead.fid[0] == 255 && fhead.fid[1] == 'W'
1040- && fhead.fid[2] == 'P' && fhead.fid[3] == 'C'
1041- && (1 == fhead.MajorVersion) && (0 == fhead.MinorVersion));
1042- if (!bRet)
1043- message_error(_("File: %s type/version unsupported.\n"), filename);
1044- }
1045-
1046- if (bRet) {
1047- int iSize;
1048- gint16 i16, iNum16;
1049- guint8 i8;
1050- MyRenderer ren;
1051-
1052- ren.pPal = g_new0(WPGColorRGB, 256);
1053-
1054- DIAG_NOTE(&ren, "Parsing: %s \n", filename);
1055-
1056- do {
1057- if (1 == fread(&rh, sizeof(WPGHead8), 1, f)) {
1058- if (rh.Size < 0xFF)
1059- iSize = rh.Size;
1060- else {
1061- bRet = (1 == fread(&i16, sizeof(guint16), 1, f));
1062- if (0x8000 & i16) {
1063- DIAG_NOTE(&ren, "Large Object: hi:lo %04X", (int)i16);
1064- iSize = i16 << 16;
1065- /* Reading large objects involves major uglyness. Instead of getting
1066- * one size, as implied by "Encyclopedia of Graphics File Formats",
1067- * it would require putting together small chunks of data to one large
1068- * object. The criteria when to stop isn't absolutely clear.
1069- */
1070- iSize = 0;
1071- bRet = (1 == fread(&i16, sizeof(guint16), 1, f));
1072- DIAG_NOTE(&ren, "Large Object: %d\n", (int)i16);
1073- iSize += i16;
1074-#if 1
1075- /* Ignore this large objec part */
1076- fseek(f, iSize, SEEK_CUR);
1077- continue;
1078-#endif
1079- }
1080- else
1081- iSize = i16;
1082- }
1083- } else
1084- iSize = 0;
1085-
1086- //DIAG_NOTE(&ren, "Type %d Size %d\n", rh.Type, iSize);
1087- if (iSize > 0) {
1088- switch (rh.Type) {
1089- case WPG_FILLATTR:
1090- bRet = (1 == fread(&ren.FillAttr, sizeof(WPGFillAttr), 1, f));
1091- break;
1092- case WPG_LINEATTR:
1093- bRet = (1 == fread(&ren.LineAttr, sizeof(WPGLineAttr), 1, f));
1094- break;
1095- case WPG_START:
1096- bRet = (1 == fread(&ren.Box, sizeof(WPGStartData), 1, f));
1097- break;
1098- case WPG_STARTWPG2:
1099- /* not sure if this is the right thing to do */
1100- bRet &= (1 == fread(&i8, sizeof(gint8), 1, f));
1101- bRet &= (1 == fread(&i16, sizeof(gint16), 1, f));
1102- DIAG_NOTE(&ren, "Ignoring tag WPG_STARTWPG2, Size %d\n Type? %d Size? %d\n",
1103- iSize, (int)i8, i16);
1104- fseek(f, iSize - 3, SEEK_CUR);
1105- break;
1106- case WPG_LINE:
1107- case WPG_POLYLINE:
1108- case WPG_RECTANGLE:
1109- case WPG_POLYGON:
1110- case WPG_POLYCURVE:
1111- case WPG_ELLIPSE:
1112- {
1113- guchar* pData;
1114-
1115- pData = g_new(guchar, iSize);
1116- bRet = (iSize == (int)fread(pData, 1, iSize, f));
1117- import_object(&ren, dia, rh.Type, iSize, pData);
1118- g_free(pData);
1119- }
1120- break;
1121- case WPG_COLORMAP:
1122- bRet &= (1 == fread(&i16, sizeof(gint16), 1, f));
1123- bRet &= (1 == fread(&iNum16, sizeof(gint16), 1, f));
1124- if (iNum16 != (gint16)((iSize - 2) / sizeof(WPGColorRGB)))
1125- g_warning(MY_RENDERER_NAME ": colormap size/header mismatch.");
1126- if (i16 >= 0 && i16 <= iSize) {
1127- bRet &= (iNum16 == (int)fread(&ren.pPal[i16], sizeof(WPGColorRGB), iNum16, f));
1128- }
1129- else {
1130- g_warning(MY_RENDERER_NAME ": start color map index out of range.");
1131- bRet &= (iNum16 == (int)fread(ren.pPal, sizeof(WPGColorRGB), iNum16, f));
1132- }
1133- break;
1134- case WPG_BITMAP2:
1135- {
1136- WPGBitmap2 bmp;
1137-
1138- fread(&bmp, sizeof(WPGBitmap2), 1, f);
1139- DIAG_NOTE(&ren, "Bitmap %dx%d %d bits @%d,%d %d,%d.\n",
1140- bmp.Width, bmp.Height, bmp.Depth,
1141- bmp.Left, bmp.Top, bmp.Right, bmp.Bottom);
1142- fseek(f, iSize - sizeof(WPGBitmap2), SEEK_CUR);
1143- }
1144- break;
1145- default:
1146- fseek(f, iSize, SEEK_CUR);
1147- g_warning ("Unknown Type %d Size %d.", (int)rh.Type, iSize);
1148- } /* switch */
1149- } /* if iSize */
1150- else {
1151- if (WPG_END != rh.Type)
1152- g_warning("Size 0 on Type %d, expecting WPG_END\n", (int)rh.Type);
1153- }
1154- }
1155- while ((iSize > 0) && (bRet));
1156-
1157- if (!bRet)
1158- g_warning(MY_RENDERER_NAME ": unexpected eof. Type %d, Size %d.\n",
1159- rh.Type, iSize);
1160- if (ren.pPal) g_free(ren.pPal);
1161- } /* bRet */
1162-
1163- if (f) fclose(f);
1164- return bRet;
1165-}
1166-
1167-#endif /* WPG_WITH_IMPORT */
1168-
1169-static const gchar *extensions[] = { "wpg", NULL };
1170-static DiaExportFilter my_export_filter = {
1171- N_(MY_RENDERER_NAME),
1172- extensions,
1173- export_data
1174-};
1175-
1176-#if WPG_WITH_IMPORT
1177-DiaImportFilter my_import_filter = {
1178- N_(MY_RENDERER_NAME),
1179- extensions,
1180- import_data
1181-};
1182-#endif /* WPG_WITH_IMPORT */
1183-
1184-/* --- dia plug-in interface --- */
1185-
1186-DIA_PLUGIN_CHECK_INIT
1187-
1188-PluginInitResult
1189-dia_plugin_init(PluginInfo *info)
1190-{
1191- if (!dia_plugin_info_init(info, "WPG",
1192- _("WordPerfect Graphics export filter"),
1193- NULL, NULL))
1194- return DIA_PLUGIN_INIT_ERROR;
1195-
1196- filter_register_export(&my_export_filter);
1197-#if WPG_WITH_IMPORT
1198- filter_register_import(&my_import_filter);
1199-#endif
1200-
1201- return DIA_PLUGIN_INIT_OK;
1202-}
1+/* Dia -- an diagram creation/manipulation program
2+ * Copyright (C) 1998 Alexander Larsson
3+ *
4+ * wpg.c -- HPGL export plugin for dia
5+ * Copyright (C) 2000, Hans Breuer, <Hans@Breuer.Org>
6+ * based on dummy.c
7+ *
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.
12+ *
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.
17+ *
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.
21+ */
22+
23+/*
24+ * ToDo:
25+ * - if helper points - like arc centers - are not in Dia's extent box
26+ * their clipping produces unpredictable results
27+ * - the font setting needs improvement (maybe on Dia's side)
28+ * - bezier curves are not correctly converted to WPG's poly curve
29+ * (two point beziers are)
30+ *
31+ * MayBe:
32+ * - full featured import (IMO Dia's import support should be improved
33+ * before / on the way ...)
34+ */
35+
36+#include <stdio.h>
37+#include <string.h>
38+#include <math.h>
39+#include <glib.h>
40+
41+#include "config.h"
42+#include "intl.h"
43+#include "message.h"
44+#include "geometry.h"
45+#include "render.h"
46+#include "filter.h"
47+#include "plug-ins.h"
48+
49+/* format specific */
50+#include "wpg_defs.h"
51+
52+/* Import is not yet finished but only implemented to check the
53+ * export capabilities and to investigate other programs WPG
54+ * formats.
55+ * The following is not the reason for <en/dis>abling import,
56+ * but it should do it for now ...
57+ */
58+#define WPG_WITH_IMPORT defined (_MSC_VER)
59+
60+/*
61+ * helper macros
62+ */
63+#define SC(a) ((a) * renderer->Scale)
64+
65+/* --- the renderer --- */
66+#define MY_RENDERER_NAME "WPG"
67+
68+typedef struct _MyRenderer MyRenderer;
69+struct _MyRenderer {
70+ Renderer renderer;
71+
72+ FILE *file;
73+
74+ real Scale;
75+
76+ real dash_length;
77+
78+ WPGStartData Box;
79+ WPGFillAttr FillAttr;
80+ WPGLineAttr LineAttr;
81+ WPGTextStyle TextStyle;
82+
83+ WPGColorRGB* pPal;
84+};
85+
86+/* include function declares and render object "vtable" */
87+#include "../renderer.inc"
88+
89+#define DIAG_NOTE my_log /* */
90+void
91+my_log(MyRenderer* renderer, char* format, ...)
92+{
93+ gchar *string;
94+ va_list args;
95+
96+ g_return_if_fail (format != NULL);
97+
98+ va_start (args, format);
99+ string = g_strdup_vprintf (format, args);
100+ va_end (args);
101+
102+ g_print(string);
103+
104+ g_free(string);
105+}
106+
107+#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
108+/* shortcut if testing of indirection isn't needed anymore */
109+#pragma message("LITTLE_ENDIAN: disabling fwrite_le")
110+#define fwrite_le(a,b,c,d) fwrite(a,b,c,d)
111+#else
112+static size_t
113+fwrite_le(void* buf, size_t size, size_t count, FILE* f)
114+{
115+ size_t n = 0;
116+ guint i;
117+
118+ g_assert((1 == size) || (2 == size) || (4 == size));
119+
120+ if (4 == size)
121+ {
122+ gint32 i32;
123+
124+ for (i = 0; i < count; i++)
125+ {
126+ i32 = GINT32_TO_LE(((gint32*)buf)[i]);
127+ n += fwrite(&i32, sizeof(gint32), 1, f);
128+ }
129+ }
130+ else if (2 == size)
131+ {
132+ gint16 i16;
133+
134+ for (i = 0; i < count; i++)
135+ {
136+ i16 = GINT16_TO_LE(((gint16*)buf)[i]);
137+ n += fwrite(&i16, sizeof(gint16), 1, f);
138+ }
139+ }
140+ else
141+ n = fwrite(buf, size, count, f);
142+
143+ return n;
144+}
145+#endif
146+
147+/*
148+ * color cube len, WPG is limited to 256 colors. To get simple
149+ * color reduction algorithms only 216 = 6^3 of them are used.
150+ */
151+#define CC_LEN 6
152+
153+/*
154+ * "To avoid problems with WPC products the first 16 colors of
155+ * the color map should never be changed".
156+ * Define WPG_NUM_DEF_COLORS to 0 ignore this statement (It
157+ * appears to work more reliable; tested with WinWord 97 and
158+ * Designer 4.1 - the latter does not respect the color maps
159+ * start color).
160+ */
161+#define WPG_NUM_DEF_COLORS 0 /* 16 */
162+
163+/*
164+ * helper functions
165+ */
166+guint8
167+LookupColor(MyRenderer *renderer, Color* colour)
168+{
169+ /* find nearest color in the renderers color map */
170+ /* the following hack does only work with a correctly
171+ sorted color map */
172+ unsigned long i = (int)floor(colour->red * (CC_LEN - 1))
173+ + (int)floor(colour->green * (CC_LEN - 1)) * CC_LEN
174+ + (int)floor(colour->blue * (CC_LEN - 1)) * CC_LEN * CC_LEN;
175+ DIAG_NOTE(renderer, "LookupColor %d.\n", i);
176+ if (i >= CC_LEN * CC_LEN * CC_LEN)
177+ return CC_LEN * CC_LEN * CC_LEN - 1 + WPG_NUM_DEF_COLORS;
178+ else
179+ return i + WPG_NUM_DEF_COLORS;
180+}
181+
182+void
183+WriteRecHead(MyRenderer *renderer, WPG_Type Type, guint32 Size)
184+{
185+ if (Size < 255)
186+ {
187+ WPGHead8 rh;
188+ rh.Type = (guint8)Type;
189+ rh.Size = (guint8)Size;
190+ fwrite(&rh, sizeof(guint8), 2, renderer->file);
191+ }
192+ else if (Size < 32768)
193+ {
194+ WPGHead16 rh;
195+ rh.Type = (guint8)Type;
196+ rh.Dummy = 0xFF;
197+ rh.Size = (guint16)Size;
198+ fwrite(&rh, sizeof(guint8), 2, renderer->file);
199+ fwrite_le(&(rh.Size), sizeof(guint16), 1, renderer->file);
200+ }
201+ else
202+ {
203+ WPGHead32 rh;
204+ rh.Type = (guint8)Type;
205+ rh.Dummy = 0xFF;
206+ rh.Size = Size;
207+
208+ /* To avoid problems with stucture packing this struct
209+ * is written in parts ...
210+ */
211+ fwrite(&rh, sizeof(guint8), 2, renderer->file);
212+ fwrite_le(&rh.Size, sizeof(guint32), 1, renderer->file);
213+ }
214+}
215+
216+void
217+WriteLineAttr(MyRenderer *renderer, Color* colour)
218+{
219+ g_assert(4 == sizeof(WPGLineAttr));
220+
221+ WriteRecHead(renderer, WPG_LINEATTR, sizeof(WPGLineAttr));
222+ renderer->LineAttr.Color = LookupColor(renderer, colour);
223+ fwrite(&renderer->LineAttr, sizeof(guint8), 2, renderer->file);
224+ fwrite_le(&renderer->LineAttr.Width, sizeof(guint16), 1, renderer->file);
225+}
226+
227+void
228+WriteFillAttr(MyRenderer *renderer, Color* colour, gboolean bFill)
229+{
230+ g_assert(2 == sizeof(WPGFillAttr));
231+
232+ WriteRecHead(renderer, WPG_FILLATTR, sizeof(WPGFillAttr));
233+ if (bFill)
234+ {
235+ renderer->FillAttr.Color = LookupColor(renderer, colour);
236+ fwrite(&renderer->FillAttr, sizeof(WPGFillAttr), 1, renderer->file);
237+ }
238+ else
239+ {
240+ WPGFillAttr fa;
241+ fa.Color = LookupColor(renderer, colour);
242+ fa.Type = WPG_FA_HOLLOW;
243+ fwrite(&fa, sizeof(WPGFillAttr), 1, renderer->file);
244+ }
245+}
246+
247+/*
248+ * render functions
249+ */
250+static void
251+begin_render(MyRenderer *renderer, DiagramData *data)
252+{
253+#if 0
254+ const WPGFileHead wpgFileHead = { "\377WPC", 16,
255+ 1, 22,
256+ 1, 0, /* Version */
257+ 0, 0};
258+#else
259+ /* static conversion to little endian */
260+ const char wpgFileHead[16] = {255, 'W', 'P', 'C', 16, 0, 0, 0,
261+ 1, 22, 1, 0, 0, 0, 0, 0};
262+#endif
263+
264+ gint16 i;
265+ guint8* pPal;
266+ Color color = {1, 1, 1};
267+
268+ DIAG_NOTE(renderer, "begin_render\n");
269+
270+ fwrite(&wpgFileHead, 1, 16, renderer->file);
271+
272+ /* bounding box */
273+ WriteRecHead(renderer, WPG_START, sizeof(WPGStartData));
274+#if 0
275+ fwrite(&renderer->Box, sizeof(WPGStartData), 1, renderer->file);
276+#else
277+ g_assert(6 == sizeof(WPGStartData));
278+ fwrite(&renderer->Box, sizeof(guint8), 2, renderer->file);
279+ fwrite_le(&renderer->Box.Width, sizeof(guint16), 2, renderer->file);
280+#endif
281+ /* initialize a well known colormap, see LookupColor */
282+ pPal = g_new(gint8, CC_LEN*CC_LEN*CC_LEN*3);
283+ for (i = 0; i < CC_LEN * CC_LEN * CC_LEN; i++)
284+ {
285+ pPal[3*i ] = ((i % CC_LEN) * 255) / (CC_LEN - 1); /* red */
286+ pPal[3*i+1] = (((i / CC_LEN) % CC_LEN) * 255) / (CC_LEN - 1); /* green */
287+ pPal[3*i+2] = ((i / (CC_LEN * CC_LEN)) * 255) / (CC_LEN - 1); /* blue varies least */
288+ /*
289+ g_print("%d\t%d\t%d\n", pPal[3*i ], pPal[3*i+1], pPal[3*i+2]);
290+ */
291+ }
292+
293+ WriteRecHead(renderer, WPG_COLORMAP, CC_LEN*CC_LEN*CC_LEN*3 + 2*sizeof(guint16));
294+ i = WPG_NUM_DEF_COLORS; /* start color */
295+ fwrite_le(&i, sizeof(gint16), 1, renderer->file);
296+ i = CC_LEN*CC_LEN*CC_LEN;
297+ fwrite_le(&i, sizeof(gint16), 1, renderer->file);
298+ fwrite(pPal, 1, CC_LEN*CC_LEN*CC_LEN*3, renderer->file);
299+
300+ /* FIXME: following 3 lines needed to make filling work !? */
301+ renderer->FillAttr.Type = WPG_FA_SOLID;
302+ WriteFillAttr(renderer, &color, TRUE);
303+ WriteFillAttr(renderer, &color, FALSE);
304+
305+ g_free(pPal);
306+}
307+
308+static void
309+end_render(MyRenderer *renderer)
310+{
311+ DIAG_NOTE(renderer, "end_render\n");
312+
313+ WriteRecHead(renderer, WPG_END, 0); /* no data following */
314+ fclose(renderer->file);
315+}
316+
317+static void
318+set_linewidth(MyRenderer *renderer, real linewidth)
319+{
320+ DIAG_NOTE(renderer, "set_linewidth %f\n", linewidth);
321+
322+ renderer->LineAttr.Width = SC(linewidth);
323+}
324+
325+static void
326+set_linecaps(MyRenderer *renderer, LineCaps mode)
327+{
328+ DIAG_NOTE(renderer, "set_linecaps %d\n", mode);
329+
330+ switch(mode) {
331+ case LINECAPS_BUTT:
332+ break;
333+ case LINECAPS_ROUND:
334+ break;
335+ case LINECAPS_PROJECTING:
336+ break;
337+ default:
338+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
339+ }
340+}
341+
342+static void
343+set_linejoin(MyRenderer *renderer, LineJoin mode)
344+{
345+ DIAG_NOTE(renderer, "set_join %d\n", mode);
346+
347+ switch(mode) {
348+ case LINEJOIN_MITER:
349+ break;
350+ case LINEJOIN_ROUND:
351+ break;
352+ case LINEJOIN_BEVEL:
353+ break;
354+ default:
355+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
356+ }
357+}
358+
359+static void
360+set_linestyle(MyRenderer *renderer, LineStyle mode)
361+{
362+ DIAG_NOTE(renderer, "set_linestyle %d\n", mode);
363+
364+ /* line type */
365+ switch (mode) {
366+ case LINESTYLE_SOLID:
367+ renderer->LineAttr.Type = WPG_LA_SOLID;
368+ break;
369+ case LINESTYLE_DASHED:
370+ if (renderer->dash_length < 0.5)
371+ renderer->LineAttr.Type = WPG_LA_SHORTDASH;
372+ else
373+ renderer->LineAttr.Type = WPG_LA_MEDIUMDASH;
374+ break;
375+ case LINESTYLE_DASH_DOT:
376+ renderer->LineAttr.Type = WPG_LA_DASHDOT;
377+ break;
378+ case LINESTYLE_DASH_DOT_DOT:
379+ renderer->LineAttr.Type = WPG_LA_DASHDOTDOT;
380+ break;
381+ case LINESTYLE_DOTTED:
382+ renderer->LineAttr.Type = WPG_LA_DOTS;
383+ break;
384+ default:
385+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
386+ }
387+}
388+
389+static void
390+set_dashlength(MyRenderer *renderer, real length)
391+{
392+ DIAG_NOTE(renderer, "set_dashlength %f\n", length);
393+
394+ /* dot = 20% of len */
395+ renderer->dash_length = length;
396+}
397+
398+static void
399+set_fillstyle(MyRenderer *renderer, FillStyle mode)
400+{
401+ DIAG_NOTE(renderer, "set_fillstyle %d\n", mode);
402+
403+ switch(mode) {
404+ case FILLSTYLE_SOLID:
405+ renderer->FillAttr.Type = WPG_FA_SOLID;
406+ break;
407+ default:
408+ message_error(MY_RENDERER_NAME ": Unsupported fill mode specified!\n");
409+ }
410+}
411+
412+static void
413+set_font(MyRenderer *renderer, Font *font, real height)
414+{
415+ DIAG_NOTE(renderer, "set_font %f %s\n", height, font->name);
416+ renderer->TextStyle.Height = SC(height);
417+
418+ if (strstr(font->name, "Courier"))
419+ renderer->TextStyle.Font = 0x0DF0;
420+ else if (strstr(font->name, "Times"))
421+ renderer->TextStyle.Font = 0x1950;
422+ else
423+ renderer->TextStyle.Font = 0x1150; /* Helv */
424+}
425+
426+/* Need to translate coord system:
427+ *
428+ * Dia x,y -> Wpg x,-y
429+ *
430+ * doing it before scaling.
431+ */
432+static void
433+draw_line(MyRenderer *renderer,
434+ Point *start, Point *end,
435+ Color *line_colour)
436+{
437+ gint16 pData[4];
438+
439+ DIAG_NOTE(renderer, "draw_line %f,%f -> %f, %f\n",
440+ start->x, start->y, end->x, end->y);
441+
442+ WriteLineAttr(renderer, line_colour);
443+ WriteRecHead(renderer, WPG_LINE, 4 * sizeof(gint16));
444+
445+ /* point data */
446+ pData[0] = SC(start->x);
447+ pData[1] = SC(-start->y);
448+ pData[2] = SC(end->x);
449+ pData[3] = SC(-end->y);
450+
451+ fwrite_le(pData, sizeof(gint16), 4, renderer->file);
452+}
453+
454+static void
455+draw_polyline(MyRenderer *renderer,
456+ Point *points, int num_points,
457+ Color *line_colour)
458+{
459+ int i;
460+ gint16* pData;
461+
462+ DIAG_NOTE(renderer, "draw_polyline n:%d %f,%f ...\n",
463+ num_points, points->x, points->y);
464+
465+ g_return_if_fail(1 < num_points);
466+
467+ WriteLineAttr(renderer, line_colour);
468+ WriteRecHead(renderer, WPG_POLYLINE, num_points * 2 * sizeof(gint16) + sizeof(gint16));
469+
470+ pData = g_new(gint16, num_points * 2);
471+
472+ /* number of points */
473+ pData[0] = num_points;
474+ fwrite_le(pData, sizeof(gint16), 1, renderer->file);
475+
476+ /* point data */
477+ for (i = 0; i < num_points; i++)
478+ {
479+ pData[2*i] = SC(points[i].x);
480+ pData[2*i+1] = SC(-points[i].y);
481+ }
482+
483+ fwrite_le(pData, sizeof(gint16), num_points*2, renderer->file);
484+
485+ g_free(pData);
486+}
487+
488+static void
489+draw_polygon(MyRenderer *renderer,
490+ Point *points, int num_points,
491+ Color *line_colour)
492+{
493+ gint16* pData;
494+ int i;
495+
496+ DIAG_NOTE(renderer, "draw_polygon n:%d %f,%f ...\n",
497+ num_points, points->x, points->y);
498+
499+ WriteLineAttr(renderer, line_colour);
500+ WriteRecHead(renderer, WPG_POLYGON, (num_points * 2 + 1) * sizeof(gint16));
501+
502+ pData = g_new(gint16, num_points * 2);
503+
504+ /* number of vertices */
505+ pData[0] = num_points;
506+ fwrite_le(pData, sizeof(gint16), 1, renderer->file);
507+
508+ /* point data */
509+ for (i = 0; i < num_points; i++)
510+ {
511+ pData[2*i] = SC(points[i].x);
512+ pData[2*i+1] = SC(-points[i].y);
513+ }
514+
515+ fwrite_le(pData, sizeof(gint16), num_points*2, renderer->file);
516+
517+ g_free(pData);
518+}
519+
520+static void
521+fill_polygon(MyRenderer *renderer,
522+ Point *points, int num_points,
523+ Color *colour)
524+{
525+ DIAG_NOTE(renderer, "fill_polygon n:%d %f,%f ...\n",
526+ num_points, points->x, points->y);
527+
528+ WriteFillAttr(renderer, colour, TRUE);
529+ draw_polygon(renderer,points,num_points,colour);
530+ WriteFillAttr(renderer, colour, FALSE);
531+}
532+
533+static void
534+draw_rect(MyRenderer *renderer,
535+ Point *ul_corner, Point *lr_corner,
536+ Color *colour)
537+{
538+ gint16* pData;
539+ DIAG_NOTE(renderer, "draw_rect %f,%f -> %f,%f\n",
540+ ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
541+
542+ WriteLineAttr(renderer, colour);
543+ WriteRecHead(renderer, WPG_RECTANGLE, 4*sizeof(gint16));
544+
545+ pData = g_new(gint16, 4);
546+ pData[0] = SC(ul_corner->x); /* lower left corner ! */
547+ pData[1] = SC(-lr_corner->y);
548+ pData[2] = SC(lr_corner->x - ul_corner->x); /* width */
549+ pData[3] = SC(lr_corner->y - ul_corner->y); /* height */
550+
551+ fwrite_le(pData, sizeof(gint16), 4, renderer->file);
552+
553+ g_free(pData);
554+}
555+
556+static void
557+fill_rect(MyRenderer *renderer,
558+ Point *ul_corner, Point *lr_corner,
559+ Color *colour)
560+{
561+ DIAG_NOTE(renderer, "fill_rect %f,%f -> %f,%f\n",
562+ ul_corner->x, ul_corner->y, lr_corner->x, lr_corner->y);
563+
564+ WriteFillAttr(renderer, colour, TRUE);
565+ draw_rect(renderer, ul_corner, lr_corner, colour);
566+ WriteFillAttr(renderer, colour, FALSE);
567+}
568+
569+static void
570+draw_arc(MyRenderer *renderer,
571+ Point *center,
572+ real width, real height,
573+ real angle1, real angle2,
574+ Color *colour)
575+{
576+ WPGEllipse ell;
577+
578+ DIAG_NOTE(renderer, "draw_arc %fx%f <%f,<%f\n",
579+ width, height, angle1, angle2);
580+
581+ ell.x = SC(center->x);
582+ ell.y = SC(-center->y);
583+ ell.RotAngle = 0;
584+ ell.rx = SC(width / 2.0);
585+ ell.ry = SC(height / 2.0);
586+
587+ ell.StartAngle = angle1;
588+ ell.EndAngle = angle2;
589+ ell.Flags = 0;
590+
591+ WriteLineAttr(renderer, colour);
592+ WriteRecHead(renderer, WPG_ELLIPSE, sizeof(WPGEllipse));
593+
594+ g_assert(16 == sizeof(WPGEllipse));
595+ fwrite_le(&ell, sizeof(guint16), sizeof(WPGEllipse) / sizeof(guint16), renderer->file);
596+}
597+
598+static void
599+fill_arc(MyRenderer *renderer,
600+ Point *center,
601+ real width, real height,
602+ real angle1, real angle2,
603+ Color *colour)
604+{
605+ WPGEllipse ell;
606+
607+ DIAG_NOTE(renderer, "fill_arc %fx%f <%f,<%f\n",
608+ width, height, angle1, angle2);
609+
610+ ell.x = SC(center->x);
611+ ell.y = SC(-center->y);
612+ ell.RotAngle = 0;
613+ ell.rx = SC(width / 2.0);
614+ ell.ry = SC(height / 2.0);
615+
616+ ell.StartAngle = angle1;
617+ ell.EndAngle = angle2;
618+ ell.Flags = 0; /* 0: connect to center; 1: connect start and end */
619+
620+ WriteLineAttr(renderer, colour);
621+ WriteFillAttr(renderer, colour, TRUE);
622+ WriteRecHead(renderer, WPG_ELLIPSE, sizeof(WPGEllipse));
623+
624+ g_assert(16 == sizeof(WPGEllipse));
625+ fwrite_le(&ell, sizeof(guint16), sizeof(WPGEllipse) / sizeof(guint16), renderer->file);
626+ WriteFillAttr(renderer, colour, FALSE);
627+}
628+
629+static void
630+draw_ellipse(MyRenderer *renderer,
631+ Point *center,
632+ real width, real height,
633+ Color *colour)
634+{
635+ WPGEllipse ell;
636+
637+ DIAG_NOTE(renderer, "draw_ellipse %fx%f center @ %f,%f\n",
638+ width, height, center->x, center->y);
639+
640+ ell.x = SC(center->x);
641+ ell.y = SC(-center->y);
642+ ell.RotAngle = 0;
643+ ell.rx = SC(width / 2.0);
644+ ell.ry = SC(height / 2.0);
645+
646+ ell.StartAngle = 0;
647+ ell.EndAngle = 360;
648+ ell.Flags = 0;
649+
650+ WriteLineAttr(renderer, colour);
651+ WriteRecHead(renderer, WPG_ELLIPSE, sizeof(WPGEllipse));
652+
653+ g_assert(16 == sizeof(WPGEllipse));
654+ fwrite_le(&ell, sizeof(guint16), sizeof(WPGEllipse) / sizeof(guint16), renderer->file);
655+}
656+
657+static void
658+fill_ellipse(MyRenderer *renderer,
659+ Point *center,
660+ real width, real height,
661+ Color *colour)
662+{
663+ DIAG_NOTE(renderer, "fill_ellipse %fx%f center @ %f,%f\n",
664+ width, height, center->x, center->y);
665+
666+ WriteFillAttr(renderer, colour, TRUE);
667+ draw_ellipse(renderer,center,width,height,colour);
668+ WriteFillAttr(renderer, colour, FALSE);
669+}
670+
671+static void
672+draw_bezier(MyRenderer *renderer,
673+ BezPoint *points,
674+ int numpoints,
675+ Color *colour)
676+{
677+ gint16* pData;
678+ int i;
679+
680+ DIAG_NOTE(renderer, "draw_bezier n:%d %fx%f ...\n",
681+ numpoints, points->p1.x, points->p1.y);
682+
683+ WriteLineAttr(renderer, colour);
684+ WriteRecHead(renderer, WPG_POLYCURVE, (numpoints * 2) * 2 * sizeof(gint16) + 3 * sizeof(gint16));
685+
686+ pData = g_new(gint16, numpoints * 6);
687+
688+ /* ??? size of equivalent data in pre5.1 files ? */
689+#if 1
690+ memset(pData, 0, sizeof(gint16)*2);
691+#else
692+ /* try first point instead */
693+ pData[0] = SC(points[0].p1.x);
694+ pData[1] = SC(-points[0].p1.y);
695+#endif
696+ fwrite_le(pData, sizeof(gint16), 2, renderer->file);
697+
698+ pData[0] = numpoints * 2;
699+ fwrite_le(pData, sizeof(gint16), 1, renderer->file);
700+
701+ /* WPG's Poly Curve is not quite the same as DIA's Bezier.
702+ * There is only one Control Point per Point and I can't
703+ * get it right, but at least they are read without error.
704+ */
705+ for (i = 0; i < numpoints; i++)
706+ {
707+ switch (points[i].type)
708+ {
709+ case BEZ_MOVE_TO:
710+ case BEZ_LINE_TO:
711+ /* real point */
712+ pData[4*i ] = SC( points[i].p1.x);
713+ pData[4*i+1] = SC(-points[i].p1.y);
714+
715+ /* control point (1st from next point) */
716+ if (i+1 < numpoints) {
717+ pData[4*i+2] = SC( points[i+1].p1.x);
718+ pData[4*i+3] = SC(-points[i+1].p1.y);
719+ }
720+ else {
721+ pData[4*i+2] = SC( points[i].p1.x);
722+ pData[4*i+3] = SC(-points[i].p1.y);
723+ }
724+ break;
725+ case BEZ_CURVE_TO:
726+ if (0 && (i+1 < numpoints)) {
727+ /* real point ?? */
728+ pData[4*i ] = SC( points[i].p3.x);
729+ pData[4*i+1] = SC(-points[i].p3.y);
730+ /* control point (1st from next point) */
731+ pData[4*i+2] = SC( points[i+1].p1.x);
732+ pData[4*i+3] = SC(-points[i+1].p1.y);
733+ }
734+ else {
735+ /* need to swap these ?? */
736+ /* real point ?? */
737+ pData[4*i ] = SC( points[i].p2.x);
738+ pData[4*i+1] = SC(-points[i].p2.y);
739+
740+ /* control point ?? */
741+ pData[4*i+2] = SC( points[i].p3.x);
742+ pData[4*i+3] = SC(-points[i].p3.y);
743+ }
744+ break;
745+ }
746+ }
747+
748+ fwrite_le(pData, sizeof(gint16), numpoints*4, renderer->file);
749+ g_free(pData);
750+}
751+
752+static void
753+fill_bezier(MyRenderer *renderer,
754+ BezPoint *points, /* Last point must be same as first point */
755+ int numpoints,
756+ Color *colour)
757+{
758+ DIAG_NOTE(renderer, "fill_bezier n:%d %fx%f ...\n",
759+ numpoints, points->p1.x, points->p1.y);
760+
761+}
762+
763+static void
764+draw_string(MyRenderer *renderer,
765+ const char *text,
766+ Point *pos, Alignment alignment,
767+ Color *colour)
768+{
769+ gint16 len;
770+ WPGPoint pt;
771+
772+ len = strlen(text);
773+
774+ DIAG_NOTE(renderer, "draw_string(%d) %f,%f %s\n",
775+ len, pos->x, pos->y, text);
776+
777+ if (len < 1) return;
778+
779+ renderer->TextStyle.YAlign = 3; /* bottom ??? */
780+
781+ switch (alignment) {
782+ case ALIGN_LEFT:
783+ renderer->TextStyle.XAlign = 0;
784+ break;
785+ case ALIGN_CENTER:
786+ renderer->TextStyle.XAlign = 1;
787+ break;
788+ case ALIGN_RIGHT:
789+ renderer->TextStyle.XAlign = 2;
790+ break;
791+ }
792+
793+ renderer->TextStyle.Color = LookupColor(renderer, colour);
794+ renderer->TextStyle.Angle = 0;
795+
796+ renderer->TextStyle.Width = renderer->TextStyle.Height * 0.6; /* ??? */
797+
798+ WriteRecHead(renderer, WPG_TEXTSTYLE, sizeof(WPGTextStyle));
799+
800+#if 0
801+ fwrite(&renderer->TextStyle, sizeof(WPGTextStyle), 1, renderer->file);
802+#else
803+ g_assert(22 == sizeof(WPGTextStyle));
804+ fwrite_le(&renderer->TextStyle.Width, sizeof(guint16), 1, renderer->file);
805+ fwrite_le(&renderer->TextStyle.Height, sizeof(guint16), 1, renderer->file);
806+ fwrite(&renderer->TextStyle.Reserved, 1, sizeof(renderer->TextStyle.Reserved), renderer->file);
807+ fwrite_le(&renderer->TextStyle.Font, sizeof(guint16), 1, renderer->file);
808+ fwrite(&renderer->TextStyle.Reserved2, sizeof(guint8), 1, renderer->file);
809+ fwrite(&renderer->TextStyle.XAlign, 1, 1, renderer->file);
810+ fwrite(&renderer->TextStyle.YAlign, 1, 1, renderer->file);
811+ fwrite(&renderer->TextStyle.Color, 1, 1, renderer->file);
812+ fwrite_le(&renderer->TextStyle.Angle, sizeof(guint16), 1, renderer->file);
813+#endif
814+ pt.x = SC(pos->x);
815+ pt.y = SC(-pos->y);
816+
817+ WriteRecHead(renderer, WPG_TEXT, 3*sizeof(gint16) + len);
818+ fwrite_le(&len, sizeof(gint16), 1, renderer->file);
819+ fwrite_le(&pt.x, sizeof(guint16), 1, renderer->file);
820+ fwrite_le(&pt.y, sizeof(guint16), 1, renderer->file);
821+ fwrite(text, 1, len, renderer->file);
822+}
823+
824+static void
825+draw_image(MyRenderer *renderer,
826+ Point *point,
827+ real width, real height,
828+ DiaImage image)
829+{
830+ WPGBitmap2 bmp;
831+ guint8 * pDiaImg = NULL, * pOut = NULL, * pIn = NULL, * p = NULL;
832+ guint8 b_1, b, cnt;
833+ int x, y;
834+
835+ bmp.Angle = 0;
836+ bmp.Left = SC(point->x);
837+ bmp.Top = SC(-point->y - height);
838+ bmp.Right = SC(point->x + width);
839+ bmp.Bottom = SC(-point->y);
840+
841+ bmp.Width = dia_image_width(image);
842+ bmp.Height = dia_image_height(image);
843+ bmp.Depth = 8; /* maximum allowed */
844+
845+ bmp.Xdpi = 72; /* ??? */
846+ bmp.Ydpi = 72;
847+
848+ DIAG_NOTE(renderer, "draw_image %fx%f [%d,%d] @%f,%f\n",
849+ width, height, bmp.Width, bmp.Height, point->x, point->y);
850+
851+ pDiaImg = pIn = dia_image_rgb_data(image);
852+ pOut = g_new(guint8, bmp.Width * bmp.Height * 2); /* space for worst case RLE */
853+ p = pOut;
854+
855+ pIn += (3* bmp.Width * (bmp.Height - 1)); /* last line */
856+ for (y = 0; y < bmp.Height; y++)
857+ {
858+ cnt = 0; /* reset with every line */
859+ for (x = 0; x < bmp.Width; x ++)
860+ {
861+ /* simple color reduction to default palette */
862+ b = (((CC_LEN - 1) * pIn[0]) / 255) /* red */
863+ + (((CC_LEN - 1) * pIn[1]) / 255) * CC_LEN /* green */
864+ + (((CC_LEN - 1) * pIn[2]) / 255) * CC_LEN * CC_LEN /* blue */
865+ + WPG_NUM_DEF_COLORS;
866+
867+ pIn += 3; /* increase read pointer */
868+
869+ if (cnt > 0)
870+ {
871+ if ((b == b_1) && (cnt < 127))
872+ cnt++; /* increase counter*/
873+ else
874+ {
875+ *p++ = (cnt | 0x80); /* write run length and value */
876+ *p++ = b_1;
877+ cnt = 1; /* reset */
878+ b_1 = b;
879+ }
880+ }
881+ else
882+ {
883+ b_1 = b;
884+ cnt = 1;
885+ }
886+ }
887+ *p++ = (cnt | 0x80); /* write last value(s) */
888+ *p++ = b;
889+ pIn -= (3 * bmp.Width * 2); /* start of previous line */
890+ }
891+ DIAG_NOTE(renderer, "Width x Height: %d RLE: %d\n", bmp.Width * bmp.Height, p - pOut);
892+
893+ if ((p - pOut) > 32767) {
894+ g_warning(MY_RENDERER_NAME ": Bitmap size exceeds blocksize. Ignored.");
895+ }
896+ else {
897+ WriteRecHead(renderer, WPG_BITMAP2, sizeof(WPGBitmap2) + (p - pOut));
898+#if 0
899+ fwrite(&bmp, sizeof(WPGBitmap2), 1, renderer->file);
900+#else
901+ g_assert(20 == sizeof(WPGBitmap2));
902+ fwrite(&bmp, sizeof(guint16), sizeof(WPGBitmap2) / sizeof(guint16), renderer->file);
903+#endif
904+ fwrite(pOut, sizeof(guint8), p - pOut, renderer->file);
905+ }
906+#if 1
907+ /* RLE diagnose */
908+ {
909+ FILE* f;
910+ int i, j;
911+ f = fopen("c:\\temp\\wpg_bmp.raw", "wb");
912+ j = p - pOut;
913+ for (i = 0; i < j; i+=2)
914+ {
915+ for (x = 0; x < (pOut[i] & 0x7F); x++)
916+ fwrite(&pOut[i+1], 1, 1, f);
917+ }
918+ fclose(f);
919+ }
920+#endif
921+ g_free(pDiaImg);
922+ g_free(pOut);
923+}
924+
925+static void
926+export_data(DiagramData *data, const gchar *filename, const gchar *diafilename)
927+{
928+ MyRenderer *renderer;
929+ FILE *file;
930+ Rectangle *extent;
931+ gint len;
932+ real width, height;
933+
934+ file = fopen(filename, "wb"); /* "wb" for binary! */
935+
936+ if (file == NULL) {
937+ message_error(_("Couldn't open: '%s' for writing.\n"), filename);
938+ return;
939+ }
940+
941+ renderer = g_new0(MyRenderer, 1);
942+ renderer->renderer.ops = &MyRenderOps;
943+ renderer->renderer.is_interactive = 0;
944+ renderer->renderer.interactive_ops = NULL;
945+
946+ renderer->file = file;
947+
948+ extent = &data->extents;
949+
950+ /* use extents */
951+ DIAG_NOTE(renderer, "export_data extents %f,%f -> %f,%f\n",
952+ extent->left, extent->top, extent->right, extent->bottom);
953+
954+ width = extent->right - extent->left;
955+ height = extent->bottom - extent->top;
956+ renderer->Scale = 0.001;
957+ if (width > height)
958+ while (renderer->Scale * width < 3276.7) renderer->Scale *= 10.0;
959+ else
960+ while (renderer->Scale * height < 3276.7) renderer->Scale *= 10.0;
961+
962+ renderer->Box.Width = width * renderer->Scale;
963+ renderer->Box.Height = height * renderer->Scale;
964+ renderer->Box.Flag = 0;
965+ renderer->Box.Version = 0;
966+
967+ data_render(data, (Renderer *)renderer, NULL, NULL, NULL);
968+
969+ g_free(renderer);
970+}
971+
972+#if WPG_WITH_IMPORT
973+/*
974+ * Import (under construction)
975+ */
976+static void
977+import_object(MyRenderer* renderer, DiagramData *dia,
978+ WPG_Type type, int iSize, guchar* pData)
979+{
980+ WPGPoint* pts = NULL;
981+ gint16* pInt16 = NULL;
982+ int iNum = 0;
983+ gint32 iPre51 = 0;
984+
985+ switch (type) {
986+ case WPG_LINE:
987+ iNum = 2;
988+ pts = (WPGPoint*)pData;
989+ break;
990+ case WPG_POLYLINE:
991+ pInt16 = (gint16*)pData;
992+ iNum = pInt16[0];
993+ pts = (WPGPoint*)(pData + sizeof(gint16));
994+ break;
995+ case WPG_RECTANGLE:
996+ iNum = 2;
997+ pts = (WPGPoint*)pData;
998+ break;
999+ case WPG_POLYGON:
1000+ pInt16 = (gint16*)pData;
1001+ iNum = pInt16[0];
1002+ pts = (WPGPoint*)(pData + sizeof(gint16));
1003+ break;
1004+ case WPG_ELLIPSE:
1005+ {
1006+ WPGEllipse* pEll;
1007+ pEll = (WPGEllipse*)pData;
1008+ }
1009+ break;
1010+ case WPG_POLYCURVE:
1011+ iPre51 = *((gint32*)pData);
1012+ pInt16 = (gint16*)pData;
1013+ iNum = pInt16[2];
1014+ pts = (WPGPoint*)(pData + 3*sizeof(gint16));
1015+ DIAG_NOTE(renderer, "POLYCURVE Num pts %d Pre51 %d\n", iNum, iPre51);
1016+ break;
1017+ } /* switch */
1018+ DIAG_NOTE(renderer, "Type %d Num pts %d Size %d\n", type, iNum, iSize);
1019+}
1020+
1021+static gboolean
1022+import_data (const gchar *filename, DiagramData *dia)
1023+{
1024+ FILE* f;
1025+ gboolean bRet;
1026+ WPGHead8 rh;
1027+
1028+ f = fopen(filename, "rb");
1029+
1030+ if (NULL == f) {
1031+ message_error(_("Couldn't open: '%s' for reading.\n"), filename);
1032+ bRet = FALSE;
1033+ }
1034+
1035+ /* check header */
1036+ if (bRet) {
1037+ WPGFileHead fhead;
1038+ bRet = ( (1 == fread(&fhead, sizeof(WPGFileHead), 1, f))
1039+ && fhead.fid[0] == 255 && fhead.fid[1] == 'W'
1040+ && fhead.fid[2] == 'P' && fhead.fid[3] == 'C'
1041+ && (1 == fhead.MajorVersion) && (0 == fhead.MinorVersion));
1042+ if (!bRet)
1043+ message_error(_("File: %s type/version unsupported.\n"), filename);
1044+ }
1045+
1046+ if (bRet) {
1047+ int iSize;
1048+ gint16 i16, iNum16;
1049+ guint8 i8;
1050+ MyRenderer ren;
1051+
1052+ ren.pPal = g_new0(WPGColorRGB, 256);
1053+
1054+ DIAG_NOTE(&ren, "Parsing: %s \n", filename);
1055+
1056+ do {
1057+ if (1 == fread(&rh, sizeof(WPGHead8), 1, f)) {
1058+ if (rh.Size < 0xFF)
1059+ iSize = rh.Size;
1060+ else {
1061+ bRet = (1 == fread(&i16, sizeof(guint16), 1, f));
1062+ if (0x8000 & i16) {
1063+ DIAG_NOTE(&ren, "Large Object: hi:lo %04X", (int)i16);
1064+ iSize = i16 << 16;
1065+ /* Reading large objects involves major uglyness. Instead of getting
1066+ * one size, as implied by "Encyclopedia of Graphics File Formats",
1067+ * it would require putting together small chunks of data to one large
1068+ * object. The criteria when to stop isn't absolutely clear.
1069+ */
1070+ iSize = 0;
1071+ bRet = (1 == fread(&i16, sizeof(guint16), 1, f));
1072+ DIAG_NOTE(&ren, "Large Object: %d\n", (int)i16);
1073+ iSize += i16;
1074+#if 1
1075+ /* Ignore this large objec part */
1076+ fseek(f, iSize, SEEK_CUR);
1077+ continue;
1078+#endif
1079+ }
1080+ else
1081+ iSize = i16;
1082+ }
1083+ } else
1084+ iSize = 0;
1085+
1086+ //DIAG_NOTE(&ren, "Type %d Size %d\n", rh.Type, iSize);
1087+ if (iSize > 0) {
1088+ switch (rh.Type) {
1089+ case WPG_FILLATTR:
1090+ bRet = (1 == fread(&ren.FillAttr, sizeof(WPGFillAttr), 1, f));
1091+ break;
1092+ case WPG_LINEATTR:
1093+ bRet = (1 == fread(&ren.LineAttr, sizeof(WPGLineAttr), 1, f));
1094+ break;
1095+ case WPG_START:
1096+ bRet = (1 == fread(&ren.Box, sizeof(WPGStartData), 1, f));
1097+ break;
1098+ case WPG_STARTWPG2:
1099+ /* not sure if this is the right thing to do */
1100+ bRet &= (1 == fread(&i8, sizeof(gint8), 1, f));
1101+ bRet &= (1 == fread(&i16, sizeof(gint16), 1, f));
1102+ DIAG_NOTE(&ren, "Ignoring tag WPG_STARTWPG2, Size %d\n Type? %d Size? %d\n",
1103+ iSize, (int)i8, i16);
1104+ fseek(f, iSize - 3, SEEK_CUR);
1105+ break;
1106+ case WPG_LINE:
1107+ case WPG_POLYLINE:
1108+ case WPG_RECTANGLE:
1109+ case WPG_POLYGON:
1110+ case WPG_POLYCURVE:
1111+ case WPG_ELLIPSE:
1112+ {
1113+ guchar* pData;
1114+
1115+ pData = g_new(guchar, iSize);
1116+ bRet = (iSize == (int)fread(pData, 1, iSize, f));
1117+ import_object(&ren, dia, rh.Type, iSize, pData);
1118+ g_free(pData);
1119+ }
1120+ break;
1121+ case WPG_COLORMAP:
1122+ bRet &= (1 == fread(&i16, sizeof(gint16), 1, f));
1123+ bRet &= (1 == fread(&iNum16, sizeof(gint16), 1, f));
1124+ if (iNum16 != (gint16)((iSize - 2) / sizeof(WPGColorRGB)))
1125+ g_warning(MY_RENDERER_NAME ": colormap size/header mismatch.");
1126+ if (i16 >= 0 && i16 <= iSize) {
1127+ bRet &= (iNum16 == (int)fread(&ren.pPal[i16], sizeof(WPGColorRGB), iNum16, f));
1128+ }
1129+ else {
1130+ g_warning(MY_RENDERER_NAME ": start color map index out of range.");
1131+ bRet &= (iNum16 == (int)fread(ren.pPal, sizeof(WPGColorRGB), iNum16, f));
1132+ }
1133+ break;
1134+ case WPG_BITMAP2:
1135+ {
1136+ WPGBitmap2 bmp;
1137+
1138+ fread(&bmp, sizeof(WPGBitmap2), 1, f);
1139+ DIAG_NOTE(&ren, "Bitmap %dx%d %d bits @%d,%d %d,%d.\n",
1140+ bmp.Width, bmp.Height, bmp.Depth,
1141+ bmp.Left, bmp.Top, bmp.Right, bmp.Bottom);
1142+ fseek(f, iSize - sizeof(WPGBitmap2), SEEK_CUR);
1143+ }
1144+ break;
1145+ default:
1146+ fseek(f, iSize, SEEK_CUR);
1147+ g_warning ("Unknown Type %d Size %d.", (int)rh.Type, iSize);
1148+ } /* switch */
1149+ } /* if iSize */
1150+ else {
1151+ if (WPG_END != rh.Type)
1152+ g_warning("Size 0 on Type %d, expecting WPG_END\n", (int)rh.Type);
1153+ }
1154+ }
1155+ while ((iSize > 0) && (bRet));
1156+
1157+ if (!bRet)
1158+ g_warning(MY_RENDERER_NAME ": unexpected eof. Type %d, Size %d.\n",
1159+ rh.Type, iSize);
1160+ if (ren.pPal) g_free(ren.pPal);
1161+ } /* bRet */
1162+
1163+ if (f) fclose(f);
1164+ return bRet;
1165+}
1166+
1167+#endif /* WPG_WITH_IMPORT */
1168+
1169+static const gchar *extensions[] = { "wpg", NULL };
1170+static DiaExportFilter my_export_filter = {
1171+ N_(MY_RENDERER_NAME),
1172+ extensions,
1173+ export_data
1174+};
1175+
1176+#if WPG_WITH_IMPORT
1177+DiaImportFilter my_import_filter = {
1178+ N_(MY_RENDERER_NAME),
1179+ extensions,
1180+ import_data
1181+};
1182+#endif /* WPG_WITH_IMPORT */
1183+
1184+/* --- dia plug-in interface --- */
1185+
1186+DIA_PLUGIN_CHECK_INIT
1187+
1188+PluginInitResult
1189+dia_plugin_init(PluginInfo *info)
1190+{
1191+ if (!dia_plugin_info_init(info, "WPG",
1192+ _("WordPerfect Graphics export filter"),
1193+ NULL, NULL))
1194+ return DIA_PLUGIN_INIT_ERROR;
1195+
1196+ filter_register_export(&my_export_filter);
1197+#if WPG_WITH_IMPORT
1198+ filter_register_import(&my_import_filter);
1199+#endif
1200+
1201+ return DIA_PLUGIN_INIT_OK;
1202+}
--- a/plug-ins/wpg/wpg_defs.h
+++ b/plug-ins/wpg/wpg_defs.h
@@ -1,185 +1,185 @@
1-/*
2- * wpg_defs.h - WordPerfect Graphics Metafile Definitions
3- *
4- * Based on: "Encyclopedia of Graphics File Formats"
5- * by James D. Murray, William vanRyper, Deborah Russel
6- *
7- * Translated to "C" by Hans Breuer <Hans@Breuer.Org>
8- */
9-
10-typedef struct
11-{
12- guchar fid[4];
13- guint32 DataOffset;
14- guint8 ProductType;
15- guint8 FileType;
16- guint8 MajorVersion;
17- guint8 MinorVersion;
18- guint16 EncryptionKey;
19- guint16 Reserved;
20-}
21-WPGFileHead;
22-
23-typedef struct
24-{
25- guint8 Type;
26- guint8 Color;
27- guint16 Width;
28-}
29-WPGLineAttr;
30-
31-typedef struct
32-{
33- guint8 Type;
34- guint8 Color;
35-}
36-WPGFillAttr;
37-
38-typedef struct
39-{
40- guint16 Width;
41- guint16 Height;
42- guint8 Reserved[10];
43-
44- guint16 Font;
45- guint8 Reserved2;
46-
47- guint8 XAlign;
48- guint8 YAlign;
49-
50- guint8 Color;
51- gint16 Angle;
52-}
53-WPGTextStyle;
54-
55-typedef struct
56-{
57- guint8 Version;
58- guint8 Flag;
59- guint16 Width;
60- guint16 Height;
61-}
62-WPGStartData;
63-
64-typedef struct
65-{
66- guint16 x, y; /* center */
67- guint16 rx, ry; /* radius */
68-
69- guint16 RotAngle; /* rotation */
70- guint16 StartAngle, EndAngle; /* 0 - 360ー */
71- guint16 Flags;
72-}
73-WPGEllipse;
74-
75-typedef struct
76-{
77- guint16 Width;
78- guint16 Height;
79- guint16 BitsPerPixel;
80- guint16 Xdpi;
81- guint16 Ydpi;
82-}
83-WPGBitmap1;
84-
85-typedef struct
86-{
87- guint16 Angle;
88- guint16 Left;
89- guint16 Bottom;
90- guint16 Right;
91- guint16 Top;
92- guint16 Width;
93- guint16 Height;
94- guint16 Depth;
95- guint16 Xdpi;
96- guint16 Ydpi;
97-}
98-WPGBitmap2;
99-
100-typedef struct
101-{
102- guint8 Type;
103- guint8 Size;
104-}
105-WPGHead8;
106-
107-typedef struct
108-{
109- guint8 Type;
110- guint8 Dummy;
111- guint16 Size;
112-}
113-WPGHead16;
114-
115-typedef struct
116-{
117- guint8 Type;
118- guint8 Dummy;
119- guint32 Size;
120-}
121-WPGHead32;
122-
123-typedef struct
124-{
125- guint16 x;
126- guint16 y;
127-}
128-WPGPoint;
129-
130-typedef struct
131-{
132- guint8 r;
133- guint8 g;
134- guint8 b;
135-}
136-WPGColorRGB;
137-
138-typedef enum
139-{
140- WPG_FILLATTR = 1,
141- WPG_LINEATTR = 2,
142- WPG_MARKERATTR = 3,
143- WPG_POLYMARKER = 4,
144- WPG_LINE = 5,
145- WPG_POLYLINE = 6,
146- WPG_RECTANGLE = 7,
147- WPG_POLYGON = 8,
148- WPG_ELLIPSE = 9,
149- WPG_BITMAP1 = 11,
150- WPG_TEXT = 12,
151- WPG_TEXTSTYLE = 13,
152- WPG_COLORMAP = 14,
153- WPG_START = 15,
154- WPG_END = 16,
155- WPG_POSTSCRIPT1 = 17,
156- WPG_OUTPUTATTR = 18,
157- WPG_POLYCURVE = 19,
158- WPG_BITMAP2 = 20,
159- WPG_STARTFIGURE = 21,
160- WPG_STARTCHART = 22,
161- WPG_PLANPERFECT = 23,
162- WPG_GRAPHICSTEXT2 = 24,
163- WPG_STARTWPG2 = 25,
164- WPG_GRAPHICSTEXT3 = 26,
165- WPG_POSTSCRIPT2 = 27
166-} WPG_Type;
167-
168-typedef enum
169-{
170- WPG_FA_HOLLOW = 0,
171- WPG_FA_SOLID = 1
172- /* ... */
173-} WPG_FillAttr;
174-
175-typedef enum
176-{
177- WPG_LA_NONE = 0,
178- WPG_LA_SOLID,
179- WPG_LA_LONGDASH,
180- WPG_LA_DOTS,
181- WPG_LA_DASHDOT,
182- WPG_LA_MEDIUMDASH,
183- WPG_LA_DASHDOTDOT,
184- WPG_LA_SHORTDASH
185-} WPG_LineAttr;
1+/*
2+ * wpg_defs.h - WordPerfect Graphics Metafile Definitions
3+ *
4+ * Based on: "Encyclopedia of Graphics File Formats"
5+ * by James D. Murray, William vanRyper, Deborah Russel
6+ *
7+ * Translated to "C" by Hans Breuer <Hans@Breuer.Org>
8+ */
9+
10+typedef struct
11+{
12+ guchar fid[4];
13+ guint32 DataOffset;
14+ guint8 ProductType;
15+ guint8 FileType;
16+ guint8 MajorVersion;
17+ guint8 MinorVersion;
18+ guint16 EncryptionKey;
19+ guint16 Reserved;
20+}
21+WPGFileHead;
22+
23+typedef struct
24+{
25+ guint8 Type;
26+ guint8 Color;
27+ guint16 Width;
28+}
29+WPGLineAttr;
30+
31+typedef struct
32+{
33+ guint8 Type;
34+ guint8 Color;
35+}
36+WPGFillAttr;
37+
38+typedef struct
39+{
40+ guint16 Width;
41+ guint16 Height;
42+ guint8 Reserved[10];
43+
44+ guint16 Font;
45+ guint8 Reserved2;
46+
47+ guint8 XAlign;
48+ guint8 YAlign;
49+
50+ guint8 Color;
51+ gint16 Angle;
52+}
53+WPGTextStyle;
54+
55+typedef struct
56+{
57+ guint8 Version;
58+ guint8 Flag;
59+ guint16 Width;
60+ guint16 Height;
61+}
62+WPGStartData;
63+
64+typedef struct
65+{
66+ guint16 x, y; /* center */
67+ guint16 rx, ry; /* radius */
68+
69+ guint16 RotAngle; /* rotation */
70+ guint16 StartAngle, EndAngle; /* 0 - 360ー */
71+ guint16 Flags;
72+}
73+WPGEllipse;
74+
75+typedef struct
76+{
77+ guint16 Width;
78+ guint16 Height;
79+ guint16 BitsPerPixel;
80+ guint16 Xdpi;
81+ guint16 Ydpi;
82+}
83+WPGBitmap1;
84+
85+typedef struct
86+{
87+ guint16 Angle;
88+ guint16 Left;
89+ guint16 Bottom;
90+ guint16 Right;
91+ guint16 Top;
92+ guint16 Width;
93+ guint16 Height;
94+ guint16 Depth;
95+ guint16 Xdpi;
96+ guint16 Ydpi;
97+}
98+WPGBitmap2;
99+
100+typedef struct
101+{
102+ guint8 Type;
103+ guint8 Size;
104+}
105+WPGHead8;
106+
107+typedef struct
108+{
109+ guint8 Type;
110+ guint8 Dummy;
111+ guint16 Size;
112+}
113+WPGHead16;
114+
115+typedef struct
116+{
117+ guint8 Type;
118+ guint8 Dummy;
119+ guint32 Size;
120+}
121+WPGHead32;
122+
123+typedef struct
124+{
125+ guint16 x;
126+ guint16 y;
127+}
128+WPGPoint;
129+
130+typedef struct
131+{
132+ guint8 r;
133+ guint8 g;
134+ guint8 b;
135+}
136+WPGColorRGB;
137+
138+typedef enum
139+{
140+ WPG_FILLATTR = 1,
141+ WPG_LINEATTR = 2,
142+ WPG_MARKERATTR = 3,
143+ WPG_POLYMARKER = 4,
144+ WPG_LINE = 5,
145+ WPG_POLYLINE = 6,
146+ WPG_RECTANGLE = 7,
147+ WPG_POLYGON = 8,
148+ WPG_ELLIPSE = 9,
149+ WPG_BITMAP1 = 11,
150+ WPG_TEXT = 12,
151+ WPG_TEXTSTYLE = 13,
152+ WPG_COLORMAP = 14,
153+ WPG_START = 15,
154+ WPG_END = 16,
155+ WPG_POSTSCRIPT1 = 17,
156+ WPG_OUTPUTATTR = 18,
157+ WPG_POLYCURVE = 19,
158+ WPG_BITMAP2 = 20,
159+ WPG_STARTFIGURE = 21,
160+ WPG_STARTCHART = 22,
161+ WPG_PLANPERFECT = 23,
162+ WPG_GRAPHICSTEXT2 = 24,
163+ WPG_STARTWPG2 = 25,
164+ WPG_GRAPHICSTEXT3 = 26,
165+ WPG_POSTSCRIPT2 = 27
166+} WPG_Type;
167+
168+typedef enum
169+{
170+ WPG_FA_HOLLOW = 0,
171+ WPG_FA_SOLID = 1
172+ /* ... */
173+} WPG_FillAttr;
174+
175+typedef enum
176+{
177+ WPG_LA_NONE = 0,
178+ WPG_LA_SOLID,
179+ WPG_LA_LONGDASH,
180+ WPG_LA_DOTS,
181+ WPG_LA_DASHDOT,
182+ WPG_LA_MEDIUMDASH,
183+ WPG_LA_DASHDOTDOT,
184+ WPG_LA_SHORTDASH
185+} WPG_LineAttr;