1 /* libwmf ("ipa/eps/draw.h"): library for wmf conversion
2    Copyright (C) 2000 - various; see CREDITS, ChangeLog, and sources
3 
4    The libwmf Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8 
9    The libwmf Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public
15    License along with the libwmf Library; see the file COPYING.  If not,
16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18 
19 
wmf_eps_flood_interior(wmfAPI * API,wmfFlood_t * flood)20 static void wmf_eps_flood_interior (wmfAPI* API,wmfFlood_t* flood)
21 {	/* wmf_eps_t* ddata = WMF_EPS_GetData (API); */
22 	(void)flood;
23 	WMF_DEBUG (API,"~~~~~~~~wmf_[eps_]flood_interior");
24 
25 	if (API->flags & WMF_OPT_IGNORE_NONFATAL)
26 	{	WMF_DEBUG (API,"flood_interior unsupported.");
27 	}
28 	else
29 	{	WMF_ERROR (API,"flood_interior unsupported.");
30 		API->err = wmf_E_Glitch;
31 	}
32 }
33 
wmf_eps_flood_exterior(wmfAPI * API,wmfFlood_t * flood)34 static void wmf_eps_flood_exterior (wmfAPI* API,wmfFlood_t* flood)
35 {	/* wmf_eps_t* ddata = WMF_EPS_GetData (API); */
36 	(void)flood;
37 	WMF_DEBUG (API,"~~~~~~~~wmf_[eps_]flood_exterior");
38 
39 	if (API->flags & WMF_OPT_IGNORE_NONFATAL)
40 	{	WMF_DEBUG (API,"flood_exterior unsupported.");
41 	}
42 	else
43 	{	WMF_ERROR (API,"flood_exterior unsupported.");
44 		API->err = wmf_E_Glitch;
45 	}
46 }
47 
wmf_eps_draw_pixel(wmfAPI * API,wmfDrawPixel_t * draw_pixel)48 static void wmf_eps_draw_pixel (wmfAPI* API,wmfDrawPixel_t* draw_pixel)
49 {	wmf_eps_t* ddata = WMF_EPS_GetData (API);
50 
51 	float red;
52 	float green;
53 	float blue;
54 
55 	wmfStream* out = ddata->out;
56 
57 	WMF_DEBUG (API,"~~~~~~~~wmf_[eps_]draw_pixel");
58 
59 	if (out == 0) return;
60 
61 	red   = (float) ((int) draw_pixel->color.r) / 255;
62 	green = (float) ((int) draw_pixel->color.g) / 255;
63 	blue  = (float) ((int) draw_pixel->color.b) / 255;
64 
65 	wmf_stream_printf (API,out,"newpath %f %f moveto ",draw_pixel->pt.x,draw_pixel->pt.y);
66 	wmf_stream_printf (API,out,"%f dup neg exch 0 rlineto 0 %f rlineto 0 rlineto ",
67 	         (float) draw_pixel->pixel_width,
68 	         (float) draw_pixel->pixel_height);
69 
70 	wmf_stream_printf (API,out,"closepath %f %f %f setrgbcolor fill\n",red,green,blue);
71 }
72 
wmf_eps_draw_pie(wmfAPI * API,wmfDrawArc_t * draw_arc)73 static void wmf_eps_draw_pie (wmfAPI* API,wmfDrawArc_t* draw_arc)
74 {	/* wmf_eps_t* ddata = WMF_EPS_GetData (API); */
75 
76 	WMF_DEBUG (API,"~~~~~~~~wmf_[eps_]draw_pie");
77 
78 	eps_draw_arc (API,draw_arc,eps_arc_pie);
79 }
80 
wmf_eps_draw_chord(wmfAPI * API,wmfDrawArc_t * draw_arc)81 static void wmf_eps_draw_chord (wmfAPI* API,wmfDrawArc_t* draw_arc)
82 {	/* wmf_eps_t* ddata = WMF_EPS_GetData (API); */
83 
84 	WMF_DEBUG (API,"~~~~~~~~wmf_[eps_]draw_chord");
85 
86 	eps_draw_arc (API,draw_arc,eps_arc_chord);
87 }
88 
wmf_eps_draw_arc(wmfAPI * API,wmfDrawArc_t * draw_arc)89 static void wmf_eps_draw_arc (wmfAPI* API,wmfDrawArc_t* draw_arc)
90 {	/* wmf_eps_t* ddata = WMF_EPS_GetData (API); */
91 
92 	WMF_DEBUG (API,"~~~~~~~~wmf_[eps_]draw_arc");
93 
94 	eps_draw_arc (API,draw_arc,eps_arc_open);
95 }
96 
wmf_eps_draw_ellipse(wmfAPI * API,wmfDrawArc_t * draw_arc)97 static void wmf_eps_draw_ellipse (wmfAPI* API,wmfDrawArc_t* draw_arc)
98 {	/* wmf_eps_t* ddata = WMF_EPS_GetData (API); */
99 
100 	WMF_DEBUG (API,"~~~~~~~~wmf_[eps_]draw_ellipse");
101 
102 	eps_draw_arc (API,draw_arc,eps_arc_ellipse);
103 }
104 
eps_draw_arc(wmfAPI * API,wmfDrawArc_t * draw_arc,eps_arc_t finish)105 static void eps_draw_arc (wmfAPI* API,wmfDrawArc_t* draw_arc,eps_arc_t finish)
106 {	wmf_eps_t* ddata = WMF_EPS_GetData (API);
107 
108 	float Ox;
109 	float Oy;
110 	float a;
111 	float b;
112 	float start = 0;
113 	float end = 360;
114 	float linewidth;
115 
116 	double x_eff;
117 	double y_eff;
118 	double stretch;
119 
120 	wmfStream* out = ddata->out;
121 
122 	wmfPen* pen = 0;
123 
124 	wmfD_Rect bbox;
125 
126 	WMF_DEBUG (API,"~~~~~~~~eps_draw_arc");
127 
128 	if (out == 0) return;
129 
130 	bbox.TL = draw_arc->TL;
131 	bbox.BR = draw_arc->BR;
132 
133 	Ox = (draw_arc->BR.x + draw_arc->TL.x) / 2; /* origin of ellipse */
134 	Oy = (draw_arc->BR.y + draw_arc->TL.y) / 2;
135 
136 	a = (draw_arc->BR.x - draw_arc->TL.x) / 2;  /* axes of ellipse */
137 	b = (draw_arc->BR.y - draw_arc->TL.y) / 2;
138 
139 	if (finish != eps_arc_ellipse)
140 	{	x_eff = (double) draw_arc->start.x;
141 		y_eff = (double) a * (double) a - x_eff * x_eff;
142 		y_eff = ((y_eff < 0) ? 0 : sqrt (y_eff));
143 		if (draw_arc->start.y < 0) y_eff = - y_eff;
144 		start = (float) (atan2 (y_eff,x_eff) * 180 / PI);
145 
146 		x_eff = (double) draw_arc->end.x;
147 		y_eff = (double) a * (double) a - x_eff * x_eff;
148 		y_eff = ((y_eff < 0) ? 0 : sqrt (y_eff));
149 		if (draw_arc->end.y < 0) y_eff = - y_eff;
150 		end = (float) (atan2 (y_eff,x_eff) * 180 / PI);
151 	}
152 
153 	if (TO_FILL (draw_arc) && (finish != eps_arc_open))
154 	{	wmf_stream_printf (API,out,"gsave %% eps_draw_arc\n");
155 
156 		wmf_stream_printf (API,out,"matrix currentmatrix %f %f translate 1 %f scale ",Ox,Oy,b/a);
157 
158 		if (finish == eps_arc_ellipse)
159 		{	wmf_stream_printf (API,out,"0 0 %f 0 360 arc ",a);
160 		}
161 		else if (finish == eps_arc_pie)
162 		{	wmf_stream_printf (API,out,"0 0 %f %f %f arc 0 0 lineto ",a,start,end);
163 		}
164 		else if (finish == eps_arc_chord)
165 		{	wmf_stream_printf (API,out,"0 0 %f %f %f arc ",a,start,end);
166 		}
167 
168 		wmf_stream_printf (API,out,"closepath setmatrix ");
169 
170 		eps_path_fill (API,draw_arc->dc,&bbox);
171 
172 		wmf_stream_printf (API,out,"grestore\n");
173 	}
174 	if (TO_DRAW (draw_arc))
175 	{	pen = WMF_DC_PEN (draw_arc->dc);
176 
177 		linewidth = (float) WMF_PEN_HEIGHT (pen);
178 		stretch = WMF_PEN_WIDTH (pen) / WMF_PEN_HEIGHT (pen);
179 
180 		wmf_stream_printf (API,out,"gsave %% eps_draw_ellipse\n");
181 
182 		wmf_stream_printf (API,out,"%f 1 scale ",stretch);
183 
184 		wmf_stream_printf (API,out,"matrix currentmatrix %f %f translate 1 %f scale ",
185 		         (float) ((double) Ox / stretch),Oy,b / (float) ((double) a  / stretch));
186 
187 		if (finish == eps_arc_ellipse)
188 		{	wmf_stream_printf (API,out,"0 0 %f 0 360 arc closepath ",a);
189 		}
190 		else if (finish == eps_arc_open)
191 		{	wmf_stream_printf (API,out,"0 0 %f %f %f arc ",a,start,end);
192 		}
193 		else if (finish == eps_arc_pie)
194 		{	wmf_stream_printf (API,out,"0 0 %f %f %f arc 0 0 lineto closepath ",a,start,end);
195 		}
196 		else if (finish == eps_arc_chord)
197 		{	wmf_stream_printf (API,out,"0 0 %f %f %f arc closepath ",a,start,end);
198 		}
199 
200 		wmf_stream_printf (API,out,"setmatrix ");
201 
202 		eps_path_stroke (API,draw_arc->dc,linewidth);
203 
204 		wmf_stream_printf (API,out,"grestore\n");
205 	}
206 }
207 
wmf_eps_draw_line(wmfAPI * API,wmfDrawLine_t * draw_line)208 static void wmf_eps_draw_line (wmfAPI* API,wmfDrawLine_t* draw_line)
209 {	wmf_eps_t* ddata = WMF_EPS_GetData (API);
210 
211 	float linewidth;
212 
213 	double stretch;
214 
215 	wmfStream* out = ddata->out;
216 
217 	wmfPen* pen = 0;
218 
219 	WMF_DEBUG (API,"~~~~~~~~wmf_[eps_]draw_line");
220 
221 	if (out == 0) return;
222 
223 	if (TO_DRAW (draw_line))
224 	{	pen = WMF_DC_PEN (draw_line->dc);
225 
226 		linewidth = (float) WMF_PEN_HEIGHT (pen);
227 		stretch = WMF_PEN_WIDTH (pen) / WMF_PEN_HEIGHT (pen);
228 
229 		wmf_stream_printf (API,out,"gsave %% wmf_[eps_]draw_line\n");
230 
231 		wmf_stream_printf (API,out,"%f 1 scale ",stretch);
232 
233 		wmf_stream_printf (API,out,"newpath %f %f moveto %f %f lineto ",
234 		         (float) ((double) draw_line->from.x / stretch),draw_line->from.y,
235 		         (float) ((double) draw_line->to.x   / stretch),draw_line->to.y  );
236 
237 		eps_path_stroke (API,draw_line->dc,linewidth);
238 
239 		wmf_stream_printf (API,out,"grestore\n");
240 	}
241 }
242 
wmf_eps_poly_line(wmfAPI * API,wmfPolyLine_t * poly_line)243 static void wmf_eps_poly_line (wmfAPI* API,wmfPolyLine_t* poly_line)
244 {	wmf_eps_t* ddata = WMF_EPS_GetData (API);
245 
246 	U16 i;
247 	U16 sub_length;
248 	U16 sub_count;
249 
250 	float linewidth;
251 
252 	double stretch;
253 
254 	wmfPolyLine_t sub_line;
255 
256 	wmfStream* out = ddata->out;
257 
258 	wmfPen* pen = 0;
259 
260 	WMF_DEBUG (API,"~~~~~~~~wmf_[eps_]poly_line");
261 
262 	if (out == 0) return;
263 
264 	if (poly_line->count > 500)
265 	{	sub_length = poly_line->count / (1 + poly_line->count / 500);
266 		sub_count = 0;
267 
268 		sub_line.dc = poly_line->dc;
269 		sub_line.pt = poly_line->pt;
270 
271 		while (poly_line->count > sub_count + 1)
272 		{	sub_line.count = MIN (sub_length,poly_line->count - sub_count);
273 
274 			wmf_eps_poly_line (API,&sub_line);
275 
276 			sub_line.pt += sub_line.count - 1;
277 			sub_count += sub_line.count - 1;
278 		}
279 	}
280 	else if ((poly_line->count > 1) && TO_DRAW (poly_line))
281 	{	pen = WMF_DC_PEN (poly_line->dc);
282 
283 		linewidth = (float) WMF_PEN_HEIGHT (pen);
284 		stretch = WMF_PEN_WIDTH (pen) / WMF_PEN_HEIGHT (pen);
285 
286 		wmf_stream_printf (API,out,"gsave %% wmf_[eps_]poly_line\n");
287 
288 		wmf_stream_printf (API,out,"%f 1 scale\n",stretch);
289 
290 		for (i = 0; i < poly_line->count; i++)
291 		{	wmf_stream_printf (API,out,"%f %f\n",
292 			         (float) ((double) poly_line->pt[poly_line->count-1-i].x / stretch),
293 			         poly_line->pt[poly_line->count-1-i].y);
294 		}
295 
296 		wmf_stream_printf (API,out,"newpath moveto 2 1 %u { pop lineto } for ",(unsigned int) poly_line->count);
297 
298 		eps_path_stroke (API,poly_line->dc,linewidth);
299 
300 		wmf_stream_printf (API,out,"grestore\n");
301 	}
302 }
303 
wmf_eps_draw_polygon(wmfAPI * API,wmfPolyLine_t * poly_line)304 static void wmf_eps_draw_polygon (wmfAPI* API,wmfPolyLine_t* poly_line)
305 {	wmf_eps_t* ddata = WMF_EPS_GetData (API);
306 
307 	U16 i;
308 
309 	float linewidth;
310 
311 	double stretch;
312 
313 	wmfStream* out = ddata->out;
314 
315 	wmfPen* pen = 0;
316 
317 	wmfD_Rect bbox;
318 
319 	WMF_DEBUG (API,"~~~~~~~~wmf_[eps_]draw_polygon");
320 
321 	if (out == 0) return;
322 
323 	if (poly_line->count > 500)
324 	{	if (API->flags & WMF_OPT_IGNORE_NONFATAL)
325 		{	WMF_DEBUG (API,"Too many points on polygon!");
326 		}
327 		else
328 		{	WMF_ERROR (API,"Too many points on polygon!");
329 			API->err = wmf_E_Glitch;
330 		}
331 	}
332 	else if (poly_line->count > 2)
333 	{	if (TO_FILL (poly_line))
334 		{	bbox.TL.x = poly_line->pt[0].x;
335 			bbox.TL.y = poly_line->pt[0].y;
336 			bbox.BR.x = poly_line->pt[0].x;
337 			bbox.BR.y = poly_line->pt[0].y;
338 
339 			wmf_stream_printf (API,out,"gsave %% wmf_[eps_]draw_polygon\n");
340 
341 			for (i = 0; i < poly_line->count; i++)
342 			{	wmf_stream_printf (API,out,"%f %f\n",poly_line->pt[i].x,poly_line->pt[i].y);
343 
344 				if (bbox.TL.x > poly_line->pt[i].x) bbox.TL.x = poly_line->pt[i].x;
345 				if (bbox.TL.y > poly_line->pt[i].y) bbox.TL.y = poly_line->pt[i].y;
346 				if (bbox.BR.x < poly_line->pt[i].x) bbox.BR.x = poly_line->pt[i].x;
347 				if (bbox.BR.y < poly_line->pt[i].y) bbox.BR.y = poly_line->pt[i].y;
348 			}
349 
350 			wmf_stream_printf (API,out,"newpath moveto 2 1 %u { pop lineto } for closepath ",
351 			         (unsigned int) poly_line->count);
352 
353 			eps_path_fill (API,poly_line->dc,&bbox);
354 
355 			wmf_stream_printf (API,out,"grestore\n");
356 		}
357 		if (TO_DRAW (poly_line))
358 		{	pen = WMF_DC_PEN (poly_line->dc);
359 
360 			linewidth = (float) WMF_PEN_HEIGHT (pen);
361 			stretch = WMF_PEN_WIDTH (pen) / WMF_PEN_HEIGHT (pen);
362 
363 			wmf_stream_printf (API,out,"gsave %% wmf_[eps_]draw_polygon\n");
364 
365 			wmf_stream_printf (API,out,"%f 1 scale\n",stretch);
366 
367 			for (i = 0; i < poly_line->count; i++)
368 			{	wmf_stream_printf (API,out,"%f %f\n",
369 				         (float) ((double) poly_line->pt[poly_line->count-1-i].x / stretch),
370 				         poly_line->pt[poly_line->count-1-i].y);
371 			}
372 
373 			wmf_stream_printf (API,out,"newpath moveto 2 1 %u { pop lineto } for closepath ",
374 			         (unsigned int) poly_line->count);
375 
376 			eps_path_stroke (API,poly_line->dc,linewidth);
377 
378 			wmf_stream_printf (API,out,"grestore\n");
379 		}
380 	}
381 }
382 
wmf_eps_draw_rectangle(wmfAPI * API,wmfDrawRectangle_t * draw_rect)383 static void wmf_eps_draw_rectangle (wmfAPI* API,wmfDrawRectangle_t* draw_rect)
384 {	wmf_eps_t* ddata = WMF_EPS_GetData (API);
385 
386 	float linewidth;
387 
388 	double stretch;
389 
390 	wmfStream* out = ddata->out;
391 
392 	wmfPen* pen = 0;
393 
394 	wmfD_Rect bbox;
395 
396 	WMF_DEBUG (API,"~~~~~~~~wmf_[eps_]draw_rectangle");
397 
398 	if (out == 0) return;
399 
400 	if (TO_FILL (draw_rect))
401 	{	bbox.TL = draw_rect->TL;
402 		bbox.BR = draw_rect->BR;
403 
404 		wmf_stream_printf (API,out,"gsave %% wmf_[eps_]draw_rectangle\n");
405 
406 		wmf_stream_printf (API,out,"newpath %f %f moveto %f %f lineto %f %f lineto %f %f lineto closepath ",
407 		         draw_rect->TL.x,draw_rect->TL.y,
408 		         draw_rect->TL.x,draw_rect->BR.y,
409 		         draw_rect->BR.x,draw_rect->BR.y,
410 		         draw_rect->BR.x,draw_rect->TL.y);
411 
412 		eps_path_fill (API,draw_rect->dc,&bbox);
413 
414 		wmf_stream_printf (API,out,"grestore\n");
415 	}
416 	if (TO_DRAW (draw_rect))
417 	{	pen = WMF_DC_PEN (draw_rect->dc);
418 
419 		linewidth = (float) WMF_PEN_HEIGHT (pen);
420 		stretch = WMF_PEN_WIDTH (pen) / WMF_PEN_HEIGHT (pen);
421 
422 		wmf_stream_printf (API,out,"gsave %% wmf_[eps_]draw_rectangle\n");
423 
424 		wmf_stream_printf (API,out,"%f 1 scale ",stretch);
425 
426 		wmf_stream_printf (API,out,"newpath %f %f moveto %f %f lineto %f %f lineto %f %f lineto closepath ",
427 		         (float) ((double) draw_rect->TL.x / stretch),draw_rect->TL.y,
428 		         (float) ((double) draw_rect->TL.x / stretch),draw_rect->BR.y,
429 		         (float) ((double) draw_rect->BR.x / stretch),draw_rect->BR.y,
430 		         (float) ((double) draw_rect->BR.x / stretch),draw_rect->TL.y);
431 
432 		eps_path_stroke (API,draw_rect->dc,linewidth);
433 
434 		wmf_stream_printf (API,out,"grestore\n");
435 	}
436 }
437