forked from mathog/libUEMF
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuwmf.c
More file actions
7038 lines (6335 loc) · 239 KB
/
Copy pathuwmf.c
File metadata and controls
7038 lines (6335 loc) · 239 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
@file uwmf.c
@brief Functions for manipulating WMF files and structures.
[U_WMR*]_set all take data and return a pointer to memory holding the constructed record.
If something goes wrong a NULL pointer is returned.
[U_WMR*]_get takes a pointer to memory and returns the length of that record as well
as the values from it (in the provided fields, passed by reference.)
If something goes wrong, a size of 0 is returned.
The _set material comes first, then all of the _get material.
Compile with "U_VALGRIND" defined defined to enable code which lets valgrind check each record for
uninitialized data.
Compile with "SOL8" defined for Solaris 8 or 9 (Sparc).
*/
/*
File: uwmf.c
Version: 0.0.17
Date: 28-MAR-2015
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h> /* for offsetof() */
#include <string.h>
#include <iconv.h>
#include <wchar.h>
#include <errno.h>
#include <string.h>
#include <limits.h> // for INT_MAX, INT_MIN
#include <math.h> // for U_ROUND()
#if 0
#include <windef.h> //Not actually used, looking for collisions
#include <winnt.h> //Not actually used, looking for collisions
#include <wingdi.h> //Not actually used, looking for collisions
#endif
#include "uwmf.h"
#include "uwmf_endian.h"
#include "uemf_safe.h"
/**
\brief Look up the full numeric type of a WMR record by type.
\return Full numeric value for this type of WMR record, Returns 0xFFFFFFFF if out of range.
\param idx WMR record type.
*/
uint32_t U_wmr_values(int idx){
int ret;
int U_WMR_VALUES[256]={
0x0000, //!< U_WMR_EOF
0x0201, //!< U_WMR_SETBKCOLOR
0x0102, //!< U_WMR_SETBKMODE
0x0103, //!< U_WMR_SETMAPMODE
0x0104, //!< U_WMR_SETROP2
0x0105, //!< U_WMR_SETRELABS
0x0106, //!< U_WMR_SETPOLYFILLMODE
0x0107, //!< U_WMR_SETSTRETCHBLTMODE
0x0108, //!< U_WMR_SETTEXTCHAREXTRA
0x0209, //!< U_WMR_SETTEXTCOLOR
0x020A, //!< U_WMR_SETTEXTJUSTIFICATION
0x020B, //!< U_WMR_SETWINDOWORG
0x020C, //!< U_WMR_SETWINDOWEXT
0x020D, //!< U_WMR_SETVIEWPORTORG
0x020E, //!< U_WMR_SETVIEWPORTEXT
0x020F, //!< U_WMR_OFFSETWINDOWORG
0x0410, //!< U_WMR_SCALEWINDOWEXT
0x0211, //!< U_WMR_OFFSETVIEWPORTORG
0x0412, //!< U_WMR_SCALEVIEWPORTEXT
0x0213, //!< U_WMR_LINETO
0x0214, //!< U_WMR_MOVETO
0x0415, //!< U_WMR_EXCLUDECLIPRECT
0x0416, //!< U_WMR_INTERSECTCLIPRECT
0x0817, //!< U_WMR_ARC
0x0418, //!< U_WMR_ELLIPSE
0x0419, //!< U_WMR_FLOODFILL
0x081A, //!< U_WMR_PIE
0x041B, //!< U_WMR_RECTANGLE
0x061C, //!< U_WMR_ROUNDRECT
0x061D, //!< U_WMR_PATBLT
0x001E, //!< U_WMR_SAVEDC
0x041F, //!< U_WMR_SETPIXEL
0x0220, //!< U_WMR_OFFSETCLIPRGN
0x0521, //!< U_WMR_TEXTOUT
0x0922, //!< U_WMR_BITBLT
0x0B23, //!< U_WMR_STRETCHBLT
0x0324, //!< U_WMR_POLYGON
0x0325, //!< U_WMR_POLYLINE
0x0626, //!< U_WMR_ESCAPE
0x0127, //!< U_WMR_RESTOREDC
0x0228, //!< U_WMR_FILLREGION
0x0429, //!< U_WMR_FRAMEREGION
0x012A, //!< U_WMR_INVERTREGION
0x012B, //!< U_WMR_PAINTREGION
0x012C, //!< U_WMR_SELECTCLIPREGION
0x012D, //!< U_WMR_SELECTOBJECT
0x012E, //!< U_WMR_SETTEXTALIGN
0x062F, //!< U_WMR_DRAWTEXT
0x0830, //!< U_WMR_CHORD
0x0231, //!< U_WMR_SETMAPPERFLAGS
0x0A32, //!< U_WMR_EXTTEXTOUT
0x0D33, //!< U_WMR_SETDIBTODEV
0x0234, //!< U_WMR_SELECTPALETTE
0x0035, //!< U_WMR_REALIZEPALETTE
0x0436, //!< U_WMR_ANIMATEPALETTE
0x0037, //!< U_WMR_SETPALENTRIES
0x0538, //!< U_WMR_POLYPOLYGON
0x0139, //!< U_WMR_RESIZEPALETTE
0x003A, //!< U_WMR_3A
0x003B, //!< U_WMR_3B
0x003C, //!< U_WMR_3C
0x003D, //!< U_WMR_3D
0x003E, //!< U_WMR_3E
0x003F, //!< U_WMR_3F
0x0940, //!< U_WMR_DIBBITBLT
0x0B41, //!< U_WMR_DIBSTRETCHBLT
0x0142, //!< U_WMR_DIBCREATEPATTERNBRUSH
0x0F43, //!< U_WMR_STRETCHDIB
0x0044, //!< U_WMR_44
0x0045, //!< U_WMR_45
0x0046, //!< U_WMR_46
0x0047, //!< U_WMR_47
0x0548, //!< U_WMR_EXTFLOODFILL
0x0049, //!< U_WMR_49
0x004A, //!< U_WMR_4A
0x004B, //!< U_WMR_4B
0x014C, //!< U_WMR_4C
0x014D, //!< U_WMR_4D
0x004E, //!< U_WMR_4E
0x004F, //!< U_WMR_4F
0x0050, //!< U_WMR_50
0x0051, //!< U_WMR_51
0x0052, //!< U_WMR_52
0x0053, //!< U_WMR_53
0x0054, //!< U_WMR_54
0x0055, //!< U_WMR_55
0x0056, //!< U_WMR_56
0x0057, //!< U_WMR_57
0x0058, //!< U_WMR_58
0x0059, //!< U_WMR_59
0x005A, //!< U_WMR_5A
0x005B, //!< U_WMR_5B
0x005C, //!< U_WMR_5C
0x005D, //!< U_WMR_5D
0x005E, //!< U_WMR_5E
0x005F, //!< U_WMR_5F
0x0060, //!< U_WMR_60
0x0061, //!< U_WMR_61
0x0062, //!< U_WMR_62
0x0063, //!< U_WMR_63
0x0064, //!< U_WMR_64
0x0065, //!< U_WMR_65
0x0066, //!< U_WMR_66
0x0067, //!< U_WMR_67
0x0068, //!< U_WMR_68
0x0069, //!< U_WMR_69
0x006A, //!< U_WMR_6A
0x006B, //!< U_WMR_6B
0x006C, //!< U_WMR_6C
0x006D, //!< U_WMR_6D
0x006E, //!< U_WMR_6E
0x006F, //!< U_WMR_6F
0x0070, //!< U_WMR_70
0x0071, //!< U_WMR_71
0x0072, //!< U_WMR_72
0x0073, //!< U_WMR_73
0x0074, //!< U_WMR_74
0x0075, //!< U_WMR_75
0x0076, //!< U_WMR_76
0x0077, //!< U_WMR_77
0x0078, //!< U_WMR_78
0x0079, //!< U_WMR_79
0x007A, //!< U_WMR_7A
0x007B, //!< U_WMR_7B
0x007C, //!< U_WMR_7C
0x007D, //!< U_WMR_7D
0x007E, //!< U_WMR_7E
0x007F, //!< U_WMR_7F
0x0080, //!< U_WMR_80
0x0081, //!< U_WMR_81
0x0082, //!< U_WMR_82
0x0083, //!< U_WMR_83
0x0084, //!< U_WMR_84
0x0085, //!< U_WMR_85
0x0086, //!< U_WMR_86
0x0087, //!< U_WMR_87
0x0088, //!< U_WMR_88
0x0089, //!< U_WMR_89
0x008A, //!< U_WMR_8A
0x008B, //!< U_WMR_8B
0x008C, //!< U_WMR_8C
0x008D, //!< U_WMR_8D
0x008E, //!< U_WMR_8E
0x008F, //!< U_WMR_8F
0x0090, //!< U_WMR_90
0x0091, //!< U_WMR_91
0x0092, //!< U_WMR_92
0x0093, //!< U_WMR_93
0x0094, //!< U_WMR_94
0x0095, //!< U_WMR_95
0x0096, //!< U_WMR_96
0x0097, //!< U_WMR_97
0x0098, //!< U_WMR_98
0x0099, //!< U_WMR_99
0x009A, //!< U_WMR_9A
0x009B, //!< U_WMR_9B
0x009C, //!< U_WMR_9C
0x009D, //!< U_WMR_9D
0x009E, //!< U_WMR_9E
0x009F, //!< U_WMR_9F
0x00A0, //!< U_WMR_A0
0x00A1, //!< U_WMR_A1
0x00A2, //!< U_WMR_A2
0x00A3, //!< U_WMR_A3
0x00A4, //!< U_WMR_A4
0x00A5, //!< U_WMR_A5
0x00A6, //!< U_WMR_A6
0x00A7, //!< U_WMR_A7
0x00A8, //!< U_WMR_A8
0x00A9, //!< U_WMR_A9
0x00AA, //!< U_WMR_AA
0x00AB, //!< U_WMR_AB
0x00AC, //!< U_WMR_AC
0x00AD, //!< U_WMR_AD
0x00AE, //!< U_WMR_AE
0x00AF, //!< U_WMR_AF
0x00B0, //!< U_WMR_B0
0x00B1, //!< U_WMR_B1
0x00B2, //!< U_WMR_B2
0x00B3, //!< U_WMR_B3
0x00B4, //!< U_WMR_B4
0x00B5, //!< U_WMR_B5
0x00B6, //!< U_WMR_B6
0x00B7, //!< U_WMR_B7
0x00B8, //!< U_WMR_B8
0x00B9, //!< U_WMR_B9
0x00BA, //!< U_WMR_BA
0x00BB, //!< U_WMR_BB
0x00BC, //!< U_WMR_BC
0x00BD, //!< U_WMR_BD
0x00BE, //!< U_WMR_BE
0x00BF, //!< U_WMR_BF
0x00C0, //!< U_WMR_C0
0x00C1, //!< U_WMR_C1
0x00C2, //!< U_WMR_C2
0x00C3, //!< U_WMR_C3
0x00C4, //!< U_WMR_C4
0x00C5, //!< U_WMR_C5
0x00C6, //!< U_WMR_C6
0x00C7, //!< U_WMR_C7
0x00C8, //!< U_WMR_C8
0x00C9, //!< U_WMR_C9
0x00CA, //!< U_WMR_CA
0x00CB, //!< U_WMR_CB
0x00CC, //!< U_WMR_CC
0x00CD, //!< U_WMR_CD
0x00CE, //!< U_WMR_CE
0x00CF, //!< U_WMR_CF
0x00D0, //!< U_WMR_D0
0x00D1, //!< U_WMR_D1
0x00D2, //!< U_WMR_D2
0x00D3, //!< U_WMR_D3
0x00D4, //!< U_WMR_D4
0x00D5, //!< U_WMR_D5
0x00D6, //!< U_WMR_D6
0x00D7, //!< U_WMR_D7
0x00D8, //!< U_WMR_D8
0x00D9, //!< U_WMR_D9
0x00DA, //!< U_WMR_DA
0x00DB, //!< U_WMR_DB
0x00DC, //!< U_WMR_DC
0x00DD, //!< U_WMR_DD
0x00DE, //!< U_WMR_DE
0x00DF, //!< U_WMR_DF
0x00E0, //!< U_WMR_E0
0x00E1, //!< U_WMR_E1
0x00E2, //!< U_WMR_E2
0x00E3, //!< U_WMR_E3
0x00E4, //!< U_WMR_E4
0x00E5, //!< U_WMR_E5
0x00E6, //!< U_WMR_E6
0x00E7, //!< U_WMR_E7
0x00E8, //!< U_WMR_E8
0x00E9, //!< U_WMR_E9
0x00EA, //!< U_WMR_EA
0x00EB, //!< U_WMR_EB
0x00EC, //!< U_WMR_EC
0x00ED, //!< U_WMR_ED
0x00EE, //!< U_WMR_EE
0x00EF, //!< U_WMR_EF
0x01F0, //!< U_WMR_DELETEOBJECT
0x00F1, //!< U_WMR_F1
0x00F2, //!< U_WMR_F2
0x00F3, //!< U_WMR_F3
0x00F4, //!< U_WMR_F4
0x00F5, //!< U_WMR_F5
0x00F6, //!< U_WMR_F6
0x00F7, //!< U_WMR_CREATEPALETTE
0x00F8, //!< U_WMR_CREATEBRUSH
0x01F9, //!< U_WMR_CREATEPATTERNBRUSH
0x02FA, //!< U_WMR_CREATEPENINDIRECT
0x02FB, //!< U_WMR_CREATEFONTINDIRECT
0x02FC, //!< U_WMR_CREATEBRUSHINDIRECT
0x02FD, //!< U_WMR_CREATEBITMAPINDIRECT
0x06FE, //!< U_WMR_CREATEBITMAP
0x06FF //!< U_WMR_CREATEREGION
};
if(idx<U_WMR_MIN || idx > U_WMR_MAX){ ret = 0xFFFFFFFF; }
else { ret = U_WMR_VALUES[idx]; }
return(ret);
}
/**
\brief Look up the name of the WMR record by type. Returns U_WMR_INVALID if out of range.
\return name of the WMR record, "U_WMR_INVALID" if out of range.
\param idx WMR record type.
*/
const char *U_wmr_names(int idx){
int ret;
static const char *U_WMR_NAMES[257]={
"U_WMR_EOF",
"U_WMR_SETBKCOLOR",
"U_WMR_SETBKMODE",
"U_WMR_SETMAPMODE",
"U_WMR_SETROP2",
"U_WMR_SETRELABS",
"U_WMR_SETPOLYFILLMODE",
"U_WMR_SETSTRETCHBLTMODE",
"U_WMR_SETTEXTCHAREXTRA",
"U_WMR_SETTEXTCOLOR",
"U_WMR_SETTEXTJUSTIFICATION",
"U_WMR_SETWINDOWORG",
"U_WMR_SETWINDOWEXT",
"U_WMR_SETVIEWPORTORG",
"U_WMR_SETVIEWPORTEXT",
"U_WMR_OFFSETWINDOWORG",
"U_WMR_SCALEWINDOWEXT",
"U_WMR_OFFSETVIEWPORTORG",
"U_WMR_SCALEVIEWPORTEXT",
"U_WMR_LINETO",
"U_WMR_MOVETO",
"U_WMR_EXCLUDECLIPRECT",
"U_WMR_INTERSECTCLIPRECT",
"U_WMR_ARC",
"U_WMR_ELLIPSE",
"U_WMR_FLOODFILL",
"U_WMR_PIE",
"U_WMR_RECTANGLE",
"U_WMR_ROUNDRECT",
"U_WMR_PATBLT",
"U_WMR_SAVEDC",
"U_WMR_SETPIXEL",
"U_WMR_OFFSETCLIPRGN",
"U_WMR_TEXTOUT",
"U_WMR_BITBLT",
"U_WMR_STRETCHBLT",
"U_WMR_POLYGON",
"U_WMR_POLYLINE",
"U_WMR_ESCAPE",
"U_WMR_RESTOREDC",
"U_WMR_FILLREGION",
"U_WMR_FRAMEREGION",
"U_WMR_INVERTREGION",
"U_WMR_PAINTREGION",
"U_WMR_SELECTCLIPREGION",
"U_WMR_SELECTOBJECT",
"U_WMR_SETTEXTALIGN",
"U_WMR_DRAWTEXT",
"U_WMR_CHORD",
"U_WMR_SETMAPPERFLAGS",
"U_WMR_EXTTEXTOUT",
"U_WMR_SETDIBTODEV",
"U_WMR_SELECTPALETTE",
"U_WMR_REALIZEPALETTE",
"U_WMR_ANIMATEPALETTE",
"U_WMR_SETPALENTRIES",
"U_WMR_POLYPOLYGON",
"U_WMR_RESIZEPALETTE",
"U_WMR_3A",
"U_WMR_3B",
"U_WMR_3C",
"U_WMR_3D",
"U_WMR_3E",
"U_WMR_3F",
"U_WMR_DIBBITBLT",
"U_WMR_DIBSTRETCHBLT",
"U_WMR_DIBCREATEPATTERNBRUSH",
"U_WMR_STRETCHDIB",
"U_WMR_44",
"U_WMR_45",
"U_WMR_46",
"U_WMR_47",
"U_WMR_EXTFLOODFILL",
"U_WMR_49",
"U_WMR_4A",
"U_WMR_4B",
"U_WMR_4C",
"U_WMR_4D",
"U_WMR_4E",
"U_WMR_4F",
"U_WMR_50",
"U_WMR_51",
"U_WMR_52",
"U_WMR_53",
"U_WMR_54",
"U_WMR_55",
"U_WMR_56",
"U_WMR_57",
"U_WMR_58",
"U_WMR_59",
"U_WMR_5A",
"U_WMR_5B",
"U_WMR_5C",
"U_WMR_5D",
"U_WMR_5E",
"U_WMR_5F",
"U_WMR_60",
"U_WMR_61",
"U_WMR_62",
"U_WMR_63",
"U_WMR_64",
"U_WMR_65",
"U_WMR_66",
"U_WMR_67",
"U_WMR_68",
"U_WMR_69",
"U_WMR_6A",
"U_WMR_6B",
"U_WMR_6C",
"U_WMR_6D",
"U_WMR_6E",
"U_WMR_6F",
"U_WMR_70",
"U_WMR_71",
"U_WMR_72",
"U_WMR_73",
"U_WMR_74",
"U_WMR_75",
"U_WMR_76",
"U_WMR_77",
"U_WMR_78",
"U_WMR_79",
"U_WMR_7A",
"U_WMR_7B",
"U_WMR_7C",
"U_WMR_7D",
"U_WMR_7E",
"U_WMR_7F",
"U_WMR_80",
"U_WMR_81",
"U_WMR_82",
"U_WMR_83",
"U_WMR_84",
"U_WMR_85",
"U_WMR_86",
"U_WMR_87",
"U_WMR_88",
"U_WMR_89",
"U_WMR_8A",
"U_WMR_8B",
"U_WMR_8C",
"U_WMR_8D",
"U_WMR_8E",
"U_WMR_8F",
"U_WMR_90",
"U_WMR_91",
"U_WMR_92",
"U_WMR_93",
"U_WMR_94",
"U_WMR_95",
"U_WMR_96",
"U_WMR_97",
"U_WMR_98",
"U_WMR_99",
"U_WMR_9A",
"U_WMR_9B",
"U_WMR_9C",
"U_WMR_9D",
"U_WMR_9E",
"U_WMR_9F",
"U_WMR_A0",
"U_WMR_A1",
"U_WMR_A2",
"U_WMR_A3",
"U_WMR_A4",
"U_WMR_A5",
"U_WMR_A6",
"U_WMR_A7",
"U_WMR_A8",
"U_WMR_A9",
"U_WMR_AA",
"U_WMR_AB",
"U_WMR_AC",
"U_WMR_AD",
"U_WMR_AE",
"U_WMR_AF",
"U_WMR_B0",
"U_WMR_B1",
"U_WMR_B2",
"U_WMR_B3",
"U_WMR_B4",
"U_WMR_B5",
"U_WMR_B6",
"U_WMR_B7",
"U_WMR_B8",
"U_WMR_B9",
"U_WMR_BA",
"U_WMR_BB",
"U_WMR_BC",
"U_WMR_BD",
"U_WMR_BE",
"U_WMR_BF",
"U_WMR_C0",
"U_WMR_C1",
"U_WMR_C2",
"U_WMR_C3",
"U_WMR_C4",
"U_WMR_C5",
"U_WMR_C6",
"U_WMR_C7",
"U_WMR_C8",
"U_WMR_C9",
"U_WMR_CA",
"U_WMR_CB",
"U_WMR_CC",
"U_WMR_CD",
"U_WMR_CE",
"U_WMR_CF",
"U_WMR_D0",
"U_WMR_D1",
"U_WMR_D2",
"U_WMR_D3",
"U_WMR_D4",
"U_WMR_D5",
"U_WMR_D6",
"U_WMR_D7",
"U_WMR_D8",
"U_WMR_D9",
"U_WMR_DA",
"U_WMR_DB",
"U_WMR_DC",
"U_WMR_DD",
"U_WMR_DE",
"U_WMR_DF",
"U_WMR_E0",
"U_WMR_E1",
"U_WMR_E2",
"U_WMR_E3",
"U_WMR_E4",
"U_WMR_E5",
"U_WMR_E6",
"U_WMR_E7",
"U_WMR_E8",
"U_WMR_E9",
"U_WMR_EA",
"U_WMR_EB",
"U_WMR_EC",
"U_WMR_ED",
"U_WMR_EE",
"U_WMR_EF",
"U_WMR_DELETEOBJECT",
"U_WMR_F1",
"U_WMR_F2",
"U_WMR_F3",
"U_WMR_F4",
"U_WMR_F5",
"U_WMR_F6",
"U_WMR_CREATEPALETTE",
"U_WMR_CREATEBRUSH",
"U_WMR_CREATEPATTERNBRUSH",
"U_WMR_CREATEPENINDIRECT",
"U_WMR_CREATEFONTINDIRECT",
"U_WMR_CREATEBRUSHINDIRECT",
"U_WMR_CREATEBITMAPINDIRECT",
"U_WMR_CREATEBITMAP",
"U_WMR_CREATEREGION"
};
if(idx<U_WMR_MIN || idx > U_WMR_MAX){ ret = 256; }
else { ret = idx; }
return(U_WMR_NAMES[ret]);
}
/**
\brief Text description of Escape record type.
\return name of the WMR record, "UNKNOWN_ESCAPE" if out of range.
\param idx Escape record type.
*/
const char *U_wmr_escnames(int idx){
const char *name;
if(idx>=1 && idx <= 0x0023){
switch(idx){
case 0x0001: name = "NEWFRAME"; break;
case 0x0002: name = "ABORTDOC"; break;
case 0x0003: name = "NEXTBAND"; break;
case 0x0004: name = "SETCOLORTABLE"; break;
case 0x0005: name = "GETCOLORTABLE"; break;
case 0x0006: name = "FLUSHOUT"; break;
case 0x0007: name = "DRAFTMODE"; break;
case 0x0008: name = "QUERYESCSUPPORT"; break;
case 0x0009: name = "SETABORTPROC"; break;
case 0x000A: name = "STARTDOC"; break;
case 0x000B: name = "ENDDOC"; break;
case 0x000C: name = "GETPHYSPAGESIZE"; break;
case 0x000D: name = "GETPRINTINGOFFSET"; break;
case 0x000E: name = "GETSCALINGFACTOR"; break;
case 0x000F: name = "META_ESCAPE_ENHANCED_METAFILE"; break;
case 0x0010: name = "SETPENWIDTH"; break;
case 0x0011: name = "SETCOPYCOUNT"; break;
case 0x0012: name = "SETPAPERSOURCE"; break;
case 0x0013: name = "PASSTHROUGH"; break;
case 0x0014: name = "GETTECHNOLOGY"; break;
case 0x0015: name = "SETLINECAP"; break;
case 0x0016: name = "SETLINEJOIN"; break;
case 0x0017: name = "SETMITERLIMIT"; break;
case 0x0018: name = "BANDINFO"; break;
case 0x0019: name = "DRAWPATTERNRECT"; break;
case 0x001A: name = "GETVECTORPENSIZE"; break;
case 0x001B: name = "GETVECTORBRUSHSIZE"; break;
case 0x001C: name = "ENABLEDUPLEX"; break;
case 0x001D: name = "GETSETPAPERBINS"; break;
case 0x001E: name = "GETSETPRINTORIENT"; break;
case 0x001F: name = "ENUMPAPERBINS"; break;
case 0x0020: name = "SETDIBSCALING"; break;
case 0x0021: name = "EPSPRINTING"; break;
case 0x0022: name = "ENUMPAPERMETRICS"; break;
case 0x0023: name = "GETSETPAPERMETRICS"; break;
}
}
else if(idx == 0x0025){ name = "POSTSCRIPT_DATA"; }
else if(idx == 0x0026){ name = "POSTSCRIPT_IGNORE"; }
else if(idx == 0x002A){ name = "GETDEVICEUNITS"; }
else if(idx == 0x0100){ name = "GETEXTENDEDTEXTMETRICS"; }
else if(idx == 0x0102){ name = "GETPAIRKERNTABLE"; }
else if(idx == 0x0200){ name = "EXTTEXTOUT"; }
else if(idx == 0x0201){ name = "GETFACENAME"; }
else if(idx == 0x0202){ name = "DOWNLOADFACE"; }
else if(idx == 0x0801){ name = "METAFILE_DRIVER"; }
else if(idx == 0x0C01){ name = "QUERYDIBSUPPORT"; }
else if(idx == 0x1000){ name = "BEGIN_PATH"; }
else if(idx == 0x1001){ name = "CLIP_TO_PATH"; }
else if(idx == 0x1002){ name = "END_PATH"; }
else if(idx == 0x100E){ name = "OPEN_CHANNEL"; }
else if(idx == 0x100F){ name = "DOWNLOADHEADER"; }
else if(idx == 0x1010){ name = "CLOSE_CHANNEL"; }
else if(idx == 0x1013){ name = "POSTSCRIPT_PASSTHROUGH"; }
else if(idx == 0x1014){ name = "ENCAPSULATED_POSTSCRIPT";}
else if(idx == 0x1015){ name = "POSTSCRIPT_IDENTIFY"; }
else if(idx == 0x1016){ name = "POSTSCRIPT_INJECTION"; }
else if(idx == 0x1017){ name = "CHECKJPEGFORMAT"; }
else if(idx == 0x1018){ name = "CHECKPNGFORMAT"; }
else if(idx == 0x1019){ name = "GET_PS_FEATURESETTING"; }
else if(idx == 0x101A){ name = "MXDC_ESCAPE"; }
else if(idx == 0x11D8){ name = "SPCLPASSTHROUGH2"; }
else { name = "UNKNOWN_ESCAPE"; }
return(name);
}
//! \cond
/* one prototype from uwmf_endian. Put it here because end user should never need to see it, so
not in uemf.h or uwmf_endian.h */
void U_swap2(void *ul, unsigned int count);
/**
\brief Check that the bitmap in the specified packed DIB is compatible with the record size
\return 1 on success, 0 on failure
\param record EMF record that contains a DIB pixel array
\param blimit one byte past the end of the record.
This method can only test DIBs that hold Microsoft's various bitmap types. PNG or JPG is just a bag
of bytes, and there is no possible way to derive from the known width and height how big it should be.
This should not be called directly by end user code.
*/
int packed_DIB_safe(
const char *record,
const char *blimit
){
int dibparams = U_BI_UNKNOWN; // type of image not yet determined
const char *px = NULL; // DIB pixels
const U_RGBQUAD *ct = NULL; // DIB color table
int bs;
int usedbytes;
if(!bitmapinfo_safe(record, blimit))return(0); // this DIB has issues with colors fitting into the record
uint32_t numCt; // these values will be set in get_DIB_params
int32_t width, height, colortype, invert; // these values will be set in get_DIB_params
// next call returns pointers and values, but allocates no memory
dibparams = wget_DIB_params(record, &px, (const U_RGBQUAD **) &ct, &numCt, &width, &height, &colortype, &invert);
// sanity checking
if(numCt && colortype >= U_BCBM_COLOR16)return(0); //color tables not used above 16 bit pixels
if(!numCt && colortype < U_BCBM_COLOR16)return(0); //color tables mandatory for < 16 bit
if(dibparams ==U_BI_RGB){
// this is the only DIB type where we can calculate how big it should be when stored in the WMF file
bs = colortype/8;
if(bs<1){
usedbytes = (width*colortype + 7)/8; // width of line in fully and partially occupied bytes
}
else {
usedbytes = width*bs;
}
if(IS_MEM_UNSAFE(px, usedbytes, blimit))return(0);
}
return(1);
}
//! \endcond
/**
\brief Derive from bounding box and start and end arc, for WMF arc, chord, or pie records, the center, start, and end points, and the bounding rectangle.
\return 0 on success, other values on errors.
\param rclBox16 Bounding box of Arc
\param ArcStart16 Coordinates for Start of Arc
\param ArcEnd16 Coordinates for End of Arc
\param f1 1 if rotation angle >= 180, else 0
\param f2 Rotation direction, 1 if counter clockwise, else 0
\param center Center coordinates
\param start Start coordinates (point on the ellipse defined by rect)
\param end End coordinates (point on the ellipse defined by rect)
\param size W,H of the x,y axes of the bounding rectangle.
*/
int wmr_arc_points(
U_RECT16 rclBox16,
U_POINT16 ArcStart16,
U_POINT16 ArcEnd16,
int *f1,
int f2,
U_PAIRF *center,
U_PAIRF *start,
U_PAIRF *end,
U_PAIRF *size
){
U_RECTL rclBox;
U_POINTL ArcStart,ArcEnd;
rclBox.left = rclBox16.left;
rclBox.top = rclBox16.top;
rclBox.right = rclBox16.right;
rclBox.bottom = rclBox16.bottom;
ArcStart.x = ArcStart16.x;
ArcStart.y = ArcStart16.y;
ArcEnd.x = ArcEnd16.x;
ArcEnd.y = ArcEnd16.y;
return emr_arc_points_common(&rclBox, &ArcStart, &ArcEnd, f1, f2, center, start, end, size);
}
/**
\brief A U_RECT16 may have its values swapped, L<->R and T<->B, this extracts the leftmost as left, and so forth.
\param rc U_RECT156 binary contents of an WMF file
\param left the leftmost of rc.left and rc.right
\param top the topmost of rc.top and rc.bottom
\param right the rightmost of rc.left and rc.right
\param bottom the bottommost of rc.top and rc.bottom
*/
void U_sanerect16(U_RECT16 rc, double *left, double *top, double *right, double *bottom){
if(rc.left < rc.right) { *left = rc.left; *right = rc.right; }
else { *left = rc.right; *right = rc.left; }
if(rc.top < rc.bottom){ *top = rc.top; *bottom = rc.bottom; }
else{ *top = rc.bottom; *bottom = rc.top; }
}
/* **********************************************************************************************
These definitions are for code pieces that are used many times in the following implementation. These
definitions are not needed in end user code, so they are here rather than in uwmf.h.
*********************************************************************************************** */
/**
\brief Get record size in bytes from U_WMR* record, which may not be aligned
\return number of bytes in record.
*/
uint32_t U_wmr_size(const U_METARECORD *record){
uint32_t Size16;
memcpy(&Size16,record, 4);
return(2*Size16);
}
//! \cond should never be called directly
#define SET_CB_FROM_PXBMI(A,B,C,D,E,F) /* A=Px, B=Bmi, C=cbImage, D=cbImage4, E=cbBmi, F=cbPx */ \
if(A){\
if(!B)return(NULL); /* size is derived from U_BITMAPINFO, but NOT from its size field, go figure*/ \
C = F;\
D = UP4(C); /* pixel array might not be a multiples of 4 bytes*/ \
E = U_SIZE_BITMAPINFOHEADER + 4 * get_real_color_count((char *)&(B->bmiHeader)); /* bmiheader + colortable*/ \
}\
else { C = 0; D = 0; E=0; }
//! \endcond
/**
\brief Create and return a U_FONT structure.
\return pointer to the created U_FONT structure.
\param Height Height in Logical units
\param Width Average Width in Logical units
\param Escapement Angle in 0.1 degrees betweem escapement vector and X axis
\param Orientation Angle in 0.1 degrees between baseline and X axis
\param Weight LF_Weight Enumeration
\param Italic LF_Italic Enumeration
\param Underline LF_Underline Enumeration
\param StrikeOut LF_StrikeOut Enumeration
\param CharSet LF_CharSet Enumeration
\param OutPrecision LF_OutPrecision Enumeration
\param ClipPrecision LF_ClipPrecision Enumeration
\param Quality LF_Quality Enumeration
\param PitchAndFamily LF_PitchAndFamily Enumeration
\param FaceName Name of font. ANSI Latin1, null terminated.
*/
U_FONT *U_FONT_set(
int16_t Height, //!< Height in Logical units
int16_t Width, //!< Average Width in Logical units
int16_t Escapement, //!< Angle in 0.1 degrees betweem escapement vector and X axis
int16_t Orientation, //!< Angle in 0.1 degrees between baseline and X axis
int16_t Weight, //!< LF_Weight Enumeration
uint8_t Italic, //!< LF_Italic Enumeration
uint8_t Underline, //!< LF_Underline Enumeration
uint8_t StrikeOut, //!< LF_StrikeOut Enumeration
uint8_t CharSet, //!< LF_CharSet Enumeration
uint8_t OutPrecision, //!< LF_OutPrecision Enumeration
uint8_t ClipPrecision, //!< LF_ClipPrecision Enumeration
uint8_t Quality, //!< LF_Quality Enumeration
uint8_t PitchAndFamily, //!< LF_PitchAndFamily Enumeration
char *FaceName //!< Name of font. ANSI Latin1, null terminated.
){
U_FONT *font;
int slen = 1 + strlen(FaceName); /* include terminator */
if(slen & 1)slen++; /* storage length even */
font = (U_FONT *) calloc(1,slen + U_SIZE_FONT_CORE); /* use calloc to auto fill in terminating '\0'*/
if(font){
font->Height = Height;
font->Width = Width;
font->Escapement = Escapement;
font->Orientation = Orientation;
font->Weight = Weight;
font->Italic = Italic;
font->Underline = Underline;
font->StrikeOut = StrikeOut;
font->CharSet = CharSet;
font->OutPrecision = OutPrecision;
font->ClipPrecision = ClipPrecision;
font->Quality = Quality;
font->PitchAndFamily = PitchAndFamily;
strcpy((char *)&font->FaceName, FaceName);
}
return(font);
}
/**
\brief Create and return a U_PLTENTRY structure.
\return the created U_PLTENTRY structure.
\param Color Color for the U_PLTENTRY
*/
U_PLTNTRY U_PLTNTRY_set(U_COLORREF Color){
U_PLTNTRY pe;
pe.Value = Color.Reserved;
pe.Blue = Color.Blue;
pe.Green = Color.Green;
pe.Red = Color.Red;
return(pe);
}
/**
\brief Create and return a U_PALETTE structure.
\return pointer to the created U_PALETTE structure.
\param Start Either 0x0300 or an offset into the Palette table
\param NumEntries Number of U_LOGPLTNTRY objects
\param PalEntries Pointer to array of PaletteEntry Objects
*/
U_PALETTE *U_PLTENTRY_set(
uint16_t Start, //!< Either 0x0300 or an offset into the Palette table
uint16_t NumEntries, //!< Number of U_LOGPLTNTRY objects
U_PLTNTRY *PalEntries //!< Pointer to array of PaletteEntry Objects
){
U_PALETTE *Palette = NULL;
if(NumEntries){
Palette = malloc(4 + 4*NumEntries);
if(Palette){
Palette->Start = Start;
Palette->NumEntries = NumEntries;
memcpy(&Palette->PalEntries, PalEntries, NumEntries*4);
}
}
return(Palette);
}
/**
\brief Create and return a U_PEN structure.
\return the created U_PEN structure.
\param Style PenStyle Enumeration
\param Width Width of Pen
\param Color Pen Color.
*/
U_PEN U_PEN_set(
uint16_t Style, //!< PenStyle Enumeration
uint16_t Width, //!< Width of Pen
U_COLORREF Color //!< Pen Color.
){
U_PEN p;
p.Style = Style;
p.Widthw[0] = Width;
p.Widthw[1] = 0; /* ignored */
p.Color.Red = Color.Red;
p.Color.Green = Color.Green;
p.Color.Blue = Color.Blue;
p.Color.Reserved = Color.Reserved;
return(p);
}
/**
\brief Create and return a U_RECT16 structure from Upper Left and Lower Right corner points.
\param ul upper left corner of rectangle
\param lr lower right corner of rectangle
*/
U_RECT16 U_RECT16_set(
U_POINT16 ul,
U_POINT16 lr
){
U_RECT16 rect;
rect.left = ul.x;
rect.top = ul.y;
rect.right = lr.x;
rect.bottom = lr.y;
return(rect);
}
/**
\brief Create and return a U_BITMAP16 structure
\return pointer to the U_BITMAP16 structure, or NULL on failure
\param Type bitmap Type (not described at all in the WMF PDF)
\param Width bitmap width in pixels.
\param Height bitmap height in scan lines.
\param LineN each array line in Bits is a multiple of this (4 for a DIB)
\param BitsPixel number of adjacent color bits on each plane (R bits + G bits + B bits ????)
\param Bits bitmap pixel data. Bytes contained = (((Width * BitsPixel + 15) >> 4) << 1) * Height
*/
U_BITMAP16 *U_BITMAP16_set(
const int16_t Type,
const int16_t Width,
const int16_t Height,
const int16_t LineN,
const uint8_t BitsPixel,
const char *Bits
){
U_BITMAP16 *bm16;
uint32_t irecsize;
int cbBits,iHeight;
int usedbytes;
int16_t WidthBytes; // total bytes per scan line (used and padding).
usedbytes = (Width * BitsPixel + 7)/8; // width of line in fully and partially occupied bytes
WidthBytes = (LineN * ((usedbytes + (LineN - 1) ) / LineN)); // Account for padding required by line alignment in the pixel array
iHeight = (Height < 0 ? -Height : Height); /* DIB can use a negative height, but it does not look like a Bitmap16 object can */
cbBits = WidthBytes * iHeight;
if(!Bits || cbBits<=0)return(NULL);
irecsize = U_SIZE_BITMAP16 + cbBits;
bm16 = (U_BITMAP16 *) malloc(irecsize);
if(bm16){
bm16->Type = Type;
bm16->Width = Width;
bm16->Height = iHeight;
bm16->WidthBytes = WidthBytes;
bm16->Planes = 1;
bm16->BitsPixel = BitsPixel;
memcpy((char *)bm16 + U_SIZE_BITMAP16,Bits,cbBits);
}
return(bm16);
}
/**
\brief Create and return a U_SCAN structure
\return U_SCAN structure
\param count Number of entries in the ScanLines array
\param top Y coordinate of the top scanline
\param bottom Y coordinate of the bottom scanline
\param ScanLines Array of 16 bit left/right pairs, array has 2*count entries
*/
U_SCAN *U_SCAN_set(
uint16_t count, //!< Number of entries in the ScanLines array
uint16_t top, //!< Y coordinate of the top scanline
uint16_t bottom, //!< Y coordinate of the bottom scanline
uint16_t *ScanLines //!< Array of 16 bit left/right pairs, array has 2*count entries
){
U_SCAN *scan=NULL;
int size = 6 + count*4;
scan = malloc(size);
if(scan){
scan->count = count;
scan->top = top;