1 /* emf.c - Support for Microsoft Enhanced Metafile Format
2
3 libzint - the open source barcode library
4 Copyright (C) 2016-2017 Robin Stuart <rstuart114@gmail.com>
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name of the project nor the names of its contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 SUCH DAMAGE.
30 */
31
32 /* Developed according to [MS-EMF] - v20160714, Released July 14, 2016
33 * and [MS-WMF] - v20160714, Released July 14, 2016 */
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <math.h>
38 #include <stdlib.h>
39 #ifdef _MSC_VER
40 #include <malloc.h>
41 #endif
42 #include "common.h"
43 #include "emf.h"
44
45 #define SSET "0123456789ABCDEF"
46
count_rectangles(struct zint_symbol * symbol)47 int count_rectangles(struct zint_symbol *symbol) {
48 int rectangles = 0;
49 int this_row;
50 int latch, i;
51
52 if ((symbol->symbology != BARCODE_MAXICODE) &&
53 ((symbol->output_options & BARCODE_DOTTY_MODE) == 0)) {
54 for(this_row = 0; this_row < symbol->rows; this_row++) {
55 latch = 0;
56 for(i = 0; i < symbol->width; i++) {
57 if ((module_is_set(symbol, this_row, i)) && (latch == 0)) {
58 latch = 1;
59 rectangles++;
60 }
61
62 if ((!(module_is_set(symbol, this_row, i))) && (latch == 1)) {
63 latch = 0;
64 }
65 }
66 }
67 }
68
69 return rectangles;
70 }
71
count_circles(struct zint_symbol * symbol)72 int count_circles(struct zint_symbol *symbol) {
73 int circles = 0;
74 int this_row;
75 int i;
76
77 if ((symbol->symbology != BARCODE_MAXICODE) &&
78 ((symbol->output_options & BARCODE_DOTTY_MODE) != 0)) {
79 for(this_row = 0; this_row < symbol->rows; this_row++) {
80 for(i = 0; i < symbol->width; i++) {
81 if (module_is_set(symbol, this_row, i)) {
82 circles++;
83 }
84 }
85 }
86 }
87
88 return circles;
89 }
90
count_hexagons(struct zint_symbol * symbol)91 int count_hexagons(struct zint_symbol *symbol) {
92 int hexagons = 0;
93 int this_row;
94 int i;
95
96 if (symbol->symbology == BARCODE_MAXICODE) {
97 for(this_row = 0; this_row < symbol->rows; this_row++) {
98 for(i = 0; i < symbol->width; i++) {
99 if (module_is_set(symbol, this_row, i)) {
100 hexagons++;
101 }
102 }
103 }
104 }
105
106 return hexagons;
107 }
108
utfle_copy(unsigned char * output,unsigned char * input,int length)109 void utfle_copy(unsigned char *output, unsigned char *input, int length) {
110 int i;
111 int o;
112
113 /* Convert UTF-8 to UTF-16LE - only needs to handle characters <= U+00FF */
114 i = 0;
115 o = 0;
116 do {
117 if(input[i] <= 0x7f) {
118 /* 1 byte mode (7-bit ASCII) */
119 output[o] = input[i];
120 output[o + 1] = 0x00;
121 o += 2;
122 i++;
123 } else {
124 /* 2 byte mode */
125 output[o] = ((input[i] & 0x1f) << 6) + (input[i + 1] & 0x3f);
126 output[o + 1] = 0x00;
127 o += 2;
128 i += 2;
129 }
130 } while (i < length);
131 }
132
bump_up(int input)133 int bump_up(int input) {
134 /* Strings length must be a multiple of 4 bytes */
135 if ((input % 2) == 1) {
136 input++;
137 }
138 return input;
139 }
140
emf_plot(struct zint_symbol * symbol)141 int emf_plot(struct zint_symbol *symbol) {
142 int i, block_width, latch, this_row;
143 float large_bar_height, preset_height, row_height, row_posn;
144 FILE *emf_file;
145 int fgred, fggrn, fgblu, bgred, bggrn, bgblu;
146 int error_number = 0;
147 int textoffset, xoffset, yoffset, textdone;
148 int large_bar_count, comp_offset;
149 float scaler = symbol->scale * 10;
150 int rectangle_count, this_rectangle;
151 int circle_count, this_circle;
152 int hexagon_count, this_hexagon;
153 int bytecount, recordcount;
154 int upcean = 0;
155 unsigned char regw[7];
156 unsigned char regx[7];
157 unsigned char regy[7];
158 unsigned char regz[7];
159 unsigned char output_buffer[12];
160 uint32_t dx;
161
162 emr_header_t emr_header;
163 emr_eof_t emr_eof;
164 emr_createbrushindirect_t emr_createbrushindirect_fg;
165 emr_createbrushindirect_t emr_createbrushindirect_bg;
166 emr_selectobject_t emr_selectobject_fgbrush;
167 emr_selectobject_t emr_selectobject_bgbrush;
168 emr_createpen_t emr_createpen;
169 emr_selectobject_t emr_selectobject_pen;
170 emr_rectangle_t background;
171 emr_ellipse_t bullseye[6];
172 emr_extcreatefontindirectw_t emr_extcreatefontindirectw;
173 emr_selectobject_t emr_selectobject_font;
174 emr_exttextoutw_t emr_exttextoutw[6];
175 emr_extcreatefontindirectw_t emr_extcreatefontindirectw_big;
176 emr_selectobject_t emr_selectobject_font_big;
177
178 box_t box;
179
180 #ifndef _MSC_VER
181 unsigned char local_text[bump_up(ustrlen(symbol->text) + 1)];
182 unsigned char string_buffer[2 * bump_up(ustrlen(symbol->text) + 1)];
183 #else
184 unsigned char* local_text;
185 unsigned char* string_buffer;
186 emr_rectangle_t *rectangle, *row_binding;
187 emr_ellipse_t* circle;
188 emr_polygon_t* hexagon;
189 local_text = (unsigned char*) _alloca(bump_up(ustrlen(symbol->text) + 1) * sizeof (unsigned char));
190 string_buffer = (unsigned char*) _alloca(2 * bump_up(ustrlen(symbol->text) + 1) * sizeof (unsigned char));
191 #endif
192
193 row_height = 0;
194 textdone = 0;
195 comp_offset = 0;
196 this_rectangle = 0;
197 this_circle = 0;
198 this_hexagon = 0;
199 dx = 0;
200 latch = 0;
201
202 for(i = 0; i < 6; i++) {
203 regw[i] = '\0';
204 regx[i] = '\0';
205 regy[i] = '\0';
206 regz[i] = '\0';
207 }
208
209 if (symbol->show_hrt != 0) {
210 /* Copy text from symbol */
211 ustrcpy(local_text, symbol->text);
212 } else {
213 /* No text needed */
214 switch (symbol->symbology) {
215 case BARCODE_EANX:
216 case BARCODE_EANX_CC:
217 case BARCODE_ISBNX:
218 case BARCODE_UPCA:
219 case BARCODE_UPCE:
220 case BARCODE_UPCA_CC:
221 case BARCODE_UPCE_CC:
222 /* For these symbols use dummy text to ensure formatting is done
223 * properly even if no text is required */
224 for (i = 0; i < ustrlen(symbol->text); i++) {
225 if (symbol->text[i] == '+') {
226 local_text[i] = '+';
227 } else {
228 local_text[i] = ' ';
229 }
230 local_text[ustrlen(symbol->text)] = '\0';
231 }
232 break;
233 default:
234 /* For everything else, just remove the text */
235 local_text[0] = '\0';
236 break;
237 }
238 }
239
240 /* sort out colour options */
241 to_upper((unsigned char*) symbol->fgcolour);
242 to_upper((unsigned char*) symbol->bgcolour);
243
244 if (strlen(symbol->fgcolour) != 6) {
245 strcpy(symbol->errtxt, "641: Malformed foreground colour target");
246 return ZINT_ERROR_INVALID_OPTION;
247 }
248
249 if (strlen(symbol->bgcolour) != 6) {
250 strcpy(symbol->errtxt, "642: Malformed background colour target");
251 return ZINT_ERROR_INVALID_OPTION;
252 }
253
254 fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
255 fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
256 fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
257 bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
258 bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
259 bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);
260
261 if (symbol->height == 0) {
262 symbol->height = 50;
263 }
264
265 large_bar_count = 0;
266 preset_height = 0.0;
267 for (i = 0; i < symbol->rows; i++) {
268 preset_height += symbol->row_height[i];
269 if (symbol->row_height[i] == 0) {
270 large_bar_count++;
271 }
272 }
273 large_bar_height = (symbol->height - preset_height) / large_bar_count;
274
275 if (large_bar_count == 0) {
276 symbol->height = preset_height;
277 }
278
279 while (!(module_is_set(symbol, symbol->rows - 1, comp_offset))) {
280 comp_offset++;
281 }
282
283 /* Certain symbols need whitespace otherwise characters get chopped off the sides */
284 if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC))
285 || (symbol->symbology == BARCODE_ISBNX)) {
286 switch (ustrlen(local_text)) {
287 case 13: /* EAN 13 */
288 case 16:
289 case 19:
290 if (symbol->whitespace_width == 0) {
291 symbol->whitespace_width = 10;
292 }
293 break;
294 }
295 upcean = 1;
296 }
297
298 if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
299 if (symbol->whitespace_width == 0) {
300 symbol->whitespace_width = 10;
301 }
302 upcean = 1;
303 }
304
305 if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
306 if (symbol->whitespace_width == 0) {
307 symbol->whitespace_width = 10;
308 }
309 upcean = 1;
310 }
311
312 if (ustrlen(local_text) != 0) {
313 textoffset = 9;
314 } else {
315 textoffset = 0;
316 }
317 xoffset = symbol->border_width + symbol->whitespace_width;
318 yoffset = symbol->border_width;
319
320 rectangle_count = count_rectangles(symbol);
321 circle_count = count_circles(symbol);
322 hexagon_count = count_hexagons(symbol);
323
324 #ifndef _MSC_VER
325 emr_rectangle_t rectangle[rectangle_count];
326 emr_rectangle_t row_binding[symbol->rows - 1];
327 emr_ellipse_t circle[circle_count];
328 emr_polygon_t hexagon[hexagon_count];
329 #else
330 rectangle = (emr_rectangle_t*) _alloca(rectangle_count*sizeof(emr_rectangle_t));
331 row_binding = (emr_rectangle_t*) _alloca((symbol->rows - 1)*sizeof(emr_rectangle_t));
332 circle = (emr_ellipse_t*) _alloca(circle_count*sizeof(emr_ellipse_t));
333 hexagon = (emr_polygon_t*) _alloca(hexagon_count*sizeof(emr_polygon_t));
334 #endif
335
336 /* Header */
337 emr_header.type = 0x00000001; // EMR_HEADER
338 emr_header.size = 88; // Assuming no additional data in header
339 emr_header.emf_header.bounds.left = 0;
340 if (symbol->symbology != BARCODE_MAXICODE) {
341 emr_header.emf_header.bounds.right = ceil((symbol->width + xoffset + xoffset) * scaler);
342 emr_header.emf_header.bounds.bottom = ceil((symbol->height + textoffset + yoffset + yoffset) * scaler);
343 } else {
344 emr_header.emf_header.bounds.right = ceil((74.0F + xoffset + xoffset) * scaler);
345 emr_header.emf_header.bounds.bottom = ceil((72.0F + yoffset + yoffset) * scaler);
346 }
347 emr_header.emf_header.bounds.top = 0;
348 emr_header.emf_header.frame.left = 0;
349 emr_header.emf_header.frame.right = emr_header.emf_header.bounds.right * 30;
350 emr_header.emf_header.frame.top = 0;
351 emr_header.emf_header.frame.bottom = emr_header.emf_header.bounds.bottom * 30;
352 emr_header.emf_header.record_signature = 0x464d4520; // ENHMETA_SIGNATURE
353 emr_header.emf_header.version = 0x00010000;;
354 emr_header.emf_header.handles = 6; // Number of graphics objects
355 emr_header.emf_header.reserved = 0x0000;
356 emr_header.emf_header.n_description = 0;
357 emr_header.emf_header.off_description = 0;
358 emr_header.emf_header.n_pal_entries = 0;
359 emr_header.emf_header.device.cx = 1000;
360 emr_header.emf_header.device.cy = 1000;
361 emr_header.emf_header.millimeters.cx = 300;
362 emr_header.emf_header.millimeters.cy = 300;
363 bytecount = 88;
364 recordcount = 1;
365
366 /* Create Brushes */
367 emr_createbrushindirect_fg.type = 0x00000027; // EMR_CREATEBRUSHINDIRECT
368 emr_createbrushindirect_fg.size = 24;
369 emr_createbrushindirect_fg.ih_brush = 1;
370 emr_createbrushindirect_fg.log_brush.brush_style = 0x0000; // BS_SOLID
371 emr_createbrushindirect_fg.log_brush.color.red = fgred;
372 emr_createbrushindirect_fg.log_brush.color.green = fggrn;
373 emr_createbrushindirect_fg.log_brush.color.blue = fgblu;
374 emr_createbrushindirect_fg.log_brush.color.reserved = 0;
375 emr_createbrushindirect_fg.log_brush.brush_hatch = 0; // ignored
376 bytecount += 24;
377 recordcount++;
378
379 emr_createbrushindirect_bg.type = 0x00000027; // EMR_CREATEBRUSHINDIRECT
380 emr_createbrushindirect_bg.size = 24;
381 emr_createbrushindirect_bg.ih_brush = 2;
382 emr_createbrushindirect_bg.log_brush.brush_style = 0x0000; // BS_SOLID
383 emr_createbrushindirect_bg.log_brush.color.red = bgred;
384 emr_createbrushindirect_bg.log_brush.color.green = bggrn;
385 emr_createbrushindirect_bg.log_brush.color.blue = bgblu;
386 emr_createbrushindirect_bg.log_brush.color.reserved = 0;
387 emr_createbrushindirect_bg.log_brush.brush_hatch = 0; // ignored
388 bytecount += 24;
389 recordcount++;
390
391 emr_selectobject_fgbrush.type = 0x00000025; // EMR_SELECTOBJECT
392 emr_selectobject_fgbrush.size = 12;
393 emr_selectobject_fgbrush.ih_object = 1;
394 bytecount += 12;
395 recordcount++;
396
397 emr_selectobject_bgbrush.type = 0x00000025; // EMR_SELECTOBJECT
398 emr_selectobject_bgbrush.size = 12;
399 emr_selectobject_bgbrush.ih_object = 2;
400 bytecount += 12;
401 recordcount++;
402
403 /* Create Pens */
404 emr_createpen.type = 0x00000026; // EMR_CREATEPEN
405 emr_createpen.size = 28;
406 emr_createpen.ih_pen = 3;
407 emr_createpen.log_pen.pen_style = 0x00000005; // PS_NULL
408 emr_createpen.log_pen.width.x = 1;
409 emr_createpen.log_pen.width.y = 0; // ignored
410 emr_createpen.log_pen.color_ref.red = 0;
411 emr_createpen.log_pen.color_ref.green = 0;
412 emr_createpen.log_pen.color_ref.blue = 0;
413 emr_createpen.log_pen.color_ref.reserved = 0;
414 bytecount += 28;
415 recordcount++;
416
417 emr_selectobject_pen.type = 0x00000025; // EMR_SELECTOBJECT
418 emr_selectobject_pen.size = 12;
419 emr_selectobject_pen.ih_object = 3;
420 bytecount += 12;
421 recordcount++;
422
423 /* Create font records */
424 if ((symbol->show_hrt != 0) && (ustrlen(local_text) != 0)) {
425 emr_extcreatefontindirectw.type = 0x00000052; // EMR_EXTCREATEFONTINDIRECTW
426 emr_extcreatefontindirectw.size = 104;
427 emr_extcreatefontindirectw.ih_fonts = 4;
428 emr_extcreatefontindirectw.elw.height = (8 * scaler);
429 emr_extcreatefontindirectw.elw.width = 0; // automatic
430 emr_extcreatefontindirectw.elw.escapement = 0;
431 emr_extcreatefontindirectw.elw.orientation = 0;
432 emr_extcreatefontindirectw.elw.weight = 400;
433 emr_extcreatefontindirectw.elw.italic = 0x00;
434 emr_extcreatefontindirectw.elw.underline = 0x00;
435 emr_extcreatefontindirectw.elw.strike_out = 0x00;
436 emr_extcreatefontindirectw.elw.char_set = 0x01;
437 emr_extcreatefontindirectw.elw.out_precision = 0x00; // OUT_DEFAULT_PRECIS
438 emr_extcreatefontindirectw.elw.clip_precision = 0x00; // CLIP_DEFAULT_PRECIS
439 emr_extcreatefontindirectw.elw.quality = 0x00;
440 emr_extcreatefontindirectw.elw.pitch_and_family = 0x00;
441 for(i = 0; i < 64; i++) {
442 emr_extcreatefontindirectw.elw.facename[i] = '\0';
443 }
444 utfle_copy(emr_extcreatefontindirectw.elw.facename, (unsigned char*) "sans-serif", 10);
445
446 emr_selectobject_font.type = 0x00000025; // EMR_SELECTOBJECT
447 emr_selectobject_font.size = 12;
448 emr_selectobject_font.ih_object = 4;
449
450 if (!((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CC) || (symbol->symbology == BARCODE_ISBNX))) {
451 bytecount += 104;
452 recordcount++;
453 bytecount += 12;
454 recordcount++;
455 }
456
457 if (upcean) {
458 emr_extcreatefontindirectw_big.type = 0x00000052; // EMR_EXTCREATEFONTINDIRECTW
459 emr_extcreatefontindirectw_big.size = 104;
460 if (!((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CC) || (symbol->symbology == BARCODE_ISBNX))) {
461 emr_extcreatefontindirectw_big.ih_fonts = 4;
462 } else {
463 emr_extcreatefontindirectw_big.ih_fonts = 5;
464 }
465 emr_extcreatefontindirectw_big.elw.height = (11 * scaler);
466 emr_extcreatefontindirectw_big.elw.width = 0; // automatic
467 emr_extcreatefontindirectw_big.elw.escapement = 0;
468 emr_extcreatefontindirectw_big.elw.orientation = 0;
469 emr_extcreatefontindirectw_big.elw.weight = 400;
470 emr_extcreatefontindirectw_big.elw.italic = 0x00;
471 emr_extcreatefontindirectw_big.elw.underline = 0x00;
472 emr_extcreatefontindirectw_big.elw.strike_out = 0x00;
473 emr_extcreatefontindirectw_big.elw.char_set = 0x01;
474 emr_extcreatefontindirectw_big.elw.out_precision = 0x00; // OUT_DEFAULT_PRECIS
475 emr_extcreatefontindirectw_big.elw.clip_precision = 0x00; // CLIP_DEFAULT_PRECIS
476 emr_extcreatefontindirectw_big.elw.quality = 0x00;
477 emr_extcreatefontindirectw_big.elw.pitch_and_family = 0x00;
478 for(i = 0; i < 64; i++) {
479 emr_extcreatefontindirectw_big.elw.facename[i] = '\0';
480 }
481 utfle_copy(emr_extcreatefontindirectw_big.elw.facename, (unsigned char*) "sans-serif", 10);
482 bytecount += 104;
483 recordcount++;
484
485 emr_selectobject_font_big.type = 0x00000025; // EMR_SELECTOBJECT
486 emr_selectobject_font_big.size = 12;
487 emr_selectobject_font_big.ih_object = 5;
488 bytecount += 12;
489 recordcount++;
490 }
491 }
492
493 /* Text */
494 if ((symbol->show_hrt != 0) && (ustrlen(local_text) != 0)) {
495
496 if ((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CC) || (symbol->symbology == BARCODE_ISBNX)) {
497 latch = ustrlen(local_text);
498 for(i = 0; i < ustrlen(local_text); i++) {
499 if (local_text[i] == '+') {
500 latch = i;
501 }
502 }
503 if (latch > 8) {
504 // EAN-13
505 for(i = 1; i <= 6; i++) {
506 regw[i - 1] = local_text[i];
507 regx[i - 1] = local_text[i + 6];
508 }
509 if (ustrlen(local_text) > latch) {
510 // With add-on
511 for (i = (latch + 1); i <= ustrlen(local_text); i++) {
512 regz[i - (latch + 1)] = local_text[i];
513 }
514 }
515 local_text[1] = '\0';
516 } else if (latch > 5) {
517 // EAN-8
518 for(i = 0; i <= 3; i++) {
519 regw[i] = local_text[i + 4];
520 }
521 if (ustrlen(local_text) > latch) {
522 // With add-on
523 for (i = (latch + 1); i <= ustrlen(local_text); i++) {
524 regz[i - (latch + 1)] = local_text[i];
525 }
526 }
527 local_text[4] = '\0';
528 }
529
530 }
531
532 if ((symbol->symbology == BARCODE_UPCA) || (symbol->symbology == BARCODE_UPCA_CC)) {
533 latch = ustrlen(local_text);
534 for(i = 0; i < ustrlen(local_text); i++) {
535 if (local_text[i] == '+') {
536 latch = i;
537 }
538 }
539 if (ustrlen(local_text) > latch) {
540 // With add-on
541 for (i = (latch + 1); i <= ustrlen(local_text); i++) {
542 regz[i - (latch + 1)] = local_text[i];
543 }
544 }
545 for(i = 1; i <= 5; i++) {
546 regw[i - 1] = local_text[i];
547 regx[i - 1] = local_text[i + 6];
548 }
549 regy[0] = local_text[11];
550 local_text[1] = '\0';
551 }
552
553 if ((symbol->symbology == BARCODE_UPCE) || (symbol->symbology == BARCODE_UPCE_CC)) {
554 latch = ustrlen(local_text);
555 for(i = 0; i < ustrlen(local_text); i++) {
556 if (local_text[i] == '+') {
557 latch = i;
558 }
559 }
560 if (ustrlen(local_text) > latch) {
561 // With add-on
562 for (i = (latch + 1); i <= ustrlen(local_text); i++) {
563 regz[i - (latch + 1)] = local_text[i];
564 }
565 }
566 for(i = 1; i <= 6; i++) {
567 regw[i - 1] = local_text[i];
568 }
569 regx[0] = local_text[7];
570 local_text[1] = '\0';
571 }
572
573 for(i = 0; i <= 5; i++) {
574 emr_exttextoutw[i].type = 0x00000054; // EMR_EXTTEXTOUTW
575 emr_exttextoutw[i].bounds.top = 0; // ignored
576 emr_exttextoutw[i].bounds.left = 0; // ignoredemr_header.emf_header.bytes +=
577 emr_exttextoutw[i].bounds.right = 0xffffffff; // ignored
578 emr_exttextoutw[i].bounds.bottom = 0xffffffff; // ignored
579 emr_exttextoutw[i].i_graphics_mode = 0x00000001; // GM_COMPATIBLE
580 emr_exttextoutw[i].ex_scale = 1.0;
581 emr_exttextoutw[i].ey_scale = 1.0;
582 emr_exttextoutw[i].w_emr_text.off_string = 76;
583 emr_exttextoutw[i].w_emr_text.options = 0;
584 emr_exttextoutw[i].w_emr_text.rectangle.top = 0;
585 emr_exttextoutw[i].w_emr_text.rectangle.left = 0;
586 emr_exttextoutw[i].w_emr_text.rectangle.right = 0xffffffff;
587 emr_exttextoutw[i].w_emr_text.rectangle.bottom = 0xffffffff;
588 if (i > 0) {
589 emr_exttextoutw[i].size = 76 + (6 * 6);
590 emr_exttextoutw[i].w_emr_text.off_dx = 76 + (2 * 6);
591 }
592 }
593
594 emr_exttextoutw[0].w_emr_text.chars = ustrlen(local_text);
595 emr_exttextoutw[0].size = 76 + (6 * bump_up(ustrlen(local_text) + 1));
596 emr_exttextoutw[0].w_emr_text.reference.x = (emr_header.emf_header.bounds.right - (ustrlen(local_text) * 5.3 * scaler)) / 2; // text left
597 emr_exttextoutw[0].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler); // text top
598 emr_exttextoutw[0].w_emr_text.off_dx = 76 + (2 * bump_up(ustrlen(local_text) + 1));
599 for (i = 0; i < bump_up(ustrlen(local_text) + 1) * 2; i++) {
600 string_buffer[i] = '\0';
601 }
602 utfle_copy(string_buffer, local_text, ustrlen(local_text));
603 bytecount += 76 + (6 * bump_up(ustrlen(local_text) + 1));
604 recordcount++;
605
606 emr_exttextoutw[1].w_emr_text.chars = ustrlen(regw);
607 emr_exttextoutw[2].w_emr_text.chars = ustrlen(regx);
608 emr_exttextoutw[3].w_emr_text.chars = ustrlen(regy);
609 emr_exttextoutw[4].w_emr_text.chars = ustrlen(regz);
610
611 if ((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CC) || (symbol->symbology == BARCODE_ISBNX)) {
612 if (latch > 8) {
613 /* EAN-13 */
614 emr_exttextoutw[0].w_emr_text.reference.x = (xoffset - 9) * scaler;
615 emr_exttextoutw[0].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
616 emr_exttextoutw[1].w_emr_text.reference.x = (8 + xoffset) * scaler;
617 emr_exttextoutw[1].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
618 emr_exttextoutw[2].w_emr_text.reference.x = (55 + xoffset) * scaler;
619 emr_exttextoutw[2].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
620 if (ustrlen(regz) > 2) {
621 emr_exttextoutw[4].w_emr_text.reference.x = (115 + xoffset) * scaler;
622 bytecount += 112;
623 recordcount++;
624 } else if (ustrlen(regz) != 0) {
625 emr_exttextoutw[4].w_emr_text.reference.x = (109 + xoffset) * scaler;
626 bytecount += 112;
627 recordcount++;
628 }
629 emr_exttextoutw[4].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - ((large_bar_height + 9) * scaler);
630 bytecount += 2 * 112;
631 recordcount += 2;
632 } else if (latch > 5) {
633 /* EAN-8 */
634 emr_exttextoutw[0].w_emr_text.reference.x = (7 + xoffset) * scaler;
635 emr_exttextoutw[0].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
636 emr_exttextoutw[1].w_emr_text.reference.x = (40 + xoffset) * scaler;
637 emr_exttextoutw[1].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
638 if (ustrlen(regz) > 2) {
639 emr_exttextoutw[4].w_emr_text.reference.x = (87 + xoffset) * scaler;
640 bytecount += 112;
641 recordcount++;
642 } else if (ustrlen(regz) != 0) {
643 emr_exttextoutw[4].w_emr_text.reference.x = (81 + xoffset) * scaler;
644 bytecount += 112;
645 recordcount++;
646 }
647 emr_exttextoutw[4].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - ((large_bar_height + 9) * scaler);
648 bytecount += 112;
649 recordcount++;
650 }
651 }
652
653 if ((symbol->symbology == BARCODE_UPCA) || (symbol->symbology == BARCODE_UPCA_CC)) {
654 emr_exttextoutw[0].w_emr_text.reference.x = (xoffset - 7) * scaler;
655 emr_exttextoutw[0].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
656 emr_exttextoutw[1].w_emr_text.reference.x = (14 + xoffset) * scaler;
657 emr_exttextoutw[1].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
658 emr_exttextoutw[2].w_emr_text.reference.x = (55 + xoffset) * scaler;
659 emr_exttextoutw[2].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
660 emr_exttextoutw[3].w_emr_text.reference.x = (98 + xoffset) * scaler;
661 emr_exttextoutw[3].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
662 if (ustrlen(regz) > 2) {
663 emr_exttextoutw[4].w_emr_text.reference.x = (117 + xoffset) * scaler;
664 bytecount += 112;
665 recordcount++;
666 } else if (ustrlen(regz) != 0) {
667 emr_exttextoutw[4].w_emr_text.reference.x = (111 + xoffset) * scaler;
668 bytecount += 112;
669 recordcount++;
670 }
671 emr_exttextoutw[4].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - ((large_bar_height + 9) * scaler);
672 bytecount += (3 * 112) + 12;
673 recordcount += 4;
674 }
675
676 if ((symbol->symbology == BARCODE_UPCE) || (symbol->symbology == BARCODE_UPCE_CC)) {
677 emr_exttextoutw[0].w_emr_text.reference.x = (xoffset - 7) * scaler;
678 emr_exttextoutw[0].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
679 emr_exttextoutw[1].w_emr_text.reference.x = (8 + xoffset) * scaler;
680 emr_exttextoutw[1].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
681 emr_exttextoutw[2].w_emr_text.reference.x = (53 + xoffset) * scaler;
682 emr_exttextoutw[2].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);;
683 if (ustrlen(regz) > 2) {
684 emr_exttextoutw[4].w_emr_text.reference.x = (71 + xoffset) * scaler;
685 bytecount += 112;
686 recordcount++;
687 } else if (ustrlen(regz) != 0) {
688 emr_exttextoutw[4].w_emr_text.reference.x = (65 + xoffset) * scaler;
689 bytecount += 112;
690 recordcount++;
691 }
692 emr_exttextoutw[4].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - ((large_bar_height + 9) * scaler);
693 bytecount += (2 * 112) + 12;
694 recordcount += 3;
695 }
696 }
697
698 /* Make background from a rectangle */
699 background.type = 0x0000002b; // EMR_RECTANGLE;
700 background.size = 24;
701 background.box.top = 0;
702 background.box.left = 0;
703 background.box.right = emr_header.emf_header.bounds.right;
704 background.box.bottom = emr_header.emf_header.bounds.bottom;
705 bytecount += 24;
706 recordcount++;
707
708 /* Make bind and box rectangles if needed */
709 if ((symbol->output_options & BARCODE_BIND) || (symbol->output_options & BARCODE_BOX)) {
710 box.top.type = 0x0000002b; // EMR_RECTANGLE;
711 box.top.size = 24;
712 box.top.box.top = 0;
713 box.top.box.bottom = symbol->border_width * scaler;
714 box.top.box.left = symbol->border_width * scaler;
715 box.top.box.right = emr_header.emf_header.bounds.right - (symbol->border_width * scaler);
716 bytecount += 24;
717 recordcount++;
718
719 box.bottom.type = 0x0000002b; // EMR_RECTANGLE;
720 box.bottom.size = 24;
721 box.bottom.box.top = emr_header.emf_header.bounds.bottom - ((symbol->border_width + textoffset) * scaler);
722 box.bottom.box.bottom = emr_header.emf_header.bounds.bottom - (textoffset * scaler);
723 box.bottom.box.left = symbol->border_width * scaler;
724 box.bottom.box.right = emr_header.emf_header.bounds.right - (symbol->border_width * scaler);
725 bytecount += 24;
726 recordcount++;
727
728 if (symbol->output_options & BARCODE_BOX) {
729 box.left.type = 0x0000002b; // EMR_RECTANGLE;
730 box.left.size = 24;
731 box.left.box.top = 0;
732 box.left.box.bottom = emr_header.emf_header.bounds.bottom - (textoffset * scaler);
733 box.left.box.left = 0;
734 box.left.box.right = symbol->border_width * scaler;
735 bytecount += 24;
736 recordcount++;
737
738 box.right.type = 0x0000002b; // EMR_RECTANGLE;
739 box.right.size = 24;
740 box.right.box.top = 0;
741 box.right.box.bottom = emr_header.emf_header.bounds.bottom - (textoffset * scaler);
742 box.right.box.left = emr_header.emf_header.bounds.right - (symbol->border_width * scaler);
743 box.right.box.right = emr_header.emf_header.bounds.right;
744 bytecount += 24;
745 recordcount++;
746 }
747 }
748
749 /* Make image rectangles, circles, hexagons */
750 for (this_row = 0; this_row < symbol->rows; this_row++) {
751
752 if (symbol->row_height[this_row] == 0) {
753 row_height = large_bar_height;
754 } else {
755 row_height = symbol->row_height[this_row];
756 }
757 row_posn = 0;
758 for (i = 0; i < this_row; i++) {
759 if (symbol->row_height[i] == 0) {
760 row_posn += large_bar_height;
761 } else {
762 row_posn += symbol->row_height[i];
763 }
764 }
765 row_posn += yoffset;
766
767 if (symbol->symbology != BARCODE_MAXICODE) {
768 if ((symbol->output_options & BARCODE_DOTTY_MODE) != 0) {
769 // Use dots (circles)
770 for(i = 0; i < symbol->width; i++) {
771 if(module_is_set(symbol, this_row, i)) {
772 circle[this_circle].type = 0x0000002a; // EMR_ELLIPSE
773 circle[this_circle].size = 24;
774 circle[this_circle].box.top = this_row * scaler;
775 circle[this_circle].box.bottom = (this_row + 1) * scaler;
776 circle[this_circle].box.left = (i + xoffset) * scaler;
777 circle[this_circle].box.right = (i + xoffset + 1) * scaler;
778 this_circle++;
779 bytecount += 24;
780 recordcount++;
781 }
782 }
783 } else {
784 // Normal mode, with rectangles
785 i = 0;
786 if (module_is_set(symbol, this_row, 0)) {
787 latch = 1;
788 } else {
789 latch = 0;
790 }
791
792 do {
793 block_width = 0;
794 do {
795 block_width++;
796 } while (module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i));
797
798 if (latch == 1) {
799 /* a bar */
800 rectangle[this_rectangle].type = 0x0000002b; // EMR_RECTANGLE;
801 rectangle[this_rectangle].size = 24;
802 rectangle[this_rectangle].box.top = row_posn * scaler;
803 rectangle[this_rectangle].box.bottom = (row_posn + row_height) * scaler;
804 rectangle[this_rectangle].box.left = (i + xoffset) * scaler;
805 rectangle[this_rectangle].box.right = (i + xoffset + block_width) * scaler;
806 bytecount += 24;
807 recordcount++;
808
809 if (this_row == symbol->rows - 1) {
810 /* Last row, extend bars if needed */
811 if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC)) ||
812 (symbol->symbology == BARCODE_ISBNX)) {
813 /* guard bar extensions for EAN8 and EAN13 */
814 if (ustrlen(regx) != 0) {
815 /* EAN-13 */
816 switch (i) {
817 case 0:
818 case 2:
819 case 46:
820 case 48:
821 case 92:
822 case 94:
823 rectangle[this_rectangle].box.bottom += (5 * scaler);
824 break;
825 }
826 if (i > 94) {
827 /* Add-on */
828 rectangle[this_rectangle].box.top += (10 * scaler);
829 rectangle[this_rectangle].box.bottom += (5 * scaler);
830 }
831 } else if (ustrlen(regw) != 0) {
832 /* EAN-8 */
833 switch (i) {
834 case 0:
835 case 2:
836 case 32:
837 case 34:
838 case 64:
839 case 66:
840 rectangle[this_rectangle].box.bottom += (5 * scaler);
841 break;
842 }
843 if (i > 66) {
844 /* Add-on */
845 rectangle[this_rectangle].box.top += (10 * scaler);
846 rectangle[this_rectangle].box.bottom += (5 * scaler);
847 }
848 }
849 }
850 if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
851 /* guard bar extensions for UPCA */
852 if (((i >= 0) && (i <= 11)) || ((i >= 85) && (i <= 96))) {
853 rectangle[this_rectangle].box.bottom += (5 * scaler);
854 }
855 if ((i == 46) || (i == 48)) {
856 rectangle[this_rectangle].box.bottom += (5 * scaler);
857 }
858 if (i > 96) {
859 /* Add-on */
860 rectangle[this_rectangle].box.top += (10 * scaler);
861 rectangle[this_rectangle].box.bottom += (5 * scaler);
862 }
863 }
864
865 if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
866 /* guard bar extensions for UPCE */
867 switch (i) {
868 case 0:
869 case 2:
870 case 46:
871 case 48:
872 case 50:
873 rectangle[this_rectangle].box.bottom += (5 * scaler);
874 break;
875 }
876 if (i > 50) {
877 /* Add-on */
878 rectangle[this_rectangle].box.top += (10 * scaler);
879 rectangle[this_rectangle].box.bottom += (5 * scaler);
880 }
881 }
882 }
883
884 this_rectangle++;
885 latch = 0;
886 } else {
887 /* a space */
888 latch = 1;
889 }
890
891
892 i += block_width;
893 } while (i < symbol->width);
894 }
895 } else {
896 float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy, mx, my;
897 /* Maxicode, use hexagons */
898
899 /* Calculate bullseye */
900 for(i = 0; i < 6; i++) {
901 bullseye[i].type = 0x0000002a; // EMR_ELLIPSE
902 bullseye[i].size = 24;
903 }
904 bullseye[0].box.top = (35.60 - 10.85) * scaler;
905 bullseye[0].box.bottom = (35.60 + 10.85) * scaler;
906 bullseye[0].box.left = (35.76 - 10.85) * scaler;
907 bullseye[0].box.right = (35.76 + 10.85) * scaler;
908 bullseye[1].box.top = (35.60 - 8.97) * scaler;
909 bullseye[1].box.bottom = (35.60 + 8.97) * scaler;
910 bullseye[1].box.left = (35.76 - 8.97) * scaler;
911 bullseye[1].box.right = (35.76 + 8.97) * scaler;
912 bullseye[2].box.top = (35.60 - 7.10) * scaler;
913 bullseye[2].box.bottom = (35.60 + 7.10) * scaler;
914 bullseye[2].box.left = (35.76 - 7.10) * scaler;
915 bullseye[2].box.right = (35.76 + 7.10) * scaler;
916 bullseye[3].box.top = (35.60 - 5.22) * scaler;
917 bullseye[3].box.bottom = (35.60 + 5.22) * scaler;
918 bullseye[3].box.left = (35.76 - 5.22) * scaler;
919 bullseye[3].box.right = (35.76 + 5.22) * scaler;
920 bullseye[4].box.top = (35.60 - 3.31) * scaler;
921 bullseye[4].box.bottom = (35.60 + 3.31) * scaler;
922 bullseye[4].box.left = (35.76 - 3.31) * scaler;
923 bullseye[4].box.right = (35.76 + 3.31) * scaler;
924 bullseye[5].box.top = (35.60 - 1.43) * scaler;
925 bullseye[5].box.bottom = (35.60 + 1.43) * scaler;
926 bullseye[5].box.left = (35.76 - 1.43) * scaler;
927 bullseye[5].box.right = (35.76 + 1.43) * scaler;
928
929 /* Plot hexagons */
930 for(i = 0; i < symbol->width; i++) {
931 if(module_is_set(symbol, this_row, i)) {
932 hexagon[this_hexagon].type = 0x00000003; // EMR_POLYGON
933 hexagon[this_hexagon].size = 76;
934 hexagon[this_hexagon].count = 6;
935
936 my = this_row * 2.135 + 1.43;
937 ay = my + 1.0 + yoffset;
938 by = my + 0.5 + yoffset;
939 cy = my - 0.5 + yoffset;
940 dy = my - 1.0 + yoffset;
941 ey = my - 0.5 + yoffset;
942 fy = my + 0.5 + yoffset;
943 if (this_row & 1) {
944 mx = (2.46 * i) + 1.23 + 1.23;
945 } else {
946 mx = (2.46 * i) + 1.23;
947 }
948 ax = mx + xoffset;
949 bx = mx + 0.86 + xoffset;
950 cx = mx + 0.86 + xoffset;
951 dx = mx + xoffset;
952 ex = mx - 0.86 + xoffset;
953 fx = mx - 0.86 + xoffset;
954
955 hexagon[this_hexagon].a_points_a.x = ax * scaler;
956 hexagon[this_hexagon].a_points_a.y = ay * scaler;
957 hexagon[this_hexagon].a_points_b.x = bx * scaler;
958 hexagon[this_hexagon].a_points_b.y = by * scaler;
959 hexagon[this_hexagon].a_points_c.x = cx * scaler;
960 hexagon[this_hexagon].a_points_c.y = cy * scaler;
961 hexagon[this_hexagon].a_points_d.x = dx * scaler;
962 hexagon[this_hexagon].a_points_d.y = dy * scaler;
963 hexagon[this_hexagon].a_points_e.x = ex * scaler;
964 hexagon[this_hexagon].a_points_e.y = ey * scaler;
965 hexagon[this_hexagon].a_points_f.x = fx * scaler;
966 hexagon[this_hexagon].a_points_f.y = fy * scaler;
967
968 hexagon[this_hexagon].bounds.top = hexagon[this_hexagon].a_points_d.y;
969 hexagon[this_hexagon].bounds.bottom = hexagon[this_hexagon].a_points_a.y;
970 hexagon[this_hexagon].bounds.left = hexagon[this_hexagon].a_points_e.x;
971 hexagon[this_hexagon].bounds.right = hexagon[this_hexagon].a_points_c.x;
972 this_hexagon++;
973 bytecount += 76;
974 recordcount++;
975 }
976 }
977 }
978 }
979
980 if (symbol->output_options & BARCODE_BIND) {
981 if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) {
982 /* row binding */
983 for (i = 1; i < symbol->rows; i++) {
984 row_binding[i - 1].type = 0x0000002b; // EMR_RECTANGLE;
985 row_binding[i - 1].size = 24;
986 row_binding[i - 1].box.top = ((i * row_height) + yoffset - 1) * scaler;
987 row_binding[i - 1].box.bottom = row_binding[i - 1].box.top + (2 * scaler);
988
989 if (symbol->symbology != BARCODE_CODABLOCKF) {
990 row_binding[i - 1].box.left = xoffset * scaler;
991 row_binding[i - 1].box.right = emr_header.emf_header.bounds.right - (xoffset * scaler);
992 } else {
993 row_binding[i - 1].box.left = (xoffset + 11) * scaler;
994 row_binding[i - 1].box.right = emr_header.emf_header.bounds.right - ((xoffset + 14) * scaler);
995 }
996 bytecount += 24;
997 recordcount++;
998 }
999 }
1000 }
1001
1002 /* Create EOF record */
1003 emr_eof.type = 0x0000000e; // EMR_EOF
1004 emr_eof.size = 18; // Assuming no palette entries
1005 emr_eof.n_pal_entries = 0;
1006 emr_eof.off_pal_entries = 0;
1007 emr_eof.size_last = emr_eof.size;
1008 bytecount += 18;
1009 recordcount++;
1010
1011 /* Put final counts in header */
1012 emr_header.emf_header.bytes = bytecount;
1013 emr_header.emf_header.records = recordcount;
1014
1015 /* Send EMF data to file */
1016 if (symbol->output_options & BARCODE_STDOUT) {
1017 emf_file = stdout;
1018 } else {
1019 emf_file = fopen(symbol->outfile, "w");
1020 }
1021 if (emf_file == NULL) {
1022 strcpy(symbol->errtxt, "640: Could not open output file");
1023 return ZINT_ERROR_FILE_ACCESS;
1024 }
1025
1026 fwrite(&emr_header, sizeof(emr_header_t), 1, emf_file);
1027
1028 fwrite(&emr_createbrushindirect_fg, sizeof(emr_createbrushindirect_t), 1, emf_file);
1029 fwrite(&emr_createbrushindirect_bg, sizeof(emr_createbrushindirect_t), 1, emf_file);
1030 fwrite(&emr_createpen, sizeof(emr_createpen_t), 1, emf_file);
1031
1032 if ((symbol->show_hrt != 0) && (ustrlen(local_text) != 0)) {
1033 fwrite(&emr_extcreatefontindirectw, sizeof(emr_extcreatefontindirectw_t), 1, emf_file);
1034 }
1035
1036 fwrite(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, emf_file);
1037 fwrite(&emr_selectobject_pen, sizeof(emr_selectobject_t), 1, emf_file);
1038 fwrite(&background, sizeof(emr_rectangle_t), 1, emf_file);
1039
1040 fwrite(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, emf_file);
1041
1042 for (i = 0; i < rectangle_count; i++) {
1043 fwrite(&rectangle[i], sizeof(emr_rectangle_t), 1, emf_file);
1044 }
1045 for (i = 0; i < circle_count; i++) {
1046 fwrite(&circle[i], sizeof(emr_ellipse_t), 1, emf_file);
1047 }
1048 for (i = 0; i < hexagon_count; i++) {
1049 fwrite(&hexagon[i], sizeof(emr_polygon_t), 1, emf_file);
1050 }
1051
1052 if ((symbol->output_options & BARCODE_BIND) || (symbol->output_options & BARCODE_BOX)) {
1053 fwrite(&box.top, sizeof(emr_rectangle_t), 1, emf_file);
1054 fwrite(&box.bottom, sizeof(emr_rectangle_t), 1, emf_file);
1055 if (symbol->output_options & BARCODE_BOX) {
1056 fwrite(&box.left, sizeof(emr_rectangle_t), 1, emf_file);
1057 fwrite(&box.right, sizeof(emr_rectangle_t), 1, emf_file);
1058 }
1059 }
1060
1061 if (symbol->output_options & BARCODE_BIND) {
1062 if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) {
1063 for(i = 0; i < symbol->rows - 1; i++) {
1064 fwrite(&row_binding[i], sizeof(emr_rectangle_t), 1, emf_file);
1065 }
1066 }
1067 }
1068
1069 if(symbol->symbology == BARCODE_MAXICODE) {
1070 fwrite(&bullseye[0], sizeof(emr_ellipse_t), 1, emf_file);
1071 fwrite(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, emf_file);
1072 fwrite(&bullseye[1], sizeof(emr_ellipse_t), 1, emf_file);
1073 fwrite(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, emf_file);
1074 fwrite(&bullseye[2], sizeof(emr_ellipse_t), 1, emf_file);
1075 fwrite(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, emf_file);
1076 fwrite(&bullseye[3], sizeof(emr_ellipse_t), 1, emf_file);
1077 fwrite(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, emf_file);
1078 fwrite(&bullseye[4], sizeof(emr_ellipse_t), 1, emf_file);
1079 fwrite(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, emf_file);
1080 fwrite(&bullseye[5], sizeof(emr_ellipse_t), 1, emf_file);
1081 }
1082
1083 if ((symbol->show_hrt != 0) && (ustrlen(local_text) != 0)) {
1084 if ((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CC) || (symbol->symbology == BARCODE_ISBNX)) {
1085 if (ustrlen(regx) != 0) {
1086 /* EAN-13 */
1087 fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file);
1088 fwrite(&emr_exttextoutw[0], sizeof(emr_exttextoutw_t), 1, emf_file);
1089 fwrite(&string_buffer, 2 * bump_up(ustrlen(local_text) + 1), 1, emf_file);
1090 for (i = 0; i < bump_up(ustrlen(local_text) + 1); i++) {
1091 fwrite(&dx, 4, 1, emf_file);
1092 }
1093 fwrite(&emr_exttextoutw[1], sizeof(emr_exttextoutw_t), 1, emf_file);
1094 utfle_copy(output_buffer, regw, 6);
1095 fwrite(&output_buffer, 12, 1, emf_file);
1096 for (i = 0; i < 6; i++) {
1097 fwrite(&dx, 4, 1, emf_file);
1098 }
1099 fwrite(&emr_exttextoutw[2], sizeof(emr_exttextoutw_t), 1, emf_file);
1100 utfle_copy(output_buffer, regx, 6);
1101 fwrite(&output_buffer, 12, 1, emf_file);
1102 for (i = 0; i < 6; i++) {
1103 fwrite(&dx, 4, 1, emf_file);
1104 }
1105 if (ustrlen(regz) != 0) {
1106 fwrite(&emr_exttextoutw[4], sizeof(emr_exttextoutw_t), 1, emf_file);
1107 utfle_copy(output_buffer, regz, 6);
1108 fwrite(&output_buffer, 12, 1, emf_file);
1109 for (i = 0; i < 6; i++) {
1110 fwrite(&dx, 4, 1, emf_file);
1111 }
1112 }
1113 textdone = 1;
1114 } else if (ustrlen(regw) != 0) {
1115 /* EAN-8 */
1116 fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file);
1117 fwrite(&emr_exttextoutw[0], sizeof(emr_exttextoutw_t), 1, emf_file);
1118 fwrite(&string_buffer, 2 * bump_up(ustrlen(local_text) + 1), 1, emf_file);
1119 for (i = 0; i < bump_up(ustrlen(local_text) + 1); i++) {
1120 fwrite(&dx, 4, 1, emf_file);
1121 }
1122 fwrite(&emr_exttextoutw[1], sizeof(emr_exttextoutw_t), 1, emf_file);
1123 utfle_copy(output_buffer, regw, 6);
1124 fwrite(&output_buffer, 12, 1, emf_file);
1125 for (i = 0; i < 6; i++) {
1126 fwrite(&dx, 4, 1, emf_file);
1127 }
1128 if (ustrlen(regz) != 0) {
1129 fwrite(&emr_exttextoutw[4], sizeof(emr_exttextoutw_t), 1, emf_file);
1130 utfle_copy(output_buffer, regz, 6);
1131 fwrite(&output_buffer, 12, 1, emf_file);
1132 for (i = 0; i < 6; i++) {
1133 fwrite(&dx, 4, 1, emf_file);
1134 }
1135 }
1136 textdone = 1;
1137 }
1138 }
1139 if ((symbol->symbology == BARCODE_UPCA) || (symbol->symbology == BARCODE_UPCA_CC)) {
1140 fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file);
1141 fwrite(&emr_exttextoutw[0], sizeof(emr_exttextoutw_t), 1, emf_file);
1142 fwrite(&string_buffer, 2 * bump_up(ustrlen(local_text) + 1), 1, emf_file);
1143 for (i = 0; i < bump_up(ustrlen(local_text) + 1); i++) {
1144 fwrite(&dx, 4, 1, emf_file);
1145 }
1146 fwrite(&emr_exttextoutw[3], sizeof(emr_exttextoutw_t), 1, emf_file);
1147 utfle_copy(output_buffer, regy, 6);
1148 fwrite(&output_buffer, 12, 1, emf_file);
1149 for (i = 0; i < 6; i++) {
1150 fwrite(&dx, 4, 1, emf_file);
1151 }
1152 fwrite(&emr_selectobject_font_big, sizeof(emr_selectobject_t), 1, emf_file);
1153 fwrite(&emr_exttextoutw[1], sizeof(emr_exttextoutw_t), 1, emf_file);
1154 utfle_copy(output_buffer, regw, 6);
1155 fwrite(&output_buffer, 12, 1, emf_file);
1156 for (i = 0; i < 6; i++) {
1157 fwrite(&dx, 4, 1, emf_file);
1158 }
1159 fwrite(&emr_exttextoutw[2], sizeof(emr_exttextoutw_t), 1, emf_file);
1160 utfle_copy(output_buffer, regx, 6);
1161 fwrite(&output_buffer, 12, 1, emf_file);
1162 for (i = 0; i < 6; i++) {
1163 fwrite(&dx, 4, 1, emf_file);
1164 }
1165 if (ustrlen(regz) != 0) {
1166 fwrite(&emr_exttextoutw[4], sizeof(emr_exttextoutw_t), 1, emf_file);
1167 utfle_copy(output_buffer, regz, 6);
1168 fwrite(&output_buffer, 12, 1, emf_file);
1169 for (i = 0; i < 6; i++) {
1170 fwrite(&dx, 4, 1, emf_file);
1171 }
1172 }
1173 textdone = 1;
1174 }
1175
1176 if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
1177 fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file);
1178 fwrite(&emr_exttextoutw[0], sizeof(emr_exttextoutw_t), 1, emf_file);
1179 fwrite(&string_buffer, 2 * bump_up(ustrlen(local_text) + 1), 1, emf_file);
1180 for (i = 0; i < bump_up(ustrlen(local_text) + 1); i++) {
1181 fwrite(&dx, 4, 1, emf_file);
1182 }
1183 fwrite(&emr_exttextoutw[2], sizeof(emr_exttextoutw_t), 1, emf_file);
1184 utfle_copy(output_buffer, regx, 6);
1185 fwrite(&output_buffer, 12, 1, emf_file);
1186 for (i = 0; i < 6; i++) {
1187 fwrite(&dx, 4, 1, emf_file);
1188 }
1189 fwrite(&emr_selectobject_font_big, sizeof(emr_selectobject_t), 1, emf_file);
1190 fwrite(&emr_exttextoutw[1], sizeof(emr_exttextoutw_t), 1, emf_file);
1191 utfle_copy(output_buffer, regw, 6);
1192 fwrite(&output_buffer, 12, 1, emf_file);
1193 for (i = 0; i < 6; i++) {
1194 fwrite(&dx, 4, 1, emf_file);
1195 }
1196 if (ustrlen(regz) != 0) {
1197 fwrite(&emr_exttextoutw[4], sizeof(emr_exttextoutw_t), 1, emf_file);
1198 utfle_copy(output_buffer, regz, 6);
1199 fwrite(&output_buffer, 12, 1, emf_file);
1200 for (i = 0; i < 6; i++) {
1201 fwrite(&dx, 4, 1, emf_file);
1202 }
1203 }
1204 textdone = 1;
1205 }
1206
1207 if (textdone == 0) {
1208 fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file);
1209 fwrite(&emr_exttextoutw[0], sizeof(emr_exttextoutw_t), 1, emf_file);
1210 fwrite(&string_buffer, 2 * bump_up(ustrlen(local_text) + 1), 1, emf_file);
1211 for (i = 0; i < bump_up(ustrlen(local_text) + 1); i++) {
1212 fwrite(&dx, 4, 1, emf_file);
1213 }
1214 }
1215 }
1216
1217 fwrite(&emr_eof, sizeof(emr_eof_t), 1, emf_file);
1218
1219 if (symbol->output_options & BARCODE_STDOUT) {
1220 fflush(emf_file);
1221 } else {
1222 fclose(emf_file);
1223 }
1224 return error_number;
1225 }
1226