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