/* Copyright (c) 2004-2010, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. 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 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file dkfigto2.c Tool module 2. */ /** Inside the dkfigto2 module. */ #define DKFIGTO2_C 1 #include "dkfig.h" #line 54 "dkfigto2.ctr" /** File open mode: Read binary. */ static char str_mode_read_binary[] = { "rb" }; /** File open mode: Read. */ static char str_mode_read_text[] = { "r" }; /** Detect encoding: auto (use LANG environment variable. */ static char str_auto[] = { "auto" }; /** Detect encoding: Keyword UTF-8. */ static char str_utf8[] = { ".UTF-8" }; /** Sequence to open math mode in LaTeX. */ static char str_open_math_mode[] = { "\\(" }; /** Sequence to close math mode in LaTeX. */ static char str_close_math_mode[] = { "\\)" }; /** Text to search for bounding box. */ static char bb_search[] = { "%%BoundingBox:" }; /** File open mode. */ static char str_mode_open_read[] = { "r" }; /** Suffixes for compressed files. */ static char *suffix_types[] = { (char *)".gz", (char *)".bz2", NULL }; /** Compare to image width information structures. @param l Pointer to left structure. @param r Pointer to right structure. @param c Comparison criteria (ignored). @return The comparison result. */ int dkfig_tool2_compare_image_width DK_P3(void *,l, void *,r, int,c) { int back = 0; dkfig_bitmap_width *wl, *wr; if(l) { if(r) { wl = (dkfig_bitmap_width *)l; wr = (dkfig_bitmap_width *)r; if(wl->width > wr->width) { back = 1; } else { if(wl->width < wr->width) { back = -1; } } if(back == 0) { if(wl->colored) { if(!(wr->colored)) { back = 1; } } else { if(wr->colored) { back = -1; } } } if(back == 0) { if(wl->seprgb) { if(wr->seprgb) { if(wl->height > wr->height) { back = 1; } else { if(wl->height < wr->height) { back = -1; } } } else { back = -1; } } else { if(wr->seprgb) { back = -1; } } } /* if(back == 0) { if(wl->fl == 2) { if(wr->fl != 2) { back = 1; } } else { if(wr->fl == 2) { back = -1; } } } */ } else { back = 1; } } else { if(r) { back = -1; } } return back; } /** Create storage container to store image width data. @return Pointer to new storage on success, NULL on error. */ dk_storage_t * dkfig_tool2_image_width_storage DK_P0() { dk_storage_t *back = NULL; back = dksto_open(0); if(back) { dksto_set_comp(back, dkfig_tool2_compare_image_width, 1); } return back; } /** Find width structure for given image attributes. @param it Image width data storage iterator. @param width Image width. @param height Image height. @param colored Flag: Colored. @param seprgb Flag: Separated color channels. @param fl Flip information. @return Pointer to image width structure on success, NULL on error. */ dkfig_bitmap_width * dkfig_tool2_find_entry_for_width DK_P6(dk_storage_iterator_t *,it, long,width, long,height, int,colored, int,seprgb,int,fl) { dkfig_bitmap_width w, *back = NULL; if(it) { w.width = width; w.height = height; if(fl == 2) { w.width = height; w.height = width; } w.colored = colored; w.seprgb = seprgb; back = (dkfig_bitmap_width *)dksto_it_find_like(it, (void *)(&w), 0); } return back; } /** Add image width structure to storage. @param st Image width data storage. @param it Image width data storage iterator. @param width Image width. @param height Image height. @param colored Flag: Colored. @param seprgb Flag: Separated color channels. @param fl Flip information. @return 1 on success, 0 on error. */ int dkfig_tool2_add_image_width DK_P7(dk_storage_t *,st, dk_storage_iterator_t *,it, long,width, long,height, int,colored, int,seprgb, int,fl) { int back = 0; dkfig_bitmap_width w, *ptr; if(st && it) { w.width = width; if(dkfig_tool2_find_entry_for_width( it, width, height,colored,seprgb,fl) ) { back = 1; } else { ptr = dk_new(dkfig_bitmap_width,1); if(ptr) { ptr->width = width; ptr->height = height; ptr->colored = colored; ptr->seprgb = seprgb; /* ptr->fl = fl; */ if(fl == 2) { ptr->width = height; ptr->height = width; } if(dksto_add(st, (void *)ptr)) { back = 1; } else { dk_delete(ptr); } } else { } } } else { } return back; } /** Error message: One constant text. @param c Conversion job structure. @param i Text index. */ void dkfig_tool2_simple_error_message DK_P2(dk_fig_conversion *,c, size_t,i) { dkfig_tool2_msg1(c, DK_LOG_LEVEL_ERROR, i); } /** Error output function for the EPS driver. @param oi EPS output instruction structure. @param i Index of error message. */ void dkfig_tool2_eps_error_message DK_P2(dkfig_eps_output_instruction *,oi, size_t,i) { if(oi) { dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, i); } } /** Error output function for the SVG driver. @param oi SVG output instruction structure. @param i Index of error message. */ void dkfig_tool2_svg_error_message DK_P2(dkfig_svg_output_instruction *,oi, size_t,i) { if(oi) { dkfig_tool2_msg1(oi->c, DK_LOG_LEVEL_ERROR, i); } } /** Error message: constant text, variable text and constant text. @param c Conversion job structure. @param i1 First constant text index. @param i2 Second constant text index. @param fn Variable text. */ void dkfig_tool2_combined_error_message DK_P4(dk_fig_conversion *,c, size_t,i1, size_t,i2, char *,fn) { dkfig_tool2_msg3(c, DK_LOG_LEVEL_ERROR, i1, i2, fn); } /** Progress message. @param c Conversion job structure. @param i Message index. */ void dkfig_tool2_simple_progress_message DK_P2(dk_fig_conversion *,c, size_t,i) { dkfig_tool2_msg1(c, DK_LOG_LEVEL_PROGRESS, i); } /** Report why the special comment can not be used. @param c Conversion job structure. @param speccom Special comment/option structure. @param i Failure reason. */ void dkfig_tool2_report_special_comment DK_P3(dk_fig_conversion *,c,dk_fig_opt *,speccom,int,i) { if((c) && (speccom)) { if((c->app) && (c->msg1)) { switch(i) { case 0: { /* unknown key */ dkapp_set_source_lineno(c->app, speccom->number); dkfig_tool2_msg3(c, DK_LOG_LEVEL_WARNING, 86, 92, speccom->name); dkapp_set_source_lineno(c->app, 0UL); } break; case -1: { /* wrong driver */ dkapp_set_source_lineno(c->app, speccom->number); dkfig_tool2_msg3(c, DK_LOG_LEVEL_WARNING, 87, 92, speccom->name); dkapp_set_source_lineno(c->app, 0UL); } break; case -2: { /* not per-instance */ dkapp_set_source_lineno(c->app, speccom->number); dkfig_tool2_msg3(c, DK_LOG_LEVEL_WARNING, 88, 92, speccom->name); dkapp_set_source_lineno(c->app, 0UL); } break; case -3: { /* other error */ dkapp_set_source_lineno(c->app, speccom->number); dkfig_tool2_msg3(c, DK_LOG_LEVEL_WARNING, 89, 92, speccom->name); dkapp_set_source_lineno(c->app, 0UL); } break; } } } } /** Report unused options. @param c Conversion job structure. */ void dkfig_tool2_report_unused_options DK_P1(dk_fig_conversion *,c) { dk_fig_opt *op; if(c) { if((c->app) && (c->msg1)) { char *oldname; unsigned long oldno; oldname = dkapp_get_source_filename(c->app); oldno = dkapp_get_source_lineno(c->app); dkapp_set_source_filename(c->app, NULL); dkapp_set_source_lineno(c->app, 0UL); /* command line options */ if((c->opt) && (c->opti)) { dksto_it_reset(c->opti); while((op = (dk_fig_opt *)dksto_it_next(c->opti)) != NULL) { if(!(op->used)) { dkfig_tool2_msg3(c, DK_LOG_LEVEL_WARNING, 90, 92, op->name); } } } /* config file */ if(c->cfgfn) { dkapp_set_source_filename(c->app, c->cfgfn); } /* configuration section */ if((c->optd) && (c->optdi)) { dksto_it_reset(c->optdi); while((op = (dk_fig_opt *)dksto_it_next(c->optdi)) != NULL) { if(!(op->used)) { dkapp_set_source_lineno(c->app, op->number); dkfig_tool2_msg3(c, DK_LOG_LEVEL_WARNING, 91, 92, op->name); } } } /* driver section */ if((c->optb) && (c->optbi)) { dksto_it_reset(c->optbi); while((op = (dk_fig_opt *)dksto_it_next(c->optbi)) != NULL) { if(!(op->used)) { dkapp_set_source_lineno(c->app, op->number); dkfig_tool2_msg3(c, DK_LOG_LEVEL_WARNING, 91, 92, op->name); } } } /* global section */ if((c->optg) && (c->optgi)) { dksto_it_reset(c->optgi); while((op = (dk_fig_opt *)dksto_it_next(c->optgi)) != NULL) { if(!(op->used)) { dkapp_set_source_lineno(c->app, op->number); dkfig_tool2_msg3(c, DK_LOG_LEVEL_WARNING, 91, 92, op->name); } } } dkapp_set_source_filename(c->app, oldname); dkapp_set_source_lineno(c->app, oldno); } } } /** Read NetPBM image size to w and h. @param c Conversion job structure. @param fn File name. @param w Pointer to variable for image width. @param h Pointer to variable for image height. @return 1 on success, 0 on error. */ static int pbm_image_size DK_P4(dk_fig_conversion *,c, char *,fn, unsigned long *,w, unsigned long *,h) { int back = 0; #if DK_HAVE_PNM_H || DK_HAVE_NETPBM_PNM_H FILE *f = NULL; xelval maxxelval = 0; int cols = 0, rows = 0, format = 0; xel **array; if(c->app) { f = dkapp_fopen(c->app, fn, str_mode_read_binary); } else { f = dksf_fopen(fn, str_mode_read_binary); } if(f) { array = pnm_readpnm(f, &cols, &rows, &maxxelval, &format); if(array) { *w = (unsigned long)cols; *h = (unsigned long)rows; back = 1; pnm_freearray(array, rows); } fclose(f); f = NULL; } #endif return back; } /** Read PNG image size to w and h. @param c Conversion job structure. @param fn File name. @param w Pointer to variable for image width. @param h Pointer to variable for image height. @return 1 on success, 0 on error. */ static int png_image_size DK_P4(dk_fig_conversion *,c, char *,fn, unsigned long *,w, unsigned long *,h) { int back = 0; #if DK_HAVE_ZLIB_H #if DK_HAVE_PNG_H FILE *f = NULL; png_uint_32 ui32 = 0, width = 0, height = 0; int bd = 0, ct = 0, zt = 0, it = 0, ft = 0; png_structp pp = NULL; png_infop pi = NULL; if(c->app) { f = dkapp_fopen(c->app, fn, str_mode_read_binary); } else { f = dksf_fopen(fn, str_mode_read_binary); } if(f) { pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL ,NULL, NULL); if(pp) { pi = png_create_info_struct(pp); if(pi) { #if DK_HAVE_SETJMP_H if(setjmp(pp->jmpbuf) == 0) { #endif png_init_io(pp, f); png_read_info(pp, pi); ui32 = png_get_IHDR(pp, pi, &width, &height, &bd, &ct, &it, &zt, &ft); if(width && height) { *w = (unsigned long)width; *h = (unsigned long)height; back = 1; } else { dkfig_tool2_combined_error_message(c, 96, 97, fn); } #if DK_HAVE_SETJMP_H } else { dkfig_tool2_combined_error_message(c, 96, 97, fn); } #endif png_destroy_info_struct(pp, &pi); pi = NULL; } png_destroy_read_struct(&pp, NULL, NULL); pp = NULL; } fclose(f); f = NULL; } #endif #endif return back; } #if DK_HAVE_JPEGLIB_H /** Flag: Already an error while reading JPEG file. */ static int had_error = 0; /** Do not exit on errors, set flag instead. */ static void error_exit_replacement DK_P1(j_common_ptr,cinfo) { had_error = 1; } #endif /** Read JPEG image size to w and h. @param c Conversion job structure. @param fn File name. @param w Pointer to variable for image width. @param h Pointer to variable for image height. @return 1 on success, 0 on error. */ static int jpg_image_size DK_P4(dk_fig_conversion *,c, char *,fn, unsigned long *,w, unsigned long *,h) { int back = 0; #if DK_HAVE_JPEGLIB_H FILE *f = NULL; JDIMENSION width, height; struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; had_error = 0; cinfo.err = jpeg_std_error(&jerr); jerr.error_exit = error_exit_replacement; jpeg_create_decompress(&cinfo); if(!had_error) { if(c->app) { f = dkapp_fopen(c->app, fn, str_mode_read_binary); } else { f = dksf_fopen(fn, str_mode_read_binary); } if(f) { jpeg_stdio_src(&cinfo, f); if(!had_error) { jpeg_read_header(&cinfo, TRUE); if(!had_error) { width = cinfo.output_width; height = cinfo.output_height; if(width && height) { *w = (unsigned long)width; *h = (unsigned long)height; back = 1; } } } jpeg_abort((j_common_ptr)(&cinfo)); fclose(f); f = NULL; } } #endif return back; } /** Read EPS image size to w and h. @param c Conversion job structure. @param fn File name. @param w Pointer to variable for image width. @param h Pointer to variable for image height. @return 1 on success, 0 on error. */ static int eps_image_size DK_P4(dk_fig_conversion *,c, char *,fn, unsigned long *,w, unsigned long *,h) { int back = 0; int state = 0; long llx, lly, urx, ury, deltax, deltay; char inputline[1024]; FILE *f = NULL; size_t minlgt; char *ptr; llx = lly = urx = ury = deltax = deltay = 0L; if(c->app) { f = dkapp_fopen(c->app, fn, str_mode_read_text); } else { f = dksf_fopen(fn, str_mode_read_text); } if(f) { minlgt = strlen(bb_search); while(state < 2) { if(fgets(inputline, sizeof(inputline), f)) { if(strlen(inputline) > minlgt) { if(strncmp(inputline, bb_search, minlgt) == 0) { ptr = dkstr_start(&(inputline[minlgt]), NULL); if(ptr) { if(sscanf(ptr, "%ld %ld %ld %ld", &llx, &lly, &urx, &ury) == 4) { back = 1; deltax = urx - llx; deltay = ury - lly; if(deltax < 0L) { deltax = 0L - deltax; } if(deltay < 0L) { deltay = 0L - deltay; } *w = (unsigned long)deltax; *h = (unsigned long)deltay; if(state == 0) { state = 2; } } else { state = 1; } } } } } else { state = 3; } } fclose(f); f = NULL; } return back; } /** Retrieve image size. @param c Conversion job structure. @param fn Image file name. @param w Pointer to width result variable. @param h Pointer to height result variable. @return 1 on success, 0 on error. */ int dkfig_tool2_get_image_size DK_P4(dk_fig_conversion *,c, char *,fn, unsigned long *,w, unsigned long *,h) { int back = 0; int ft; if((fn) && (w) && (h)) { *w = 0UL; *h = 0UL; ft = dkfig_ei_get_image_type(fn); if(ft >= 0) { switch(ft) { case 0: { /* PS/EPS */ back = eps_image_size(c, fn, w, h); } break; case 1: { /* PNG */ back = png_image_size(c, fn, w, h); } break; case 2: { /* JPEG */ back = jpg_image_size(c, fn, w, h); } break; case 3: { /* NetPBM */ back = pbm_image_size(c, fn, w, h); } break; } } } return back; } /** Check whether or not an object is a background rectangle. @param o Object to inspect. @param wbgr Flag: Background rectangle uses color white instead of default. @return 1=true, 0=false. */ int dkfig_tool2_obj_is_bg_rect DK_P2(dk_fig_object *,o, int,wbgr) { int back = 0; if(o->layer == 999L) { if(o->objtype == DK_FIG_OBJ_POLYLINE) { if(o->subtype == 2) { if((o->fpd).lt == 0L) { if((o->fpd).af == -1) { if(wbgr) { if((o->fpd).pc == 7) { back = 1; } } else { if((o->fpd).pc == -1) { back = 1; } } } } } } } return back; } /** Double round with specified number of digits. @param v Value to round. @param c Conversion job structure. @param w Rounding type (1=coordinate, 2=coordinate obtained from trigonometric calculation, default=color). */ double dkfig_tool2_drd DK_P3(double,v, dk_fig_conversion *,c, int,w) { double back; back = v; if(c) { switch(w) { case 1: { back = dkma_double_restrict_digits(back, c->nodcoord); } break; case 2: { back = dkma_double_restrict_digits(back, (c->nodcoord + c->nodtrigo)); } break; default: { back = dkma_double_restrict_digits(back, c->nodcolor); } break; } } return back; } /** Retrieve UTF-8 enabled/disabled setting from LANG environment variable. @param c Conversion job structure. @return 1 on success (LANG environment var found), 0 on error. */ int dkfig_tool2_utf8_auto DK_P1(dk_fig_conversion *,c) { int back = 0; char *ptr1, *ptr2; if(c) { c->opt2 |= DKFIG_OPT_UTF_AUTO; ptr1 = getenv("LANG"); if(ptr1) { back = 1; ptr2 = strchr(ptr1, '.'); if(ptr2) { if(dkstr_casecmp(ptr2, str_utf8) == 0) { c->opt2 |= DKFIG_OPT_UTF_8; } else { c->opt2 &= (~(DKFIG_OPT_UTF_8)); } } else { c->opt2 &= (~(DKFIG_OPT_UTF_8)); } } else { c->opt2 &= (~(DKFIG_OPT_UTF_8)); } } return back; } /** Enable/disable UTF-8. @param c Conversion job structure. @param v Text containing either a boolean or "auto". @param allow_auto Flag: Allow automatic detection of UTF-8 setting. @return 1 on success (tests found a result), 0 on error. */ int dkfig_tool2_set_utf8 DK_P3(dk_fig_conversion *,c, char *,v, int,allow_auto) { int back = 0; char *ptr1; if((c) && (v)) { ptr1 = dkstr_start(v, NULL); if(ptr1) { dkstr_chomp(ptr1, NULL); if(dkstr_is_bool(ptr1)) { if(dkstr_is_on(ptr1)) { c->opt2 |= DKFIG_OPT_UTF_8; } else { c->opt2 &= (~(DKFIG_OPT_UTF_8)); } c->opt2 &= (~(DKFIG_OPT_UTF_AUTO)); back = 1; } else { if(dkstr_casecmp(ptr1, str_auto) == 0) { back = dkfig_tool2_utf8_auto(c); } } } } return back; } /** Log message consisting of 2 constant parts and a variable one. @param c Conversion job structure. @param l Log level (DK_LOG_LEVEL_xxx). @param s1 Index of first (constant) part. @param s2 Index of third (constant) part. @param t Second (variable) part of the message. */ void dkfig_tool2_msg3 DK_P5(dk_fig_conversion *,c, int,l, size_t,s1, size_t,s2, char *,t) { char *msgs[3]; if((c) && (t)) { if(c->msg1) { if(c->app) { msgs[0] = (c->msg1)[s1]; msgs[1] = t; msgs[2] = (c->msg1)[s2]; dkapp_log_msg(c->app, l, msgs, 3); } else { } } } } /** Log message. @param c Conversion job structure. @param l Log level (DK_LOG_LEVEL_xxx). @param s1 Index of message text. */ void dkfig_tool2_msg1 DK_P3(dk_fig_conversion *,c, int,l, size_t,s1) { if(c) { if(c->msg1) { if(c->app) { dkapp_log_msg(c->app, l, &((c->msg1)[s1]), 1); } else { } } } } /** Report error if no encoding table was found for a 32-bit character. @param c Conversion job structure. @param ucb The 32-bit character. */ static void error_no_table_found DK_P2(dk_fig_conversion *,c, dk_udword,ucb) { char buffer[32]; sprintf(buffer, "0x%08lx", ucb); dkfig_tool2_msg3(c, DK_LOG_LEVEL_WARNING, 123, 124, buffer); } /** Report error if no encoding was found for a 32-bit character. @param c Conversion job structure. @param ucb The 32-bit character. */ static void error_no_encoding_found DK_P2(dk_fig_conversion *,c, dk_udword,ucb) { char buffer[32]; sprintf(buffer, "0x%08lx", ucb); dkfig_tool2_msg3(c, DK_LOG_LEVEL_WARNING, 125, 126, buffer); } /** Write LaTeX representation of UTF-8 encoded string to output stream. @param os Output stream. @param c Conversion job structure. @param t UTF-8 encoded string. */ void dkfig_tool2_utf8_to_latex DK_P3(dk_stream_t *,os, dk_fig_conversion *,c, char *,t) { dk_udword ucb; int cc, mm, must_issue; size_t max, used, avail, step, u_obuffer; char obuffer[16], *found; cc = 1; max = strlen(t); used = 0; avail = max; mm = 0; /* not in math mode by default */ while(cc) { cc = 0; must_issue = 0; if(avail > 0) { step = 0; cc = dkenc_utf82uc(&ucb, (unsigned char *)(&(t[used])), avail, &step); if(cc) { found = NULL; if(dkle_load(c->uc2lat, ucb)) { found = dkle_get_encoding(c->uc2lat, ucb, 0); if(found) { if(mm) { dkstream_puts(os, str_close_math_mode); mm = 0; } dkstream_puts(os, found); } else { found = dkle_get_encoding(c->uc2lat, ucb, 1); if(found) { if(mm == 0) { dkstream_puts(os, str_open_math_mode); mm = 1; } dkstream_puts(os, found); } else { if(ucb < 256UL) { found = dk_l2l_encoding((unsigned char)ucb); if(found) { if(mm) { dkstream_puts(os, str_close_math_mode); mm = 0; } dkstream_puts(os, found); } else { must_issue = 1; error_no_encoding_found(c, ucb); } } else { must_issue = 1; error_no_encoding_found(c, ucb); } } } } else { if(ucb < 256UL) { found = dk_l2l_encoding((unsigned char)ucb); if(found) { if(mm) { dkstream_puts(os, str_close_math_mode); mm = 0; } dkstream_puts(os, found); } else { must_issue = 1; error_no_encoding_found(c, ucb); } } else { must_issue = 1; error_no_table_found(c, ucb); } } if(must_issue) { if(mm) { dkstream_puts(os, str_close_math_mode); mm = 0; } /* Convert back and issue UTF-8 */ u_obuffer = dkenc_uc2utf8(ucb, (dk_ubyte *)obuffer, sizeof(obuffer)); if(u_obuffer > 0) { obuffer[u_obuffer] = '\0'; dkstream_write(os, obuffer, u_obuffer); } } used = used + step; if(avail > step) { avail = avail - step; } else { avail = 0; } } else { } } } if(mm) { dkstream_puts(os, str_close_math_mode); mm = 0; } } /** Find compression type for file name. @param n File name. @return -1=not compressed, 0=gzip, 1=bzip2. */ static int compression_type DK_P1(char *,n) { int back = -1; char *suffixptr; suffixptr = dksf_get_file_type_dot(n); if(n) { back = dkstr_array_index(suffix_types, suffixptr, 0); } return back; } /** Open the font mapping file. @param c Conversion structure. @param n File name of font mapping file. @return Pointer to stream structure to read file on success, NULL on error. */ static dk_stream_t * open_the_mapping_file DK_P2(dk_fig_conversion *,c, char *,n) { dk_stream_t *back = NULL; switch(compression_type(n)) { case 0: { #if DK_HAVE_ZLIB_H if(c->app) { back = dkapp_stream_opengz(c->app, n, str_mode_open_read); } else { back = dkstream_opengz(n, str_mode_open_read, 0, NULL); } #else if(c->app) dkapp_err_no_zlib_support_for(c->app, n); #endif } break; case 1: { #if DK_HAVE_BZLIB_H if(c->app) { back = dkapp_stream_openbz2(c->app, n, str_mode_open_read); } else { back = dkstream_openbz2(n, str_mode_open_read, 0, NULL); } #else if(c->app) dkapp_err_no_bzlib_support_for(c->app, n); #endif } break; default: { if(c->app) { back = dkapp_stream_openfile(c->app, n, str_mode_open_read); } else { back = dkstream_openfile(n, str_mode_open_read, 0, NULL); } } break; } return back; } /** Create font mapping from file. @param c Conversion structure. @return Pointer to font mapping on success, NULL on error. */ dk_font_mapping_t * dkfig_tool2_read_font_mapping DK_P1(dk_fig_conversion *,c) { dk_font_mapping_t *back = NULL; /* Function result. */ char *n; /* File name buffer. */ size_t szn; /* Size of n. */ char *ofn; /* Old error file name. */ unsigned long oln; /* Old error line number. */ dk_stream_t *st; /* Stream to read file. */ if(c->fcfg) { back = dkfont_mapping_open(); if(back) { if(c->app) { szn = (size_t)dksf_get_maxpathlen(); n = dk_new(char,szn); if(n) { if(dkapp_find_file(c->app, c->fcfg, n, szn)) { st = open_the_mapping_file(c, n); if(st) { if(!dkfont_mapping_add_stream(back, st)) { ofn = dkapp_get_source_filename(c->app); oln = dkapp_get_source_lineno(c->app); dkapp_set_source_filename(c->app, n); dkapp_set_source_lineno(c->app, dkfont_get_error_lineno(back)); switch(dkfont_get_error_code(back)) { case DK_ERR_NOMEM: { dkfig_tool2_simple_error_message(c, 11); } break; default: { dkfig_tool2_simple_error_message(c, 12); } break; } dkapp_set_source_lineno(c->app, oln); dkapp_set_source_filename(c->app, ofn); dkfont_mapping_close(back); back = NULL; } dkstream_close(st); } else { dkfont_mapping_close(back); back = NULL; dkapp_err_fopenr(c->app, n); } } else { dkfont_mapping_close(back); back = NULL; dkapp_err_matchfile(c->app, c->fcfg); } dk_delete(n); } else { dkfont_mapping_close(back); back = NULL; dkapp_err_memory(c->app, 1, szn); } } else { st = open_the_mapping_file(c, c->fcfg); if(st) { if(!dkfont_mapping_add_stream(back, st)) { dkfont_mapping_close(back); back = NULL; /* ##### ERROR: Failed to use font file. */ } dkstream_close(st); } else { dkfont_mapping_close(back); back = NULL; /* ##### ERROR: Failed to read file. */ } } } else { /* ##### ERROR: Memory. */ } } else { /* ##### ERROR: No file specified. */ } return back; }