2022-07-14 16:01:30 +01:00
/* emf.c - Support for Microsoft Enhanced Metafile Format */
/*
2016-12-23 16:48:03 +00:00
libzint - the open source barcode library
2022-07-14 16:01:30 +01:00
Copyright ( C ) 2016 - 2022 Robin Stuart < rstuart114 @ gmail . com >
2016-12-23 16:48:03 +00:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
2017-10-23 21:37:52 +02:00
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2016-12-23 16:48:03 +00:00
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
2017-10-23 21:37:52 +02:00
documentation and / or other materials provided with the distribution .
2016-12-23 16:48:03 +00:00
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
2017-10-23 21:37:52 +02:00
without specific prior written permission .
2016-12-23 16:48:03 +00:00
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
2017-10-23 21:37:52 +02:00
OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
2016-12-23 16:48:03 +00:00
SUCH DAMAGE .
*/
2022-07-14 16:01:30 +01:00
/* SPDX-License-Identifier: BSD-3-Clause */
2016-12-23 16:48:03 +00:00
/* Developed according to [MS-EMF] - v20160714, Released July 14, 2016
* and [ MS - WMF ] - v20160714 , Released July 14 , 2016 */
2021-06-10 11:15:39 +01:00
# include <errno.h>
2016-12-23 16:48:03 +00:00
# include <stdio.h>
2020-07-19 10:31:12 +01:00
# include <assert.h>
2016-12-23 16:48:03 +00:00
# include <math.h>
2017-10-15 12:29:46 +02:00
# ifdef _MSC_VER
2021-07-26 15:29:05 +01:00
# include <io.h>
# include <fcntl.h>
2017-10-15 12:29:46 +02:00
# endif
2016-12-23 16:48:03 +00:00
# include "common.h"
# include "emf.h"
2021-08-27 18:07:05 +01:00
/* Multiply truncating to 3 decimal places (avoids rounding differences on various platforms) */
2021-10-20 23:05:30 +01:00
# define mul3dpf(m, arg) stripf(roundf(m * arg * 1000.0) / 1000.0f)
2021-08-27 18:07:05 +01:00
2019-12-19 00:37:55 +00:00
static int count_rectangles ( struct zint_symbol * symbol ) {
2016-12-23 16:48:03 +00:00
int rectangles = 0 ;
2018-06-10 09:16:18 +01:00
struct zint_vector_rect * rect ;
2017-10-23 21:37:52 +02:00
2018-06-10 09:16:18 +01:00
rect = symbol - > vector - > rectangles ;
while ( rect ) {
rectangles + + ;
rect = rect - > next ;
2016-12-23 16:48:03 +00:00
}
2017-10-23 21:37:52 +02:00
2016-12-23 16:48:03 +00:00
return rectangles ;
}
2019-12-19 00:37:55 +00:00
static int count_circles ( struct zint_symbol * symbol ) {
2016-12-23 16:48:03 +00:00
int circles = 0 ;
2018-06-10 09:16:18 +01:00
struct zint_vector_circle * circ ;
2017-10-23 21:37:52 +02:00
2018-06-10 09:16:18 +01:00
circ = symbol - > vector - > circles ;
while ( circ ) {
circles + + ;
circ = circ - > next ;
2016-12-23 16:48:03 +00:00
}
2017-10-23 21:37:52 +02:00
2021-08-22 13:59:01 +01:00
/* Hack for MaxiCode */
return symbol - > symbology = = BARCODE_MAXICODE ? circles * 2 : circles ;
2016-12-23 16:48:03 +00:00
}
2019-12-19 00:37:55 +00:00
static int count_hexagons ( struct zint_symbol * symbol ) {
2016-12-23 16:48:03 +00:00
int hexagons = 0 ;
2018-06-10 09:16:18 +01:00
struct zint_vector_hexagon * hex ;
2017-10-23 21:37:52 +02:00
2018-06-10 09:16:18 +01:00
hex = symbol - > vector - > hexagons ;
while ( hex ) {
hexagons + + ;
hex = hex - > next ;
2016-12-23 16:48:03 +00:00
}
2017-10-23 21:37:52 +02:00
2016-12-23 16:48:03 +00:00
return hexagons ;
}
2020-12-23 10:57:24 +00:00
static int count_strings ( struct zint_symbol * symbol , float * fsize , float * fsize2 , int * halign , int * halign1 ,
int * halign2 ) {
2018-06-10 09:16:18 +01:00
int strings = 0 ;
struct zint_vector_string * str ;
2020-12-23 10:57:24 +00:00
* fsize = * fsize2 = 0.0f ;
* halign = * halign1 = * halign2 = 0 ;
2020-09-30 12:19:12 +01:00
2018-06-10 09:16:18 +01:00
str = symbol - > vector - > strings ;
while ( str ) {
2020-09-30 12:19:12 +01:00
/* Allow 2 font sizes */
2020-12-23 10:57:24 +00:00
if ( * fsize = = 0.0f ) {
* fsize = str - > fsize ;
} else if ( str - > fsize ! = * fsize & & * fsize2 = = 0.0f ) {
* fsize2 = str - > fsize ;
2020-09-30 12:19:12 +01:00
}
/* Only 3 haligns possible */
if ( str - > halign ) {
if ( str - > halign = = 1 ) {
* halign1 = str - > halign ;
} else {
* halign2 = str - > halign ;
}
}
2018-06-10 09:16:18 +01:00
strings + + ;
str = str - > next ;
}
return strings ;
}
2019-12-19 00:37:55 +00:00
static void utfle_copy ( unsigned char * output , unsigned char * input , int length ) {
2016-12-23 16:48:03 +00:00
int i ;
int o ;
2017-10-23 21:37:52 +02:00
2016-12-23 16:48:03 +00:00
/* Convert UTF-8 to UTF-16LE - only needs to handle characters <= U+00FF */
i = 0 ;
o = 0 ;
do {
2018-06-10 09:16:18 +01:00
if ( input [ i ] < = 0x7f ) {
2016-12-23 16:48:03 +00:00
/* 1 byte mode (7-bit ASCII) */
output [ o ] = input [ i ] ;
output [ o + 1 ] = 0x00 ;
o + = 2 ;
i + + ;
} else {
/* 2 byte mode */
output [ o ] = ( ( input [ i ] & 0x1f ) < < 6 ) + ( input [ i + 1 ] & 0x3f ) ;
output [ o + 1 ] = 0x00 ;
o + = 2 ;
i + = 2 ;
}
} while ( i < length ) ;
}
2019-12-19 00:37:55 +00:00
static int bump_up ( int input ) {
2016-12-23 16:48:03 +00:00
/* Strings length must be a multiple of 4 bytes */
2020-12-23 10:57:24 +00:00
if ( ( input & 1 ) = = 1 ) {
2016-12-23 16:48:03 +00:00
input + + ;
}
return input ;
}
2020-09-30 12:19:12 +01:00
static int utfle_length ( unsigned char * input , int length ) {
int result = 0 ;
int i ;
for ( i = 0 ; i < length ; i + + ) {
result + + ;
if ( input [ i ] > = 0x80 ) { /* 2 byte UTF-8 counts as one UTF-16LE character */
i + + ;
}
}
return result ;
}
INTERNAL int emf_plot ( struct zint_symbol * symbol , int rotate_angle ) {
int i ;
2016-12-23 16:48:03 +00:00
FILE * emf_file ;
int fgred , fggrn , fgblu , bgred , bggrn , bgblu ;
int error_number = 0 ;
int rectangle_count , this_rectangle ;
int circle_count , this_circle ;
int hexagon_count , this_hexagon ;
2018-06-10 09:16:18 +01:00
int string_count , this_text ;
2016-12-23 16:48:03 +00:00
int bytecount , recordcount ;
2020-10-26 12:21:43 +00:00
float previous_diameter ;
float radius , half_radius , half_sqrt3_radius ;
2020-01-13 19:24:01 +00:00
int colours_used = 0 ;
2021-07-26 15:29:05 +01:00
int rectangle_bycolour [ 9 ] = { 0 } ;
2020-09-30 12:19:12 +01:00
int width , height ;
2020-08-02 22:26:39 +01:00
int draw_background = 1 ;
2020-09-30 12:19:12 +01:00
int bold ;
2021-07-26 15:29:05 +01:00
const int output_to_stdout = symbol - > output_options & BARCODE_STDOUT ;
2018-06-10 09:16:18 +01:00
struct zint_vector_rect * rect ;
struct zint_vector_circle * circ ;
struct zint_vector_hexagon * hex ;
struct zint_vector_string * str ;
2017-10-23 21:37:52 +02:00
2021-07-26 15:29:05 +01:00
/* Allow for up to 6 strings (current max 3 for UPC/EAN) */
unsigned char * this_string [ 6 ] ;
emr_exttextoutw_t text [ 6 ] ;
float text_fsizes [ 6 ] ;
int text_haligns [ 6 ] ;
2016-12-23 16:48:03 +00:00
emr_header_t emr_header ;
emr_eof_t emr_eof ;
2020-09-30 12:19:12 +01:00
emr_mapmode_t emr_mapmode ;
emr_setworldtransform_t emr_setworldtransform ;
2016-12-23 16:48:03 +00:00
emr_createbrushindirect_t emr_createbrushindirect_fg ;
emr_createbrushindirect_t emr_createbrushindirect_bg ;
2022-07-14 16:01:30 +01:00
emr_createbrushindirect_t emr_createbrushindirect_colour [ 9 ] ; /* Used for colour symbols only */
2016-12-23 16:48:03 +00:00
emr_selectobject_t emr_selectobject_fgbrush ;
emr_selectobject_t emr_selectobject_bgbrush ;
2022-07-14 16:01:30 +01:00
emr_selectobject_t emr_selectobject_colour [ 9 ] ; /* Used for colour symbols only */
2016-12-23 16:48:03 +00:00
emr_createpen_t emr_createpen ;
emr_selectobject_t emr_selectobject_pen ;
emr_rectangle_t background ;
2020-08-04 13:12:47 +01:00
emr_settextcolor_t emr_settextcolor ;
2020-09-30 12:19:12 +01:00
2020-12-23 10:57:24 +00:00
float fsize ;
2020-09-30 12:19:12 +01:00
emr_extcreatefontindirectw_t emr_extcreatefontindirectw ;
2016-12-23 16:48:03 +00:00
emr_selectobject_t emr_selectobject_font ;
2020-12-23 10:57:24 +00:00
float fsize2 ;
2020-09-30 12:19:12 +01:00
emr_extcreatefontindirectw_t emr_extcreatefontindirectw2 ;
emr_selectobject_t emr_selectobject_font2 ;
int halign ;
emr_settextalign_t emr_settextalign ;
int halign1 ;
emr_settextalign_t emr_settextalign1 ;
int halign2 ;
emr_settextalign_t emr_settextalign2 ;
2020-12-23 10:57:24 +00:00
float current_fsize ;
2020-09-30 12:19:12 +01:00
int current_halign ;
2017-10-23 21:37:52 +02:00
2018-11-02 09:09:38 +01:00
emr_rectangle_t * rectangle ;
emr_ellipse_t * circle ;
emr_polygon_t * hexagon ;
2021-07-26 15:29:05 +01:00
if ( symbol - > vector = = NULL ) {
strcpy ( symbol - > errtxt , " 643: Vector header NULL " ) ;
return ZINT_ERROR_INVALID_DATA ;
}
2016-12-23 16:48:03 +00:00
fgred = ( 16 * ctoi ( symbol - > fgcolour [ 0 ] ) ) + ctoi ( symbol - > fgcolour [ 1 ] ) ;
fggrn = ( 16 * ctoi ( symbol - > fgcolour [ 2 ] ) ) + ctoi ( symbol - > fgcolour [ 3 ] ) ;
fgblu = ( 16 * ctoi ( symbol - > fgcolour [ 4 ] ) ) + ctoi ( symbol - > fgcolour [ 5 ] ) ;
bgred = ( 16 * ctoi ( symbol - > bgcolour [ 0 ] ) ) + ctoi ( symbol - > bgcolour [ 1 ] ) ;
bggrn = ( 16 * ctoi ( symbol - > bgcolour [ 2 ] ) ) + ctoi ( symbol - > bgcolour [ 3 ] ) ;
bgblu = ( 16 * ctoi ( symbol - > bgcolour [ 4 ] ) ) + ctoi ( symbol - > bgcolour [ 5 ] ) ;
2021-06-10 11:15:39 +01:00
2020-08-02 22:26:39 +01:00
if ( strlen ( symbol - > bgcolour ) > 6 ) {
if ( ( ctoi ( symbol - > bgcolour [ 6 ] ) = = 0 ) & & ( ctoi ( symbol - > bgcolour [ 7 ] ) = = 0 ) ) {
draw_background = 0 ;
}
}
2017-10-23 21:37:52 +02:00
2016-12-23 16:48:03 +00:00
rectangle_count = count_rectangles ( symbol ) ;
circle_count = count_circles ( symbol ) ;
hexagon_count = count_hexagons ( symbol ) ;
2020-09-30 12:19:12 +01:00
string_count = count_strings ( symbol , & fsize , & fsize2 , & halign , & halign1 , & halign2 ) ;
2016-12-23 16:48:03 +00:00
2022-07-14 16:01:30 +01:00
/* Avoid sanitize runtime error by making always non-zero */
rectangle = ( emr_rectangle_t * ) z_alloca ( sizeof ( emr_rectangle_t ) * ( rectangle_count ? rectangle_count : 1 ) ) ;
circle = ( emr_ellipse_t * ) z_alloca ( sizeof ( emr_ellipse_t ) * ( circle_count ? circle_count : 1 ) ) ;
hexagon = ( emr_polygon_t * ) z_alloca ( sizeof ( emr_polygon_t ) * ( hexagon_count ? hexagon_count : 1 ) ) ;
2020-01-13 19:24:01 +00:00
2022-07-14 16:01:30 +01:00
/* Calculate how many coloured rectangles */
2020-01-13 19:24:01 +00:00
if ( symbol - > symbology = = BARCODE_ULTRA ) {
rect = symbol - > vector - > rectangles ;
while ( rect ) {
2021-07-26 15:29:05 +01:00
if ( rect - > colour = = - 1 ) { /* Foreground colour */
if ( rectangle_bycolour [ 0 ] = = 0 ) {
colours_used + + ;
rectangle_bycolour [ 0 ] = 1 ;
}
} else {
if ( rectangle_bycolour [ rect - > colour ] = = 0 ) {
colours_used + + ;
rectangle_bycolour [ rect - > colour ] = 1 ;
}
2020-01-13 19:24:01 +00:00
}
rect = rect - > next ;
}
}
2021-07-26 15:29:05 +01:00
width = ( int ) ceilf ( symbol - > vector - > width ) ;
height = ( int ) ceilf ( symbol - > vector - > height ) ;
2020-09-30 12:19:12 +01:00
2016-12-23 16:48:03 +00:00
/* Header */
2022-07-14 16:01:30 +01:00
emr_header . type = 0x00000001 ; /* EMR_HEADER */
emr_header . size = 108 ; /* Including extensions */
2016-12-23 16:48:03 +00:00
emr_header . emf_header . bounds . left = 0 ;
2020-09-30 12:19:12 +01:00
emr_header . emf_header . bounds . right = rotate_angle = = 90 | | rotate_angle = = 270 ? height : width ;
emr_header . emf_header . bounds . bottom = rotate_angle = = 90 | | rotate_angle = = 270 ? width : height ;
2016-12-23 16:48:03 +00:00
emr_header . emf_header . bounds . top = 0 ;
emr_header . emf_header . frame . left = 0 ;
emr_header . emf_header . frame . right = emr_header . emf_header . bounds . right * 30 ;
emr_header . emf_header . frame . top = 0 ;
emr_header . emf_header . frame . bottom = emr_header . emf_header . bounds . bottom * 30 ;
2022-07-14 16:01:30 +01:00
emr_header . emf_header . record_signature = 0x464d4520 ; /* ENHMETA_SIGNATURE */
2018-06-10 09:16:18 +01:00
emr_header . emf_header . version = 0x00010000 ;
2020-08-12 15:10:48 +01:00
if ( symbol - > symbology = = BARCODE_ULTRA ) {
2022-07-14 16:01:30 +01:00
emr_header . emf_header . handles = 12 ; /* Number of graphics objects */
2020-08-12 15:10:48 +01:00
} else {
2020-12-23 10:57:24 +00:00
emr_header . emf_header . handles = fsize2 ! = 0.0f ? 5 : 4 ;
2020-08-12 15:10:48 +01:00
}
2016-12-23 16:48:03 +00:00
emr_header . emf_header . reserved = 0x0000 ;
emr_header . emf_header . n_description = 0 ;
emr_header . emf_header . off_description = 0 ;
emr_header . emf_header . n_pal_entries = 0 ;
emr_header . emf_header . device . cx = 1000 ;
emr_header . emf_header . device . cy = 1000 ;
emr_header . emf_header . millimeters . cx = 300 ;
emr_header . emf_header . millimeters . cy = 300 ;
2020-04-19 18:46:14 +01:00
/* HeaderExtension1 */
2022-07-14 16:01:30 +01:00
emr_header . emf_header . cb_pixel_format = 0x0000 ; /* None set */
emr_header . emf_header . off_pixel_format = 0x0000 ; /* None set */
emr_header . emf_header . b_open_gl = 0x0000 ; /* OpenGL not present */
2020-04-19 18:46:14 +01:00
/* HeaderExtension2 */
emr_header . emf_header . micrometers . cx = 0 ;
emr_header . emf_header . micrometers . cy = 0 ;
bytecount = 108 ;
2016-12-23 16:48:03 +00:00
recordcount = 1 ;
2022-07-14 16:01:30 +01:00
emr_mapmode . type = 0x00000011 ; /* EMR_SETMAPMODE */
2020-09-30 12:19:12 +01:00
emr_mapmode . size = 12 ;
2022-07-14 16:01:30 +01:00
emr_mapmode . mapmode = 0x01 ; /* MM_TEXT */
2020-09-30 12:19:12 +01:00
bytecount + = 12 ;
recordcount + + ;
if ( rotate_angle ) {
2022-07-14 16:01:30 +01:00
emr_setworldtransform . type = 0x00000023 ; /* EMR_SETWORLDTRANSFORM */
2020-09-30 12:19:12 +01:00
emr_setworldtransform . size = 32 ;
emr_setworldtransform . m11 = rotate_angle = = 90 ? 0.0f : rotate_angle = = 180 ? - 1.0f : 0.0f ;
emr_setworldtransform . m12 = rotate_angle = = 90 ? 1.0f : rotate_angle = = 180 ? 0.0f : - 1.0f ;
emr_setworldtransform . m21 = rotate_angle = = 90 ? - 1.0f : rotate_angle = = 180 ? 0.0f : 1.0f ;
emr_setworldtransform . m22 = rotate_angle = = 90 ? 0.0f : rotate_angle = = 180 ? - 1.0f : 0.0f ;
emr_setworldtransform . dx = rotate_angle = = 90 ? height : rotate_angle = = 180 ? width : 0.0f ;
emr_setworldtransform . dy = rotate_angle = = 90 ? 0.0f : rotate_angle = = 180 ? height : width ;
bytecount + = 32 ;
recordcount + + ;
}
2016-12-23 16:48:03 +00:00
/* Create Brushes */
2022-07-14 16:01:30 +01:00
emr_createbrushindirect_bg . type = 0x00000027 ; /* EMR_CREATEBRUSHINDIRECT */
2016-12-23 16:48:03 +00:00
emr_createbrushindirect_bg . size = 24 ;
2020-01-13 19:24:01 +00:00
emr_createbrushindirect_bg . ih_brush = 1 ;
2022-07-14 16:01:30 +01:00
emr_createbrushindirect_bg . log_brush . brush_style = 0x0000 ; /* BS_SOLID */
2016-12-23 16:48:03 +00:00
emr_createbrushindirect_bg . log_brush . color . red = bgred ;
emr_createbrushindirect_bg . log_brush . color . green = bggrn ;
emr_createbrushindirect_bg . log_brush . color . blue = bgblu ;
emr_createbrushindirect_bg . log_brush . color . reserved = 0 ;
2022-07-14 16:01:30 +01:00
emr_createbrushindirect_bg . log_brush . brush_hatch = 0x0006 ; /* HS_SOLIDCLR */
2016-12-23 16:48:03 +00:00
bytecount + = 24 ;
recordcount + + ;
2017-10-23 21:37:52 +02:00
2020-01-13 19:24:01 +00:00
if ( symbol - > symbology = = BARCODE_ULTRA ) {
2021-07-26 15:29:05 +01:00
for ( i = 0 ; i < 9 ; i + + ) {
2022-07-14 16:01:30 +01:00
emr_createbrushindirect_colour [ i ] . type = 0x00000027 ; /* EMR_CREATEBRUSHINDIRECT */
2020-01-13 19:24:01 +00:00
emr_createbrushindirect_colour [ i ] . size = 24 ;
emr_createbrushindirect_colour [ i ] . ih_brush = 2 + i ;
2022-07-14 16:01:30 +01:00
emr_createbrushindirect_colour [ i ] . log_brush . brush_style = 0x0000 ; /* BS_SOLID */
2021-07-26 15:29:05 +01:00
if ( i = = 0 ) {
emr_createbrushindirect_colour [ i ] . log_brush . color . red = fgred ;
emr_createbrushindirect_colour [ i ] . log_brush . color . green = fggrn ;
emr_createbrushindirect_colour [ i ] . log_brush . color . blue = fgblu ;
} else {
emr_createbrushindirect_colour [ i ] . log_brush . color . red = colour_to_red ( i ) ;
emr_createbrushindirect_colour [ i ] . log_brush . color . green = colour_to_green ( i ) ;
emr_createbrushindirect_colour [ i ] . log_brush . color . blue = colour_to_blue ( i ) ;
}
2020-01-13 19:24:01 +00:00
emr_createbrushindirect_colour [ i ] . log_brush . color . reserved = 0 ;
2022-07-14 16:01:30 +01:00
emr_createbrushindirect_colour [ i ] . log_brush . brush_hatch = 0x0006 ; /* HS_SOLIDCLR */
2020-01-13 19:24:01 +00:00
}
bytecount + = colours_used * 24 ;
recordcount + = colours_used ;
} else {
2022-07-14 16:01:30 +01:00
emr_createbrushindirect_fg . type = 0x00000027 ; /* EMR_CREATEBRUSHINDIRECT */
2020-01-13 19:24:01 +00:00
emr_createbrushindirect_fg . size = 24 ;
emr_createbrushindirect_fg . ih_brush = 2 ;
2022-07-14 16:01:30 +01:00
emr_createbrushindirect_fg . log_brush . brush_style = 0x0000 ; /* BS_SOLID */
2020-01-13 19:24:01 +00:00
emr_createbrushindirect_fg . log_brush . color . red = fgred ;
emr_createbrushindirect_fg . log_brush . color . green = fggrn ;
emr_createbrushindirect_fg . log_brush . color . blue = fgblu ;
emr_createbrushindirect_fg . log_brush . color . reserved = 0 ;
2022-07-14 16:01:30 +01:00
emr_createbrushindirect_fg . log_brush . brush_hatch = 0x0006 ; /* HS_SOLIDCLR */
2020-01-13 19:24:01 +00:00
bytecount + = 24 ;
recordcount + + ;
}
2017-10-23 21:37:52 +02:00
2022-07-14 16:01:30 +01:00
emr_selectobject_bgbrush . type = 0x00000025 ; /* EMR_SELECTOBJECT */
2016-12-23 16:48:03 +00:00
emr_selectobject_bgbrush . size = 12 ;
2020-01-13 19:24:01 +00:00
emr_selectobject_bgbrush . ih_object = 1 ;
2016-12-23 16:48:03 +00:00
bytecount + = 12 ;
recordcount + + ;
2020-01-13 19:24:01 +00:00
if ( symbol - > symbology = = BARCODE_ULTRA ) {
2021-07-26 15:29:05 +01:00
for ( i = 0 ; i < 9 ; i + + ) {
2022-07-14 16:01:30 +01:00
emr_selectobject_colour [ i ] . type = 0x00000025 ; /* EMR_SELECTOBJECT */
2020-01-13 19:24:01 +00:00
emr_selectobject_colour [ i ] . size = 12 ;
emr_selectobject_colour [ i ] . ih_object = 2 + i ;
}
bytecount + = colours_used * 12 ;
recordcount + = colours_used ;
} else {
2022-07-14 16:01:30 +01:00
emr_selectobject_fgbrush . type = 0x00000025 ; /* EMR_SELECTOBJECT */
2020-01-13 19:24:01 +00:00
emr_selectobject_fgbrush . size = 12 ;
emr_selectobject_fgbrush . ih_object = 2 ;
bytecount + = 12 ;
recordcount + + ;
}
2016-12-23 16:48:03 +00:00
/* Create Pens */
2022-07-14 16:01:30 +01:00
emr_createpen . type = 0x00000026 ; /* EMR_CREATEPEN */
2016-12-23 16:48:03 +00:00
emr_createpen . size = 28 ;
2021-07-26 15:29:05 +01:00
emr_createpen . ih_pen = 11 ;
2022-07-14 16:01:30 +01:00
emr_createpen . log_pen . pen_style = 0x00000005 ; /* PS_NULL */
2016-12-23 16:48:03 +00:00
emr_createpen . log_pen . width . x = 1 ;
2022-07-14 16:01:30 +01:00
emr_createpen . log_pen . width . y = 0 ; /* ignored */
2016-12-23 16:48:03 +00:00
emr_createpen . log_pen . color_ref . red = 0 ;
emr_createpen . log_pen . color_ref . green = 0 ;
emr_createpen . log_pen . color_ref . blue = 0 ;
emr_createpen . log_pen . color_ref . reserved = 0 ;
bytecount + = 28 ;
recordcount + + ;
2017-10-23 21:37:52 +02:00
2022-07-14 16:01:30 +01:00
emr_selectobject_pen . type = 0x00000025 ; /* EMR_SELECTOBJECT */
2016-12-23 16:48:03 +00:00
emr_selectobject_pen . size = 12 ;
2021-07-26 15:29:05 +01:00
emr_selectobject_pen . ih_object = 11 ;
2016-12-23 16:48:03 +00:00
bytecount + = 12 ;
recordcount + + ;
2017-10-23 21:37:52 +02:00
2020-08-02 22:26:39 +01:00
if ( draw_background ) {
/* Make background from a rectangle */
2022-07-14 16:01:30 +01:00
background . type = 0x0000002b ; /* EMR_RECTANGLE */
2020-08-02 22:26:39 +01:00
background . size = 24 ;
background . box . top = 0 ;
background . box . left = 0 ;
background . box . right = emr_header . emf_header . bounds . right ;
background . box . bottom = emr_header . emf_header . bounds . bottom ;
bytecount + = 24 ;
recordcount + + ;
}
2018-06-10 09:16:18 +01:00
2022-07-14 16:01:30 +01:00
/* Rectangles */
2018-06-10 09:16:18 +01:00
rect = symbol - > vector - > rectangles ;
this_rectangle = 0 ;
while ( rect ) {
2022-07-14 16:01:30 +01:00
rectangle [ this_rectangle ] . type = 0x0000002b ; /* EMR_RECTANGLE */
2018-06-10 09:16:18 +01:00
rectangle [ this_rectangle ] . size = 24 ;
2020-12-23 10:57:24 +00:00
rectangle [ this_rectangle ] . box . top = ( int32_t ) rect - > y ;
2021-10-20 23:05:30 +01:00
rectangle [ this_rectangle ] . box . bottom = ( int32_t ) stripf ( rect - > y + rect - > height ) ;
2020-12-23 10:57:24 +00:00
rectangle [ this_rectangle ] . box . left = ( int32_t ) rect - > x ;
2021-10-20 23:05:30 +01:00
rectangle [ this_rectangle ] . box . right = ( int32_t ) stripf ( rect - > x + rect - > width ) ;
2018-06-10 09:16:18 +01:00
this_rectangle + + ;
bytecount + = 24 ;
recordcount + + ;
rect = rect - > next ;
}
2022-07-14 16:01:30 +01:00
/* Circles */
2020-10-26 12:21:43 +00:00
previous_diameter = radius = 0.0f ;
2018-06-10 09:16:18 +01:00
circ = symbol - > vector - > circles ;
this_circle = 0 ;
while ( circ ) {
2021-08-22 13:59:01 +01:00
/* Note using circle width the proper way, with a non-null pen of specified width and a null brush for fill,
causes various different rendering issues for LibreOffice Draw and Inkscape , so using following hack */
if ( previous_diameter ! = circ - > diameter + circ - > width ) { /* Drawing MaxiCode bullseye using overlayed discs */
previous_diameter = circ - > diameter + circ - > width ;
2021-08-27 18:07:05 +01:00
radius = mul3dpf ( 0.5 , previous_diameter ) ;
2020-10-26 12:21:43 +00:00
}
2022-07-14 16:01:30 +01:00
circle [ this_circle ] . type = 0x0000002a ; /* EMR_ELLIPSE */
2018-06-10 09:16:18 +01:00
circle [ this_circle ] . size = 24 ;
2021-10-20 23:05:30 +01:00
circle [ this_circle ] . box . top = ( int32_t ) stripf ( circ - > y - radius ) ;
circle [ this_circle ] . box . bottom = ( int32_t ) stripf ( circ - > y + radius ) ;
circle [ this_circle ] . box . left = ( int32_t ) stripf ( circ - > x - radius ) ;
circle [ this_circle ] . box . right = ( int32_t ) stripf ( circ - > x + radius ) ;
2018-06-10 09:16:18 +01:00
this_circle + + ;
bytecount + = 24 ;
recordcount + + ;
2021-08-22 13:59:01 +01:00
if ( symbol - > symbology = = BARCODE_MAXICODE ) { /* Drawing MaxiCode bullseye using overlayed discs */
float inner_radius = radius - circ - > width ;
2022-07-14 16:01:30 +01:00
circle [ this_circle ] . type = 0x0000002a ; /* EMR_ELLIPSE */
2021-08-22 13:59:01 +01:00
circle [ this_circle ] . size = 24 ;
2021-10-20 23:05:30 +01:00
circle [ this_circle ] . box . top = ( int32_t ) stripf ( circ - > y - inner_radius ) ;
circle [ this_circle ] . box . bottom = ( int32_t ) stripf ( circ - > y + inner_radius ) ;
circle [ this_circle ] . box . left = ( int32_t ) stripf ( circ - > x - inner_radius ) ;
circle [ this_circle ] . box . right = ( int32_t ) stripf ( circ - > x + inner_radius ) ;
2021-08-22 13:59:01 +01:00
this_circle + + ;
bytecount + = 24 ;
recordcount + + ;
}
2018-06-10 09:16:18 +01:00
circ = circ - > next ;
}
2022-07-14 16:01:30 +01:00
/* Hexagons */
2020-10-26 12:21:43 +00:00
previous_diameter = radius = half_radius = half_sqrt3_radius = 0.0f ;
2018-06-10 09:16:18 +01:00
hex = symbol - > vector - > hexagons ;
this_hexagon = 0 ;
while ( hex ) {
2022-07-14 16:01:30 +01:00
hexagon [ this_hexagon ] . type = 0x00000003 ; /* EMR_POLYGON */
2018-06-10 09:16:18 +01:00
hexagon [ this_hexagon ] . size = 76 ;
hexagon [ this_hexagon ] . count = 6 ;
2020-10-26 12:21:43 +00:00
if ( previous_diameter ! = hex - > diameter ) {
previous_diameter = hex - > diameter ;
2021-08-27 18:07:05 +01:00
radius = mul3dpf ( 0.5 , previous_diameter ) ;
half_radius = mul3dpf ( 0.25 , previous_diameter ) ;
half_sqrt3_radius = mul3dpf ( 0.43301270189221932338 , previous_diameter ) ;
2020-10-26 12:21:43 +00:00
}
2018-06-10 09:16:18 +01:00
2021-07-26 15:29:05 +01:00
/* Note rotation done via world transform */
2021-10-20 23:05:30 +01:00
hexagon [ this_hexagon ] . a_points_a . x = ( int32_t ) hex - > x ;
hexagon [ this_hexagon ] . a_points_a . y = ( int32_t ) stripf ( hex - > y + radius ) ;
hexagon [ this_hexagon ] . a_points_b . x = ( int32_t ) stripf ( hex - > x + half_sqrt3_radius ) ;
hexagon [ this_hexagon ] . a_points_b . y = ( int32_t ) stripf ( hex - > y + half_radius ) ;
hexagon [ this_hexagon ] . a_points_c . x = ( int32_t ) stripf ( hex - > x + half_sqrt3_radius ) ;
hexagon [ this_hexagon ] . a_points_c . y = ( int32_t ) stripf ( hex - > y - half_radius ) ;
hexagon [ this_hexagon ] . a_points_d . x = ( int32_t ) hex - > x ;
hexagon [ this_hexagon ] . a_points_d . y = ( int32_t ) stripf ( hex - > y - radius ) ;
hexagon [ this_hexagon ] . a_points_e . x = ( int32_t ) stripf ( hex - > x - half_sqrt3_radius ) ;
hexagon [ this_hexagon ] . a_points_e . y = ( int32_t ) stripf ( hex - > y - half_radius ) ;
hexagon [ this_hexagon ] . a_points_f . x = ( int32_t ) stripf ( hex - > x - half_sqrt3_radius ) ;
hexagon [ this_hexagon ] . a_points_f . y = ( int32_t ) stripf ( hex - > y + half_radius ) ;
2018-06-10 09:16:18 +01:00
hexagon [ this_hexagon ] . bounds . top = hexagon [ this_hexagon ] . a_points_d . y ;
hexagon [ this_hexagon ] . bounds . bottom = hexagon [ this_hexagon ] . a_points_a . y ;
hexagon [ this_hexagon ] . bounds . left = hexagon [ this_hexagon ] . a_points_e . x ;
hexagon [ this_hexagon ] . bounds . right = hexagon [ this_hexagon ] . a_points_c . x ;
this_hexagon + + ;
bytecount + = 76 ;
recordcount + + ;
hex = hex - > next ;
}
2020-09-30 12:19:12 +01:00
/* Create font records, alignment records and text color */
2018-06-10 09:16:18 +01:00
if ( symbol - > vector - > strings ) {
2020-12-23 10:57:24 +00:00
bold = ( symbol - > output_options & BOLD_TEXT ) & &
( ! is_extendable ( symbol - > symbology ) | | ( symbol - > output_options & SMALL_TEXT ) ) ;
2020-09-30 12:19:12 +01:00
memset ( & emr_extcreatefontindirectw , 0 , sizeof ( emr_extcreatefontindirectw ) ) ;
2022-07-14 16:01:30 +01:00
emr_extcreatefontindirectw . type = 0x00000052 ; /* EMR_EXTCREATEFONTINDIRECTW */
2016-12-23 16:48:03 +00:00
emr_extcreatefontindirectw . size = 104 ;
2021-07-26 15:29:05 +01:00
emr_extcreatefontindirectw . ih_fonts = 12 ;
2020-12-23 10:57:24 +00:00
emr_extcreatefontindirectw . elw . height = ( int32_t ) fsize ;
2022-07-14 16:01:30 +01:00
emr_extcreatefontindirectw . elw . width = 0 ; /* automatic */
2020-09-30 12:19:12 +01:00
emr_extcreatefontindirectw . elw . weight = bold ? 700 : 400 ;
2022-07-14 16:01:30 +01:00
emr_extcreatefontindirectw . elw . char_set = 0x00 ; /* ANSI_CHARSET */
emr_extcreatefontindirectw . elw . out_precision = 0x00 ; /* OUT_DEFAULT_PRECIS */
emr_extcreatefontindirectw . elw . clip_precision = 0x00 ; /* CLIP_DEFAULT_PRECIS */
emr_extcreatefontindirectw . elw . pitch_and_family = 0x02 | ( 0x02 < < 6 ) ; /* FF_SWISS | VARIABLE_PITCH */
2021-08-10 12:04:25 +01:00
utfle_copy ( emr_extcreatefontindirectw . elw . facename , ( unsigned char * ) " sans-serif " , 10 ) ;
2018-06-10 09:16:18 +01:00
bytecount + = 104 ;
recordcount + + ;
2020-09-30 12:19:12 +01:00
2022-07-14 16:01:30 +01:00
emr_selectobject_font . type = 0x00000025 ; /* EMR_SELECTOBJECT */
2016-12-23 16:48:03 +00:00
emr_selectobject_font . size = 12 ;
2021-07-26 15:29:05 +01:00
emr_selectobject_font . ih_object = 12 ;
2018-06-10 09:16:18 +01:00
bytecount + = 12 ;
2016-12-23 16:48:03 +00:00
recordcount + + ;
2020-09-30 12:19:12 +01:00
if ( fsize2 ) {
memcpy ( & emr_extcreatefontindirectw2 , & emr_extcreatefontindirectw , sizeof ( emr_extcreatefontindirectw ) ) ;
2021-07-26 15:29:05 +01:00
emr_extcreatefontindirectw2 . ih_fonts = 13 ;
2020-12-23 10:57:24 +00:00
emr_extcreatefontindirectw2 . elw . height = ( int32_t ) fsize2 ;
2020-09-30 12:19:12 +01:00
bytecount + = 104 ;
recordcount + + ;
2022-07-14 16:01:30 +01:00
emr_selectobject_font2 . type = 0x00000025 ; /* EMR_SELECTOBJECT */
2020-09-30 12:19:12 +01:00
emr_selectobject_font2 . size = 12 ;
2021-07-26 15:29:05 +01:00
emr_selectobject_font2 . ih_object = 13 ;
2020-09-30 12:19:12 +01:00
bytecount + = 12 ;
recordcount + + ;
}
/* Note select aligns counted below in strings loop */
2022-07-14 16:01:30 +01:00
emr_settextalign . type = 0x00000016 ; /* EMR_SETTEXTALIGN */
2020-09-30 12:19:12 +01:00
emr_settextalign . size = 12 ;
2022-07-14 16:01:30 +01:00
emr_settextalign . text_alignment_mode = 0x0006 | 0x0018 ; /* TA_CENTER | TA_BASELINE */
2020-09-30 12:19:12 +01:00
if ( halign1 ) {
2022-07-14 16:01:30 +01:00
emr_settextalign1 . type = 0x00000016 ; /* EMR_SETTEXTALIGN */
2020-09-30 12:19:12 +01:00
emr_settextalign1 . size = 12 ;
2022-07-14 16:01:30 +01:00
emr_settextalign1 . text_alignment_mode = 0x0000 | 0x0018 ; /* TA_LEFT | TA_BASELINE */
2020-09-30 12:19:12 +01:00
}
if ( halign2 ) {
2022-07-14 16:01:30 +01:00
emr_settextalign2 . type = 0x00000016 ; /* EMR_SETTEXTALIGN */
2020-09-30 12:19:12 +01:00
emr_settextalign2 . size = 12 ;
2022-07-14 16:01:30 +01:00
emr_settextalign2 . text_alignment_mode = 0x0002 | 0x0018 ; /* TA_RIGHT | TA_BASELINE */
2020-09-30 12:19:12 +01:00
}
2022-07-14 16:01:30 +01:00
emr_settextcolor . type = 0x0000018 ; /* EMR_SETTEXTCOLOR */
2020-08-04 13:12:47 +01:00
emr_settextcolor . size = 12 ;
emr_settextcolor . color . red = fgred ;
emr_settextcolor . color . green = fggrn ;
emr_settextcolor . color . blue = fgblu ;
emr_settextcolor . color . reserved = 0 ;
bytecount + = 12 ;
recordcount + + ;
2016-12-23 16:48:03 +00:00
}
2022-07-14 16:01:30 +01:00
/* Text */
2018-06-10 09:16:18 +01:00
this_text = 0 ;
2022-07-14 16:01:30 +01:00
/* Loop over font sizes so that they're grouped together, so only have to select font twice at most */
2021-07-26 15:29:05 +01:00
for ( i = 0 , current_fsize = fsize ; i < 2 & & current_fsize ; i + + , current_fsize = fsize2 ) {
2020-09-30 12:19:12 +01:00
str = symbol - > vector - > strings ;
current_halign = - 1 ;
while ( str ) {
2021-07-26 15:29:05 +01:00
int utfle_len ;
int bumped_len ;
2020-09-30 12:19:12 +01:00
if ( str - > fsize ! = current_fsize ) {
str = str - > next ;
continue ;
}
text_fsizes [ this_text ] = str - > fsize ;
text_haligns [ this_text ] = str - > halign ;
if ( text_haligns [ this_text ] ! = current_halign ) {
current_halign = text_haligns [ this_text ] ;
bytecount + = 12 ;
recordcount + + ;
}
assert ( str - > length > 0 ) ;
utfle_len = utfle_length ( str - > text , str - > length ) ;
bumped_len = bump_up ( utfle_len ) * 2 ;
2021-06-29 15:43:42 +01:00
if ( ! ( this_string [ this_text ] = ( unsigned char * ) malloc ( bumped_len ) ) ) {
for ( i = 0 ; i < this_text ; i + + ) {
free ( this_string [ i ] ) ;
}
strcpy ( symbol - > errtxt , " 641: Insufficient memory for EMF string buffer " ) ;
return ZINT_ERROR_MEMORY ;
}
2020-09-30 12:19:12 +01:00
memset ( this_string [ this_text ] , 0 , bumped_len ) ;
2022-07-14 16:01:30 +01:00
text [ this_text ] . type = 0x00000054 ; /* EMR_EXTTEXTOUTW */
2020-09-30 12:19:12 +01:00
text [ this_text ] . size = 76 + bumped_len ;
2022-07-14 16:01:30 +01:00
text [ this_text ] . bounds . top = 0 ; /* ignored */
text [ this_text ] . bounds . left = 0 ; /* ignored */
text [ this_text ] . bounds . right = 0xffffffff ; /* ignored */
text [ this_text ] . bounds . bottom = 0xffffffff ; /* ignored */
text [ this_text ] . i_graphics_mode = 0x00000002 ; /* GM_ADVANCED */
2020-09-30 12:19:12 +01:00
text [ this_text ] . ex_scale = 1.0f ;
text [ this_text ] . ey_scale = 1.0f ;
2020-12-23 10:57:24 +00:00
text [ this_text ] . w_emr_text . reference . x = ( int32_t ) str - > x ;
text [ this_text ] . w_emr_text . reference . y = ( int32_t ) str - > y ;
2020-09-30 12:19:12 +01:00
text [ this_text ] . w_emr_text . chars = utfle_len ;
text [ this_text ] . w_emr_text . off_string = 76 ;
text [ this_text ] . w_emr_text . options = 0 ;
text [ this_text ] . w_emr_text . rectangle . top = 0 ;
text [ this_text ] . w_emr_text . rectangle . left = 0 ;
text [ this_text ] . w_emr_text . rectangle . right = 0xffffffff ;
text [ this_text ] . w_emr_text . rectangle . bottom = 0xffffffff ;
text [ this_text ] . w_emr_text . off_dx = 0 ;
utfle_copy ( this_string [ this_text ] , str - > text , str - > length ) ;
bytecount + = 76 + bumped_len ;
recordcount + + ;
this_text + + ;
str = str - > next ;
}
2016-12-23 16:48:03 +00:00
}
2021-07-26 15:55:34 +01:00
/* Suppress clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult warning */
assert ( this_text = = string_count ) ;
2016-12-23 16:48:03 +00:00
/* Create EOF record */
2022-07-14 16:01:30 +01:00
emr_eof . type = 0x0000000e ; /* EMR_EOF */
emr_eof . size = 20 ; /* Assuming no palette entries */
2016-12-23 16:48:03 +00:00
emr_eof . n_pal_entries = 0 ;
emr_eof . off_pal_entries = 0 ;
emr_eof . size_last = emr_eof . size ;
2019-03-14 11:02:17 +00:00
bytecount + = 20 ;
2016-12-23 16:48:03 +00:00
recordcount + + ;
2017-10-23 21:37:52 +02:00
2018-06-10 09:16:18 +01:00
if ( symbol - > symbology = = BARCODE_MAXICODE ) {
2021-06-10 11:15:39 +01:00
bytecount + = 5 * sizeof ( emr_selectobject_t ) ;
2018-06-10 09:16:18 +01:00
recordcount + = 5 ;
}
2016-12-23 16:48:03 +00:00
/* Put final counts in header */
emr_header . emf_header . bytes = bytecount ;
emr_header . emf_header . records = recordcount ;
2017-10-23 21:37:52 +02:00
2016-12-23 16:48:03 +00:00
/* Send EMF data to file */
2021-07-26 15:29:05 +01:00
if ( output_to_stdout ) {
# ifdef _MSC_VER
if ( - 1 = = _setmode ( _fileno ( stdout ) , _O_BINARY ) ) {
sprintf ( symbol - > errtxt , " 642: Could not set stdout to binary (%d: %.30s) " , errno , strerror ( errno ) ) ;
return ZINT_ERROR_FILE_ACCESS ;
}
# endif
2016-12-23 16:48:03 +00:00
emf_file = stdout ;
} else {
2021-07-26 15:29:05 +01:00
if ( ! ( emf_file = fopen ( symbol - > outfile , " wb " ) ) ) {
sprintf ( symbol - > errtxt , " 640: Could not open output file (%d: %.30s) " , errno , strerror ( errno ) ) ;
return ZINT_ERROR_FILE_ACCESS ;
}
2016-12-23 16:48:03 +00:00
}
2017-10-23 21:37:52 +02:00
2021-06-10 11:15:39 +01:00
fwrite ( & emr_header , sizeof ( emr_header_t ) , 1 , emf_file ) ;
2017-10-23 21:37:52 +02:00
2021-06-10 11:15:39 +01:00
fwrite ( & emr_mapmode , sizeof ( emr_mapmode_t ) , 1 , emf_file ) ;
2020-09-30 12:19:12 +01:00
if ( rotate_angle ) {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_setworldtransform , sizeof ( emr_setworldtransform_t ) , 1 , emf_file ) ;
2020-09-30 12:19:12 +01:00
}
2021-06-10 11:15:39 +01:00
fwrite ( & emr_createbrushindirect_bg , sizeof ( emr_createbrushindirect_t ) , 1 , emf_file ) ;
2020-01-13 19:24:01 +00:00
if ( symbol - > symbology = = BARCODE_ULTRA ) {
2021-07-26 15:29:05 +01:00
for ( i = 0 ; i < 9 ; i + + ) {
if ( rectangle_bycolour [ i ] ) {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_createbrushindirect_colour [ i ] , sizeof ( emr_createbrushindirect_t ) , 1 , emf_file ) ;
2020-01-13 19:24:01 +00:00
}
}
} else {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_createbrushindirect_fg , sizeof ( emr_createbrushindirect_t ) , 1 , emf_file ) ;
2020-01-13 19:24:01 +00:00
}
2021-06-10 11:15:39 +01:00
fwrite ( & emr_createpen , sizeof ( emr_createpen_t ) , 1 , emf_file ) ;
2017-10-23 21:37:52 +02:00
2018-06-10 09:16:18 +01:00
if ( symbol - > vector - > strings ) {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_extcreatefontindirectw , sizeof ( emr_extcreatefontindirectw_t ) , 1 , emf_file ) ;
2020-09-30 12:19:12 +01:00
if ( fsize2 ) {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_extcreatefontindirectw2 , sizeof ( emr_extcreatefontindirectw_t ) , 1 , emf_file ) ;
2020-09-30 12:19:12 +01:00
}
2016-12-23 16:48:03 +00:00
}
2017-10-23 21:37:52 +02:00
2021-06-10 11:15:39 +01:00
fwrite ( & emr_selectobject_bgbrush , sizeof ( emr_selectobject_t ) , 1 , emf_file ) ;
fwrite ( & emr_selectobject_pen , sizeof ( emr_selectobject_t ) , 1 , emf_file ) ;
2020-08-02 22:26:39 +01:00
if ( draw_background ) {
2021-06-10 11:15:39 +01:00
fwrite ( & background , sizeof ( emr_rectangle_t ) , 1 , emf_file ) ;
2020-08-02 22:26:39 +01:00
}
2017-10-23 21:37:52 +02:00
2020-01-13 19:24:01 +00:00
if ( symbol - > symbology = = BARCODE_ULTRA ) {
2021-07-26 15:29:05 +01:00
for ( i = 0 ; i < 9 ; i + + ) {
if ( rectangle_bycolour [ i ] ) {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_selectobject_colour [ i ] , sizeof ( emr_selectobject_t ) , 1 , emf_file ) ;
2020-01-13 19:24:01 +00:00
rect = symbol - > vector - > rectangles ;
this_rectangle = 0 ;
while ( rect ) {
2021-07-26 15:29:05 +01:00
if ( ( i = = 0 & & rect - > colour = = - 1 ) | | rect - > colour = = i ) {
2021-06-10 11:15:39 +01:00
fwrite ( & rectangle [ this_rectangle ] , sizeof ( emr_rectangle_t ) , 1 , emf_file ) ;
2020-01-13 19:24:01 +00:00
}
this_rectangle + + ;
rect = rect - > next ;
}
}
}
} else {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_selectobject_fgbrush , sizeof ( emr_selectobject_t ) , 1 , emf_file ) ;
2016-12-23 16:48:03 +00:00
2022-07-14 16:01:30 +01:00
/* Rectangles */
2020-01-13 19:24:01 +00:00
for ( i = 0 ; i < rectangle_count ; i + + ) {
2021-06-10 11:15:39 +01:00
fwrite ( & rectangle [ i ] , sizeof ( emr_rectangle_t ) , 1 , emf_file ) ;
2020-01-13 19:24:01 +00:00
}
2016-12-23 16:48:03 +00:00
}
2017-10-23 21:37:52 +02:00
2022-07-14 16:01:30 +01:00
/* Hexagons */
2018-06-10 09:16:18 +01:00
for ( i = 0 ; i < hexagon_count ; i + + ) {
2021-06-10 11:15:39 +01:00
fwrite ( & hexagon [ i ] , sizeof ( emr_polygon_t ) , 1 , emf_file ) ;
2016-12-23 16:48:03 +00:00
}
2017-10-23 21:37:52 +02:00
2022-07-14 16:01:30 +01:00
/* Circles */
2018-06-10 09:16:18 +01:00
if ( symbol - > symbology = = BARCODE_MAXICODE ) {
2022-07-14 16:01:30 +01:00
/* Bullseye needed */
2018-06-10 09:16:18 +01:00
for ( i = 0 ; i < circle_count ; i + + ) {
2021-06-10 11:15:39 +01:00
fwrite ( & circle [ i ] , sizeof ( emr_ellipse_t ) , 1 , emf_file ) ;
2018-06-10 09:16:18 +01:00
if ( i < circle_count - 1 ) {
if ( i % 2 ) {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_selectobject_fgbrush , sizeof ( emr_selectobject_t ) , 1 , emf_file ) ;
2018-06-10 09:16:18 +01:00
} else {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_selectobject_bgbrush , sizeof ( emr_selectobject_t ) , 1 , emf_file ) ;
2016-12-23 16:48:03 +00:00
}
}
}
2018-06-10 09:16:18 +01:00
} else {
for ( i = 0 ; i < circle_count ; i + + ) {
2021-06-10 11:15:39 +01:00
fwrite ( & circle [ i ] , sizeof ( emr_ellipse_t ) , 1 , emf_file ) ;
2016-12-23 16:48:03 +00:00
}
2018-06-10 09:16:18 +01:00
}
2016-12-23 16:48:03 +00:00
2022-07-14 16:01:30 +01:00
/* Text */
2020-04-19 18:46:14 +01:00
if ( string_count > 0 ) {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_selectobject_font , sizeof ( emr_selectobject_t ) , 1 , emf_file ) ;
fwrite ( & emr_settextcolor , sizeof ( emr_settextcolor_t ) , 1 , emf_file ) ;
2020-04-19 18:46:14 +01:00
}
2020-05-05 22:51:04 +01:00
2020-09-30 12:19:12 +01:00
current_fsize = fsize ;
current_halign = - 1 ;
2018-06-10 09:16:18 +01:00
for ( i = 0 ; i < string_count ; i + + ) {
2020-12-23 10:57:24 +00:00
if ( text_fsizes [ i ] ! = current_fsize ) {
2020-09-30 12:19:12 +01:00
current_fsize = text_fsizes [ i ] ;
2021-06-10 11:15:39 +01:00
fwrite ( & emr_selectobject_font2 , sizeof ( emr_selectobject_t ) , 1 , emf_file ) ;
2020-09-30 12:19:12 +01:00
}
if ( text_haligns [ i ] ! = current_halign ) {
current_halign = text_haligns [ i ] ;
if ( current_halign = = 0 ) {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_settextalign , sizeof ( emr_settextalign_t ) , 1 , emf_file ) ;
2020-09-30 12:19:12 +01:00
} else if ( current_halign = = 1 ) {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_settextalign1 , sizeof ( emr_settextalign_t ) , 1 , emf_file ) ;
2020-09-30 12:19:12 +01:00
} else {
2021-06-10 11:15:39 +01:00
fwrite ( & emr_settextalign2 , sizeof ( emr_settextalign_t ) , 1 , emf_file ) ;
2020-09-30 12:19:12 +01:00
}
}
2021-06-10 11:15:39 +01:00
fwrite ( & text [ i ] , sizeof ( emr_exttextoutw_t ) , 1 , emf_file ) ;
2020-09-30 12:19:12 +01:00
fwrite ( this_string [ i ] , bump_up ( text [ i ] . w_emr_text . chars ) * 2 , 1 , emf_file ) ;
2020-04-04 16:53:29 +01:00
free ( this_string [ i ] ) ;
2016-12-23 16:48:03 +00:00
}
2017-10-23 21:37:52 +02:00
2021-06-10 11:15:39 +01:00
fwrite ( & emr_eof , sizeof ( emr_eof_t ) , 1 , emf_file ) ;
2017-10-23 21:37:52 +02:00
2021-07-26 15:29:05 +01:00
if ( output_to_stdout ) {
2016-12-23 16:48:03 +00:00
fflush ( emf_file ) ;
} else {
fclose ( emf_file ) ;
}
return error_number ;
}
2022-07-14 16:01:30 +01:00
/* vim: set ts=4 sw=4 et : */