作図ソフト dia の改良版
修訂 | a45b01acbb81b3dbc162ba69a9290df6ed522992 (tree) |
---|---|
時間 | 2000-06-07 18:05:44 |
作者 | James Henstridge <james@daa....> |
Commiter | James Henstridge |
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.
@@ -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 | + | |
1 | 15 | 2000-06-06 James Henstridge <james@daa.com.au> |
2 | 16 | |
3 | 17 | * plug-ins/{hpgl,wmf,wpg}/*: Hans Breuer's plug-ins. They still need |
@@ -187,7 +187,7 @@ get_plugin_manager(void) | ||
187 | 187 | pm.name_label = gtk_label_new(""); |
188 | 188 | gtk_misc_set_alignment(GTK_MISC(pm.name_label), 0.0, 0.5); |
189 | 189 | 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); | |
191 | 191 | gtk_widget_show(pm.name_label); |
192 | 192 | |
193 | 193 | label = gtk_label_new(_("File name:")); |
@@ -199,7 +199,7 @@ get_plugin_manager(void) | ||
199 | 199 | pm.file_label = gtk_label_new(""); |
200 | 200 | gtk_misc_set_alignment(GTK_MISC(pm.file_label), 0.0, 0.5); |
201 | 201 | 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); | |
203 | 203 | gtk_widget_show(pm.file_label); |
204 | 204 | |
205 | 205 | label = gtk_label_new(_("Description:")); |
@@ -213,7 +213,7 @@ get_plugin_manager(void) | ||
213 | 213 | gtk_label_set_justify(GTK_LABEL(pm.description_label), GTK_JUSTIFY_LEFT); |
214 | 214 | gtk_label_set_line_wrap(GTK_LABEL(pm.description_label), TRUE); |
215 | 215 | 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); | |
217 | 217 | gtk_widget_show(pm.description_label); |
218 | 218 | |
219 | 219 | label = gtk_label_new(_("Loaded:")); |
@@ -225,7 +225,7 @@ get_plugin_manager(void) | ||
225 | 225 | pm.loaded_label = gtk_label_new(""); |
226 | 226 | gtk_misc_set_alignment(GTK_MISC(pm.loaded_label), 0.0, 0.5); |
227 | 227 | 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); | |
229 | 229 | gtk_widget_show(pm.loaded_label); |
230 | 230 | |
231 | 231 | pm.autoload_cbutton = gtk_check_button_new_with_label( |
@@ -256,6 +256,8 @@ plug-ins/Makefile | ||
256 | 256 | plug-ins/cgm/Makefile |
257 | 257 | plug-ins/pstricks/Makefile |
258 | 258 | plug-ins/dxf/Makefile |
259 | +plug-ins/hpgl/Makefile | |
260 | +plug-ins/wpg/Makefile | |
259 | 261 | ) |
260 | 262 | |
261 | 263 | echo " |
@@ -269,5 +271,6 @@ Configuration: | ||
269 | 271 | |
270 | 272 | Gnome support: ${GNOME} |
271 | 273 | Build bonobo component (not supported): ${enable_bonobo} |
274 | + Gnome-print support (not recommended): ${enable_gnome_print} | |
272 | 275 | |
273 | 276 | Now type make to build dia." |
@@ -1 +1 @@ | ||
1 | -SUBDIRS = cgm pstricks dxf | |
1 | +SUBDIRS = cgm pstricks dxf hpgl wpg |
@@ -0,0 +1,9 @@ | ||
1 | +.cvsignore | |
2 | +.deps | |
3 | +.libs | |
4 | +Makefile | |
5 | +Makefile.in | |
6 | +*.lo | |
7 | +*.la | |
8 | +*.pyc | |
9 | + |
@@ -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) |
@@ -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 | +} |
@@ -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); | |
163 | 163 | } |
\ No newline at end of file |
@@ -0,0 +1,9 @@ | ||
1 | +.cvsignore | |
2 | +.deps | |
3 | +.libs | |
4 | +Makefile | |
5 | +Makefile.in | |
6 | +*.lo | |
7 | +*.la | |
8 | +*.pyc | |
9 | + |
@@ -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 | +} |
@@ -0,0 +1,9 @@ | ||
1 | +.cvsignore | |
2 | +.deps | |
3 | +.libs | |
4 | +Makefile | |
5 | +Makefile.in | |
6 | +*.lo | |
7 | +*.la | |
8 | +*.pyc | |
9 | + |
@@ -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) |
@@ -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 | +} |
@@ -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; |