1 /* libwmf ("player/meta.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 
20 #ifndef WMFPLAYER_META_H
21 #define WMFPLAYER_META_H
22 
meta_mapmode(wmfAPI * API,wmfRecord * Record)23 static int meta_mapmode (wmfAPI* API,wmfRecord* Record)
24 {	int changed = 0;
25 
26 	U16 par_U16;
27 
28 	if (SCAN (API) && DIAG (API))
29 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
30 		fprintf (stderr,"\t#par=%lu; max. index = 0",Record->size);
31 	}
32 
33 	par_U16 = ParU16 (API,Record,0);
34 
35 	WmfSetMapMode (API,par_U16);
36 
37 	return (changed);
38 }
39 
meta_orgext(wmfAPI * API,wmfRecord * Record)40 static int meta_orgext (wmfAPI* API,wmfRecord* Record)
41 {	int changed = 0;
42 
43 	wmfPlayer_t* P = (wmfPlayer_t*) API->player_data;
44 
45 	S32 par_S32_x;
46 	S32 par_S32_y;
47 
48 	if (SCAN (API) && DIAG (API))
49 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
50 		fprintf (stderr,"\t#par=%lu; max. index = 1",Record->size);
51 	}
52 
53 	par_S32_x = ParS32 (API,Record,1);
54 	par_S32_y = ParS32 (API,Record,0);
55 
56 	switch (Record->function)
57 	{
58 	case META_SETWINDOWORG:
59 		P->dc->Window.Ox = par_S32_x;
60 		P->dc->Window.Oy = par_S32_y;
61 	break;
62 
63 	case META_SETVIEWPORTORG:
64 		P->Viewport_Origin.x = (float) ((double) par_S32_x * P->dc->pixel_width );
65 		P->Viewport_Origin.y = (float) ((double) par_S32_y * P->dc->pixel_height);
66 	break;
67 
68 	case META_SETVIEWPORTEXT:
69 		P->Viewport_Width  = par_S32_x;
70 		P->Viewport_Height = par_S32_y;
71 		PixelWidth (API);
72 		PixelHeight (API); /* Recalculate pixel size */
73 	break;
74 
75 	case META_SETWINDOWEXT:
76 		P->dc->Window.width  = par_S32_x;
77 		P->dc->Window.height = par_S32_y;
78 		PixelWidth (API);
79 		PixelHeight (API); /* Recalculate pixel size */
80 	break;
81 
82 	case META_OFFSETWINDOWORG:
83 		P->dc->Window.Ox += par_S32_x;
84 		P->dc->Window.Oy += par_S32_y;
85 	break;
86 
87 	case META_OFFSETVIEWPORTORG:
88 		P->Viewport_Origin.x += (float) ((double) par_S32_x * P->dc->pixel_width );
89 		P->Viewport_Origin.y += (float) ((double) par_S32_y * P->dc->pixel_height);
90 	break;
91 
92 	default:
93 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
94 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
95 		API->err = wmf_E_Glitch;
96 	break;
97 	}
98 
99 	return (changed);
100 }
101 
meta_scale(wmfAPI * API,wmfRecord * Record)102 static int meta_scale (wmfAPI* API,wmfRecord* Record)
103 {	int changed = 0;
104 
105 	wmfPlayer_t* P = (wmfPlayer_t*) API->player_data;
106 
107 	S32 par_S32_x1;
108 	S32 par_S32_x2;
109 	S32 par_S32_y1;
110 	S32 par_S32_y2;
111 
112 	double x1;
113 	double x2;
114 	double y1;
115 	double y2;
116 
117 	if (SCAN (API) && DIAG (API))
118 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
119 		fprintf (stderr,"\t#par=%lu; max. index = 3",Record->size);
120 	}
121 
122 	par_S32_x2 = ParS32 (API,Record,3);
123 	par_S32_x1 = ParS32 (API,Record,2);
124 	par_S32_y2 = ParS32 (API,Record,1);
125 	par_S32_y1 = ParS32 (API,Record,0);
126 
127 	if ((par_S32_x1 == 0) || (par_S32_y1 == 0))
128 	{	WMF_ERROR (API,"meta file attempts division by zero!");
129 		API->err = wmf_E_BadFormat;
130 		return (changed);
131 	}
132 
133 	x2 = (double) par_S32_x2;
134 	x1 = (double) par_S32_x1;
135 	y2 = (double) par_S32_y2;
136 	y1 = (double) par_S32_y1;
137 
138 	switch (Record->function)
139 	{
140 	case META_SCALEWINDOWEXT:
141 		P->dc->Window.width  = (S32) (((double) P->dc->Window.width  * x2) / x1);
142 		P->dc->Window.height = (S32) (((double) P->dc->Window.height * y2) / y1);
143 	break;
144 
145 	case META_SCALEVIEWPORTEXT:
146 		P->Viewport_Width  = (S32) (((double) P->Viewport_Width  * x2) / x1);
147 		P->Viewport_Height = (S32) (((double) P->Viewport_Height * y2) / y1);
148 	break;
149 
150 	default:
151 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
152 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
153 		API->err = wmf_E_Glitch;
154 	break;
155 	}
156 
157 	PixelWidth (API);
158 	PixelHeight (API); /* Recalculate pixel size */
159 
160 	return (changed);
161 }
162 
meta_moveto(wmfAPI * API,wmfRecord * Record)163 static int meta_moveto (wmfAPI* API,wmfRecord* Record)
164 {	int changed = 0;
165 
166 	wmfPlayer_t* P = (wmfPlayer_t*) API->player_data;
167 
168 	U16 par_U16_x;
169 	U16 par_U16_y;
170 
171 	if (SCAN (API) && DIAG (API))
172 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
173 		fprintf (stderr,"\t#par=%lu; max. index = 1",Record->size);
174 	}
175 
176 	par_U16_x = ParU16 (API,Record,1);
177 	par_U16_y = ParU16 (API,Record,0);
178 
179 	P->current = L_Coord (par_U16_x,par_U16_y);
180 
181 	return (changed);
182 }
183 
meta_flood(wmfAPI * API,wmfRecord * Record)184 static int meta_flood (wmfAPI* API,wmfRecord* Record)
185 {	int changed = 0;
186 
187 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
188 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
189 
190 	wmfL_Coord l_pt;
191 
192 	wmfFlood_t flood;
193 
194 	U16 par_U16_x;
195 	U16 par_U16_y;
196 	U16 par_U16_rg;
197 	U16 par_U16_b;
198 	U16 par_U16_t;
199 
200 	if (SCAN (API) && DIAG (API))
201 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
202 		fprintf (stderr,"\t#par=%lu; max. index = 4",Record->size);
203 	}
204 
205 	par_U16_x  = ParU16 (API,Record,4);
206 	par_U16_y  = ParU16 (API,Record,3);
207 	par_U16_b  = ParU16 (API,Record,2);
208 	par_U16_rg = ParU16 (API,Record,1);
209 	par_U16_t  = ParU16 (API,Record,0);
210 
211 	l_pt = L_Coord (par_U16_x,par_U16_y);
212 
213 	flood.pt = wmf_D_Coord_translate (API,l_pt);
214 
215 	flood.color = rgb (par_U16_rg,par_U16_b);
216 
217 	if (SCAN (API))
218 	{	wmf_ipa_color_add (API,&(flood.color));
219 		D_Coord_Register (API,flood.pt,0);
220 		return (changed);
221 	}
222 
223 	flood.dc = P->dc;
224 
225 	flood.type = par_U16_t;
226 
227 	flood.pixel_width  = ABS (P->dc->pixel_width );
228 	flood.pixel_height = ABS (P->dc->pixel_height);
229 
230 	switch (Record->function)
231 	{
232 	case META_FLOODFILL:
233 		if (FR->flood_interior) FR->flood_interior (API,&flood);
234 	break;
235 
236 	case META_EXTFLOODFILL:
237 		if (FR->flood_exterior) FR->flood_exterior (API,&flood);
238 	break;
239 
240 	default:
241 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
242 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
243 		API->err = wmf_E_Glitch;
244 	break;
245 	}
246 
247 	return (changed);
248 }
249 
meta_pixel(wmfAPI * API,wmfRecord * Record)250 static int meta_pixel (wmfAPI* API,wmfRecord* Record)
251 {	int changed = 0;
252 
253 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
254 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
255 
256 	wmfL_Coord l_pt;
257 
258 	wmfDrawPixel_t drawpixel;
259 
260 	U16 par_U16_x;
261 	U16 par_U16_y;
262 	U16 par_U16_rg;
263 	U16 par_U16_b;
264 
265 	float scope;
266 
267 	if (SCAN (API) && DIAG (API))
268 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
269 		fprintf (stderr,"\t#par=%lu; max. index = 3",Record->size);
270 	}
271 
272 	par_U16_x  = ParU16 (API,Record,3);
273 	par_U16_y  = ParU16 (API,Record,2);
274 	par_U16_b  = ParU16 (API,Record,1);
275 	par_U16_rg = ParU16 (API,Record,0);
276 
277 	l_pt = L_Coord (par_U16_x,par_U16_y);
278 
279 	drawpixel.pt = wmf_D_Coord_translate (API,l_pt);
280 
281 	drawpixel.color = rgb (par_U16_rg,par_U16_b);
282 
283 	drawpixel.pixel_width  = ABS (P->dc->pixel_width );
284 	drawpixel.pixel_height = ABS (P->dc->pixel_height);
285 
286 	if (SCAN (API))
287 	{	wmf_ipa_color_add (API,&(drawpixel.color));
288 		scope = (float) MAX (drawpixel.pixel_width,drawpixel.pixel_height);
289 		D_Coord_Register (API,drawpixel.pt,scope);
290 		return (changed);
291 	}
292 
293 	drawpixel.dc = P->dc;
294 
295 	if (FR->draw_pixel) FR->draw_pixel (API,&drawpixel);
296 
297 	return (changed);
298 }
299 
meta_arc(wmfAPI * API,wmfRecord * Record)300 static int meta_arc (wmfAPI* API,wmfRecord* Record)
301 {	int changed = 0;
302 
303 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
304 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
305 
306 	wmfL_Coord l_pt;
307 	wmfD_Coord d_pt;
308 	wmfD_Coord c_pt;
309 
310 	wmfDrawArc_t drawarc;
311 
312 	wmfPen* pen = 0;
313 
314 	U16 par_U16_x;
315 	U16 par_U16_y;
316 	U16 end_x;
317 	U16 end_y;
318 
319 	char Qs;
320 	char Qe;
321 
322 	float scope = 0;
323 
324 	if (SCAN (API) && DIAG (API))
325 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
326 		fprintf (stderr,"\t#par=%lu; max. index = 7",Record->size);
327 	}
328 
329 	par_U16_x = ParU16 (API,Record,7);
330 	par_U16_y = ParU16 (API,Record,6);
331 
332 	l_pt = L_Coord (par_U16_x,par_U16_y);
333 
334 	drawarc.TL = wmf_D_Coord_translate (API,l_pt);
335 
336 	par_U16_x = ParU16 (API,Record,5);
337 	par_U16_y = ParU16 (API,Record,4);
338 
339 	l_pt = L_Coord (par_U16_x,par_U16_y);
340 
341 	drawarc.BR = wmf_D_Coord_translate (API,l_pt);
342 
343 	par_U16_x = ParU16 (API,Record,3);
344 	par_U16_y = ParU16 (API,Record,2);
345 
346 	l_pt = L_Coord (par_U16_x,par_U16_y);
347 
348 	drawarc.end = wmf_D_Coord_translate (API,l_pt);
349 
350 	end_x = par_U16_x;
351 	end_y = par_U16_y;
352 
353 	par_U16_x = ParU16 (API,Record,1);
354 	par_U16_y = ParU16 (API,Record,0);
355 
356 	if ((end_x == par_U16_x) && (end_y == par_U16_y))
357 	{	/* start == end: This is probably an ellipse... TODO */
358 	}
359 
360 	l_pt = L_Coord (par_U16_x,par_U16_y);
361 
362 	drawarc.start = wmf_D_Coord_translate (API,l_pt);
363 
364 	if (SCAN (API))
365 	{	pen = WMF_DC_PEN (P->dc);
366 
367 		scope = (float) (MAX (WMF_PEN_WIDTH (pen),WMF_PEN_HEIGHT (pen))) / 2;
368 
369 		D_Coord_Register (API,drawarc.end,scope);
370 		D_Coord_Register (API,drawarc.start,scope);
371 	}
372 
373 	c_pt.x = (drawarc.TL.x + drawarc.BR.x) / 2; /* ellipse origin */
374 	c_pt.y = (drawarc.TL.y + drawarc.BR.y) / 2;
375 
376 	drawarc.start.x -= c_pt.x;
377 	drawarc.start.y -= c_pt.y;
378 
379 	drawarc.end.x -= c_pt.x;
380 	drawarc.end.y -= c_pt.y;
381 
382 	if (SCAN (API))
383 	{	if ((drawarc.start.x > 0) && (drawarc.start.y >= 0)) Qs = '1';
384 		else if ((drawarc.start.x <= 0) && (drawarc.start.y > 0)) Qs = '2';
385 		else if ((drawarc.start.x < 0) && (drawarc.start.y <= 0)) Qs = '3';
386 		else Qs = '4';
387 
388 		if ((drawarc.end.x > 0) && (drawarc.end.y >= 0)) Qe = '1';
389 		else if ((drawarc.end.x <= 0) && (drawarc.end.y > 0)) Qe = '2';
390 		else if ((drawarc.end.x < 0) && (drawarc.end.y <= 0)) Qe = '3';
391 		else Qe = '4';
392 
393 		switch (Qs)
394 		{
395 		case '1':
396 			switch (Qe)
397 			{
398 			case '1':
399 				if ( (drawarc.end.x < drawarc.start.x)
400 				  || (drawarc.end.y < drawarc.start.y)) break;
401 				d_pt.x = drawarc.BR.x;
402 				d_pt.y = c_pt.y;
403 				D_Coord_Register (API,d_pt,scope);
404 				/* fallthrough */
405 			case '4':
406 				d_pt.x = c_pt.x;
407 				d_pt.y = drawarc.BR.y;
408 				D_Coord_Register (API,d_pt,scope);
409 				/* fallthrough */
410 			case '3':
411 				d_pt.x = drawarc.TL.x;
412 				d_pt.y = c_pt.y;
413 				D_Coord_Register (API,d_pt,scope);
414 				/* fallthrough */
415 			default:
416 			case '2':
417 				d_pt.x = c_pt.x;
418 				d_pt.y = drawarc.TL.y;
419 				D_Coord_Register (API,d_pt,scope);
420 			break;
421 			}
422 		break;
423 
424 		case '2':
425 			switch (Qe)
426 			{
427 			case '2':
428 				if ( (drawarc.end.x < drawarc.start.x)
429 				  || (drawarc.end.y > drawarc.start.y)) break;
430 				d_pt.x = c_pt.x;
431 				d_pt.y = drawarc.TL.y;
432 				D_Coord_Register (API,d_pt,scope);
433 				/* fallthrough */
434 			case '1':
435 				d_pt.x = drawarc.BR.x;
436 				d_pt.y = c_pt.y;
437 				D_Coord_Register (API,d_pt,scope);
438 				/* fallthrough */
439 			case '4':
440 				d_pt.x = c_pt.x;
441 				d_pt.y = drawarc.BR.y;
442 				D_Coord_Register (API,d_pt,scope);
443 				/* fallthrough */
444 			default:
445 			case '3':
446 				d_pt.x = drawarc.TL.x;
447 				d_pt.y = c_pt.y;
448 				D_Coord_Register (API,d_pt,scope);
449 			break;
450 			}
451 		break;
452 
453 		case '3':
454 			switch (Qe)
455 			{
456 			case '3':
457 				if ( (drawarc.end.x > drawarc.start.x)
458 				  || (drawarc.end.y > drawarc.start.y)) break;
459 				d_pt.x = drawarc.TL.x;
460 				d_pt.y = c_pt.y;
461 				D_Coord_Register (API,d_pt,scope);
462 				/* fallthrough */
463 			case '2':
464 				d_pt.x = c_pt.x;
465 				d_pt.y = drawarc.TL.y;
466 				D_Coord_Register (API,d_pt,scope);
467 				/* fallthrough */
468 			case '1':
469 				d_pt.x = drawarc.BR.x;
470 				d_pt.y = c_pt.y;
471 				D_Coord_Register (API,d_pt,scope);
472 				/* fallthrough */
473 			default:
474 			case '4':
475 				d_pt.x = c_pt.x;
476 				d_pt.y = drawarc.BR.y;
477 				D_Coord_Register (API,d_pt,scope);
478 			break;
479 			}
480 		break;
481 
482 		case '4':
483 		default:
484 			switch (Qe)
485 			{
486 			case '4':
487 				if ( (drawarc.end.x > drawarc.start.x)
488 				  || (drawarc.end.y < drawarc.start.y)) break;
489 				d_pt.x = c_pt.x;
490 				d_pt.y = drawarc.BR.y;
491 				D_Coord_Register (API,d_pt,scope);
492 				/* fallthrough */
493 			case '3':
494 				d_pt.x = drawarc.TL.x;
495 				d_pt.y = c_pt.y;
496 				D_Coord_Register (API,d_pt,scope);
497 				/* fallthrough */
498 			case '2':
499 				d_pt.x = c_pt.x;
500 				d_pt.y = drawarc.TL.y;
501 				D_Coord_Register (API,d_pt,scope);
502 				/* fallthrough */
503 			default:
504 			case '1':
505 				d_pt.x = drawarc.BR.x;
506 				d_pt.y = c_pt.y;
507 				D_Coord_Register (API,d_pt,scope);
508 			break;
509 			}
510 		break;
511 		}
512 
513 		return (changed);
514 	}
515 
516 	d_pt.x = (drawarc.BR.x - drawarc.TL.x) / 2; /* elliptic axes */
517 	d_pt.y = (drawarc.BR.y - drawarc.TL.y) / 2;
518 
519 	if ((drawarc.start.x == 0) && (drawarc.start.y == 0)) drawarc.start.x = d_pt.x;
520 
521 	if (drawarc.start.x >   d_pt.x ) drawarc.start.x =   d_pt.x;
522 	if (drawarc.start.x < (-d_pt.x)) drawarc.start.x = - d_pt.x;
523 	if (drawarc.start.y >   d_pt.y ) drawarc.start.y =   d_pt.y;
524 	if (drawarc.start.y < (-d_pt.y)) drawarc.start.y = - d_pt.y;
525 
526 	if ((drawarc.end.x == 0) && (drawarc.end.y == 0)) drawarc.end.x = d_pt.x;
527 
528 	if (drawarc.end.x >   d_pt.x ) drawarc.end.x =   d_pt.x;
529 	if (drawarc.end.x < (-d_pt.x)) drawarc.end.x = - d_pt.x;
530 	if (drawarc.end.y >   d_pt.y ) drawarc.end.y =   d_pt.y;
531 	if (drawarc.end.y < (-d_pt.y)) drawarc.end.y = - d_pt.y;
532 
533 	drawarc.dc = P->dc;
534 
535 	switch (Record->function)
536 	{
537 	case META_PIE:
538 		if (FR->draw_pie) FR->draw_pie (API,&drawarc);
539 	break;
540 
541 	case META_CHORD:
542 		if (FR->draw_chord) FR->draw_chord (API,&drawarc);
543 	break;
544 
545 	case META_ARC:
546 		if (FR->draw_arc) FR->draw_arc (API,&drawarc);
547 	break;
548 
549 	default:
550 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
551 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
552 		API->err = wmf_E_Glitch;
553 	break;
554 	}
555 
556 	return (changed);
557 }
558 
meta_ellipse(wmfAPI * API,wmfRecord * Record)559 static int meta_ellipse (wmfAPI* API,wmfRecord* Record)
560 {	int changed = 0;
561 
562 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
563 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
564 
565 	wmfL_Coord l_pt;
566 
567 	wmfDrawArc_t drawarc;
568 
569 	wmfPen* pen = 0;
570 
571 	U16 par_U16_x;
572 	U16 par_U16_y;
573 
574 	float scope;
575 
576 	if (SCAN (API) && DIAG (API))
577 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
578 		fprintf (stderr,"\t#par=%lu; max. index = 3",Record->size);
579 	}
580 
581 	par_U16_x = ParU16 (API,Record,3);
582 	par_U16_y = ParU16 (API,Record,2);
583 
584 	l_pt = L_Coord (par_U16_x,par_U16_y);
585 
586 	drawarc.TL = wmf_D_Coord_translate (API,l_pt);
587 
588 	par_U16_x = ParU16 (API,Record,1);
589 	par_U16_y = ParU16 (API,Record,0);
590 
591 	l_pt = L_Coord (par_U16_x,par_U16_y);
592 
593 	drawarc.BR = wmf_D_Coord_translate (API,l_pt);
594 
595 	if (SCAN (API))
596 	{	pen = WMF_DC_PEN (P->dc);
597 
598 		scope = (float) (MAX (WMF_PEN_WIDTH (pen),WMF_PEN_HEIGHT (pen))) / 2;
599 
600 		D_Coord_Register (API,drawarc.TL,scope);
601 		D_Coord_Register (API,drawarc.BR,scope);
602 		return (changed);
603 	}
604 
605 	drawarc.dc = P->dc;
606 
607 	if (FR->draw_ellipse) FR->draw_ellipse (API,&drawarc);
608 
609 	return (changed);
610 }
611 
meta_line(wmfAPI * API,wmfRecord * Record)612 static int meta_line (wmfAPI* API,wmfRecord* Record)
613 {	int changed = 0;
614 
615 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
616 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
617 
618 	wmfL_Coord l_pt;
619 
620 	wmfDrawLine_t drawline;
621 
622 	wmfPen* pen = 0;
623 
624 	U16 par_U16_x;
625 	U16 par_U16_y;
626 
627 	float scope;
628 
629 	if (SCAN (API) && DIAG (API))
630 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
631 		fprintf (stderr,"\t#par=%lu; max. index = 1",Record->size);
632 	}
633 
634 	drawline.from = wmf_D_Coord_translate (API,P->current);
635 
636 	par_U16_x = ParU16 (API,Record,1);
637 	par_U16_y = ParU16 (API,Record,0);
638 
639 	l_pt = L_Coord (par_U16_x,par_U16_y);
640 
641 	drawline.to = wmf_D_Coord_translate (API,l_pt);
642 
643 	P->current = l_pt;
644 
645 	if (SCAN (API))
646 	{	pen = WMF_DC_PEN (P->dc);
647 
648 		scope = (float) (MAX (WMF_PEN_WIDTH (pen),WMF_PEN_HEIGHT (pen))) / 2;
649 
650 		D_Coord_Register (API,drawline.from,scope);
651 		D_Coord_Register (API,drawline.to,scope);
652 		return (changed);
653 	}
654 
655 	drawline.dc = P->dc;
656 
657 	if (FR->draw_line) FR->draw_line (API,&drawline);
658 
659 	return (changed);
660 }
661 
meta_lines(wmfAPI * API,wmfRecord * Record)662 static int meta_lines (wmfAPI* API,wmfRecord* Record)
663 {	int changed = 0;
664 
665 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
666 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
667 
668 	wmfL_Coord l_pt;
669 	wmfD_Coord d_pt;
670 
671 	wmfPolyLine_t polyline;
672 
673 	wmfPen* pen = 0;
674 
675 	U16 par_U16_x;
676 	U16 par_U16_y;
677 
678 	U16 i;
679 
680 	unsigned long index;
681 
682 	float scope;
683 
684 	if (SCAN (API) && DIAG (API))
685 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
686 		fprintf (stderr,"\t#par=%lu; max. index = 0",Record->size);
687 	}
688 
689 	polyline.count = ParU16 (API,Record,0);
690 
691 	if (SCAN (API) && DIAG (API))
692 	{	fprintf (stderr,",%lu",(unsigned long) (2 * polyline.count));
693 	}
694 
695 	if (SCAN (API))
696 	{	pen = WMF_DC_PEN (P->dc);
697 
698 		scope = (float) (MAX (WMF_PEN_WIDTH (pen),WMF_PEN_HEIGHT (pen))) / 2;
699 
700 		index = 1;
701 		for (i = 0; i < polyline.count; i++)
702 		{	par_U16_x = ParU16 (API,Record,index);
703 			index++;
704 			par_U16_y = ParU16 (API,Record,index);
705 			index++;
706 			l_pt = L_Coord (par_U16_x,par_U16_y);
707 			d_pt = wmf_D_Coord_translate (API,l_pt);
708 			D_Coord_Register (API,d_pt,scope);
709 		}
710 		return (changed);
711 	}
712 
713 	polyline.pt = (wmfD_Coord*) wmf_malloc (API,polyline.count * sizeof (wmfD_Coord));
714 
715 	if (ERR (API))
716 	{	WMF_DEBUG (API,"bailing...");
717 		return (changed);
718 	}
719 
720 	index = 1;
721 	for (i = 0; i < polyline.count; i++)
722 	{	par_U16_x = ParU16 (API,Record,index);
723 		index++;
724 		par_U16_y = ParU16 (API,Record,index);
725 		index++;
726 		l_pt = L_Coord (par_U16_x,par_U16_y);
727 		polyline.pt[i] = wmf_D_Coord_translate (API,l_pt);
728 	}
729 
730 	polyline.dc = P->dc;
731 
732 	if (FR->poly_line) FR->poly_line (API,&polyline);
733 
734 	wmf_free (API,polyline.pt);
735 
736 	return (changed);
737 }
738 
meta_polygon(wmfAPI * API,wmfRecord * Record)739 static int meta_polygon (wmfAPI* API,wmfRecord* Record)
740 {	int changed = 0;
741 
742 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
743 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
744 
745 	wmfL_Coord l_pt;
746 	wmfD_Coord d_pt;
747 
748 	wmfPolyLine_t polyline;
749 
750 	wmfPen* pen = 0;
751 
752 	U16 par_U16_x;
753 	U16 par_U16_y;
754 
755 	U16 i;
756 
757 	unsigned long index;
758 
759 	float scope;
760 
761 	if (SCAN (API) && DIAG (API))
762 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
763 		fprintf (stderr,"\t#par=%lu; max. index = 0",Record->size);
764 	}
765 
766 	polyline.count = ParU16 (API,Record,0);
767 
768 	if (SCAN (API) && DIAG (API))
769 	{	fprintf (stderr,",%lu",(unsigned long) (2 * polyline.count));
770 	}
771 
772 	if (SCAN (API))
773 	{	pen = WMF_DC_PEN (P->dc);
774 
775 		scope = (float) (MAX (WMF_PEN_WIDTH (pen),WMF_PEN_HEIGHT (pen))) / 2;
776 
777 		index = 1;
778 		for (i = 0; i < polyline.count; i++)
779 		{	par_U16_x = ParU16 (API,Record,index);
780 			index++;
781 			par_U16_y = ParU16 (API,Record,index);
782 			index++;
783 			l_pt = L_Coord (par_U16_x,par_U16_y);
784 			d_pt = wmf_D_Coord_translate (API,l_pt);
785 			D_Coord_Register (API,d_pt,scope);
786 		}
787 		return (changed);
788 	}
789 
790 	polyline.pt = (wmfD_Coord*) wmf_malloc (API,polyline.count * sizeof (wmfD_Coord));
791 
792 	if (ERR (API))
793 	{	WMF_DEBUG (API,"bailing...");
794 		return (changed);
795 	}
796 
797 	index = 1;
798 	for (i = 0; i < polyline.count; i++)
799 	{	par_U16_x = ParU16 (API,Record,index);
800 		index++;
801 		par_U16_y = ParU16 (API,Record,index);
802 		index++;
803 		l_pt = L_Coord (par_U16_x,par_U16_y);
804 		polyline.pt[i] = wmf_D_Coord_translate (API,l_pt);
805 	}
806 
807 	polyline.dc = P->dc;
808 
809 	if (FR->draw_polygon) FR->draw_polygon (API,&polyline);
810 
811 	wmf_free (API,polyline.pt);
812 
813 	return (changed);
814 }
815 
meta_polygons(wmfAPI * API,wmfRecord * Record)816 static int meta_polygons (wmfAPI* API,wmfRecord* Record)
817 {	int changed = 0;
818 
819 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
820 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
821 
822 	wmfL_Coord l_pt;
823 	wmfD_Coord d_pt;
824 
825 	wmfPolyLine_t polyline;
826 	wmfPolyPoly_t polypoly;
827 
828 	wmfRecord Polygon;
829 
830 	wmfPen* pen = 0;
831 
832 	U16 par_U16_x;
833 	U16 par_U16_y;
834 
835 	U16 num_pars;
836 	U16 count;
837 	U16 style;
838 
839 	U16 i;
840 	U16 j;
841 
842 	unsigned long index;
843 
844 	float scope;
845 
846 	int skip_record;
847 
848 	if (SCAN (API) && DIAG (API))
849 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
850 		fprintf (stderr,"\t#par=%lu; max. index = 0",Record->size);
851 	}
852 
853 	polypoly.npoly = ParU16 (API,Record,0);
854 
855 	if (polypoly.npoly == 0) return (changed);
856 
857 	if (SCAN (API) && DIAG (API))
858 	{	fprintf (stderr,",%lu",(unsigned long) polypoly.npoly);
859 	}
860 
861 	polypoly.pt = (wmfD_Coord**) wmf_malloc (API, polypoly.npoly * sizeof (wmfD_Coord*));
862 
863 	if (ERR (API))
864 	{	WMF_DEBUG (API,"bailing...");
865 		return (changed);
866 	}
867 
868 	polypoly.count = (U16*) wmf_malloc (API, polypoly.npoly * sizeof (U16));
869 
870 	if (ERR (API))
871 	{	WMF_DEBUG (API,"bailing...");
872 		return (changed);
873 	}
874 
875 	count = 0;
876 	num_pars = 0;
877 	skip_record = 0;
878 	for (i = 0; i < polypoly.npoly; i++)
879 	{	polypoly.count[i] = ParU16 (API,Record,(unsigned long) (1 + i));
880 		count += polypoly.count[i] + 2; /* for polypoly->polyline fill constructor */
881 		num_pars += polypoly.count[i];
882 		if ((polypoly.count[i] < 3) && (skip_record == 0))
883 		{	WMF_DEBUG (API,"strange polygon in polypolygon list; skipping record...");
884 			skip_record = 1;
885 		}
886 		if (skip_record)
887 		{	polypoly.pt[i] = 0;
888 		}
889 		else
890 		{	polypoly.pt[i] = (wmfD_Coord*) wmf_malloc (API, polypoly.count[i] * sizeof (wmfD_Coord));
891 			if (ERR (API)) break;
892 		}
893 	}
894 	if (skip_record)
895 	{
896 		for (i = 0; i < polypoly.npoly; i++)
897 		{	if (polypoly.pt[i]) wmf_free (API, polypoly.pt[i]);
898 		}
899 		wmf_free (API, polypoly.pt);
900 		wmf_free (API, polypoly.count);
901 		return (changed);
902 	}
903 	if (ERR (API))
904 	{	WMF_DEBUG (API,"bailing...");
905 		return (changed);
906 	}
907 
908 	if (SCAN (API) && DIAG (API))
909 	{	fprintf (stderr,",%lu",(unsigned long) (polypoly.npoly + 2 * num_pars));
910 	}
911 
912 	if (SCAN (API))
913 	{	pen = WMF_DC_PEN (P->dc);
914 
915 		scope = (float) (MAX (WMF_PEN_WIDTH (pen),WMF_PEN_HEIGHT (pen))) / 2;
916 
917 		index = 1 + polypoly.npoly;
918 		for (i = 0; i < num_pars; i++)
919 		{	par_U16_x = ParU16 (API,Record,index);
920 			index++;
921 			par_U16_y = ParU16 (API,Record,index);
922 			index++;
923 			l_pt = L_Coord (par_U16_x,par_U16_y);
924 			d_pt = wmf_D_Coord_translate (API,l_pt);
925 			D_Coord_Register (API,d_pt,scope);
926 		}
927 		return (changed);
928 	}
929 
930 	polypoly.dc = P->dc;
931 
932 	Polygon = OffsetRecord (API,Record,(unsigned long) (1 + polypoly.npoly));
933 
934 	for (i = 0; i < polypoly.npoly; i++)
935 	{	polyline.count = polypoly.count[i];
936 		index = 0;
937 		for (j = 0; j < polyline.count; j++)
938 		{	par_U16_x = ParU16 (API,&Polygon,index);
939 			index++;
940 			par_U16_y = ParU16 (API,&Polygon,index);
941 			index++;
942 			l_pt = L_Coord (par_U16_x,par_U16_y);
943 			polypoly.pt[i][j] = wmf_D_Coord_translate (API,l_pt);
944 		}
945 		Polygon = OffsetRecord (API,&Polygon,index);
946 	}
947 
948 	if (FR->draw_polypolygon)
949 	{	FR->draw_polypolygon (API,&polypoly);
950 	}
951 	else if (FR->draw_polygon)
952 	{	if (TO_FILL (&polypoly))
953 		{	style = polypoly.dc->pen->lopnStyle; /* [TODO: use macros ??] */
954 			polypoly.dc->pen->lopnStyle = PS_NULL;
955 
956 			polyline.dc = polypoly.dc;
957 			polyline.pt = (wmfD_Coord*) wmf_malloc (API, count * sizeof (wmfD_Coord));
958 			polyline.count = 0;
959 
960 			if (ERR (API))
961 			{	WMF_DEBUG (API,"bailing...");
962 				return (changed);
963 			}
964 
965 			polypoly_construct (API, &polypoly, &polyline, 0);
966 
967 			if (polyline.count > 2) FR->draw_polygon (API,&polyline);
968 
969 			wmf_free (API, polyline.pt);
970 
971 			polypoly.dc->pen->lopnStyle = style;
972 		}
973 		if (TO_DRAW (&polypoly))
974 		{	style = polypoly.dc->brush->lbStyle; /* [TODO: use macros ??] */
975 			polypoly.dc->brush->lbStyle = BS_NULL;
976 			for (i = 0; i < polypoly.npoly; i++)
977 			{	polyline.dc = polypoly.dc;
978 				polyline.pt = polypoly.pt[i];
979 				polyline.count = polypoly.count[i];
980 				if ((polyline.count > 2) && polyline.pt)
981 				{	FR->draw_polygon (API,&polyline);
982 				}
983 			}
984 			polypoly.dc->brush->lbStyle = style;
985 		}
986 	}
987 
988 	for (i = 0; i < polypoly.npoly; i++)
989 	{	if (polypoly.pt[i]) wmf_free (API, polypoly.pt[i]);
990 	}
991 	wmf_free (API, polypoly.pt);
992 	wmf_free (API, polypoly.count);
993 
994 	return (changed);
995 }
996 
polypoly_construct(wmfAPI * API,wmfPolyPoly_t * polypoly,wmfPolyLine_t * polyline,U16 ipoly)997 static void polypoly_construct (wmfAPI* API,wmfPolyPoly_t* polypoly,wmfPolyLine_t* polyline,U16 ipoly)
998 {	U16 count = polypoly->count[ipoly];
999 	U16 i;
1000 	U16 imin;
1001 	U16 last;
1002 
1003 	double x2;
1004 	double y2;
1005 	double r2;
1006 	double r2_min = 0;
1007 
1008 	if ((polyline->pt == 0) || (polypoly->pt == 0)) return; /* erk!! */
1009 
1010 	if ((polypoly->pt[ipoly] == 0) || (polypoly->count[ipoly] < 3)) return;
1011 
1012 	while ((polypoly->pt[ipoly][0].x == polypoly->pt[ipoly][count-1].x)
1013 	    && (polypoly->pt[ipoly][0].y == polypoly->pt[ipoly][count-1].y))
1014 	{
1015 		count--;
1016 		if (count < 3) break;
1017 	}
1018 	if (count < 3) return;
1019 
1020 	last = 0;
1021 	if (ipoly < (polypoly->npoly - 1))
1022 	{	if ((polypoly->pt[ipoly+1] == 0) || (polypoly->count[ipoly+1] < 3))
1023 		{	last = 1; /* erk!! */
1024 		}
1025 	}
1026 	else
1027 	{	last = 1; /* last poly, yay! */
1028 	}
1029 	if (last)
1030 	{	for (i = 0; i < count; i++)
1031 		{	polyline->pt[polyline->count].x = polypoly->pt[ipoly][i].x;
1032 			polyline->pt[polyline->count].y = polypoly->pt[ipoly][i].y;
1033 			polyline->count++;
1034 		}
1035 		polyline->pt[polyline->count].x = polypoly->pt[ipoly][0].x;
1036 		polyline->pt[polyline->count].y = polypoly->pt[ipoly][0].y;
1037 		polyline->count++;
1038 
1039 		return;
1040 	}
1041 
1042 	/* find polygon point closest to point 0 in next polygon [TODO: improve this??]
1043 	 */
1044 	imin = 0;
1045 	for (i = 0; i < count; i++)
1046 	{	x2 = (double) polypoly->pt[ipoly][i].x - (double) polypoly->pt[ipoly+1][0].x;
1047 		x2 *= x2;
1048 		y2 = (double) polypoly->pt[ipoly][i].y - (double) polypoly->pt[ipoly+1][0].y;
1049 		y2 *= y2;
1050 		r2 = x2 + y2;
1051 		if (i == 0)
1052 		{	r2_min = r2;
1053 		}
1054 		else if (r2 < r2_min)
1055 		{	r2_min = r2;
1056 			imin = i;
1057 		}
1058 	}
1059 
1060 	for (i = 0; i <= imin; i++)
1061 	{	polyline->pt[polyline->count].x = polypoly->pt[ipoly][i].x;
1062 		polyline->pt[polyline->count].y = polypoly->pt[ipoly][i].y;
1063 		polyline->count++;
1064 	}
1065 
1066 	polypoly_construct (API, polypoly, polyline, (U16)(ipoly + 1));
1067 
1068 	for (i = imin; i < count; i++)
1069 	{	polyline->pt[polyline->count].x = polypoly->pt[ipoly][i].x;
1070 		polyline->pt[polyline->count].y = polypoly->pt[ipoly][i].y;
1071 		polyline->count++;
1072 	}
1073 	polyline->pt[polyline->count].x = polypoly->pt[ipoly][0].x;
1074 	polyline->pt[polyline->count].y = polypoly->pt[ipoly][0].y;
1075 	polyline->count++;
1076 }
1077 
meta_round(wmfAPI * API,wmfRecord * Record)1078 static int meta_round (wmfAPI* API,wmfRecord* Record)
1079 {	int changed = 0;
1080 
1081 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
1082 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
1083 
1084 	wmfL_Coord l_pt;
1085 
1086 	wmfDrawRectangle_t drawrect;
1087 
1088 	wmfPen* pen = 0;
1089 
1090 	U16 par_U16_x;
1091 	U16 par_U16_y;
1092 
1093 	float scope;
1094 
1095 	if (SCAN (API) && DIAG (API))
1096 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
1097 		fprintf (stderr,"\t#par=%lu; max. index = 5",Record->size);
1098 	}
1099 
1100 	par_U16_x = ParU16 (API,Record,5);
1101 	par_U16_y = ParU16 (API,Record,4);
1102 
1103 	l_pt = L_Coord (par_U16_x,par_U16_y);
1104 
1105 	drawrect.TL = wmf_D_Coord_translate (API,l_pt);
1106 
1107 	par_U16_x = ParU16 (API,Record,3);
1108 	par_U16_y = ParU16 (API,Record,2);
1109 
1110 	l_pt = L_Coord (par_U16_x,par_U16_y);
1111 
1112 	drawrect.BR = wmf_D_Coord_translate (API,l_pt);
1113 
1114 	if (SCAN (API))
1115 	{	pen = WMF_DC_PEN (P->dc);
1116 
1117 		scope = (float) (MAX (WMF_PEN_WIDTH (pen),WMF_PEN_HEIGHT (pen))) / 2;
1118 
1119 		D_Coord_Register (API,drawrect.TL,scope);
1120 		D_Coord_Register (API,drawrect.BR,scope);
1121 		return (changed);
1122 	}
1123 
1124 	par_U16_x = ParU16 (API,Record,1);
1125 	par_U16_y = ParU16 (API,Record,0);
1126 
1127 	drawrect.width  = (float) ((double) par_U16_x * ABS (P->dc->pixel_width ));
1128 	drawrect.height = (float) ((double) par_U16_y * ABS (P->dc->pixel_height));
1129 
1130 	drawrect.dc = P->dc;
1131 
1132 	if (FR->draw_rectangle) FR->draw_rectangle (API,&drawrect);
1133 
1134 	return (changed);
1135 }
1136 
meta_rect(wmfAPI * API,wmfRecord * Record)1137 static int meta_rect (wmfAPI* API,wmfRecord* Record)
1138 {	int changed = 0;
1139 
1140 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
1141 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
1142 
1143 	wmfL_Coord l_pt;
1144 
1145 	wmfDrawRectangle_t drawrect;
1146 
1147 	wmfPen* pen = 0;
1148 
1149 	U16 par_U16_x;
1150 	U16 par_U16_y;
1151 
1152 	float scope;
1153 
1154 	if (SCAN (API) && DIAG (API))
1155 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
1156 		fprintf (stderr,"\t#par=%lu; max. index = 3",Record->size);
1157 	}
1158 
1159 	par_U16_x = ParU16 (API,Record,3);
1160 	par_U16_y = ParU16 (API,Record,2);
1161 
1162 	l_pt = L_Coord (par_U16_x,par_U16_y);
1163 
1164 	drawrect.TL = wmf_D_Coord_translate (API,l_pt);
1165 
1166 	par_U16_x = ParU16 (API,Record,1);
1167 	par_U16_y = ParU16 (API,Record,0);
1168 
1169 	l_pt = L_Coord (par_U16_x,par_U16_y);
1170 
1171 	drawrect.BR = wmf_D_Coord_translate (API,l_pt);
1172 
1173 	if (SCAN (API))
1174 	{	pen = WMF_DC_PEN (P->dc);
1175 
1176 		scope = (float) (MAX (WMF_PEN_WIDTH (pen),WMF_PEN_HEIGHT (pen))) / 2;
1177 
1178 		D_Coord_Register (API,drawrect.TL,scope);
1179 		D_Coord_Register (API,drawrect.BR,scope);
1180 		return (changed);
1181 	}
1182 
1183 	drawrect.width  = 0;
1184 	drawrect.height = 0;
1185 
1186 	drawrect.dc = P->dc;
1187 
1188 	if (FR->draw_rectangle) FR->draw_rectangle (API,&drawrect);
1189 
1190 	return (changed);
1191 }
1192 
meta_rgn_brush(wmfAPI * API,wmfRecord * Record)1193 static int meta_rgn_brush (wmfAPI* API,wmfRecord* Record)
1194 {	int changed = 0;
1195 
1196 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
1197 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
1198 
1199 	wmfObject* objects;
1200 	wmfObject* obj_region;
1201 	wmfObject* obj_brush;
1202 
1203 	wmfRegion* region;
1204 	wmfRegion* clip;
1205 
1206 	wmfBrush* brush;
1207 	wmfBrush* temp_brush;
1208 
1209 	wmfD_Coord d_pt;
1210 
1211 	wmfPolyRectangle_t polyrect;
1212 
1213 	U16 oid_region;
1214 	U16 oid_brush;
1215 
1216 	U16 par_U16_x;
1217 	U16 par_U16_y;
1218 
1219 	unsigned int i;
1220 
1221 	unsigned long max_index;
1222 
1223 	float width;
1224 	float height;
1225 
1226 	objects = P->objects;
1227 
1228 	if (Record->function == META_FRAMEREGION)
1229 	{	max_index = 3;
1230 	}
1231 	else
1232 	{	max_index = 1;
1233 	}
1234 
1235 	if (SCAN (API) && DIAG (API))
1236 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
1237 		fprintf (stderr,"\t#par=%lu; max. index = %lu",Record->size,max_index);
1238 	}
1239 
1240 	oid_region = ParU16 (API,Record,0);
1241 	oid_brush  = ParU16 (API,Record,1);
1242 
1243 	if ((oid_region >= NUM_OBJECTS (API)) || (oid_brush >= NUM_OBJECTS (API)))
1244 	{	WMF_ERROR (API,"Object out of range!");
1245 		API->err = wmf_E_BadFormat;
1246 		return (changed);
1247 	}
1248 
1249 	obj_region = objects + oid_region;
1250 	obj_brush  = objects + oid_brush;
1251 
1252 	if (SCAN (API) && DIAG (API))
1253 	{	diagnose_object (API,(unsigned int) oid_region,obj_region);
1254 		diagnose_object (API,(unsigned int) oid_brush, obj_brush );
1255 	}
1256 
1257 	if ((obj_region->type != OBJ_REGION) || (obj_brush->type != OBJ_BRUSH))
1258 	{	WMF_ERROR (API,"libwmf: have lost track of the objects in this metafile");
1259 		WMF_ERROR (API,"        please send it to us at http://www.wvware.com/");
1260 		API->err = wmf_E_Glitch;
1261 		return (changed);
1262 	}
1263 
1264 	region = &(obj_region->obj.rgn);
1265 	brush = &(obj_brush->obj.brush);
1266 
1267 	if (Record->function == META_FRAMEREGION)
1268 	{	par_U16_x = ParU16 (API,Record,3);
1269 		par_U16_y = ParU16 (API,Record,2);
1270 
1271 		width  = (float) ((double) par_U16_x * ABS (P->dc->pixel_width ));
1272 		height = (float) ((double) par_U16_y * ABS (P->dc->pixel_height));
1273 	}
1274 	else
1275 	{	width  = 0;
1276 		height = 0;
1277 	}
1278 
1279 	if (SCAN (API))
1280 	{	d_pt = region->extents.TL;
1281 		d_pt.x -= width;
1282 		d_pt.y -= height;
1283 		D_Coord_Register (API,d_pt,0);
1284 
1285 		d_pt = region->extents.BR;
1286 		d_pt.x += width;
1287 		d_pt.y += height;
1288 		D_Coord_Register (API,d_pt,0);
1289 
1290 		return (changed);
1291 	}
1292 
1293 	polyrect.dc = P->dc;
1294 
1295 	polyrect.TL = 0;
1296 	polyrect.BR = 0;
1297 
1298 	polyrect.count = 0;
1299 
1300 	polyrect.width  = 0;
1301 	polyrect.height = 0;
1302 
1303 	if (FR->region_clip) FR->region_clip (API,&polyrect); /* i.e., none */
1304 
1305 	clip = (wmfRegion*) P->dc->clip;
1306 
1307 	polyrect.count = MAX (clip->numRects,region->numRects + 1);
1308 
1309 	polyrect.TL = (wmfD_Coord*) wmf_malloc (API,polyrect.count * sizeof (wmfD_Coord));
1310 
1311 	if (ERR (API))
1312 	{	WMF_DEBUG (API,"bailing...");
1313 		return (changed);
1314 	}
1315 
1316 	polyrect.BR = (wmfD_Coord*) wmf_malloc (API,polyrect.count * sizeof (wmfD_Coord));
1317 
1318 	if (ERR (API))
1319 	{	WMF_DEBUG (API,"bailing...");
1320 		return (changed);
1321 	}
1322 
1323 	polyrect.count = region->numRects;
1324 	for (i = 0; i < polyrect.count; i++)
1325 	{	polyrect.TL[i] = region->rects[i].TL;
1326 		polyrect.BR[i] = region->rects[i].BR;
1327 	}
1328 	i = polyrect.count;
1329 	polyrect.TL[i] = region->extents.TL;
1330 	polyrect.BR[i] = region->extents.BR;
1331 
1332 	polyrect.width  = width;
1333 	polyrect.height = height;
1334 
1335 	switch (Record->function)
1336 	{
1337 	case META_FRAMEREGION:
1338 		if (FR->region_frame)
1339 		{	temp_brush = WMF_DC_BRUSH (polyrect.dc); /* ultimately redundant ?? */
1340 
1341 			WMF_DC_SET_BRUSH (polyrect.dc,brush);
1342 
1343 			FR->region_frame (API,&polyrect);
1344 
1345 			WMF_DC_SET_BRUSH (polyrect.dc,temp_brush); /* ultimately redundant ?? */
1346 		}
1347 	break;
1348 
1349 	case META_FILLREGION:
1350 		if (FR->region_paint)
1351 		{	temp_brush = WMF_DC_BRUSH (polyrect.dc); /* ultimately redundant ?? */
1352 
1353 			WMF_DC_SET_BRUSH (polyrect.dc,brush);
1354 
1355 			FR->region_paint (API,&polyrect);
1356 
1357 			WMF_DC_SET_BRUSH (polyrect.dc,temp_brush); /* ultimately redundant ?? */
1358 		}
1359 	break;
1360 
1361 	default:
1362 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
1363 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
1364 		API->err = wmf_E_Glitch;
1365 	break;
1366 	}
1367 
1368 	polyrect.count = clip->numRects;
1369 	for (i = 0; i < polyrect.count; i++)
1370 	{	polyrect.TL[i] = clip->rects[i].TL;
1371 		polyrect.BR[i] = clip->rects[i].BR;
1372 	}
1373 
1374 	polyrect.width  = 0;
1375 	polyrect.height = 0;
1376 
1377 	if (FR->region_clip) FR->region_clip (API,&polyrect);
1378 
1379 	wmf_free (API,polyrect.TL);
1380 	wmf_free (API,polyrect.BR);
1381 
1382 	return (changed);
1383 }
1384 
meta_rgn_paint(wmfAPI * API,wmfRecord * Record)1385 static int meta_rgn_paint (wmfAPI* API,wmfRecord* Record)
1386 {	int changed = 0;
1387 
1388 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
1389 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
1390 
1391 	wmfObject* objects;
1392 	wmfObject* obj_region;
1393 
1394 	wmfRegion* region;
1395 	wmfRegion* clip;
1396 
1397 	wmfD_Coord d_pt;
1398 
1399 	wmfPolyRectangle_t polyrect;
1400 
1401 	U16 oid_region;
1402 
1403 	U16 temp_rop;
1404 
1405 	unsigned int i;
1406 
1407 	objects = P->objects;
1408 
1409 	if (SCAN (API) && DIAG (API))
1410 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
1411 		fprintf (stderr,"\t#par=%lu; max. index = 0",Record->size);
1412 	}
1413 
1414 	oid_region = ParU16 (API,Record,0);
1415 
1416 	if (oid_region >= NUM_OBJECTS (API))
1417 	{	WMF_ERROR (API,"Object out of range!");
1418 		API->err = wmf_E_BadFormat;
1419 		return (changed);
1420 	}
1421 
1422 	obj_region = objects + oid_region;
1423 
1424 	if (SCAN (API) && DIAG (API))
1425 	{	diagnose_object (API,(unsigned int) oid_region,obj_region);
1426 	}
1427 
1428 	if (obj_region->type != OBJ_REGION)
1429 	{	WMF_ERROR (API,"libwmf: have lost track of the objects in this metafile");
1430 		WMF_ERROR (API,"        please send it to us at http://www.wvware.com/");
1431 		API->err = wmf_E_Glitch;
1432 		return (changed);
1433 	}
1434 
1435 	region = &(obj_region->obj.rgn);
1436 
1437 	if (SCAN (API))
1438 	{	d_pt = region->extents.TL;
1439 		D_Coord_Register (API,d_pt,0);
1440 
1441 		d_pt = region->extents.BR;
1442 		D_Coord_Register (API,d_pt,0);
1443 
1444 		return (changed);
1445 	}
1446 
1447 	polyrect.dc = P->dc;
1448 
1449 	polyrect.TL = 0;
1450 	polyrect.BR = 0;
1451 
1452 	polyrect.count = 0;
1453 
1454 	polyrect.width  = 0;
1455 	polyrect.height = 0;
1456 
1457 	if (FR->region_clip) FR->region_clip (API,&polyrect); /* i.e., none */
1458 
1459 	clip = (wmfRegion*) P->dc->clip;
1460 
1461 	polyrect.count = MAX (clip->numRects,region->numRects + 1);
1462 
1463 	polyrect.TL = (wmfD_Coord*) wmf_malloc (API,polyrect.count * sizeof (wmfD_Coord));
1464 
1465 	if (ERR (API))
1466 	{	WMF_DEBUG (API,"bailing...");
1467 		return (changed);
1468 	}
1469 
1470 	polyrect.BR = (wmfD_Coord*) wmf_malloc (API,polyrect.count * sizeof (wmfD_Coord));
1471 
1472 	if (ERR (API))
1473 	{	WMF_DEBUG (API,"bailing...");
1474 		return (changed);
1475 	}
1476 
1477 	polyrect.count = region->numRects;
1478 	for (i = 0; i < polyrect.count; i++)
1479 	{	polyrect.TL[i] = region->rects[i].TL;
1480 		polyrect.BR[i] = region->rects[i].BR;
1481 	}
1482 	i = polyrect.count;
1483 	polyrect.TL[i] = region->extents.TL;
1484 	polyrect.BR[i] = region->extents.BR;
1485 
1486 	switch (Record->function)
1487 	{
1488 	case META_INVERTREGION:
1489 		if (FR->region_paint)
1490 		{	temp_rop = WMF_DC_ROP (polyrect.dc); /* ultimately redundant ?? */
1491 
1492 			WMF_DC_SET_ROP (polyrect.dc,R2_NOT);
1493 
1494 			FR->region_paint (API,&polyrect);
1495 
1496 			WMF_DC_SET_ROP (polyrect.dc,temp_rop); /* ultimately redundant ?? */
1497 		}
1498 	break;
1499 
1500 	case META_PAINTREGION:
1501 		if (FR->region_paint) FR->region_paint (API,&polyrect);
1502 	break;
1503 
1504 	default:
1505 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
1506 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
1507 		API->err = wmf_E_Glitch;
1508 	break;
1509 	}
1510 
1511 	polyrect.count = clip->numRects;
1512 	for (i = 0; i < polyrect.count; i++)
1513 	{	polyrect.TL[i] = clip->rects[i].TL;
1514 		polyrect.BR[i] = clip->rects[i].BR;
1515 	}
1516 
1517 	if (FR->region_clip) FR->region_clip (API,&polyrect);
1518 
1519 	wmf_free (API,polyrect.TL);
1520 	wmf_free (API,polyrect.BR);
1521 
1522 	return (changed);
1523 }
1524 
meta_rgn_create(wmfAPI * API,wmfRecord * Record)1525 static int meta_rgn_create (wmfAPI* API,wmfRecord* Record)
1526 {	int changed = 0;
1527 
1528 	wmfPlayer_t* P = (wmfPlayer_t*) API->player_data;
1529 
1530 	wmfRecord start;
1531 	wmfRecord end;
1532 
1533 	wmfObject* objects;
1534 	wmfObject* obj_region;
1535 
1536 	wmfRegion* region;
1537 	wmfRegion  temp_region;
1538 
1539 	wmfD_Rect d_r;
1540 
1541 	U16 i;
1542 	U16 oid_region;
1543 
1544 	U16 x1;
1545 	U16 x2;
1546 	U16 y1;
1547 	U16 y2;
1548 
1549 	U16 band;
1550 	U16 num_band;
1551 	U16 num_pair;
1552 
1553 	U16 count;
1554 
1555 	unsigned long max_index;
1556 
1557 	objects = P->objects;
1558 
1559 	i = 0;
1560 	while ((i < NUM_OBJECTS (API)) && objects[i].type) i++;
1561 
1562 	if (i == NUM_OBJECTS (API))
1563 	{	WMF_ERROR (API,"Object out of range!");
1564 		API->err = wmf_E_BadFormat;
1565 		return (changed);
1566 	}
1567 
1568 	oid_region = i;
1569 	obj_region = objects + oid_region;
1570 
1571 	obj_region->type = OBJ_REGION;
1572 
1573 	region = &(obj_region->obj.rgn);
1574 
1575 	region->rects = (wmfD_Rect*) wmf_malloc (API,8 * sizeof (wmfD_Rect));
1576 	region->size = 8;
1577 
1578 	if (ERR (API))
1579 	{	WMF_DEBUG (API,"bailing...");
1580 		return (changed);
1581 	}
1582 
1583 	WmfSetRectRgn (region,0);
1584 
1585 	if (SCAN (API) && DIAG (API))
1586 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
1587 		fprintf (stderr,"\t#par=%lu; index 0-4,6-10 skipped; max. index = 5",Record->size);
1588 
1589 		diagnose_object (API,(unsigned int) oid_region,obj_region);
1590 	}
1591 
1592 	num_band = ParU16 (API,Record,5);
1593 
1594 	if (num_band == 0) return (changed);
1595 
1596 	temp_region.rects = (wmfD_Rect*) wmf_malloc (API,8 * sizeof (wmfD_Rect));
1597 	temp_region.size = 8;
1598 
1599 	if (ERR (API))
1600 	{	WMF_DEBUG (API,"bailing...");
1601 		return (changed);
1602 	}
1603 
1604 	WmfSetRectRgn (&temp_region,0);
1605 
1606 	end = OffsetRecord (API,Record,10);
1607 	max_index = 10;
1608 	for (band = 0; band < num_band; band++)
1609 	{	max_index++;
1610 		if (SCAN (API) && DIAG (API))
1611 		{	fprintf (stderr,",%lu",max_index);
1612 		}
1613 
1614 		start = OffsetRecord (API,&end,1);
1615 
1616 		count = ParU16 (API,&start,0);
1617 
1618 		if (count & 1)
1619 		{	WMF_ERROR (API,"Delimiter not even!");
1620 			API->err = wmf_E_BadFormat;
1621 			break;
1622 		}
1623 
1624 		num_pair = count >> 1;
1625 
1626 		max_index += count + 3;
1627 		if (SCAN (API) && DIAG (API))
1628 		{	fprintf (stderr,",%lu",max_index);
1629 		}
1630 
1631 		end = OffsetRecord (API,&start,(unsigned long) (count + 3));
1632 
1633 		if (ParU16 (API,&end,0) != count)
1634 		{	WMF_ERROR (API,"Mismatched delimiters!");
1635 			API->err = wmf_E_BadFormat;
1636 			break;
1637 		}
1638 
1639 		y1 = ParU16 (API,&start,1);
1640 		y2 = ParU16 (API,&start,2);
1641 
1642 		for (i = 0; i < num_pair; i++)
1643 		{	x1 = ParU16 (API,&start,(unsigned long) (3 + 2 * i));
1644 			x2 = ParU16 (API,&start,(unsigned long) (4 + 2 * i));
1645 
1646 			D_Rect (API,&d_r,x1,y1,x2,y2);
1647 
1648 			WmfSetRectRgn (&temp_region,&d_r);
1649 			WmfCombineRgn (API,region,region,&temp_region,RGN_OR);
1650 		}
1651 	}
1652 
1653 	wmf_free (API,temp_region.rects);
1654 
1655 	return (changed);
1656 }
1657 
meta_clip_select(wmfAPI * API,wmfRecord * Record)1658 static int meta_clip_select (wmfAPI* API,wmfRecord* Record)
1659 {	int changed = 0;
1660 
1661 	wmfPlayer_t* P = (wmfPlayer_t*) API->player_data;
1662 
1663 	wmfObject* objects;
1664 	wmfObject* obj_region;
1665 
1666 	wmfRegion* region;
1667 	wmfRegion* clip;
1668 
1669 	U16 oid_region;
1670 
1671 	objects = P->objects;
1672 
1673 	if (SCAN (API) && DIAG (API))
1674 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
1675 		fprintf (stderr,"\t#par=%lu; max. index = 0",Record->size);
1676 	}
1677 
1678 	oid_region = ParU16 (API,Record,0);
1679 
1680 	if (oid_region >= NUM_OBJECTS (API))
1681 	{	WMF_ERROR (API,"Object out of range!");
1682 		API->err = wmf_E_BadFormat;
1683 		return (changed);
1684 	}
1685 
1686 	obj_region = objects + oid_region;
1687 
1688 	if (SCAN (API) && DIAG (API))
1689 	{	diagnose_object (API,(unsigned int) oid_region,obj_region);
1690 	}
1691 
1692 	if (obj_region->type != OBJ_REGION)
1693 	{	if (API->flags & WMF_OPT_IGNORE_NONFATAL)
1694 		{	/* Some metafiles use this even though no region-objects have been defined,
1695 			 * so I have some doubt about the correctness of this handler; perhaps
1696 			 * this should reset the clip region to the entire space?
1697 			 *
1698 			 * Anyway, I am making this particular error non-fatal.
1699 			 */
1700 			WMF_DEBUG (API,"libwmf: have lost track of the objects in this metafile");
1701 			WMF_DEBUG (API,"        please send it to us at http://www.wvware.com/");
1702 		}
1703 		else
1704 		{	WMF_ERROR (API,"libwmf: have lost track of the objects in this metafile");
1705 			WMF_ERROR (API,"        please send it to us at http://www.wvware.com/");
1706 			API->err = wmf_E_Glitch;
1707 		}
1708 		return (changed);
1709 	}
1710 
1711 	region = &(obj_region->obj.rgn);
1712 
1713 	clip = (wmfRegion*) P->dc->clip;
1714 
1715 	WmfCombineRgn (API,clip,region,0,RGN_COPY);
1716 
1717 	return (changed);
1718 }
1719 
meta_clip_offset(wmfAPI * API,wmfRecord * Record)1720 static int meta_clip_offset (wmfAPI* API,wmfRecord* Record)
1721 {	int changed = 0;
1722 
1723 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
1724 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
1725 
1726 	wmfRegion* clip;
1727 
1728 	wmfPolyRectangle_t polyrect;
1729 
1730 	wmfL_Coord l_pt;
1731 
1732 	U16 par_U16_x;
1733 	U16 par_U16_y;
1734 
1735 	unsigned int i;
1736 
1737 	if (SCAN (API) && DIAG (API))
1738 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
1739 		fprintf (stderr,"\t#par=%lu; max. index = 1",Record->size);
1740 	}
1741 
1742 	clip = (wmfRegion*) P->dc->clip;
1743 
1744 	par_U16_x = ParU16 (API,Record,1);
1745 	par_U16_y = ParU16 (API,Record,0);
1746 
1747 	l_pt = L_Coord (par_U16_x,par_U16_y);
1748 
1749 	for (i = 0; i < clip->numRects; i++)
1750 	{	clip->rects[i].TL.x += l_pt.x;
1751 		clip->rects[i].TL.y += l_pt.y;
1752 		clip->rects[i].BR.x += l_pt.x;
1753 		clip->rects[i].BR.y += l_pt.y;
1754 	}
1755 	clip->extents.TL.x += l_pt.x;
1756 	clip->extents.TL.y += l_pt.y;
1757 	clip->extents.BR.x += l_pt.x;
1758 	clip->extents.BR.y += l_pt.y;
1759 
1760 	if (SCAN (API)) return (changed);
1761 
1762 	polyrect.TL = (wmfD_Coord*) wmf_malloc (API,clip->numRects * sizeof (wmfD_Coord));
1763 
1764 	if (ERR (API))
1765 	{	WMF_DEBUG (API,"bailing...");
1766 		return (changed);
1767 	}
1768 
1769 	polyrect.BR = (wmfD_Coord*) wmf_malloc (API,clip->numRects * sizeof (wmfD_Coord));
1770 
1771 	if (ERR (API))
1772 	{	WMF_DEBUG (API,"bailing...");
1773 		return (changed);
1774 	}
1775 
1776 	polyrect.count = clip->numRects;
1777 	for (i = 0; i < polyrect.count; i++)
1778 	{	polyrect.TL[i] = clip->rects[i].TL;
1779 		polyrect.BR[i] = clip->rects[i].BR;
1780 	}
1781 
1782 	polyrect.dc = P->dc;
1783 
1784 	polyrect.width  = 0;
1785 	polyrect.height = 0;
1786 
1787 	if (FR->region_clip) FR->region_clip (API,&polyrect);
1788 
1789 	wmf_free (API,polyrect.TL);
1790 	wmf_free (API,polyrect.BR);
1791 
1792 	return (changed);
1793 }
1794 
meta_clip_combine(wmfAPI * API,wmfRecord * Record)1795 static int meta_clip_combine (wmfAPI* API,wmfRecord* Record)
1796 {	int changed = 0;
1797 
1798 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
1799 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
1800 
1801 	wmfRegion* visible;
1802 	wmfRegion* clip;
1803 
1804 	wmfPolyRectangle_t polyrect;
1805 
1806 	wmfD_Rect d_r;
1807 
1808 	U16 x1;
1809 	U16 x2;
1810 	U16 y1;
1811 	U16 y2;
1812 
1813 	unsigned int i;
1814 
1815 	visible = &(P->visible);
1816 
1817 	if (SCAN (API) && DIAG (API))
1818 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
1819 		fprintf (stderr,"\t#par=%lu; max. index = 3",Record->size);
1820 	}
1821 
1822 	x1 = ParU16 (API,Record,3);
1823 	y1 = ParU16 (API,Record,2);
1824 	x2 = ParU16 (API,Record,1);
1825 	y2 = ParU16 (API,Record,0);
1826 
1827 	D_Rect (API,&d_r,x1,y1,x2,y2);
1828 
1829 	clip = (wmfRegion*) P->dc->clip;
1830 
1831 	switch (Record->function)
1832 	{
1833 	case META_EXCLUDECLIPRECT:
1834 		Clipping (API,clip,visible,&d_r,CLIP_EXCLUDE);
1835 	break;
1836 
1837 	case META_INTERSECTCLIPRECT:
1838 		Clipping (API,clip,visible,&d_r,CLIP_INTERSECT);
1839 	break;
1840 
1841 	default:
1842 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
1843 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
1844 		API->err = wmf_E_Glitch;
1845 	break;
1846 	}
1847 
1848 	if (ERR (API))
1849 	{	WMF_DEBUG (API,"bailing...");
1850 		return (changed);
1851 	}
1852 
1853 	if (SCAN (API)) return (changed);
1854 
1855 	polyrect.TL = (wmfD_Coord*) wmf_malloc (API,clip->numRects * sizeof (wmfD_Coord));
1856 
1857 	if (ERR (API))
1858 	{	WMF_DEBUG (API,"bailing...");
1859 		return (changed);
1860 	}
1861 
1862 	polyrect.BR = (wmfD_Coord*) wmf_malloc (API,clip->numRects * sizeof (wmfD_Coord));
1863 
1864 	if (ERR (API))
1865 	{	WMF_DEBUG (API,"bailing...");
1866 		return (changed);
1867 	}
1868 
1869 	polyrect.count = clip->numRects;
1870 	for (i = 0; i < polyrect.count; i++)
1871 	{	polyrect.TL[i] = clip->rects[i].TL;
1872 		polyrect.BR[i] = clip->rects[i].BR;
1873 	}
1874 
1875 	polyrect.dc = P->dc;
1876 
1877 	polyrect.width  = 0;
1878 	polyrect.height = 0;
1879 
1880 	if (FR->region_clip) FR->region_clip (API,&polyrect);
1881 
1882 	wmf_free (API,polyrect.TL);
1883 	wmf_free (API,polyrect.BR);
1884 
1885 	return (changed);
1886 }
1887 
meta_dib_draw(wmfAPI * API,wmfRecord * Record)1888 static int meta_dib_draw (wmfAPI* API,wmfRecord* Record)
1889 {	int changed = 0;
1890 
1891 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
1892 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
1893 
1894 	wmfRecord bmp_record;
1895 
1896 	wmfBMP_Read_t bmp_read;
1897 	wmfBMP_Draw_t bmp_draw;
1898 
1899 	wmfL_Coord l_pt_TL;
1900 	wmfL_Coord l_pt;
1901 	wmfD_Coord d_pt;
1902 
1903 	U16 par_U16_x = 0;
1904 	U16 par_U16_y = 0;
1905 	U16 par_U16_w = 0;
1906 	U16 par_U16_h = 0;
1907 
1908 	S32 width;
1909 	S32 height;
1910 
1911 	long pos_current;
1912 
1913 	double stretch_x;
1914 	double stretch_y;
1915 
1916 	if ((Record->function == META_DIBBITBLT) && ((Record->size) == 9)) /* Special case... */
1917 	{	changed = meta_rop_draw (API,Record);
1918 		return (changed);
1919 	}
1920 
1921 	if (SCAN (API) && DIAG (API))
1922 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
1923 	}
1924 
1925 	switch (Record->function)
1926 	{
1927 	case META_SETDIBTODEV:
1928 		if (SCAN (API) && DIAG (API))
1929 		{	fprintf (stderr,"\t#par=%lu; index 0 skipped; max. index = 8",Record->size);
1930 		}
1931 
1932 		par_U16_x = ParU16 (API,Record,8);
1933 		par_U16_y = ParU16 (API,Record,7);
1934 
1935 		par_U16_w = ParU16 (API,Record,6);
1936 		par_U16_h = ParU16 (API,Record,5);
1937 
1938 		bmp_draw.crop.w = par_U16_w;
1939 		bmp_draw.crop.h = par_U16_h;
1940 
1941 		bmp_draw.crop.x = ParU16 (API,Record,4);
1942 		bmp_draw.crop.y = ParU16 (API,Record,3);
1943 
1944 		bmp_read.width  = ParU16 (API,Record,2); /* uncertain about this ?? */
1945 		bmp_read.height = ParU16 (API,Record,1);
1946 
1947 		bmp_draw.type = SRCCOPY;
1948 
1949 		bmp_record = OffsetRecord (API,Record,9);
1950 	break;
1951 
1952 	case META_STRETCHDIB:
1953 		if (SCAN (API) && DIAG (API))
1954 		{	fprintf (stderr,"\t#par=%lu; index 2 skipped; max. index = 10",Record->size);
1955 		}
1956 
1957 		par_U16_x = ParU16 (API,Record,10);
1958 		par_U16_y = ParU16 (API,Record,9);
1959 
1960 		par_U16_w = ParU16 (API,Record,8);
1961 		par_U16_h = ParU16 (API,Record,7);
1962 
1963 		bmp_draw.crop.x = ParU16 (API,Record,6);
1964 		bmp_draw.crop.y = ParU16 (API,Record,5);
1965 
1966 		bmp_draw.crop.w = ParU16 (API,Record,4);
1967 		bmp_draw.crop.h = ParU16 (API,Record,3);
1968 
1969 		bmp_read.width  = 0;
1970 		bmp_read.height = 0;
1971 
1972 		bmp_draw.type = (U32) ParU16 (API,Record,0) + (((U32) ParU16 (API,Record,1)) << 16);
1973 
1974 		bmp_record = OffsetRecord (API,Record,11);
1975 	break;
1976 
1977 	case META_DIBSTRETCHBLT:
1978 		if (SCAN (API) && DIAG (API))
1979 		{	fprintf (stderr,"\t#par=%lu; max. index = 9",Record->size);
1980 		}
1981 
1982 		par_U16_x = ParU16 (API,Record,9);
1983 		par_U16_y = ParU16 (API,Record,8);
1984 
1985 		par_U16_w = ParU16 (API,Record,7);
1986 		par_U16_h = ParU16 (API,Record,6);
1987 
1988 		bmp_draw.crop.x = ParU16 (API,Record,5);
1989 		bmp_draw.crop.y = ParU16 (API,Record,4);
1990 
1991 		bmp_draw.crop.w = ParU16 (API,Record,3);
1992 		bmp_draw.crop.h = ParU16 (API,Record,2);
1993 
1994 		bmp_read.width  = 0;
1995 		bmp_read.height = 0;
1996 
1997 		bmp_draw.type = (U32) ParU16 (API,Record,0) + (((U32) ParU16 (API,Record,1)) << 16);
1998 
1999 		bmp_record = OffsetRecord (API,Record,10);
2000 	break;
2001 
2002 	case META_DIBBITBLT: WMF_DEBUG (API,"(play) META_DIBBITBLT");
2003 		if (SCAN (API) && DIAG (API))
2004 		{	fprintf (stderr,"\t#par=%lu; max. index = 7",Record->size);
2005 		}
2006 
2007 		par_U16_x = ParU16 (API,Record,7);
2008 		par_U16_y = ParU16 (API,Record,6);
2009 
2010 		par_U16_w = ParU16 (API,Record,5);
2011 		par_U16_h = ParU16 (API,Record,4);
2012 
2013 		bmp_draw.crop.x = ParU16 (API,Record,3);
2014 		bmp_draw.crop.y = ParU16 (API,Record,2);
2015 
2016 		bmp_draw.crop.w = par_U16_w;
2017 		bmp_draw.crop.h = par_U16_h;
2018 
2019 		bmp_read.width  = 0;
2020 		bmp_read.height = 0;
2021 
2022 		bmp_draw.type = (U32) ParU16 (API,Record,0) + (((U32) ParU16 (API,Record,1)) << 16);
2023 
2024 		bmp_record = OffsetRecord (API,Record,8);
2025 	break;
2026 
2027 	default:
2028 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
2029 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
2030 		API->err = wmf_E_Glitch;
2031 	break;
2032 	}
2033 
2034 	if (ERR (API))
2035 	{	WMF_DEBUG (API,"bailing...");
2036 		return (changed);
2037 	}
2038 
2039 	if ((par_U16_w == 0) || (par_U16_h == 0) || (bmp_draw.crop.w == 0) || (bmp_draw.crop.h == 0))
2040 	{	return (changed);
2041 	}
2042 
2043 	l_pt_TL = L_Coord (par_U16_x,par_U16_y);
2044 
2045 	bmp_draw.pt = wmf_D_Coord_translate (API,l_pt_TL);
2046 
2047 	l_pt = L_Coord (par_U16_w,par_U16_h);
2048 
2049 	width  = ABS (l_pt.x);
2050 	height = ABS (l_pt.y);
2051 
2052 	if (SCAN (API))
2053 	{	D_Coord_Register (API,bmp_draw.pt,0);
2054 
2055 		l_pt.x = l_pt_TL.x + width;
2056 		l_pt.y = l_pt_TL.y + height;
2057 		d_pt = wmf_D_Coord_translate (API,l_pt);
2058 		D_Coord_Register (API,d_pt,0);
2059 
2060 		return (changed);
2061 	}
2062 
2063 	pos_current = WMF_TELL (API);
2064 	if (pos_current < 0)
2065 	{	WMF_ERROR (API,"API's tell() failed on input stream!");
2066 		API->err = wmf_E_BadFile;
2067 		return (changed);
2068 	}
2069 
2070 	bmp_read.offset = bmp_record.position;
2071 	bmp_read.buffer = bmp_record.parameter;
2072 	bmp_read.length = (long) (bmp_record.size) * 2;
2073 
2074 	bmp_read.bmp.data = 0;
2075 
2076 	if (FR->bmp_read) FR->bmp_read (API,&bmp_read);
2077 
2078 	if (ERR (API) || (bmp_read.bmp.data == 0))
2079 	{	WMF_DEBUG (API,"bailing...");
2080 		return (changed);
2081 	}
2082 
2083 	if (WMF_SEEK (API,pos_current) == (-1))
2084 	{	WMF_ERROR (API,"API's seek() failed on input stream!");
2085 		API->err = wmf_E_BadFile;
2086 		return (changed);
2087 	}
2088 
2089 	bmp_draw.dc = P->dc;
2090 	bmp_draw.bmp = bmp_read.bmp;
2091 	if (bmp_draw.crop.x >= bmp_read.bmp.width ) bmp_draw.crop.x = 0;
2092 	if (bmp_draw.crop.y >= bmp_read.bmp.height) bmp_draw.crop.y = 0;
2093 	if (bmp_draw.crop.x + bmp_draw.crop.w >= bmp_read.bmp.width)
2094 	{	bmp_draw.crop.w = bmp_read.bmp.width - bmp_draw.crop.x;
2095 	}
2096 	if (bmp_draw.crop.y + bmp_draw.crop.h >= bmp_read.bmp.height)
2097 	{	bmp_draw.crop.h = bmp_read.bmp.height - bmp_draw.crop.y;
2098 	}
2099 
2100 	stretch_x = (double) par_U16_w / (double) bmp_draw.crop.w;
2101 	stretch_y = (double) par_U16_h / (double) bmp_draw.crop.h;
2102 
2103 	bmp_draw.pixel_width  = ABS (P->dc->pixel_width ) * stretch_x;
2104 	bmp_draw.pixel_height = ABS (P->dc->pixel_height) * stretch_y;
2105 
2106 	if (FR->bmp_draw) FR->bmp_draw (API,&bmp_draw);
2107 
2108 	if (FR->bmp_free) FR->bmp_free (API,&(bmp_draw.bmp));
2109 
2110 	return (changed);
2111 }
2112 
meta_dib_brush(wmfAPI * API,wmfRecord * Record)2113 static int meta_dib_brush (wmfAPI* API,wmfRecord* Record)
2114 {	int changed = 0;
2115 
2116 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
2117 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
2118 
2119 	wmfRecord bmp_record;
2120 
2121 	wmfObject* objects;
2122 	wmfObject* obj_brush;
2123 
2124 	wmfBrush* brush;
2125 
2126 	wmfBMP_Read_t bmp_read;
2127 
2128 	U16 oid_brush;
2129 
2130 	unsigned int i;
2131 
2132 	long pos_current;
2133 
2134 	objects = P->objects;
2135 
2136 	i = 0;
2137 	while ((i < NUM_OBJECTS (API)) && objects[i].type) i++;
2138 
2139 	if (i == NUM_OBJECTS (API))
2140 	{	WMF_ERROR (API,"Object out of range!");
2141 		API->err = wmf_E_BadFormat;
2142 		return (changed);
2143 	}
2144 
2145 	oid_brush = i;
2146 	obj_brush = objects + oid_brush;
2147 
2148 	obj_brush->type = OBJ_BRUSH;
2149 
2150 	brush = &(obj_brush->obj.brush);
2151 
2152 	if (SCAN (API) && DIAG (API))
2153 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
2154 		fprintf (stderr,"\t#par=%lu; max. index = ?",Record->size);
2155 
2156 		diagnose_object (API,(unsigned int) oid_brush,obj_brush);
2157 	}
2158 
2159 	bmp_record = OffsetRecord (API,Record,2);
2160 
2161 	pos_current = WMF_TELL (API);
2162 	if (pos_current < 0)
2163 	{	WMF_ERROR (API,"API's tell() failed on input stream!");
2164 		API->err = wmf_E_BadFile;
2165 		return (changed);
2166 	}
2167 
2168 	bmp_read.offset = bmp_record.position;
2169 	bmp_read.buffer = bmp_record.parameter;
2170 	bmp_read.length = (long) (bmp_record.size) * 2;
2171 
2172 	bmp_read.width  = 0;
2173 	bmp_read.height = 0;
2174 
2175 	bmp_read.bmp.width  = 0;
2176 	bmp_read.bmp.height = 0;
2177 	bmp_read.bmp.data = 0;
2178 
2179 	if (PLAY (API) && FR->bmp_read) FR->bmp_read (API,&bmp_read);
2180 
2181 	if (ERR (API))
2182 	{	WMF_DEBUG (API,"bailing...");
2183 		return (changed);
2184 	}
2185 
2186 	if (WMF_SEEK (API,pos_current) == (-1))
2187 	{	WMF_ERROR (API,"API's seek() failed on input stream!");
2188 		API->err = wmf_E_BadFile;
2189 		return (changed);
2190 	}
2191 
2192 	WMF_BRUSH_SET_STYLE (brush,BS_DIBPATTERN);
2193 
2194 	WMF_BRUSH_SET_COLOR (brush,&wmf_black);
2195 
2196 	WMF_BRUSH_SET_BITMAP (brush,&(bmp_read.bmp));
2197 
2198 	if (SCAN (API)) wmf_ipa_color_add (API,WMF_BRUSH_COLOR (brush));
2199 
2200 	WMF_DC_SET_BRUSH (P->dc,brush);
2201 
2202 	return (changed);
2203 }
2204 
meta_rop_draw(wmfAPI * API,wmfRecord * Record)2205 static int meta_rop_draw (wmfAPI* API,wmfRecord* Record)
2206 {	int changed = 0;
2207 
2208 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
2209 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
2210 
2211 	wmfROP_Draw_t rop_draw;
2212 
2213 	wmfL_Coord l_pt_TL;
2214 	wmfL_Coord l_pt;
2215 
2216 	U16 par_U16_x = 0;
2217 	U16 par_U16_y = 0;
2218 	U16 par_U16_w = 0;
2219 	U16 par_U16_h = 0;
2220 
2221 	S32 width;
2222 	S32 height;
2223 
2224 	if (SCAN (API) && DIAG (API))
2225 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
2226 	}
2227 
2228 	switch (Record->function)
2229 	{
2230 	case META_DIBBITBLT: /* META_DIBBITBLT: Special case: Size = 12 */
2231 		if (SCAN (API) && DIAG (API))
2232 		{	fprintf (stderr,"\t#par=%lu; index 2-4 skipped; max. index = 8",Record->size);
2233 		}
2234 
2235 		par_U16_x = ParU16 (API,Record,8);
2236 		par_U16_y = ParU16 (API,Record,7);
2237 
2238 		par_U16_w = ParU16 (API,Record,6);
2239 		par_U16_h = ParU16 (API,Record,5);
2240 
2241 		rop_draw.ROP = (U32) ParU16 (API,Record,0) + (((U32) ParU16 (API,Record,1)) << 16);
2242 	break;
2243 
2244 	case META_PATBLT:
2245 		if (SCAN (API) && DIAG (API))
2246 		{	fprintf (stderr,"\t#par=%lu; max. index = 5",Record->size);
2247 		}
2248 
2249 		par_U16_x = ParU16 (API,Record,5);
2250 		par_U16_y = ParU16 (API,Record,4);
2251 
2252 		par_U16_w = ParU16 (API,Record,3);
2253 		par_U16_h = ParU16 (API,Record,2);
2254 
2255 		rop_draw.ROP = (U32) ParU16 (API,Record,0) + (((U32) ParU16 (API,Record,1)) << 16);
2256 	break;
2257 
2258 	default:
2259 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
2260 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
2261 		API->err = wmf_E_Glitch;
2262 	break;
2263 	}
2264 
2265 	if (ERR (API))
2266 	{	WMF_DEBUG (API,"bailing...");
2267 		return (changed);
2268 	}
2269 
2270 	l_pt_TL = L_Coord (par_U16_x,par_U16_y);
2271 
2272 	rop_draw.TL = wmf_D_Coord_translate (API,l_pt_TL);
2273 
2274 	l_pt = L_Coord (par_U16_w,par_U16_h);
2275 
2276 	width  = ABS (l_pt.x);
2277 	height = ABS (l_pt.y);
2278 
2279 	l_pt.x = l_pt_TL.x + width;
2280 	l_pt.y = l_pt_TL.y + height;
2281 
2282 	rop_draw.BR = wmf_D_Coord_translate (API,l_pt);
2283 
2284 	if (SCAN (API))
2285 	{	D_Coord_Register (API,rop_draw.TL,0);
2286 		D_Coord_Register (API,rop_draw.BR,0);
2287 		return (changed);
2288 	}
2289 
2290 	rop_draw.dc = P->dc;
2291 
2292 	rop_draw.pixel_width  = ABS (P->dc->pixel_width );
2293 	rop_draw.pixel_height = ABS (P->dc->pixel_height);
2294 
2295 	if (FR->rop_draw) FR->rop_draw (API,&rop_draw);
2296 
2297 	return (changed);
2298 }
2299 
meta_dc_set(wmfAPI * API,wmfRecord * Record)2300 static int meta_dc_set (wmfAPI* API,wmfRecord* Record)
2301 {	int changed = 0;
2302 
2303 	wmfPlayer_t* P = (wmfPlayer_t*) API->player_data;
2304 
2305 	U16 par_U16;
2306 
2307 	if (SCAN (API) && DIAG (API))
2308 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
2309 		fprintf (stderr,"\t#par=%lu; max. index = 0",Record->size);
2310 	}
2311 
2312 	par_U16 = ParU16 (API,Record,0);
2313 
2314 	switch (Record->function)
2315 	{
2316 	case META_SETROP2:
2317 		WMF_DC_SET_ROP (P->dc,par_U16);
2318 	break;
2319 
2320 	case META_SETTEXTJUSTIFICATION:
2321 		WMF_DC_SET_BREAKEXTRA (P->dc,par_U16);
2322 	break;
2323 
2324 	case META_SETTEXTCHAREXTRA:
2325 		WMF_DC_SET_CHAREXTRA (P->dc,par_U16);
2326 	break;
2327 
2328 	case META_SETPOLYFILLMODE:
2329 		WMF_DC_SET_POLYFILL (P->dc,par_U16);
2330 	break;
2331 
2332 	case META_SETTEXTALIGN:
2333 		WMF_DC_SET_TEXTALIGN (P->dc,par_U16);
2334 	break;
2335 
2336 	case META_SETBKMODE:
2337 		if (par_U16 == TRANSPARENT)
2338 		{	WMF_DC_SET_TRANSPARENT (P->dc);
2339 		}
2340 		else
2341 		{	WMF_DC_SET_OPAQUE (P->dc);
2342 			if (par_U16 != OPAQUE) { WMF_DEBUG (API,"unexpected background mode; assuming opaque..."); }
2343 		}
2344 	break;
2345 
2346 	default:
2347 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
2348 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
2349 		API->err = wmf_E_Glitch;
2350 	break;
2351 	}
2352 
2353 	return (changed);
2354 }
2355 
meta_dc_color(wmfAPI * API,wmfRecord * Record,wmfAttributes * attrlist)2356 static int meta_dc_color (wmfAPI* API,wmfRecord* Record,wmfAttributes* attrlist)
2357 {	int changed = 0;
2358 
2359 	wmfPlayer_t* P = (wmfPlayer_t*) API->player_data;
2360 
2361 	wmfRGB color;
2362 
2363 	U16 par_U16_rg;
2364 	U16 par_U16_b;
2365 
2366 	const char * value = 0;
2367 	char hash[8];
2368 	unsigned long rgbhex;
2369 
2370 	static char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
2371 
2372 	if (SCAN (API) && DIAG (API))
2373 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
2374 		fprintf (stderr,"\t#par=%lu; max. index = 1",Record->size);
2375 	}
2376 
2377 	if (API->flags & API_ENABLE_EDITING)
2378 	{	if ((value = wmf_attr_query (API, attrlist, "color")))
2379 		{	if ((*value) == '#')
2380 			{	if (sscanf (value+1, "%lx", &rgbhex) == 1)
2381 				{	par_U16_rg = (U16) ((rgbhex >> 8) & 0xffff);
2382 					par_U16_b  = (U16) ( rgbhex       & 0x00ff);
2383 
2384 					if (PutParU16 (API,Record,1,par_U16_b )) changed = 1;
2385 					if (PutParU16 (API,Record,0,par_U16_rg)) changed = 1;
2386 				}
2387 				else
2388 				{	value = 0; /* force a re-write below */
2389 				}
2390 			}
2391 			else
2392 			{	value = 0; /* force a re-write below */
2393 			}
2394 		}
2395 	}
2396 
2397 	par_U16_b  = ParU16 (API,Record,1);
2398 	par_U16_rg = ParU16 (API,Record,0);
2399 
2400 	color = rgb (par_U16_rg,par_U16_b);
2401 
2402 	if ((API->flags & API_ENABLE_EDITING) && ((value == 0) || changed))
2403 	{	hash[0] = '#';
2404 		hash[1] = hex[(color.r >> 4) & 0x0f];
2405 		hash[2] = hex[ color.r       & 0x0f];
2406 		hash[3] = hex[(color.g >> 4) & 0x0f];
2407 		hash[4] = hex[ color.g       & 0x0f];
2408 		hash[5] = hex[(color.b >> 4) & 0x0f];
2409 		hash[6] = hex[ color.b       & 0x0f];
2410 		hash[7] = 0;
2411 		wmf_attr_add (API, attrlist, "color", hash);
2412 	}
2413 
2414 	if (SCAN (API)) wmf_ipa_color_add (API,&color);
2415 
2416 	switch (Record->function)
2417 	{
2418 	case META_SETTEXTCOLOR:
2419 		WMF_DC_SET_TEXTCOLOR (P->dc,&color);
2420 	break;
2421 
2422 	case META_SETBKCOLOR:
2423 		WMF_DC_SET_BACKGROUND (P->dc,&color);
2424 	break;
2425 
2426 	default:
2427 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
2428 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
2429 		API->err = wmf_E_Glitch;
2430 	break;
2431 	}
2432 
2433 	return (changed);
2434 }
2435 
meta_dc_select(wmfAPI * API,wmfRecord * Record)2436 static int meta_dc_select (wmfAPI* API,wmfRecord* Record)
2437 {	int changed = 0;
2438 
2439 	wmfPlayer_t* P = (wmfPlayer_t*) API->player_data;
2440 
2441 	wmfObject* objects;
2442 	wmfObject* obj;
2443 
2444 	U16 oid;
2445 
2446 	objects = P->objects;
2447 
2448 	if (SCAN (API) && DIAG (API))
2449 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
2450 		fprintf (stderr,"\t#par=%lu; max. index = 0",Record->size);
2451 	}
2452 
2453 	oid = ParU16 (API,Record,0);
2454 
2455 	if (oid >= NUM_OBJECTS (API))
2456 	{	WMF_ERROR (API,"Object out of range!");
2457 		API->err = wmf_E_BadFormat;
2458 		return (changed);
2459 	}
2460 
2461 	obj = objects + oid;
2462 
2463 	if (SCAN (API) && DIAG (API))
2464 	{	diagnose_object (API,(unsigned int) oid,obj);
2465 	}
2466 
2467 	switch (obj->type)
2468 	{
2469 	case OBJ_BRUSH:
2470 		WMF_DC_SET_BRUSH (P->dc,&(obj->obj.brush));
2471 	break;
2472 
2473 	case OBJ_PEN:
2474 		WMF_DC_SET_PEN (P->dc,&(obj->obj.pen));
2475 	break;
2476 
2477 	case OBJ_FONT:
2478 		WMF_DC_SET_FONT (P->dc,&(obj->obj.font));
2479 	break;
2480 
2481 	default:
2482 		WMF_DEBUG (API,"unexpected object type!");
2483 	break;
2484 	}
2485 
2486 	return (changed);
2487 }
2488 
meta_dc_save(wmfAPI * API,wmfRecord * Record)2489 static int meta_dc_save (wmfAPI* API,wmfRecord* Record) /* complete ?? */
2490 {	int changed = 0;
2491 
2492 	wmfPlayer_t* P = (wmfPlayer_t*) API->player_data;
2493 
2494 	if (SCAN (API) && DIAG (API))
2495 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
2496 		fprintf (stderr,"\t#par=%lu; max. index = ?",Record->size);
2497 	}
2498 
2499 	dc_stack_push (API,P->dc);
2500 
2501 	P->dc = dc_copy (API,P->dc);
2502 
2503 	return (changed);
2504 }
2505 
meta_dc_restore(wmfAPI * API,wmfRecord * Record)2506 static int meta_dc_restore (wmfAPI* API,wmfRecord* Record)
2507 {	int changed = 0;
2508 
2509 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
2510 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
2511 
2512 	wmfRegion* clip;
2513 
2514 	wmfPolyRectangle_t polyrect;
2515 	wmfUserData_t      userdata;
2516 
2517 	unsigned int i;
2518 
2519 	if (SCAN (API) && DIAG (API))
2520 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
2521 		fprintf (stderr,"\t#par=%lu; max. index = ?",Record->size);
2522 	}
2523 
2524 	/* for (i = PAR(0); i < 0; i++) *//* Implies PAR(0) is signed ?? */
2525 
2526 	userdata.dc = P->dc;
2527 	userdata.data = P->dc->userdata;
2528 
2529 	if (PLAY (API) && FR->udata_free) FR->udata_free (API,&userdata);
2530 
2531 	clip = (wmfRegion*) P->dc->clip;
2532 
2533 	wmf_free (API,clip->rects);
2534 
2535 	wmf_free (API,P->dc->clip);
2536 	wmf_free (API,P->dc);
2537 
2538 	P->dc = dc_stack_pop (API);
2539 
2540 	if (ERR (API))
2541 	{	WMF_DEBUG (API,"bailing...");
2542 		return (changed);
2543 	}
2544 
2545 	if (SCAN (API)) return (changed);
2546 
2547 	userdata.dc = P->dc;
2548 	userdata.data = P->dc->userdata;
2549 
2550 	if (FR->udata_set) FR->udata_set (API,&userdata);
2551 
2552 	clip = (wmfRegion*) P->dc->clip;
2553 
2554 	polyrect.dc = P->dc;
2555 
2556 	polyrect.width  = 0;
2557 	polyrect.height = 0;
2558 
2559 	if (clip->numRects)
2560 	{	polyrect.TL = (wmfD_Coord*) wmf_malloc (API,clip->numRects * sizeof (wmfD_Coord));
2561 
2562 		if (ERR (API))
2563 		{	WMF_DEBUG (API,"bailing...");
2564 			return (changed);
2565 		}
2566 
2567 		polyrect.BR = (wmfD_Coord*) wmf_malloc (API,clip->numRects * sizeof (wmfD_Coord));
2568 
2569 		if (ERR (API))
2570 		{	WMF_DEBUG (API,"bailing...");
2571 			return (changed);
2572 		}
2573 
2574 		polyrect.count = clip->numRects;
2575 		for (i = 0; i < polyrect.count; i++)
2576 		{	polyrect.TL[i] = clip->rects[i].TL;
2577 			polyrect.BR[i] = clip->rects[i].BR;
2578 		}
2579 
2580 		if (FR->region_clip) FR->region_clip (API,&polyrect);
2581 
2582 		wmf_free (API,polyrect.TL);
2583 		wmf_free (API,polyrect.BR);
2584 	}
2585 	else
2586 	{	polyrect.TL = 0;
2587 		polyrect.BR = 0;
2588 
2589 		polyrect.count = 0;
2590 
2591 		if (FR->region_clip) FR->region_clip (API,&polyrect);
2592 	}
2593 
2594 
2595 	return (changed);
2596 }
2597 
meta_text(wmfAPI * API,wmfRecord * Record)2598 static int meta_text (wmfAPI* API,wmfRecord* Record)
2599 {	int changed = 0;
2600 
2601 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
2602 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
2603 	wmfFontData*          FD = (wmfFontData*)          API->font_data;
2604 
2605 	wmfRecord str_record;
2606 	wmfRecord lpDx_record;
2607 
2608 	wmfL_Coord l_pt;
2609 
2610 	wmfD_Coord d_pt;
2611 	wmfD_Coord t_pt;
2612 	wmfD_Coord o_pt;
2613 
2614 	wmfDrawText_t drawtext;
2615 
2616 	wmfFont* font = 0;
2617 
2618 	U16 par_U16;
2619 	U16 par_U16_x;
2620 	U16 par_U16_y;
2621 
2622 	U16 i;
2623 	U16 length = 0;
2624 
2625 	U16 bbox_info = 0;
2626 
2627 	U16 l_width;
2628 
2629 	U16* lpDx = 0;
2630 
2631 	char buffer[2];
2632 
2633 	char* str_save;
2634 
2635 	double theta;
2636 	double ratio;
2637 
2638 	float cos_theta;
2639 	float sin_theta;
2640 
2641 	float width;
2642 
2643 	switch (Record->function)
2644 	{
2645 	case META_TEXTOUT:
2646 		if (SCAN (API) && DIAG (API))
2647 		{	fprintf (stderr,"\t[0x%04x]",Record->function);
2648 			fprintf (stderr,"\t#par=%lu; max. index = 0",Record->size);
2649 		}
2650 
2651 		if (WMF_DC_TEXTALIGN (P->dc) & TA_UPDATECP)
2652 		{	if ((Record->size) < (unsigned int)(1 + (length + 1) / 2))
2653 			{	WMF_ERROR (API,"Record is too short!");
2654 				API->err = wmf_E_BadFormat;
2655 				break;
2656 			}
2657 
2658 			l_pt = P->current;
2659 		}
2660 		else
2661 		{	if ((Record->size) < (unsigned int)(3 + (length + 1) / 2))
2662 			{	WMF_ERROR (API,"Record is too short!");
2663 				API->err = wmf_E_BadFormat;
2664 				break;
2665 			}
2666 
2667 			if (SCAN (API) && DIAG (API))
2668 			{	fprintf (stderr,",-2,-1");
2669 			}
2670 
2671 			par_U16_x  = ParU16 (API,Record,(Record->size)-1);
2672 			par_U16_y  = ParU16 (API,Record,(Record->size)-2);
2673 
2674 			l_pt = L_Coord (par_U16_x,par_U16_y);
2675 		}
2676 
2677 		drawtext.pt = wmf_D_Coord_translate (API,l_pt);
2678 
2679 		length = ParU16 (API,Record,0);
2680 
2681 		if (length == 0) break;
2682 
2683 		drawtext.TL.x = 0;
2684 		drawtext.TL.y = 0;
2685 
2686 		drawtext.BR.x = 0;
2687 		drawtext.BR.y = 0;
2688 
2689 		str_record = OffsetRecord (API,Record,1);
2690 	break;
2691 
2692 	case META_EXTTEXTOUT:
2693 		if (SCAN (API) && DIAG (API))
2694 		{	fprintf (stderr,"\t[0x%04x]",Record->function);
2695 		}
2696 
2697 		if (WMF_DC_TEXTALIGN (P->dc) & TA_UPDATECP)
2698 		{	if (SCAN (API) && DIAG (API))
2699 			{	fprintf (stderr,"\t#par=%lu; index 0-1 ignored; max. index = 3",Record->size);
2700 			}
2701 
2702 			l_pt = P->current;
2703 		}
2704 		else
2705 		{	if (SCAN (API) && DIAG (API))
2706 			{	fprintf (stderr,"\t#par=%lu; max. index = 3",Record->size);
2707 			}
2708 
2709 			par_U16_x  = ParU16 (API,Record,1);
2710 			par_U16_y  = ParU16 (API,Record,0);
2711 
2712 			l_pt = L_Coord (par_U16_x,par_U16_y);
2713 		}
2714 
2715 		drawtext.pt = wmf_D_Coord_translate (API,l_pt);
2716 
2717 		length = ParU16 (API,Record,2);
2718 
2719 		if (length == 0) break;
2720 
2721 		bbox_info = ParU16 (API,Record,3);
2722 		if (bbox_info)
2723 		{	if (SCAN (API) && DIAG (API))
2724 			{	fprintf (stderr,",7");
2725 			}
2726 
2727 			par_U16_x  = ParU16 (API,Record,4); /* Is this right ?? */
2728 			par_U16_y  = ParU16 (API,Record,5);
2729 
2730 			l_pt = L_Coord (par_U16_x,par_U16_y);
2731 
2732 			drawtext.TL = wmf_D_Coord_translate (API,l_pt);
2733 
2734 			par_U16_x  = ParU16 (API,Record,6); /* Is this right ?? */
2735 			par_U16_y  = ParU16 (API,Record,7);
2736 
2737 			l_pt = L_Coord (par_U16_x,par_U16_y);
2738 
2739 			drawtext.BR = wmf_D_Coord_translate (API,l_pt);
2740 
2741 			if (SCAN (API))
2742 			{	D_Coord_Register (API,drawtext.TL,0);
2743 				D_Coord_Register (API,drawtext.BR,0);
2744 			}
2745 
2746 			str_record = OffsetRecord (API,Record,8);
2747 		}
2748 		else
2749 		{	drawtext.TL.x = 0;
2750 			drawtext.TL.y = 0;
2751 
2752 			drawtext.BR.x = 0;
2753 			drawtext.BR.y = 0;
2754 
2755 			str_record = OffsetRecord (API,Record,4);
2756 		}
2757 	break;
2758 
2759 	default:
2760 		WMF_ERROR (API,"libwmf: erk! programmer's error...");
2761 		WMF_ERROR (API,"        please contact us at http://www.wvware.com/");
2762 		API->err = wmf_E_Glitch;
2763 	break;
2764 	}
2765 
2766 	if (ERR (API)) return (changed);
2767 
2768 	if (length == 0) return (changed);
2769 
2770 	drawtext.str = (char*) wmf_malloc (API,length + 1);
2771 
2772 	if (ERR (API))
2773 	{	WMF_DEBUG (API,"bailing...");
2774 		return (changed);
2775 	}
2776 
2777 	font = WMF_DC_FONT (P->dc);
2778 
2779         /* FIXME: bug here?  Negative font height is supposed to represent absolute font pointsize */
2780 	drawtext.font_height = (double) WMF_FONT_HEIGHT (font) * ABS (P->dc->pixel_height);
2781 
2782         /* FIXME: bug here, WMF_FONT_WIDTH and  WMF_FONT_HEIGHT do not necessarily have same scale! */
2783 	drawtext.font_ratio = (double) WMF_FONT_WIDTH (font) / (double) WMF_FONT_HEIGHT (font);
2784 
2785 	par_U16 = 0;
2786 	for (i = 0; i < length; i++)
2787 	{	if (i & 1)
2788 		{	drawtext.str[i] =  (par_U16 >> 8) & 0xff;
2789 		}
2790 		else
2791 		{	par_U16 = ParU16 (API,&str_record,i/2);
2792 			drawtext.str[i] =  par_U16 & 0xff;
2793 		}
2794 	}
2795 	drawtext.str[length] = '\0';
2796 
2797 	width = FD->stringwidth (API,font,drawtext.str);
2798 
2799 	width = (float) ((double) width * drawtext.font_height * drawtext.font_ratio);
2800 
2801 	lpDx_record = OffsetRecord (API,&str_record,(length+1)/2);
2802 
2803 	if ((Record->function == META_EXTTEXTOUT) && ((lpDx_record.size) >= length))
2804 	{	lpDx = (U16*) wmf_malloc (API,length * sizeof (U16));
2805 
2806 		if (ERR (API))
2807 		{	WMF_DEBUG (API,"bailing...");
2808 			return (changed);
2809 		}
2810 
2811 		l_width = 0;
2812 		for (i = 0; i < length; i++)
2813 		{	lpDx[i] = ParU16 (API,&lpDx_record,i);
2814 			l_width += lpDx[i];
2815 		}
2816 
2817 		l_pt = L_Coord (0,0);
2818 		t_pt = wmf_D_Coord_translate (API,l_pt);
2819 		l_pt = L_Coord (l_width,0);
2820 		d_pt = wmf_D_Coord_translate (API,l_pt);
2821 
2822 		width = d_pt.x - t_pt.x;
2823 	}
2824 
2825 	theta = - WMF_TEXT_ANGLE (font);
2826 
2827 	cos_theta = (float) cos (theta);
2828 	sin_theta = (float) sin (theta);
2829 
2830 	/* Okay, have text reference point, string width & font height, & angle (in radians)
2831 	 * Compute bounding box and adjust for alignment:
2832 	 */
2833 	if (WMF_DC_TEXTALIGN (P->dc) & TA_BASELINE)
2834 	{	/* */
2835 	}
2836 	else if (WMF_DC_TEXTALIGN (P->dc) & TA_BOTTOM)
2837 	{	d_pt.y = - drawtext.font_height / 3; /* This is only approximate... */
2838 		t_pt.x = - d_pt.y * sin_theta;
2839 		t_pt.y =   d_pt.y * cos_theta;
2840 		drawtext.pt.x += t_pt.x;
2841 		drawtext.pt.y += t_pt.y;
2842 	}
2843 	else /* if (WMF_DC_TEXTALIGN (P->dc) & TA_TOP) */
2844 	{	d_pt.y = drawtext.font_height;       /* This is only approximate... */
2845 		t_pt.x = - d_pt.y * sin_theta;
2846 		t_pt.y =   d_pt.y * cos_theta;
2847 		drawtext.pt.x += t_pt.x;
2848 		drawtext.pt.y += t_pt.y;
2849 	}
2850 
2851 	if (WMF_DC_TEXTALIGN (P->dc) & TA_CENTER)
2852 	{	d_pt.x = width / 2;
2853 		d_pt.y = - drawtext.font_height * 0.77;
2854 		t_pt.x = d_pt.x * cos_theta - d_pt.y * sin_theta;
2855 		t_pt.y = d_pt.x * sin_theta + d_pt.y * cos_theta;
2856 		drawtext.bbox.TR.x = drawtext.pt.x + t_pt.x;
2857 		drawtext.bbox.TR.y = drawtext.pt.y + t_pt.y;
2858 		D_Coord_Register (API,drawtext.bbox.TR,0);
2859 
2860 		drawtext.bbox.BL.x = drawtext.pt.x - t_pt.x;
2861 		drawtext.bbox.BL.y = drawtext.pt.y - t_pt.y;
2862 		D_Coord_Register (API,drawtext.bbox.BL,0);
2863 
2864 		d_pt.x = width / 2;
2865 		d_pt.y = drawtext.font_height * 0.23;
2866 		t_pt.x = d_pt.x * cos_theta - d_pt.y * sin_theta;
2867 		t_pt.y = d_pt.x * sin_theta + d_pt.y * cos_theta;
2868 		drawtext.bbox.BR.x = drawtext.pt.x + t_pt.x;
2869 		drawtext.bbox.BR.y = drawtext.pt.y + t_pt.y;
2870 		D_Coord_Register (API,drawtext.bbox.BR,0);
2871 
2872 		drawtext.bbox.TL.x = drawtext.pt.x - t_pt.x;
2873 		drawtext.bbox.TL.y = drawtext.pt.y - t_pt.y;
2874 		D_Coord_Register (API,drawtext.bbox.TL,0);
2875 
2876 		d_pt.x = - width / 2;
2877 		t_pt.x = d_pt.x * cos_theta;
2878 		t_pt.y = d_pt.x * sin_theta;
2879 		drawtext.pt.x += t_pt.x;
2880 		drawtext.pt.y += t_pt.y;
2881 	}
2882 	else if (WMF_DC_TEXTALIGN (P->dc) & TA_RIGHT)
2883 	{	d_pt.y = - drawtext.font_height * 0.77;
2884 		t_pt.x = - d_pt.y * sin_theta;
2885 		t_pt.y =   d_pt.y * cos_theta;
2886 		drawtext.bbox.TR.x = drawtext.pt.x + t_pt.x;
2887 		drawtext.bbox.TR.y = drawtext.pt.y + t_pt.y;
2888 		D_Coord_Register (API,drawtext.bbox.TR,0);
2889 
2890 		d_pt.y = drawtext.font_height * 0.23;
2891 		t_pt.x = - d_pt.y * sin_theta;
2892 		t_pt.y =   d_pt.y * cos_theta;
2893 		drawtext.bbox.BR.x = drawtext.pt.x + t_pt.x;
2894 		drawtext.bbox.BR.y = drawtext.pt.y + t_pt.y;
2895 		D_Coord_Register (API,drawtext.bbox.BR,0);
2896 
2897 		d_pt.x = - width;
2898 		d_pt.y = - drawtext.font_height * 0.77;
2899 		t_pt.x = d_pt.x * cos_theta - d_pt.y * sin_theta;
2900 		t_pt.y = d_pt.x * sin_theta + d_pt.y * cos_theta;
2901 		drawtext.bbox.TL.x = drawtext.pt.x + t_pt.x;
2902 		drawtext.bbox.TL.y = drawtext.pt.y + t_pt.y;
2903 		D_Coord_Register (API,drawtext.bbox.TL,0);
2904 
2905 		d_pt.x = - width;
2906 		d_pt.y = drawtext.font_height * 0.23;
2907 		t_pt.x = d_pt.x * cos_theta - d_pt.y * sin_theta;
2908 		t_pt.y = d_pt.x * sin_theta + d_pt.y * cos_theta;
2909 		drawtext.bbox.BL.x = drawtext.pt.x + t_pt.x;
2910 		drawtext.bbox.BL.y = drawtext.pt.y + t_pt.y;
2911 		D_Coord_Register (API,drawtext.bbox.BL,0);
2912 
2913 		d_pt.x = - width;
2914 		t_pt.x = d_pt.x * cos_theta;
2915 		t_pt.y = d_pt.x * sin_theta;
2916 		d_pt.x = drawtext.pt.x + t_pt.x;
2917 		d_pt.y = drawtext.pt.y + t_pt.y;
2918 
2919 		drawtext.pt = d_pt;
2920 
2921 		if (WMF_DC_TEXTALIGN (P->dc) & TA_UPDATECP)
2922 		{	P->current = wmf_L_Coord_translate (API,drawtext.pt);
2923 		}
2924 	}
2925 	else /* if (WMF_DC_TEXTALIGN (P->dc) & TA_LEFT) */
2926 	{	d_pt.y = - drawtext.font_height * 0.77;
2927 		t_pt.x = - d_pt.y * sin_theta;
2928 		t_pt.y =   d_pt.y * cos_theta;
2929 		drawtext.bbox.TL.x = drawtext.pt.x + t_pt.x;
2930 		drawtext.bbox.TL.y = drawtext.pt.y + t_pt.y;
2931 		D_Coord_Register (API,drawtext.bbox.TL,0);
2932 
2933 		d_pt.y = drawtext.font_height * 0.23;
2934 		t_pt.x = - d_pt.y * sin_theta;
2935 		t_pt.y =   d_pt.y * cos_theta;
2936 		drawtext.bbox.BL.x = drawtext.pt.x + t_pt.x;
2937 		drawtext.bbox.BL.y = drawtext.pt.y + t_pt.y;
2938 		D_Coord_Register (API,drawtext.bbox.BL,0);
2939 
2940 		d_pt.x = width;
2941 		d_pt.y = - drawtext.font_height * 0.77;
2942 		t_pt.x = d_pt.x * cos_theta - d_pt.y * sin_theta;
2943 		t_pt.y = d_pt.x * sin_theta + d_pt.y * cos_theta;
2944 		drawtext.bbox.TR.x = drawtext.pt.x + t_pt.x;
2945 		drawtext.bbox.TR.y = drawtext.pt.y + t_pt.y;
2946 		D_Coord_Register (API,drawtext.bbox.TR,0);
2947 
2948 		d_pt.x = width;
2949 		d_pt.y = drawtext.font_height * 0.23;
2950 		t_pt.x = d_pt.x * cos_theta - d_pt.y * sin_theta;
2951 		t_pt.y = d_pt.x * sin_theta + d_pt.y * cos_theta;
2952 		drawtext.bbox.BR.x = drawtext.pt.x + t_pt.x;
2953 		drawtext.bbox.BR.y = drawtext.pt.y + t_pt.y;
2954 		D_Coord_Register (API,drawtext.bbox.BR,0);
2955 
2956 		if (WMF_DC_TEXTALIGN (P->dc) & TA_UPDATECP)
2957 		{	d_pt.x = width;
2958 			t_pt.x = d_pt.x * cos_theta;
2959 			t_pt.y = d_pt.x * sin_theta;
2960 			d_pt.x = drawtext.pt.x + t_pt.x;
2961 			d_pt.y = drawtext.pt.y + t_pt.y;
2962 
2963 			P->current = wmf_L_Coord_translate (API,drawtext.pt);
2964 		}
2965 	}
2966 
2967 	if (SCAN (API))
2968 	{	wmf_free (API,drawtext.str);
2969 		if (lpDx) wmf_free (API,lpDx);
2970 		return (changed);
2971 	}
2972 
2973 	drawtext.dc = P->dc;
2974 
2975 	drawtext.flags = bbox_info;
2976 
2977 	if (lpDx)
2978 	{	str_save = drawtext.str;
2979 		drawtext.str = buffer;
2980 		t_pt = drawtext.pt;
2981 		ratio = drawtext.font_ratio;
2982 		l_width = 0;
2983 		for (i = 0; i < length; i++)
2984 		{	buffer[0] = str_save[i];
2985 			buffer[1] = 0;
2986 
2987 			l_pt = L_Coord (0,0);
2988 			o_pt = wmf_D_Coord_translate (API,l_pt);
2989 			l_pt = L_Coord (l_width,0);
2990 			d_pt = wmf_D_Coord_translate (API,l_pt);
2991 			d_pt.x -= o_pt.x;
2992 			d_pt.y -= o_pt.y;
2993 			drawtext.pt.x = t_pt.x + d_pt.x * cos_theta;
2994 			drawtext.pt.y = t_pt.y + d_pt.x * sin_theta;
2995 
2996 			l_pt = L_Coord (0,0);
2997 			o_pt = wmf_D_Coord_translate (API,l_pt);
2998 			l_pt = L_Coord (lpDx[i],0);
2999 			d_pt = wmf_D_Coord_translate (API,l_pt);
3000 			d_pt.x -= o_pt.x;
3001 			d_pt.y -= o_pt.y;
3002 			width = FD->stringwidth (API,font,drawtext.str);
3003 			width = (float) ((double) width * drawtext.font_height * ratio);
3004 			if (d_pt.x < width)
3005 			{	drawtext.font_ratio = ratio * (d_pt.x / width);
3006 			}
3007 			else
3008 			{	drawtext.font_ratio = ratio;
3009 			}
3010 
3011 			if (FR->draw_text) FR->draw_text (API,&drawtext);
3012 
3013 			l_width += lpDx[i];
3014 
3015 			drawtext.bbox.TL.x = 0;
3016 			drawtext.bbox.TL.y = 0;
3017 			drawtext.bbox.TR.x = 0;
3018 			drawtext.bbox.TR.y = 0;
3019 			drawtext.bbox.BL.x = 0;
3020 			drawtext.bbox.BL.y = 0;
3021 			drawtext.bbox.BR.x = 0;
3022 			drawtext.bbox.BR.y = 0;
3023 		}
3024 		wmf_free (API,lpDx);
3025 	}
3026 	else
3027 	{	if (FR->draw_text) FR->draw_text (API,&drawtext);
3028 	}
3029 
3030 	wmf_free (API,drawtext.str);
3031 
3032 	return (changed);
3033 }
3034 
meta_pen_create(wmfAPI * API,wmfRecord * Record,wmfAttributes * attrlist)3035 static int meta_pen_create (wmfAPI* API,wmfRecord* Record,wmfAttributes* attrlist) /* complete, I think */
3036 {	int changed = 0;
3037 
3038 	wmfPlayer_t* P  = (wmfPlayer_t*) API->player_data;
3039 
3040 	wmfObject* objects = 0;
3041 	wmfObject* obj_pen = 0;
3042 
3043 	wmfRGB color;
3044 
3045 	wmfPen* pen = 0;
3046 
3047 	U16 par_U16_rg;
3048 	U16 par_U16_b;
3049 	U16 par_U16_w;
3050 	U16 par_U16_s;
3051 
3052 	U16 oid_pen;
3053 
3054 	U16 i;
3055 
3056 	const char * value = 0;
3057 	char hash[8];
3058 	unsigned long rgbhex;
3059 
3060 	static char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
3061 
3062 	objects = P->objects;
3063 
3064 	i = 0;
3065 	while ((i < NUM_OBJECTS (API)) && objects[i].type) i++;
3066 
3067 	if (i == NUM_OBJECTS (API))
3068 	{	WMF_ERROR (API,"Object out of range!");
3069 		API->err = wmf_E_BadFormat;
3070 		return (changed);
3071 	}
3072 
3073 	oid_pen = i;
3074 	obj_pen = objects + oid_pen;
3075 
3076 	obj_pen->type = OBJ_PEN;
3077 
3078 	pen = &(obj_pen->obj.pen);
3079 
3080 	if (SCAN (API) && DIAG (API))
3081 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
3082 		fprintf (stderr,"\t#par=%lu; index 2 skipped; max. index = 4",Record->size);
3083 
3084 		diagnose_object (API,(unsigned int) oid_pen,obj_pen);
3085 	}
3086 
3087 	par_U16_s = ParU16 (API,Record,0);
3088 
3089 	WMF_PEN_SET_STYLE  (pen,par_U16_s); /* Need to do all of these separately... */
3090 	WMF_PEN_SET_ENDCAP (pen,par_U16_s);
3091 	WMF_PEN_SET_JOIN   (pen,par_U16_s);
3092 	WMF_PEN_SET_TYPE   (pen,par_U16_s);
3093 
3094 	par_U16_w = ParU16 (API,Record,1);
3095 
3096 	par_U16_w = MAX (1,par_U16_w);
3097 
3098 	WMF_PEN_SET_WIDTH  (pen,(double) par_U16_w * ABS (P->dc->pixel_width ));
3099 	WMF_PEN_SET_HEIGHT (pen,(double) par_U16_w * ABS (P->dc->pixel_height));
3100 
3101 	if (API->flags & API_ENABLE_EDITING)
3102 	{	if ((value = wmf_attr_query (API, attrlist, "color")))
3103 		{	if ((*value) == '#')
3104 			{	if (sscanf (value+1, "%lx", &rgbhex) == 1)
3105 				{	par_U16_rg = (U16) ((rgbhex >> 8) & 0xffff);
3106 					par_U16_b  = (U16) ( rgbhex       & 0x00ff);
3107 
3108 					if (PutParU16 (API,Record,4,par_U16_b )) changed = 1;
3109 					if (PutParU16 (API,Record,3,par_U16_rg)) changed = 1;
3110 				}
3111 				else
3112 				{	value = 0; /* force a re-write below */
3113 				}
3114 			}
3115 			else
3116 			{	value = 0; /* force a re-write below */
3117 			}
3118 		}
3119 	}
3120 
3121 	par_U16_b  = ParU16 (API,Record,4);
3122 	par_U16_rg = ParU16 (API,Record,3);
3123 
3124 	color = rgb (par_U16_rg,par_U16_b);
3125 
3126 	if ((API->flags & API_ENABLE_EDITING) && ((value == 0) || changed))
3127 	{	hash[0] = '#';
3128 		hash[1] = hex[(color.r >> 4) & 0x0f];
3129 		hash[2] = hex[ color.r       & 0x0f];
3130 		hash[3] = hex[(color.g >> 4) & 0x0f];
3131 		hash[4] = hex[ color.g       & 0x0f];
3132 		hash[5] = hex[(color.b >> 4) & 0x0f];
3133 		hash[6] = hex[ color.b       & 0x0f];
3134 		hash[7] = 0;
3135 		wmf_attr_add (API, attrlist, "color", hash);
3136 	}
3137 
3138 	WMF_PEN_SET_COLOR (pen,&color);
3139 
3140 	if (SCAN (API)) wmf_ipa_color_add (API,&color);
3141 
3142 	if (WMF_PEN_STYLE (pen) != PS_NULL) { WMF_DEBUG (API,"Non-null pen style..."); }
3143 
3144 	WMF_DC_SET_PEN (P->dc,pen);
3145 
3146 	return (changed);
3147 }
3148 
meta_brush_create(wmfAPI * API,wmfRecord * Record,wmfAttributes * attrlist)3149 static int meta_brush_create (wmfAPI* API,wmfRecord* Record,wmfAttributes* attrlist) /* unfinished */
3150 {	int changed = 0;
3151 
3152 	wmfPlayer_t* P  = (wmfPlayer_t*) API->player_data;
3153 
3154 	wmfObject* objects = 0;
3155 	wmfObject* obj_brush = 0;
3156 
3157 	wmfRGB color;
3158 
3159 	wmfBrush* brush = 0;
3160 
3161 	wmfBMP bmp;
3162 
3163 	U16 par_U16_rg;
3164 	U16 par_U16_b;
3165 
3166 	U16 oid_brush;
3167 
3168 	U16 i;
3169 
3170 	const char * value = 0;
3171 	char hash[8];
3172 	unsigned long rgbhex;
3173 
3174 	static char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
3175 
3176 	objects = P->objects;
3177 
3178 	i = 0;
3179 	while ((i < NUM_OBJECTS (API)) && objects[i].type) i++;
3180 
3181 	if (i == NUM_OBJECTS (API))
3182 	{	WMF_ERROR (API,"Object out of range!");
3183 		API->err = wmf_E_BadFormat;
3184 		return (changed);
3185 	}
3186 
3187 	oid_brush = i;
3188 	obj_brush = objects + oid_brush;
3189 
3190 	obj_brush->type = OBJ_BRUSH;
3191 
3192 	brush = &(obj_brush->obj.brush);
3193 
3194 	if (SCAN (API) && DIAG (API))
3195 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
3196 		fprintf (stderr,"\t#par=%lu; max. index = 3",Record->size);
3197 
3198 		diagnose_object (API,(unsigned int) oid_brush,obj_brush);
3199 	}
3200 
3201 	WMF_BRUSH_SET_STYLE (brush,ParU16 (API,Record,0));
3202 
3203 	if (API->flags & API_ENABLE_EDITING)
3204 	{	if ((value = wmf_attr_query (API, attrlist, "color")))
3205 		{	if ((*value) == '#')
3206 			{	if (sscanf (value+1, "%lx", &rgbhex) == 1)
3207 				{	par_U16_rg = (U16) ((rgbhex >> 8) & 0xffff);
3208 					par_U16_b  = (U16) ( rgbhex       & 0x00ff);
3209 
3210 					if (PutParU16 (API,Record,2,par_U16_b )) changed = 1;
3211 					if (PutParU16 (API,Record,1,par_U16_rg)) changed = 1;
3212 				}
3213 				else
3214 				{	value = 0; /* force a re-write below */
3215 				}
3216 			}
3217 			else
3218 			{	value = 0; /* force a re-write below */
3219 			}
3220 		}
3221 	}
3222 
3223 	par_U16_b  = ParU16 (API,Record,2);
3224 	par_U16_rg = ParU16 (API,Record,1);
3225 
3226 	color = rgb (par_U16_rg,par_U16_b);
3227 
3228 	if ((API->flags & API_ENABLE_EDITING) && ((value == 0) || changed))
3229 	{	hash[0] = '#';
3230 		hash[1] = hex[(color.r >> 4) & 0x0f];
3231 		hash[2] = hex[ color.r       & 0x0f];
3232 		hash[3] = hex[(color.g >> 4) & 0x0f];
3233 		hash[4] = hex[ color.g       & 0x0f];
3234 		hash[5] = hex[(color.b >> 4) & 0x0f];
3235 		hash[6] = hex[ color.b       & 0x0f];
3236 		hash[7] = 0;
3237 		wmf_attr_add (API, attrlist, "color", hash);
3238 	}
3239 
3240 	WMF_BRUSH_SET_COLOR (brush,&color);
3241 
3242 	WMF_BRUSH_SET_HATCH (brush,ParU16 (API,Record,3));
3243 
3244 	bmp.width  = 0;
3245 	bmp.height = 0;
3246 
3247 	bmp.data = 0;
3248 
3249 	WMF_BRUSH_SET_BITMAP (brush,&bmp);
3250 
3251 	if (SCAN (API)) wmf_ipa_color_add (API,&color);
3252 
3253 	WMF_DC_SET_BRUSH (P->dc,brush);
3254 
3255 	return (changed);
3256 }
3257 
meta_font_create(wmfAPI * API,wmfRecord * Record)3258 static int meta_font_create (wmfAPI* API,wmfRecord* Record)
3259 {	int changed = 0;
3260 
3261 	wmfPlayer_t* P  = (wmfPlayer_t*) API->player_data;
3262 	wmfFontData* FD = (wmfFontData*) API->font_data;
3263 
3264 	wmfRecord name_record;
3265 
3266 	wmfObject* objects = 0;
3267 	wmfObject* obj_font = 0;
3268 
3269 	wmfFont* font = 0;
3270 
3271 	U16 oid_font;
3272 
3273 	U16 par_U16;
3274 
3275 	S16 par_S16_w;
3276 	S16 par_S16_h;
3277 
3278 	unsigned long i;
3279 	unsigned long length;
3280 
3281 	char* fontname = 0;
3282 
3283 	objects = P->objects;
3284 
3285 	i = 0;
3286 	while ((i < NUM_OBJECTS (API)) && objects[i].type) i++;
3287 
3288 	if (i == NUM_OBJECTS (API))
3289 	{	WMF_ERROR (API,"Object out of range!");
3290 		API->err = wmf_E_BadFormat;
3291 		return (changed);
3292 	}
3293 
3294 	oid_font = i;
3295 	obj_font = objects + oid_font;
3296 
3297 	obj_font->type = OBJ_FONT;
3298 
3299 	font = &(obj_font->obj.font);
3300 
3301 	if (SCAN (API) && DIAG (API))
3302 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
3303 		fprintf (stderr,"\t#par=%lu; max. index = 8",Record->size);
3304 
3305 		diagnose_object (API,(unsigned int) oid_font,obj_font);
3306 	}
3307 
3308 	par_S16_w = ParS16 (API,Record,1);
3309 	par_S16_h = ParS16 (API,Record,0);
3310 
3311 	WMF_FONT_SET_HEIGHT (font,ABS (par_S16_h));
3312 	WMF_FONT_SET_WIDTH  (font,ABS (par_S16_w));
3313 
3314 	WMF_FONT_SET_ESCAPEMENT  (font,ParS16 (API,Record,2)); /* text angle */
3315 	WMF_FONT_SET_ORIENTATION (font,ParS16 (API,Record,3));
3316 
3317 	WMF_FONT_SET_WEIGHT (font,ParU16 (API,Record,4));
3318 
3319 	par_U16 = ParU16 (API,Record,5);
3320 	WMF_FONT_SET_ITALIC (font,par_U16 & 0xff);
3321 
3322 	WMF_TEXT_SET_UNDERLINE (font,(par_U16 >> 8) & 0xff);
3323 
3324 	par_U16 = ParU16 (API,Record,6);
3325 	WMF_TEXT_SET_STRIKEOUT (font,par_U16 & 0xff);
3326 
3327 	WMF_FONT_SET_CHARSET (font,(par_U16 >> 8) & 0xff);
3328 
3329 	par_U16 = ParU16 (API,Record,7);
3330 	WMF_FONT_SET_OUT (font,par_U16 & 0xff);
3331 
3332 	WMF_FONT_SET_CLIP (font,(par_U16 >> 8) & 0xff);
3333 
3334 	par_U16 = ParU16 (API,Record,8);
3335 	WMF_FONT_SET_QUALITY (font,par_U16 & 0xff);
3336 
3337 	WMF_FONT_SET_PITCH (font,(par_U16 >> 8) & 0xff);
3338 
3339 	if (WMF_FONT_WIDTH (font) == 0)
3340 	{	WMF_FONT_SET_WIDTH (font,WMF_FONT_HEIGHT (font));
3341 	}
3342 
3343 	name_record = OffsetRecord (API,Record,9);
3344 
3345 	length = (name_record.size) * 2;
3346 
3347 	fontname = (char*) wmf_malloc (API,length + 1);
3348 
3349 	if (ERR (API))
3350 	{	WMF_DEBUG (API,"bailing...");
3351 		return (changed);
3352 	}
3353 
3354 	par_U16 = 0;
3355 	for (i = 0; i < length; i++)
3356 	{	if (i & 1)
3357 		{	fontname[i] = (par_U16 >> 8) & 0xff;
3358 		}
3359 		else
3360 		{	par_U16 = ParU16 (API,&name_record,i/2);
3361 			fontname[i] = par_U16 & 0xff;
3362 		}
3363 	}
3364 	fontname[length] = '\0';
3365 
3366 	WMF_FONT_SET_NAME (font,fontname); /* must not free fontname */
3367 
3368 	font->user_data = 0;
3369 
3370 	FD->map (API,font); /* Determine/Load freetype face */
3371 
3372 	if (ERR (API))
3373 	{	WMF_DEBUG (API,"bailing...");
3374 		return (changed);
3375 	}
3376 
3377 	WMF_DC_SET_FONT (P->dc,font);
3378 
3379 	return (changed);
3380 }
3381 
meta_palette_create(wmfAPI * API)3382 static int meta_palette_create (wmfAPI* API)
3383 {	int changed = 0;
3384 
3385 	wmfPlayer_t* P  = (wmfPlayer_t*) API->player_data;
3386 
3387 	wmfObject* objects = 0;
3388 
3389 	unsigned long i;
3390 
3391 	objects = P->objects;
3392 
3393 	i = 0;
3394 	while ((i < NUM_OBJECTS (API)) && objects[i].type) i++;
3395 
3396 	if (i == NUM_OBJECTS (API))
3397 	{	WMF_ERROR (API,"Object out of range!");
3398 		API->err = wmf_E_BadFormat;
3399 		return (changed);
3400 	}
3401 
3402 	objects[i].type = OBJ_PAL;
3403 
3404 	return (changed);
3405 }
3406 
meta_delete(wmfAPI * API,wmfRecord * Record)3407 static int meta_delete (wmfAPI* API,wmfRecord* Record)
3408 {	int changed = 0;
3409 
3410 	wmfPlayer_t*          P  = (wmfPlayer_t*)          API->player_data;
3411 	wmfFunctionReference* FR = (wmfFunctionReference*) API->function_reference;
3412 
3413 	wmfObject* objects;
3414 	wmfObject* obj;
3415 
3416 	U16 oid;
3417 
3418 	objects = P->objects;
3419 
3420 	if (SCAN (API) && DIAG (API))
3421 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
3422 		fprintf (stderr,"\t#par=%lu; max. index = 0",Record->size);
3423 	}
3424 
3425 	oid = ParU16 (API,Record,0);
3426 
3427 	if (oid >= NUM_OBJECTS (API))
3428 	{	WMF_ERROR (API,"Object out of range!");
3429 		API->err = wmf_E_BadFormat;
3430 		return (changed);
3431 	}
3432 
3433 	obj = objects + oid;
3434 
3435 	if (SCAN (API) && DIAG (API))
3436 	{	diagnose_object (API,(unsigned int) oid,obj);
3437 	}
3438 
3439 	if (obj->type == OBJ_BRUSH)
3440 	{	if (obj->obj.brush.lbStyle == BS_DIBPATTERN)
3441 		{	if (PLAY (API) && FR->bmp_free) FR->bmp_free (API,&(obj->obj.brush.bmp));
3442 		}
3443 	}
3444 	else if (obj->type == OBJ_REGION)
3445 	{	wmf_free (API,obj->obj.rgn.rects);
3446 	}
3447 
3448 	obj->type = 0;
3449 
3450 	return (changed);
3451 }
3452 
meta_unused(wmfAPI * API,wmfRecord * Record)3453 static int meta_unused (wmfAPI* API,wmfRecord* Record)
3454 {	int changed = 0;
3455 
3456 	if (SCAN (API) && DIAG (API))
3457 	{	fprintf (stderr,"\t[0x%04x]",Record->function);
3458 		fprintf (stderr,"\t#par=%lu; max. index = ?",Record->size);
3459 	}
3460 
3461 	/* META_SETSTRETCHBLTMODE: not all that important really */
3462 
3463 	/* META_SETMAPPERFLAGS:
3464 extract from http://www.melander.dk/lib/windows/gdi/fontmap.htm
3465 					{
3466 					Windows Font Mapping
3467 
3468 					Ron Gery
3469 					Microsoft Developer Network Technology Group
3470 
3471 					Created: June 8, 1992
3472 
3473 					Filters
3474 
3475 An application can, to some extent, filter which physical fonts are examined by the font mapper.
3476 Aspect-ratio filtering, which is available in both Windows versions 3.0 and 3.1, allows an
3477 application to specify that only fonts designed for the device's aspect ratio should be considered
3478 by the font mapper. An application enables and disables this filter by using the SetMapperFlags
3479 function. Because nonscaling raster fonts are designed with a certain aspect ratio in mind, it is
3480 sometimes desirable to ensure that only fonts actually designed for the device are used. When this
3481 filter is enabled, the font mapper does not consider any physical fonts whose design aspect ratio
3482 does not match that of the device. Aspect-ratio filtering does not affect TrueType fonts because
3483 they can scale to match any aspect ratio. This filter affects all font selections to the DC until
3484 the filter is turned off. Aspect-ratio filtering is a holdover from earlier times and is not a
3485 recommended approach in today's font world.
3486 					}
3487 
3488 	So we're going to ignore this call entirely */
3489 
3490 	/* META_REALIZEPALETTE:
3491 	   META_SELECTPALETTE:
3492 	   META_SETPALENTRIES:
3493 	as these set and fiddle with the palette i don't think
3494 	they have much relevence to our converter, we will
3495 	do our own color management elsewhere (if we do it
3496 	at all), so i think we can safely ignore these things. */
3497 
3498 	/* META_ESCAPE: ?? */
3499 
3500 	return (changed);
3501 }
3502 
diagnose_object(wmfAPI * API,unsigned int oid,wmfObject * obj)3503 static void diagnose_object (wmfAPI* API,unsigned int oid,wmfObject* obj)
3504 {	fprintf (stderr,"\toid=%u / %u ",(unsigned) oid,(unsigned) NUM_OBJECTS (API));
3505 
3506 	switch (obj->type)
3507 	{
3508 	case OBJ_BRUSH:
3509 		fprintf (stderr,"(brush)");
3510 	break;
3511 
3512 	case OBJ_PEN:
3513 		fprintf (stderr,"(pen)");
3514 	break;
3515 
3516 	case OBJ_FONT:
3517 		fprintf (stderr,"(font)");
3518 	break;
3519 
3520 	case OBJ_REGION:
3521 		fprintf (stderr,"(region)");
3522 	break;
3523 
3524 	case OBJ_PAL:
3525 		fprintf (stderr,"(palette)");
3526 	break;
3527 
3528 	default:
3529 		fprintf (stderr,"(other [%u])",(unsigned) obj->type);
3530 	break;
3531 	}
3532 }
3533 
3534 #endif /* ! WMFPLAYER_META_H */
3535