1/* 2 * "$Id: print-util.c,v 1.117 2010/06/26 20:02:02 rlk Exp $" 3 * 4 * Print plug-in driver utility functions for the GIMP. 5 * 6 * Copyright 1997-2000 Michael Sweet (mike@easysw.com) and 7 * Robert Krawitz (rlk@alum.mit.edu) 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the Free 11 * Software Foundation; either version 2 of the License, or (at your option) 12 * any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 */ 23 24/* 25 * This file must include only standard C header files. The core code must 26 * compile on generic platforms that don't support glib, gimp, gtk, etc. 27 */ 28 29#ifdef HAVE_CONFIG_H 30#include <config.h> 31#endif 32#include <gutenprint/gutenprint.h> 33#include "gutenprint-internal.h" 34#include <gutenprint/gutenprint-intl-internal.h> 35#include <math.h> 36#include <limits.h> 37#if defined(HAVE_VARARGS_H) && !defined(HAVE_STDARG_H) 38#include <varargs.h> 39#else 40#include <stdarg.h> 41#endif 42#include <string.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <sys/types.h> 46#include <sys/stat.h> 47#include <unistd.h> 48#include "generic-options.h" 49 50#define FMIN(a, b) ((a) < (b) ? (a) : (b)) 51 52typedef struct 53{ 54 stp_outfunc_t ofunc; 55 void *odata; 56 char *data; 57 size_t bytes; 58} debug_msgbuf_t; 59 60/* 61 * We cannot avoid use of the (non-ANSI) vsnprintf here; ANSI does 62 * not provide a safe, length-limited sprintf function. 63 */ 64 65#define STPI_VASPRINTF(result, bytes, format) \ 66{ \ 67 int current_allocation = 64; \ 68 result = stp_malloc(current_allocation); \ 69 while (1) \ 70 { \ 71 va_list args; \ 72 va_start(args, format); \ 73 bytes = vsnprintf(result, current_allocation, format, args); \ 74 va_end(args); \ 75 if (bytes >= 0 && bytes < current_allocation) \ 76 break; \ 77 else \ 78 { \ 79 stp_free (result); \ 80 if (bytes < 0) \ 81 current_allocation *= 2; \ 82 else \ 83 current_allocation = bytes + 1; \ 84 result = stp_malloc(current_allocation); \ 85 } \ 86 } \ 87} 88 89void 90stp_zprintf(const stp_vars_t *v, const char *format, ...) 91{ 92 char *result; 93 int bytes; 94 STPI_VASPRINTF(result, bytes, format); 95 (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), result, bytes); 96 stp_free(result); 97} 98 99void 100stp_asprintf(char **strp, const char *format, ...) 101{ 102 char *result; 103 int bytes; 104 STPI_VASPRINTF(result, bytes, format); 105 *strp = result; 106} 107 108void 109stp_catprintf(char **strp, const char *format, ...) 110{ 111 char *result1; 112 char *result2; 113 int bytes; 114 STPI_VASPRINTF(result1, bytes, format); 115 stp_asprintf(&result2, "%s%s", *strp, result1); 116 stp_free(result1); 117 *strp = result2; 118} 119 120 121void 122stp_zfwrite(const char *buf, size_t bytes, size_t nitems, const stp_vars_t *v) 123{ 124 (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), buf, bytes * nitems); 125} 126 127void 128stp_write_raw(const stp_raw_t *raw, const stp_vars_t *v) 129{ 130 (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), raw->data, raw->bytes); 131} 132 133void 134stp_putc(int ch, const stp_vars_t *v) 135{ 136 unsigned char a = (unsigned char) ch; 137 (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), (char *) &a, 1); 138} 139 140#define BYTE(expr, byteno) (((expr) >> (8 * byteno)) & 0xff) 141 142void 143stp_put16_le(unsigned short sh, const stp_vars_t *v) 144{ 145 stp_putc(BYTE(sh, 0), v); 146 stp_putc(BYTE(sh, 1), v); 147} 148 149void 150stp_put16_be(unsigned short sh, const stp_vars_t *v) 151{ 152 stp_putc(BYTE(sh, 1), v); 153 stp_putc(BYTE(sh, 0), v); 154} 155 156void 157stp_put32_le(unsigned int in, const stp_vars_t *v) 158{ 159 stp_putc(BYTE(in, 0), v); 160 stp_putc(BYTE(in, 1), v); 161 stp_putc(BYTE(in, 2), v); 162 stp_putc(BYTE(in, 3), v); 163} 164 165void 166stp_put32_be(unsigned int in, const stp_vars_t *v) 167{ 168 stp_putc(BYTE(in, 3), v); 169 stp_putc(BYTE(in, 2), v); 170 stp_putc(BYTE(in, 1), v); 171 stp_putc(BYTE(in, 0), v); 172} 173 174void 175stp_puts(const char *s, const stp_vars_t *v) 176{ 177 (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), s, strlen(s)); 178} 179 180void 181stp_putraw(const stp_raw_t *r, const stp_vars_t *v) 182{ 183 (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), r->data, r->bytes); 184} 185 186void 187stp_send_command(const stp_vars_t *v, const char *command, 188 const char *format, ...) 189{ 190 int i = 0; 191 char fchar; 192 const char *out_str; 193 const stp_raw_t *out_raw; 194 unsigned short byte_count = 0; 195 va_list args; 196 197 if (strlen(format) > 0) 198 { 199 va_start(args, format); 200 for (i = 0; i < strlen(format); i++) 201 { 202 switch (format[i]) 203 { 204 case 'a': 205 case 'b': 206 case 'B': 207 case 'd': 208 case 'D': 209 break; 210 case 'c': 211 (void) va_arg(args, unsigned int); 212 byte_count += 1; 213 break; 214 case 'h': 215 case 'H': 216 (void) va_arg(args, unsigned int); 217 byte_count += 2; 218 break; 219 case 'l': 220 case 'L': 221 (void) va_arg(args, unsigned int); 222 byte_count += 4; 223 break; 224 case 'r': 225 out_raw = va_arg(args, const stp_raw_t *); 226 byte_count += out_raw->bytes; 227 break; 228 case 's': 229 out_str = va_arg(args, const char *); 230 byte_count += strlen(out_str); 231 break; 232 } 233 } 234 va_end(args); 235 } 236 237 stp_puts(command, v); 238 239 va_start(args, format); 240 while ((fchar = format[0]) != '\0') 241 { 242 switch (fchar) 243 { 244 case 'a': 245 stp_putc(byte_count, v); 246 break; 247 case 'b': 248 stp_put16_le(byte_count, v); 249 break; 250 case 'B': 251 stp_put16_be(byte_count, v); 252 break; 253 case 'd': 254 stp_put32_le(byte_count, v); 255 break; 256 case 'D': 257 stp_put32_be(byte_count, v); 258 break; 259 case 'c': 260 stp_putc(va_arg(args, unsigned int), v); 261 break; 262 case 'h': 263 stp_put16_le(va_arg(args, unsigned int), v); 264 break; 265 case 'H': 266 stp_put16_be(va_arg(args, unsigned int), v); 267 break; 268 case 'l': 269 stp_put32_le(va_arg(args, unsigned int), v); 270 break; 271 case 'L': 272 stp_put32_be(va_arg(args, unsigned int), v); 273 break; 274 case 's': 275 stp_puts(va_arg(args, const char *), v); 276 break; 277 case 'r': 278 stp_putraw(va_arg(args, const stp_raw_t *), v); 279 break; 280 } 281 format++; 282 } 283 va_end(args); 284} 285 286void 287stp_eprintf(const stp_vars_t *v, const char *format, ...) 288{ 289 int bytes; 290 if (stp_get_errfunc(v)) 291 { 292 char *result; 293 STPI_VASPRINTF(result, bytes, format); 294 (stp_get_errfunc(v))((void *)(stp_get_errdata(v)), result, bytes); 295 stp_free(result); 296 } 297 else 298 { 299 va_list args; 300 va_start(args, format); 301 vfprintf(stderr, format, args); 302 va_end(args); 303 } 304} 305 306void 307stp_erputc(int ch) 308{ 309 putc(ch, stderr); 310} 311 312void 313stp_erprintf(const char *format, ...) 314{ 315 va_list args; 316 va_start(args, format); 317 vfprintf(stderr, format, args); 318 va_end(args); 319} 320 321static unsigned long stpi_debug_level = 0; 322 323static void 324stpi_init_debug(void) 325{ 326 static int debug_initialized = 0; 327 if (!debug_initialized) 328 { 329 const char *dval = getenv("STP_DEBUG"); 330 debug_initialized = 1; 331 if (dval) 332 { 333 stpi_debug_level = strtoul(dval, 0, 0); 334 stp_erprintf("Gutenprint %s %s\n", VERSION, RELEASE_DATE); 335 } 336 } 337} 338 339unsigned long 340stp_get_debug_level(void) 341{ 342 stpi_init_debug(); 343 return stpi_debug_level; 344} 345 346void 347stp_dprintf(unsigned long level, const stp_vars_t *v, const char *format, ...) 348{ 349 int bytes; 350 stpi_init_debug(); 351 if (level & stpi_debug_level) 352 { 353 if (stp_get_errfunc(v)) 354 { 355 char *result; 356 STPI_VASPRINTF(result, bytes, format); 357 (stp_get_errfunc(v))((void *)(stp_get_errdata(v)), result, bytes); 358 stp_free(result); 359 } else { 360 va_list args; 361 va_start(args, format); 362 vfprintf(stderr, format, args); 363 va_end(args); 364 } 365 } 366} 367 368void 369stp_deprintf(unsigned long level, const char *format, ...) 370{ 371 va_list args; 372 va_start(args, format); 373 stpi_init_debug(); 374 if (level & stpi_debug_level) 375 vfprintf(stderr, format, args); 376 va_end(args); 377} 378 379static void 380fill_buffer_writefunc(void *priv, const char *buffer, size_t bytes) 381{ 382 debug_msgbuf_t *msgbuf = (debug_msgbuf_t *) priv; 383 if (msgbuf->bytes == 0) 384 msgbuf->data = stp_malloc(bytes + 1); 385 else 386 msgbuf->data = stp_realloc(msgbuf->data, msgbuf->bytes + bytes + 1); 387 memcpy(msgbuf->data + msgbuf->bytes, buffer, bytes); 388 msgbuf->bytes += bytes; 389 msgbuf->data[msgbuf->bytes] = '\0'; 390} 391 392void 393stp_init_debug_messages(stp_vars_t *v) 394{ 395 int verified_flag = stp_get_verified(v); 396 debug_msgbuf_t *msgbuf = stp_malloc(sizeof(debug_msgbuf_t)); 397 msgbuf->ofunc = stp_get_errfunc(v); 398 msgbuf->odata = stp_get_errdata(v); 399 msgbuf->data = NULL; 400 msgbuf->bytes = 0; 401 stp_set_errfunc((stp_vars_t *) v, fill_buffer_writefunc); 402 stp_set_errdata((stp_vars_t *) v, msgbuf); 403 stp_set_verified((stp_vars_t *) v, verified_flag); 404} 405 406void 407stp_flush_debug_messages(stp_vars_t *v) 408{ 409 int verified_flag = stp_get_verified(v); 410 debug_msgbuf_t *msgbuf = (debug_msgbuf_t *)stp_get_errdata(v); 411 stp_set_errfunc((stp_vars_t *) v, msgbuf->ofunc); 412 stp_set_errdata((stp_vars_t *) v, msgbuf->odata); 413 stp_set_verified((stp_vars_t *) v, verified_flag); 414 if (msgbuf->bytes > 0) 415 { 416 stp_eprintf(v, "%s", msgbuf->data); 417 stp_free(msgbuf->data); 418 } 419 stp_free(msgbuf); 420} 421 422/* pointers to the allocation functions to use, which may be set by 423 client applications */ 424void *(*stp_malloc_func)(size_t size) = malloc; 425void *(*stpi_realloc_func)(void *ptr, size_t size) = realloc; 426void (*stpi_free_func)(void *ptr) = free; 427 428void * 429stp_malloc (size_t size) 430{ 431 register void *memptr = NULL; 432 433 if ((memptr = stp_malloc_func (size)) == NULL) 434 { 435 fputs("Virtual memory exhausted.\n", stderr); 436 stp_abort(); 437 } 438 return (memptr); 439} 440 441void * 442stp_zalloc (size_t size) 443{ 444 register void *memptr = stp_malloc(size); 445 (void) memset(memptr, 0, size); 446 return (memptr); 447} 448 449void * 450stp_realloc (void *ptr, size_t size) 451{ 452 register void *memptr = NULL; 453 454 if (size > 0 && ((memptr = stpi_realloc_func (ptr, size)) == NULL)) 455 { 456 fputs("Virtual memory exhausted.\n", stderr); 457 stp_abort(); 458 } 459 return (memptr); 460} 461 462void 463stp_free(void *ptr) 464{ 465 stpi_free_func(ptr); 466} 467 468int 469stp_init(void) 470{ 471 static int stpi_is_initialised = 0; 472 if (!stpi_is_initialised) 473 { 474 /* Things that are only initialised once */ 475 /* Set up gettext */ 476#ifdef HAVE_LOCALE_H 477 char *locale = stp_strdup(setlocale (LC_ALL, "")); 478#endif 479#ifdef ENABLE_NLS 480 bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR); 481#endif 482#ifdef HAVE_LOCALE_H 483 setlocale(LC_ALL, locale); 484 stp_free(locale); 485#endif 486 stpi_init_debug(); 487 stp_xml_preinit(); 488 stpi_init_printer(); 489 stpi_init_paper(); 490 stpi_init_dither(); 491 /* Load modules */ 492 if (stp_module_load()) 493 return 1; 494 /* Load XML data */ 495 if (stp_xml_init_defaults()) 496 return 1; 497 /* Initialise modules */ 498 if (stp_module_init()) 499 return 1; 500 /* Set up defaults for core parameters */ 501 stp_initialize_printer_defaults(); 502 } 503 504 stpi_is_initialised = 1; 505 return 0; 506} 507 508size_t 509stp_strlen(const char *s) 510{ 511 return strlen(s); 512} 513 514char * 515stp_strndup(const char *s, int n) 516{ 517 char *ret; 518 if (!s || n < 0) 519 { 520 ret = stp_malloc(1); 521 ret[0] = 0; 522 return ret; 523 } 524 else 525 { 526 ret = stp_malloc(n + 1); 527 memcpy(ret, s, n); 528 ret[n] = 0; 529 return ret; 530 } 531} 532 533char * 534stp_strdup(const char *s) 535{ 536 char *ret; 537 if (!s) 538 { 539 ret = stp_malloc(1); 540 ret[0] = '\0'; 541 return ret; 542 } 543 else 544 return stp_strndup(s, stp_strlen(s)); 545} 546 547const char * 548stp_set_output_codeset(const char *codeset) 549{ 550#if defined(ENABLE_NLS) && !defined(__APPLE__) 551 return (const char *)(bind_textdomain_codeset(PACKAGE, codeset)); 552#else 553 return "US-ASCII"; 554#endif 555} 556 557stp_curve_t * 558stp_read_and_compose_curves(const char *s1, const char *s2, 559 stp_curve_compose_t comp, 560 size_t piecewise_point_count) 561{ 562 stp_curve_t *ret = NULL; 563 stp_curve_t *t1 = NULL; 564 stp_curve_t *t2 = NULL; 565 if (s1) 566 t1 = stp_curve_create_from_string(s1); 567 if (s2) 568 t2 = stp_curve_create_from_string(s2); 569 if (t1 && t2) 570 { 571 if (stp_curve_is_piecewise(t1) && stp_curve_is_piecewise(t2)) 572 { 573 stp_curve_resample(t1, piecewise_point_count); 574 stp_curve_resample(t2, piecewise_point_count); 575 } 576 stp_curve_compose(&ret, t1, t2, comp, -1); 577 } 578 if (ret) 579 { 580 stp_curve_destroy(t1); 581 stp_curve_destroy(t2); 582 return ret; 583 } 584 else if (t1) 585 { 586 if(t2) 587 stp_curve_destroy(t2); 588 return t1; 589 } 590 else 591 return t2; 592} 593 594void 595stp_merge_printvars(stp_vars_t *user, const stp_vars_t *print) 596{ 597 int i; 598 stp_parameter_list_t params = stp_get_parameter_list(print); 599 int count = stp_parameter_list_count(params); 600 stp_deprintf(STP_DBG_VARS, "Merging printvars from %s\n", 601 stp_get_driver(print)); 602 for (i = 0; i < count; i++) 603 { 604 const stp_parameter_t *p = stp_parameter_list_param(params, i); 605 if (p->p_type == STP_PARAMETER_TYPE_DOUBLE && 606 p->p_class == STP_PARAMETER_CLASS_OUTPUT && 607 stp_check_float_parameter(print, p->name, STP_PARAMETER_DEFAULTED)) 608 { 609 stp_parameter_t desc; 610 double prnval = stp_get_float_parameter(print, p->name); 611 double usrval; 612 stp_describe_parameter(print, p->name, &desc); 613 if (stp_check_float_parameter(user, p->name, STP_PARAMETER_ACTIVE)) 614 usrval = stp_get_float_parameter(user, p->name); 615 else 616 usrval = desc.deflt.dbl; 617 if (strcmp(p->name, "Gamma") == 0) 618 usrval /= prnval; 619 else 620 usrval *= prnval; 621 if (usrval < desc.bounds.dbl.lower) 622 usrval = desc.bounds.dbl.lower; 623 else if (usrval > desc.bounds.dbl.upper) 624 usrval = desc.bounds.dbl.upper; 625 if (!stp_check_float_parameter(user, p->name, STP_PARAMETER_ACTIVE)) 626 { 627 stp_clear_float_parameter(user, p->name); 628 stp_set_default_float_parameter(user, p->name, usrval); 629 } 630 else 631 stp_set_float_parameter(user, p->name, usrval); 632 stp_parameter_description_destroy(&desc); 633 } 634 } 635 stp_deprintf(STP_DBG_VARS, "Exiting merge printvars\n"); 636 stp_parameter_list_destroy(params); 637} 638 639stp_parameter_list_t 640stp_get_parameter_list(const stp_vars_t *v) 641{ 642 stp_parameter_list_t ret = stp_parameter_list_create(); 643 stp_parameter_list_t tmp_list; 644 645 tmp_list = stp_printer_list_parameters(v); 646 stp_parameter_list_append(ret, tmp_list); 647 stp_parameter_list_destroy(tmp_list); 648 649 tmp_list = stp_color_list_parameters(v); 650 stp_parameter_list_append(ret, tmp_list); 651 stp_parameter_list_destroy(tmp_list); 652 653 tmp_list = stp_dither_list_parameters(v); 654 stp_parameter_list_append(ret, tmp_list); 655 stp_parameter_list_destroy(tmp_list); 656 657 tmp_list = stp_list_generic_parameters(v); 658 stp_parameter_list_append(ret, tmp_list); 659 stp_parameter_list_destroy(tmp_list); 660 661 return ret; 662} 663 664void 665stp_abort(void) 666{ 667 abort(); 668} 669