%% options copyright owner = Dirk Krause copyright year = 2018-xxxx SPDX-License-Identifier: BSD-3-Clause %% header /** @file dk4grcoa.h Graphics configuration with application support. */ #ifndef DK4CONF_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4conf.h" #else #include #endif #endif #ifndef DK4APP_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4app.h" #else #include #endif #endif #ifndef DK4GRCO_H_INCLUDED #if DK4_BUILDING_DKTOOLS4 #include "dk4grco.h" #else #include #endif #endif #ifdef __cplusplus extern "C" { #endif /** Set up graphics configuration from text string and/or configuration file(s). @param conf Configuration structure to set up. @param txt Text containing information, may be NULL. @param usecfg Flag: Process configuration file. @param cfscope Configuration scopes allowed in txt. @param app Application structure for diagnostics, may be NULL. @return 1 on success (program can continue), 0 on error (abort program). */ int dk4gra_conf_setup( dk4_gra_conf_t *conf, dkChar const *txt, int usecfg, int cfscope, dk4_app_t *app ); #ifdef __cplusplus } #endif /* vim: set ai sw=4 ts=4 : */ %% module #ifndef DK4CONF_H_INCLUDED #include "dk4conf.h" #endif #ifndef DK4MPL_H_INCLUDED #include "dk4mpl.h" #endif #ifndef DK4FS_H_INCLUDED #include "dk4fs.h" #endif #ifndef DK4STRD_H_INCLUDED #include "dk4strd.h" #endif #ifndef DK4STRDA_H_INCLUDED #include "dk4strda.h" #endif #ifndef DK4TSPDK_H_INCLUDED #include "dk4tspdk.h" #endif #ifndef DK4STRMR_H_INCLUDED #include "dk4strmr.h" #endif #ifndef DK4PAPER_H_INCLUDED #include "dk4paper.h" #endif #ifndef DK4GRALO_H_INCLUDED #include "dk4gralo.h" #endif #ifndef DK4GRCOA_H_INCLUDED #include "dk4grcoa.h" #endif #ifndef DK4PAPEA_H_INCLUDED #include "dk4papea.h" #endif #ifndef DK4MAIDDII_H_INCLUDED #include "dk4maiddii.h" #endif #ifndef DK4MAIDDUI_H_INCLUDED #include "dk4maiddui.h" #endif #ifndef DK4MAIDDBL_H_INCLUDED #include "dk4maiddbl.h" #endif #ifndef DK4UNUSED_H_INCLUDED #include "dk4unused.h" #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif $!trace-include /** Driver names. */ static dkChar const * const dk4gra_conf_driver_names[] = { $!string-table macro=dkT pdf eps ps tex bb $!end }; /** Purpose names. */ static dkChar const * const dk4gra_conf_purpose_names[] = { $!string-table macro=dkT o$bject i$mage d$ocument $!end }; /** Names of configuration keys. Order of entries must match in dk4gra_conf_key_names, dk4gra_conf_cfgfile_key_names and dk4gra_conf_key_scopes. */ static dkChar const * const dk4gra_conf_key_names[] = { $!string-table macro=dkT # # 0 Allow color output # c$olor # # 1 How to use alpha channel # al$pha # # 2 Background RGB triple # b$g # # 3 Force image background # f$orce-bg # # 4 Allow image interpolation # in$terpolation # # 5 Use DCT-encoded data from JPEG files directly # dc$t # # 6 Allow image interpolation for DCT-encoded data from JPEG files # dct-$interpolation # # 7 Analyze bits per component, reduce if possible # a-b$pc # # 8 Analyze use of color, switch to grayscale if possible # a-c$olor # # 9 Analyze alpha channel, ignore if possible # a-a$lpha # # 10 Ignore resolution chunk from bitmap image files # i-$res # # 11 PS language level # le$vel # # 12 Allow LZW compression in PS 2 output # lz$w # # 13 Paper size # p$aper # # 14 Duplex printing # du$plex # # 15 Duplex and tumble # t$umble # # 16 Document structuring comments # ds$c # # 17 RGB to gray conversion method # rgb-to-gray # # 18 RGB to CMYK conversion method # rgb-to-cmyk # # 19 Ignore aspect ratio # i-a$spect # # 20 Allow to rotate image # ro$tate # # 21 Specified image resolution # resolution # # 22 X-spline sub segments # xss$s # # 23 X-spline length precision # xsl$p # # 24 X-spline parameter precision # xsp$p $!end }; /** Key names in configuration files. Order of entries must match in dk4gra_conf_key_names, dk4gra_conf_cfgfile_key_names and dk4gra_conf_key_scopes. */ static dkChar const * const dk4gra_conf_cfgfile_key_names[] = { $!string-table macro=dkT # # 0 Allow color output # color # # 1 How to use alpha channel # use alpha channel # # 2 Background RGB triple # image background # # 3 Force image background # force image background # # 4 Allow image interpolation # image interpolation # # 5 Use DCT-encoded data from JPEG files directly # use dct encoded data # # 6 Allow image interpolation for DCT-encoded data from JPEG files # dct image interpolation # # 7 Analyze bits per component, reduce if possible # analyze bits per component # # 8 Analyze use of color, switch to grayscale if possible # analyze colors # # 9 Analyze alpha channel, ignore if possible # analyze alpha # # 10 Ignore resolution chunk from bitmap image files # ignore resolution # # 11 PS language level # level # # 12 Allow LZW compression in PS 2 output # lzw # # 13 Paper size # paper size # # 14 Duplex printing # duplex # # 15 Duplex and tumble # tumble # # 16 Document structuring comments # dsc # # 17 RGB to gray conversion method # rgb to gray # # 18 RGB to CMYK conversion method # rgb to cmyk # # 19 Ignore aspect ratio # ignore aspect ratio # # 20 Allow to rotate image # allow rotate # # 21 Image resolution when processing just one image # resolution # # 22 Number of Bezier segements to draw per X-spline segment # x-spline sub segments # # 23 X-spline length precision # x-spline length precision # # 24 X-spline parameter precision # x-spline parameter precision $!end }; /** Constant text fragments. */ static const dkChar * const dk4gra_conf_txt[] = { $!string-table macro=dkT # # 0 Separator string # : \t\r\n\v\f # # 1 Configuration file name # dk4gra.conf # # 2 Match any driver or purpose # * $!end }; /** Names for alpha channel handling methods. */ static const dkChar * const dk4gra_conf_alpha_processing[] = { $!string-table macro=dkT m$ix f$oreground $!end }; /** Names of RGB to gray conversion methods. */ static const dkChar * const dk4gra_conf_rgb_to_gray_methods[] = { $!string-table macro=dkT bt6$01 l$uminance f$ast faste$st bt7$09 a$verage d$esaturation mi$n me$dian ma$x r$ed g$reen bl$ue $!end }; /** Method names for RGB to CMYK conversion. */ static const dkChar * const dk4gra_conf_rgb_to_cmyk_methods[] = { $!string-table macro=dkT n$on-standard s$tandard $!end }; /** Names for methods how to handle resolution. */ static const dkChar * const dk4gra_reso_names[] = { $!string-table macro=dkT 1$px1pt c$hunk $!end }; /** Scopes of configuration keys. Order of entries must match in dk4gra_conf_key_names, dk4gra_conf_cfgfile_key_names and dk4gra_conf_key_scopes. */ static const int dk4gra_conf_key_scopes[] = { /* 0 Allow color output */ DK4_GRA_CONF_SCOPE_SETUP , /* 1 How to use alpha channel */ DK4_GRA_CONF_SCOPE_IMAGE , /* 2 Background RGB triple */ DK4_GRA_CONF_SCOPE_IMAGE , /* 3 Force image background */ DK4_GRA_CONF_SCOPE_IMAGE , /* 4 Allow image interpolation */ DK4_GRA_CONF_SCOPE_IMAGE , /* 5 Use DCT-encoded data from JPEG files directly */ DK4_GRA_CONF_SCOPE_IMAGE , /* 6 Allow image interpolation for DCT-encoded data from JPEG files */ DK4_GRA_CONF_SCOPE_IMAGE , /* 7 Analyze bits per component, reduce if possible */ DK4_GRA_CONF_SCOPE_IMAGE , /* 8 Analyze use of color, switch to grayscale if possible */ DK4_GRA_CONF_SCOPE_IMAGE , /* 9 Analyze alpha channel, ignore if possible */ DK4_GRA_CONF_SCOPE_IMAGE , /* 10 Ignore resolution chunk from bitmap image files */ DK4_GRA_CONF_SCOPE_IMAGE , /* 11 PS language level */ DK4_GRA_CONF_SCOPE_SETUP , /* 12 Allow LZW compression in PS 2 output */ DK4_GRA_CONF_SCOPE_SETUP , /* 13 Paper size */ DK4_GRA_CONF_SCOPE_SETUP , /* 14 Duplex printing */ DK4_GRA_CONF_SCOPE_SETUP , /* 15 Duplex and tumble */ DK4_GRA_CONF_SCOPE_SETUP , /* 16 Document structuring comments */ DK4_GRA_CONF_SCOPE_SETUP , /* 17 RGB to gray conversion method */ DK4_GRA_CONF_SCOPE_SETUP , /* 18 RGB to CMYK conversion method */ DK4_GRA_CONF_SCOPE_SETUP, /* 19 Ignore aspect ratio of image */ DK4_GRA_CONF_SCOPE_IMAGE, /* 20 Allow image rotation to better fit into space */ DK4_GRA_CONF_SCOPE_IMAGE, /* 21 Image resolution when bmpp processes one image per page */ DK4_GRA_CONF_SCOPE_IMAGE, /* 22 Bezier segments per X-spline segment */ DK4_GRA_CONF_SCOPE_DRAW, /* 23 X-spline length precision */ DK4_GRA_CONF_SCOPE_DRAW, /* 24 X-spline parameter precision */ DK4_GRA_CONF_SCOPE_DRAW, }; /** Retrieve boolean value from value text. @param bptr Address of boolean variable. @param keyname Key name to use in diagnostics. @param value Value text, may be NULL. @param app Application structure for diagnostics, may be NULL. @return 1 on success (continue processing), 0 on error (abort). */ static int dk4gra_conf_bool( int *bptr, #if TRACE_DEBUG dkChar const *keyname, #else dkChar const * DK4_ARG_UNUSED(keyname), #endif dkChar const *value, dk4_app_t *app ) { int back = 1; #if (!(TRACE_DEBUG)) DK4_UNUSED_ARG(keyname) #endif $? "+ dk4gra_conf_bool \"%!ds\"=\"%!ds\"", TR_STR(keyname), TR_STR(value) #if DK4_USE_ASSERT assert(NULL != bptr); assert(NULL != value); #endif if (NULL != value) { if (0 != dk4str_is_bool(value)) { *bptr = dk4str_is_on(value); } else { /* ERROR: Not a boolean */ dk4gralog_3(app, DK4_LL_ERROR, 0, 1, value); back = 0; } } else { *bptr = 1; } $? "- dk4gra_conf_bool %d", back return back; } /** Retrieve method for RGB to gray conversion. @param conf Structure to configure. @param keyname Key name to use in diagnostics. @param value Value text, may be NULL. @param app Application structure for diagnostics, may be NULL. @return 1 on success (continue processing), 0 on error (abort). */ static int dk4gra_conf_rgb_to_gray( dk4_gra_conf_t *conf, dkChar const *keyname, dkChar const *value, dk4_app_t *app ) { int back = 0; int res; $? "+ dk4gra_conf_rgb_to_gray \"%!ds\"", TR_STR(value) #if DK4_USE_ASSERT assert(NULL != conf); assert(NULL != value); #endif if (NULL != value) { res = dk4str_abbr_index( dk4gra_conf_rgb_to_gray_methods, dkT('$'), value, 0 ); if (-1 < res) { back = 1; } switch (res) { case 0: { /* bt601 */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_ITU_BT601, NULL ); } break; case 1: { /* luminance */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_LUMA, NULL ); } break; case 2: { /* fast */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_FAST, NULL ); } break; case 3: { /* fastest */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_VERY_FAST, NULL ); } break; case 4: { /* bt709 */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_ITU_BT709, NULL ); } break; case 5: { /* average */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_AVERAGE, NULL ); } break; case 6: { /* desaturation */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_DESATURATION, NULL ); } break; case 7: { /* min */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_MIN_DECOMPOSITION, NULL ); } break; case 8: { /* medium */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_MEDIUM_DECOMPOSITION, NULL ); } break; case 9: { /* max */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_MAX_DECOMPOSITION, NULL ); } break; case 10: { /* red */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_CHANNEL_RED, NULL ); } break; case 11: { /* green */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_CHANNEL_GREEN, NULL ); } break; case 12: { /* blue */ back = 1; (void)dk4cs_context_set_rgb_to_gray( &(conf->ctx), DK4_CS_CONV_RGB_TO_GRAY_CHANNEL_BLUE, NULL ); } break; default : { /* ERROR: Unknown method name */ dk4gralog_3(app, DK4_LL_ERROR, 34, 35, value); } break; } } else { /* ERROR: Missing value */ dk4gralog_3(app, DK4_LL_ERROR, 20, 21, keyname); } $? "- dk4gra_conf_rgb_to_gray %d", back return back; } /** Retrieve method for RGB to CMYK conversion. @param conf Structure to configure. @param keyname Key name to use in diagnostics. @param value Value text, may be NULL. @param app Application structure for diagnostics, may be NULL. @return 1 on success (continue processing), 0 on error (abort). */ static int dk4gra_conf_rgb_to_cmyk( dk4_gra_conf_t *conf, dkChar const *keyname, dkChar const *value, dk4_app_t *app ) { int back = 0; int res; $? "+ dk4gra_conf_rgb_to_cmyk \"%!ds\"", TR_STR(value) #if DK4_USE_ASSERT assert(NULL != conf); assert(NULL != value); #endif if (NULL != value) { res = dk4str_abbr_index( dk4gra_conf_rgb_to_cmyk_methods, dkT('$'), value, 0 ); switch (res) { case 0: { /* non-standard */ back = 1; (void)dk4cs_context_set_rgb_to_cmyk( &(conf->ctx), DK4_CS_CONV_RGB_TO_CMYK_NOT_PS_PDF, NULL ); } break; case 1: { /* standard */ back = 1; (void)dk4cs_context_set_rgb_to_cmyk( &(conf->ctx), DK4_CS_CONV_RGB_TO_CMYK_PS_PDF, NULL ); } break; default: { /* ERROR: Unknown method */ dk4gralog_3(app, DK4_LL_ERROR, 36, 37, value); } break; } } else { /* ERROR: Value required */ dk4gralog_3(app, DK4_LL_ERROR, 20, 21, keyname); } $? "- dk4gra_conf_rgb_to_cmyk %d", back return back; } /** Retrieve alpha handling value from value text. @param conf Structure to configure. @param keyname Key name to use in diagnostics. @param value Value text, may be NULL. @param app Application structure for diagnostics, may be NULL. @return 1 on success (continue processing), 0 on error (abort). */ static int dk4gra_conf_alpha_handling( dk4_gra_conf_t *conf, dkChar const *keyname, dkChar const *value, dk4_app_t *app ) { int back = 0; int res; $? "+ dk4gra_conf_alpha_handling \"%!ds\"", TR_STR(value) #if DK4_USE_ASSERT assert(NULL != conf); assert(NULL != value); #endif if (NULL != value) { res = dk4str_abbr_index(dk4gra_conf_alpha_processing,dkT('$'),value,0); switch (res) { case 0: { back = 1; dk4cs_context_set_alpha( &(conf->ctx), DK4_CS_CONV_ALPHA_MIX, NULL ); } break; case 1: { back = 1; dk4cs_context_set_alpha( &(conf->ctx), DK4_CS_CONV_ALPHA_FOREGROUND, NULL ); } break; default : { /* ERROR: Illegal value */ dk4gralog_3(app, DK4_LL_ERROR, 38, 39, value); } break; } } else { /* ERROR: Value required */ dk4gralog_3(app, DK4_LL_ERROR, 20, 21, keyname); } $? "- dk4gra_conf_alpha_handling %d", back return back; } /** Check whether a value is within specified range, correct if necessary. @param value Address of value variable. @param min Minimum value. @param max Maximum value. @param app Application structure for diagnostics. @return 1 on success, 0 on error. */ static int dk4gra_conf_check_range( int *value, int min, int max, dkChar const *txt, dk4_app_t *app ) { int back = 1; #if DK4_USE_ASSERT assert(NULL != value); #endif if (min > *value) { *value = min; back = 0; /* ERROR: Value too small! */ dk4gralog_3(app, DK4_LL_ERROR, 4, 5, txt); } if (max < *value) { *value = max; back = 0; /* ERROR: Value too large! */ dk4gralog_3(app, DK4_LL_ERROR, 4, 5, txt); } return back; } /** Retrieve background color from value text. @param bptr Address of boolean variable. @param keyname Key name to use in diagnostics. @param value Value text, may be NULL. @param app Application structure for diagnostics, may be NULL. @return 1 on success (continue processing), 0 on error (abort). */ static int dk4gra_conf_background( int *r, int *g, int *b, int *f, dkChar const *keyname, dkChar *value, dk4_app_t *app ) { dkChar const *ep; dkChar *p[8]; size_t numtok = 0; int back = 0; $? "+ dk4gra_conf_background \"%!ds\"", TR_STR(value) #if DK4_USE_ASSERT assert(NULL != r); assert(NULL != g); assert(NULL != b); assert(NULL != f); assert(NULL != value); #endif if (NULL != value) { numtok = dk4str_tokenize(p, 8, value, dk4gra_conf_txt[0], NULL); switch (numtok) { case 3: case 4: { back = 1; ep = NULL; if (0 == dk4ma_input_dk_dec_int(r, p[0], &ep, 1, NULL)) { back = 0; /* ERROR: Incorrect value */ dk4gralog_3(app, DK4_LL_ERROR, 6, 7, p[0]); } else { if (0 == dk4gra_conf_check_range(r, 0, 255, p[0], app)) { back = 0; } } ep = NULL; if (0 == dk4ma_input_dk_dec_int(g, p[1], &ep, 1, NULL)) { back = 0; /* ERROR: Incorrect value */ dk4gralog_3(app, DK4_LL_ERROR, 6, 7, p[1]); } else { if (0 == dk4gra_conf_check_range(g, 0, 255, p[1], app)) { back = 0; } } ep = NULL; if (0 == dk4ma_input_dk_dec_int(b, p[2], &ep, 1, NULL)) { back = 0; /* ERROR: Incorrect value */ dk4gralog_3(app, DK4_LL_ERROR, 6, 7, p[2]); } else { if (0 == dk4gra_conf_check_range(b, 0, 255, p[2], app)) { back = 0; } } if (4 == numtok) { if (dk4str_is_bool(p[3])) { *f = dk4str_is_on(p[3]); } else { /* ERROR: Incorrect value */ dk4gralog_3(app, DK4_LL_ERROR, 4, 5, p[3]); } } } break; default : { /* ERROR: Incorrect value */ dk4gralog_1(app, DK4_LL_ERROR, 14); } break; } } else { /* ERROR: Value required */ dk4gralog_3(app, DK4_LL_ERROR, 20, 21, keyname); } $? "- dk4gra_conf_background %d", back return back; } /** Retrieve PS language level value from value text. @param bptr Address of boolean variable. @param keyname Key name to use in diagnostics. @param value Value text, may be NULL. @param app Application structure for diagnostics, may be NULL. @return 1 on success (continue processing), 0 on error (abort). */ static int dk4gra_conf_psll( int *bptr, dkChar const *keyname, dkChar const *value, dk4_app_t *app ) { const dkChar *ep = NULL; int back = 0; int psl = 0; int res = 0; $? "+ dk4gra_conf_psll \"%!ds\"", TR_STR(value) #if DK4_USE_ASSERT assert(NULL != bptr); assert(NULL != value); #endif if (NULL != value) { res = dk4ma_input_dk_dec_int(&psl, value, &ep, 1, NULL); if (0 != res) { if ((1 < psl) && (4 > psl)) { *bptr = psl; $? ". psl = %d", psl back = 1; } else { /* ERROR: Invalid value */ dk4gralog_3(app, DK4_LL_ERROR, 24, 25, value); } } else { /* ERROR: Not a number */ dk4gralog_3(app, DK4_LL_ERROR, 6, 7, value); } } else { /* ERROR: Value required */ dk4gralog_3(app, DK4_LL_ERROR, 20, 21, keyname); } $? "- dk4gra_conf_psll %d", back return back; } /** Retrieve paper size from value text. @param bptr Address of boolean variable. @param keyname Key name to use in diagnostics. @param value Value text, may be NULL. @param app Application structure for diagnostics, may be NULL. @return 1 on success (continue processing), 0 on error (abort). */ static int dk4gra_conf_paper_size( dk4_gra_conf_t *conf, #if 0 dk4_paper_size_t *paper, #endif dkChar const *keyname, dkChar const *value, dk4_app_t *app ) { #if VERSION_BEFORE_2018_03_27 dk4_paper_size_t *paps; int back = 0; $? "+ dk4gra_conf_paper_size \"%!ds\"", TR_STR(value) #if DK4_USE_ASSERT assert(NULL != conf); assert(NULL != value); #endif if (NULL != value) { paps = dk4app_get_paper_size(app, value); if (NULL != paps) { DK4_MEMCPY(&(conf->media), paps, sizeof(dk4_paper_size_t)); back = 1; dk4mem_free(paps); } else { /* ERROR: Not found */ dk4gralog_3(app, DK4_LL_ERROR, 16, 17, value); } } else { /* ERROR: Value required */ dk4gralog_3(app, DK4_LL_ERROR, 20, 21, keyname); } $? "- dk4gra_conf_paper_size %d", back return back; #else dk4_paper_size_collection_t *pcoll = NULL; dk4_paper_size_t *paps = NULL; dk4_paper_size_t const *cpaps = NULL; int back = 0; $? "+ dk4gra_conf_paper_size \"%!ds\"", TR_STR(value) conf->psi = 0; conf->have_psi = 0; if (NULL != value) { /* First attempt: Use collection */ pcoll = dk4app_get_paper_sizes(app); if (NULL != pcoll) { $? ". have collection, search for size and ind" cpaps = dk4papersize_coll_find_with_index( pcoll, value, &(conf->psi), NULL ); if (NULL != cpaps) { DK4_MEMCPY(&(conf->media), cpaps, sizeof(dk4_paper_size_t)); conf->media.name = NULL; back = 1; conf->have_psi = 1; } dk4papersize_coll_close(pcoll); } /* Second attempt: Ask for paper size directly */ if (0 == back) { paps = dk4app_get_paper_size(app, value); if (NULL != paps) { DK4_MEMCPY(&(conf->media), paps, sizeof(dk4_paper_size_t)); back = 1; dk4mem_free(paps); } else { /* ERROR: Not found */ dk4gralog_3(app, DK4_LL_ERROR, 16, 17, value); } } } else { /* ERROR: Value required */ dk4gralog_3(app, DK4_LL_ERROR, 20, 21, keyname); } $? "- dk4gra_conf_paper_size %d", back return back; #endif } static int dk4gra_conf_resolution( dk4_gra_conf_t *conf, const dkChar *keyname, dkChar *value, dk4_app_t *app ) { dkChar *p[8]; const dkChar *ep = NULL; double rv; double rw; size_t numtok = 0; int back = 0; int res; #if DK4_USE_ASSERT assert(NULL != conf); assert(NULL != value); #endif if (NULL != value) { numtok = dk4str_tokenize(p, 8, value, dk4gra_conf_txt[0], NULL); switch (numtok) { case 1: { switch (dk4str_abbr_index(dk4gra_reso_names,dkT('$'),p[0],0)) { case 0: { conf->xres = 72.0; conf->yres = 72.0; back = 1; } break; case 1: { /* Left empty by intent, do not specify a resolution */ back = 1; } break; default : { rv = 0.0; res = dk4ma_input_dk_double(&rv, p[0], &ep, 1, NULL); if (0 != res) { if (0.0 < rv) { conf->xres = conf->yres = rv; back = 1; } else { dk4gralog_3(app, DK4_LL_ERROR, 2, 3, p[0]); } } else { /* ERROR: Invalid resolution value */ dk4gralog_3(app, DK4_LL_ERROR, 2, 3, p[0]); } } break; } } break; case 2: { rv = rw = 0.0; ep = NULL; res = dk4ma_input_dk_double(&rv, p[0], &ep, 1, NULL); if (0 != res) { ep = NULL; res = dk4ma_input_dk_double(&rw, p[1], &ep, 1, NULL); if (0 != res) { if (0.0 < rv) { if (0.0 < rw) { conf->xres = rv; conf->yres = rw; back = 1; } else { dk4gralog_3(app, DK4_LL_ERROR, 2, 3, p[1]); } } else { dk4gralog_3(app, DK4_LL_ERROR, 2, 3, p[0]); } } else { /* ERROR: Invalid resolution value */ dk4gralog_3(app, DK4_LL_ERROR, 2, 3, p[1]); } } else { /* ERROR: Invalid resolution value */ dk4gralog_3(app, DK4_LL_ERROR, 2, 3, p[0]); } } break; default : { dk4gralog_1(app, DK4_LL_ERROR, 14); } break; } } else { /* ERROR: Value required */ dk4gralog_3(app, DK4_LL_ERROR, 20, 21, keyname); } return back; } static int dk4gra_conf_xsss( dk4_gra_conf_t *conf, dkChar *value, dk4_app_t *app ) { const dkChar *ep = NULL; unsigned u = 0U; int res = 0; int back = 0; #if DK4_USE_ASSERT assert(NULL != conf); assert(NULL != value); #endif if (NULL != value) { res = dk4ma_input_dk_dec_uint(&u, value, &ep, 1, NULL); if (0 != res) { if (0U < u) { conf->xsss = u; back = 1; if (16U < u) { dk4gralog_1(app, DK4_LL_WARNING, 64); } else { if (4U > u) { dk4gralog_1(app, DK4_LL_WARNING, 65); } } } else { /* ERROR: Illegal value 0 */ conf->xsss = 8U; dk4gralog_1(app, DK4_LL_ERROR, 63); } } else { /* ERROR: Not an unsigned number */ conf->xsss = 8U; dk4gralog_3(app, DK4_LL_ERROR, 61, 62, value); } } else { conf->xsss = 8U; back = 1; } return back; } static int dk4gra_conf_posdouble( double *rp, const dkChar *keyname, dkChar *value, dk4_app_t *app ) { double d; const dkChar *ep = NULL; int back = 1; #if DK4_USE_ASSERT assert(NULL != rp); assert(NULL != value); #endif if (NULL != value) { back = dk4ma_input_dk_double(&d, value, &ep, 1, NULL); if (0 != back) { if (0.0 < d) { *rp = d; } else { back = 0; /* ERROR: Positive number required */ dk4gralog_3(app, DK4_LL_ERROR, 70, 71, keyname); } } else { /* ERROR: Not a double number */ dk4gralog_3(app, DK4_LL_ERROR, 68, 69, value); } } else { /* WARNING: Value required */ dk4gralog_3(app, DK4_LL_WARNING, 66, 67, keyname); } return back; } /** Reader object. */ typedef struct { dk4_gra_conf_t *conf; /**< Configuration structure to modify. */ dk4_app_t *app; /**< Application structure. */ dk4_um_t lno; /**< Line number. */ int insc; /**< Flag: In scope */ } reader_obj_t; /** Check scope line whether or not it matches driver, purpose or combination of both. @param conf Configuration structure to set up. @param txt Text line to process. @param app Application structure for diagnostics, may be NULL. @return 1 on match, 0 on no match. */ static int dk4gra_conf_scope_check( dk4_gra_conf_t *conf, dkChar *txt, dk4_app_t *app ) { dkChar *eptr; dkChar *pptr; int drno; int puno; int drmatch; int pumatch; int back = 0; $? "+ dk4gra_conf_scope_check \"%!ds\"", TR_STR(txt) #if DK4_USE_ASSERT assert(NULL != conf); assert(NULL != txt); #endif txt++; txt = dk4str_start(txt, NULL); if (NULL != txt) { eptr = dk4str_chr(txt, dkT(']')); if (NULL != eptr) { *eptr = dkT('\0'); } pptr = dk4str_chr(txt, dkT('.')); if (NULL != pptr) { *(pptr++) = dkT('\0'); pptr = dk4str_start(pptr, NULL); } if (NULL != pptr) { $? ". driver and purpose" /* Driver.purpose combination */ drno = dk4str_array_index(dk4gra_conf_driver_names, txt, 0); puno = dk4str_abbr_index( dk4gra_conf_purpose_names, dkT('$'), pptr, 0 ); if (-1 < drno) { $? ". valid driver" if (-1 < puno) { $? ". valid purpose" drmatch = pumatch = 0; switch (drno) { case 0: { /* pdf */ if (DK4_GRA_DRIVER_PDF == conf->driver) { drmatch = 1; $? ". driver match" } } break; case 1: { /* eps */ if (DK4_GRA_DRIVER_EPS == conf->driver) { drmatch = 1; $? ". driver match" } } break; case 2: { /* ps */ if (DK4_GRA_DRIVER_EPS == conf->driver) { drmatch = 1; $? ". driver match" } else { if (DK4_GRA_DRIVER_PS == conf->driver) { drmatch = 1; $? ". driver match" } } } break; case 3: { /* tex */ if (DK4_GRA_DRIVER_PGF == conf->driver) { drmatch = 1; $? ". driver match" } } break; case 4: { /* bb */ if (DK4_GRA_DRIVER_BB == conf->driver) { drmatch = 1; $? ". driver match" } } break; } switch (puno) { case 0: { if (DK4_GRA_PURPOSE_OBJECT == conf->purpose) { pumatch = 1; $? ". purpose match" } } break; case 1: { if (DK4_GRA_PURPOSE_IMAGE == conf->purpose) { pumatch = 1; $? ". purpose match" } } break; case 2: { if (DK4_GRA_PURPOSE_DOCUMENT == conf->purpose) { pumatch = 1; $? ". purpose match" } } break; } if ((0 != drmatch) && (0 != pumatch)) { back = 1; $? ". match ok" } else { $? ". drmatch=%d pumatch=%d", drmatch, pumatch } } else { $? "! invalid purpose" /* ERROR: No such purpose */ dk4gralog_3(app, DK4_LL_ERROR, 27, 28, pptr); } } else { $? "! invalid driver" /* ERROR: No such driver */ dk4gralog_3(app, DK4_LL_ERROR, 29, 30, txt); } } else { $? ". driver or purpose" /* Either only driver or purpose */ switch (dk4str_array_index(dk4gra_conf_driver_names, txt, 0)) { case 0: { /* pdf */ if (DK4_GRA_DRIVER_PDF == conf->driver) { back = 1; $? ". driver match" } } break; case 1: { /* eps */ if (DK4_GRA_DRIVER_EPS == conf->driver) { back = 1; $? ". driver match" } } break; case 2: { /* ps */ if (DK4_GRA_DRIVER_EPS == conf->driver) { back = 1; $? ". driver match" } else { if (DK4_GRA_DRIVER_PS == conf->driver) { back = 1; $? ". driver match" } } } break; case 3: { /* tex */ if (DK4_GRA_DRIVER_PGF == conf->driver) { back = 1; $? ". driver match" } } break; case 4: { /* bb */ if (DK4_GRA_DRIVER_BB == conf->driver) { back = 1; $? ". driver match" } } break; default : { switch ( dk4str_abbr_index( dk4gra_conf_purpose_names, dkT('$'), txt, 0 ) ) { case 0: { if (DK4_GRA_PURPOSE_OBJECT == conf->purpose) { back = 1; $? ". purpose match" } } break; case 1: { if (DK4_GRA_PURPOSE_IMAGE == conf->purpose) { back = 1; $? ". purpose match" } } break; case 2: { if (DK4_GRA_PURPOSE_DOCUMENT == conf->purpose) { back = 1; $? ". purpose match" } } break; default : { if (0 == dk4str_cmp(txt, dk4gra_conf_txt[2])) { back = 1; $? ". general match" } else { /* ERROR: Not a driver or purpose */ dk4gralog_3(app, DK4_LL_ERROR, 44, 45, txt); } } break; } } break; } } } $? "- dk4gra_conf_scope_check %d", back return back; } /** Callback function, handler to process a line read by the text stream processor. @param obj Reader object. @param line Line to process. @param lineno Line number. @param erp Error report, may be NULL. @return DK4_TSP_RES_OK if the line was processed successfully, DK4_TSP_RES_ERROR on error (can continue), DK4_TSP_RES_FATAL on fatal error (must abort). */ static int dk4gra_conf_line_handler( void *obj, dkChar *line, dk4_um_t lineno, dk4_er_t * DK4_ARG_UNUSED(erp) ) { reader_obj_t *rdo; dkChar *pcur; dkChar *vptr; dk4_app_t *app; dk4_gra_conf_t *conf; int back; int res; DK4_UNUSED_ARG(erp) $!trace-code if (NULL != line) { dk4str_delnl(line); } $? "+ dk4gra_conf_line_handler \"%!ds\"", TR_STR(line) back = DK4_TSP_RES_OK; rdo = (reader_obj_t *)obj; app = rdo->app; conf = rdo->conf; dk4app_set_log_source_line(rdo->app, lineno); pcur = dk4str_start(line, NULL); if (NULL != pcur) { $? ". have text" if (dkT('#') != *pcur) { $? ". not a comment" if (dkT('[') == *pcur) { $? ". scope definition" rdo->insc = dk4gra_conf_scope_check(conf, pcur, app); #if TRACE_DEBUG if (0 != rdo->insc) { $? ". scope on" } else { $? ". scope off" } #endif } else { $? ". data line" if (0 != rdo->insc) { $? ". in scope" vptr = dk4str_chr(pcur, dkT('=')); if (NULL != vptr) { $? ". have value" *(vptr++) = dkT('\0'); vptr = dk4str_start(vptr, NULL); if (NULL != vptr) { $? ". vptr=%!ds", vptr dk4str_normalize(pcur, NULL); $? ". pcur=%!ds", pcur dk4str_normalize(vptr, NULL); $? ". vptr=%!ds", vptr res = dk4str_abbr_index( dk4gra_conf_cfgfile_key_names, dkT('$'), pcur, 0 ); $? ". res = %d", res switch (res) { case 0 : { /* color */ res = dk4gra_conf_bool( &(conf->color), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 1 : { /* alpha */ res = dk4gra_conf_alpha_handling( conf, pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 2 : { /* background */ res = dk4gra_conf_background( &(conf->img_bg_r), &(conf->img_bg_g), &(conf->img_bg_b), &(conf->img_bg_f), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 3 : { /* force background */ res = dk4gra_conf_bool( &(conf->img_bg_f), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 4 : { /* image interpolation */ res = dk4gra_conf_bool( &(conf->img_int), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 5 : { /* dct */ res = dk4gra_conf_bool( &(conf->img_dct), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 6 : { /* dct interpolation */ res = dk4gra_conf_bool( &(conf->img_dct_int), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 7 : { /* analyze bits per component */ res = dk4gra_conf_bool( &(conf->img_an_bpc), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 8 : { /* analyze color use */ res = dk4gra_conf_bool( &(conf->img_an_color), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 9 : { /* analyze alpha use */ res = dk4gra_conf_bool( &(conf->img_an_alpha), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 10 : { /* ignore resolution */ res = dk4gra_conf_bool( &(conf->img_ign_res), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 11 : { /* ps language level */ res = dk4gra_conf_psll( &(conf->ps_level), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 12 : { /* allow lzw */ res = dk4gra_conf_bool( &(conf->ps_lzw), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 13 : { /* paper size */ res = dk4gra_conf_paper_size( conf, pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 14 : { /* duplex */ res = dk4gra_conf_bool( &(conf->doc_duplex), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 15 : { /* tumble */ res = dk4gra_conf_bool( &(conf->doc_tumble), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 16 : { /* dsc */ res = dk4gra_conf_bool( &(conf->ps_dsc), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 17 : { /* rgb to gray */ res = dk4gra_conf_rgb_to_gray( conf,pcur,vptr,app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 18 : { /* rgb to cmyk */ res = dk4gra_conf_rgb_to_cmyk( conf,pcur,vptr,app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 19 : { /* ignore aspect ratio */ res = dk4gra_conf_bool( &(conf->img_ign_asp), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 20 : { /* allow rotate */ res = dk4gra_conf_bool( &(conf->img_rot), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 21 : { /* resolution */ res = dk4gra_conf_resolution( conf, pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 22 : { /* X-spline sub segments */ res = dk4gra_conf_xsss( conf, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 23 : { res = dk4gra_conf_posdouble( &(conf->xslp), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; case 24 : { res = dk4gra_conf_posdouble( &(conf->xspp), pcur, vptr, app ); if (0 == res) { back = DK4_TSP_RES_ERROR; } } break; default : { /* ERROR: Unknown key */ back = DK4_TSP_RES_ERROR; dk4gralog_3( app, DK4_LL_ERROR, 31, 32, pcur ); } break; } } else { $? "! no value found" dk4gralog_1(app, DK4_LL_ERROR, 46); } } else { $? "! no value found" dk4gralog_1(app, DK4_LL_ERROR, 46); } } #if TRACE_DEBUG else { $? ". not in scope" } #endif } } #if TRACE_DEBUG else { $? ". comment line" } #endif } #if TRACE_DEBUG else { $? ". empty line ok" } #endif $? "- dk4gra_conf_line_handler %d", back return back; } /** Apply one configuration file cumulative to the configuration. @param conf Configuration structure to modify. @param filename Input file name. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ static int dk4gra_conf_apply_file( dk4_gra_conf_t *conf, dkChar const *filename, dk4_app_t *app ) { char ib[4096]; dkChar il[256]; dk4_tspdk_t tsp; reader_obj_t obj; dk4_stream_t *istrm = NULL; dkChar const *oldsourcefile; dk4_um_t oldsourceline; size_t rb; int res; int back = 1; int cc = 1; $? "+ dk4gra_conf_apply_file \"%!ds\"", TR_STR(filename) #if DK4_USE_ASSERT assert(NULL != conf); assert(NULL != filename); #endif /* Initialize reader object */ obj.conf = conf; obj.app = app; obj.lno = (dk4_um_t)0UL; obj.insc = 1; /* Set up logging for file to process */ oldsourcefile = dk4app_get_log_source_file(app); oldsourceline = dk4app_get_log_source_line(app); dk4app_set_log_source_file(app, filename); dk4app_set_log_source_line(app, (dk4_um_t)0UL); dk4gralog_1(app, DK4_LL_PROGRESS, 50); /* Open input stream */ istrm = dk4stream_open_file_reader(filename, NULL); if (NULL != istrm) { res = dk4tspdk_setup_line( &tsp, &obj, dk4gra_conf_line_handler, il, DK4_SIZEOF(il,dkChar), dk4app_get_encoding(app), dk4app_get_file_in_encoding(app), NULL ); if (0 != res) { do { cc = 0; rb = sizeof(ib); if (0 != dk4stream_read(ib, &rb, istrm, NULL)) { if (0 < rb) { res = dk4tspdk_add_bytes( &tsp, (const unsigned char *)ib, rb ); if (DK4_TSP_RES_FATAL != res) { cc = 1; } else { cc = -1; back = 0; } } #if TRACE_DEBUG else { $? ". rb 0" } #endif } #if TRACE_DEBUG else { $? ". read 0" } #endif } while (1 == cc); if (0 == cc) { res = dk4tspdk_finish(&tsp); if (DK4_TSP_RES_FATAL == res) { back = 0; } } } else { /* ERROR: Failed to set up text processing */ dk4gralog_1(app, DK4_LL_ERROR, 40); } dk4stream_close(istrm, NULL); } else { /* ERROR: Failed to read file */ dk4gralog_1(app, DK4_LL_ERROR, 41); } /* Set up logging for file processed previously */ dk4app_set_log_source_line(app, (dk4_um_t)0UL); dk4gralog_1(app, DK4_LL_PROGRESS, 51); dk4app_set_log_source_file(app, oldsourcefile); dk4app_set_log_source_line(app, oldsourceline); /* Finished, return */ $? "- dk4gra_conf_apply_file %d", back return back; } /** Complete setup by reading configuration files after finding driver and purpose. @param conf Configuration structure to set up. @param app Application structure for diagnostics, may be NULL. @return 1 on success (continue processing), 0 on error (abort program). */ static int dk4gra_conf_setup_cfgfiles( dk4_gra_conf_t *conf, dk4_app_t *app ) { dkChar fnb[DK4_MAX_PATH]; /* Buffer to construct cfg file name */ dkChar const *osf; /* Old source file */ dk4_um_t osl; /* Old source line */ size_t i; /* Index of current cfg file */ int res; /* Operation result */ int back = 1; $? "+ dk4gra_conf_setup_cfgfiles" #if DK4_USE_ASSERT assert(NULL != conf); #endif /* Progress message */ osf = dk4app_get_log_source_file(app); osl = dk4app_get_log_source_line(app); dk4app_set_log_source_file(app, NULL); dk4app_set_log_source_line(app, (dk4_um_t)0UL); dk4gralog_1(app, DK4_LL_PROGRESS, 48); for (i = 0; i <= DK4_FS_CONF_MAX; i++) { res = dk4app_search_one_config_file( fnb, DK4_SIZEOF(fnb,dkChar), app, dk4gra_conf_txt[1], (int)i, 1, NULL ); if (0 != res) { $? ". process file \"%!ds\"", fnb if (0 == dk4gra_conf_apply_file(conf, fnb, app)) { back = 0; } } } dk4gralog_1(app, DK4_LL_PROGRESS, 49); dk4app_set_log_source_file(app, osf); dk4app_set_log_source_line(app, osl); $? "- dk4gra_conf_setup_cfgfiles %d", back return back; } /** Find driver and purpose from string. @param conf Configuration structure to set up. @param txt Text containing driver and purpose names. @param app Application structure for diagnostics, may be NULL. @return 1 on success (continue processing), 0 on error (abort). */ static int dk4gra_conf_driver_purpose( dk4_gra_conf_t *conf, dkChar *txt, dk4_app_t *app ) { dkChar *ppur = NULL; int back = 0; $? "+ dk4gra_conf_driver_purpose \"%!ds\"", TR_STR(txt) #if DK4_USE_ASSERT assert(NULL != conf); assert(NULL != txt); #endif ppur = dk4str_chr(txt, dkT('.')); if (NULL != ppur) { *(ppur++) = dkT('\0'); ppur = dk4str_start(ppur, NULL); } conf->driver = dk4str_array_index(dk4gra_conf_driver_names, txt, 0); $? ". driver = %d", conf->driver if (-1 < conf->driver) { back = 1; if (NULL != ppur) { conf->purpose = dk4str_abbr_index( dk4gra_conf_purpose_names, dkT('$'), ppur, 0 ); $? ". purpose = %d", conf->purpose if (0 > conf->purpose) { back = 0; /* ERROR: Illegal purpose name */ dk4gralog_3(app, DK4_LL_ERROR, 27, 28, ppur); } } if (DK4_GRA_DRIVER_PS == conf->driver) { if (DK4_GRA_PURPOSE_DOCUMENT == conf->purpose) { conf->ps_dsc = 1; } } } else { /* ERROR: Illegal driver name */ dk4gralog_3(app, DK4_LL_ERROR, 29, 30, txt); } $? "- dk4gra_conf_driver_purpose %d", back return back; } static int dk4gra_conf_key_value( dk4_gra_conf_t *conf, dkChar *txt, int cfscope, dk4_app_t *app ) { dkChar *pcur; dkChar *pnext; dkChar *vptr; int back = 1; int res; $? "+ dk4gra_conf_key_value \"%!ds\"", TR_STR(txt) #if DK4_USE_ASSERT assert(NULL != conf); assert(NULL != txt); #endif pcur = txt; while ((0 != back) && (NULL != pcur)) { pnext = dk4str_chr(pcur, dkT(',')); if (NULL != pnext) { *(pnext++) = dkT('\0'); pnext = dk4str_start(pnext, NULL); } vptr = dk4str_chr(pcur, dkT('=')); if (NULL != vptr) { *(vptr++) = dkT('\0'); vptr = dk4str_start(vptr, NULL); } res = dk4str_abbr_index(dk4gra_conf_key_names, dkT('$'), pcur, 0); if (-1 < res) { if (0 == (cfscope & dk4gra_conf_key_scopes[res])) { /* Warning: Ignored configuration key */ dk4gralog_3(app, DK4_LL_ERROR, 42, 43, pcur); } } switch (res) { case 0 : { /* color */ res = dk4gra_conf_bool(&(conf->color), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 1 : { /* alpha */ res = dk4gra_conf_alpha_handling(conf, pcur, vptr, app); if (0 == res) { back = 0; } } break; case 2 : { /* background */ res = dk4gra_conf_background( &(conf->img_bg_r), &(conf->img_bg_g), &(conf->img_bg_b), &(conf->img_bg_f), pcur, vptr, app ); if (0 == res) { back = 0; } } break; case 3 : { /* force background */ res = dk4gra_conf_bool(&(conf->img_bg_f), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 4 : { /* image interpolation */ res = dk4gra_conf_bool(&(conf->img_int), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 5 : { /* dct */ res = dk4gra_conf_bool(&(conf->img_dct), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 6 : { /* dct interpolation */ res = dk4gra_conf_bool(&(conf->img_dct_int), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 7 : { /* analyze bits per component */ res = dk4gra_conf_bool(&(conf->img_an_bpc), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 8 : { /* analyze color use */ res = dk4gra_conf_bool(&(conf->img_an_color), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 9 : { /* analyze alpha use */ res = dk4gra_conf_bool(&(conf->img_an_alpha), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 10 : { /* ignore resolution */ res = dk4gra_conf_bool(&(conf->img_ign_res), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 11 : { /* ps language level */ res = dk4gra_conf_psll( &(conf->ps_level), pcur, vptr, app ); if (0 == res) { back = 0; } } break; case 12 : { /* allow lzw */ res = dk4gra_conf_bool(&(conf->ps_lzw), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 13 : { /* paper size */ res = dk4gra_conf_paper_size( conf, pcur, vptr, app ); if (0 == res) { back = 0; } } break; case 14 : { /* duplex */ res = dk4gra_conf_bool(&(conf->doc_duplex), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 15 : { /* tumble */ res = dk4gra_conf_bool(&(conf->doc_tumble), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 16 : { /* dsc */ res = dk4gra_conf_bool(&(conf->ps_dsc), pcur, vptr, app); if (0 == res) { back = 0; } } break; case 17 : { /* rgb to gray */ res = dk4gra_conf_rgb_to_gray(conf, pcur, vptr, app); if (0 == res) { back = 0; } } break; case 18 : { /* rgb to cmyk */ res = dk4gra_conf_rgb_to_cmyk(conf, pcur, vptr, app); if (0 == res) { back = 0; } } break; case 19 : { res = dk4gra_conf_bool( &(conf->img_ign_asp), pcur, vptr, app ); if (0 == res) { back = 0; } } break; case 20 : { res = dk4gra_conf_bool( &(conf->img_rot), pcur, vptr, app ); if (0 == res) { back = 0; } } break; case 21: { res = dk4gra_conf_resolution( conf, pcur, vptr, app ); if (0 == res) { back = 0; } } break; case 22: { res = dk4gra_conf_xsss( conf, vptr, app ); if (0 == res) { back = 0; } } break; case 23 : { res = dk4gra_conf_posdouble( &(conf->xslp), pcur, vptr, app ); if (0 == res) { back = 0; } } break; case 24 : { res = dk4gra_conf_posdouble( &(conf->xspp), pcur, vptr, app ); if (0 == res) { back = 0; } } break; default : { /* ERROR: Unknown key */ dk4gralog_3(app, DK4_LL_ERROR, 31, 32, pcur); back = 0; } break; } pcur = pnext; } $? "- dk4gra_conf_key_value %d", back return back; } /** Process configuration string. @param conf Configuration structure to set up. @param txt Writable copy of configuration string. @param usecfg Flag: Process configuration files after finding driver and purpose. @param cfscope Configuration scope. @param app Application structure for diagnostics, may be NULL. @return 1 on success (continue processing), 0 on error (abort program). */ static int dk4gra_conf_setup_txt( dk4_gra_conf_t *conf, dkChar *txt, int usecfg, int cfscope, dk4_app_t *app ) { dkChar *pcur; dkChar *pnext; int back = 1; $? "+ dk4gra_conf_setup_txt \"%!ds\"", TR_PTR(txt) #if DK4_USE_ASSERT assert(NULL != conf); assert(NULL != txt); #endif pcur = dk4str_start(txt, NULL); if (NULL != pcur) { pnext = dk4str_chr(pcur, dkT(',')); if (NULL != pnext) { *(pnext++) = dkT('\0'); pnext = dk4str_start(pnext, NULL); } back = dk4gra_conf_driver_purpose(conf, pcur, app); if (0 != back) { if (0 != usecfg) { back = dk4gra_conf_setup_cfgfiles(conf, app); } if (0 != back) { back = dk4gra_conf_key_value(conf, pnext, cfscope, app); } } } else { /* Warning: Empty configuration string */ } $? "- dk4gra_conf_setup_txt %d", back return back; } int dk4gra_conf_setup( dk4_gra_conf_t *conf, dkChar const *txt, int usecfg, int cfscope, dk4_app_t *app ) { dkChar *mycopy; int back = 0; $? "+ dk4gra_conf_setup" #if DK4_USE_ASSERT assert(NULL != conf); #endif if (NULL != conf) { if ((NULL != txt) || (0 != usecfg)) { if (NULL != txt) { mycopy = dk4str_dup_app(txt, app); if (NULL != mycopy) { back = dk4gra_conf_setup_txt( conf, mycopy, usecfg, cfscope, app ); dk4mem_free(mycopy); } } else { back = dk4gra_conf_setup_cfgfiles(conf, app); } } if (DK4_GRA_PURPOSE_DOCUMENT == conf->purpose) { switch (conf->driver) { case DK4_GRA_DRIVER_PDF : case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_PGF : { /* Empty by intent */ } break; default : { /* ERROR: Driver/purpose combination no allowd */ back = 1; dk4gralog_1(app, DK4_LL_ERROR, 47); } break; } } } $? "- dk4gra_conf_setup %d", back return back; } /* vim: set ai sw=4 ts=4 : */