1 /**
2 @file uemf.c
3
4 @brief Functions for manipulating EMF files and structures.
5
6 [U_EMR]_set all take data and return a pointer to memory holding the constructed record.
7 The size of that record is also returned in recsize.
8 It is also in the second int32 in the record, but may have been byte swapped and so not usable.
9 If something goes wrong a NULL pointer is returned and recsize is set to 0.
10
11 Compile with "U_VALGRIND" defined defined to enable code which lets valgrind check each record for
12 uninitialized data.
13
14 Compile with "SOL8" defined for Solaris 8 or 9 (Sparc).
15 */
16
17 /*
18 File: uemf.c
19 Version: 0.0.31
20 Date: 26-JAN-2016
21 Author: David Mathog, Biology Division, Caltech
22 email: mathog@caltech.edu
23 Copyright: 2016 David Mathog and California Institute of Technology (Caltech)
24 */
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <iconv.h>
34 #include <wchar.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <limits.h> // for INT_MAX, INT_MIN
38 #include <math.h> // for U_ROUND()
39 #include <stddef.h> /* for offsetof() macro */
40 #if 0
41 #include <windef.h> //Not actually used, looking for collisions
42 #include <winnt.h> //Not actually used, looking for collisions
43 #include <wingdi.h> //Not actually used, looking for collisions
44 #endif
45 #include "uemf.h"
46
47 //! \cond
48 /* one prototype from uemf_endian. Put it here because end user should never need to see it, so
49 not in uemf.h or uemf_endian.h */
50 void U_swap2(void *ul, unsigned int count);
51 //! \endcond
52
53 /**
54 \brief Look up the name of the EMR record by type. Returns U_EMR_INVALID if out of range.
55
56 \return name of the EMR record, "U_EMR_INVALID" if out of range.
57 \param idx EMR record type.
58
59 */
U_emr_names(unsigned int idx)60 char *U_emr_names(unsigned int idx){
61 if(idx<U_EMR_MIN || idx > U_EMR_MAX){ idx = 0; }
62 static char *U_EMR_NAMES[U_EMR_MAX+1]={
63 "U_EMR_INVALID",
64 "U_EMR_HEADER",
65 "U_EMR_POLYBEZIER",
66 "U_EMR_POLYGON",
67 "U_EMR_POLYLINE",
68 "U_EMR_POLYBEZIERTO",
69 "U_EMR_POLYLINETO",
70 "U_EMR_POLYPOLYLINE",
71 "U_EMR_POLYPOLYGON",
72 "U_EMR_SETWINDOWEXTEX",
73 "U_EMR_SETWINDOWORGEX",
74 "U_EMR_SETVIEWPORTEXTEX",
75 "U_EMR_SETVIEWPORTORGEX",
76 "U_EMR_SETBRUSHORGEX",
77 "U_EMR_EOF",
78 "U_EMR_SETPIXELV",
79 "U_EMR_SETMAPPERFLAGS",
80 "U_EMR_SETMAPMODE",
81 "U_EMR_SETBKMODE",
82 "U_EMR_SETPOLYFILLMODE",
83 "U_EMR_SETROP2",
84 "U_EMR_SETSTRETCHBLTMODE",
85 "U_EMR_SETTEXTALIGN",
86 "U_EMR_SETCOLORADJUSTMENT",
87 "U_EMR_SETTEXTCOLOR",
88 "U_EMR_SETBKCOLOR",
89 "U_EMR_OFFSETCLIPRGN",
90 "U_EMR_MOVETOEX",
91 "U_EMR_SETMETARGN",
92 "U_EMR_EXCLUDECLIPRECT",
93 "U_EMR_INTERSECTCLIPRECT",
94 "U_EMR_SCALEVIEWPORTEXTEX",
95 "U_EMR_SCALEWINDOWEXTEX",
96 "U_EMR_SAVEDC",
97 "U_EMR_RESTOREDC",
98 "U_EMR_SETWORLDTRANSFORM",
99 "U_EMR_MODIFYWORLDTRANSFORM",
100 "U_EMR_SELECTOBJECT",
101 "U_EMR_CREATEPEN",
102 "U_EMR_CREATEBRUSHINDIRECT",
103 "U_EMR_DELETEOBJECT",
104 "U_EMR_ANGLEARC",
105 "U_EMR_ELLIPSE",
106 "U_EMR_RECTANGLE",
107 "U_EMR_ROUNDRECT",
108 "U_EMR_ARC",
109 "U_EMR_CHORD",
110 "U_EMR_PIE",
111 "U_EMR_SELECTPALETTE",
112 "U_EMR_CREATEPALETTE",
113 "U_EMR_SETPALETTEENTRIES",
114 "U_EMR_RESIZEPALETTE",
115 "U_EMR_REALIZEPALETTE",
116 "U_EMR_EXTFLOODFILL",
117 "U_EMR_LINETO",
118 "U_EMR_ARCTO",
119 "U_EMR_POLYDRAW",
120 "U_EMR_SETARCDIRECTION",
121 "U_EMR_SETMITERLIMIT",
122 "U_EMR_BEGINPATH",
123 "U_EMR_ENDPATH",
124 "U_EMR_CLOSEFIGURE",
125 "U_EMR_FILLPATH",
126 "U_EMR_STROKEANDFILLPATH",
127 "U_EMR_STROKEPATH",
128 "U_EMR_FLATTENPATH",
129 "U_EMR_WIDENPATH",
130 "U_EMR_SELECTCLIPPATH",
131 "U_EMR_ABORTPATH",
132 "U_EMR_UNDEF69",
133 "U_EMR_COMMENT",
134 "U_EMR_FILLRGN",
135 "U_EMR_FRAMERGN",
136 "U_EMR_INVERTRGN",
137 "U_EMR_PAINTRGN",
138 "U_EMR_EXTSELECTCLIPRGN",
139 "U_EMR_BITBLT",
140 "U_EMR_STRETCHBLT",
141 "U_EMR_MASKBLT",
142 "U_EMR_PLGBLT",
143 "U_EMR_SETDIBITSTODEVICE",
144 "U_EMR_STRETCHDIBITS",
145 "U_EMR_EXTCREATEFONTINDIRECTW",
146 "U_EMR_EXTTEXTOUTA",
147 "U_EMR_EXTTEXTOUTW",
148 "U_EMR_POLYBEZIER16",
149 "U_EMR_POLYGON16",
150 "U_EMR_POLYLINE16",
151 "U_EMR_POLYBEZIERTO16",
152 "U_EMR_POLYLINETO16",
153 "U_EMR_POLYPOLYLINE16",
154 "U_EMR_POLYPOLYGON16",
155 "U_EMR_POLYDRAW16",
156 "U_EMR_CREATEMONOBRUSH",
157 "U_EMR_CREATEDIBPATTERNBRUSHPT",
158 "U_EMR_EXTCREATEPEN",
159 "U_EMR_POLYTEXTOUTA",
160 "U_EMR_POLYTEXTOUTW",
161 "U_EMR_SETICMMODE",
162 "U_EMR_CREATECOLORSPACE",
163 "U_EMR_SETCOLORSPACE",
164 "U_EMR_DELETECOLORSPACE",
165 "U_EMR_GLSRECORD",
166 "U_EMR_GLSBOUNDEDRECORD",
167 "U_EMR_PIXELFORMAT",
168 "U_EMR_DRAWESCAPE",
169 "U_EMR_EXTESCAPE",
170 "U_EMR_UNDEF107",
171 "U_EMR_SMALLTEXTOUT",
172 "U_EMR_FORCEUFIMAPPING",
173 "U_EMR_NAMEDESCAPE",
174 "U_EMR_COLORCORRECTPALETTE",
175 "U_EMR_SETICMPROFILEA",
176 "U_EMR_SETICMPROFILEW",
177 "U_EMR_ALPHABLEND",
178 "U_EMR_SETLAYOUT",
179 "U_EMR_TRANSPARENTBLT",
180 "U_EMR_UNDEF117",
181 "U_EMR_GRADIENTFILL",
182 "U_EMR_SETLINKEDUFIS",
183 "U_EMR_SETTEXTJUSTIFICATION",
184 "U_EMR_COLORMATCHTOTARGETW",
185 "U_EMR_CREATECOLORSPACEW"
186 };
187 return(U_EMR_NAMES[idx]);
188 }
189
190
191
192 /* **********************************************************************************************
193 These definitions are for code pieces that are used many times in the following implementation. These
194 definitions are not needed in end user code, so they are here rather than in uemf.h.
195 *********************************************************************************************** */
196
197 //! @cond
198
199 // this one may also be used A=Msk,B=MskBmi and F=cbMsk
200 #define SET_CB_FROM_PXBMI(A,B,C,D,E,F) /* A=Px, B=Bmi, C=cbImage, D=cbImage4, E=cbBmi, F=cbPx */ \
201 if(A){\
202 if(!B)return(NULL); /* size is derived from U_BITMAPINFO, but NOT from its size field, go figure*/ \
203 C = F;\
204 D = UP4(C); /* pixel array might not be a multiples of 4 bytes*/ \
205 E = sizeof(U_BITMAPINFOHEADER) + 4 * get_real_color_count((const char *) &(B->bmiHeader)); /* bmiheader + colortable*/ \
206 }\
207 else { C = 0; D = 0; E=0; }
208
209 // variable "off" must be declared in the function
210
211 #define APPEND_PXBMISRC(A,B,C,D,E,F,G) /* A=record, B=U_EMR,C=cbBmi, D=Bmi, E=Px, F=cbImage, G=cbImage4 */ \
212 if(C){\
213 memcpy(A + off, D, C);\
214 ((B *) A)->offBmiSrc = off;\
215 ((B *) A)->cbBmiSrc = C;\
216 off += C;\
217 memcpy(A + off, E, F);\
218 ((B *) A)->offBitsSrc = off;\
219 ((B *) A)->cbBitsSrc = F;\
220 if(G - F){ \
221 off += F;\
222 memset(A + off, 0, G - F); \
223 }\
224 }\
225 else {\
226 ((B *) A)->offBmiSrc = 0;\
227 ((B *) A)->cbBmiSrc = 0;\
228 ((B *) A)->offBitsSrc = 0;\
229 ((B *) A)->cbBitsSrc = 0;\
230 }
231
232 // variable "off" must be declared in the function
233
234 #define APPEND_MSKBMISRC(A,B,C,D,E,F,G) /* A=record, B=U_EMR*,C=cbMskBmi, D=MskBmi, E=Msk, F=cbMskImage, G=cbMskImage4 */ \
235 if(C){\
236 memcpy(A + off, D, C);\
237 ((B *) A)->offBmiMask = off;\
238 ((B *) A)->cbBmiMask = C;\
239 off += C;\
240 memcpy(A + off, Msk, F);\
241 ((B *) A)->offBitsMask = off;\
242 ((B *) A)->cbBitsMask = F;\
243 if(G - F){ memset(A + off, 0, G - F); }\
244 }\
245 else {\
246 ((B *) A)->offBmiMask = 0;\
247 ((B *) A)->cbBmiMask = 0;\
248 ((B *) A)->offBitsMask = 0;\
249 ((B *) A)->cbBitsMask = 0;\
250 }
251
252 //! @endcond
253
254 /* **********************************************************************************************
255 These functions are used for development and debugging and should be be includied in production code.
256 *********************************************************************************************** */
257
258 /**
259 \brief Debugging utility, used with valgrind to find uninitialized values. Not for use in production code.
260 \param buf memory area to examine !
261 \param size length in bytes of buf!
262 */
memprobe(const void * buf,size_t size)263 int memprobe(
264 const void *buf,
265 size_t size
266 ){
267 int sum=0;
268 char *ptr=(char *)buf;
269 for(;size;size--,ptr++){ sum += *ptr; } // read all bytes, trigger valgrind warning if any uninitialized
270 return(sum);
271 }
272
273 /**
274 \brief Dump an EMFHANDLES structure. Not for use in production code.
275 \param string Text to output before dumping eht structure
276 \param handle Handle
277 \param eht EMFHANDLES structure to dump
278 */
dumpeht(char * string,unsigned int * handle,EMFHANDLES * eht)279 void dumpeht(
280 char *string,
281 unsigned int *handle,
282 EMFHANDLES *eht
283 ){
284 uint32_t i;
285 printf("%s\n",string);
286 printf("sptr: %d peak: %d top: %d\n",eht->sptr,eht->peak,eht->top);
287 if(handle){
288 printf("handle: %d \n",*handle);
289 }
290 for(i=0;i<=5;i++){
291 printf("table[%d]: %d\n",i,eht->table[i]);
292 }
293 for(i=1;i<=5;i++){
294 printf("stack[%d]: %d\n",i,eht->stack[i]);
295 }
296 }
297
298 /* **********************************************************************************************
299 These functions are used for Image conversions and other
300 utility operations. Character type conversions are in uemf_utf.c
301 *********************************************************************************************** */
302
303 /**
304 \brief Make up an approximate dx array to pass to emrtext_set(), based on character height and weight.
305
306 Take abs. value of character height, get width by multiplying by 0.6, and correct weight
307 approximately, with formula (measured on screen for one text line of Arial).
308 Caller is responsible for free() on the returned pointer.
309
310 \return pointer to dx array
311 \param height character height (absolute value will be used)
312 \param weight LF_Weight Enumeration (character weight)
313 \param members Number of entries to put into dx
314
315 */
dx_set(int32_t height,uint32_t weight,uint32_t members)316 uint32_t *dx_set(
317 int32_t height,
318 uint32_t weight,
319 uint32_t members
320 ){
321 uint32_t i, width, *dx;
322 dx = (uint32_t *) malloc(members * sizeof(uint32_t));
323 if(dx){
324 if(U_FW_DONTCARE == weight)weight=U_FW_NORMAL;
325 width = (uint32_t) U_ROUND(((float) (height > 0 ? height : -height)) * 0.6 * (0.00024*(float) weight + 0.904));
326 for ( i = 0; i < members; i++ ){ dx[i] = width; }
327 }
328 return(dx);
329 }
330
331 /**
332 \brief Look up the properties (a bit map) of a type of EMR record.
333 Bits that may be set are defined in "Draw Properties" in uemf.h, they are U_DRAW_NOTEMPTY, etc..
334
335 \return bitmap of EMR record properties, or U_EMR_INVALID on error or release of all memory
336 \param type EMR record type. If U_EMR_INVALID release memory. (There is no U_EMR_INVALID EMR record type)
337
338 */
emr_properties(uint32_t type)339 uint32_t emr_properties(uint32_t type){
340 static uint32_t *table=NULL;
341 uint32_t result = U_EMR_INVALID; // initialized to indicate an error (on a lookup) or nothing (on a memory release)
342 if(type == U_EMR_INVALID){
343 if(table)free(table);
344 table=NULL;
345 }
346 else if(type>=1 && type<U_EMR_MAX){
347 if(!table){
348 table = (uint32_t *) malloc(sizeof(uint32_t)*(1 + U_EMR_MAX));
349 if(!table)return(result);
350 // 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01
351 // Path properties (U_DRAW_*) TEXT ALTERS ONLYTO VISIBLE
352 // PATH FORCE CLOSED NOTEMPTY
353 table[ 0] = 0x00; // Does not map to any EMR record
354 table[ 1] = 0x80; // U_EMRHEADER 1 0 0 0 0 0 0 0
355 table[ 2] = 0x83; // U_EMRPOLYBEZIER 1 0 0 0 0 0 1 1
356 table[ 3] = 0x87; // U_EMRPOLYGON 1 0 0 0 0 1 1 1
357 table[ 4] = 0x83; // U_EMRPOLYLINE 1 0 0 0 0 0 1 1
358 table[ 5] = 0x8B; // U_EMRPOLYBEZIERTO 1 0 0 0 1 0 1 1
359 table[ 6] = 0x8B; // U_EMRPOLYLINETO 1 0 0 0 1 0 1 1
360 table[ 7] = 0x83; // U_EMRPOLYPOLYLINE 1 0 0 0 0 0 1 1
361 table[ 8] = 0x87; // U_EMRPOLYPOLYGON 1 0 0 0 0 1 1 1
362 table[ 9] = 0xA0; // U_EMRSETWINDOWEXTEX 1 0 1 0 0 0 0 0
363 table[ 10] = 0xA0; // U_EMRSETWINDOWORGEX 1 0 1 0 0 0 0 0
364 table[ 11] = 0xA0; // U_EMRSETVIEWPORTEXTEX 1 0 1 0 0 0 0 0
365 table[ 12] = 0xA0; // U_EMRSETVIEWPORTORGEX 1 0 1 0 0 0 0 0
366 table[ 13] = 0xA0; // U_EMRSETBRUSHORGEX 1 0 1 0 0 0 0 0
367 table[ 14] = 0x82; // U_EMREOF 1 0 1 0 0 0 0 0 Force out any pending draw
368 table[ 15] = 0x82; // U_EMRSETPIXELV 1 0 0 0 0 0 1 0
369 table[ 16] = 0xA0; // U_EMRSETMAPPERFLAGS 1 0 1 0 0 0 0 0
370 table[ 17] = 0xA0; // U_EMRSETMAPMODE 1 0 1 0 0 0 0 0
371 table[ 18] = 0x20; // U_EMRSETBKMODE 0 0 1 0 0 0 0 0
372 table[ 19] = 0xA0; // U_EMRSETPOLYFILLMODE 1 0 1 0 0 0 0 0
373 table[ 20] = 0xA0; // U_EMRSETROP2 1 0 1 0 0 0 0 0
374 table[ 21] = 0xA0; // U_EMRSETSTRETCHBLTMODE 1 0 1 0 0 0 0 0
375 table[ 22] = 0x20; // U_EMRSETTEXTALIGN 0 0 1 0 0 0 0 0
376 table[ 23] = 0xA0; // U_EMRSETCOLORADJUSTMENT 1 0 1 0 0 0 0 0
377 table[ 24] = 0x20; // U_EMRSETTEXTCOLOR 0 0 1 0 0 0 0 0
378 table[ 25] = 0x20; // U_EMRSETBKCOLOR 0 0 1 0 0 0 0 0
379 table[ 26] = 0xA0; // U_EMROFFSETCLIPRGN 1 0 1 0 0 0 0 0
380 table[ 27] = 0x89; // U_EMRMOVETOEX 1 0 0 0 1 0 0 1
381 table[ 28] = 0xA0; // U_EMRSETMETARGN 1 0 1 0 0 0 0 0
382 table[ 29] = 0xA0; // U_EMREXCLUDECLIPRECT 1 0 1 0 0 0 0 0
383 table[ 30] = 0xA0; // U_EMRINTERSECTCLIPRECT 1 0 1 0 0 0 0 0
384 table[ 31] = 0xA0; // U_EMRSCALEVIEWPORTEXTEX 1 0 1 0 0 0 0 0
385 table[ 32] = 0xA0; // U_EMRSCALEWINDOWEXTEX 1 0 1 0 0 0 0 0
386 table[ 33] = 0xA0; // U_EMRSAVEDC 1 0 1 0 0 0 0 0
387 table[ 34] = 0xA0; // U_EMRRESTOREDC 1 0 1 0 0 0 0 0
388 table[ 35] = 0xA0; // U_EMRSETWORLDTRANSFORM 1 0 1 0 0 0 0 0
389 table[ 36] = 0xA0; // U_EMRMODIFYWORLDTRANSFORM 1 0 1 0 0 0 0 0
390 table[ 37] = 0x20; // U_EMRSELECTOBJECT 0 0 1 0 0 0 0 0
391 table[ 38] = 0x20; // U_EMRCREATEPEN 0 0 1 0 0 0 0 0
392 table[ 39] = 0x20; // U_EMRCREATEBRUSHINDIRECT 0 0 1 0 0 0 0 0
393 table[ 40] = 0x20; // U_EMRDELETEOBJECT 0 0 1 0 0 0 0 0
394 table[ 41] = 0x83; // U_EMRANGLEARC 1 0 0 0 0 0 1 1
395 table[ 42] = 0x87; // U_EMRELLIPSE 1 0 0 0 0 1 1 1
396 table[ 43] = 0x87; // U_EMRRECTANGLE 1 0 0 0 0 1 1 1
397 table[ 44] = 0x87; // U_EMRROUNDRECT 1 0 0 0 0 1 1 1
398 table[ 45] = 0x83; // U_EMRARC 1 0 0 0 0 0 1 1
399 table[ 46] = 0x87; // U_EMRCHORD 1 0 0 0 0 1 1 1
400 table[ 47] = 0x87; // U_EMRPIE 1 0 0 0 0 1 1 1
401 table[ 48] = 0xA0; // U_EMRSELECTPALETTE 1 0 1 0 0 0 0 0
402 table[ 49] = 0xA0; // U_EMRCREATEPALETTE 1 0 1 0 0 0 0 0
403 table[ 50] = 0xA0; // U_EMRSETPALETTEENTRIES 1 0 1 0 0 0 0 0
404 table[ 51] = 0xA0; // U_EMRRESIZEPALETTE 1 0 1 0 0 0 0 0
405 table[ 52] = 0xA0; // U_EMRREALIZEPALETTE 1 0 1 0 0 0 0 0
406 table[ 53] = 0x82; // U_EMREXTFLOODFILL 1 0 0 0 0 0 1 0
407 table[ 54] = 0x8B; // U_EMRLINETO 1 0 0 0 1 0 1 1
408 table[ 55] = 0x8B; // U_EMRARCTO 1 0 0 0 1 0 1 1
409 table[ 56] = 0x83; // U_EMRPOLYDRAW 1 0 0 0 0 0 1 1
410 table[ 57] = 0xA0; // U_EMRSETARCDIRECTION 1 0 1 0 0 0 0 0
411 table[ 58] = 0xA0; // U_EMRSETMITERLIMIT 1 0 1 0 0 0 0 0
412 table[ 59] = 0xE0; // U_EMRBEGINPATH 1 1 1 0 0 0 0 0
413 table[ 60] = 0x80; // U_EMRENDPATH 1 0 0 0 0 0 0 0
414 table[ 61] = 0x84; // U_EMRCLOSEFIGURE 1 0 0 0 0 1 0 0
415 table[ 62] = 0x94; // U_EMRFILLPATH 1 0 0 1 0 1 0 0
416 table[ 63] = 0x94; // U_EMRSTROKEANDFILLPATH 1 0 0 1 0 1 0 0
417 table[ 64] = 0x90; // U_EMRSTROKEPATH 1 0 0 1 0 0 0 0
418 table[ 65] = 0xA0; // U_EMRFLATTENPATH 1 0 1 0 0 0 0 0
419 table[ 66] = 0xA0; // U_EMRWIDENPATH 1 0 1 0 0 0 0 0
420 table[ 67] = 0x80; // U_EMRSELECTCLIPPATH 1 0 0 0 0 0 0 0 consumes the path, draws nothing
421 table[ 68] = 0xA0; // U_EMRABORTPATH 1 0 1 0 0 0 0 0
422 table[ 69] = 0xA0; // U_EMRUNDEF69 1 0 1 0 0 0 0 0
423 table[ 70] = 0x00; // U_EMRCOMMENT 0 0 0 0 0 0 0 0
424 table[ 71] = 0x82; // U_EMRFILLRGN 1 0 0 0 0 0 1 0
425 table[ 72] = 0x82; // U_EMRFRAMERGN 1 0 0 0 0 0 1 0
426 table[ 73] = 0x82; // U_EMRINVERTRGN 1 0 0 0 0 0 1 0
427 table[ 74] = 0x82; // U_EMRPAINTRGN 1 0 0 0 0 0 1 0
428 table[ 75] = 0xA0; // U_EMREXTSELECTCLIPRGN 1 0 1 0 0 0 0 0
429 table[ 76] = 0x82; // U_EMRBITBLT 1 0 0 0 0 0 1 0
430 table[ 77] = 0x82; // U_EMRSTRETCHBLT 1 0 0 0 0 0 1 0
431 table[ 78] = 0x82; // U_EMRMASKBLT 1 0 0 0 0 0 1 0
432 table[ 79] = 0x82; // U_EMRPLGBLT 1 0 0 0 0 0 1 0
433 table[ 80] = 0xA0; // U_EMRSETDIBITSTODEVICE 1 0 1 0 0 0 0 0
434 table[ 81] = 0xA0; // U_EMRSTRETCHDIBITS 1 0 1 0 0 0 0 0
435 table[ 82] = 0x20; // U_EMREXTCREATEFONTINDIRECTW 0 0 1 0 0 0 0 0
436 table[ 83] = 0x02; // U_EMREXTTEXTOUTA 0 0 0 0 0 0 1 0
437 table[ 84] = 0x02; // U_EMREXTTEXTOUTW 0 0 0 0 0 0 1 0
438 table[ 85] = 0x83; // U_EMRPOLYBEZIER16 1 0 0 0 0 0 1 1
439 table[ 86] = 0x83; // U_EMRPOLYGON16 1 0 0 0 0 0 1 1
440 table[ 87] = 0x83; // U_EMRPOLYLINE16 1 0 0 0 0 0 1 1
441 table[ 88] = 0x8B; // U_EMRPOLYBEZIERTO16 1 0 0 0 1 0 1 1
442 table[ 89] = 0x8B; // U_EMRPOLYLINETO16 1 0 0 0 1 0 1 1
443 table[ 90] = 0x83; // U_EMRPOLYPOLYLINE16 1 0 0 0 0 0 1 1
444 table[ 91] = 0x87; // U_EMRPOLYPOLYGON16 1 0 0 0 0 1 1 1
445 table[ 92] = 0x83; // U_EMRPOLYDRAW16 1 0 0 0 0 0 1 1
446 table[ 93] = 0x80; // U_EMRCREATEMONOBRUSH 1 0 0 0 0 0 0 0 Not selected yet, so no change in drawing conditions
447 table[ 94] = 0x80; // U_EMRCREATEDIBPATTERNBRUSHPT 1 0 0 0 0 0 0 0 "
448 table[ 95] = 0x00; // U_EMREXTCREATEPEN 0 0 0 0 0 0 0 0 "
449 table[ 96] = 0x02; // U_EMRPOLYTEXTOUTA 0 0 0 0 0 0 1 0
450 table[ 97] = 0x02; // U_EMRPOLYTEXTOUTW 0 0 0 0 0 0 1 0
451 table[ 98] = 0xA0; // U_EMRSETICMMODE 1 0 1 0 0 0 0 0
452 table[ 99] = 0xA0; // U_EMRCREATECOLORSPACE 1 0 1 0 0 0 0 0
453 table[100] = 0xA0; // U_EMRSETCOLORSPACE 1 0 1 0 0 0 0 0
454 table[101] = 0xA0; // U_EMRDELETECOLORSPACE 1 0 1 0 0 0 0 0
455 table[102] = 0xA0; // U_EMRGLSRECORD 1 0 1 0 0 0 0 0
456 table[103] = 0xA0; // U_EMRGLSBOUNDEDRECORD 1 0 1 0 0 0 0 0
457 table[104] = 0xA0; // U_EMRPIXELFORMAT 1 0 1 0 0 0 0 0
458 table[105] = 0xA0; // U_EMRDRAWESCAPE 1 0 1 0 0 0 0 0
459 table[106] = 0xA0; // U_EMREXTESCAPE 1 0 1 0 0 0 0 0
460 table[107] = 0xA0; // U_EMRUNDEF107 1 0 1 0 0 0 0 0
461 table[108] = 0x02; // U_EMRSMALLTEXTOUT 0 0 0 0 0 0 1 0
462 table[109] = 0xA0; // U_EMRFORCEUFIMAPPING 1 0 1 0 0 0 0 0
463 table[110] = 0xA0; // U_EMRNAMEDESCAPE 1 0 1 0 0 0 0 0
464 table[111] = 0xA0; // U_EMRCOLORCORRECTPALETTE 1 0 1 0 0 0 0 0
465 table[112] = 0xA0; // U_EMRSETICMPROFILEA 1 0 1 0 0 0 0 0
466 table[113] = 0xA0; // U_EMRSETICMPROFILEW 1 0 1 0 0 0 0 0
467 table[114] = 0x82; // U_EMRALPHABLEND 1 0 0 0 0 0 1 0
468 table[115] = 0xA0; // U_EMRSETLAYOUT 1 0 1 0 0 0 0 0
469 table[116] = 0x82; // U_EMRTRANSPARENTBLT 1 0 0 0 0 0 1 0
470 table[117] = 0xA0; // U_EMRUNDEF117 1 0 1 0 0 0 0 0
471 table[118] = 0x82; // U_EMRGRADIENTFILL 1 0 1 0 0 0 1 0
472 table[119] = 0xA0; // U_EMRSETLINKEDUFIS 1 0 1 0 0 0 0 0
473 table[120] = 0x20; // U_EMRSETTEXTJUSTIFICATION 0 0 1 0 0 0 0 0
474 table[121] = 0xA0; // U_EMRCOLORMATCHTOTARGETW 1 0 1 0 0 0 0 0
475 table[122] = 0xA0; // U_EMRCREATECOLORSPACEW 1 0 1 0 0 0 0 0
476 }
477 result = table[type];
478 }
479 return(result);
480 }
481
482 /**
483 \brief Derive from bounding rect, start and end radials, for arc, chord, or pie, the center, start, and end points, and the bounding rectangle.
484
485 \return 0 on success, other values on errors.
486 \param rclBox bounding rectangle
487 \param ArcStart start of arc
488 \param ArcEnd end of arc
489 \param f1 1 if rotation angle >= 180, else 0
490 \param f2 Rotation direction, 1 if counter clockwise, else 0
491 \param center Center coordinates
492 \param start Start coordinates (point on the ellipse defined by rect)
493 \param end End coordinates (point on the ellipse defined by rect)
494 \param size W,H of the x,y axes of the bounding rectangle.
495 */
emr_arc_points_common(PU_RECTL rclBox,PU_POINTL ArcStart,PU_POINTL ArcEnd,int * f1,int f2,PU_PAIRF center,PU_PAIRF start,PU_PAIRF end,PU_PAIRF size)496 int emr_arc_points_common(
497 PU_RECTL rclBox,
498 PU_POINTL ArcStart,
499 PU_POINTL ArcEnd,
500 int *f1,
501 int f2,
502 PU_PAIRF center,
503 PU_PAIRF start,
504 PU_PAIRF end,
505 PU_PAIRF size
506 ){
507 U_PAIRF estart; // EMF start position, defines a radial
508 U_PAIRF eend; // EMF end position, defines a radial
509 U_PAIRF vec_estart; // define a unit vector from the center to estart
510 U_PAIRF vec_eend; // define a unit vector from the center to eend
511 U_PAIRF radii; // x,y radii of ellipse
512 U_PAIRF ratio; // intermediate value
513 float scale, cross;
514 center->x = ((float)(rclBox->left + rclBox->right ))/2.0;
515 center->y = ((float)(rclBox->top + rclBox->bottom))/2.0;
516 size->x = (float)(rclBox->right - rclBox->left );
517 size->y = (float)(rclBox->bottom - rclBox->top );
518 estart.x = (float)(ArcStart->x);
519 estart.y = (float)(ArcStart->y);
520 eend.x = (float)(ArcEnd->x);
521 eend.y = (float)(ArcEnd->y);
522 radii.x = size->x/2.0;
523 radii.y = size->y/2.0;
524
525 vec_estart.x = (estart.x - center->x); // initial vector, not unit length
526 vec_estart.y = (estart.y - center->y);
527 scale = sqrt(vec_estart.x*vec_estart.x + vec_estart.y*vec_estart.y);
528 if(!scale)return(1); // bogus record, has start at center
529 vec_estart.x /= scale; // now a unit vector
530 vec_estart.y /= scale;
531
532 vec_eend.x = (eend.x - center->x); // initial vector, not unit length
533 vec_eend.y = (eend.y - center->y);
534 scale = sqrt(vec_eend.x*vec_eend.x + vec_eend.y*vec_eend.y);
535 if(!scale)return(2); // bogus record, has end at center
536 vec_eend.x /= scale; // now a unit vector
537 vec_eend.y /= scale;
538
539
540 // Find the intersection of the vectors with the ellipse. With no loss of generality
541 // we can translate the ellipse to the origin, then we just need to find tu (t a factor, u the unit vector)
542 // that also satisfies (x/Rx)^2 + (y/Ry)^2 = 1. x is t*(ux), y is t*(uy), where ux,uy are the x,y components
543 // of the unit vector. Substituting gives:
544 // (t*(ux)/Rx)^2 + (t*(uy)/Ry)^2 = 1
545 // t^2 = 1/( (ux/Rx)^2 + (uy/Ry)^2 )
546 // t = sqrt(1/( (ux/Rx)^2 + (uy/Ry)^2 ))
547
548 ratio.x = vec_estart.x/radii.x;
549 ratio.y = vec_estart.y/radii.y;
550 ratio.x *= ratio.x; // we only use the square
551 ratio.y *= ratio.y;
552 scale = 1.0/sqrt(ratio.x + ratio.y);
553 start->x = center->x + scale * vec_estart.x;
554 start->y = center->y + scale * vec_estart.y;
555
556 ratio.x = vec_eend.x/radii.x;
557 ratio.y = vec_eend.y/radii.y;
558 ratio.x *= ratio.x; // we only use the square
559 ratio.y *= ratio.y;
560 scale = 1.0/sqrt(ratio.x + ratio.y);
561 end->x = center->x + scale * vec_eend.x;
562 end->y = center->y + scale * vec_eend.y;
563
564 //lastly figure out if the swept angle is >180 degrees or not, based on the direction of rotation
565 //and the two unit vectors.
566
567 cross = vec_estart.x * vec_eend.y - vec_estart.y * vec_eend.x;
568 if(!f2){ // counter clockwise rotation
569 if(cross >=0){ *f1 = 1; }
570 else { *f1 = 0; }
571 }
572 else {
573 if(cross >=0){ *f1 = 0; }
574 else { *f1 = 1; }
575 }
576
577
578 return(0);
579 }
580
581 /**
582 \brief Derive from an EMF arc, chord, or pie the center, start, and end points, and the bounding rectangle.
583
584 \return 0 on success, other values on errors.
585 \param record U_EMRPIE, U_EMRCHORD, or _EMRARC record
586 \param f1 1 if rotation angle >= 180, else 0
587 \param f2 Rotation direction, 1 if counter clockwise, else 0
588 \param center Center coordinates
589 \param start Start coordinates (point on the ellipse defined by rect)
590 \param end End coordinates (point on the ellipse defined by rect)
591 \param size W,H of the x,y axes of the bounding rectangle.
592 */
emr_arc_points(PU_ENHMETARECORD record,int * f1,int f2,PU_PAIRF center,PU_PAIRF start,PU_PAIRF end,PU_PAIRF size)593 int emr_arc_points(
594 PU_ENHMETARECORD record,
595 int *f1,
596 int f2,
597 PU_PAIRF center,
598 PU_PAIRF start,
599 PU_PAIRF end,
600 PU_PAIRF size
601 ){
602 PU_EMRARC pEmr = (PU_EMRARC) (record);
603 return emr_arc_points_common(&(pEmr->rclBox), &(pEmr->ptlStart), &(pEmr->ptlEnd), f1, f2, center, start, end, size );
604 }
605
606 /**
607 \brief Convert a U_RGBA 32 bit pixmap to one of many different types of DIB pixmaps.
608
609 Conversions to formats using color tables assume that the color table can hold every color
610 in the input image. If that assumption is false then the conversion will fail. Conversion
611 from 8 bit color to N bit colors (N<8) do so by shifting the appropriate number of bits.
612
613 \return 0 on success, other values on errors.
614 \param px DIB pixel array
615 \param cbPx DIB pixel array size in bytes
616 \param ct DIB color table
617 \param numCt DIB color table number of entries
618 \param rgba_px U_RGBA pixel array (32 bits)
619 \param w Width of pixel array
620 \param h Height of pixel array
621 \param stride Row stride of input pixel array in bytes
622 \param colortype DIB BitCount Enumeration
623 \param use_ct If true use color table (only for 1-16 bit DIBs).
624 \param invert If DIB rows are in opposite order from RGBA rows
625 */
RGBA_to_DIB(char ** px,uint32_t * cbPx,PU_RGBQUAD * ct,int * numCt,const char * rgba_px,int w,int h,int stride,uint32_t colortype,int use_ct,int invert)626 int RGBA_to_DIB(
627 char **px,
628 uint32_t *cbPx,
629 PU_RGBQUAD *ct,
630 int *numCt,
631 const char *rgba_px,
632 int w,
633 int h,
634 int stride,
635 uint32_t colortype,
636 int use_ct,
637 int invert
638 ){
639 int bs;
640 int pad;
641 int i,j,k;
642 int istart, iend, iinc;
643 uint8_t r,g,b,a,tmp8;
644 char *pxptr;
645 const char *rptr;
646 int found;
647 int usedbytes;
648 U_RGBQUAD color;
649 PU_RGBQUAD lct;
650 int32_t index;
651
652 *px=NULL;
653 *ct=NULL;
654 *numCt=0;
655 *cbPx=0;
656 // sanity checking
657 if(!w || !h || !stride || !colortype || !rgba_px)return(1);
658 if(use_ct && colortype >= U_BCBM_COLOR16)return(2); //color tables not used above 16 bit pixels
659 if(!use_ct && colortype < U_BCBM_COLOR16)return(3); //color tables mandatory for < 16 bit
660
661 bs = colortype/8;
662 if(bs<1){
663 usedbytes = (w*colortype + 7)/8; // width of line in fully and partially occupied bytes
664 }
665 else {
666 usedbytes = w*bs;
667 }
668 pad = UP4(usedbytes) - usedbytes; // DIB rows must be aligned on 4 byte boundaries, they are padded at the end to accomplish this.;
669 *cbPx = h * (usedbytes + pad); // Rows must start on a 4 byte boundary!
670 *px = (char *) malloc(*cbPx);
671 if(!px)return(4);
672 if(use_ct){
673 *numCt = 1<< colortype;
674 if(*numCt >w*h)*numCt=w*h;
675 lct = (PU_RGBQUAD) malloc(*numCt * sizeof(U_RGBQUAD));
676 if(!lct)return(5);
677 *ct = lct;
678 }
679
680 if(invert){
681 istart = h-1;
682 iend = -1;
683 iinc = -1;
684 }
685 else {
686 istart = 0;
687 iend = h;
688 iinc = 1;
689 }
690
691 found = 0;
692 tmp8 = 0;
693 pxptr = *px;
694 for(i=istart; i!=iend; i+=iinc){
695 rptr= rgba_px + i*stride;
696 for(j=0; j<w; j++){
697 r = *rptr++;
698 g = *rptr++;
699 b = *rptr++;
700 a = *rptr++;
701 if(use_ct){
702 color = U_BGRA(r,g,b,a); // color has order in memory: b,g,r,a, same as EMF+ ARGB
703 index = -1;
704 for(lct = *ct, k=0; k<found; k++,lct++){ // Is this color in the table (VERY inefficient if there are a lot of colors!!!)
705 if(*(uint32_t *)lct != *(uint32_t *) &color)continue;
706 index =k;
707 break;
708 }
709 if(index==-1){ // add a color
710 found++;
711 if(found > *numCt){ // More colors found than are supported by the color table
712 free(*ct);
713 free(*px);
714 *numCt=0;
715 *cbPx=0;
716 return(6);
717 }
718 index = found - 1;
719 *lct = color;
720 }
721 switch(colortype){
722 case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries
723 tmp8 = tmp8 >> 1; // This seems wrong, as it fills from the top of each byte. But it works.
724 tmp8 |= index << 7;
725 if(!((j+1) % 8)){
726 *pxptr++ = tmp8;
727 tmp8 = 0;
728 }
729 break;
730 case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries
731 tmp8 = tmp8 << 4;
732 tmp8 |= index;
733 if(!((j+1) % 2)){
734 *pxptr++ = tmp8;
735 tmp8 = 0;
736 }
737 break;
738 case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries
739 tmp8 = index;
740 *pxptr++ = tmp8;
741 break;
742 case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods))
743 case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE.
744 case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD.
745 case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ?
746 default:
747 return(7); // This should not be possible, but might happen with memory corruption
748 }
749 }
750 else {
751 switch(colortype){
752 case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods))
753 b /= 8; g /= 8; r /= 8;
754 // Do it in this way so that the bytes are always stored Little Endian
755 tmp8 = b;
756 tmp8 |= g<<5; // least significant 3 bits of green
757 *pxptr++ = tmp8;
758 tmp8 = g>>3; // most significant 2 bits of green (there are only 5 bits of data)
759 tmp8 |= r<<2;
760 *pxptr++ = tmp8;
761 break;
762 case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE.
763 *pxptr++ = b;
764 *pxptr++ = g;
765 *pxptr++ = r;
766 break;
767 case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD.
768 *pxptr++ = b;
769 *pxptr++ = g;
770 *pxptr++ = r;
771 *pxptr++ = a;
772 break;
773 case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries
774 case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries
775 case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries
776 case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ?
777 default:
778 return(7); // This should not be possible, but might happen with memory corruption
779 }
780 }
781 }
782 if( use_ct && colortype == U_BCBM_MONOCHROME && (j % 8) ){
783 *pxptr++ = tmp8; // Write last few indices
784 tmp8 = 0;
785 }
786 if( use_ct && colortype == U_BCBM_COLOR4 && (j % 2) ){
787 *pxptr++ = tmp8; // Write last few indices
788 tmp8 = 0;
789 }
790 if(pad){
791 memset(pxptr,0,pad); // not strictly necessary, but set all bytes so that we can find important unset ones with valgrind
792 pxptr += pad;
793 }
794 }
795 return(0);
796 }
797
798 /**
799 \brief Get the actual number of colors in the color table from the BitMapInfoHeader.
800 \return Number of entries in the color table.
801 \param Bmih char * pointer to the U_BITMAPINFOHEADER
802
803 BitmapInfoHeader may list 0 for some types which implies the maximum value.
804 If the image is big enough, that is set by the bit count, as in 256 for an 8
805 bit image.
806 If the image is smaller it is set by width * height.
807 Note, this may be called by WMF code, so it is not safe to assume the data is aligned.
808 */
get_real_color_count(const char * Bmih)809 int get_real_color_count(
810 const char *Bmih
811 ){
812 int Colors, BitCount, Width, Height;
813 uint32_t utmp4;
814 uint16_t utmp2;
815 int32_t tmp4;
816 char *cBmih = (char *) Bmih;
817 memcpy(&utmp4, cBmih + offsetof(U_BITMAPINFOHEADER,biClrUsed), 4); Colors = utmp4;
818 memcpy(&utmp2, cBmih + offsetof(U_BITMAPINFOHEADER,biBitCount), 2); BitCount = utmp2;
819 memcpy(&tmp4, cBmih + offsetof(U_BITMAPINFOHEADER,biWidth), 4); Width = tmp4;
820 memcpy(&tmp4, cBmih + offsetof(U_BITMAPINFOHEADER,biHeight), 4); Height = tmp4;
821 return(get_real_color_icount(Colors, BitCount, Width, Height));
822 }
823
824 /**
825 \brief Get the actual number of colors in the color table from the ClrUsed, BitCount, Width, and Height.
826 \return Number of entries in the color table.
827 \param Colors Number of colors in the table.
828 \param BitCount BitCount Enumeration
829 \param Width bitmap width
830 \param Height bitmap height
831 */
get_real_color_icount(int Colors,int BitCount,int Width,int Height)832 int get_real_color_icount(
833 int Colors,
834 int BitCount,
835 int Width,
836 int Height
837 ){
838 int area = Width * Height;
839 if(area < 0){ area = -area; } /* Height might be negative */
840 if(Colors == 0){
841 if( BitCount == U_BCBM_MONOCHROME){ Colors = 2; }
842 else if(BitCount == U_BCBM_COLOR4 ){ Colors = 16; }
843 else if(BitCount == U_BCBM_COLOR8 ){ Colors = 256; }
844 if(Colors > area){ Colors = area; }
845 }
846 return(Colors);
847 }
848
849
850 /**
851 \brief Get the DIB parameters from the BMI of the record for use by DBI_to_RGBA()
852
853 \return BI_Compression Enumeration. For anything other than U_BI_RGB values other than px may not be valid.
854 \param record pointer to EMR record that has a U_BITMAPINFO and bitmap
855 \param offBitsSrc Offset to the bitmap
856 \param offBmiSrc Offset to the U_BITMAPINFO
857 \param px pointer to DIB pixel array in pEmr
858 \param ct pointer to DIB color table in pEmr
859 \param numCt DIB color table number of entries, for PNG or JPG returns the number of bytes in the image
860 \param width Width of pixel array
861 \param height Height of pixel array (always returned as a positive number)
862 \param colortype DIB BitCount Enumeration
863 \param invert If DIB rows are in opposite order from RGBA rows
864 */
get_DIB_params(const char * record,uint32_t offBitsSrc,uint32_t offBmiSrc,const char ** px,const U_RGBQUAD ** ct,uint32_t * numCt,uint32_t * width,uint32_t * height,uint32_t * colortype,uint32_t * invert)865 int get_DIB_params(
866 const char *record,
867 uint32_t offBitsSrc,
868 uint32_t offBmiSrc,
869 const char **px,
870 const U_RGBQUAD **ct,
871 uint32_t *numCt,
872 uint32_t *width,
873 uint32_t *height,
874 uint32_t *colortype,
875 uint32_t *invert
876 ){
877 uint32_t bic;
878 PU_BITMAPINFO Bmi = (PU_BITMAPINFO)(record + offBmiSrc);
879 PU_BITMAPINFOHEADER Bmih = &(Bmi->bmiHeader);
880 /* if biCompression is not U_BI_RGB some or all of the following might not hold real values */
881 bic = Bmih->biCompression;
882 *width = Bmih->biWidth;
883 *colortype = Bmih->biBitCount;
884 if(Bmih->biHeight < 0){
885 *height = -Bmih->biHeight;
886 *invert = 1;
887 }
888 else {
889 *height = Bmih->biHeight;
890 *invert = 0;
891 }
892 if(bic == U_BI_RGB){
893 *numCt = get_real_color_count((const char *) Bmih);
894 if( numCt){ *ct = (PU_RGBQUAD) ((char *)Bmi + sizeof(U_BITMAPINFOHEADER)); }
895 else { *ct = NULL; }
896 }
897 else if(bic == U_BI_BITFIELDS){ /* to date only encountered once, for 32 bit, from PPT*/
898 *numCt = 0;
899 *ct = NULL;
900 bic = U_BI_RGB; /* there seems to be no difference, at least for the 32 bit images */
901 }
902 else {
903 *numCt = Bmih->biSizeImage;
904 *ct = NULL;
905 }
906 *px = record + offBitsSrc;
907 return(bic);
908 }
909
910 /**
911 \brief Convert one of many different types of DIB pixmaps to an RGBA 32 bit pixmap.
912
913 \return 0 on success, other values on errors.
914 \param px DIB pixel array
915 \param ct DIB color table
916 \param numCt DIB color table number of entries
917 \param rgba_px U_RGBA pixel array (32 bits), created by this routine, caller must free.
918 \param w Width of pixel array in the record
919 \param h Height of pixel array in the record
920 \param colortype DIB BitCount Enumeration
921 \param use_ct Kept for symmetry with RGBA_to_DIB, should be set to numCt
922 \param invert If DIB rows are in opposite order from RGBA rows
923 */
DIB_to_RGBA(const char * px,const U_RGBQUAD * ct,int numCt,char ** rgba_px,int w,int h,uint32_t colortype,int use_ct,int invert)924 int DIB_to_RGBA(
925 const char *px,
926 const U_RGBQUAD *ct,
927 int numCt,
928 char **rgba_px,
929 int w,
930 int h,
931 uint32_t colortype,
932 int use_ct,
933 int invert
934 ){
935 uint32_t cbRgba_px;
936 int stride;
937 int bs;
938 int pad;
939 int i,j;
940 int istart, iend, iinc;
941 uint8_t r,g,b,a,tmp8;
942 const char *pxptr;
943 char *rptr;
944 int usedbytes;
945 U_RGBQUAD color;
946 int32_t index;
947
948 // sanity checking
949 if(!w || !h || !colortype || !px)return(1);
950 if(use_ct && colortype >= U_BCBM_COLOR16)return(2); //color tables not used above 16 bit pixels
951 if(!use_ct && colortype < U_BCBM_COLOR16)return(3); //color tables mandatory for < 16 bit
952 if(use_ct && !numCt)return(4); //color table not adequately described
953
954 stride = w * 4;
955 cbRgba_px = stride * h;
956 bs = colortype/8;
957 if(bs<1){
958 usedbytes = (w*colortype + 7)/8; // width of line in fully and partially occupied bytes
959 }
960 else {
961 usedbytes = w*bs;
962 }
963 pad = UP4(usedbytes) - usedbytes; // DIB rows must be aligned on 4 byte boundaries, they are padded at the end to accomplish this.;
964 *rgba_px = (char *) malloc(cbRgba_px);
965 if(!rgba_px)return(4);
966
967 if(invert){
968 istart = h-1;
969 iend = -1;
970 iinc = -1;
971 }
972 else {
973 istart = 0;
974 iend = h;
975 iinc = 1;
976 }
977
978 pxptr = px;
979 tmp8 = 0; // silences a compiler warning, tmp8 always sets when j=0, so never used uninitialized
980 for(i=istart; i!=iend; i+=iinc){
981 rptr= *rgba_px + i*stride;
982 for(j=0; j<w; j++){
983 if(use_ct){
984 switch(colortype){
985 case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries
986 if(!(j % 8)){ tmp8 = *pxptr++; }
987 index = 0x80 & tmp8; // This seems wrong, as lowest position is top bit, but it works.
988 index = index >> 7;
989 tmp8 = tmp8 << 1;
990 break;
991 case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries
992 if(!(j % 2)){ tmp8 = *pxptr++; }
993 index = 0xF0 & tmp8;
994 index = index >> 4;
995 tmp8 = tmp8 << 4;
996 break;
997 case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries
998 index = (uint8_t) *pxptr++;;
999 break;
1000 case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods))
1001 case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE.
1002 case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD.
1003 case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ?
1004 default:
1005 return(7); // This should not be possible, but might happen with memory corruption
1006 }
1007 color = ct[index];
1008 b = U_BGRAGetB(color);
1009 g = U_BGRAGetG(color);
1010 r = U_BGRAGetR(color);
1011 a = U_BGRAGetA(color);
1012 }
1013 else {
1014 switch(colortype){
1015 case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods))
1016 // Do it in this way because the bytes are always stored Little Endian
1017 tmp8 = *pxptr++;
1018 b = (0x1F & tmp8) <<3; // 5 bits of b into the top 5 of 8
1019 g = tmp8 >> 5; // least significant 3 bits of green
1020 tmp8 = *pxptr++;
1021 r = (0x7C & tmp8) << 1; // 5 bits of r into the top 5 of 8
1022 g |= (0x3 & tmp8) << 3; // most significant 2 bits of green (there are only 5 bits of data)
1023 g = g << 3; // restore intensity (have lost 3 bits of accuracy)
1024 a = 0;
1025 break;
1026 case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE.
1027 b = *pxptr++;
1028 g = *pxptr++;
1029 r = *pxptr++;
1030 a = 0;
1031 break;
1032 case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD.
1033 b = *pxptr++;
1034 g = *pxptr++;
1035 r = *pxptr++;
1036 a = *pxptr++;
1037 break;
1038 case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries
1039 case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries
1040 case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries
1041 case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ?
1042 default:
1043 return(7); // This should not be possible, but might happen with memory corruption
1044 }
1045 }
1046 *rptr++ = r;
1047 *rptr++ = g;
1048 *rptr++ = b;
1049 *rptr++ = a;
1050 }
1051 for(j=0; j<pad; j++){ pxptr++; } // DIB rows are all 4 byte aligned
1052 }
1053 return(0);
1054 }
1055
1056 /**
1057 \brief Extract a subset of an RGBA bitmap array.
1058 Frees the incoming bitmap array IF a subset is extracted, otherwise it is left alone.
1059 If the entire array is extracted it just returns the incoming pointer.
1060 If the subset requested is partially outside of the bitmap the region is clipped to the
1061 bitmap boundaries and extracted. This seems to be a (very) grey area in EMF files, and
1062 even different Microsoft applications do not always do the same thing. For instance,
1063 XP Preview gives some different images for EMR_BITBLT records than does the "import image"
1064 (but not unpacked) view in PowerPoint. Since all of these states are probably best viewed
1065 as undefined or errors we can only try to do something reasonable and not blow up when
1066 encountering one.
1067
1068 \return Pointer to the sub array on success, NULL otherwise.
1069 \param rgba_px U_RGBA pixel array (32 bits), created by this routine, caller must free.
1070 \param w Width of pixel array in the record
1071 \param h Height of pixel array in the record
1072 \param sl start left position in the pixel array in the record to start extracting
1073 \param st start top position in the pixel array in the record to start extracting
1074 \param eew Width of pixel array to extract
1075 \param eeh Height of pixel array to extract
1076 */
RGBA_to_RGBA(char * rgba_px,int w,int h,int sl,int st,int * eew,int * eeh)1077 char *RGBA_to_RGBA(
1078 char *rgba_px,
1079 int w,
1080 int h,
1081 int sl,
1082 int st,
1083 int *eew,
1084 int *eeh
1085 ){
1086 int i;
1087 char *sub;
1088 char *sptr;
1089 int ew = *eew;
1090 int eh = *eeh;
1091
1092 // sanity checking
1093 if(w<=0 || h<=0 || ew<=0 || eh<=0 || !rgba_px)return(NULL);
1094
1095 if(sl>w || st >h)return(NULL); // This is hopeless, the start point is outside of the array.
1096 if(sl<0){
1097 if(sl+ew<=0)return(NULL); // This is hopeless, the start point is outside of the array.
1098 ew += sl;
1099 sl = 0;
1100 }
1101 if(st<0){
1102 if(st+eh<=0)return(NULL); // This is hopeless, the start point is outside of the array.
1103 eh += st;
1104 st = 0;
1105 }
1106 if(sl+ew > w)ew=w-sl;
1107 if(st+eh > h)eh=h-st;
1108 if(!sl && !st && (ew == w) && (eh == h)){
1109 sub = rgba_px;
1110 }
1111 else {
1112 sptr = sub = malloc(ew*eh*4);
1113 if(!sub)return(NULL);
1114 for(i=st; i<st+eh; i++){
1115 memcpy(sptr,rgba_px + i*w*4 + sl*4,4*ew);
1116 sptr += 4*ew;
1117 }
1118 free(rgba_px);
1119 }
1120 *eeh = eh;
1121 *eew = ew;
1122 return(sub);
1123 }
1124
1125
1126 /* **********************************************************************************************
1127 These functions are for setting up, appending to, and then tearing down an EMF structure, including
1128 writing the final data structure out to a file.
1129 *********************************************************************************************** */
1130
1131 /**
1132 \brief Duplicate an EMR record.
1133 \param emr record to duplicate
1134 */
emr_dup(const char * emr)1135 char *emr_dup(
1136 const char *emr
1137 ){
1138 char *dup;
1139 int irecsize;
1140
1141 if(!emr)return(NULL);
1142 irecsize = ((PU_EMR)emr)->nSize;
1143 dup=malloc(irecsize);
1144 if(dup){ memcpy(dup,emr,irecsize); }
1145 return(dup);
1146 }
1147
1148
1149 /**
1150 \brief Start constructing an emf in memory. Supply the file name and initial size.
1151 \return 0 for success, >=0 for failure.
1152 \param name EMF filename (will be opened)
1153 \param initsize Initialize EMF in memory to hold this many bytes
1154 \param chunksize When needed increase EMF in memory by this number of bytes
1155 \param et EMF in memory
1156
1157
1158 */
emf_start(const char * name,const uint32_t initsize,const uint32_t chunksize,EMFTRACK ** et)1159 int emf_start(
1160 const char *name,
1161 const uint32_t initsize,
1162 const uint32_t chunksize,
1163 EMFTRACK **et
1164 ){
1165 FILE *fp;
1166 EMFTRACK *etl=NULL;
1167
1168 if(initsize < 1)return(1);
1169 if(chunksize < 1)return(2);
1170 if(!name)return(3);
1171 etl = (EMFTRACK *) malloc(sizeof(EMFTRACK));
1172 if(!etl)return(4);
1173 etl->buf = malloc(initsize); // no need to zero the memory
1174 if(!etl->buf){
1175 free(etl);
1176 return(5);
1177 }
1178 fp=emf_fopen(name,U_WRITE);
1179 if(!fp){
1180 free(etl->buf);
1181 free(etl);
1182 return(6);
1183 }
1184 etl->fp = fp;
1185 etl->allocated = initsize;
1186 etl->used = 0;
1187 etl->records = 0;
1188 etl->PalEntries = 0;
1189 etl->chunk = chunksize;
1190 *et=etl;
1191 return(0);
1192 }
1193
1194 /**
1195 \brief Finalize the emf in memory and write it to the file.
1196 \return 0 on success, >=1 on failure
1197 \param et EMF in memory
1198 \param eht EMF handle table (peak handle number needed)
1199 */
emf_finish(EMFTRACK * et,EMFHANDLES * eht)1200 int emf_finish(
1201 EMFTRACK *et,
1202 EMFHANDLES *eht
1203 ){
1204 U_EMRHEADER *record;
1205
1206 if(!et->fp)return(1); // This could happen if something stomps on memory, otherwise should be caught in emf_start
1207
1208 // Set the header fields which were unknown up until this point
1209
1210 record = (U_EMRHEADER *)et->buf;
1211 record->nBytes = et->used;
1212 record->nRecords = et->records;
1213 record->nHandles = eht->peak + 1;
1214 record->nPalEntries = et->PalEntries;
1215
1216 #if U_BYTE_SWAP
1217 //This is a Big Endian machine, EMF data must be Little Endian
1218 U_emf_endian(et->buf,et->used,1);
1219 #endif
1220
1221 if(1 != fwrite(et->buf,et->used,1,et->fp))return(2);
1222 (void) fclose(et->fp);
1223 et->fp=NULL;
1224 return(0);
1225 }
1226
1227 /**
1228 \brief Release memory for an emf structure in memory. Call this after emf_finish().
1229 \return 0 on success, >=1 on failure
1230 \param et EMF in memory
1231 */
emf_free(EMFTRACK ** et)1232 int emf_free(
1233 EMFTRACK **et
1234 ){
1235 EMFTRACK *etl;
1236 if(!et)return(1);
1237 etl=*et;
1238 if(!etl)return(2);
1239 free(etl->buf);
1240 free(etl);
1241 *et=NULL;
1242 return(0);
1243 }
1244
1245 /**
1246 \brief wrapper for fopen, works on any platform
1247 \return 0 on success, >=1 on failure
1248 \param filename file to open (either ASCII or UTF-8)
1249 \param mode U_READ or U_WRITE (these map to "rb" and "wb")
1250 */
emf_fopen(const char * filename,const int mode)1251 FILE *emf_fopen(
1252 const char *filename,
1253 const int mode
1254 ){
1255 FILE *fp = NULL;
1256 #ifdef WIN32
1257 uint16_t *fn16;
1258 uint16_t *md16;
1259 if(mode == U_READ){ md16 = U_Utf8ToUtf16le("rb", 0, NULL); }
1260 else { md16 = U_Utf8ToUtf16le("wb", 0, NULL); }
1261 fn16 = U_Utf8ToUtf16le(filename, 0, NULL);
1262 fp = _wfopen(fn16,md16);
1263 free(fn16);
1264 free(md16);
1265 #else
1266 if(mode == U_READ){ fp = fopen(filename,"rb"); }
1267 else { fp = fopen(filename,"wb"); }
1268 #endif
1269 return(fp);
1270 }
1271
1272 /**
1273 \brief Retrieve contents of an EMF file by name.
1274 \return 0 on success, >=1 on failure
1275 \param filename Name of file to open, including the path
1276 \param contents Contents of the file. Buffer must be free()'d by caller.
1277 \param length Number of bytes in Contents
1278 */
emf_readdata(const char * filename,char ** contents,size_t * length)1279 int emf_readdata(
1280 const char *filename,
1281 char **contents,
1282 size_t *length
1283 ){
1284 FILE *fp;
1285 int status=0;
1286
1287 *contents=NULL;
1288 fp=emf_fopen(filename,U_READ);
1289 if(!fp){ status = 1; }
1290 else {
1291 // read the entire file into memory
1292 fseek(fp, 0, SEEK_END); // move to end
1293 *length = ftell(fp);
1294 rewind(fp);
1295 *contents = (char *) malloc(*length);
1296 if(!*contents){
1297 status = 2;
1298 }
1299 else {
1300 size_t inbytes = fread(*contents,*length,1,fp);
1301 if(inbytes != 1){
1302 free(*contents);
1303 status = 3;
1304 }
1305 else {
1306 #if U_BYTE_SWAP
1307 //This is a Big Endian machine, EMF data is Little Endian
1308 U_emf_endian(*contents,*length,0); // LE to BE
1309 #endif
1310 }
1311 }
1312 fclose(fp);
1313 }
1314 return(status);
1315 }
1316
1317
1318 /**
1319 \brief Append an EMF record to an emf in memory. This may reallocate buf memory.
1320 \return 0 for success, >=1 for failure.
1321 \param rec Record to append to EMF in memory
1322 \param et EMF in memory
1323 \param freerec If true, free rec after append
1324 */
emf_append(U_ENHMETARECORD * rec,EMFTRACK * et,int freerec)1325 int emf_append(
1326 U_ENHMETARECORD *rec,
1327 EMFTRACK *et,
1328 int freerec
1329 ){
1330 size_t deficit;
1331
1332 #ifdef U_VALGRIND
1333 printf("\nbefore \n");
1334 printf(" probe %d\n",memprobe(rec, U_EMRSIZE(rec)));
1335 printf("after \n");
1336 #endif
1337 if(!rec)return(1);
1338 if(!et)return(2);
1339 if(rec->nSize + et->used > et->allocated){
1340 deficit = rec->nSize + et->used - et->allocated;
1341 if(deficit < et->chunk)deficit = et->chunk;
1342 et->allocated += deficit;
1343 et->buf = realloc(et->buf,et->allocated);
1344 if(!et->buf)return(3);
1345 }
1346 memcpy(et->buf + et->used, rec, rec->nSize);
1347 et->used += rec->nSize;
1348 et->records++;
1349 if(rec->iType == U_EMR_EOF){ et->PalEntries = ((U_EMREOF *)rec)->cbPalEntries; }
1350 if(freerec){ free(rec); }
1351 return(0);
1352 }
1353
1354 /**
1355 \brief Create a handle table. Entries filled with 0 are empty, entries >0 hold a handle.
1356 \return 0 for success, >=1 for failure.
1357 \param initsize Initialize with space for this number of handles
1358 \param chunksize When needed increase space by this number of handles
1359 \param eht EMF handle table
1360 */
emf_htable_create(uint32_t initsize,uint32_t chunksize,EMFHANDLES ** eht)1361 int emf_htable_create(
1362 uint32_t initsize,
1363 uint32_t chunksize,
1364 EMFHANDLES **eht
1365 ){
1366 EMFHANDLES *ehtl;
1367 unsigned int i;
1368
1369 if(initsize<1)return(1);
1370 if(chunksize<1)return(2);
1371 ehtl = (EMFHANDLES *) malloc(sizeof(EMFHANDLES));
1372 if(!ehtl)return(3);
1373 ehtl->table = malloc(initsize * sizeof(uint32_t));
1374 if(!ehtl->table){
1375 free(ehtl);
1376 return(4);
1377 }
1378 ehtl->stack = malloc(initsize * sizeof(uint32_t));
1379 if(!ehtl->stack){
1380 free(ehtl->table);
1381 free(ehtl);
1382 return(5);
1383 }
1384 memset(ehtl->table , 0, initsize * sizeof(uint32_t)); // zero all slots in the table
1385 for(i=1; i<initsize; i++){ehtl->stack[i]=i;} // preset the stack
1386 ehtl->allocated = initsize;
1387 ehtl->chunk = chunksize;
1388 ehtl->table[0] = 0; // This slot isn't actually ever used
1389 ehtl->stack[0] = 0; // This stack position isn't actually ever used
1390 ehtl->peak = 1;
1391 ehtl->sptr = 1;
1392 ehtl->top = 0;
1393 *eht = ehtl;
1394 return(0);
1395 }
1396
1397 /**
1398 \brief Delete an entry from the handle table. Move it back onto the stack. The specified slot is filled with a 0.
1399 \return 0 for success, >=1 for failure.
1400 \param ih handle
1401 \param eht EMF handle table
1402
1403 */
emf_htable_delete(uint32_t * ih,EMFHANDLES * eht)1404 int emf_htable_delete(
1405 uint32_t *ih,
1406 EMFHANDLES *eht
1407 ){
1408 if(!eht)return(1);
1409 if(!eht->table)return(2);
1410 if(!eht->stack)return(3);
1411 if(*ih < 1)return(4); // invalid handle
1412 if(!eht->table[*ih])return(5); // requested table position was not in use
1413 eht->table[*ih]=0; // remove handle from table
1414 while(eht->top>0 && !eht->table[eht->top]){ // adjust top
1415 eht->top--;
1416 }
1417 eht->sptr--; // adjust stack
1418 eht->stack[eht->sptr]=*ih; // place handle on stack
1419 *ih=0; // invalidate handle variable, so a second delete will of it is not possible
1420 return(0);
1421 }
1422
1423 /**
1424 \brief Returns the index of the first free slot.
1425 Call realloc() if needed. The slot is set to handle (indicates occupied) and the peak value is adjusted.
1426 \return 0 for success, >=1 for failure.
1427 \param ih handle
1428 \param eht EMF handle table
1429 */
emf_htable_insert(uint32_t * ih,EMFHANDLES * eht)1430 int emf_htable_insert(
1431 uint32_t *ih,
1432 EMFHANDLES *eht
1433 ){
1434 unsigned int i;
1435 size_t newsize;
1436
1437 if(!eht)return(1);
1438 if(!eht->table)return(2);
1439 if(!eht->stack)return(3);
1440 if(!ih)return(4);
1441 if(eht->sptr >= eht->allocated - 1){ // need to reallocate
1442 newsize=eht->allocated + eht->chunk;
1443 eht->table = realloc(eht->table,newsize * sizeof(uint32_t));
1444 if(!eht->table)return(5);
1445 memset(&eht->table[eht->allocated] , 0, eht->chunk * sizeof(uint32_t)); // zero all NEW slots in the table
1446
1447 eht->stack = realloc(eht->stack,newsize * sizeof(uint32_t));
1448 if(!eht->stack)return(6);
1449 for(i=eht->allocated; i<newsize;i++){ eht->stack[i] = i; } // init all NEW slots in the stack
1450 eht->allocated = newsize;
1451 }
1452 *ih = eht->stack[eht->sptr]; // handle that is inserted
1453 if(eht->table[*ih])return(7);
1454 eht->table[*ih] = *ih; // handle goes into preexisting (but zero) slot in table
1455 eht->stack[eht->sptr] = 0;
1456 if(*ih > eht->top){ eht->top = *ih; }
1457 if(eht->sptr > eht->peak){ eht->peak = eht->sptr; }
1458 eht->sptr++; // next available handle
1459 return(0);
1460 }
1461
1462 /**
1463 \brief Free all memory in an htable. Sets the pointer to NULL.
1464 \return 0 for success, >=1 for failure.
1465 \param eht EMF handle table
1466 */
emf_htable_free(EMFHANDLES ** eht)1467 int emf_htable_free(
1468 EMFHANDLES **eht
1469 ){
1470 EMFHANDLES *ehtl;
1471 if(!eht)return(1);
1472 ehtl = *eht;
1473 if(!ehtl)return(2);
1474 if(!ehtl->table)return(3);
1475 if(!ehtl->stack)return(4);
1476 free(ehtl->table);
1477 free(ehtl->stack);
1478 free(ehtl);
1479 *eht=NULL;
1480 return(0);
1481 }
1482
1483 /* **********************************************************************************************
1484 These functions create standard structures used in the EMR records.
1485 *********************************************************************************************** */
1486
1487
1488 /**
1489 \brief Set up fields for an EMR_HEADER from the physical device's width and height in mm and dots per millimeter.
1490 Typically this is something like 216,279,47.244 (Letter paper, 1200 DPI = 47.244 DPmm)
1491 \return 0 for success, >=1 for failure.
1492 \param xmm Device width in millimeters
1493 \param ymm Device height in millimeters
1494 \param dpmm Dots per millimeter
1495 \param szlDev Device size structure in pixels
1496 \param szlMm Device size structure in mm
1497 */
device_size(const int xmm,const int ymm,const float dpmm,U_SIZEL * szlDev,U_SIZEL * szlMm)1498 int device_size(
1499 const int xmm,
1500 const int ymm,
1501 const float dpmm,
1502 U_SIZEL *szlDev,
1503 U_SIZEL *szlMm
1504 ){
1505 if(xmm < 0 || ymm < 0 || dpmm < 0)return(1);
1506 szlDev->cx = U_ROUND((float) xmm * dpmm);
1507 szlDev->cy = U_ROUND((float) ymm * dpmm);;
1508 szlMm->cx = xmm;
1509 szlMm->cy = ymm;
1510 return(0);
1511 }
1512
1513 /**
1514 \brief Set up fields for an EMR_HEADER for drawing by physical size in mm and dots per millimeter.
1515 Technically rclBounds is supposed to be the extent of the drawing within the EMF, but libUEMF has no way
1516 of knowing this since it never actually draws anything. Instead this is set to the full drawing size.
1517 Coordinates are inclusive inclusive, so 297 -> 0,29699.
1518 \return 0 for success, >=1 for failure.
1519 \param xmm Drawing width in millimeters
1520 \param ymm Drawing height in millimeters
1521 \param dpmm Dots per millimeter
1522 \param rclBounds Drawing size structure in pixels
1523 \param rclFrame Drawing size structure in mm
1524 */
drawing_size(const int xmm,const int ymm,const float dpmm,U_RECTL * rclBounds,U_RECTL * rclFrame)1525 int drawing_size(
1526 const int xmm,
1527 const int ymm,
1528 const float dpmm,
1529 U_RECTL *rclBounds,
1530 U_RECTL *rclFrame
1531 ){
1532 if(xmm < 0 || ymm < 0 || dpmm < 0)return(1);
1533 rclBounds->left = 0;
1534 rclBounds->top = 0;
1535 rclBounds->right = U_ROUND((float) xmm * dpmm) - 1; // because coordinate system is 0,0 in upper left, N,M in lower right
1536 rclBounds->bottom = U_ROUND((float) ymm * dpmm) - 1;
1537 rclFrame->left = 0;
1538 rclFrame->top = 0;
1539 rclFrame->right = U_ROUND((float) xmm * 100.) - 1;
1540 rclFrame->bottom = U_ROUND((float) ymm * 100.) - 1;
1541 return(0);
1542 }
1543
1544 /**
1545 \brief Set a U_COLORREF value from separate R,G,B values.
1546 \param red Red component
1547 \param green Green component
1548 \param blue Blue component
1549
1550 */
colorref3_set(uint8_t red,uint8_t green,uint8_t blue)1551 U_COLORREF colorref3_set(
1552 uint8_t red,
1553 uint8_t green,
1554 uint8_t blue
1555 ){
1556 U_COLORREF cr = (U_COLORREF){red , green, blue, 0};
1557 return(cr);
1558 }
1559
1560 /**
1561 \brief Set a U_COLORREF value from separate R,G,B, and Reserved values.
1562 \param red Red component
1563 \param green Green component
1564 \param blue Blue component
1565 \param Reserved Reserved component
1566
1567 */
colorref4_set(uint8_t red,uint8_t green,uint8_t blue,uint8_t Reserved)1568 U_COLORREF colorref4_set(
1569 uint8_t red,
1570 uint8_t green,
1571 uint8_t blue,
1572 uint8_t Reserved
1573 ){
1574 U_COLORREF cr = (U_COLORREF){red , green, blue, Reserved};
1575 return(cr);
1576 }
1577
1578 /**
1579 \brief Set a U_RGBQUAD value from separate R,G,B, Reserved values.
1580 \param red Red component
1581 \param green Green component
1582 \param blue Blue component
1583 \param reserved Reserved component
1584
1585 */
rgbquad_set(uint8_t red,uint8_t green,uint8_t blue,uint8_t reserved)1586 U_RGBQUAD rgbquad_set(
1587 uint8_t red,
1588 uint8_t green,
1589 uint8_t blue,
1590 uint8_t reserved
1591 ){
1592 U_RGBQUAD cr = (U_RGBQUAD){blue , green, red, reserved};
1593 return(cr);
1594 }
1595
1596 /**
1597 \brief Set rect and rectl objects from Upper Left and Lower Right corner points.
1598 \param ul upper left corner of rectangle
1599 \param lr lower right corner of rectangle
1600 */
rectl_set(U_POINTL ul,U_POINTL lr)1601 U_RECTL rectl_set(
1602 U_POINTL ul,
1603 U_POINTL lr
1604 ){
1605 U_RECTL rct;
1606 rct.left = ul.x;
1607 rct.top = ul.y;
1608 rct.right = lr.x;
1609 rct.bottom = lr.y;
1610 return(rct);
1611 }
1612
1613 /**
1614 \brief Set rect and rectl objects from Upper Left and Lower Right corner points.
1615 \param array array of rectangles
1616 \param index array entry to fill, numbered from 0
1617 \param ul upper left corner of rectangle
1618 \param lr lower right corner of rectangle
1619 */
rectli_set(PU_RECTL array,int index,U_POINTL ul,U_POINTL lr)1620 void rectli_set(
1621 PU_RECTL array,
1622 int index,
1623 U_POINTL ul,
1624 U_POINTL lr
1625 ){
1626 PU_RECTL rct = &(array[index]);
1627 rct->left = ul.x;
1628 rct->top = ul.y;
1629 rct->right = lr.x;
1630 rct->bottom = lr.y;
1631 }
1632
1633 /**
1634 \brief Set sizel objects with X,Y values.
1635 \param x X coordinate
1636 \param y Y coordinate
1637 */
sizel_set(int32_t x,int32_t y)1638 U_SIZEL sizel_set(
1639 int32_t x,
1640 int32_t y
1641 ){
1642 U_SIZEL sz;
1643 sz.cx = x;
1644 sz.cy = y;
1645 return(sz);
1646 }
1647
1648 /**
1649 \brief Set pointl objects with X,Y values.
1650 \param x X coordinate
1651 \param y Y coordinate
1652 */
point32_set(int32_t x,int32_t y)1653 U_POINTL point32_set(
1654 int32_t x,
1655 int32_t y
1656 ){
1657 U_POINTL pt;
1658 pt.x = x;
1659 pt.y = y;
1660 return(pt);
1661 }
1662
1663 /**
1664 \brief Set point16 objects with 16 bit X,Y values.
1665 \param x X coordinate
1666 \param y Y coordinate
1667 */
point16_set(int16_t x,int16_t y)1668 U_POINT16 point16_set(
1669 int16_t x,
1670 int16_t y
1671 ){
1672 U_POINT16 pt;
1673 pt.x = x;
1674 pt.y = y;
1675 return(pt);
1676 }
1677
1678 /**
1679 \brief Find the bounding rectangle from a polyline of a given width.
1680 \param count number of points in the polyline
1681 \param pts the polyline
1682 \param width width of drawn line
1683
1684 */
findbounds(uint32_t count,PU_POINT pts,uint32_t width)1685 U_RECT findbounds(
1686 uint32_t count,
1687 PU_POINT pts,
1688 uint32_t width
1689 ){
1690 U_RECT rect={INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN };
1691 unsigned int i;
1692
1693 for(i=0; i<count;i++,pts++){
1694 if ( pts->x < rect.left ) rect.left = pts->x;
1695 if ( pts->x > rect.right ) rect.right = pts->x;
1696 if ( pts->y < rect.top ) rect.top = pts->y;
1697 if ( pts->y > rect.bottom ) rect.bottom = pts->y;
1698 }
1699 if(width > 0){
1700 rect.left -= width;
1701 rect.right += width;
1702 rect.top += width;
1703 rect.bottom -= width;
1704 }
1705 return(rect);
1706 }
1707
1708 /**
1709 \brief Find the bounding rectangle from a polyline of a given width.
1710 \param count number of points in the polyline
1711 \param pts the polyline
1712 \param width width of drawn line
1713
1714 */
findbounds16(uint32_t count,PU_POINT16 pts,uint32_t width)1715 U_RECT findbounds16(
1716 uint32_t count,
1717 PU_POINT16 pts,
1718 uint32_t width
1719 ){
1720 U_RECT rect={INT16_MAX, INT16_MAX, INT16_MIN, INT16_MIN };
1721 unsigned int i;
1722
1723 for(i=0; i<count;i++,pts++){
1724 if ( pts->x < rect.left ) rect.left = pts->x;
1725 if ( pts->x > rect.right ) rect.right = pts->x;
1726 if ( pts->y < rect.top ) rect.top = pts->y;
1727 if ( pts->y > rect.bottom ) rect.bottom = pts->y;
1728 }
1729 if(width > 0){
1730 rect.left -= width;
1731 rect.right += width;
1732 rect.top += width;
1733 rect.bottom -= width;
1734 }
1735 return(rect);
1736 }
1737 /**
1738 \brief Construct a U_LOGBRUSH structure.
1739 \return U_LOGBRUSH structure
1740 \param lbStyle LB_Style Enumeration
1741 \param lbColor Brush color
1742 \param lbHatch HatchStyle Enumertaion
1743 */
logbrush_set(uint32_t lbStyle,U_COLORREF lbColor,int32_t lbHatch)1744 U_LOGBRUSH logbrush_set(
1745 uint32_t lbStyle,
1746 U_COLORREF lbColor,
1747 int32_t lbHatch
1748 ){
1749 U_LOGBRUSH lb;
1750 lb.lbStyle = lbStyle;
1751 lb.lbColor = lbColor;
1752 lb.lbHatch = lbHatch;
1753 return(lb);
1754 }
1755
1756 /**
1757 \brief Construct a U_XFORM structure.
1758 \return U_XFORM structure
1759 \param eM11 Rotation Matrix element
1760 \param eM12 Rotation Matrix element
1761 \param eM21 Rotation Matrix element
1762 \param eM22 Rotation Matrix element
1763 \param eDx Translation element
1764 \param eDy Translation element
1765 */
xform_set(U_FLOAT eM11,U_FLOAT eM12,U_FLOAT eM21,U_FLOAT eM22,U_FLOAT eDx,U_FLOAT eDy)1766 U_XFORM xform_set(
1767 U_FLOAT eM11,
1768 U_FLOAT eM12,
1769 U_FLOAT eM21,
1770 U_FLOAT eM22,
1771 U_FLOAT eDx,
1772 U_FLOAT eDy
1773 ){
1774 U_XFORM xform;
1775 xform.eM11 = eM11;
1776 xform.eM12 = eM12;
1777 xform.eM21 = eM21;
1778 xform.eM22 = eM22;
1779 xform.eDx = eDx;
1780 xform.eDy = eDy;
1781 return(xform);
1782 }
1783
1784 /**
1785 \brief Construct a U_XFORM structure.
1786 \return U_XFORM structure
1787 \param scale Scale factor
1788 \param ratio Ratio of minor axis/major axis
1789 \param rot Rotation angle in degrees, positive is counter clockwise from the x axis.
1790 \param axisrot Angle in degrees defining the major axis before rotation, positive is counter clockwise from the x axis.
1791 \param eDx Translation element
1792 \param eDy Translation element
1793
1794 Operation is:
1795 1 Conformal map of points based on scale, axis rotation, and axis ratio,
1796 2. Apply rotation
1797 3. Apply offset
1798 */
xform_alt_set(U_FLOAT scale,U_FLOAT ratio,U_FLOAT rot,U_FLOAT axisrot,U_FLOAT eDx,U_FLOAT eDy)1799 U_XFORM xform_alt_set(
1800 U_FLOAT scale,
1801 U_FLOAT ratio,
1802 U_FLOAT rot,
1803 U_FLOAT axisrot,
1804 U_FLOAT eDx,
1805 U_FLOAT eDy
1806 ){
1807 U_XFORM xform;
1808 U_MAT2X2 mat1, mat2;
1809 // angles are in degrees, must be in radians
1810 rot *= (2.0 * U_PI)/360.0;
1811 axisrot *= -(2.0 * U_PI)/360.0;
1812 mat1.M11 = cos(rot); // set up the rotation matrix
1813 mat1.M12 = -sin(rot);
1814 mat1.M21 = sin(rot);
1815 mat1.M22 = cos(rot);
1816 if(ratio!=1.0){ // set scale/ellipticity matrix
1817 mat2.M11 = scale*( cos(axisrot)*cos(axisrot) + ratio*sin(axisrot)*sin(axisrot) );
1818 mat2.M12 = mat2.M21 = scale*( sin(axisrot)*cos(axisrot) * (1.0 - ratio) );
1819 mat2.M22 = scale*( sin(axisrot)*sin(axisrot) + ratio*cos(axisrot)*cos(axisrot) );
1820 }
1821 else { // when the ratio is 1.0 then the major axis angle is ignored and only scale matters
1822 mat2.M11 = scale;
1823 mat2.M12 = 0.0;
1824 mat2.M21 = 0.0;
1825 mat2.M22 = scale;
1826 }
1827 xform.eM11 = mat2.M11 * mat1.M11 + mat2.M12 * mat1.M21;
1828 xform.eM12 = mat2.M11 * mat1.M12 + mat2.M12 * mat1.M22;;
1829 xform.eM21 = mat2.M21 * mat1.M11 + mat2.M22 * mat1.M21;
1830 xform.eM22 = mat2.M21 * mat1.M12 + mat2.M22 * mat1.M22;
1831 xform.eDx = eDx;
1832 xform.eDy = eDy;
1833 return(xform);
1834 }
1835
1836
1837 /**
1838 \brief Construct a U_LOGCOLORSPACEA structure.
1839 \return U_LOGCOLORSPACEA structure
1840 \param lcsCSType LCS_CSType Enumeration
1841 \param lcsIntent LCS_Intent Enumeration
1842 \param lcsEndpoints CIE XYZ color space endpoints
1843 \param lcsGammaRGB Gamma For RGB
1844 \param lcsFilename Could name an external color profile file, otherwise empty string
1845 */
logcolorspacea_set(int32_t lcsCSType,int32_t lcsIntent,U_CIEXYZTRIPLE lcsEndpoints,U_LCS_GAMMARGB lcsGammaRGB,char * lcsFilename)1846 U_LOGCOLORSPACEA logcolorspacea_set(
1847 int32_t lcsCSType,
1848 int32_t lcsIntent,
1849 U_CIEXYZTRIPLE lcsEndpoints,
1850 U_LCS_GAMMARGB lcsGammaRGB,
1851 char *lcsFilename
1852 ){
1853 U_LOGCOLORSPACEA lcsa;
1854 lcsa.lcsSignature = U_LCS_SIGNATURE;
1855 lcsa.lcsVersion = U_LCS_SIGNATURE;
1856 lcsa.lcsSize = sizeof(U_LOGCOLORSPACEA);
1857 lcsa.lcsCSType = lcsCSType;
1858 lcsa.lcsIntent = lcsIntent;
1859 lcsa.lcsEndpoints = lcsEndpoints;
1860 lcsa.lcsGammaRGB = lcsGammaRGB;
1861 strncpy(lcsa.lcsFilename,lcsFilename,U_MAX_PATH);
1862 lcsa.lcsFilename[U_MAX_PATH-1] = '\0';
1863 return(lcsa);
1864 }
1865
1866 /**
1867
1868 \brief Construct a U_LOGCOLORSPACEW structure.
1869 \return U_LOGCOLORSPACEW structure
1870 \param lcsCSType LCS_CSType Enumeration
1871 \param lcsIntent LCS_Intent Enumeration
1872 \param lcsEndpoints CIE XYZ color space endpoints
1873 \param lcsGammaRGB Gamma For RGB
1874 \param lcsFilename Could name an external color profile file, otherwise empty string
1875 */
logcolorspacew_set(int32_t lcsCSType,int32_t lcsIntent,U_CIEXYZTRIPLE lcsEndpoints,U_LCS_GAMMARGB lcsGammaRGB,uint16_t * lcsFilename)1876 U_LOGCOLORSPACEW logcolorspacew_set(
1877 int32_t lcsCSType,
1878 int32_t lcsIntent,
1879 U_CIEXYZTRIPLE lcsEndpoints,
1880 U_LCS_GAMMARGB lcsGammaRGB,
1881 uint16_t *lcsFilename
1882 ){
1883 U_LOGCOLORSPACEW lcsa;
1884 lcsa.lcsSignature = U_LCS_SIGNATURE;
1885 lcsa.lcsVersion = U_LCS_SIGNATURE;
1886 lcsa.lcsSize = sizeof(U_LOGCOLORSPACEW);
1887 lcsa.lcsCSType = lcsCSType;
1888 lcsa.lcsIntent = lcsIntent;
1889 lcsa.lcsEndpoints = lcsEndpoints;
1890 lcsa.lcsGammaRGB = lcsGammaRGB;
1891 wchar16strncpypad(lcsa.lcsFilename,lcsFilename,U_MAX_PATH);
1892 lcsa.lcsFilename[U_MAX_PATH-1] = '\0';
1893 return(lcsa);
1894 }
1895
1896 /**
1897
1898 \brief Construct a U_PANOSE structure.
1899 \return U_PANOSE structure
1900 \param bFamilyType FamilyType Enumeration
1901 \param bSerifStyle SerifType Enumeration
1902 \param bWeight Weight Enumeration
1903 \param bProportion Proportion Enumeration
1904 \param bContrast Contrast Enumeration
1905 \param bStrokeVariation StrokeVariation Enumeration
1906 \param bArmStyle ArmStyle Enumeration
1907 \param bLetterform Letterform Enumeration
1908 \param bMidline Midline Enumeration
1909 \param bXHeight XHeight Enumeration
1910 */
panose_set(uint8_t bFamilyType,uint8_t bSerifStyle,uint8_t bWeight,uint8_t bProportion,uint8_t bContrast,uint8_t bStrokeVariation,uint8_t bArmStyle,uint8_t bLetterform,uint8_t bMidline,uint8_t bXHeight)1911 U_PANOSE panose_set(
1912 uint8_t bFamilyType,
1913 uint8_t bSerifStyle,
1914 uint8_t bWeight,
1915 uint8_t bProportion,
1916 uint8_t bContrast,
1917 uint8_t bStrokeVariation,
1918 uint8_t bArmStyle,
1919 uint8_t bLetterform,
1920 uint8_t bMidline,
1921 uint8_t bXHeight
1922 ){
1923 U_PANOSE panose;
1924 panose.bFamilyType = bFamilyType;
1925 panose.bSerifStyle = bSerifStyle;
1926 panose.bWeight = bWeight;
1927 panose.bProportion = bProportion;
1928 panose.bContrast = bContrast;
1929 panose.bStrokeVariation = bStrokeVariation;
1930 panose.bArmStyle = bArmStyle;
1931 panose.bLetterform = bLetterform;
1932 panose.bMidline = bMidline;
1933 panose.bXHeight = bXHeight;
1934 return(panose);
1935 }
1936
1937 /**
1938 \brief Construct a U_LOGFONT structure.
1939 \return U_LOGFONT structure
1940 \param lfHeight Height in Logical units
1941 \param lfWidth Average Width in Logical units
1942 \param lfEscapement Angle in 0.1 degrees betweem escapement vector and X axis
1943 \param lfOrientation Angle in 0.1 degrees between baseline and X axis
1944 \param lfWeight LF_Weight Enumeration
1945 \param lfItalic Italics: 0 or 1
1946 \param lfUnderline Underline: 0 or 1
1947 \param lfStrikeOut Strikeout: 0 or 1
1948 \param lfCharSet LF_CharSet Enumeration
1949 \param lfOutPrecision LF_OutPrecision Enumeration
1950 \param lfClipPrecision LF_ClipPrecision Enumeration
1951 \param lfQuality LF_Quality Enumeration
1952 \param lfPitchAndFamily LF_PitchAndFamily Enumeration
1953 \param lfFaceName Name of font. truncates at U_LF_FACESIZE, smaller must be null terminated
1954
1955 */
logfont_set(int32_t lfHeight,int32_t lfWidth,int32_t lfEscapement,int32_t lfOrientation,int32_t lfWeight,uint8_t lfItalic,uint8_t lfUnderline,uint8_t lfStrikeOut,uint8_t lfCharSet,uint8_t lfOutPrecision,uint8_t lfClipPrecision,uint8_t lfQuality,uint8_t lfPitchAndFamily,uint16_t * lfFaceName)1956 U_LOGFONT logfont_set(
1957 int32_t lfHeight,
1958 int32_t lfWidth,
1959 int32_t lfEscapement,
1960 int32_t lfOrientation,
1961 int32_t lfWeight,
1962 uint8_t lfItalic,
1963 uint8_t lfUnderline,
1964 uint8_t lfStrikeOut,
1965 uint8_t lfCharSet,
1966 uint8_t lfOutPrecision,
1967 uint8_t lfClipPrecision,
1968 uint8_t lfQuality,
1969 uint8_t lfPitchAndFamily,
1970 uint16_t *lfFaceName
1971 ){
1972 U_LOGFONT lf;
1973 lf.lfHeight = lfHeight;
1974 lf.lfWidth = lfWidth;
1975 lf.lfEscapement = lfEscapement;
1976 lf.lfOrientation = lfOrientation;
1977 lf.lfWeight = lfWeight;
1978 lf.lfItalic = lfItalic;
1979 lf.lfUnderline = lfUnderline;
1980 lf.lfStrikeOut = lfStrikeOut;
1981 lf.lfCharSet = lfCharSet;
1982 lf.lfOutPrecision = lfOutPrecision;
1983 lf.lfClipPrecision = lfClipPrecision;
1984 lf.lfQuality = lfQuality;
1985 lf.lfPitchAndFamily = lfPitchAndFamily;
1986 wchar16strncpypad(lf.lfFaceName, lfFaceName, U_LF_FACESIZE); // pad this one as the intial structure was not set to zero
1987 lf.lfFaceName[U_LF_FACESIZE-1] = '\0';
1988 return(lf);
1989 }
1990
1991
1992 /**
1993 \brief Construct a U_LOGFONT_PANOSE structure.
1994 \return U_LOGFONT_PANOSE structure
1995 \param elfLogFont Basic font attributes
1996 \param elfFullName Font full name, truncates at U_LF_FULLFACESIZE, smaller must be null terminated
1997 \param elfStyle Font style, truncates at U_LF_FULLFACESIZE, smaller must be null terminated
1998 \param elfStyleSize Font hinting starting at this point size, if 0, starts at Height
1999 \param elfPanose Panose Object. If all zero, it is ignored.
2000 */
logfont_panose_set(U_LOGFONT elfLogFont,uint16_t * elfFullName,uint16_t * elfStyle,uint32_t elfStyleSize,U_PANOSE elfPanose)2001 U_LOGFONT_PANOSE logfont_panose_set(
2002 U_LOGFONT elfLogFont,
2003 uint16_t *elfFullName,
2004 uint16_t *elfStyle,
2005 uint32_t elfStyleSize,
2006 U_PANOSE elfPanose
2007 ){
2008 U_LOGFONT_PANOSE lfp;
2009 memset(&lfp,0,sizeof(U_LOGFONT_PANOSE)); // all fields zero unless needed. Many should be ignored or must be 0.
2010 wchar16strncpy(lfp.elfFullName, elfFullName, U_LF_FULLFACESIZE);
2011 lfp.elfFullName[U_LF_FULLFACESIZE-1] = '\0';
2012 wchar16strncpy(lfp.elfStyle, elfStyle, U_LF_FACESIZE);
2013 lfp.elfStyle[U_LF_FACESIZE-1] = '\0';
2014 lfp.elfLogFont = elfLogFont;
2015 lfp.elfStyleSize = elfStyleSize;
2016 lfp.elfPanose = elfPanose;
2017 return(lfp);
2018 }
2019
2020 /**
2021 \brief Construct a U_BITMAPINFOHEADER structure.
2022 \return U_BITMAPINFOHEADER structure
2023 \param biWidth Bitmap width in pixels
2024 \param biHeight Bitmap height in pixels
2025 \param biPlanes Planes (must be 1)
2026 \param biBitCount BitCount Enumeration
2027 \param biCompression BI_Compression Enumeration
2028 \param biSizeImage Size in bytes of image
2029 \param biXPelsPerMeter X Resolution in pixels/meter
2030 \param biYPelsPerMeter Y Resolution in pixels/meter
2031 \param biClrUsed Number of bmciColors in U_BITMAPCOREINFO
2032 \param biClrImportant Number of bmciColors needed (0 means all).
2033 */
bitmapinfoheader_set(int32_t biWidth,int32_t biHeight,uint16_t biPlanes,uint16_t biBitCount,uint32_t biCompression,uint32_t biSizeImage,int32_t biXPelsPerMeter,int32_t biYPelsPerMeter,U_NUM_RGBQUAD biClrUsed,uint32_t biClrImportant)2034 U_BITMAPINFOHEADER bitmapinfoheader_set(
2035 int32_t biWidth,
2036 int32_t biHeight,
2037 uint16_t biPlanes,
2038 uint16_t biBitCount,
2039 uint32_t biCompression,
2040 uint32_t biSizeImage,
2041 int32_t biXPelsPerMeter,
2042 int32_t biYPelsPerMeter,
2043 U_NUM_RGBQUAD biClrUsed,
2044 uint32_t biClrImportant
2045 ){
2046 U_BITMAPINFOHEADER Bmi;
2047 Bmi.biSize = sizeof(U_BITMAPINFOHEADER);
2048 Bmi.biWidth = biWidth;
2049 Bmi.biHeight = biHeight;
2050 Bmi.biPlanes = biPlanes;
2051 Bmi.biBitCount = biBitCount;
2052 Bmi.biCompression = biCompression;
2053 Bmi.biSizeImage = biSizeImage;
2054 Bmi.biXPelsPerMeter = biXPelsPerMeter;
2055 Bmi.biYPelsPerMeter = biYPelsPerMeter;
2056 Bmi.biClrUsed = biClrUsed;
2057 Bmi.biClrImportant = biClrImportant;
2058 return(Bmi);
2059 }
2060
2061
2062 /**
2063 \brief Allocate and construct a U_BITMAPINFO structure.
2064 \return Pointer to a U_BITMAPINFO structure
2065 \param BmiHeader Geometry and pixel properties
2066 \param BmiColors Color table (must be NULL for some values of BmiHeader->biBitCount)
2067 */
bitmapinfo_set(U_BITMAPINFOHEADER BmiHeader,PU_RGBQUAD BmiColors)2068 PU_BITMAPINFO bitmapinfo_set(
2069 U_BITMAPINFOHEADER BmiHeader,
2070 PU_RGBQUAD BmiColors
2071 ){
2072 char *record;
2073 int irecsize;
2074 int cbColors, cbColors4, off;
2075
2076 cbColors = 4*get_real_color_count((char *) &BmiHeader);
2077 cbColors4 = UP4(cbColors);
2078 irecsize = sizeof(U_BITMAPINFOHEADER) + cbColors4;
2079 record = malloc(irecsize);
2080 if(record){
2081 memcpy(record, &BmiHeader, sizeof(U_BITMAPINFOHEADER));
2082 if(cbColors){
2083 off = sizeof(U_BITMAPINFOHEADER);
2084 memcpy(record + off, BmiColors, cbColors);
2085 off += cbColors;
2086 if(cbColors4 - cbColors){ memset(record + off, 0, cbColors4 - cbColors); }
2087 }
2088 }
2089 return((PU_BITMAPINFO) record);
2090 }
2091
2092 /**
2093 \brief Allocate and construct a U_EXTLOGPEN structure.
2094 \return pointer to U_EXTLOGPEN structure, or NULL on error
2095 \param elpPenStyle PenStyle Enumeration
2096 \param elpWidth Width in logical units (elpPenStyle & U_PS_GEOMETRIC) or 1 (pixel)
2097 \param elpBrushStyle LB_Style Enumeration
2098 \param elpColor Pen color
2099 \param elpHatch HatchStyle Enumeration
2100 \param elpNumEntries Count of StyleEntry array
2101 \param elpStyleEntry Array of StyleEntry (For user specified dot/dash patterns)
2102 */
extlogpen_set(uint32_t elpPenStyle,uint32_t elpWidth,uint32_t elpBrushStyle,U_COLORREF elpColor,int32_t elpHatch,U_NUM_STYLEENTRY elpNumEntries,U_STYLEENTRY * elpStyleEntry)2103 PU_EXTLOGPEN extlogpen_set(
2104 uint32_t elpPenStyle,
2105 uint32_t elpWidth,
2106 uint32_t elpBrushStyle,
2107 U_COLORREF elpColor,
2108 int32_t elpHatch,
2109 U_NUM_STYLEENTRY elpNumEntries,
2110 U_STYLEENTRY *elpStyleEntry
2111 ){
2112 int irecsize,szSyleArray;
2113 char *record;
2114
2115 if(elpNumEntries){
2116 if(!elpStyleEntry)return(NULL);
2117 szSyleArray = elpNumEntries * sizeof(U_STYLEENTRY);
2118 irecsize = sizeof(U_EXTLOGPEN) + szSyleArray - sizeof(U_STYLEENTRY); // first one is in the record
2119 }
2120 else {
2121 szSyleArray = 0;
2122 irecsize = sizeof(U_EXTLOGPEN);
2123 }
2124 record = malloc(irecsize);
2125 if(record){
2126 ((PU_EXTLOGPEN) record)->elpPenStyle = elpPenStyle;
2127 ((PU_EXTLOGPEN) record)->elpWidth = elpWidth;
2128 ((PU_EXTLOGPEN) record)->elpBrushStyle = elpBrushStyle;
2129 ((PU_EXTLOGPEN) record)->elpColor = elpColor;
2130 ((PU_EXTLOGPEN) record)->elpHatch = elpHatch;
2131 ((PU_EXTLOGPEN) record)->elpNumEntries = elpNumEntries;
2132 if(elpNumEntries){ memcpy(((PU_EXTLOGPEN) record)->elpStyleEntry,elpStyleEntry,szSyleArray); }
2133 else { memset(((PU_EXTLOGPEN) record)->elpStyleEntry,0,sizeof(U_STYLEENTRY)); } // not used, but this stops valgrind warnings
2134 }
2135 return((PU_EXTLOGPEN) record);
2136 }
2137
2138 /**
2139 \brief Construct a U_LOGPEN structure.
2140 \return U_LOGPEN structure
2141 \param lopnStyle PenStyle Enumeration
2142 \param lopnWidth Width of pen set by X, Y is ignored
2143 \param lopnColor Pen color value
2144
2145 */
logpen_set(uint32_t lopnStyle,U_POINT lopnWidth,U_COLORREF lopnColor)2146 U_LOGPEN logpen_set(
2147 uint32_t lopnStyle,
2148 U_POINT lopnWidth,
2149 U_COLORREF lopnColor
2150 ){
2151 U_LOGPEN lp;
2152 lp.lopnStyle = lopnStyle;
2153 lp.lopnWidth = lopnWidth;
2154 lp.lopnColor = lopnColor;
2155 return(lp);
2156 }
2157
2158 /**
2159 \brief Construct a U_LOGPLTNTRY structure.
2160 \return U_LOGPLTNTRY structure
2161 \param peReserved Ignore
2162 \param peRed Palette entry Red Intensity
2163 \param peGreen Palette entry Green Intensity
2164 \param peBlue Palette entry Blue Intensity
2165 */
logpltntry_set(uint8_t peReserved,uint8_t peRed,uint8_t peGreen,uint8_t peBlue)2166 U_LOGPLTNTRY logpltntry_set(
2167 uint8_t peReserved,
2168 uint8_t peRed,
2169 uint8_t peGreen,
2170 uint8_t peBlue
2171 ){
2172 U_LOGPLTNTRY lpny;
2173 lpny.peReserved = peReserved;
2174 lpny.peRed = peRed;
2175 lpny.peGreen = peGreen;
2176 lpny.peBlue = peBlue;
2177 return(lpny);
2178 }
2179
2180 /**
2181 \brief Allocate and construct a U_LOGPALETTE structure.
2182 \return pointer to U_LOGPALETTE structure, or NULL on error.
2183 \param palNumEntries Number of U_LOGPLTNTRY objects
2184 \param palPalEntry array, PC_Entry Enumeration
2185 */
logpalette_set(U_NUM_LOGPLTNTRY palNumEntries,PU_LOGPLTNTRY * palPalEntry)2186 PU_LOGPALETTE logpalette_set(
2187 U_NUM_LOGPLTNTRY palNumEntries,
2188 PU_LOGPLTNTRY *palPalEntry
2189 ){
2190 PU_LOGPALETTE record;
2191 int cbPalArray,irecsize;
2192
2193 if(palNumEntries == 0 || !palPalEntry)return(NULL);
2194 cbPalArray = palNumEntries * sizeof(U_LOGPLTNTRY);
2195 irecsize = sizeof(U_LOGPALETTE) + cbPalArray - sizeof(U_LOGPLTNTRY);
2196 record = (PU_LOGPALETTE) malloc(irecsize);
2197 if(irecsize){
2198 record->palVersion = U_LP_VERSION;
2199 record->palNumEntries = palNumEntries;
2200 memcpy(record->palPalEntry,palPalEntry,cbPalArray);
2201 }
2202 return(record);
2203 }
2204
2205 /**
2206 \brief Construct a U_RGNDATAHEADER structure.
2207 \return U_RGNDATAHEADER structure
2208 \param nCount Number of rectangles in region
2209 \param rclBounds Region bounds
2210 */
rgndataheader_set(U_NUM_RECTL nCount,U_RECTL rclBounds)2211 U_RGNDATAHEADER rgndataheader_set(
2212 U_NUM_RECTL nCount,
2213 U_RECTL rclBounds
2214 ){
2215 U_RGNDATAHEADER rdh;
2216 rdh.dwSize = U_RDH_OBJSIZE;
2217 rdh.iType = U_RDH_RECTANGLES;
2218 rdh.nCount = nCount;
2219 rdh.nRgnSize = nCount * sizeof(U_RECTL); // Size in bytes of rectangle array
2220 rdh.rclBounds = rclBounds;
2221 return(rdh);
2222 }
2223
2224 /**
2225 \brief Allocate and construct a U_RGNDATA structure.
2226 \return pointer to U_RGNDATA structure, or NULL on error.
2227 \param rdh Data description
2228 \param Buffer Array of U_RECTL elements
2229 */
rgndata_set(U_RGNDATAHEADER rdh,PU_RECTL Buffer)2230 PU_RGNDATA rgndata_set(
2231 U_RGNDATAHEADER rdh,
2232 PU_RECTL Buffer
2233 ){
2234 char *record;
2235 int irecsize;
2236 int szRgnArray,off;
2237
2238 if(!Buffer || !rdh.nCount || !rdh.nRgnSize)return(NULL);
2239 szRgnArray = rdh.nRgnSize; // size of the U_RECTL array
2240 irecsize = sizeof(U_RGNDATA) + szRgnArray - sizeof(U_RECTL); // core + array - overlap
2241 record = malloc(irecsize);
2242 if(record){
2243 memcpy(record, &rdh, sizeof(U_RGNDATAHEADER));
2244 off = sizeof(U_RGNDATAHEADER);
2245 memcpy(record + off, Buffer, szRgnArray);
2246 }
2247 return((PU_RGNDATA) record);
2248 }
2249
2250 /**
2251 \brief Construct a U_COLORADJUSTMENT structure.
2252 \return U_COLORADJUSTMENT structure
2253 \param Size Size of this structure in bytes
2254 \param Flags ColorAdjustment Enumeration
2255 \param IlluminantIndex Illuminant Enumeration
2256 \param RedGamma Red Gamma correction (range:2500:65000, 10000 is no correction)
2257 \param GreenGamma Green Gamma correction (range:2500:65000, 10000 is no correction)
2258 \param BlueGamma Blue Gamma correction (range:2500:65000, 10000 is no correction)
2259 \param ReferenceBlack Values less than this are black (range:0:4000)
2260 \param ReferenceWhite Values more than this are white (range:6000:10000)
2261 \param Contrast Contrast adjustment (range:-100:100, 0 is no correction)
2262 \param Brightness Brightness adjustment (range:-100:100, 0 is no correction)
2263 \param Colorfulness Colorfulness adjustment (range:-100:100, 0 is no correction)
2264 \param RedGreenTint Tine adjustment (range:-100:100, 0 is no correction)
2265 */
coloradjustment_set(uint16_t Size,uint16_t Flags,uint16_t IlluminantIndex,uint16_t RedGamma,uint16_t GreenGamma,uint16_t BlueGamma,uint16_t ReferenceBlack,uint16_t ReferenceWhite,int16_t Contrast,int16_t Brightness,int16_t Colorfulness,int16_t RedGreenTint)2266 U_COLORADJUSTMENT coloradjustment_set(
2267 uint16_t Size,
2268 uint16_t Flags,
2269 uint16_t IlluminantIndex,
2270 uint16_t RedGamma,
2271 uint16_t GreenGamma,
2272 uint16_t BlueGamma,
2273 uint16_t ReferenceBlack,
2274 uint16_t ReferenceWhite,
2275 int16_t Contrast,
2276 int16_t Brightness,
2277 int16_t Colorfulness,
2278 int16_t RedGreenTint
2279 ){
2280 U_COLORADJUSTMENT ca;
2281 ca.caSize = Size;
2282 ca.caFlags = Flags;
2283 ca.caIlluminantIndex = IlluminantIndex;
2284 ca.caRedGamma = U_MNMX(RedGamma, U_RGB_GAMMA_MIN, U_RGB_GAMMA_MAX);
2285 ca.caGreenGamma = U_MNMX(GreenGamma, U_RGB_GAMMA_MIN, U_RGB_GAMMA_MAX);
2286 ca.caBlueGamma = U_MNMX(BlueGamma, U_RGB_GAMMA_MIN, U_RGB_GAMMA_MAX);
2287 // Next one is different to eliminate compiler warning - U_R_B_MIN is 0 and unsigned
2288 ca.caReferenceBlack = U_MAX( ReferenceBlack, U_REFERENCE_BLACK_MAX);
2289 ca.caReferenceWhite = U_MNMX(ReferenceWhite, U_REFERENCE_WHITE_MIN, U_REFERENCE_WHITE_MAX);
2290 ca.caContrast = U_MNMX(Contrast, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX);
2291 ca.caBrightness = U_MNMX(Brightness, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX);
2292 ca.caColorfulness = U_MNMX(Colorfulness, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX);
2293 ca.caRedGreenTint = U_MNMX(RedGreenTint, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX);
2294 return(ca);
2295 }
2296
2297 /**
2298 \brief Construct a U_PIXELFORMATDESCRIPTOR structure.
2299 \return U_PIXELFORMATDESCRIPTOR structure
2300 \param dwFlags PFD_dwFlags Enumeration
2301 \param iPixelType PFD_iPixelType Enumeration
2302 \param cColorBits RGBA: total bits per pixel
2303 \param cRedBits Red bits per pixel
2304 \param cRedShift Red shift to data bits
2305 \param cGreenBits Green bits per pixel
2306 \param cGreenShift Green shift to data bits
2307 \param cBlueBits Blue bits per pixel
2308 \param cBlueShift Blue shift to data bits
2309 \param cAlphaBits Alpha bits per pixel
2310 \param cAlphaShift Alpha shift to data bits
2311 \param cAccumBits Accumulator buffer, total bitplanes
2312 \param cAccumRedBits Red accumulator buffer bitplanes
2313 \param cAccumGreenBits Green accumulator buffer bitplanes
2314 \param cAccumBlueBits Blue accumulator buffer bitplanes
2315 \param cAccumAlphaBits Alpha accumulator buffer bitplanes
2316 \param cDepthBits Depth of Z-buffer
2317 \param cStencilBits Depth of stencil buffer
2318 \param cAuxBuffers Depth of auxilliary buffers (not supported)
2319 \param iLayerType PFD_iLayerType Enumeration, may be ignored
2320 \param bReserved Bits 0:3/4:7 are number of Overlay/Underlay planes
2321 \param dwLayerMask may be ignored
2322 \param dwVisibleMask color or index of underlay plane
2323 \param dwDamageMask may be ignored
2324 */
pixelformatdescriptor_set(uint32_t dwFlags,uint8_t iPixelType,uint8_t cColorBits,uint8_t cRedBits,uint8_t cRedShift,uint8_t cGreenBits,uint8_t cGreenShift,uint8_t cBlueBits,uint8_t cBlueShift,uint8_t cAlphaBits,uint8_t cAlphaShift,uint8_t cAccumBits,uint8_t cAccumRedBits,uint8_t cAccumGreenBits,uint8_t cAccumBlueBits,uint8_t cAccumAlphaBits,uint8_t cDepthBits,uint8_t cStencilBits,uint8_t cAuxBuffers,uint8_t iLayerType,uint8_t bReserved,uint32_t dwLayerMask,uint32_t dwVisibleMask,uint32_t dwDamageMask)2325 U_PIXELFORMATDESCRIPTOR pixelformatdescriptor_set(
2326 uint32_t dwFlags,
2327 uint8_t iPixelType,
2328 uint8_t cColorBits,
2329 uint8_t cRedBits,
2330 uint8_t cRedShift,
2331 uint8_t cGreenBits,
2332 uint8_t cGreenShift,
2333 uint8_t cBlueBits,
2334 uint8_t cBlueShift,
2335 uint8_t cAlphaBits,
2336 uint8_t cAlphaShift,
2337 uint8_t cAccumBits,
2338 uint8_t cAccumRedBits,
2339 uint8_t cAccumGreenBits,
2340 uint8_t cAccumBlueBits,
2341 uint8_t cAccumAlphaBits,
2342 uint8_t cDepthBits,
2343 uint8_t cStencilBits,
2344 uint8_t cAuxBuffers,
2345 uint8_t iLayerType,
2346 uint8_t bReserved,
2347 uint32_t dwLayerMask,
2348 uint32_t dwVisibleMask,
2349 uint32_t dwDamageMask
2350 ){
2351 U_PIXELFORMATDESCRIPTOR pfd;
2352 pfd.nSize = sizeof(U_PIXELFORMATDESCRIPTOR);
2353 pfd.nVersion = 1;
2354 pfd.dwFlags = dwFlags;
2355 pfd.iPixelType = iPixelType;
2356 pfd.cColorBits = cColorBits;
2357 pfd.cRedBits = cRedBits;
2358 pfd.cRedShift = cRedShift;
2359 pfd.cGreenBits = cGreenBits;
2360 pfd.cGreenShift = cGreenShift;
2361 pfd.cBlueBits = cBlueBits;
2362 pfd.cBlueShift = cBlueShift;
2363 pfd.cAlphaBits = cAlphaBits;
2364 pfd.cAlphaShift = cAlphaShift;
2365 pfd.cAccumBits = cAccumBits;
2366 pfd.cAccumRedBits = cAccumRedBits;
2367 pfd.cAccumGreenBits = cAccumGreenBits;
2368 pfd.cAccumBlueBits = cAccumBlueBits;
2369 pfd.cAccumAlphaBits = cAccumAlphaBits;
2370 pfd.cDepthBits = cDepthBits;
2371 pfd.cStencilBits = cStencilBits;
2372 pfd.cAuxBuffers = cAuxBuffers;
2373 pfd.iLayerType = iLayerType;
2374 pfd.bReserved = bReserved;
2375 pfd.dwLayerMask = dwLayerMask;
2376 pfd.dwVisibleMask = dwVisibleMask;
2377 pfd.dwDamageMask = dwDamageMask;
2378 return(pfd);
2379 }
2380
2381 /**
2382 \brief Allocate and create a U_EMRTEXT structure followed by its variable pieces via a char* pointer.
2383 Dx cannot be NULL, if the calling program has no appropriate values call dx_set() first.
2384 \return char* pointer to U_EMRTEXT structure followed by its variable pieces, or NULL on error
2385 \param ptlReference String start coordinates
2386 \param NumString Number of characters in string, does NOT include a terminator
2387 \param cbChar Number of bytes per character
2388 \param String String to write
2389 \param fOptions ExtTextOutOptions Enumeration
2390 \param rcl (Optional, when fOptions & 7) grayed/clipping/opaque rectangle
2391 \param Dx Character spacing array from the start of the RECORD
2392 */
emrtext_set(U_POINTL ptlReference,U_NUM_STR NumString,uint32_t cbChar,void * String,uint32_t fOptions,U_RECTL rcl,uint32_t * Dx)2393 char *emrtext_set(
2394 U_POINTL ptlReference,
2395 U_NUM_STR NumString,
2396 uint32_t cbChar,
2397 void *String,
2398 uint32_t fOptions,
2399 U_RECTL rcl,
2400 uint32_t *Dx
2401 ){
2402 int irecsize,cbDxArray,cbString4,cbString,off;
2403 char *record;
2404 uint32_t *loffDx;
2405
2406 if(!String)return(NULL);
2407 if(!Dx)return(NULL);
2408 cbString = cbChar * NumString; // size of the string in bytes
2409 cbString4 = UP4(cbString); // size of the string buffer
2410 cbDxArray = sizeof(uint32_t)*NumString; // size of Dx array storage
2411 if(fOptions & U_ETO_PDY)cbDxArray += cbDxArray; // of the Dx buffer, here do both X and Y coordinates
2412 irecsize = sizeof(U_EMRTEXT) + sizeof(uint32_t) + cbString4 + cbDxArray; // core structure + offDx + string buf + dx buf
2413 if(!(fOptions & U_ETO_NO_RECT)){ irecsize += sizeof(U_RECTL); } // plus variable U_RECTL, when it is present
2414 record = malloc(irecsize);
2415 if(record){
2416 ((PU_EMRTEXT)record)->ptlReference = ptlReference;
2417 ((PU_EMRTEXT)record)->nChars = NumString;
2418 // pick up ((PU_EMRTEXT)record)->offString later
2419 ((PU_EMRTEXT)record)->fOptions = fOptions;
2420 off = sizeof(U_EMRTEXT); // location where variable pieces will start to be written
2421 if(!(fOptions & U_ETO_NO_RECT)){ // variable field, may or may not be present
2422 memcpy(record + off,&rcl, sizeof(U_RECTL));
2423 off += sizeof(U_RECTL);
2424 }
2425 loffDx = (uint32_t *)(record + off); // offDx will go here, but we do not know with what value yet
2426 off += sizeof(uint32_t);
2427 memcpy(record + off,String,cbString); // copy the string data to its buffer
2428 ((PU_EMRTEXT)record)->offString = off; // now save offset in the structure
2429 off += cbString;
2430 if(cbString < cbString4){
2431 memset(record+off,0,cbString4-cbString); // keeps valgrind happy (initialize padding after string)
2432 off += cbString4-cbString;
2433 }
2434 memcpy(record + off, Dx, cbDxArray); // copy the Dx data to its buffer
2435 *loffDx = off; // now save offDx to the structure
2436 }
2437 return(record);
2438 }
2439
2440
2441
2442 /* **********************************************************************************************
2443 These functions are simpler or more convenient ways to generate the specified types of EMR records.
2444 Each should be called in preference to the underlying "base" EMR function.
2445 *********************************************************************************************** */
2446
2447
2448 /**
2449 \brief Allocate and construct a U_EMRCOMMENT structure with a UTF8 string.
2450 A U_EMRCOMMENT contains application specific data, and that may include contain null characters. This function may be used when the
2451 comment only incluces UT8 text.
2452 \return pointer to U_EMRCOMMENT structure, or NULL on error.
2453 \param string UTF8 string to store in the comment
2454
2455
2456 */
textcomment_set(const char * string)2457 char *textcomment_set(
2458 const char *string
2459 ){
2460 if(!string)return(NULL);
2461 return(U_EMRCOMMENT_set(1 + strlen(string),string));
2462 }
2463
2464 /**
2465 \brief Allocate and construct a U_EMRDELETEOBJECT structure and also delete the requested object from the table.
2466 Use this function instead of calling U_EMRDELETEOBJECT_set() directly.
2467 \return pointer to U_EMRDELETEOBJECT structure, or NULL on error.
2468 \param ihObject Pointer to handle to delete. This value is set to 0 if the function succeeds.
2469 \param eht EMF handle table
2470
2471 Note that calling this function should always be conditional on the specifed object being defined. It is easy to
2472 write a program where deleteobject_set() is called in a sequence where, at the time, we know that ihObject is defined.
2473 Then a later modification, possibly quite far away in the code, causes it to be undefined. That distant change will
2474 result in a failure when this function reutrns. That problem cannot be handled here because the only values which
2475 may be returned are a valid U_EMRDELETEOBJECT record or a NULL, and other errors could result in the NULL.
2476 So the object must be checked before the call.
2477 */
deleteobject_set(uint32_t * ihObject,EMFHANDLES * eht)2478 char *deleteobject_set(
2479 uint32_t *ihObject,
2480 EMFHANDLES *eht
2481 ){
2482 uint32_t saveObject=*ihObject;
2483 if(emf_htable_delete(ihObject,eht))return(NULL); // invalid handle or other problem, cannot be deleted
2484 return(U_EMRDELETEOBJECT_set(saveObject));
2485 }
2486
2487 /**
2488 \brief Allocate and construct a U_EMRSELECTOBJECT structure, checks that the handle specified is one that can actually be selected.
2489 Use this function instead of calling U_EMRSELECTOBJECT_set() directly.
2490 \return pointer to U_EMRSELECTOBJECT structure, or NULL on error.
2491 \param ihObject handle to select
2492 \param eht EMF handle table
2493 */
selectobject_set(uint32_t ihObject,EMFHANDLES * eht)2494 char *selectobject_set(
2495 uint32_t ihObject,
2496 EMFHANDLES *eht
2497 ){
2498 if(!(U_STOCK_OBJECT & ihObject)){ // not a stock object, those go straight through
2499 if(ihObject > eht->top)return(NULL); // handle this high is not in the table
2500 if(!eht->table[ihObject])return(NULL); // handle is not in the table, so not active, so cannot be selected
2501 }
2502 return(U_EMRSELECTOBJECT_set(ihObject));
2503 }
2504
2505 /**
2506 \brief Allocate and construct a U_EMREXTCREATEPEN structure, create a handle and return it.
2507 Use this function instead of calling U_EMREXTCREATEPEN_set() directly.
2508 \return pointer to U_EMREXTCREATEPEN structure, or NULL on error.
2509 \param ihPen handle to be used by new object
2510 \param eht EMF handle table
2511 \param Bmi bitmapbuffer
2512 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
2513 \param Px pixel array (NULL if cbPx == 0)
2514 \param elp Pen parameters (Size is Variable!!!!)
2515 */
extcreatepen_set(uint32_t * ihPen,EMFHANDLES * eht,PU_BITMAPINFO Bmi,const uint32_t cbPx,char * Px,PU_EXTLOGPEN elp)2516 char *extcreatepen_set(
2517 uint32_t *ihPen,
2518 EMFHANDLES *eht,
2519 PU_BITMAPINFO Bmi,
2520 const uint32_t cbPx,
2521 char *Px,
2522 PU_EXTLOGPEN elp
2523 ){
2524 if(emf_htable_insert(ihPen, eht))return(NULL);
2525 return(U_EMREXTCREATEPEN_set(*ihPen, Bmi, cbPx, Px, elp ));
2526 }
2527
2528 /**
2529 \brief Allocate and construct a U_EMRCREATEPEN structure, create a handle and returns it
2530 Use this function instead of calling U_EMRCREATEPEN_set() directly.
2531 \return pointer to U_EMRCREATEPEN structure, or NULL on error.
2532 \param ihPen handle to be used by new object
2533 \param eht EMF handle table
2534 \param lopn Pen parameters
2535 */
createpen_set(uint32_t * ihPen,EMFHANDLES * eht,U_LOGPEN lopn)2536 char *createpen_set(
2537 uint32_t *ihPen,
2538 EMFHANDLES *eht,
2539 U_LOGPEN lopn
2540 ){
2541 if(emf_htable_insert(ihPen, eht))return(NULL);
2542 return(U_EMRCREATEPEN_set(*ihPen, lopn));
2543 }
2544
2545 /**
2546 \brief Allocate and construct a U_EMRCREATEBRUSHINDIRECT structure, create a handle and returns it
2547 Use this function instead of calling U_EMRCREATEBRUSHINDIRECT_set() directly.
2548 \return pointer to U_EMRCREATEBRUSHINDIRECT structure, or NULL on error.
2549 \param ihBrush handle to be used by new object
2550 \param eht EMF handle table
2551 \param lb Brush parameters
2552 */
createbrushindirect_set(uint32_t * ihBrush,EMFHANDLES * eht,U_LOGBRUSH lb)2553 char *createbrushindirect_set(
2554 uint32_t *ihBrush,
2555 EMFHANDLES *eht,
2556 U_LOGBRUSH lb
2557 ){
2558 if(emf_htable_insert(ihBrush, eht))return(NULL);
2559 return(U_EMRCREATEBRUSHINDIRECT_set(*ihBrush, lb));
2560 }
2561
2562 /**
2563 \brief Allocate and construct a U_EMRCREATEDIBPATTERNBRUSHPT_set structure, create a handle and returns it
2564 Use this function instead of calling U_EMRCREATEDIBPATTERNBRUSHPT_set() directly.
2565 \return pointer to U_EMRCREATEDIBPATTERNBRUSHPT_set structure, or NULL on error.
2566 \param ihBrush handle to be used by new object
2567 \param eht EMF handle table
2568 \param iUsage DIBColors enumeration
2569 \param Bmi Bitmap info
2570 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
2571 \param Px (Optional) bitmapbuffer (pixel array section )
2572 */
createdibpatternbrushpt_set(uint32_t * ihBrush,EMFHANDLES * eht,const uint32_t iUsage,PU_BITMAPINFO Bmi,const uint32_t cbPx,const char * Px)2573 char *createdibpatternbrushpt_set(
2574 uint32_t *ihBrush,
2575 EMFHANDLES *eht,
2576 const uint32_t iUsage,
2577 PU_BITMAPINFO Bmi,
2578 const uint32_t cbPx,
2579 const char *Px
2580
2581 ){
2582 if(emf_htable_insert(ihBrush, eht))return(NULL);
2583 return(U_EMRCREATEDIBPATTERNBRUSHPT_set(*ihBrush, iUsage, Bmi, cbPx, Px));
2584 }
2585
2586 /**
2587 \brief Allocate and construct a U_EMRCREATEMONOBRUSH_set structure, create a handle and returns it
2588 Use this function instead of calling U_EMRCREATEMONOBRUSH_set() directly.
2589 \return pointer to U_EMRCREATEMONOBRUSH_set structure, or NULL on error.
2590 \param ihBrush handle to be used by new object
2591 \param eht EMF handle table
2592 \param iUsage DIBColors enumeration
2593 \param Bmi Bitmap info
2594 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
2595 \param Px (Optional) bitmapbuffer (pixel array section )
2596 */
createmonobrush_set(uint32_t * ihBrush,EMFHANDLES * eht,const uint32_t iUsage,PU_BITMAPINFO Bmi,const uint32_t cbPx,const char * Px)2597 char *createmonobrush_set(
2598 uint32_t *ihBrush,
2599 EMFHANDLES *eht,
2600 const uint32_t iUsage,
2601 PU_BITMAPINFO Bmi,
2602 const uint32_t cbPx,
2603 const char *Px
2604
2605 ){
2606 if(emf_htable_insert(ihBrush, eht))return(NULL);
2607 return(U_EMRCREATEMONOBRUSH_set(*ihBrush, iUsage, Bmi, cbPx, Px));
2608 }
2609
2610
2611 /**
2612 \brief Allocate and construct a U_EMRCREATECOLORSPACE structure, create a handle and returns it
2613 Use this function instead of calling U_EMRCREATECOLORSPACE_set() directly.
2614 \return pointer to U_EMRCREATECOLORSPACE structure, or NULL on error.
2615 \param ihCS ColorSpace handle, will be created and returned
2616 \param eht Pointer to structure holding all EMF handles
2617 \param lcs ColorSpace parameters
2618 */
createcolorspace_set(uint32_t * ihCS,EMFHANDLES * eht,U_LOGCOLORSPACEA lcs)2619 char *createcolorspace_set(
2620 uint32_t *ihCS,
2621 EMFHANDLES *eht,
2622 U_LOGCOLORSPACEA lcs
2623 ){
2624 if(emf_htable_insert(ihCS, eht))return(NULL);
2625 return(U_EMRCREATECOLORSPACE_set(*ihCS,lcs));
2626 }
2627
2628 /**
2629 \brief Allocate and construct a U_EMRCREATECOLORSPACEW structure, create a handle and returns it
2630 Use this function instead of calling U_EMRCREATECOLORSPACEW_set() directly.
2631 \return pointer to U_EMRCREATECOLORSPACEW structure, or NULL on error.
2632 \param ihCS ColorSpace handle, will be created and returned
2633 \param eht Pointer to structure holding all EMF handles
2634 \param lcs ColorSpace parameters
2635 \param dwFlags If low bit set Data is present
2636 \param cbData Number of bytes of theData field.
2637 \param Data (Optional, dwFlags & 1) color profile data
2638 */
createcolorspacew_set(uint32_t * ihCS,EMFHANDLES * eht,U_LOGCOLORSPACEW lcs,uint32_t dwFlags,U_CBDATA cbData,uint8_t * Data)2639 char *createcolorspacew_set(
2640 uint32_t *ihCS,
2641 EMFHANDLES *eht,
2642 U_LOGCOLORSPACEW lcs,
2643 uint32_t dwFlags,
2644 U_CBDATA cbData,
2645 uint8_t *Data
2646 ){
2647 if(emf_htable_insert(ihCS, eht))return(NULL);
2648 return(U_EMRCREATECOLORSPACEW_set(*ihCS, lcs, dwFlags, cbData, Data));
2649 }
2650
2651 /**
2652 \brief Allocate and construct a U_EMREXTCREATEFONTINDIRECTW structure, create a handle and returns it
2653 Use this function instead of calling U_EMREXTCREATEFONTINDIRECTW_set() directly.
2654 \return pointer to U_EMREXTCREATEFONTINDIRECTW structure, or NULL on error.
2655 \param ihFont Font handle, will be created and returned
2656 \param eht Pointer to structure holding all EMF handles
2657 \param elf Pointer to Font parameters asPU_LOGFONT
2658 \param elfw Pointer to Font parameters as U_LOGFONT_PANOSE
2659 */
extcreatefontindirectw_set(uint32_t * ihFont,EMFHANDLES * eht,const char * elf,const char * elfw)2660 char *extcreatefontindirectw_set(
2661 uint32_t *ihFont,
2662 EMFHANDLES *eht,
2663 const char *elf,
2664 const char *elfw
2665 ){
2666 if(emf_htable_insert(ihFont, eht))return(NULL);
2667 return(U_EMREXTCREATEFONTINDIRECTW_set(*ihFont, elf, elfw));
2668 }
2669
2670 /**
2671 \brief Allocate and construct a U_EMRCREATEPALETTE structure, create a handle and returns it
2672 Use this function instead of calling U_EMRCREATEPALETTE_set() directly.
2673 \return pointer to U_EMRCREATEPALETTE structure, or NULL on error.
2674 \param ihPal Palette handle, will be created and returned
2675 \param eht Pointer to structure holding all EMF handles
2676 \param lgpl PaletteFont parameters
2677 */
createpalette_set(uint32_t * ihPal,EMFHANDLES * eht,U_LOGPALETTE lgpl)2678 char *createpalette_set(
2679 uint32_t *ihPal,
2680 EMFHANDLES *eht,
2681 U_LOGPALETTE lgpl
2682 ){
2683 if(emf_htable_insert(ihPal, eht))return(NULL);
2684 return(U_EMRCREATEPALETTE_set(*ihPal, lgpl));
2685 }
2686
2687 /**
2688 \brief Allocate and construct a U_EMRSETPALETTEENTRIES structure, create a handle and returns it
2689 Use this function instead of calling U_EMRSETPALETTEENTRIES_set() directly.
2690 \return pointer to U_EMRSETPALETTEENTRIES structure, or NULL on error.
2691 \param ihPal Palette handle, will be created and returned
2692 \param eht Pointer to structure holding all EMF handles
2693 \param iStart First Palette entry in selected object to set
2694 \param cEntries Number of Palette entries in selected object to set
2695 \param aPalEntries Values to set with
2696 */
setpaletteentries_set(uint32_t * ihPal,EMFHANDLES * eht,const uint32_t iStart,const U_NUM_LOGPLTNTRY cEntries,const PU_LOGPLTNTRY aPalEntries)2697 char *setpaletteentries_set(
2698 uint32_t *ihPal,
2699 EMFHANDLES *eht,
2700 const uint32_t iStart,
2701 const U_NUM_LOGPLTNTRY cEntries,
2702 const PU_LOGPLTNTRY aPalEntries
2703 ){
2704 if(emf_htable_insert(ihPal, eht))return(NULL);
2705 return(U_EMRSETPALETTEENTRIES_set(*ihPal, iStart, cEntries, aPalEntries));
2706 }
2707
2708 /**
2709 \brief Allocate and construct a U_EMRFILLRGN structure, create a handle and returns it
2710 Use this function instead of calling U_EMRFILLRGN_set() directly.
2711 \return pointer to U_EMRFILLRGN structure, or NULL on error.
2712 \param ihBrush Brush handle, will be created and returned
2713 \param eht Pointer to structure holding all EMF handles
2714 \param rclBounds Bounding rectangle in device units
2715 \param RgnData Pointer to a U_RGNDATA structure
2716 */
fillrgn_set(uint32_t * ihBrush,EMFHANDLES * eht,const U_RECTL rclBounds,const PU_RGNDATA RgnData)2717 char *fillrgn_set(
2718 uint32_t *ihBrush,
2719 EMFHANDLES *eht,
2720 const U_RECTL rclBounds,
2721 const PU_RGNDATA RgnData
2722 ){
2723 if(emf_htable_insert(ihBrush, eht))return(NULL);
2724 return(U_EMRFILLRGN_set(rclBounds, *ihBrush, RgnData));
2725 }
2726
2727 /**
2728 \brief Allocate and construct a U_EMRFRAMERGN structure, create a handle and returns it
2729 Use this function instead of calling U_EMRFRAMERGN_set() directly.
2730 \return pointer to U_EMRFRAMERGN structure, or NULL on error.
2731 \param ihBrush Brush handle, will be created and returned
2732 \param eht Pointer to structure holding all EMF handles
2733 \param rclBounds Bounding rectangle in device units
2734 \param szlStroke W & H of Brush stroke
2735 \param RgnData Pointer to a U_RGNDATA structure
2736 */
framergn_set(uint32_t * ihBrush,EMFHANDLES * eht,const U_RECTL rclBounds,const U_SIZEL szlStroke,const PU_RGNDATA RgnData)2737 char *framergn_set(
2738 uint32_t *ihBrush,
2739 EMFHANDLES *eht,
2740 const U_RECTL rclBounds,
2741 const U_SIZEL szlStroke,
2742 const PU_RGNDATA RgnData
2743 ){
2744 if(emf_htable_insert(ihBrush, eht))return(NULL);
2745 return(U_EMRFRAMERGN_set(rclBounds, *ihBrush, szlStroke, RgnData));
2746 }
2747
2748 /**
2749 \brief Allocate and construct an array of U_POINT objects which has been subjected to a U_XFORM
2750 \returns pointer to an array of U_POINT structures.
2751 \param points pointer to the source U_POINT structures
2752 \param count number of members in points
2753 \param xform U_XFORM to apply
2754
2755 May also be used to modify U_RECT by doubling the count and casting the pointer.
2756 */
points_transform(PU_POINT points,int count,U_XFORM xform)2757 PU_POINT points_transform(PU_POINT points, int count, U_XFORM xform){
2758 PU_POINT newpts;
2759 int i;
2760 float x,y;
2761 newpts = (PU_POINT) malloc(count * sizeof(U_POINT));
2762 for(i=0; i<count; i++){
2763 x = (float) points[i].x;
2764 y = (float) points[i].y;
2765 newpts[i].x = U_ROUND(x * xform.eM11 + y * xform.eM21 + xform.eDx);
2766 newpts[i].y = U_ROUND(x * xform.eM12 + y * xform.eM22 + xform.eDy);
2767 }
2768 return(newpts);
2769 }
2770
2771 /**
2772 \brief Allocate and construct an array of U_POINT16 objects which has been subjected to a U_XFORM
2773 \returns pointer to an array of U_POINT16 structures.
2774 \param points pointer to the source U_POINT16 structures
2775 \param count number of members in points
2776 \param xform U_XFORM to apply
2777
2778 Transformed src points {x0,y0} appear at {x0*xscale + x, y0*yscale + y}
2779 */
point16_transform(PU_POINT16 points,int count,U_XFORM xform)2780 PU_POINT16 point16_transform(PU_POINT16 points, int count, U_XFORM xform){
2781 PU_POINT16 newpts;
2782 int i;
2783 float x,y;
2784 newpts = (PU_POINT16) malloc(count * sizeof(U_POINT16));
2785 for(i=0; i<count; i++){
2786 x = (float) points[i].x;
2787 y = (float) points[i].y;
2788 newpts[i].x = U_ROUND(x * xform.eM11 + y * xform.eM21 + xform.eDx);
2789 newpts[i].y = U_ROUND(x * xform.eM12 + y * xform.eM22 + xform.eDy);
2790 }
2791 return(newpts);
2792 }
2793
2794 /**
2795 \brief Allocate and construct an array of U_TRIVERTEX objects which has been subjected to a U_XFORM
2796 \returns pointer to an array of U_TRIVERTEX structures.
2797 \param tv pointer to the source U_TRIVERTEX structures
2798 \param count number of members in points
2799 \param xform U_XFORM to apply
2800
2801 Transformed Trivertex points {x0,y0} appear at {x0*xscale + x, y0*yscale + y}
2802 */
trivertex_transform(PU_TRIVERTEX tv,int count,U_XFORM xform)2803 PU_TRIVERTEX trivertex_transform(PU_TRIVERTEX tv, int count, U_XFORM xform){
2804 PU_TRIVERTEX newtvs;
2805 int i;
2806 float x,y;
2807 newtvs = (PU_TRIVERTEX) malloc(count * sizeof(U_TRIVERTEX));
2808 for(i=0; i<count; i++){
2809 x = (float) tv[i].x;
2810 y = (float) tv[i].y;
2811 newtvs[i] = tv[i];
2812 newtvs[i].x = U_ROUND(x * xform.eM11 + y * xform.eM21 + xform.eDx);
2813 newtvs[i].y = U_ROUND(x * xform.eM12 + y * xform.eM22 + xform.eDy);
2814 }
2815 return(newtvs);
2816 }
2817
2818 /**
2819 \brief Allocate and construct an array of U_POINT objects from a set of U_POINT16 objects
2820 \returns pointer to an array of U_POINT structures.
2821 \param points pointer to the source U_POINT16 structures
2822 \param count number of members in points
2823
2824 */
point16_to_point(PU_POINT16 points,int count)2825 PU_POINT point16_to_point(PU_POINT16 points, int count){
2826 PU_POINT newpts;
2827 int i;
2828 newpts = (PU_POINT) malloc(count * sizeof(U_POINT));
2829 for(i=0; i<count; i++){
2830 newpts[i].x = points[i].x;
2831 newpts[i].y = points[i].y;
2832 }
2833 return(newpts);
2834 }
2835
2836 /**
2837 \brief Allocate and construct an array of U_POINT16 objects from a set of U_POINT objects
2838 \returns pointer to an array of U_POINT16 structures.
2839 \param points pointer to the source U_POINT structures
2840 \param count number of members in points
2841
2842 If a coordinate is out of range it saturates at boundary.
2843 */
point_to_point16(PU_POINT points,int count)2844 PU_POINT16 point_to_point16(PU_POINT points, int count){
2845 PU_POINT16 newpts;
2846 int i;
2847 newpts = (PU_POINT16) malloc(count * sizeof(U_POINT16));
2848 for(i=0; i<count; i++){
2849 newpts[i].x = U_MNMX(points[i].x, INT16_MIN, INT16_MAX);
2850 newpts[i].y = U_MNMX(points[i].y, INT16_MIN, INT16_MAX);
2851 }
2852 return(newpts);
2853 }
2854
2855 // hide these from Doxygen
2856 //! @cond
2857 /* **********************************************************************************************
2858 These functions contain shared code used by various U_EMR*_set functions. These should NEVER be called
2859 by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen.
2860
2861
2862 These are (mostly) ordered by U_EMR_* index number.
2863 For all _set functions the caller must eventually call free() on the returned pointer.
2864
2865 CORE1(uint32_t iType, U_RECTL rclBounds, const uint32_t cptl, const U_POINTL *points){
2866 CORE2(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cptl, const U_POINTL *points){
2867 CORE3(uint32_t iType, uint32_t iMode){ (generic 1 uint)
2868 CORE4(uint32_t iType, U_RECTL rclBox){
2869 CORE5(uint32_t iType){ (generic noargs)
2870 CORE6(uint32_t iType, U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points){ (16bit form of CORE1)
2871 CORE7(uint32_t iType, U_PAIR pair){
2872 CORE8(uint32_t iType, U_RECTL rclBounds, uint32_t iGraphicsMode, U_FLOAT exScale, U_FLOAT eyScale, PU_EMRTEXT emrtext){
2873 CORE9(uint32_t iType, U_RECTL rclBox, U_POINTL ptlStart, U_POINTL ptlEnd){
2874 CORE10(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points){ (16bit form of CORE2)
2875 CORE11(uint32_t iType, PU_RGNDATA RgnData){
2876 CORE12(uint32_t iType, uint32_t ihBrush, uint32_t iUsage, PU_BITMAPINFO Bmi){
2877 CORE13(uint32_t iType, U_RECTL rclBounds, U_POINTL Dest, U_POINTL cDest,
2878 U_POINTL Src, U_POINTL cSrc, U_XFORM xformSrc, U_COLORREF crBkColorSrc, uint32_t iUsageSrc,
2879 uint32_t Data, PU_BITMAPINFO Bmi);
2880 *********************************************************************************************** */
2881
2882
2883 // Functions with the same form starting with U_EMRPOLYBEZIER_set
U_EMR_CORE1_set(uint32_t iType,U_RECTL rclBounds,const uint32_t cptl,const U_POINTL * points)2884 char *U_EMR_CORE1_set(uint32_t iType, U_RECTL rclBounds, const uint32_t cptl, const U_POINTL *points){
2885 char *record;
2886 int cbPoints;
2887 int irecsize;
2888
2889 cbPoints = sizeof(U_POINTL)*cptl;
2890 irecsize = sizeof(U_EMRPOLYBEZIER) + cbPoints - sizeof(U_POINTL); // First instance is in struct
2891 record = malloc(irecsize);
2892 if(record){
2893 ((PU_EMR) record)->iType = iType;
2894 ((PU_EMR) record)->nSize = irecsize;
2895 ((PU_EMRPOLYBEZIER) record)->rclBounds = rclBounds;
2896 ((PU_EMRPOLYBEZIER) record)->cptl = cptl;
2897 memcpy(((PU_EMRPOLYBEZIER) record)->aptl,points,cbPoints);
2898 }
2899 return(record);
2900 }
2901
2902 // Functions with the same form starting with U_EMR_POLYPOLYLINE
U_EMR_CORE2_set(uint32_t iType,U_RECTL rclBounds,const uint32_t nPolys,const uint32_t * aPolyCounts,const uint32_t cptl,const U_POINTL * points)2903 char *U_EMR_CORE2_set(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cptl, const U_POINTL *points){
2904 char *record;
2905 int cbPolys,cbPoints,off;
2906 int irecsize;
2907
2908 cbPoints = sizeof(U_POINTL)*cptl;
2909 cbPolys = sizeof(uint32_t)*nPolys;
2910 irecsize = sizeof(U_EMRPOLYPOLYLINE) + cbPoints + cbPolys - sizeof(uint32_t); // First instance of each is in struct
2911 record = malloc(irecsize);
2912 if(record){
2913 ((PU_EMR) record)->iType = iType;
2914 ((PU_EMR) record)->nSize = irecsize;
2915 ((PU_EMRPOLYPOLYLINE) record)->rclBounds = rclBounds;
2916 ((PU_EMRPOLYPOLYLINE) record)->nPolys = nPolys;
2917 ((PU_EMRPOLYPOLYLINE) record)->cptl = cptl;
2918 memcpy(((PU_EMRPOLYPOLYLINE) record)->aPolyCounts,aPolyCounts,cbPolys);
2919 off = sizeof(U_EMRPOLYPOLYLINE) - 4 + cbPolys;
2920 memcpy(record + off,points,cbPoints);
2921 }
2922 return(record);
2923 }
2924
2925 // Functions with the same form starting with U_EMR_SETMAPMODE_set
U_EMR_CORE3_set(uint32_t iType,uint32_t iMode)2926 char *U_EMR_CORE3_set(uint32_t iType, uint32_t iMode){
2927 char *record;
2928 int irecsize;
2929
2930 irecsize = sizeof(U_EMRSETMAPMODE);
2931 record = malloc(irecsize);
2932 if(record){
2933 ((PU_EMR) record)->iType = iType;
2934 ((PU_EMR) record)->nSize = irecsize;
2935 ((PU_EMRSETMAPMODE)record)->iMode = iMode;
2936 }
2937 return(record);
2938 }
2939
2940 // Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_set, also U_EMRFILLPATH,
U_EMR_CORE4_set(uint32_t iType,U_RECTL rclBox)2941 char *U_EMR_CORE4_set(uint32_t iType, U_RECTL rclBox){
2942 char *record;
2943 int irecsize;
2944
2945 irecsize = sizeof(U_EMRELLIPSE);
2946 record = malloc(irecsize);
2947 memset(record,0,irecsize);
2948 if(record){
2949 ((PU_EMR) record)->iType = iType;
2950 ((PU_EMR) record)->nSize = irecsize;
2951 ((PU_EMRELLIPSE)record)->rclBox = rclBox; // bounding rectangle in logical units
2952 }
2953 return(record);
2954 }
2955
2956 // Functions with the same form starting with U_EMRSETMETARGN_set
U_EMR_CORE5_set(uint32_t iType)2957 char *U_EMR_CORE5_set(uint32_t iType){
2958 char *record;
2959 int irecsize = 8;
2960
2961 record = malloc(irecsize);
2962 if(record){
2963 ((PU_EMR) record)->iType = iType;
2964 ((PU_EMR) record)->nSize = irecsize;
2965 }
2966 return(record);
2967 }
2968
2969 // Functions with the same form starting with U_EMRPOLYBEZIER16_set
U_EMR_CORE6_set(uint32_t iType,U_RECTL rclBounds,const uint32_t cpts,const U_POINT16 * points)2970 char *U_EMR_CORE6_set(uint32_t iType, U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points){
2971 char *record;
2972 int cbPoints,cbPoints4,off;
2973 int irecsize;
2974
2975 cbPoints = sizeof(U_POINT16)*cpts;
2976 cbPoints4 = UP4(cbPoints);
2977 off = sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINT16); // offset to the start of the variable region
2978 irecsize = off + cbPoints4; // First instance is in struct
2979 record = malloc(irecsize);
2980 if(record){
2981 ((PU_EMR) record)->iType = iType;
2982 ((PU_EMR) record)->nSize = irecsize;
2983 ((PU_EMRPOLYBEZIER16) record)->rclBounds = rclBounds;
2984 ((PU_EMRPOLYBEZIER16) record)->cpts = cpts;
2985 memcpy(record + off, points, cbPoints);
2986 if(cbPoints < cbPoints4){
2987 off += cbPoints;
2988 memset(record + off, 0, cbPoints4 - cbPoints);
2989 }
2990 }
2991 return(record);
2992 }
2993
2994
2995 // Functions that take a single struct argument which contains two uint32_t, starting with U_EMRSETWINDOWEXTEX_set
2996 // these all pass two 32 bit ints and are cast by the caller to U_PAIR
U_EMR_CORE7_set(uint32_t iType,U_PAIR pair)2997 char *U_EMR_CORE7_set(uint32_t iType, U_PAIR pair){
2998 char *record;
2999 int irecsize = sizeof(U_EMRGENERICPAIR);
3000
3001 record = malloc(irecsize);
3002 if(record){
3003 ((PU_EMR) record)->iType = iType;
3004 ((PU_EMR) record)->nSize = irecsize;
3005 ((PU_EMRGENERICPAIR)record)->pair = pair;
3006 }
3007 return(record);
3008 }
3009
3010 // For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW
U_EMR_CORE8_set(uint32_t iType,U_RECTL rclBounds,uint32_t iGraphicsMode,U_FLOAT exScale,U_FLOAT eyScale,PU_EMRTEXT emrtext)3011 char *U_EMR_CORE8_set(
3012 uint32_t iType,
3013 U_RECTL rclBounds, // Bounding rectangle in device units
3014 uint32_t iGraphicsMode, // Graphics mode Enumeration
3015 U_FLOAT exScale, // scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
3016 U_FLOAT eyScale, // scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
3017 PU_EMRTEXT emrtext // Text parameters
3018 ){
3019 char *record;
3020 int irecsize,cbString,cbString4,cbDx,cbEmrtext,cbEmrtextAll;
3021 uint32_t *loffDx;
3022 int csize;
3023
3024 if( iType == U_EMR_EXTTEXTOUTA){ csize = 1; } // how many bytes per character
3025 else if(iType == U_EMR_EXTTEXTOUTW){ csize = 2; }
3026 else { return(NULL); }
3027
3028 cbString = csize * emrtext->nChars;
3029 cbString4 = UP4(cbString); // size of the string buffer
3030 cbEmrtext = sizeof(U_EMRTEXT); // size of the constant part of the U_EMRTEXT structure
3031 if(!(emrtext->fOptions & U_ETO_NO_RECT)){ cbEmrtext += sizeof(U_RECTL); } // plus the variable U_RECTL, when it is present
3032 cbDx = emrtext->nChars * sizeof(int32_t); // size of Dx buffer
3033 if(emrtext->fOptions & U_ETO_PDY)cbDx += cbDx; // size of Dx buffer when both x and y offsets are used
3034 cbEmrtextAll = cbEmrtext + sizeof(uint32_t) + cbString4 + cbDx; // structure (+- rect) + offDx + string buf + dx buf + offDx
3035
3036 /* adjust offset fields in emrtext to match the EMRTEXTOUT* field, currently they match EMRTEXT.
3037 This works because the variable pieces have all been moved outside of the U_EMRTEXT and U_EMRTEXTOUTA strutures.
3038 */
3039 ((PU_EMRTEXT)emrtext)->offString += sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT); // adjust offString
3040 loffDx = (uint32_t *)((char *)emrtext + cbEmrtext);
3041 *loffDx += sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT);
3042
3043 // final record size is: U_EMREXTTEXTOUTA (includes constant part of U_EMRTEXT) + U_RECTL (if present) + offDx + dx buffer + string buffer
3044 irecsize = sizeof(U_EMREXTTEXTOUTA) + cbEmrtextAll - sizeof(U_EMRTEXT); // do not count core emrtext strcture twice
3045 record = malloc(irecsize);
3046 if(record){
3047 ((PU_EMR) record)->iType = iType;
3048 ((PU_EMR) record)->nSize = irecsize;
3049 ((PU_EMREXTTEXTOUTA) record)->iGraphicsMode = iGraphicsMode;
3050 ((PU_EMREXTTEXTOUTA) record)->rclBounds = rclBounds;
3051 ((PU_EMREXTTEXTOUTA) record)->exScale = exScale;
3052 ((PU_EMREXTTEXTOUTA) record)->eyScale = eyScale;
3053 // copy the adjusted U_EMRTEXT into the emrtext part of the full record..
3054 memcpy(&(((PU_EMREXTTEXTOUTA) record)->emrtext), emrtext, cbEmrtextAll);
3055 }
3056 return(record);
3057 }
3058
3059 // Functions that take a rect and a pair of points, starting with U_EMRARC_set
U_EMR_CORE9_set(uint32_t iType,U_RECTL rclBox,U_POINTL ptlStart,U_POINTL ptlEnd)3060 char *U_EMR_CORE9_set(uint32_t iType, U_RECTL rclBox, U_POINTL ptlStart, U_POINTL ptlEnd){
3061 char *record;
3062 int irecsize = sizeof(U_EMRARC);
3063
3064 record = malloc(irecsize);
3065 if(record){
3066 ((PU_EMR) record)->iType = iType;
3067 ((PU_EMR) record)->nSize = irecsize;
3068 ((PU_EMRARC) record)->rclBox = rclBox;
3069 ((PU_EMRARC) record)->ptlStart = ptlStart;
3070 ((PU_EMRARC) record)->ptlEnd = ptlEnd;
3071 }
3072 return(record);
3073 }
3074
3075 // Functions with the same form starting with U_EMR_POLYPOLYLINE16
U_EMR_CORE10_set(uint32_t iType,U_RECTL rclBounds,const uint32_t nPolys,const uint32_t * aPolyCounts,const uint32_t cpts,const U_POINT16 * points)3076 char *U_EMR_CORE10_set(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points){
3077 char *record;
3078 int cbPoints,cbPolys,off;
3079 int irecsize;
3080
3081 cbPolys = sizeof(uint32_t)*nPolys;
3082 cbPoints = sizeof(U_POINT16)*cpts;
3083 irecsize = sizeof(U_EMRPOLYPOLYLINE16) + cbPoints + cbPolys - sizeof(uint32_t); // First instance of each is in struct
3084 record = malloc(irecsize);
3085 if(record){
3086 ((PU_EMR) record)->iType = iType;
3087 ((PU_EMR) record)->nSize = irecsize;
3088 ((PU_EMRPOLYPOLYLINE16) record)->rclBounds = rclBounds;
3089 ((PU_EMRPOLYPOLYLINE16) record)->nPolys = nPolys;
3090 ((PU_EMRPOLYPOLYLINE16) record)->cpts = cpts;
3091 memcpy(((PU_EMRPOLYPOLYLINE16) record)->aPolyCounts,aPolyCounts,cbPolys);
3092 off = sizeof(U_EMRPOLYPOLYLINE16) - 4 + cbPolys;
3093 memcpy(record + off,points,cbPoints);
3094 }
3095 return(record);
3096 }
3097
3098 // common code for U_EMRINVERTRGN and U_EMRPAINTRGN,
U_EMR_CORE11_set(uint32_t iType,PU_RGNDATA RgnData)3099 char *U_EMR_CORE11_set(uint32_t iType, PU_RGNDATA RgnData){
3100 char *record;
3101 int irecsize;
3102 int cbRgns,cbRgns4,rds,rds4,off;
3103
3104 if(!RgnData)return(NULL);
3105 cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
3106 cbRgns4 = UP4(cbRgns);
3107 rds = sizeof(U_RGNDATAHEADER) + cbRgns;
3108 rds4 = UP4(rds);
3109 irecsize = sizeof(U_EMRINVERTRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
3110 record = malloc(irecsize);
3111 if(record){
3112 ((PU_EMR) record)->iType = iType;
3113 ((PU_EMR) record)->nSize = irecsize;
3114 ((PU_EMRINVERTRGN) record)->rclBounds = ((PU_RGNDATAHEADER) RgnData)->rclBounds;
3115 ((PU_EMRINVERTRGN) record)->cbRgnData = rds;
3116 off = sizeof(U_EMRINVERTRGN) - sizeof(U_RGNDATA);
3117 memcpy(record + off, RgnData, rds);
3118 off += rds;
3119 if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
3120 }
3121 return(record);
3122 }
3123
3124
3125 // common code for U_EMRCREATEMONOBRUSH_set and U_EMRCREATEDIBPATTERNBRUSHPT_set,
U_EMR_CORE12_set(uint32_t iType,uint32_t ihBrush,uint32_t iUsage,PU_BITMAPINFO Bmi,const uint32_t cbPx,const char * Px)3126 char *U_EMR_CORE12_set(
3127 uint32_t iType,
3128 uint32_t ihBrush, // Index to place object in EMF object table (this entry must not yet exist)
3129 uint32_t iUsage, // DIBcolors Enumeration
3130 PU_BITMAPINFO Bmi, // (Optional) bitmapbuffer (U_BITMAPINFO + pixel array)
3131 const uint32_t cbPx, // Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
3132 const char *Px // (Optional) bitmapbuffer (pixel array section )
3133 ){
3134 char *record;
3135 int irecsize;
3136 int cbImage,cbImage4,cbBmi,off;
3137
3138 SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
3139
3140 irecsize = sizeof(U_EMRCREATEMONOBRUSH) + cbBmi + cbImage4;
3141 record = malloc(irecsize);
3142 if(record){
3143 ((PU_EMR) record)->iType = iType;
3144 ((PU_EMR) record)->nSize = irecsize;
3145 ((PU_EMRCREATEMONOBRUSH) record)->ihBrush = ihBrush;
3146 ((PU_EMRCREATEMONOBRUSH) record)->iUsage = iUsage;
3147 if(cbBmi){
3148 off = sizeof(U_EMRCREATEMONOBRUSH);
3149 memcpy(record + off, Bmi, cbBmi);
3150 ((PU_EMRCREATEMONOBRUSH) record)->offBmi = off;
3151 ((PU_EMRCREATEMONOBRUSH) record)->cbBmi = cbBmi;
3152 off += cbBmi;
3153 memcpy(record + off, Px, cbPx);
3154 ((PU_EMRCREATEMONOBRUSH) record)->offBits = off;
3155 ((PU_EMRCREATEMONOBRUSH) record)->cbBits = cbImage;
3156 }
3157 else {
3158 ((PU_EMRCREATEMONOBRUSH) record)->offBmi = 0;
3159 ((PU_EMRCREATEMONOBRUSH) record)->cbBmi = 0;
3160 ((PU_EMRCREATEMONOBRUSH) record)->offBits = 0;
3161 ((PU_EMRCREATEMONOBRUSH) record)->cbBits = 0;
3162 }
3163 }
3164 return(record);
3165 }
3166
3167 // common code for U_EMRBLEND_set and U_EMRTRANSPARENTBLT_set,
U_EMR_CORE13_set(uint32_t iType,U_RECTL rclBounds,U_POINTL Dest,U_POINTL cDest,U_POINTL Src,U_POINTL cSrc,U_XFORM xformSrc,U_COLORREF crBkColorSrc,uint32_t iUsageSrc,uint32_t Data,const PU_BITMAPINFO Bmi,const uint32_t cbPx,char * Px)3168 char *U_EMR_CORE13_set(
3169 uint32_t iType,
3170 U_RECTL rclBounds, // Bounding rectangle in device units
3171 U_POINTL Dest, // Destination UL corner in logical units
3172 U_POINTL cDest, // Destination width in logical units
3173 U_POINTL Src, // Source UL corner in logical units
3174 U_POINTL cSrc, // Src W & H in logical units
3175 U_XFORM xformSrc, // Transform to apply to source
3176 U_COLORREF crBkColorSrc, // Background color
3177 uint32_t iUsageSrc, // DIBcolors Enumeration
3178 uint32_t Data, // The meaning and type of this field varies, but it is always 4 bytes
3179 const PU_BITMAPINFO Bmi, // (Optional) bitmapbuffer (U_BITMAPINFO section)
3180 const uint32_t cbPx, // Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
3181 char *Px // (Optional) bitmapbuffer (pixel array section )
3182 ){
3183 char *record;
3184 int irecsize;
3185 int cbImage,cbImage4,cbBmi,off;
3186
3187 SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
3188
3189 irecsize = sizeof(U_EMRALPHABLEND) + cbBmi + cbImage4;
3190 record = malloc(irecsize);
3191 if(record){
3192 ((PU_EMR) record)->iType = iType;
3193 ((PU_EMR) record)->nSize = irecsize;
3194 ((PU_EMRALPHABLEND) record)->rclBounds = rclBounds;
3195 ((PU_EMRALPHABLEND) record)->Dest = Dest;
3196 ((PU_EMRALPHABLEND) record)->cDest = cDest;
3197 ((PU_EMRALPHABLEND) record)->Blend = *((PU_BLEND)&Data);
3198 ((PU_EMRALPHABLEND) record)->Src = Src;
3199 ((PU_EMRALPHABLEND) record)->xformSrc = xformSrc;
3200 ((PU_EMRALPHABLEND) record)->crBkColorSrc = crBkColorSrc;
3201 ((PU_EMRALPHABLEND) record)->iUsageSrc = iUsageSrc;
3202 off = sizeof(U_EMRALPHABLEND);
3203 APPEND_PXBMISRC(record, U_EMRALPHABLEND, cbBmi, Bmi, Px, cbImage, cbImage4);
3204 ((PU_EMRALPHABLEND) record)->cSrc = cSrc;
3205 }
3206 return(record);
3207 }
3208 //! @endcond
3209
3210 /* **********************************************************************************************
3211 These are the core EMR functions, each creates a particular type of record.
3212 All return these records via a char* pointer, which is NULL if the call failed.
3213 They are listed in order by the corresponding U_EMR_* index number.
3214 *********************************************************************************************** */
3215
3216 // U_EMRHEADER_set 1
3217
3218 /**
3219 \brief Allocate and construct a U_EMRHEADER record.
3220 \return pointer to U_EMRHEADER record, or NULL on error.
3221 \param rclBounds Bounding rectangle in device units
3222 \param rclFrame Bounding rectangle in 0.01 mm units
3223 \param pfmtDesc Pointer to a PixelFormatDescriptor
3224 \param nDesc number of characters in Description, will include first three '\0'
3225 \param Description Description, formatted like: text1\0text2\0\0
3226 \param szlDevice Reference device size in pixels
3227 \param szlMillimeters Reference device size in 0.01 mm
3228 \param bOpenGL nonZero if OpenGL commands are included
3229 */
U_EMRHEADER_set(const U_RECTL rclBounds,const U_RECTL rclFrame,U_PIXELFORMATDESCRIPTOR * const pfmtDesc,U_CBSTR nDesc,uint16_t * const Description,const U_SIZEL szlDevice,const U_SIZEL szlMillimeters,const uint32_t bOpenGL)3230 char *U_EMRHEADER_set(
3231 const U_RECTL rclBounds,
3232 const U_RECTL rclFrame,
3233 U_PIXELFORMATDESCRIPTOR* const pfmtDesc,
3234 U_CBSTR nDesc,
3235 uint16_t* const Description,
3236 const U_SIZEL szlDevice,
3237 const U_SIZEL szlMillimeters,
3238 const uint32_t bOpenGL
3239 ){
3240
3241 char *record;
3242 int cbPFD,cbDesc,cbDesc4;
3243 uint32_t off;
3244 int irecsize;
3245
3246 if(pfmtDesc){ cbPFD = sizeof(U_PIXELFORMATDESCRIPTOR); }
3247 else { cbPFD = 0; }
3248 if(Description){ cbDesc = 2*nDesc; } // also copy the terminator. Size is in bytes
3249 else { cbDesc = 0; }
3250 cbDesc4 = UP4(cbDesc);
3251 irecsize = sizeof(U_EMRHEADER) + cbPFD + cbDesc4;
3252 record = malloc(irecsize);
3253 if(record){
3254 off = sizeof(U_EMRHEADER);
3255 ((PU_EMR) record)->iType = U_EMR_HEADER;
3256 ((PU_EMR) record)->nSize = irecsize;
3257 ((PU_EMRHEADER) record)->rclBounds = rclBounds;
3258 ((PU_EMRHEADER) record)->rclFrame = rclFrame;
3259 ((PU_EMRHEADER) record)->dSignature = U_ENHMETA_SIGNATURE;
3260 ((PU_EMRHEADER) record)->nVersion = U_ENHMETA_VERSION;
3261 ((PU_EMRHEADER) record)->nBytes = 0; // Not known yet
3262 ((PU_EMRHEADER) record)->nRecords = 0; // Not known yet
3263 ((PU_EMRHEADER) record)->nHandles = 0; // Not known yet
3264 ((PU_EMRHEADER) record)->sReserved = 0; // Must be 0
3265 ((PU_EMRHEADER) record)->nDescription = nDesc;
3266 ((PU_EMRHEADER) record)->offDescription = 0; // may change below
3267 ((PU_EMRHEADER) record)->nPalEntries = 0; // Not known yet
3268 ((PU_EMRHEADER) record)->szlDevice = szlDevice;
3269 ((PU_EMRHEADER) record)->szlMillimeters = szlMillimeters;
3270 ((PU_EMRHEADER) record)->cbPixelFormat = cbPFD;
3271 ((PU_EMRHEADER) record)->offPixelFormat = 0; // may change below
3272 ((PU_EMRHEADER) record)->bOpenGL = bOpenGL;
3273 ((PU_EMRHEADER) record)->szlMicrometers.cx = szlMillimeters.cx*1000;
3274 ((PU_EMRHEADER) record)->szlMicrometers.cy = szlMillimeters.cy*1000;
3275 if(cbDesc4){
3276 ((PU_EMRHEADER) record)->offDescription = off;
3277 memcpy(record + off, Description, cbDesc);
3278 off += cbDesc;
3279 if(cbDesc < cbDesc4)memset(record + off,0,cbDesc4-cbDesc); // clear any unused bytes
3280 off += cbDesc4 - cbDesc;
3281 }
3282 if(cbPFD){
3283 ((PU_EMRHEADER) record)->offPixelFormat = off;
3284 memcpy(record+off,pfmtDesc,cbPFD);
3285 }
3286 }
3287 return(record);
3288 }
3289
3290 // U_EMRPOLYBEZIER_set 2
3291 /**
3292 \brief Allocate and construct a U_EMR_POLYBEZIER record.
3293 \return pointer to U_EMR_POLYBEZIER record, or NULL on error.
3294 \param rclBounds bounding rectangle in device units
3295 \param cptl Number of points to draw
3296 \param points array of points
3297 */
U_EMRPOLYBEZIER_set(const U_RECTL rclBounds,const uint32_t cptl,const U_POINTL * points)3298 char *U_EMRPOLYBEZIER_set(
3299 const U_RECTL rclBounds,
3300 const uint32_t cptl,
3301 const U_POINTL *points
3302 ){
3303 return(U_EMR_CORE1_set(U_EMR_POLYBEZIER, rclBounds, cptl, points));
3304 }
3305
3306 // U_EMRPOLYGON_set 3
3307 /**
3308 \brief Allocate and construct a U_EMR_POLYGON record.
3309 \return pointer to U_EMR_POLYGON record, or NULL on error.
3310 \param rclBounds bounding rectangle in device units
3311 \param cptl Number of points to draw
3312 \param points array of points
3313 */
U_EMRPOLYGON_set(const U_RECTL rclBounds,const uint32_t cptl,const U_POINTL * points)3314 char *U_EMRPOLYGON_set(
3315 const U_RECTL rclBounds,
3316 const uint32_t cptl,
3317 const U_POINTL *points
3318 ){
3319 return(U_EMR_CORE1_set(U_EMR_POLYGON, rclBounds, cptl, points));
3320 }
3321
3322 // U_EMRPOLYLINE_set 4
3323 /**
3324 \brief Allocate and construct a U_EMR_POLYLINE record.
3325 \return pointer to U_EMR_POLYLINE record, or NULL on error.
3326 \param rclBounds bounding rectangle in device units
3327 \param cptl Number of points to draw
3328 \param points array of points
3329 */
U_EMRPOLYLINE_set(const U_RECTL rclBounds,const uint32_t cptl,const U_POINTL * points)3330 char *U_EMRPOLYLINE_set(
3331 const U_RECTL rclBounds,
3332 const uint32_t cptl,
3333 const U_POINTL *points
3334 ){
3335 return(U_EMR_CORE1_set(U_EMR_POLYLINE, rclBounds, cptl, points));
3336 }
3337
3338 // U_EMRPOLYBEZIERTO_set 5
3339 /**
3340 \brief Allocate and construct a U_EMR_POLYBEZIERTO record.
3341 \return pointer to U_EMR_POLYBEZIERTO record, or NULL on error.
3342 \param rclBounds bounding rectangle in device units
3343 \param cptl Number of points to draw
3344 \param points array of points
3345 */
U_EMRPOLYBEZIERTO_set(const U_RECTL rclBounds,const uint32_t cptl,const U_POINTL * points)3346 char *U_EMRPOLYBEZIERTO_set(
3347 const U_RECTL rclBounds,
3348 const uint32_t cptl,
3349 const U_POINTL *points
3350 ){
3351 return(U_EMR_CORE1_set(U_EMR_POLYBEZIERTO, rclBounds, cptl, points));
3352 }
3353
3354 // U_EMRPOLYLINETO_set 6
3355 /**
3356 \brief Allocate and construct a U_EMR_POLYLINETO record.
3357 \return pointer to U_EMR_POLYLINETO record, or NULL on error.
3358 \param rclBounds bounding rectangle in device units
3359 \param cptl Number of points to draw
3360 \param points array of points
3361 */
U_EMRPOLYLINETO_set(const U_RECTL rclBounds,const uint32_t cptl,const U_POINTL * points)3362 char *U_EMRPOLYLINETO_set(
3363 const U_RECTL rclBounds,
3364 const uint32_t cptl,
3365 const U_POINTL *points
3366 ){
3367 return(U_EMR_CORE1_set(U_EMR_POLYLINETO, rclBounds, cptl, points));
3368 }
3369
3370 // U_EMRPOLYPOLYLINE_set 7
3371 /**
3372 \brief Allocate and construct a U_EMR_POLYPOLYLINE record.
3373 \return pointer to U_EMR_POLYPOLYLINE record, or NULL on error.
3374 \param rclBounds bounding rectangle in device units
3375 \param nPolys Number of elements in aPolyCounts
3376 \param aPolyCounts Number of points in each poly (sequential)
3377 \param cptl Total number of points (over all poly)
3378 \param points array of points
3379 */
U_EMRPOLYPOLYLINE_set(const U_RECTL rclBounds,const uint32_t nPolys,const uint32_t * aPolyCounts,const uint32_t cptl,const U_POINTL * points)3380 char *U_EMRPOLYPOLYLINE_set(
3381 const U_RECTL rclBounds,
3382 const uint32_t nPolys,
3383 const uint32_t *aPolyCounts,
3384 const uint32_t cptl,
3385 const U_POINTL *points
3386 ){
3387 return(U_EMR_CORE2_set(U_EMR_POLYPOLYLINE, rclBounds, nPolys, aPolyCounts,cptl, points));
3388 }
3389
3390 // U_EMRPOLYPOLYGON_set 8
3391 /**
3392 \brief Allocate and construct a U_EMR_POLYPOLYGON record.
3393 \return pointer to U_EMR_POLYPOLYGON record, or NULL on error.
3394 \param rclBounds bounding rectangle in device units
3395 \param nPolys Number of elements in aPolyCounts
3396 \param aPolyCounts Number of points in each poly (sequential)
3397 \param cptl Total number of points (over all poly)
3398 \param points array of points
3399 */
U_EMRPOLYPOLYGON_set(const U_RECTL rclBounds,const uint32_t nPolys,const uint32_t * aPolyCounts,const uint32_t cptl,const U_POINTL * points)3400 char *U_EMRPOLYPOLYGON_set(
3401 const U_RECTL rclBounds,
3402 const uint32_t nPolys,
3403 const uint32_t *aPolyCounts,
3404 const uint32_t cptl,
3405 const U_POINTL *points
3406 ){
3407 return(U_EMR_CORE2_set(U_EMR_POLYPOLYGON, rclBounds, nPolys, aPolyCounts,cptl, points));
3408 }
3409
3410 // U_EMRSETWINDOWEXTEX_set 9
3411 /**
3412 \brief Allocate and construct a U_EMR_SETWINDOWEXTEX record.
3413 \return pointer to U_EMR_SETWINDOWEXTEX record, or NULL on error.
3414 \param szlExtent H & V extent in logical units
3415 */
U_EMRSETWINDOWEXTEX_set(const U_SIZEL szlExtent)3416 char *U_EMRSETWINDOWEXTEX_set(
3417 const U_SIZEL szlExtent
3418 ){
3419 U_PAIR temp;
3420 temp.x = szlExtent.cx;
3421 temp.y = szlExtent.cy;
3422 return(U_EMR_CORE7_set(U_EMR_SETWINDOWEXTEX, temp));
3423 }
3424
3425 // U_EMRSETWINDOWORGEX_set 10
3426 /**
3427 \brief Allocate and construct a U_EMR_SETWINDOWORGEX record.
3428 \return pointer to U_EMR_SETWINDOWORGEX record, or NULL on error.
3429 \param ptlOrigin H & V origin in logical units
3430 */
U_EMRSETWINDOWORGEX_set(const U_POINTL ptlOrigin)3431 char *U_EMRSETWINDOWORGEX_set(
3432 const U_POINTL ptlOrigin
3433 ){
3434 return(U_EMR_CORE7_set(U_EMR_SETWINDOWORGEX, ptlOrigin)); // U_PAIR and U_POINTL are the same thing
3435 }
3436
3437 // U_EMRSETVIEWPORTEXTEX_set 11
3438 /**
3439 \brief Allocate and construct a U_EMR_SETVIEWPORTEXTEX record.
3440 \return pointer to U_EMR_SETVIEWPORTEXTEX record, or NULL on error.
3441 \param szlExtent H & V extent in logical units
3442 */
U_EMRSETVIEWPORTEXTEX_set(const U_SIZEL szlExtent)3443 char *U_EMRSETVIEWPORTEXTEX_set(
3444 const U_SIZEL szlExtent
3445 ){
3446 U_PAIR temp;
3447 temp.x = szlExtent.cx;
3448 temp.y = szlExtent.cy;
3449 return(U_EMR_CORE7_set(U_EMR_SETVIEWPORTEXTEX, temp));
3450 }
3451
3452 // U_EMRSETVIEWPORTORGEX_set 12
3453 /**
3454 \brief Allocate and construct a U_EMR_SETVIEWPORTORGEX record.
3455 \return pointer to U_EMR_SETVIEWPORTORGEX record, or NULL on error.
3456 \param ptlOrigin H & V origin in logical units
3457 */
U_EMRSETVIEWPORTORGEX_set(const U_POINTL ptlOrigin)3458 char *U_EMRSETVIEWPORTORGEX_set(
3459 const U_POINTL ptlOrigin
3460 ){
3461 return(U_EMR_CORE7_set(U_EMR_SETVIEWPORTORGEX, ptlOrigin)); // U_PAIR and U_POINTL are the same thing
3462 }
3463
3464 // U_EMRSETBRUSHORGEX_set 13
3465 /**
3466 \brief Allocate and construct a U_EMR_SETBRUSHORGEX record.
3467 \return pointer to U_EMR_SETBRUSHORGEX record, or NULL on error.
3468 \param ptlOrigin H & V origin in logical units
3469 */
U_EMRSETBRUSHORGEX_set(const U_POINTL ptlOrigin)3470 char *U_EMRSETBRUSHORGEX_set(
3471 const U_POINTL ptlOrigin
3472 ){
3473 return(U_EMR_CORE7_set(U_EMR_SETBRUSHORGEX, *((PU_PAIR) & ptlOrigin)));
3474 }
3475
3476 // U_EMREOF_set 14
3477 /**
3478 \brief Allocate and construct a U_EMR_EOF record.
3479 \return pointer to U_EMR_EOF record, or NULL on error.
3480 \param cbPalEntries Number of palette entries
3481 \param PalEntries (optional) array of PalEntries
3482 \param et tracking information, needed for nSizeLast calculation
3483 */
U_EMREOF_set(const U_CBPLENTRIES cbPalEntries,const PU_LOGPLTNTRY PalEntries,EMFTRACK * et)3484 char *U_EMREOF_set(
3485 const U_CBPLENTRIES cbPalEntries,
3486 const PU_LOGPLTNTRY PalEntries,
3487 EMFTRACK *et
3488 ){
3489 char *record;
3490 char *ptr;
3491 int irecsize;
3492 int cbPals; // space allocated for Palette Entries
3493 uint32_t off;
3494
3495 if(cbPalEntries && !PalEntries)return(NULL);
3496 if(!et)return(NULL);
3497 cbPals = cbPalEntries * sizeof(U_LOGPLTNTRY);
3498 irecsize = sizeof(U_EMREOF) + cbPals + sizeof(uint32_t); //invariant core, variable palette, palette byte count
3499 record = malloc(irecsize);
3500 if(record){
3501 ((PU_EMR) record)->iType = U_EMR_EOF;
3502 ((PU_EMR) record)->nSize = irecsize;
3503 ((PU_EMREOF) record)->cbPalEntries = cbPalEntries;
3504 ((PU_EMREOF) record)->offPalEntries = 0; // May be changed below
3505 off = sizeof(U_EMREOF); //start of the variable region
3506 if(cbPals){
3507 ((PU_EMREOF) record)->offPalEntries = off;
3508 memcpy(record+off,PalEntries,cbPals);
3509 off += cbPals;
3510 }
3511 ptr = record + off;
3512 *(uint32_t *)ptr = irecsize + et->used; // EMREOF nSizeLast field, not at a fixed position, cannot be accessed by field name
3513 }
3514 et->PalEntries = cbPalEntries;
3515 return(record);
3516 }
3517
3518
3519 // U_EMRSETPIXELV_set 15
3520 /**
3521 \brief Allocate and construct a U_EMR_SETPIXELV record.
3522 \return pointer to U_EMR_SETPIXELV record, or NULL on error.
3523 \param ptlPixel Pixel coordinates (logical)
3524 \param crColor Pixel color
3525 */
U_EMRSETPIXELV_set(const U_POINTL ptlPixel,const U_COLORREF crColor)3526 char *U_EMRSETPIXELV_set(
3527 const U_POINTL ptlPixel,
3528 const U_COLORREF crColor
3529 ){
3530 char *record;
3531 int irecsize;
3532
3533 irecsize = sizeof(U_EMRSETPIXELV);
3534 record = malloc(irecsize);
3535 if(record){
3536 ((PU_EMR) record)->iType = U_EMR_SETPIXELV;
3537 ((PU_EMR) record)->nSize = irecsize;
3538 ((PU_EMRSETPIXELV)record)->ptlPixel = ptlPixel;
3539 ((PU_EMRSETPIXELV)record)->crColor = crColor;
3540 }
3541 return(record);
3542 }
3543
3544
3545 // U_EMRSETMAPPERFLAGS_set 16
3546 /**
3547 \brief Allocate and construct a U_EMR_SETMAPPERFLAGS record.
3548 \return pointer to U_EMR_SETMAPPERFLAGS record, or NULL on error.
3549 */
U_EMRSETMAPPERFLAGS_set(void)3550 char *U_EMRSETMAPPERFLAGS_set(void){
3551 char *record;
3552 int irecsize;
3553
3554 irecsize = sizeof(U_EMRSETMAPPERFLAGS);
3555 record = malloc(irecsize);
3556 if(record){
3557 ((PU_EMR) record)->iType = U_EMR_SETMAPPERFLAGS;
3558 ((PU_EMR) record)->nSize = irecsize;
3559 ((PU_EMRSETMAPPERFLAGS)record)->dwFlags = 1;
3560 }
3561 return(record);
3562 }
3563
3564 // U_EMRSETMAPMODE_set 17
3565 /**
3566 \brief Allocate and construct a U_EMR_SETMAPMODE record.
3567 \return pointer to U_EMR_SETMAPMODE record, or NULL on error.
3568 \param iMode MapMode Enumeration
3569 */
U_EMRSETMAPMODE_set(const uint32_t iMode)3570 char *U_EMRSETMAPMODE_set(
3571 const uint32_t iMode
3572 ){
3573 return(U_EMR_CORE3_set(U_EMR_SETMAPMODE, iMode));
3574 }
3575
3576 // U_EMRSETBKMODE_set 18
3577 /**
3578 \brief Allocate and construct a U_EMR_SETBKMODE record.
3579 \return pointer to U_EMR_SETBKMODE record, or NULL on error.
3580 \param iMode BackgroundMode Enumeration
3581 */
U_EMRSETBKMODE_set(const uint32_t iMode)3582 char *U_EMRSETBKMODE_set(
3583 const uint32_t iMode
3584 ){
3585 return(U_EMR_CORE3_set(U_EMR_SETBKMODE, iMode));
3586 }
3587
3588 // U_EMRSETPOLYFILLMODE_set 19
3589 /**
3590 \brief Allocate and construct a U_EMR_SETPOLYFILLMODE record.
3591 \return pointer to U_EMR_SETPOLYFILLMODE record, or NULL on error.
3592 \param iMode PolygonFillMode Enumeration
3593 */
U_EMRSETPOLYFILLMODE_set(const uint32_t iMode)3594 char *U_EMRSETPOLYFILLMODE_set(
3595 const uint32_t iMode
3596 ){
3597 return(U_EMR_CORE3_set(U_EMR_SETPOLYFILLMODE, iMode));
3598 }
3599
3600 // U_EMRSETROP2_set 20
3601 /**
3602 \brief Allocate and construct a U_EMR_SETROP2 record.
3603 \return pointer to U_EMR_SETROP2 record, or NULL on error.
3604 \param iMode RasterOperation2 Enumeration
3605 */
U_EMRSETROP2_set(const uint32_t iMode)3606 char *U_EMRSETROP2_set(
3607 const uint32_t iMode
3608 ){
3609 return(U_EMR_CORE3_set(U_EMR_SETROP2, iMode));
3610 }
3611
3612 // U_EMRSETSTRETCHBLTMODE_set 21
3613 /**
3614 \brief Allocate and construct a U_EMR_SETSTRETCHBLTMODE record.
3615 \return pointer to U_EMR_SETSTRETCHBLTMODE record, or NULL on error.
3616 \param iMode StretchMode Enumeration
3617 */
U_EMRSETSTRETCHBLTMODE_set(const uint32_t iMode)3618 char *U_EMRSETSTRETCHBLTMODE_set(
3619 const uint32_t iMode
3620 ){
3621 return(U_EMR_CORE3_set(U_EMR_SETSTRETCHBLTMODE, iMode));
3622 }
3623
3624 // U_EMRSETTEXTALIGN_set 22
3625 /**
3626 \brief Allocate and construct a U_EMR_SETTEXTALIGN record.
3627 \return pointer to U_EMR_SETTEXTALIGN record, or NULL on error.
3628 \param iMode TextAlignment Enumeration
3629 */
U_EMRSETTEXTALIGN_set(const uint32_t iMode)3630 char *U_EMRSETTEXTALIGN_set(
3631 const uint32_t iMode
3632 ){
3633 return(U_EMR_CORE3_set(U_EMR_SETTEXTALIGN, iMode));
3634 }
3635
3636 // U_EMRSETCOLORADJUSTMENT_set 23
3637 /**
3638 \brief Allocate and construct a U_EMR_SETCOLORADJUSTMENT record.
3639 \return pointer to U_EMR_SETCOLORADJUSTMENT record, or NULL on error.
3640 \param ColorAdjustment Color Adjustment
3641 */
U_EMRSETCOLORADJUSTMENT_set(const U_COLORADJUSTMENT ColorAdjustment)3642 char *U_EMRSETCOLORADJUSTMENT_set(
3643 const U_COLORADJUSTMENT ColorAdjustment
3644 ){
3645 char *record;
3646 int irecsize;
3647
3648 irecsize = sizeof(U_EMRSETCOLORADJUSTMENT);
3649 record = malloc(irecsize);
3650 if(record){
3651 ((PU_EMR) record)->iType = U_EMR_SETCOLORADJUSTMENT;
3652 ((PU_EMR) record)->nSize = irecsize;
3653 ((PU_EMRSETCOLORADJUSTMENT) record)->ColorAdjustment = ColorAdjustment;
3654 }
3655 return(record);
3656 }
3657
3658 // U_EMRSETTEXTCOLOR_set 24
3659 /**
3660 \brief Allocate and construct a U_EMR_SETTEXTCOLOR record.
3661 \return pointer to U_EMR_SETTEXTCOLOR record, or NULL on error.
3662 \param crColor Text Color
3663 */
U_EMRSETTEXTCOLOR_set(const U_COLORREF crColor)3664 char *U_EMRSETTEXTCOLOR_set(
3665 const U_COLORREF crColor
3666 ){
3667 return(U_EMR_CORE3_set(U_EMR_SETTEXTCOLOR, *(uint32_t *) &crColor));
3668 }
3669
3670 // U_EMRSETBKCOLOR_set 25
3671 /**
3672 \brief Allocate and construct a U_EMR_SETBKCOLOR record.
3673 \return pointer to U_EMR_SETBKCOLOR record, or NULL on error.
3674 \param crColor Background Color
3675 */
U_EMRSETBKCOLOR_set(const U_COLORREF crColor)3676 char *U_EMRSETBKCOLOR_set(
3677 const U_COLORREF crColor
3678 ){
3679 return(U_EMR_CORE3_set(U_EMR_SETBKCOLOR, *(uint32_t *) &crColor));
3680 }
3681
3682 // U_EMROFFSETCLIPRGN_set 26
3683 /**
3684 \brief Allocate and construct a U_EMR_OFFSETCLIPRGN record.
3685 \return pointer to U_EMR_OFFSETCLIPRGN record, or NULL on error.
3686 \param ptl Clipping region
3687 */
U_EMROFFSETCLIPRGN_set(const U_POINTL ptl)3688 char *U_EMROFFSETCLIPRGN_set(
3689 const U_POINTL ptl
3690 ){
3691 return(U_EMR_CORE7_set(U_EMR_OFFSETCLIPRGN, ptl));
3692 }
3693
3694 // U_EMRMOVETOEX_set 27
3695 /**
3696 \brief Allocate and construct a U_EMR_MOVETOEX record.
3697 \return pointer to U_EMR_MOVETOEX record, or NULL on error.
3698 \param ptl Point coordinates
3699 */
U_EMRMOVETOEX_set(const U_POINTL ptl)3700 char *U_EMRMOVETOEX_set(
3701 const U_POINTL ptl
3702 ){
3703 return(U_EMR_CORE7_set(U_EMR_MOVETOEX, ptl));
3704 }
3705
3706 // U_EMRSETMETARGN_set 28
3707 /**
3708 \brief Allocate and construct a U_EMR_SETMETARGN record.
3709 \return pointer to U_EMR_SETMETARGN record, or NULL on error.
3710 */
U_EMRSETMETARGN_set(void)3711 char *U_EMRSETMETARGN_set(void){
3712 return(U_EMR_CORE5_set(U_EMR_SETMETARGN));
3713 }
3714
3715 // U_EMREXCLUDECLIPRECT_set 29
3716 /**
3717 \brief Allocate and construct a U_EMR_EXCLUDECLIPRECT record.
3718 \return pointer to U_EMR_EXCLUDECLIPRECT record, or NULL on error.
3719 \param rclClip Clipping Region
3720 */
U_EMREXCLUDECLIPRECT_set(const U_RECTL rclClip)3721 char *U_EMREXCLUDECLIPRECT_set(
3722 const U_RECTL rclClip
3723 ){
3724 return(U_EMR_CORE4_set(U_EMR_EXCLUDECLIPRECT,rclClip));
3725 }
3726
3727 // U_EMRINTERSECTCLIPRECT_set 30
3728 /**
3729 \brief Allocate and construct a U_EMR_INTERSECTCLIPRECT record.
3730 \return pointer to U_EMR_INTERSECTCLIPRECT record, or NULL on error.
3731 \param rclClip Clipping Region
3732 */
U_EMRINTERSECTCLIPRECT_set(const U_RECTL rclClip)3733 char *U_EMRINTERSECTCLIPRECT_set(
3734 const U_RECTL rclClip
3735 ){
3736 return(U_EMR_CORE4_set(U_EMR_INTERSECTCLIPRECT,rclClip));
3737 }
3738
3739 // U_EMRSCALEVIEWPORTEXTEX_set 31
3740 /**
3741 \brief Allocate and construct a U_EMR_SCALEVIEWPORTEXTEX record.
3742 \return pointer to U_EMR_SCALEVIEWPORTEXTEX record, or NULL on error.
3743 \param xNum Horizontal multiplier (!=0)
3744 \param xDenom Horizontal divisor (!=0)
3745 \param yNum Vertical multiplier (!=0)
3746 \param yDenom Vertical divisor (!=0)
3747 */
U_EMRSCALEVIEWPORTEXTEX_set(const int32_t xNum,const int32_t xDenom,const int32_t yNum,const int32_t yDenom)3748 char *U_EMRSCALEVIEWPORTEXTEX_set(
3749 const int32_t xNum,
3750 const int32_t xDenom,
3751 const int32_t yNum,
3752 const int32_t yDenom
3753 ){
3754 return(U_EMR_CORE4_set(U_EMR_SCALEVIEWPORTEXTEX,(U_RECTL){xNum,xDenom,yNum,yDenom}));
3755 }
3756
3757
3758 // U_EMRSCALEWINDOWEXTEX_set 32
3759 /**
3760 \brief Allocate and construct a U_EMR_SCALEWINDOWEXTEX record.
3761 \return pointer to U_EMR_SCALEWINDOWEXTEX record, or NULL on error.
3762 \param xNum Horizontal multiplier (!=0)
3763 \param xDenom Horizontal divisor (!=0)
3764 \param yNum Vertical multiplier (!=0)
3765 \param yDenom Vertical divisor (!=0)
3766 */
U_EMRSCALEWINDOWEXTEX_set(const int32_t xNum,const int32_t xDenom,const int32_t yNum,const int32_t yDenom)3767 char *U_EMRSCALEWINDOWEXTEX_set(
3768 const int32_t xNum,
3769 const int32_t xDenom,
3770 const int32_t yNum,
3771 const int32_t yDenom
3772 ){
3773 return(U_EMR_CORE4_set(U_EMR_SCALEWINDOWEXTEX,(U_RECTL){xNum,xDenom,yNum,yDenom}));
3774 }
3775
3776 // U_EMRSAVEDC_set 33
3777 /**
3778 \brief Allocate and construct a U_EMR_SAVEDC record.
3779 \return pointer to U_EMR_SAVEDC record, or NULL on error.
3780 */
U_EMRSAVEDC_set(void)3781 char *U_EMRSAVEDC_set(void){
3782 return(U_EMR_CORE5_set(U_EMR_SAVEDC));
3783 }
3784
3785 // U_EMRRESTOREDC_set 34
3786 /**
3787 \brief Allocate and construct a U_EMR_RESTOREDC record.
3788 \return pointer to U_EMR_RESTOREDC record, or NULL on error.
3789 \param iRelative DC to restore. -1 is preceding
3790 */
U_EMRRESTOREDC_set(const int32_t iRelative)3791 char *U_EMRRESTOREDC_set(
3792 const int32_t iRelative
3793 ){
3794 return(U_EMR_CORE3_set(U_EMR_RESTOREDC, (uint32_t) iRelative));
3795 }
3796
3797 // U_EMRSETWORLDTRANSFORM_set 35
3798 /**
3799 \brief Allocate and construct a U_EMR_SETWORLDTRANSFORM record.
3800 \return pointer to U_EMR_SETWORLDTRANSFORM record, or NULL on error.
3801 \param xform Transform to use
3802 */
U_EMRSETWORLDTRANSFORM_set(const U_XFORM xform)3803 char *U_EMRSETWORLDTRANSFORM_set(
3804 const U_XFORM xform
3805 ){
3806 char *record;
3807 int irecsize;
3808
3809 irecsize = sizeof(U_EMRSETWORLDTRANSFORM);
3810 record = malloc(irecsize);
3811 if(record){
3812 ((PU_EMR) record)->iType = U_EMR_SETWORLDTRANSFORM;
3813 ((PU_EMR) record)->nSize = irecsize;
3814 ((PU_EMRSETWORLDTRANSFORM) record)->xform = xform;
3815 }
3816 return(record);
3817 }
3818
3819 // U_EMRMODIFYWORLDTRANSFORM_set 36
3820 /**
3821 \brief Allocate and construct a U_EMR_MODIFYWORLDTRANSFORM record.
3822 \return pointer to U_EMR_MODIFYWORLDTRANSFORM record, or NULL on error.
3823 \param xform Transform to use
3824 \param iMode ModifyWorldTransformMode Enumeration
3825 */
U_EMRMODIFYWORLDTRANSFORM_set(const U_XFORM xform,const uint32_t iMode)3826 char *U_EMRMODIFYWORLDTRANSFORM_set(
3827 const U_XFORM xform,
3828 const uint32_t iMode
3829 ){
3830 char *record;
3831 int irecsize;
3832
3833 irecsize = sizeof(U_EMRMODIFYWORLDTRANSFORM);
3834 record = malloc(irecsize);
3835 if(record){
3836 ((PU_EMR) record)->iType = U_EMR_MODIFYWORLDTRANSFORM;
3837 ((PU_EMR) record)->nSize = irecsize;
3838 ((PU_EMRMODIFYWORLDTRANSFORM) record)->xform = xform;
3839 ((PU_EMRMODIFYWORLDTRANSFORM) record)->iMode = iMode;
3840 }
3841 return(record);
3842 }
3843
3844 // U_EMRSELECTOBJECT_set 37
3845 /**
3846 \brief Allocate and construct a U_EMR_SELECTOBJECT record.
3847 Use selectobject_set() instead of calling this function directly.
3848 \return pointer to U_EMR_SELECTOBJECT record, or NULL on error.
3849 \param ihObject Number of a stock or created object
3850 */
U_EMRSELECTOBJECT_set(const uint32_t ihObject)3851 char *U_EMRSELECTOBJECT_set(
3852 const uint32_t ihObject
3853 ){
3854 char *record;
3855 int irecsize;
3856
3857 irecsize = sizeof(U_EMRSELECTOBJECT);
3858 record = malloc(irecsize);
3859 if(record){
3860 ((PU_EMR) record)->iType = U_EMR_SELECTOBJECT;
3861 ((PU_EMR) record)->nSize = irecsize;
3862 ((PU_EMRSELECTOBJECT) record)->ihObject = ihObject; // Index of object to SELECT
3863 }
3864 return(record);
3865 }
3866
3867 // U_EMRCREATEPEN_set 38
3868 /**
3869 \brief Allocate and construct a U_EMR_CREATEPEN record.
3870 Use createpen_set() instead of calling this function directly.
3871 \return pointer to U_EMR_CREATEPEN record, or NULL on error.
3872 \param ihPen Handle of created pen
3873 \param lopn U_LOGPEN structure describing this pen
3874 */
U_EMRCREATEPEN_set(const uint32_t ihPen,const U_LOGPEN lopn)3875 char *U_EMRCREATEPEN_set(
3876 const uint32_t ihPen,
3877 const U_LOGPEN lopn
3878 ){
3879 char *record;
3880 int irecsize=sizeof(U_EMRCREATEPEN);
3881
3882 record = malloc(irecsize);
3883 if(record){
3884 ((PU_EMR) record)->iType = U_EMR_CREATEPEN;
3885 ((PU_EMR) record)->nSize = irecsize;
3886 ((PU_EMRCREATEPEN) record)->ihPen = ihPen;
3887 ((PU_EMRCREATEPEN) record)->lopn = lopn;
3888 }
3889 return(record);
3890 }
3891
3892 // U_EMRCREATEBRUSHINDIRECT_set 39
3893 /**
3894 \brief Allocate and construct a U_EMR_CREATEBRUSHINDIRECT record.
3895 Use createbrushindirect_set() instead of calling this function directly.
3896 \return pointer to U_EMR_CREATEBRUSHINDIRECT record, or NULL on error.
3897 \param ihBrush Index to place object in EMF object table (this entry must not yet exist)
3898 \param lb Brush properties
3899 */
U_EMRCREATEBRUSHINDIRECT_set(const uint32_t ihBrush,const U_LOGBRUSH lb)3900 char *U_EMRCREATEBRUSHINDIRECT_set(
3901 const uint32_t ihBrush,
3902 const U_LOGBRUSH lb
3903 ){
3904 char *record;
3905 int irecsize;
3906
3907 irecsize = sizeof(U_EMRCREATEBRUSHINDIRECT);
3908 record = malloc(irecsize);
3909 if(record){
3910 ((PU_EMR) record)->iType = U_EMR_CREATEBRUSHINDIRECT;
3911 ((PU_EMR) record)->nSize = irecsize;
3912 ((PU_EMRCREATEBRUSHINDIRECT) record)->ihBrush = ihBrush; // Index to place object in EMF object table (this entry must not yet exist)
3913 ((PU_EMRCREATEBRUSHINDIRECT) record)->lb = lb;
3914 }
3915 return(record);
3916 }
3917
3918 // U_EMRDELETEOBJECT_set 40
3919 /**
3920 \brief Allocate and construct a U_EMR_DELETEOBJECT record.
3921 Use deleteobject_set() instead of calling this function directly.
3922 \return pointer to U_EMR_DELETEOBJECT record, or NULL on error.
3923 \param ihObject Number of a stock or created object
3924 */
U_EMRDELETEOBJECT_set(const uint32_t ihObject)3925 char *U_EMRDELETEOBJECT_set(
3926 const uint32_t ihObject
3927 ){
3928 char *record;
3929 int irecsize;
3930
3931 irecsize = sizeof(U_EMRDELETEOBJECT);
3932 record = malloc(irecsize);
3933 if(record){
3934 ((PU_EMR) record)->iType = U_EMR_DELETEOBJECT;
3935 ((PU_EMR) record)->nSize = irecsize;
3936 ((PU_EMRDELETEOBJECT) record)->ihObject = ihObject; // Index of object to DELETE
3937 }
3938 return(record);
3939 }
3940
3941 // U_EMRANGLEARC_set 41
3942 /**
3943 \brief Allocate and construct a U_EMR_ANGLEARC record.
3944 \return pointer to U_EMR_ANGLEARC record, or NULL on error.
3945 \param ptlCenter Center in logical units
3946 \param nRadius Radius in logical units
3947 \param eStartAngle Starting angle in degrees (counter clockwise from x axis)
3948 \param eSweepAngle Sweep angle in degrees
3949 */
U_EMRANGLEARC_set(const U_POINTL ptlCenter,const uint32_t nRadius,const U_FLOAT eStartAngle,const U_FLOAT eSweepAngle)3950 char *U_EMRANGLEARC_set(
3951 const U_POINTL ptlCenter,
3952 const uint32_t nRadius,
3953 const U_FLOAT eStartAngle,
3954 const U_FLOAT eSweepAngle
3955 ){
3956 char *record;
3957 int irecsize;
3958
3959 irecsize = sizeof(U_EMRANGLEARC);
3960 record = malloc(irecsize);
3961 if(record){
3962 ((PU_EMR) record)->iType = U_EMR_ANGLEARC;
3963 ((PU_EMR) record)->nSize = irecsize;
3964 ((PU_EMRANGLEARC) record)->ptlCenter = ptlCenter;
3965 ((PU_EMRANGLEARC) record)->nRadius = nRadius;
3966 ((PU_EMRANGLEARC) record)->eStartAngle = eStartAngle;
3967 ((PU_EMRANGLEARC) record)->eSweepAngle = eSweepAngle;
3968 }
3969 return(record);
3970 }
3971
3972 // U_EMRELLIPSE_set 42
3973 /**
3974 \brief Allocate and construct a U_EMR_ELLIPSE record.
3975 \return pointer to U_EMR_ELLIPSE record, or NULL on error.
3976 \param rclBox bounding rectangle in logical units
3977 */
U_EMRELLIPSE_set(const U_RECTL rclBox)3978 char *U_EMRELLIPSE_set(
3979 const U_RECTL rclBox
3980 ){
3981 return(U_EMR_CORE4_set(U_EMR_ELLIPSE,rclBox));
3982 }
3983
3984 // U_EMRRECTANGLE_set 43
3985 /**
3986 \brief Allocate and construct a U_EMR_RECTANGLE record.
3987 \return pointer to U_EMR_RECTANGLE record, or NULL on error.
3988 \param rclBox bounding rectangle in logical units
3989 */
U_EMRRECTANGLE_set(const U_RECTL rclBox)3990 char *U_EMRRECTANGLE_set(
3991 const U_RECTL rclBox
3992 ){
3993 return(U_EMR_CORE4_set(U_EMR_RECTANGLE,rclBox));
3994 }
3995
3996 // U_EMRROUNDRECT_set 44
3997 /**
3998 \brief Allocate and construct a U_EMR_ROUNDRECT record.
3999 \return pointer to U_EMR_ROUNDRECT record, or NULL on error.
4000 \param rclBox bounding rectangle in logical units
4001 \param szlCorner W & H in logical units of ellipse used to round corner
4002 */
U_EMRROUNDRECT_set(const U_RECTL rclBox,const U_SIZEL szlCorner)4003 char *U_EMRROUNDRECT_set(
4004 const U_RECTL rclBox,
4005 const U_SIZEL szlCorner
4006 ){
4007 char *record;
4008 int irecsize;
4009
4010 irecsize = sizeof(U_EMRROUNDRECT);
4011 record = malloc(irecsize);
4012 if(record){
4013 ((PU_EMR) record)->iType = U_EMR_ROUNDRECT;
4014 ((PU_EMR) record)->nSize = irecsize;
4015 ((PU_EMRROUNDRECT) record)->rclBox = rclBox;
4016 ((PU_EMRROUNDRECT) record)->szlCorner = szlCorner;
4017 }
4018 return(record);
4019 }
4020
4021 // U_EMRARC_set 45
4022 /**
4023 \brief Allocate and construct a U_EMR_ARC record.
4024 \return pointer to U_EMR_ARC record, or NULL on error.
4025 \param rclBox bounding rectangle in logical units
4026 \param ptlStart Start point in logical units
4027 \param ptlEnd End point in logical units
4028 */
U_EMRARC_set(const U_RECTL rclBox,const U_POINTL ptlStart,const U_POINTL ptlEnd)4029 char *U_EMRARC_set(
4030 const U_RECTL rclBox,
4031 const U_POINTL ptlStart,
4032 const U_POINTL ptlEnd
4033 ){
4034 return(U_EMR_CORE9_set(U_EMR_ARC,rclBox, ptlStart, ptlEnd));
4035 }
4036
4037 // U_EMRCHORD_set 46
4038 /**
4039 \brief Allocate and construct a U_EMR_CHORD record.
4040 \return pointer to U_EMR_CHORD record, or NULL on error.
4041 \param rclBox bounding rectangle in logical units
4042 \param ptlStart Start point in logical units
4043 \param ptlEnd End point in logical units
4044 */
U_EMRCHORD_set(const U_RECTL rclBox,const U_POINTL ptlStart,const U_POINTL ptlEnd)4045 char *U_EMRCHORD_set(
4046 const U_RECTL rclBox,
4047 const U_POINTL ptlStart,
4048 const U_POINTL ptlEnd
4049 ){
4050 return(U_EMR_CORE9_set(U_EMR_CHORD,rclBox, ptlStart, ptlEnd));
4051 }
4052
4053 // U_EMRPIE_set 47
4054 /**
4055 \brief Allocate and construct a U_EMR_PIE record.
4056 \return pointer to U_EMR_PIE record, or NULL on error.
4057 \param rclBox bounding rectangle in logical units
4058 \param ptlStart Start point in logical units
4059 \param ptlEnd End point in logical units
4060 */
U_EMRPIE_set(const U_RECTL rclBox,const U_POINTL ptlStart,const U_POINTL ptlEnd)4061 char *U_EMRPIE_set(
4062 const U_RECTL rclBox,
4063 const U_POINTL ptlStart,
4064 const U_POINTL ptlEnd
4065 ){
4066 return(U_EMR_CORE9_set(U_EMR_PIE,rclBox, ptlStart, ptlEnd));
4067 }
4068
4069 // U_EMRSELECTPALETTE_set 48
4070 /**
4071 \brief Allocate and construct a U_EMR_SELECTPALETTE record.
4072 \return pointer to U_EMR_SELECTPALETTE record, or NULL on error.
4073 \param ihPal Index of a Palette object in the EMF object table
4074 */
U_EMRSELECTPALETTE_set(const uint32_t ihPal)4075 char *U_EMRSELECTPALETTE_set(
4076 const uint32_t ihPal
4077 ){
4078 return(U_EMR_CORE3_set(U_EMR_SELECTPALETTE, ihPal));
4079 }
4080
4081 // U_EMRCREATEPALETTE_set 49
4082 /**
4083 \brief Allocate and construct a U_EMR_CREATEPALETTE record.
4084 Use createpalette_set() instead of calling this function directly.
4085 \return pointer to U_EMR_CREATEPALETTE record, or NULL on error.
4086 \param ihPal Index to place object in EMF object table (this entry must not yet exist)
4087 \param lgpl Palette properties
4088 */
U_EMRCREATEPALETTE_set(const uint32_t ihPal,const U_LOGPALETTE lgpl)4089 char *U_EMRCREATEPALETTE_set(
4090 const uint32_t ihPal,
4091 const U_LOGPALETTE lgpl
4092 ){
4093 char *record;
4094 int irecsize;
4095
4096 irecsize = sizeof(U_EMRCREATEPALETTE);
4097 record = malloc(irecsize);
4098 if(record){
4099 ((PU_EMR) record)->iType = U_EMR_CREATEPALETTE;
4100 ((PU_EMR) record)->nSize = irecsize;
4101 ((PU_EMRCREATEPALETTE) record)->ihPal = ihPal;
4102 ((PU_EMRCREATEPALETTE) record)->lgpl = lgpl;
4103 }
4104 return(record);
4105 }
4106
4107 // U_EMRSETPALETTEENTRIES_set 50
4108 /**
4109 \brief Allocate and construct a U_EMR_SETPALETTEENTRIES record.
4110 Use setpaletteentries_set() instead of calling this function directly.
4111 \return pointer to U_EMR_SETPALETTEENTRIES record, or NULL on error.
4112 \param ihPal Index of a Palette object in the EMF object table
4113 \param iStart First Palette entry in selected object to set
4114 \param cEntries Number of Palette entries in selected object to set
4115 \param aPalEntries Values to set with
4116 */
U_EMRSETPALETTEENTRIES_set(const uint32_t ihPal,const uint32_t iStart,const U_NUM_LOGPLTNTRY cEntries,const PU_LOGPLTNTRY aPalEntries)4117 char *U_EMRSETPALETTEENTRIES_set(
4118 const uint32_t ihPal,
4119 const uint32_t iStart,
4120 const U_NUM_LOGPLTNTRY cEntries,
4121 const PU_LOGPLTNTRY aPalEntries
4122 ){
4123 char *record;
4124 int irecsize;
4125 int cbPals;
4126
4127 if(!aPalEntries)return(NULL);
4128 cbPals = cEntries * sizeof(U_LOGPLTNTRY);
4129 irecsize = sizeof(U_EMRSETPALETTEENTRIES) + cbPals - sizeof(U_LOGPLTNTRY);
4130 record = malloc(irecsize);
4131 if(record){
4132 ((PU_EMR) record)->iType = U_EMR_SETPALETTEENTRIES;
4133 ((PU_EMR) record)->nSize = irecsize;
4134 ((PU_EMRSETPALETTEENTRIES) record)->ihPal = ihPal;
4135 ((PU_EMRSETPALETTEENTRIES) record)->iStart = iStart;
4136 ((PU_EMRSETPALETTEENTRIES) record)->cEntries = cEntries;
4137 memcpy(((PU_EMRSETPALETTEENTRIES) record)->aPalEntries, aPalEntries,cbPals);
4138 }
4139 return(record);
4140 }
4141
4142 // U_EMRRESIZEPALETTE_set 51
4143 /**
4144 \brief Allocate and construct a U_EMR_RESIZEPALETTE record.
4145 \return pointer to U_EMR_RESIZEPALETTE record, or NULL on error.
4146 \param ihPal Index of a Palette object in the EMF object table
4147 \param cEntries Number to expand or truncate the Palette entry list to
4148 */
U_EMRRESIZEPALETTE_set(const uint32_t ihPal,const uint32_t cEntries)4149 char *U_EMRRESIZEPALETTE_set(
4150 const uint32_t ihPal,
4151 const uint32_t cEntries
4152 ){
4153 return(U_EMR_CORE7_set(U_EMR_RESIZEPALETTE, (U_PAIR){ihPal,cEntries}));
4154 }
4155
4156 // U_EMRREALIZEPALETTE_set 52
4157 /**
4158 \brief Allocate and construct a U_EMR_REALIZEPALETTE record.
4159 \return pointer to U_EMR_REALIZEPALETTE record, or NULL on error.
4160 */
U_EMRREALIZEPALETTE_set(void)4161 char *U_EMRREALIZEPALETTE_set(void){
4162 return(U_EMR_CORE5_set(U_EMR_REALIZEPALETTE));
4163 }
4164
4165 // U_EMREXTFLOODFILL_set 53
4166 /**
4167 \brief Allocate and construct a U_EMR_EXTFLOODFILL record.
4168 \return pointer to U_EMR_EXTFLOODFILL record, or NULL on error.
4169 \param ptlStart Start point in logical units
4170 \param crColor Color to fill with
4171 \param iMode FloodFill Enumeration
4172 */
U_EMREXTFLOODFILL_set(const U_POINTL ptlStart,const U_COLORREF crColor,const uint32_t iMode)4173 char *U_EMREXTFLOODFILL_set(
4174 const U_POINTL ptlStart,
4175 const U_COLORREF crColor,
4176 const uint32_t iMode
4177 ){
4178 char *record;
4179 int irecsize;
4180
4181 irecsize = sizeof(U_EMREXTFLOODFILL);
4182 record = malloc(irecsize);
4183 if(record){
4184 ((PU_EMR) record)->iType = U_EMR_EXTFLOODFILL;
4185 ((PU_EMR) record)->nSize = irecsize;
4186 ((PU_EMREXTFLOODFILL) record)->ptlStart = ptlStart;
4187 ((PU_EMREXTFLOODFILL) record)->crColor = crColor;
4188 ((PU_EMREXTFLOODFILL) record)->iMode = iMode;
4189 }
4190 return(record);
4191 }
4192
4193 // U_EMRLINETO_set 54
4194 /**
4195 \brief Allocate and construct a U_EMR_LINETO record.
4196 \return pointer to U_EMR_LINETO record, or NULL on error.
4197 \param ptl Point coordinates
4198 */
U_EMRLINETO_set(const U_POINTL ptl)4199 char *U_EMRLINETO_set(
4200 const U_POINTL ptl
4201 ){
4202 return(U_EMR_CORE7_set(U_EMR_LINETO, ptl));
4203 }
4204
4205 // U_EMRARCTO_set 55
4206 /**
4207 \brief Allocate and construct a U_EMR_ARCTO record.
4208 \return pointer to U_EMR_ARCTO record, or NULL on error.
4209 \param rclBox bounding rectangle in logical units
4210 \param ptlStart Start point in logical units
4211 \param ptlEnd End point in logical units
4212
4213 Note that the draw begins with a line from the current point to ptlStart, which is
4214 not indicated in the Microsoft EMF documentation for this record.
4215 */
U_EMRARCTO_set(U_RECTL rclBox,U_POINTL ptlStart,U_POINTL ptlEnd)4216 char *U_EMRARCTO_set(
4217 U_RECTL rclBox,
4218 U_POINTL ptlStart,
4219 U_POINTL ptlEnd
4220 ){
4221 return(U_EMR_CORE9_set(U_EMR_ARCTO,rclBox, ptlStart, ptlEnd));
4222 }
4223
4224 // U_EMRPOLYDRAW_set 56
4225 /**
4226 \brief Allocate and construct a U_EMR_POLYDRAW record.
4227 \return pointer to U_EMR_POLYDRAW record, or NULL on error.
4228 \param rclBounds Bounding rectangle in device units
4229 \param cptl Number of U_POINTL objects
4230 \param aptl Array of U_POINTL objects
4231 \param abTypes Array of Point Enumeration
4232 */
U_EMRPOLYDRAW_set(const U_RECTL rclBounds,const U_NUM_POINTL cptl,const U_POINTL * aptl,const uint8_t * abTypes)4233 char *U_EMRPOLYDRAW_set(
4234 const U_RECTL rclBounds,
4235 const U_NUM_POINTL cptl,
4236 const U_POINTL *aptl,
4237 const uint8_t *abTypes
4238 ){
4239 char *record;
4240 int irecsize;
4241 int cbPoints, cbAbTypes, cbAbTypes4, off;
4242
4243 if(!cptl || !aptl || !abTypes)return(NULL);
4244 cbPoints = cptl * sizeof(U_POINTL); // space for aptl
4245 cbAbTypes = cptl; // number of abTypes (same array size, 1 byte each)
4246 cbAbTypes4 = UP4(cbAbTypes); // space for abTypes
4247 irecsize = sizeof(U_EMRPOLYDRAW) + cbPoints + cbAbTypes4 - sizeof(U_POINTL) - 1;
4248 record = malloc(irecsize);
4249 if(record){
4250 ((PU_EMR) record)->iType = U_EMR_POLYDRAW;
4251 ((PU_EMR) record)->nSize = irecsize;
4252 ((PU_EMRPOLYDRAW) record)->rclBounds = rclBounds;
4253 ((PU_EMRPOLYDRAW) record)->cptl = cptl;
4254 off = sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(uint32_t); // offset to first variable part
4255 memcpy(record+off,aptl,cbPoints);
4256 off += cbPoints;
4257 memcpy(record+off,abTypes,cbAbTypes);
4258 off += cbAbTypes;
4259 if(cbAbTypes4 > cbAbTypes){ memset(record+off,0,cbAbTypes4-cbAbTypes); } // keeps valgrind happy (initialize padding after byte array)
4260 }
4261 return(record);
4262 }
4263
4264 // U_EMRSETARCDIRECTION_set 57
4265 /**
4266 \brief Allocate and construct a U_EMR_SETARCDIRECTION record.
4267 \return pointer to U_EMR_SETARCDIRECTION record, or NULL on error.
4268 \param iArcDirection ArcDirection Enumeration
4269 */
U_EMRSETARCDIRECTION_set(const uint32_t iArcDirection)4270 char *U_EMRSETARCDIRECTION_set(
4271 const uint32_t iArcDirection
4272 ){
4273 return(U_EMR_CORE3_set(U_EMR_SETARCDIRECTION, iArcDirection));
4274 }
4275
4276 // U_EMRSETMITERLIMIT_set 58
4277 /**
4278 \brief Allocate and construct a U_EMR_SETMITERLIMIT record.
4279 \return pointer to U_EMR_SETMITERLIMIT record, or NULL on error.
4280 \param eMiterLimit MapMode Enumeration
4281 */
U_EMRSETMITERLIMIT_set(const uint32_t eMiterLimit)4282 char *U_EMRSETMITERLIMIT_set(
4283 const uint32_t eMiterLimit
4284 ){
4285 return(U_EMR_CORE3_set(U_EMR_SETMITERLIMIT, eMiterLimit));
4286 }
4287
4288
4289 // U_EMRBEGINPATH_set 59
4290 /**
4291 \brief Allocate and construct a U_EMR_BEGINPATH record.
4292 \return pointer to U_EMR_BEGINPATH record, or NULL on error.
4293 */
U_EMRBEGINPATH_set(void)4294 char *U_EMRBEGINPATH_set(void){
4295 return(U_EMR_CORE5_set(U_EMR_BEGINPATH));
4296 }
4297
4298 // U_EMRENDPATH_set 60
4299 /**
4300 \brief Allocate and construct a U_EMR_ENDPATH record.
4301 \return pointer to U_EMR_ENDPATH record, or NULL on error.
4302 */
U_EMRENDPATH_set(void)4303 char *U_EMRENDPATH_set(void){
4304 return(U_EMR_CORE5_set(U_EMR_ENDPATH));
4305 }
4306
4307 // U_EMRCLOSEFIGURE_set 61
4308 /**
4309 \brief Allocate and construct a U_EMR_CLOSEFIGURE record.
4310 \return pointer to U_EMR_CLOSEFIGURE record, or NULL on error.
4311 */
U_EMRCLOSEFIGURE_set(void)4312 char *U_EMRCLOSEFIGURE_set(void){
4313 return(U_EMR_CORE5_set(U_EMR_CLOSEFIGURE));
4314 }
4315
4316 // U_EMRFILLPATH_set 62
4317 /**
4318 \brief Allocate and construct a U_EMR_FILLPATH record.
4319 \return pointer to U_EMR_FILLPATH record, or NULL on error.
4320 \param rclBox Bounding rectangle in device units
4321
4322 U_EMR_FILLPATH closes the open figure before filling.
4323 */
U_EMRFILLPATH_set(const U_RECTL rclBox)4324 char *U_EMRFILLPATH_set(
4325 const U_RECTL rclBox
4326 ){
4327 return(U_EMR_CORE4_set(U_EMR_FILLPATH,rclBox));
4328 }
4329
4330 // U_EMRSTROKEANDFILLPATH_set 63
4331 /**
4332 \brief Allocate and construct a U_EMR_STROKEANDFILLPATH record.
4333 \return pointer to U_EMR_STROKEANDFILLPATH record, or NULL on error.
4334 \param rclBox Bounding rectangle in device units
4335
4336 U_EMR_STROKEANDFILLPATH closes the open figure before filling and stroking.
4337 There appears to be no way to fill an open path while stroking it, as any one
4338 of U_EMRFILLPATH, U_EMRSTROKEPATH, or U_EMRSTROKEANDFILEPATH will "use up" the path,
4339 */
U_EMRSTROKEANDFILLPATH_set(const U_RECTL rclBox)4340 char *U_EMRSTROKEANDFILLPATH_set(
4341 const U_RECTL rclBox
4342 ){
4343 return(U_EMR_CORE4_set(U_EMR_STROKEANDFILLPATH,rclBox));
4344 }
4345
4346 // U_EMRSTROKEPATH_set 64
4347 /**
4348 \brief Allocate and construct a U_EMR_STROKEPATH record.
4349 \return pointer to U_EMR_STROKEPATH record, or NULL on error.
4350 \param rclBox Bounding rectangle in device units
4351
4352 U_EMR_STROKEPATH does NOT close the open figure before stroking it.
4353 */
U_EMRSTROKEPATH_set(const U_RECTL rclBox)4354 char *U_EMRSTROKEPATH_set(
4355 const U_RECTL rclBox
4356 ){
4357 return(U_EMR_CORE4_set(U_EMR_STROKEPATH,rclBox));
4358 }
4359
4360 // U_EMRFLATTENPATH_set 65
4361 /**
4362 \brief Allocate and construct a U_EMR_FLATTENPATH record.
4363 \return pointer to U_EMR_FLATTENPATH record, or NULL on error.
4364 */
U_EMRFLATTENPATH_set(void)4365 char *U_EMRFLATTENPATH_set(void){
4366 return(U_EMR_CORE5_set(U_EMR_FLATTENPATH));
4367 }
4368
4369 // U_EMRWIDENPATH_set 66
4370 /**
4371 \brief Allocate and construct a U_EMR_WIDENPATH record.
4372 \return pointer to U_EMR_WIDENPATH record, or NULL on error.
4373 */
U_EMRWIDENPATH_set(void)4374 char *U_EMRWIDENPATH_set(void){
4375 return(U_EMR_CORE5_set(U_EMR_WIDENPATH));
4376 }
4377
4378 // U_EMRSELECTCLIPPATH_set 67
4379 /**
4380 \brief Allocate and construct a U_EMR_SELECTCLIPPATH record.
4381 \return pointer to U_EMR_SELECTCLIPPATH record, or NULL on error.
4382 \param iMode RegionMode Enumeration
4383 */
U_EMRSELECTCLIPPATH_set(const uint32_t iMode)4384 char *U_EMRSELECTCLIPPATH_set(
4385 const uint32_t iMode
4386 ){
4387 return(U_EMR_CORE3_set(U_EMR_SELECTCLIPPATH, iMode));
4388 }
4389
4390 // U_EMRABORTPATH_set 68
4391 /**
4392 \brief Allocate and construct a U_EMR_ABORTPATH record.
4393 \return pointer to U_EMR_ABORTPATH record, or NULL on error.
4394 */
U_EMRABORTPATH_set(void)4395 char *U_EMRABORTPATH_set(void){
4396 return(U_EMR_CORE5_set(U_EMR_ABORTPATH));
4397 }
4398
4399 // U_EMRUNDEF69 69
4400
4401 // U_EMRCOMMENT_set 70 Comment (any binary data, interpretation is program specific)
4402 /**
4403 \brief Allocate and construct a U_EMR_COMMENT record.
4404 \return pointer to U_EMR_COMMENT record, or NULL on error.
4405 \param cbData Number of bytes in comment
4406 \param Data Comment (any binary data, interpretation is program specific)
4407 */
U_EMRCOMMENT_set(const U_CBDATA cbData,const char * Data)4408 char *U_EMRCOMMENT_set(
4409 const U_CBDATA cbData,
4410 const char *Data
4411 ){
4412 char *record;
4413 unsigned int cbData4;
4414 int irecsize;
4415
4416 cbData4 = UP4(cbData);
4417 irecsize = sizeof(U_EMR) + sizeof(U_CBDATA) + cbData4;
4418 record = malloc(irecsize);
4419 if(record){
4420 ((PU_EMR) record)->iType = U_EMR_COMMENT;
4421 ((PU_EMR) record)->nSize = irecsize;
4422 ((PU_EMRCOMMENT) record)->cbData = cbData;
4423 memcpy(record + irecsize - cbData4,Data,cbData);
4424 if(cbData4 > cbData)memset(record + irecsize - cbData4 + cbData,0,cbData4-cbData); // clear any unused bytes
4425 }
4426 return(record);
4427 }
4428
4429 // U_EMRFILLRGN_set 71
4430 /**
4431 \brief Allocate and construct a U_EMR_FILLRGN record.
4432 Use fillrgn_set() instead of calling this function directly.
4433 \return pointer to U_EMR_FILLRGN record, or NULL on error.
4434 \param rclBounds Bounding rectangle in device units
4435 \param ihBrush Index of a Brush object in the EMF object table
4436 \param RgnData Pointer to a U_RGNDATA structure
4437 */
U_EMRFILLRGN_set(const U_RECTL rclBounds,const uint32_t ihBrush,const PU_RGNDATA RgnData)4438 char *U_EMRFILLRGN_set(
4439 const U_RECTL rclBounds,
4440 const uint32_t ihBrush,
4441 const PU_RGNDATA RgnData
4442 ){
4443 char *record;
4444 int irecsize;
4445 int cbRgns,cbRgns4,rds,rds4,off;
4446
4447 if(!RgnData)return(NULL);
4448 cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
4449 cbRgns4 = UP4(cbRgns);
4450 rds = sizeof(U_RGNDATAHEADER) + cbRgns;
4451 rds4 = UP4(rds);
4452 irecsize = sizeof(U_EMRFILLRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
4453 record = malloc(irecsize);
4454 if(record){
4455 ((PU_EMR) record)->iType = U_EMR_FILLRGN;
4456 ((PU_EMR) record)->nSize = irecsize;
4457 ((PU_EMRFILLRGN) record)->rclBounds = rclBounds;
4458 ((PU_EMRFILLRGN) record)->cbRgnData = rds;
4459 ((PU_EMRFILLRGN) record)->ihBrush = ihBrush;
4460 off = sizeof(U_EMRFILLRGN) - sizeof(U_RGNDATA);
4461 memcpy(record + off, RgnData, rds);
4462 off += rds;
4463 if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
4464 }
4465 return(record);
4466 }
4467
4468 // U_EMRFRAMERGN_set 72
4469 /**
4470 \brief Allocate and construct a U_EMR_FRAMERGN record.
4471 Use framegrn_set() instead of calling this function directly.
4472 \return pointer to U_EMR_FRAMERGN record, or NULL on error.
4473 \param rclBounds Bounding rectangle in device units
4474 \param ihBrush Index of a Brush object in the EMF object table
4475 \param szlStroke W & H of Brush stroke
4476 \param RgnData Pointer to a U_RGNDATA structure
4477 */
U_EMRFRAMERGN_set(const U_RECTL rclBounds,const uint32_t ihBrush,const U_SIZEL szlStroke,const PU_RGNDATA RgnData)4478 char *U_EMRFRAMERGN_set(
4479 const U_RECTL rclBounds,
4480 const uint32_t ihBrush,
4481 const U_SIZEL szlStroke,
4482 const PU_RGNDATA RgnData
4483 ){
4484 char *record;
4485 int irecsize;
4486 int cbRgns,cbRgns4,rds,rds4,off;
4487
4488 if(!RgnData)return(NULL);
4489 cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
4490 cbRgns4 = UP4(cbRgns);
4491 rds = sizeof(U_RGNDATAHEADER) + cbRgns;
4492 rds4 = UP4(rds);
4493 irecsize = sizeof(U_EMRFRAMERGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
4494 record = malloc(irecsize);
4495 if(record){
4496 ((PU_EMR) record)->iType = U_EMR_FRAMERGN;
4497 ((PU_EMR) record)->nSize = irecsize;
4498 ((PU_EMRFRAMERGN) record)->rclBounds = rclBounds;
4499 ((PU_EMRFRAMERGN) record)->cbRgnData = rds;
4500 ((PU_EMRFRAMERGN) record)->ihBrush = ihBrush;
4501 ((PU_EMRFRAMERGN) record)->szlStroke = szlStroke;
4502 off = sizeof(U_EMRFRAMERGN) - sizeof(U_RGNDATA);
4503 memcpy(record + off, RgnData, rds);
4504 off += rds;
4505 if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
4506 }
4507 return(record);
4508 }
4509
4510 // U_EMRINVERTRGN_set 73
4511 /**
4512 \brief Allocate and construct a U_EMR_INVERTRGN record.
4513 \return pointer to U_EMR_INVERTRGN record, or NULL on error.
4514 \param RgnData Variable size U_RGNDATA structure
4515 */
U_EMRINVERTRGN_set(const PU_RGNDATA RgnData)4516 char *U_EMRINVERTRGN_set(
4517 const PU_RGNDATA RgnData
4518 ){
4519 return(U_EMR_CORE11_set(U_EMR_INVERTRGN, RgnData));
4520 }
4521
4522 // U_EMRPAINTRGN_set 74
4523 /**
4524 \brief Allocate and construct a U_EMR_PAINTRGN record.
4525 \return pointer to U_EMR_PAINTRGN record, or NULL on error.
4526 \param RgnData Variable size U_RGNDATA structure
4527 */
U_EMRPAINTRGN_set(const PU_RGNDATA RgnData)4528 char *U_EMRPAINTRGN_set(
4529 const PU_RGNDATA RgnData
4530 ){
4531 return(U_EMR_CORE11_set(U_EMR_PAINTRGN, RgnData));
4532 }
4533
4534 // U_EMREXTSELECTCLIPRGN_set 75
4535 /**
4536 \brief Allocate and construct a U_EMR_EXTSELECTCLIPRGN record.
4537 \return pointer to U_EMR_EXTSELECTCLIPRGN or NULL on error.
4538 \param iMode RegionMode Enumeration
4539 \param RgnData Variable size U_RGNDATA structure
4540 */
U_EMREXTSELECTCLIPRGN_set(const uint32_t iMode,const PU_RGNDATA RgnData)4541 char *U_EMREXTSELECTCLIPRGN_set(
4542 const uint32_t iMode,
4543 const PU_RGNDATA RgnData
4544 ){
4545 char *record;
4546 int irecsize;
4547 int cbRgns,cbRgns4,rds,rds4,off;
4548
4549 if(!RgnData)return(NULL);
4550 cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
4551 cbRgns4 = UP4(cbRgns);
4552 rds = sizeof(U_RGNDATAHEADER) + cbRgns;
4553 rds4 = UP4(rds);
4554 irecsize = sizeof(U_EMREXTSELECTCLIPRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
4555 record = malloc(irecsize);
4556 if(record){
4557 ((PU_EMR) record)->iType = U_EMR_EXTSELECTCLIPRGN;
4558 ((PU_EMR) record)->nSize = irecsize;
4559 ((PU_EMREXTSELECTCLIPRGN) record)->cbRgnData = rds;
4560 ((PU_EMREXTSELECTCLIPRGN) record)->iMode = iMode;
4561 off = sizeof(U_EMREXTSELECTCLIPRGN) - sizeof(U_RGNDATA);
4562 memcpy(record + off, RgnData, rds);
4563 off += rds;
4564 if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
4565 }
4566 return(record);
4567 }
4568
4569 // U_EMRBITBLT_set 76
4570 /**
4571 \brief Allocate and construct a U_EMR_BITBLT record.
4572 \return pointer to U_EMR_BITBLT record, or NULL on error.
4573 \param rclBounds Bounding rectangle in device units
4574 \param Dest Destination UL corner in logical units
4575 \param cDest Destination width in logical units
4576 \param Src Source rectangle UL corner in logical units
4577 \param xformSrc Source bitmap transform (world to page coordinates)
4578 \param crBkColorSrc Source bitmap background color
4579 \param iUsageSrc DIBcolors Enumeration
4580 \param dwRop Ternary Raster Operation enumeration
4581 \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
4582 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
4583 \param Px (Optional) bitmapbuffer (pixel array section )
4584 */
U_EMRBITBLT_set(const U_RECTL rclBounds,const U_POINTL Dest,const U_POINTL cDest,const U_POINTL Src,const U_XFORM xformSrc,const U_COLORREF crBkColorSrc,const uint32_t iUsageSrc,const uint32_t dwRop,const PU_BITMAPINFO Bmi,const uint32_t cbPx,char * Px)4585 char *U_EMRBITBLT_set(
4586 const U_RECTL rclBounds,
4587 const U_POINTL Dest,
4588 const U_POINTL cDest,
4589 const U_POINTL Src,
4590 const U_XFORM xformSrc,
4591 const U_COLORREF crBkColorSrc,
4592 const uint32_t iUsageSrc,
4593 const uint32_t dwRop,
4594 const PU_BITMAPINFO Bmi,
4595 const uint32_t cbPx,
4596 char *Px
4597 ){
4598 char *record;
4599 int irecsize;
4600 int cbImage,cbImage4,cbBmi,off;
4601
4602 SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
4603 irecsize = sizeof(U_EMRBITBLT) + cbBmi + cbImage4;
4604 record = malloc(irecsize);
4605 if(record){
4606 ((PU_EMR) record)->iType = U_EMR_BITBLT;
4607 ((PU_EMR) record)->nSize = irecsize;
4608 ((PU_EMRBITBLT) record)->rclBounds = rclBounds;
4609 ((PU_EMRBITBLT) record)->Dest = Dest;
4610 ((PU_EMRBITBLT) record)->cDest = cDest;
4611 ((PU_EMRBITBLT) record)->dwRop = dwRop;
4612 ((PU_EMRBITBLT) record)->Src = Src;
4613 ((PU_EMRBITBLT) record)->xformSrc = xformSrc;
4614 ((PU_EMRBITBLT) record)->crBkColorSrc = crBkColorSrc;
4615 ((PU_EMRBITBLT) record)->iUsageSrc = iUsageSrc;
4616 off = sizeof(U_EMRBITBLT);
4617 APPEND_PXBMISRC(record, U_EMRBITBLT, cbBmi, Bmi, Px, cbImage, cbImage4);
4618 }
4619 return(record);
4620 }
4621
4622 // U_EMRSTRETCHBLT_set 77
4623 /**
4624 \brief Allocate and construct a U_EMR_STRETCHBLT record.
4625 \return pointer to U_EMR_STRETCHBLT record, or NULL on error.
4626 \param rclBounds Bounding rectangle in device units
4627 \param Dest Destination UL corner in logical units
4628 \param cDest Destination width in logical units
4629 \param Src Source UL corner in logical units
4630 \param cSrc Src W & H in logical units
4631 \param xformSrc Transform to apply to source
4632 \param crBkColorSrc Background color
4633 \param iUsageSrc DIBcolors Enumeration
4634 \param dwRop Ternary Raster Operation enumeration
4635 \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
4636 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
4637 \param Px (Optional) bitmapbuffer (pixel array section )
4638 */
U_EMRSTRETCHBLT_set(const U_RECTL rclBounds,const U_POINTL Dest,const U_POINTL cDest,const U_POINTL Src,const U_POINTL cSrc,const U_XFORM xformSrc,const U_COLORREF crBkColorSrc,const uint32_t iUsageSrc,const uint32_t dwRop,const PU_BITMAPINFO Bmi,const uint32_t cbPx,char * Px)4639 char *U_EMRSTRETCHBLT_set(
4640 const U_RECTL rclBounds,
4641 const U_POINTL Dest,
4642 const U_POINTL cDest,
4643 const U_POINTL Src,
4644 const U_POINTL cSrc,
4645 const U_XFORM xformSrc,
4646 const U_COLORREF crBkColorSrc,
4647 const uint32_t iUsageSrc,
4648 const uint32_t dwRop,
4649 const PU_BITMAPINFO Bmi,
4650 const uint32_t cbPx,
4651 char *Px
4652 ){
4653 char *record;
4654 int irecsize;
4655 int cbImage,cbImage4,cbBmi,off;
4656
4657 SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
4658
4659 irecsize = sizeof(U_EMRSTRETCHBLT) + cbBmi + cbImage4;
4660 record = malloc(irecsize);
4661 if(record){
4662 ((PU_EMR) record)->iType = U_EMR_STRETCHBLT;
4663 ((PU_EMR) record)->nSize = irecsize;
4664 ((PU_EMRSTRETCHBLT) record)->rclBounds = rclBounds;
4665 ((PU_EMRSTRETCHBLT) record)->Dest = Dest;
4666 ((PU_EMRSTRETCHBLT) record)->cDest = cDest;
4667 ((PU_EMRSTRETCHBLT) record)->dwRop = dwRop;
4668 ((PU_EMRSTRETCHBLT) record)->Src = Src;
4669 ((PU_EMRSTRETCHBLT) record)->xformSrc = xformSrc;
4670 ((PU_EMRSTRETCHBLT) record)->crBkColorSrc = crBkColorSrc;
4671 ((PU_EMRSTRETCHBLT) record)->iUsageSrc = iUsageSrc;
4672 off = sizeof(U_EMRSTRETCHBLT);
4673 APPEND_PXBMISRC(record, U_EMRSTRETCHBLT, cbBmi, Bmi, Px, cbImage, cbImage4);
4674 ((PU_EMRSTRETCHBLT) record)->cSrc = cSrc;
4675 }
4676 return(record);
4677 }
4678
4679 // U_EMRMASKBLT_set 78
4680 /**
4681 \brief Allocate and construct a U_EMR_MASKBLT record.
4682 \return pointer to U_EMR_MASKBLT record, or NULL on error.
4683 \param rclBounds Bounding rectangle in device units
4684 \param Dest Destination UL corner in logical units
4685 \param cDest Destination width in logical units
4686 \param Src Source UL corner in logical units
4687 \param xformSrc Transform to apply to source
4688 \param crBkColorSrc Background color
4689 \param iUsageSrc DIBcolors Enumeration
4690 \param Mask Mask UL corner in logical units
4691 \param iUsageMask DIBcolors Enumeration
4692 \param dwRop Ternary Raster Operation enumeration
4693 \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
4694 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
4695 \param Px (Optional) bitmapbuffer (pixel array section )
4696 \param MskBmi (Optional) bitmapbuffer (U_BITMAPINFO section)
4697 \param cbMsk Size in bytes of mask array (row stride * height, there may be some padding at the end of each row)
4698 \param Msk (Optional) bitmapbuffer (mask section )
4699 */
U_EMRMASKBLT_set(const U_RECTL rclBounds,const U_POINTL Dest,const U_POINTL cDest,const U_POINTL Src,const U_XFORM xformSrc,const U_COLORREF crBkColorSrc,const uint32_t iUsageSrc,const U_POINTL Mask,const uint32_t iUsageMask,const uint32_t dwRop,const PU_BITMAPINFO Bmi,const uint32_t cbPx,char * Px,const PU_BITMAPINFO MskBmi,const uint32_t cbMsk,char * Msk)4700 char *U_EMRMASKBLT_set(
4701 const U_RECTL rclBounds,
4702 const U_POINTL Dest,
4703 const U_POINTL cDest,
4704 const U_POINTL Src,
4705 const U_XFORM xformSrc,
4706 const U_COLORREF crBkColorSrc,
4707 const uint32_t iUsageSrc,
4708 const U_POINTL Mask,
4709 const uint32_t iUsageMask,
4710 const uint32_t dwRop,
4711 const PU_BITMAPINFO Bmi,
4712 const uint32_t cbPx,
4713 char *Px,
4714 const PU_BITMAPINFO MskBmi,
4715 const uint32_t cbMsk,
4716 char *Msk
4717 ){
4718 char *record;
4719 int irecsize;
4720 int cbImage,cbImage4,cbBmi,cbMskImage,cbMskImage4,cbMskBmi,off;
4721
4722 SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
4723 SET_CB_FROM_PXBMI(Msk,MskBmi,cbMskImage,cbMskImage4,cbMskBmi,cbMsk);
4724
4725 irecsize = sizeof(U_EMRMASKBLT) + cbBmi + cbImage4 + cbMskBmi + cbMskImage4;
4726 record = malloc(irecsize);
4727 if(record){
4728 ((PU_EMR) record)->iType = U_EMR_MASKBLT;
4729 ((PU_EMR) record)->nSize = irecsize;
4730 ((PU_EMRMASKBLT) record)->rclBounds = rclBounds;
4731 ((PU_EMRMASKBLT) record)->Dest = Dest;
4732 ((PU_EMRMASKBLT) record)->cDest = cDest;
4733 ((PU_EMRMASKBLT) record)->dwRop = dwRop;
4734 ((PU_EMRMASKBLT) record)->Src = Src;
4735 ((PU_EMRMASKBLT) record)->xformSrc = xformSrc;
4736 ((PU_EMRMASKBLT) record)->crBkColorSrc = crBkColorSrc;
4737 ((PU_EMRMASKBLT) record)->iUsageSrc = iUsageSrc;
4738 ((PU_EMRMASKBLT) record)->Mask = Mask;
4739 ((PU_EMRMASKBLT) record)->iUsageMask = iUsageMask;
4740 off = sizeof(U_EMRMASKBLT);
4741 APPEND_PXBMISRC(record, U_EMRMASKBLT, cbBmi, Bmi, Px, cbImage, cbImage4);
4742 APPEND_MSKBMISRC(record, U_EMRMASKBLT, cbMskBmi, MskBmi, Msk, cbMskImage, cbMskImage4);
4743 }
4744 return(record);
4745 }
4746
4747 // U_EMRPLGBLT_set 79
4748
4749 /**
4750 \brief Allocate and construct a U_EMRPLGBLT record.
4751 \return U_EMRPLGBLT record.
4752 \param rclBounds Bounding rectangle in device units
4753 \param aptlDst Defines parallelogram, UL, UR, LL corners, LR is derived (3 points)
4754 \param Src Source UL corner in logical units
4755 \param cSrc Source width in logical units
4756 \param xformSrc Transform to apply to source
4757 \param crBkColorSrc Background color
4758 \param iUsageSrc DIBcolors Enumeration
4759 \param Mask Mask UL corner in logical units
4760 \param iUsageMask DIBcolors Enumeration
4761 \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
4762 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
4763 \param Px (Optional) bitmapbuffer (pixel array section )
4764 \param MskBmi (Optional) bitmapbuffer (U_BITMAPINFO section)
4765 \param cbMsk Size in bytes of mask array (row stride * height, there may be some padding at the end of each row)
4766 \param Msk (Optional) bitmapbuffer (mask section )
4767 */
U_EMRPLGBLT_set(const U_RECTL rclBounds,const PU_POINTL aptlDst,const U_POINTL Src,const U_POINTL cSrc,const U_XFORM xformSrc,const U_COLORREF crBkColorSrc,const uint32_t iUsageSrc,const U_POINTL Mask,const uint32_t iUsageMask,const PU_BITMAPINFO Bmi,const uint32_t cbPx,char * Px,const PU_BITMAPINFO MskBmi,const uint32_t cbMsk,char * Msk)4768 char *U_EMRPLGBLT_set(
4769 const U_RECTL rclBounds,
4770 const PU_POINTL aptlDst,
4771 const U_POINTL Src,
4772 const U_POINTL cSrc,
4773 const U_XFORM xformSrc,
4774 const U_COLORREF crBkColorSrc,
4775 const uint32_t iUsageSrc,
4776 const U_POINTL Mask,
4777 const uint32_t iUsageMask,
4778 const PU_BITMAPINFO Bmi,
4779 const uint32_t cbPx,
4780 char *Px,
4781 const PU_BITMAPINFO MskBmi,
4782 const uint32_t cbMsk,
4783 char *Msk
4784 ){
4785 char *record;
4786 int irecsize;
4787 int cbImage,cbImage4,cbBmi,cbMskImage,cbMskImage4,cbMskBmi,off;
4788
4789 SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
4790 SET_CB_FROM_PXBMI(Msk,MskBmi,cbMskImage,cbMskImage4,cbMskBmi,cbMsk);
4791
4792 irecsize = sizeof(U_EMRPLGBLT) + cbBmi + cbImage4 + cbMskBmi + cbMskImage4;
4793 record = malloc(irecsize);
4794 if(record){
4795 ((PU_EMR) record)->iType = U_EMR_PLGBLT;
4796 ((PU_EMR) record)->nSize = irecsize;
4797 ((PU_EMRPLGBLT) record)->rclBounds = rclBounds;
4798 memcpy(((PU_EMRPLGBLT) record)->aptlDst,aptlDst,3*sizeof(U_POINTL));
4799 ((PU_EMRPLGBLT) record)->Src = Src;
4800 ((PU_EMRPLGBLT) record)->cSrc = cSrc;
4801 ((PU_EMRPLGBLT) record)->xformSrc = xformSrc;
4802 ((PU_EMRPLGBLT) record)->crBkColorSrc = crBkColorSrc;
4803 ((PU_EMRPLGBLT) record)->iUsageSrc = iUsageSrc;
4804 ((PU_EMRPLGBLT) record)->Mask = Mask;
4805 ((PU_EMRPLGBLT) record)->iUsageMask = iUsageMask;
4806 off = sizeof(U_EMRPLGBLT);
4807 APPEND_PXBMISRC(record, U_EMRPLGBLT, cbBmi, Bmi, Px, cbImage, cbImage4);
4808 APPEND_MSKBMISRC(record, U_EMRPLGBLT, cbMskBmi, MskBmi, Msk, cbMskImage, cbMskImage4);
4809 }
4810 return(record);
4811 }
4812
4813 // U_EMRSETDIBITSTODEVICE_set 80
4814 /**
4815 \brief Allocate and construct a U_EMR_SETDIBITSTODEVICE record.
4816 \return pointer to U_EMR_SETDIBITSTODEVICE record, or NULL on error.
4817 \param rclBounds Bounding rectangle in device units
4818 \param Dest Destination UL corner in logical units
4819 \param Src Source UL corner in logical units
4820 \param cSrc Source W & H in logical units
4821 \param iUsageSrc DIBColors Enumeration
4822 \param iStartScan First scan line
4823 \param cScans Number of scan lines
4824 \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
4825 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
4826 \param Px (Optional) bitmapbuffer (pixel array section )
4827 */
U_EMRSETDIBITSTODEVICE_set(const U_RECTL rclBounds,const U_POINTL Dest,const U_POINTL Src,const U_POINTL cSrc,const uint32_t iUsageSrc,const uint32_t iStartScan,const uint32_t cScans,const PU_BITMAPINFO Bmi,const uint32_t cbPx,char * Px)4828 char *U_EMRSETDIBITSTODEVICE_set(
4829 const U_RECTL rclBounds,
4830 const U_POINTL Dest,
4831 const U_POINTL Src,
4832 const U_POINTL cSrc,
4833 const uint32_t iUsageSrc,
4834 const uint32_t iStartScan,
4835 const uint32_t cScans,
4836 const PU_BITMAPINFO Bmi,
4837 const uint32_t cbPx,
4838 char *Px
4839 ){
4840 char *record;
4841 int irecsize;
4842 int cbImage,cbImage4,cbBmi,off;
4843
4844 SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
4845
4846 irecsize = sizeof(U_EMRSETDIBITSTODEVICE) + cbBmi + cbImage4;
4847 record = malloc(irecsize);
4848 if(record){
4849 ((PU_EMR) record)->iType = U_EMR_SETDIBITSTODEVICE;
4850 ((PU_EMR) record)->nSize = irecsize;
4851 ((PU_EMRSETDIBITSTODEVICE) record)->rclBounds = rclBounds;
4852 ((PU_EMRSETDIBITSTODEVICE) record)->Dest = Dest;
4853 ((PU_EMRSETDIBITSTODEVICE) record)->Src = Src;
4854 ((PU_EMRSETDIBITSTODEVICE) record)->cSrc = cSrc;
4855 ((PU_EMRSETDIBITSTODEVICE) record)->iUsageSrc = iUsageSrc;
4856 ((PU_EMRSETDIBITSTODEVICE) record)->iStartScan = iStartScan;
4857 ((PU_EMRSETDIBITSTODEVICE) record)->cScans = cScans;
4858 off = sizeof(U_EMRSETDIBITSTODEVICE);
4859 APPEND_PXBMISRC(record, U_EMRSETDIBITSTODEVICE, cbBmi, Bmi, Px, cbImage, cbImage4);
4860 }
4861 return(record);
4862 }
4863
4864 // U_EMRSTRETCHDIBITS_set 81
4865 /**
4866 \brief Allocate and construct a U_EMR_EMRSTRETCHDIBITS record.
4867 \return pointer to U_EMR_EMRSTRETCHDIBITS record, or NULL on error.
4868 \param rclBounds Bounding rectangle in device units
4869 \param Dest Destination UL corner in logical units
4870 \param cDest Destination W & H in logical units
4871 \param Src Source UL corner in logical units
4872 \param cSrc Source W & H in logical units
4873 \param iUsageSrc DIBColors Enumeration
4874 \param dwRop RasterOPeration Enumeration
4875 \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
4876 \param cbPx Size in bytes of pixel array (row STRIDE * height, there may be some padding at the end of each row)
4877 \param Px (Optional) bitmapbuffer (pixel array section )
4878 */
U_EMRSTRETCHDIBITS_set(const U_RECTL rclBounds,const U_POINTL Dest,const U_POINTL cDest,const U_POINTL Src,const U_POINTL cSrc,const uint32_t iUsageSrc,const uint32_t dwRop,const PU_BITMAPINFO Bmi,const uint32_t cbPx,char * Px)4879 char *U_EMRSTRETCHDIBITS_set(
4880 const U_RECTL rclBounds,
4881 const U_POINTL Dest,
4882 const U_POINTL cDest,
4883 const U_POINTL Src,
4884 const U_POINTL cSrc,
4885 const uint32_t iUsageSrc,
4886 const uint32_t dwRop,
4887 const PU_BITMAPINFO Bmi,
4888 const uint32_t cbPx,
4889 char *Px
4890 ){
4891 char *record;
4892 int irecsize;
4893 int cbImage,cbImage4,cbBmi,off;
4894
4895 SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
4896
4897 irecsize = sizeof(U_EMRSTRETCHDIBITS) + cbBmi + cbImage4;
4898 record = malloc(irecsize);
4899 if(record){
4900 ((PU_EMR) record)->iType = U_EMR_STRETCHDIBITS;
4901 ((PU_EMR) record)->nSize = irecsize;
4902 ((PU_EMRSTRETCHDIBITS) record)->rclBounds = rclBounds;
4903 ((PU_EMRSTRETCHDIBITS) record)->Dest = Dest;
4904 ((PU_EMRSTRETCHDIBITS) record)->Src = Src;
4905 ((PU_EMRSTRETCHDIBITS) record)->cSrc = cSrc;
4906 ((PU_EMRSTRETCHDIBITS) record)->iUsageSrc = iUsageSrc;
4907 ((PU_EMRSTRETCHDIBITS) record)->dwRop = dwRop;
4908 ((PU_EMRSTRETCHDIBITS) record)->cDest = cDest;
4909 off = sizeof(U_EMRSTRETCHDIBITS);
4910 APPEND_PXBMISRC(record, U_EMRSTRETCHDIBITS, cbBmi, Bmi, Px, cbImage, cbImage4);
4911 }
4912 return(record);
4913 }
4914
4915 // U_EMREXTCREATEFONTINDIRECTW_set 82
4916 /**
4917 \brief Allocate and construct a U_EMR_EXTCREATEFONTINDIRECTW record.
4918 Use extcreatefontindirectw_set() instead of calling this function directly.
4919 \return pointer to U_EMR_EXTCREATEFONTINDIRECTW record, or NULL on error.
4920 \param ihFont Index of the font in the EMF object table
4921 \param elf Font parameters as U_LOGFONT
4922 \param elfw Font parameters as U_LOGFONT_PANOSE
4923 */
U_EMREXTCREATEFONTINDIRECTW_set(const uint32_t ihFont,const char * elf,const char * elfw)4924 char *U_EMREXTCREATEFONTINDIRECTW_set(
4925 const uint32_t ihFont,
4926 const char * elf,
4927 const char * elfw
4928 ){
4929 char *record;
4930 const char *cptr;
4931 int irecsize;
4932 int cbLf,off;
4933
4934 if((elf && elfw) || (!elf && !elfw))return(NULL); // ONE only must be passed
4935 if(elf){ cbLf = sizeof(U_LOGFONT); cptr = elf; }
4936 else { cbLf = sizeof(U_LOGFONT_PANOSE); cptr = elfw; }
4937
4938 irecsize = sizeof(U_EMR) + sizeof(uint32_t) + cbLf;
4939 record = malloc(irecsize);
4940 if(record){
4941 ((PU_EMR) record)->iType = U_EMR_EXTCREATEFONTINDIRECTW;
4942 ((PU_EMR) record)->nSize = irecsize;
4943 ((PU_EMREXTCREATEFONTINDIRECTW) record)->ihFont = ihFont;
4944 off = sizeof(U_EMR) + sizeof(uint32_t);
4945 memcpy(record + off, cptr, cbLf); // No need to add padding for either structure
4946 }
4947 return(record);
4948 }
4949
4950 // U_EMREXTTEXTOUTA_set 83
4951 /**
4952 \brief Allocate and construct a U_EMR_EXTTEXTOUTA record.
4953 \return pointer to U_EMR_EXTTEXTOUTA record, or NULL on error.
4954 \param rclBounds Bounding rectangle in device units
4955 \param iGraphicsMode Graphics mode Enumeration
4956 \param exScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
4957 \param eyScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
4958 \param emrtext Text parameters
4959 */
U_EMREXTTEXTOUTA_set(const U_RECTL rclBounds,const uint32_t iGraphicsMode,const U_FLOAT exScale,const U_FLOAT eyScale,const PU_EMRTEXT emrtext)4960 char *U_EMREXTTEXTOUTA_set(
4961 const U_RECTL rclBounds,
4962 const uint32_t iGraphicsMode,
4963 const U_FLOAT exScale,
4964 const U_FLOAT eyScale,
4965 const PU_EMRTEXT emrtext
4966 ){
4967 return(U_EMR_CORE8_set(U_EMR_EXTTEXTOUTA,rclBounds, iGraphicsMode, exScale, eyScale,emrtext));
4968 }
4969
4970 // U_EMREXTTEXTOUTW_set 84
4971 /**
4972 \brief Allocate and construct a U_EMR_EXTTEXTOUTW record.
4973 \return pointer to U_EMR_EXTTEXTOUTW record, or NULL on error.
4974 \param rclBounds Bounding rectangle in device units
4975 \param iGraphicsMode Graphics mode Enumeration
4976 \param exScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
4977 \param eyScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
4978 \param emrtext Text parameters
4979 */
U_EMREXTTEXTOUTW_set(const U_RECTL rclBounds,const uint32_t iGraphicsMode,const U_FLOAT exScale,const U_FLOAT eyScale,const PU_EMRTEXT emrtext)4980 char *U_EMREXTTEXTOUTW_set(
4981 const U_RECTL rclBounds,
4982 const uint32_t iGraphicsMode,
4983 const U_FLOAT exScale,
4984 const U_FLOAT eyScale,
4985 const PU_EMRTEXT emrtext
4986 ){
4987 return(U_EMR_CORE8_set(U_EMR_EXTTEXTOUTW,rclBounds, iGraphicsMode, exScale, eyScale,emrtext));
4988 }
4989
4990 // U_EMRPOLYBEZIER16_set 85
4991 /**
4992 \brief Allocate and construct a U_EMR_POLYBEZIER16 record.
4993 \return pointer to U_EMR_POLYBEZIER16 record, or NULL on error.
4994 \param rclBounds Bounding rectangle in device units
4995 \param cpts Number of POINT16 in array
4996 \param points Array of POINT16
4997 */
U_EMRPOLYBEZIER16_set(const U_RECTL rclBounds,const uint32_t cpts,const U_POINT16 * points)4998 char *U_EMRPOLYBEZIER16_set(
4999 const U_RECTL rclBounds,
5000 const uint32_t cpts,
5001 const U_POINT16 *points
5002 ){
5003 return(U_EMR_CORE6_set(U_EMR_POLYBEZIER16, rclBounds, cpts, points));
5004 }
5005
5006 // U_EMRPOLYGON16_set 86
5007 /**
5008 \brief Allocate and construct a U_EMR_POLYGON16 record.
5009 \return pointer to U_EMR_POLYGON16 record, or NULL on error.
5010 \param rclBounds Bounding rectangle in device units
5011 \param cpts Number of POINT16 in array
5012 \param points Array of POINT16
5013 */
U_EMRPOLYGON16_set(const U_RECTL rclBounds,const uint32_t cpts,const U_POINT16 * points)5014 char *U_EMRPOLYGON16_set(
5015 const U_RECTL rclBounds,
5016 const uint32_t cpts,
5017 const U_POINT16 *points
5018 ){
5019 return(U_EMR_CORE6_set(U_EMR_POLYGON16, rclBounds, cpts, points));
5020 }
5021
5022 // U_EMRPOLYLINE16_set 87
5023 /**
5024 \brief Allocate and construct a U_EMR_POLYLINE16 record.
5025 \return pointer to U_EMR_POLYLINE16 record, or NULL on error.
5026 \param rclBounds Bounding rectangle in device units
5027 \param cpts Number of POINT16 in array
5028 \param points Array of POINT16
5029 */
U_EMRPOLYLINE16_set(const U_RECTL rclBounds,const uint32_t cpts,const U_POINT16 * points)5030 char *U_EMRPOLYLINE16_set(
5031 const U_RECTL rclBounds,
5032 const uint32_t cpts,
5033 const U_POINT16 *points
5034 ){
5035 return(U_EMR_CORE6_set(U_EMR_POLYLINE16, rclBounds, cpts, points));
5036 }
5037
5038 // U_EMRPOLYBEZIERTO16_set 88
5039 /**
5040 \brief Allocate and construct a U_EMR_POLYBEZIERTO record.
5041 \return pointer to U_EMR_POLYBEZIERTO record, or NULL on error.
5042 \param rclBounds Bounding rectangle in device units
5043 \param cpts Number of POINT16 in array
5044 \param points Array of POINT16
5045 */
U_EMRPOLYBEZIERTO16_set(const U_RECTL rclBounds,const uint32_t cpts,const U_POINT16 * points)5046 char *U_EMRPOLYBEZIERTO16_set(
5047 const U_RECTL rclBounds,
5048 const uint32_t cpts,
5049 const U_POINT16 *points
5050 ){
5051 return(U_EMR_CORE6_set(U_EMR_POLYBEZIERTO16, rclBounds, cpts, points));
5052 }
5053
5054 // U_EMRPOLYLINETO16_set 89
5055 /**
5056 \brief Allocate and construct a U_EMR_POLYLINETO record.
5057 \return pointer to U_EMR_POLYLINETO record, or NULL on error.
5058 \param rclBounds Bounding rectangle in device units
5059 \param cpts Number of POINT16 in array
5060 \param points Array of POINT16
5061 */
U_EMRPOLYLINETO16_set(const U_RECTL rclBounds,const uint32_t cpts,const U_POINT16 * points)5062 char *U_EMRPOLYLINETO16_set(
5063 const U_RECTL rclBounds,
5064 const uint32_t cpts,
5065 const U_POINT16 *points
5066 ){
5067 return(U_EMR_CORE6_set(U_EMR_POLYLINETO16, rclBounds, cpts, points));
5068 }
5069
5070 // U_EMRPOLYPOLYLINE16_set 90
5071 /**
5072 \brief Allocate and construct a U_EMR_POLYPOLYLINE16 record.
5073 \return pointer to U_EMR_POLYPOLYLINE16 record, or NULL on error.
5074 \param rclBounds Bounding rectangle in device units
5075 \param nPolys Number of elements in aPolyCounts
5076 \param aPolyCounts Number of points in each poly (sequential)
5077 \param cpts Number of POINT16 in array
5078 \param points Array of POINT16
5079 */
U_EMRPOLYPOLYLINE16_set(const U_RECTL rclBounds,const uint32_t nPolys,const uint32_t * aPolyCounts,const uint32_t cpts,const U_POINT16 * points)5080 char *U_EMRPOLYPOLYLINE16_set(
5081 const U_RECTL rclBounds,
5082 const uint32_t nPolys,
5083 const uint32_t *aPolyCounts,
5084 const uint32_t cpts,
5085 const U_POINT16 *points
5086 ){
5087 return(U_EMR_CORE10_set(U_EMR_POLYPOLYLINE16, rclBounds, nPolys, aPolyCounts,cpts, points));
5088 }
5089
5090 // U_EMRPOLYPOLYGON16_set 91
5091 /**
5092 \brief Allocate and construct a U_EMR_POLYPOLYGON16 record.
5093 \return pointer to U_EMR_POLYPOLYGON16 record, or NULL on error.
5094 \param rclBounds Bounding rectangle in device units
5095 \param nPolys Number of elements in aPolyCounts
5096 \param aPolyCounts Number of points in each poly (sequential)
5097 \param cpts Number of POINT16 in array
5098 \param points Array of POINT16
5099 */
U_EMRPOLYPOLYGON16_set(const U_RECTL rclBounds,const uint32_t nPolys,const uint32_t * aPolyCounts,const uint32_t cpts,const U_POINT16 * points)5100 char *U_EMRPOLYPOLYGON16_set(
5101 const U_RECTL rclBounds,
5102 const uint32_t nPolys,
5103 const uint32_t *aPolyCounts,
5104 const uint32_t cpts,
5105 const U_POINT16 *points
5106 ){
5107 return(U_EMR_CORE10_set(U_EMR_POLYPOLYGON16, rclBounds, nPolys, aPolyCounts,cpts, points));
5108 }
5109
5110
5111 // U_EMRPOLYDRAW16_set 92
5112 /**
5113 \brief Allocate and construct a U_EMR_POLYDRAW16 record.
5114 \return pointer to U_EMR_POLYDRAW16 record, or NULL on error.
5115 \param rclBounds Bounding rectangle in device units
5116 \param cpts Number of U_POINTL objects
5117 \param aptl Array of U_POINTL objects
5118 \param abTypes Array of Point Enumeration
5119 */
U_EMRPOLYDRAW16_set(const U_RECTL rclBounds,const U_NUM_POINT16 cpts,const U_POINT16 * aptl,const uint8_t * abTypes)5120 char *U_EMRPOLYDRAW16_set(
5121 const U_RECTL rclBounds,
5122 const U_NUM_POINT16 cpts,
5123 const U_POINT16 *aptl,
5124 const uint8_t *abTypes
5125 ){
5126 char *record;
5127 int irecsize;
5128 int cbPoints, cbAbTypes, cbAbTypes4, off;
5129
5130 if(!cpts || !aptl || !abTypes)return(NULL);
5131 cbPoints = cpts * sizeof(U_POINT16); // space for aptl
5132 cbAbTypes = cpts; // number of abTypes (same array size, 1 byte each)
5133 cbAbTypes4 = UP4(cbAbTypes); // space for abTypes
5134 irecsize = sizeof(U_EMRPOLYDRAW16) + cbPoints + cbAbTypes4 - sizeof(U_POINT16) - 1;
5135 record = malloc(irecsize);
5136 if(record){
5137 ((PU_EMR) record)->iType = U_EMR_POLYDRAW16;
5138 ((PU_EMR) record)->nSize = irecsize;
5139 ((PU_EMRPOLYDRAW16) record)->rclBounds = rclBounds;
5140 ((PU_EMRPOLYDRAW16) record)->cpts = cpts;
5141 off = sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(uint32_t); // offset to first variable part
5142 memcpy(record+off,aptl,cbPoints);
5143 off += cbPoints;
5144 memcpy(record+off,abTypes,cbAbTypes);
5145 off += cbAbTypes;
5146 if(cbAbTypes4 > cbAbTypes){ memset(record+off,0,cbAbTypes4-cbAbTypes); } // keeps valgrind happy (initialize padding after byte array)
5147 }
5148 return(record);
5149 }
5150
5151 // U_EMRCREATEMONOBRUSH_set 93
5152 /**
5153 \brief Allocate and construct a U_EMR_CREATEMONOBRUSH record.
5154 \return pointer to U_EMR_CREATEMONOBRUSH record, or NULL on error.
5155 \param ihBrush Index to place object in EMF object table (this entry must not yet exist)
5156 \param iUsage DIBcolors Enumeration
5157 \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO + pixel array)
5158 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
5159 \param Px (Optional) bitmapbuffer (pixel array section )
5160 */
U_EMRCREATEMONOBRUSH_set(const uint32_t ihBrush,const uint32_t iUsage,const PU_BITMAPINFO Bmi,const uint32_t cbPx,const char * Px)5161 char *U_EMRCREATEMONOBRUSH_set(
5162 const uint32_t ihBrush,
5163 const uint32_t iUsage,
5164 const PU_BITMAPINFO Bmi,
5165 const uint32_t cbPx,
5166 const char *Px
5167 ){
5168 return(U_EMR_CORE12_set(U_EMR_CREATEMONOBRUSH,ihBrush,iUsage,Bmi,cbPx,Px));
5169 }
5170
5171 // U_EMRCREATEDIBPATTERNBRUSHPT_set 94
5172 /**
5173 \brief Allocate and construct a U_EMR_CREATEDIBPATTERNBRUSHPT record.
5174 Use createdibpatternbrushpt_set() instead of calling this function directly.
5175 \return pointer to U_EMR_CREATEDIBPATTERNBRUSHPT record, or NULL on error.
5176 \param ihBrush Index to place object in EMF object table (this entry must not yet exist)
5177 \param iUsage DIBcolors Enumeration
5178 \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO + pixel array)
5179 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
5180 \param Px (Optional) bitmapbuffer (pixel array section )
5181 */
U_EMRCREATEDIBPATTERNBRUSHPT_set(const uint32_t ihBrush,const uint32_t iUsage,const PU_BITMAPINFO Bmi,const uint32_t cbPx,const char * Px)5182 char *U_EMRCREATEDIBPATTERNBRUSHPT_set(
5183 const uint32_t ihBrush,
5184 const uint32_t iUsage,
5185 const PU_BITMAPINFO Bmi,
5186 const uint32_t cbPx,
5187 const char *Px
5188 ){
5189 return(U_EMR_CORE12_set(U_EMR_CREATEDIBPATTERNBRUSHPT,ihBrush,iUsage,Bmi,cbPx,Px));
5190 }
5191
5192
5193 // U_EMREXTCREATEPEN_set 95
5194 /**
5195 \brief Allocate and construct a U_EMR_EXTCREATEPEN record.
5196 Use extcreatepen_set() instead of calling this function directly.
5197 \return pointer to U_EMR_EXTCREATEPEN record, or NULL on error.
5198 \param ihPen ihPen Index to place object in EMF object table (this entry must not yet exist)
5199 \param Bmi Bmi bitmapbuffer
5200 \param cbPx cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
5201 \param Px Px pixel array (NULL if cbPx == 0)
5202 \param elp elp Pen parameters (Size is Variable!!!!)
5203 */
U_EMREXTCREATEPEN_set(const uint32_t ihPen,const PU_BITMAPINFO Bmi,const uint32_t cbPx,char * Px,const PU_EXTLOGPEN elp)5204 char *U_EMREXTCREATEPEN_set(
5205 const uint32_t ihPen,
5206 const PU_BITMAPINFO Bmi,
5207 const uint32_t cbPx,
5208 char *Px,
5209 const PU_EXTLOGPEN elp
5210 ){
5211 char *record;
5212 int cbImage,cbImage4,cbBmi,off;
5213 int irecsize,cbStyleArray,cbElp;
5214
5215 if(!elp)return(NULL);
5216
5217 SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
5218
5219 cbStyleArray = elp->elpNumEntries * sizeof(U_STYLEENTRY); // space actually used by penstyle entries
5220 // EXTLOGPEN is already included in EMREXTCREATEPEN, including the possibly unused first penstyle entry
5221 if(cbStyleArray){
5222 cbElp = sizeof(U_EXTLOGPEN) + cbStyleArray - sizeof(U_STYLEENTRY); // space actually used by elp
5223 irecsize = sizeof(U_EMREXTCREATEPEN) + cbBmi + cbImage4 + cbStyleArray - sizeof(U_STYLEENTRY);
5224 }
5225 else {
5226 cbElp = sizeof(U_EXTLOGPEN); // first U_STYLEENTRY is present but unused
5227 irecsize = sizeof(U_EMREXTCREATEPEN) + cbBmi + cbImage4;
5228 }
5229 record = malloc(irecsize);
5230
5231 if(record){
5232 ((PU_EMR) record)->iType = U_EMR_EXTCREATEPEN;
5233 ((PU_EMR) record)->nSize = irecsize;
5234 ((PU_EMREXTCREATEPEN) record)->ihPen = ihPen;
5235 memcpy(&(((PU_EMREXTCREATEPEN) record)->elp),elp,cbElp);
5236 if(cbStyleArray){
5237 off = sizeof(U_EMREXTCREATEPEN) + cbStyleArray - sizeof(U_STYLEENTRY);
5238 }
5239 else {
5240 off = sizeof(U_EMREXTCREATEPEN);
5241 }
5242 // Cannot use APPEND_PXBMISRC here because there is no "Src" in the field names
5243 if(cbBmi){
5244 memcpy(record + off, Bmi, cbBmi);
5245 ((PU_EMREXTCREATEPEN) record)->offBmi = off;
5246 ((PU_EMREXTCREATEPEN) record)->cbBmi = cbBmi;
5247 off += cbBmi;
5248 memcpy(record + off, Px, cbImage);
5249 ((PU_EMREXTCREATEPEN) record)->offBits = off;
5250 ((PU_EMREXTCREATEPEN) record)->cbBits = cbImage;
5251 off += cbImage;
5252 if(cbImage4 - cbImage){ memset(record + off, 0, cbImage4 - cbImage); }
5253 }
5254 else {
5255 ((PU_EMREXTCREATEPEN) record)->cbBmi = 0;
5256 ((PU_EMREXTCREATEPEN) record)->offBmi = 0;
5257 ((PU_EMREXTCREATEPEN) record)->cbBits = 0;
5258 ((PU_EMREXTCREATEPEN) record)->offBits = 0;
5259 }
5260 }
5261 return(record);
5262 }
5263
5264 // U_EMRPOLYTEXTOUTA_set 96 NOT IMPLEMENTED, denigrated after Windows NT
5265 // U_EMRPOLYTEXTOUTW_set 97 NOT IMPLEMENTED, denigrated after Windows NT
5266
5267 // U_EMRSETICMMODE_set 98
5268 /**
5269 \brief Allocate and construct a U_EMR_SETICMMODE record.
5270 \return pointer to U_EMR_SETICMMODE record, or NULL on error.
5271 \param iMode ICMMode Enumeration
5272 */
U_EMRSETICMMODE_set(const uint32_t iMode)5273 char *U_EMRSETICMMODE_set(
5274 const uint32_t iMode
5275 ){
5276 return(U_EMR_CORE3_set(U_EMR_SETICMMODE, iMode));
5277 }
5278
5279 // U_EMRCREATECOLORSPACE_set 99
5280 /**
5281 \brief Allocate and construct a U_EMR_CREATECOLORSPACE record.
5282 Use createcolorspace_set() instead of calling this function directly.
5283 \return pointer to U_EMR_CREATECOLORSPACE record, or NULL on error.
5284 \param ihCS Index to place object in EMF object table (this entry must not yet exist)
5285 \param lcs ColorSpace parameters
5286 */
U_EMRCREATECOLORSPACE_set(const uint32_t ihCS,const U_LOGCOLORSPACEA lcs)5287 char *U_EMRCREATECOLORSPACE_set(
5288 const uint32_t ihCS,
5289 const U_LOGCOLORSPACEA lcs
5290 ){
5291 char *record;
5292 int irecsize;
5293
5294 irecsize = sizeof(U_EMRCREATECOLORSPACE);
5295 record = malloc(irecsize);
5296 if(record){
5297 ((PU_EMR) record)->iType = U_EMR_CREATECOLORSPACE;
5298 ((PU_EMR) record)->nSize = irecsize;
5299 ((PU_EMRCREATECOLORSPACE) record)->ihCS = ihCS;
5300 ((PU_EMRCREATECOLORSPACE) record)->lcs = lcs;
5301 }
5302 return(record);
5303 }
5304
5305 // U_EMRSETCOLORSPACE_set 100
5306 /**
5307 \brief Allocate and construct a U_EMR_SETCOLORSPACE record.
5308 \return pointer to U_EMR_SETCOLORSPACE record, or NULL on error.
5309 \param ihCS Index of object in EMF object table
5310 */
U_EMRSETCOLORSPACE_set(const uint32_t ihCS)5311 char *U_EMRSETCOLORSPACE_set(
5312 const uint32_t ihCS
5313 ){
5314 return(U_EMR_CORE3_set(U_EMR_SETCOLORSPACE, ihCS));
5315 }
5316
5317 // U_EMRDELETECOLORSPACE_set 101
5318 /**
5319 \brief Allocate and construct a U_EMR_DELETECOLORSPACE record.
5320 \return pointer to U_EMR_DELETECOLORSPACE record, or NULL on error.
5321 \param ihCS Index of object in EMF object table
5322 */
U_EMRDELETECOLORSPACE_set(const uint32_t ihCS)5323 char *U_EMRDELETECOLORSPACE_set(
5324 const uint32_t ihCS
5325 ){
5326 return(U_EMR_CORE3_set(U_EMR_DELETECOLORSPACE, ihCS));
5327 }
5328
5329 // U_EMRGLSRECORD_set 102 Not implemented
5330 // U_EMRGLSBOUNDEDRECORD_set 103 Not implemented
5331 // U_EMRPIXELFORMAT_set 104
5332 /**
5333 \brief Allocate and construct a U_EMR_PIXELFORMAT record.
5334 \return pointer to U_EMR_PIXELFORMAT record, or NULL on error.
5335 \param pfd PixelFormatDescriptor
5336 */
U_EMRPIXELFORMAT_set(const U_PIXELFORMATDESCRIPTOR pfd)5337 char *U_EMRPIXELFORMAT_set(
5338 const U_PIXELFORMATDESCRIPTOR pfd
5339 ){
5340 char *record;
5341 int irecsize;
5342
5343 irecsize = sizeof(U_EMRPIXELFORMAT);
5344 record = malloc(irecsize);
5345 if(record){
5346 ((PU_EMR) record)->iType = U_EMR_PIXELFORMAT;
5347 ((PU_EMR) record)->nSize = irecsize;
5348 ((PU_EMRPIXELFORMAT) record)->pfd = pfd;
5349 }
5350 return(record);
5351 }
5352 // U_EMRDRAWESCAPE_set 105 Not implemented
5353 // U_EMREXTESCAPE_set 106 Not implemented
5354 // U_EMRUNDEF107_set 107 Not implemented
5355
5356 // U_EMRSMALLTEXTOUT_set 108
5357 /**
5358 \brief Allocate and construct a U_EMR_SMALLTEXTOUT record.
5359 \return pointer to U_EMR_SMALLTEXTOUT record, or NULL on error.
5360 \param Dest Where to draw the text
5361 \param cChars Characters in TextString (not null terminated)
5362 \param fuOptions ExtTextOutOptions Enumeration
5363 \param iGraphicsMode GraphicsMode Enumeration
5364 \param exScale scale on X axis
5365 \param eyScale scale on Y axis
5366 \param rclBounds OPTIONAL Bounding rectangle (absent when: fuOPtions & ETO_NO_U_RECT)
5367 \param TextString text to output (fuOptions & ETO_SMALL_CHARS ? 8 bit : 16 bit)
5368 */
U_EMRSMALLTEXTOUT_set(const U_POINTL Dest,const U_NUM_STR cChars,const uint32_t fuOptions,const uint32_t iGraphicsMode,const U_FLOAT exScale,const U_FLOAT eyScale,const U_RECTL rclBounds,const char * TextString)5369 char *U_EMRSMALLTEXTOUT_set(
5370 const U_POINTL Dest,
5371 const U_NUM_STR cChars,
5372 const uint32_t fuOptions,
5373 const uint32_t iGraphicsMode,
5374 const U_FLOAT exScale,
5375 const U_FLOAT eyScale,
5376 const U_RECTL rclBounds,
5377 const char *TextString
5378 ){
5379 char *record;
5380 int irecsize,cbString,cbString4,cbRectl,off;
5381 int csize;
5382
5383 if( fuOptions & U_ETO_SMALL_CHARS ){ csize = 1; } // how many bytes per character
5384 else { csize = 2; }
5385 cbString = csize * cChars; // filled contents of the string buffer
5386 cbString4 = UP4(cbString); // size of the variable string buffer
5387 if(fuOptions & U_ETO_NO_RECT){ cbRectl = 0; } // size of the optional U_RECTL field
5388 else { cbRectl = sizeof(U_RECTL); }
5389
5390 irecsize = sizeof(U_EMRSMALLTEXTOUT) + cbString4 + cbRectl;
5391 record = malloc(irecsize);
5392 if(record){
5393 ((PU_EMR) record)->iType = U_EMR_SMALLTEXTOUT;
5394 ((PU_EMR) record)->nSize = irecsize;
5395 ((PU_EMRSMALLTEXTOUT) record)->Dest = Dest;
5396 ((PU_EMRSMALLTEXTOUT) record)->cChars = cChars;
5397 ((PU_EMRSMALLTEXTOUT) record)->fuOptions = fuOptions;
5398 ((PU_EMRSMALLTEXTOUT) record)->iGraphicsMode = iGraphicsMode;
5399 ((PU_EMRSMALLTEXTOUT) record)->exScale = exScale;
5400 ((PU_EMRSMALLTEXTOUT) record)->eyScale = eyScale;
5401 off = sizeof(U_EMRSMALLTEXTOUT); //offset to the start of the variable fields
5402 if(cbRectl){
5403 memcpy(record + off, &rclBounds, cbRectl);
5404 off += cbRectl;
5405 }
5406 memcpy(record + off, TextString, cbString);
5407 if(cbString < cbString4){
5408 off += cbString;
5409 memset(record + off, 0, cbString4 - cbString);
5410 }
5411 }
5412 return(record);
5413 }
5414
5415 // U_EMRFORCEUFIMAPPING_set 109 Not implemented
5416 // U_EMRNAMEDESCAPE_set 110 Not implemented
5417 // U_EMRCOLORCORRECTPALETTE_set 111 Not implemented
5418 // U_EMRSETICMPROFILEA_set 112 Not implemented
5419 // U_EMRSETICMPROFILEW_set 113 Not implemented
5420
5421 // U_EMRALPHABLEND_set 114
5422 /**
5423 \brief Allocate and construct a U_EMR_ALPHABLEND record.
5424 \return pointer to U_EMR_ALPHABLEND record, or NULL on error.
5425 \param rclBounds Bounding rectangle in device units
5426 \param Dest Destination UL corner in logical units
5427 \param cDest Destination width in logical units
5428 \param Src Source UL corner in logical units
5429 \param cSrc Src W & H in logical units
5430 \param xformSrc Transform to apply to source
5431 \param crBkColorSrc Background color
5432 \param iUsageSrc DIBcolors Enumeration
5433 \param Blend Blend function
5434 \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
5435 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
5436 \param Px (Optional) bitmapbuffer (pixel array section )
5437 */
U_EMRALPHABLEND_set(const U_RECTL rclBounds,const U_POINTL Dest,const U_POINTL cDest,const U_POINTL Src,const U_POINTL cSrc,const U_XFORM xformSrc,const U_COLORREF crBkColorSrc,const uint32_t iUsageSrc,const U_BLEND Blend,const PU_BITMAPINFO Bmi,const uint32_t cbPx,char * Px)5438 char *U_EMRALPHABLEND_set(
5439 const U_RECTL rclBounds,
5440 const U_POINTL Dest,
5441 const U_POINTL cDest,
5442 const U_POINTL Src,
5443 const U_POINTL cSrc,
5444 const U_XFORM xformSrc,
5445 const U_COLORREF crBkColorSrc,
5446 const uint32_t iUsageSrc,
5447 const U_BLEND Blend,
5448 const PU_BITMAPINFO Bmi,
5449 const uint32_t cbPx,
5450 char *Px
5451 ){
5452 return(U_EMR_CORE13_set(U_EMR_ALPHABLEND,rclBounds,Dest,cDest,Src,cSrc,xformSrc,crBkColorSrc,iUsageSrc,*((uint32_t *) &Blend),Bmi,cbPx,Px));
5453 }
5454
5455 // U_EMRSETLAYOUT_set 115
5456 /**
5457 \brief Allocate and construct a U_EMR_SETLAYOUT record.
5458 \return pointer to U_EMR_SETLAYOUT record, or NULL on error.
5459 \param iMode Mirroring Enumeration
5460 */
U_EMRSETLAYOUT_set(uint32_t iMode)5461 char *U_EMRSETLAYOUT_set(uint32_t iMode){
5462 return(U_EMR_CORE3_set(U_EMR_SETLAYOUT, iMode));
5463 }
5464
5465 // U_EMRTRANSPARENTBLT_set 116
5466 /**
5467 \brief Allocate and construct a U_EMR_TRANSPARENTBLT record.
5468 \return pointer to U_EMR_TRANSPARENTBLT record, or NULL on error.
5469 \param rclBounds Bounding rectangle in device units
5470 \param Dest Destination UL corner in logical units
5471 \param cDest Destination width in logical units
5472 \param Src Source UL corner in logical units
5473 \param cSrc Src W & H in logical units
5474 \param xformSrc Transform to apply to source
5475 \param crBkColorSrc Background color
5476 \param iUsageSrc DIBcolors Enumeration
5477 \param TColor Bitmap color to be treated as transparent
5478 \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
5479 \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
5480 \param Px (Optional) bitmapbuffer (pixel array section )
5481 */
U_EMRTRANSPARENTBLT_set(const U_RECTL rclBounds,const U_POINTL Dest,const U_POINTL cDest,const U_POINTL Src,const U_POINTL cSrc,const U_XFORM xformSrc,const U_COLORREF crBkColorSrc,const uint32_t iUsageSrc,const uint32_t TColor,const PU_BITMAPINFO Bmi,const uint32_t cbPx,char * Px)5482 char *U_EMRTRANSPARENTBLT_set(
5483 const U_RECTL rclBounds,
5484 const U_POINTL Dest,
5485 const U_POINTL cDest,
5486 const U_POINTL Src,
5487 const U_POINTL cSrc,
5488 const U_XFORM xformSrc,
5489 const U_COLORREF crBkColorSrc,
5490 const uint32_t iUsageSrc,
5491 const uint32_t TColor,
5492 const PU_BITMAPINFO Bmi,
5493 const uint32_t cbPx,
5494 char *Px
5495 ){
5496 return(U_EMR_CORE13_set(U_EMR_TRANSPARENTBLT,rclBounds,Dest,cDest,Src,cSrc,xformSrc,crBkColorSrc,iUsageSrc,TColor,Bmi,cbPx,Px));
5497 }
5498 // U_EMRUNDEF117_set 117 Not implemented
5499 // U_EMRGRADIENTFILL_set 118
5500 /**
5501 \brief Allocate and construct a U_EMR_TRANSPARENTBLT record.
5502 \return pointer to U_EMR_TRANSPARENTBLT record, or NULL on error.
5503 \param rclBounds Bounding rectangle in device units
5504 \param nTriVert Number of TriVertex objects in TriVert
5505 \param nGradObj Number of gradient triangle/rectangle objects
5506 \param ulMode Gradientfill Enumeration (determines Triangle/Rectangle)
5507 \param TriVert Array of TriVertex objects
5508 \param GradObj Array of gradient objects (each has 2 [rect] or 3 [triangle] indices into TriVert array)
5509
5510 There is an MS documentation or library problem for this record, as the size of the GradObj must always be set
5511 as if it was an array of U_GRADIENT3 objects for both rect and triangle. For horizontal and vertical gradients
5512 this means that there will be unused bytes at the end of the record. This is not what the documentation says,
5513 but it is how MS's libraries work.
5514
5515 */
U_EMRGRADIENTFILL_set(const U_RECTL rclBounds,const U_NUM_TRIVERTEX nTriVert,const U_NUM_GRADOBJ nGradObj,const uint32_t ulMode,const PU_TRIVERTEX TriVert,const uint32_t * GradObj)5516 char *U_EMRGRADIENTFILL_set(
5517 const U_RECTL rclBounds,
5518 const U_NUM_TRIVERTEX nTriVert,
5519 const U_NUM_GRADOBJ nGradObj,
5520 const uint32_t ulMode,
5521 const PU_TRIVERTEX TriVert,
5522 const uint32_t *GradObj
5523 ){
5524 char *record;
5525 unsigned int cbTriVert,cbGradObj,off;
5526 unsigned int cbGradObjAlloc; /* larger than cbGradObj, because of problem described above */
5527 int irecsize;
5528
5529 cbTriVert = sizeof(U_TRIVERTEX) * nTriVert; // all of the cb's will be a multiple of 4 bytes
5530 if( ulMode == U_GRADIENT_FILL_TRIANGLE){ cbGradObj = sizeof(U_GRADIENT3) * nGradObj; }
5531 else if(ulMode == U_GRADIENT_FILL_RECT_H ||
5532 ulMode == U_GRADIENT_FILL_RECT_V){ cbGradObj = sizeof(U_GRADIENT4) * nGradObj; }
5533 else { return(NULL); }
5534 cbGradObjAlloc = sizeof(U_GRADIENT3) * nGradObj;
5535
5536 irecsize = sizeof(U_EMRGRADIENTFILL) + cbTriVert + cbGradObjAlloc;
5537 record = malloc(irecsize);
5538 if(record){
5539 ((PU_EMR) record)->iType = U_EMR_GRADIENTFILL;
5540 ((PU_EMR) record)->nSize = irecsize;
5541 ((PU_EMRGRADIENTFILL) record)->rclBounds = rclBounds;
5542 ((PU_EMRGRADIENTFILL) record)->nTriVert = nTriVert;
5543 ((PU_EMRGRADIENTFILL) record)->nGradObj = nGradObj;
5544 ((PU_EMRGRADIENTFILL) record)->ulMode = ulMode;
5545 off = sizeof(U_EMRGRADIENTFILL); // offset to TriVert field
5546 memcpy(record + off, TriVert, cbTriVert);
5547 off += cbTriVert;
5548 memcpy(record + off, GradObj, cbGradObj);
5549 off += cbGradObj;
5550 if(cbGradObjAlloc > cbGradObj){
5551 memset(record+off,0,cbGradObjAlloc - cbGradObj);
5552 }
5553 }
5554 return(record);
5555 }
5556
5557 // U_EMRSETLINKEDUFIS_set 119 Not implemented
5558 // U_EMRSETTEXTJUSTIFICATION_set 120 Not implemented (denigrated)
5559 // U_EMRCOLORMATCHTOTARGETW_set 121 Not implemented
5560
5561 // U_EMRCREATECOLORSPACEW_set 122
5562 /**
5563 \brief Allocate and construct a U_EMR_CREATECOLORSPACEW record.
5564 Use createcolorspacew_set() instead of calling this function directly.
5565 \return pointer to U_EMR_CREATECOLORSPACEW record, or NULL on error.
5566 \param ihCS Index to place object in EMF object table (this entry must not yet exist)
5567 \param lcs ColorSpace parameters
5568 \param dwFlags If low bit set Data is present
5569 \param cbData Number of bytes of theData field.
5570 \param Data (Optional, dwFlags & 1) color profile data
5571 */
U_EMRCREATECOLORSPACEW_set(const uint32_t ihCS,const U_LOGCOLORSPACEW lcs,const uint32_t dwFlags,const U_CBDATA cbData,const uint8_t * Data)5572 char *U_EMRCREATECOLORSPACEW_set(
5573 const uint32_t ihCS,
5574 const U_LOGCOLORSPACEW lcs,
5575 const uint32_t dwFlags,
5576 const U_CBDATA cbData,
5577 const uint8_t *Data
5578 ){
5579 char *record;
5580 unsigned int cbData4,off;
5581 int irecsize;
5582
5583 cbData4 = UP4(cbData); // buffer to hold Data
5584 irecsize = sizeof(U_EMRCREATECOLORSPACEW) + cbData4;
5585 record = malloc(irecsize);
5586 if(record){
5587 ((PU_EMR) record)->iType = U_EMR_CREATECOLORSPACEW;
5588 ((PU_EMR) record)->nSize = irecsize;
5589 ((PU_EMRCREATECOLORSPACEW) record)->ihCS = ihCS;
5590 ((PU_EMRCREATECOLORSPACEW) record)->lcs = lcs;
5591 ((PU_EMRCREATECOLORSPACEW) record)->dwFlags = dwFlags;
5592 ((PU_EMRCREATECOLORSPACEW) record)->cbData = cbData;
5593 off = sizeof(U_EMR) + sizeof(uint32_t) + sizeof(U_LOGCOLORSPACEW) + sizeof(uint32_t) + sizeof(U_CBDATA); // offset to Data field
5594 memcpy(record + off, Data, cbData);
5595 if(cbData < cbData4){
5596 off += cbData;
5597 memset(record + off,0,cbData4-cbData);
5598 }
5599 }
5600 return(record);
5601 }
5602
5603
5604 #ifdef __cplusplus
5605 }
5606 #endif
5607