/* Copyright (C) 1999, 2000 artofcode LLC. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA, 02111-1307. */ /*$Id: spsdf.c,v 1.5.2.1.2.1 2003/01/17 00:49:05 giles Exp $ */ /* Common utilities for PostScript and PDF format printing */ #include "stdio_.h" /* for stream.h */ #include "string_.h" #include "gstypes.h" #include "gsmemory.h" #include "gserror.h" #include "gserrors.h" #include "spprint.h" #include "spsdf.h" #include "stream.h" #include "strimpl.h" #include "sa85x.h" #include "sstring.h" #include "scanchar.h" /* * Write a string in its shortest form ( () or <> ). Note that * this form is different depending on whether binary data are allowed. * Currently we don't support ASCII85 strings ( <~ ~> ). */ void s_write_ps_string(stream * s, const byte * str, uint size, int print_ok) { uint added = 0; uint i; const stream_template *template; stream_AXE_state state; stream_state *st = NULL; if (print_ok & PRINT_BINARY_OK) { /* Only need to escape (, ), \, CR, EOL. */ stream_putc(s, '('); for (i = 0; i < size; ++i) { byte ch = str[i]; switch (ch) { case char_CR: stream_puts(s, "\\r"); continue; case char_EOL: stream_puts(s, "\\n"); continue; case '(': case ')': case '\\': stream_putc(s, '\\'); } stream_putc(s, ch); } stream_putc(s, ')'); return; } for (i = 0; i < size; ++i) { byte ch = str[i]; if (ch == 0 || ch >= 127) added += 3; else if (strchr("()\\\n\r\t\b\f", ch) != 0) ++added; else if (ch < 32) added += 3; } if (added < size || (print_ok & PRINT_HEX_NOT_OK)) { /* More efficient, or mandatory, to represent as PostScript string. */ template = &s_PSSE_template; stream_putc(s, '('); } else { /* More efficient, and permitted, to represent as hex string. */ template = &s_AXE_template; st = (stream_state *) & state; s_AXE_init_inline(&state); stream_putc(s, '<'); } { byte buf[100]; /* size is arbitrary */ stream_cursor_read r; stream_cursor_write w; int status; r.ptr = str - 1; r.limit = r.ptr + size; w.limit = buf + sizeof(buf) - 1; do { /* One picky compiler complains if we initialize to buf - 1. */ w.ptr = buf; w.ptr--; status = (*template->process) (st, &r, &w, true); stream_write(s, buf, (uint) (w.ptr + 1 - buf)); } while (status == 1); } } /* Set up a write stream that just keeps track of the position. */ int s_alloc_position_stream(stream ** ps, gs_memory_t * mem) { stream *s = *ps = s_alloc(mem, "s_alloc_position_stream"); if (s == 0) return_error(gs_error_VMerror); swrite_position_only(s); return 0; } /* ---------------- Parameter printing ---------------- */ private_st_printer_param_list(); const param_printer_params_t param_printer_params_default = { param_printer_params_default_values }; /* We'll implement the other printers later if we have to. */ private param_proc_xmit_typed(param_print_typed); /*private param_proc_begin_xmit_collection(param_print_begin_collection); */ /*private param_proc_end_xmit_collection(param_print_end_collection); */ private const gs_param_list_procs printer_param_list_procs = { param_print_typed, NULL /* begin_collection */ , NULL /* end_collection */ , NULL /* get_next_key */ , gs_param_request_default, gs_param_requested_default }; int s_init_param_printer(printer_param_list_t *prlist, const param_printer_params_t * ppp, stream * s) { gs_param_list_init((gs_param_list *)prlist, &printer_param_list_procs, NULL); prlist->strm = s; prlist->params = *ppp; prlist->any = false; return 0; } int s_alloc_param_printer(gs_param_list ** pplist, const param_printer_params_t * ppp, stream * s, gs_memory_t * mem) { printer_param_list_t *prlist = gs_alloc_struct(mem, printer_param_list_t, &st_printer_param_list, "s_alloc_param_printer"); int code; *pplist = (gs_param_list *)prlist; if (prlist == 0) return_error(gs_error_VMerror); code = s_init_param_printer(prlist, ppp, s); prlist->memory = mem; return code; } void s_release_param_printer(printer_param_list_t *prlist) { if (prlist) { if (prlist->any && prlist->params.suffix) stream_puts(prlist->strm, prlist->params.suffix); } } void s_free_param_printer(gs_param_list * plist) { if (plist) { printer_param_list_t *const prlist = (printer_param_list_t *) plist; s_release_param_printer(prlist); gs_free_object(prlist->memory, plist, "s_free_param_printer"); } } private int param_print_typed(gs_param_list * plist, gs_param_name pkey, gs_param_typed_value * pvalue) { printer_param_list_t *const prlist = (printer_param_list_t *)plist; stream *s = prlist->strm; if (!prlist->any) { if (prlist->params.prefix) stream_puts(s, prlist->params.prefix); prlist->any = true; } if (prlist->params.item_prefix) stream_puts(s, prlist->params.item_prefix); pprints1(s, "/%s", pkey); switch (pvalue->type) { case gs_param_type_null: stream_puts(s, " null"); break; case gs_param_type_bool: stream_puts(s, (pvalue->value.b ? " true" : " false")); break; case gs_param_type_int: pprintd1(s, " %d", pvalue->value.i); break; case gs_param_type_long: pprintld1(s, " %l", pvalue->value.l); break; case gs_param_type_float: pprintg1(s, " %g", pvalue->value.f); break; case gs_param_type_string: s_write_ps_string(s, pvalue->value.s.data, pvalue->value.s.size, prlist->params.print_ok); break; case gs_param_type_name: /****** SHOULD USE #-ESCAPES FOR PDF ******/ stream_putc(s, '/'); stream_write(s, pvalue->value.n.data, pvalue->value.n.size); break; case gs_param_type_int_array: { uint i; char sepr = (pvalue->value.ia.size <= 10 ? ' ' : '\n'); stream_putc(s, '['); for (i = 0; i < pvalue->value.ia.size; ++i) { pprintd1(s, "%d", pvalue->value.ia.data[i]); stream_putc(s, sepr); } stream_putc(s, ']'); } break; case gs_param_type_float_array: { uint i; char sepr = (pvalue->value.fa.size <= 10 ? ' ' : '\n'); stream_putc(s, '['); for (i = 0; i < pvalue->value.fa.size; ++i) { pprintg1(s, "%g", pvalue->value.fa.data[i]); stream_putc(s, sepr); } stream_putc(s, ']'); } break; /*case gs_param_type_string_array: */ /*case gs_param_type_name_array: */ default: return_error(gs_error_typecheck); } if (prlist->params.item_suffix) stream_puts(s, prlist->params.item_suffix); return 0; }