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