summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/utils/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/utils/utils.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/utils/utils.c1809
1 files changed, 0 insertions, 1809 deletions
diff --git a/Build/source/texk/web2c/luatexdir/utils/utils.c b/Build/source/texk/web2c/luatexdir/utils/utils.c
deleted file mode 100644
index b8e715a4a64..00000000000
--- a/Build/source/texk/web2c/luatexdir/utils/utils.c
+++ /dev/null
@@ -1,1809 +0,0 @@
-/* utils.c
-
- Copyright 1996-2006 Han The Thanh <thanh@pdftex.org>
- Copyright 2006-2009 Taco Hoekwater <taco@luatex.org>
-
- This file is part of LuaTeX.
-
- LuaTeX 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.
-
- LuaTeX 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 Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License along
- with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */
-
-#include "openbsd-compat.h"
-
-#include "sys/types.h"
-#ifndef __MINGW32__
-# include "sysexits.h"
-#else
-# define EX_SOFTWARE 70
-#endif
-#include "md5.h"
-#include <kpathsea/c-proto.h>
-#include <kpathsea/c-stat.h>
-#include <kpathsea/c-fopen.h>
-#include <kpathsea/version.h>
-#include <string.h>
-#include <time.h>
-#include <float.h> /* for DBL_EPSILON */
-#include "zlib.h"
-#include "ptexlib.h"
-#include "utils.h"
-
-#include "png.h"
-#ifdef POPPLER_VERSION
-# define xpdfString "poppler"
-# include "poppler-config.h"
-# define xpdfVersion POPPLER_VERSION
-#else
-# define xpdfString "xpdf"
-# include "xpdf/config.h" /* just to get the xpdf version */
-#endif
-
-static const char __svn_version[] =
- "$Id: utils.c 2492 2009-06-14 13:14:50Z taco $ "
- "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.40.6/source/texk/web2c/luatexdir/utils/utils.c $";
-
-#define check_nprintf(size_get, size_want) \
- if ((unsigned)(size_get) >= (unsigned)(size_want)) \
- pdftex_fail ("snprintf failed: file %s, line %d", __FILE__, __LINE__);
-
-char *cur_file_name = NULL;
-str_number last_tex_string;
-static char print_buf[PRINTF_BUF_SIZE];
-static char *jobname_cstr = NULL;
-static char *job_id_string = NULL;
-
-size_t last_ptr_index; /* for use with alloc_array */
-
-/* define fb_ptr, fb_array & fb_limit */
-typedef char fb_entry;
-define_array(fb);
-
-/* define char_ptr, char_array & char_limit */
-typedef char char_entry;
-define_array(char);
-
-integer fb_offset(void)
-{
- return fb_ptr - fb_array;
-}
-
-void fb_seek(integer offset)
-{
- fb_ptr = fb_array + offset;
-}
-
-void fb_putchar(eight_bits b)
-{
- alloc_array(fb, 1, SMALL_ARRAY_SIZE);
- *fb_ptr++ = b;
-}
-
-void fb_flush(void)
-{
- fb_entry *p;
- integer n;
- for (p = fb_array; p < fb_ptr;) {
- n = pdf_buf_size - pdf_ptr;
- if (fb_ptr - p < n)
- n = fb_ptr - p;
- memcpy(pdf_buf + pdf_ptr, p, (unsigned) n);
- pdf_ptr += n;
- if (pdf_ptr == pdf_buf_size)
- pdf_flush();
- p += n;
- }
- fb_ptr = fb_array;
-}
-
-#define SUBSET_TAG_LENGTH 6
-void make_subset_tag(fd_entry * fd)
-{
- int i, j = 0, a[SUBSET_TAG_LENGTH];
- md5_state_t pms;
- char *glyph;
- glw_entry *glw_glyph;
- struct avl_traverser t;
- md5_byte_t digest[16];
- void **aa;
- static struct avl_table *st_tree = NULL;
- if (st_tree == NULL)
- st_tree = avl_create(comp_string_entry, NULL, &avl_xallocator);
- assert(fd != NULL);
- assert(fd->gl_tree != NULL);
- assert(fd->fontname != NULL);
- assert(fd->subset_tag == NULL);
- fd->subset_tag = xtalloc(SUBSET_TAG_LENGTH + 1, char);
- do {
- md5_init(&pms);
- avl_t_init(&t, fd->gl_tree);
- if (is_cidkeyed(fd->fm)) { /* glw_entry items */
- for (glw_glyph = (glw_entry *) avl_t_first(&t, fd->gl_tree);
- glw_glyph != NULL; glw_glyph = (glw_entry *) avl_t_next(&t)) {
- glyph = malloc(24);
- sprintf(glyph, "%05u%05u ", glw_glyph->id, glw_glyph->wd);
- md5_append(&pms, (md5_byte_t *) glyph, strlen(glyph));
- free(glyph);
- }
- } else {
- for (glyph = (char *) avl_t_first(&t, fd->gl_tree); glyph != NULL;
- glyph = (char *) avl_t_next(&t)) {
- md5_append(&pms, (md5_byte_t *) glyph, strlen(glyph));
- md5_append(&pms, (const md5_byte_t *) " ", 1);
- }
- }
- md5_append(&pms, (md5_byte_t *) fd->fontname, strlen(fd->fontname));
- md5_append(&pms, (md5_byte_t *) & j, sizeof(int)); /* to resolve collision */
- md5_finish(&pms, digest);
- for (a[0] = 0, i = 0; i < 13; i++)
- a[0] += digest[i];
- for (i = 1; i < SUBSET_TAG_LENGTH; i++)
- a[i] = a[i - 1] - digest[i - 1] + digest[(i + 12) % 16];
- for (i = 0; i < SUBSET_TAG_LENGTH; i++)
- fd->subset_tag[i] = a[i] % 26 + 'A';
- fd->subset_tag[SUBSET_TAG_LENGTH] = '\0';
- j++;
- assert(j < 100);
- }
- while ((char *) avl_find(st_tree, fd->subset_tag) != NULL);
- aa = avl_probe(st_tree, fd->subset_tag);
- assert(aa != NULL);
- if (j > 2)
- pdftex_warn
- ("\nmake_subset_tag(): subset-tag collision, resolved in round %d.\n",
- j);
-}
-
-void pdf_puts(const char *s)
-{
- pdfroom(strlen(s) + 1);
- while (*s)
- pdf_buf[pdf_ptr++] = *s++;
-}
-
-__attribute__ ((format(printf, 1, 2)))
-void pdf_printf(const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
- pdf_puts(print_buf);
- va_end(args);
-}
-
-str_number maketexstring(const char *s)
-{
- if (s == NULL || *s == 0)
- return get_nullstr();
- return maketexlstring(s, strlen(s));
-}
-
-str_number maketexlstring(const char *s, size_t l)
-{
- if (s == NULL || l == 0)
- return get_nullstr();
- check_pool_overflow(pool_ptr + l);
- while (l-- > 0)
- str_pool[pool_ptr++] = *s++;
- last_tex_string = make_string();
- return last_tex_string;
-}
-
-/* print a C string through TeX */
-void print_string(const char *j)
-{
- while (*j) {
- print_char(*j);
- j++;
- }
-}
-
-/* append a C string to a TeX string */
-void append_string(const char *s)
-{
- if (s == NULL || *s == 0)
- return;
- check_buf(pool_ptr + strlen(s), pool_size);
- while (*s)
- str_pool[pool_ptr++] = *s++;
- return;
-}
-
-__attribute__ ((format(printf, 1, 2)))
-void tex_printf(const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
- print_string(print_buf);
- xfflush(stdout);
- va_end(args);
-}
-
-/* Helper for pdftex_fail. */
-static void safe_print(const char *str)
-{
- const char *c;
- for (c = str; *c; ++c)
- print(*c);
-}
-
-void remove_pdffile(void)
-{
- if (!kpathsea_debug && output_file_name && !fixed_pdf_draftmode) {
- xfclose(pdf_file, makecstring(output_file_name));
- remove(makecstring(output_file_name));
- }
-}
-
-/* pdftex_fail may be called when a buffer overflow has happened/is
- happening, therefore may not call mktexstring. However, with the
- current implementation it appears that error messages are misleading,
- possibly because pool overflows are detected too late.
-
- The output format of this fuction must be the same as pdf_error in
- pdftex.web! */
-
-__attribute__ ((noreturn, format(printf, 1, 2)))
-void pdftex_fail(const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- print_ln();
- safe_print("!LuaTeX error");
- if (cur_file_name) {
- safe_print(" (file ");
- safe_print(cur_file_name);
- safe_print(")");
- }
- safe_print(": ");
- vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
- safe_print(print_buf);
- va_end(args);
- print_ln();
- remove_pdffile();
- safe_print(" ==> Fatal error occurred, no output PDF file produced!");
- print_ln();
- if (kpathsea_debug) {
- abort();
- } else {
- exit(EX_SOFTWARE);
- }
-}
-
-/* The output format of this fuction must be the same as pdf_warn in
- pdftex.web! */
-
-__attribute__ ((format(printf, 1, 2)))
-void pdftex_warn(const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- print_ln();
- tex_printf("LuaTeX warning");
- if (cur_file_name)
- tex_printf(" (file %s)", cur_file_name);
- tex_printf(": ");
- vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
- print_string(print_buf);
- va_end(args);
- print_ln();
-}
-
-void tex_error(const char *msg, const char **hlp)
-{
- str_number aa = 0, bb = 0, cc = 0, dd = 0, ee = 0;
- int k = 0;
- if (hlp != NULL) {
- while (hlp[k] != NULL)
- k++;
- if (k > 0)
- aa = maketexstring(hlp[0]);
- if (k > 1)
- bb = maketexstring(hlp[1]);
- if (k > 2)
- cc = maketexstring(hlp[2]);
- if (k > 3)
- dd = maketexstring(hlp[3]);
- if (k > 4)
- ee = maketexstring(hlp[4]);
- }
- do_print_err(maketexstring(msg));
- flush_str(last_tex_string);
-
-/* *INDENT-OFF* */
- switch (k) {
- case 0: dohelp0(); break;
- case 1: dohelp1(aa); break;
- case 2: dohelp2(aa, bb); break;
- case 3: dohelp3(aa, bb, cc); break;
- case 4: dohelp4(aa, bb, cc, dd); break;
- case 5: dohelp5(aa, bb, cc, dd, ee); break;
- }
-/* *INDENT-ON* */
- error();
-
- if (ee)
- flush_str(ee);
- if (dd)
- flush_str(dd);
- if (cc)
- flush_str(cc);
- if (bb)
- flush_str(bb);
- if (aa)
- flush_str(aa);
-}
-
-void garbage_warning(void)
-{
- pdftex_warn("dangling objects discarded, no output file produced.");
- remove_pdffile();
-}
-
-char *makecstring(integer s)
-{
- size_t l;
- return makeclstring(s, &l);
-}
-
-char *makeclstring(integer s, size_t * len)
-{
- static char *cstrbuf = NULL;
- char *p;
- static int allocsize;
- int allocgrow, i, l;
- if (s >= 2097152) {
- s -= 2097152;
- l = str_start[s + 1] - str_start[s];
- *len = l;
- check_buf(l + 1, MAX_CSTRING_LEN);
- if (cstrbuf == NULL) {
- allocsize = l + 1;
- cstrbuf = xmallocarray(char, allocsize);
- } else if (l + 1 > allocsize) {
- allocgrow = allocsize * 0.2;
- if (l + 1 - allocgrow > allocsize)
- allocsize = l + 1;
- else if (allocsize < MAX_CSTRING_LEN - allocgrow)
- allocsize += allocgrow;
- else
- allocsize = MAX_CSTRING_LEN;
- cstrbuf = xreallocarray(cstrbuf, char, allocsize);
- }
- p = cstrbuf;
- for (i = 0; i < l; i++)
- *p++ = str_pool[i + str_start[s]];
- *p = 0;
- } else {
- if (cstrbuf == NULL) {
- allocsize = 5;
- cstrbuf = xmallocarray(char, allocsize);
- }
- if (s <= 0x7F) {
- cstrbuf[0] = s;
- cstrbuf[1] = 0;
- *len = 1;
- } else if (s <= 0x7FF) {
- cstrbuf[0] = 0xC0 + (s / 0x40);
- cstrbuf[1] = 0x80 + (s % 0x40);
- cstrbuf[2] = 0;
- *len = 2;
- } else if (s <= 0xFFFF) {
- cstrbuf[0] = 0xE0 + (s / 0x1000);
- cstrbuf[1] = 0x80 + ((s % 0x1000) / 0x40);
- cstrbuf[2] = 0x80 + ((s % 0x1000) % 0x40);
- cstrbuf[3] = 0;
- *len = 3;
- } else {
- if (s >= 0x10FF00) {
- cstrbuf[0] = s - 0x10FF00;
- cstrbuf[1] = 0;
- *len = 1;
- } else {
- cstrbuf[0] = 0xF0 + (s / 0x40000);
- cstrbuf[1] = 0x80 + ((s % 0x40000) / 0x1000);
- cstrbuf[2] = 0x80 + (((s % 0x40000) % 0x1000) / 0x40);
- cstrbuf[3] = 0x80 + (((s % 0x40000) % 0x1000) % 0x40);
- cstrbuf[4] = 0;
- *len = 4;
- }
- }
- }
- return cstrbuf;
-}
-
-void set_job_id(int year, int month, int day, int time)
-{
- char *name_string, *format_string, *s;
- size_t slen;
- int i;
-
- if (job_id_string != NULL)
- return;
-
- name_string = xstrdup(makecstring(job_name));
- format_string = xstrdup(makecstring(format_ident));
- slen = SMALL_BUF_SIZE +
- strlen(name_string) +
- strlen(format_string) +
- strlen(ptexbanner) +
- strlen(versionstring) + strlen(kpathsea_version_string);
- s = xtalloc(slen, char);
- /* The Web2c version string starts with a space. */
- i = snprintf(s, slen,
- "%.4d/%.2d/%.2d %.2d:%.2d %s %s %s%s %s",
- year, month, day, time / 60, time % 60,
- name_string, format_string, ptexbanner,
- versionstring, kpathsea_version_string);
- check_nprintf(i, slen);
- job_id_string = xstrdup(s);
- xfree(s);
- xfree(name_string);
- xfree(format_string);
-}
-
-void make_pdftex_banner(void)
-{
- static boolean pdftexbanner_init = false;
- char *s;
- size_t slen;
- int i;
-
- if (pdftexbanner_init)
- return;
-
- slen = SMALL_BUF_SIZE +
- strlen(ptexbanner) +
- strlen(versionstring) + strlen(kpathsea_version_string);
- s = xtalloc(slen, char);
- /* The Web2c version string starts with a space. */
- i = snprintf(s, slen,
- "%s%s %s", ptexbanner, versionstring, kpathsea_version_string);
- check_nprintf(i, slen);
- pdftex_banner = maketexstring(s);
- xfree(s);
- pdftexbanner_init = true;
-}
-
-str_number get_resname_prefix(void)
-{
-/* static char name_str[] = */
-/* "!\"$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\" */
-/* "^_`abcdefghijklmnopqrstuvwxyz|~"; */
- static char name_str[] =
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
- char prefix[7]; /* make a tag of 6 chars long */
- unsigned long crc;
- short i;
- size_t base = strlen(name_str);
- crc = crc32(0L, Z_NULL, 0);
- crc = crc32(crc, (Bytef *) job_id_string, strlen(job_id_string));
- for (i = 0; i < 6; i++) {
- prefix[i] = name_str[crc % base];
- crc /= base;
- }
- prefix[6] = 0;
- return maketexstring(prefix);
-}
-
-size_t xfwrite(void *ptr, size_t size, size_t nmemb, FILE * stream)
-{
- if (fwrite(ptr, size, nmemb, stream) != nmemb)
- pdftex_fail("fwrite() failed");
- return nmemb;
-}
-
-int xfflush(FILE * stream)
-{
- if (fflush(stream) != 0)
- pdftex_fail("fflush() failed (%s)", strerror(errno));
- return 0;
-}
-
-int xgetc(FILE * stream)
-{
- int c = getc(stream);
- if (c < 0 && c != EOF)
- pdftex_fail("getc() failed (%s)", strerror(errno));
- return c;
-}
-
-int xputc(int c, FILE * stream)
-{
- int i = putc(c, stream);
- if (i < 0)
- pdftex_fail("putc() failed (%s)", strerror(errno));
- return i;
-}
-
-void write_stream_length(integer length, longinteger offset)
-{
- if (jobname_cstr == NULL)
- jobname_cstr = xstrdup(makecstring(job_name));
- if (fixed_pdf_draftmode == 0) {
- xfseeko(pdf_file, (off_t) offset, SEEK_SET, jobname_cstr);
- fprintf(pdf_file, "%li", (long int) length);
- xfseeko(pdf_file, (off_t) pdfoffset(), SEEK_SET, jobname_cstr);
- }
-}
-
-scaled ext_xn_over_d(scaled x, scaled n, scaled d)
-{
- double r = (((double) x) * ((double) n)) / ((double) d);
- if (r > DBL_EPSILON)
- r += 0.5;
- else
- r -= 0.5;
- if (r >= (double) max_integer || r <= -(double) max_integer)
- pdftex_warn("arithmetic: number too big");
- return (scaled) r;
-}
-
-void libpdffinish(void)
-{
- xfree(fb_array);
- xfree(char_array);
- xfree(job_id_string);
- fm_free();
- t1_free();
- enc_free();
- epdf_free();
- ttf_free();
- sfd_free();
- glyph_unicode_free();
- zip_free();
-}
-
-/* Converts any string given in in in an allowed PDF string which can be
- * handled by printf et.al.: \ is escaped to \\, parenthesis are escaped and
- * control characters are octal encoded.
- * This assumes that the string does not contain any already escaped
- * characters!
- */
-char *convertStringToPDFString(const char *in, int len)
-{
- static char pstrbuf[MAX_PSTRING_LEN];
- char *out = pstrbuf;
- int i, j, k;
- char buf[5];
- j = 0;
- for (i = 0; i < len; i++) {
- check_buf(j + sizeof(buf), MAX_PSTRING_LEN);
- if (((unsigned char) in[i] < '!') || ((unsigned char) in[i] > '~')) {
- /* convert control characters into oct */
- k = snprintf(buf, sizeof(buf),
- "\\%03o", (unsigned int) (unsigned char) in[i]);
- check_nprintf(k, sizeof(buf));
- out[j++] = buf[0];
- out[j++] = buf[1];
- out[j++] = buf[2];
- out[j++] = buf[3];
- } else if ((in[i] == '(') || (in[i] == ')')) {
- /* escape paranthesis */
- out[j++] = '\\';
- out[j++] = in[i];
- } else if (in[i] == '\\') {
- /* escape backslash */
- out[j++] = '\\';
- out[j++] = '\\';
- } else {
- /* copy char :-) */
- out[j++] = in[i];
- }
- }
- out[j] = '\0';
- return pstrbuf;
-}
-
-/* Converts any string given in in in an allowed PDF string which can be
- * handled by printf et.al.: \ is escaped to \\, parenthesis are escaped and
- * control characters are octal encoded.
- * This assumes that the string does not contain any already escaped
- * characters!
- *
- * See escapename for parameter description.
- */
-void escapestring(poolpointer in)
-{
- const poolpointer out = pool_ptr;
- unsigned char ch;
- int i;
- while (in < out) {
- if (pool_ptr + 4 >= pool_size) {
- pool_ptr = pool_size;
- /* error by str_toks that calls str_room(1) */
- return;
- }
-
- ch = (unsigned char) str_pool[in++];
-
- if ((ch < '!') || (ch > '~')) {
- /* convert control characters into oct */
- i = snprintf((char *) &str_pool[pool_ptr], 5,
- "\\%.3o", (unsigned int) ch);
- check_nprintf(i, 5);
- pool_ptr += i;
- continue;
- }
- if ((ch == '(') || (ch == ')') || (ch == '\\')) {
- /* escape parenthesis and backslash */
- str_pool[pool_ptr++] = '\\';
- }
- /* copy char :-) */
- str_pool[pool_ptr++] = ch;
- }
-}
-
-/* Convert any given string in a PDF name using escaping mechanism
- of PDF 1.2. The result does not include the leading slash.
-
- PDF specification 1.6, section 3.2.6 "Name Objects" explains:
- <blockquote>
- Beginning with PDF 1.2, any character except null (character code 0) may
- be included in a name by writing its 2-digit hexadecimal code, preceded
- by the number sign character (#); see implementation notes 3 and 4 in
- Appendix H. This syntax is required to represent any of the delimiter or
- white-space characters or the number sign character itself; it is
- recommended but not required for characters whose codes are outside the
- range 33 (!) to 126 (~).
- </blockquote>
- The following table shows the conversion that are done by this
- function:
- code result reason
- -----------------------------------
- 0 ignored not allowed
- 1..32 escaped must for white-space:
- 9 (tab), 10 (lf), 12 (ff), 13 (cr), 32 (space)
- recommended for the other control characters
- 35 escaped escape char "#"
- 37 escaped delimiter "%"
- 40..41 escaped delimiters "(" and ")"
- 47 escaped delimiter "/"
- 60 escaped delimiter "<"
- 62 escaped delimiter ">"
- 91 escaped delimiter "["
- 93 escaped delimiter "]"
- 123 escaped delimiter "{"
- 125 escaped delimiter "}"
- 127..255 escaped recommended
- else copy regular characters
-
- Parameter "in" is a pointer into the string pool where
- the input string is located. The output string is written
- as temporary string right after the input string.
- Thus at the begin of the procedure the global variable
- "pool_ptr" points to the start of the output string and
- after the end when the procedure returns.
-*/
-void escapename(poolpointer in)
-{
- const poolpointer out = pool_ptr;
- unsigned char ch;
- int i;
-
- while (in < out) {
- if (pool_ptr + 3 >= pool_size) {
- pool_ptr = pool_size;
- /* error by str_toks that calls str_room(1) */
- return;
- }
-
- ch = (unsigned char) str_pool[in++];
-
- if ((ch >= 1 && ch <= 32) || ch >= 127) {
- /* escape */
- i = snprintf((char *) &str_pool[pool_ptr], 4,
- "#%.2X", (unsigned int) ch);
- check_nprintf(i, 4);
- pool_ptr += i;
- continue;
- }
- switch (ch) {
- case 0:
- /* ignore */
- break;
- case 35:
- case 37:
- case 40:
- case 41:
- case 47:
- case 60:
- case 62:
- case 91:
- case 93:
- case 123:
- case 125:
- /* escape */
- i = snprintf((char *) &str_pool[pool_ptr], 4,
- "#%.2X", (unsigned int) ch);
- check_nprintf(i, 4);
- pool_ptr += i;
- break;
- default:
- /* copy */
- str_pool[pool_ptr++] = ch;
- }
- }
-}
-
-/* Convert any given string in a PDF hexadecimal string. The
- result does not include the angle brackets.
-
- This procedure uses uppercase hexadecimal letters.
-
- See escapename for description of parameters.
-*/
-void escapehex(poolpointer in)
-{
- const poolpointer out = pool_ptr;
- unsigned char ch;
- int i;
-
- while (in < out) {
- if (pool_ptr + 2 >= pool_size) {
- pool_ptr = pool_size;
- /* error by str_toks that calls str_room(1) */
- return;
- }
-
- ch = (unsigned char) str_pool[in++];
-
- i = snprintf((char *) &str_pool[pool_ptr], 3, "%.2X",
- (unsigned int) ch);
- check_nprintf(i, 3);
- pool_ptr += 2;
- }
-}
-
-/* Unescape any given hexadecimal string.
-
- Last hex digit can be omitted, it is replaced by zero, see
- PDF specification.
-
- Invalid digits are silently ignored.
-
- See escapename for description of parameters.
-*/
-void unescapehex(poolpointer in)
-{
- const poolpointer out = pool_ptr;
- unsigned char ch;
- boolean first = true;
- unsigned char a = 0; /* to avoid warning about uninitialized use of a */
- while (in < out) {
- if (pool_ptr + 1 >= pool_size) {
- pool_ptr = pool_size;
- /* error by str_toks that calls str_room(1) */
- return;
- }
-
- ch = (unsigned char) str_pool[in++];
-
- if ((ch >= '0') && (ch <= '9')) {
- ch -= '0';
- } else if ((ch >= 'A') && (ch <= 'F')) {
- ch -= 'A' - 10;
- } else if ((ch >= 'a') && (ch <= 'f')) {
- ch -= 'a' - 10;
- } else {
- continue; /* ignore wrong character */
- }
-
- if (first) {
- a = ch << 4;
- first = false;
- continue;
- }
-
- str_pool[pool_ptr++] = a + ch;
- first = true;
- }
- if (!first) { /* last hex digit is omitted */
- str_pool[pool_ptr++] = a;
- }
-}
-
-/* Converts any string given in in in an allowed PDF string which is
- * hexadecimal encoded;
- * sizeof(out) should be at least lin*2+1.
- */
-
-static void convertStringToHexString(const char *in, char *out, int lin)
-{
- int i, j, k;
- char buf[3];
- j = 0;
- for (i = 0; i < lin; i++) {
- k = snprintf(buf, sizeof(buf),
- "%02X", (unsigned int) (unsigned char) in[i]);
- check_nprintf(k, sizeof(buf));
- out[j++] = buf[0];
- out[j++] = buf[1];
- }
- out[j] = '\0';
-}
-
-/* Compute the ID string as per PDF1.4 9.3:
- <blockquote>
- File identifers are defined by the optional ID entry in a PDF file's
- trailer dictionary (see Section 3.4.4, "File Trailer"; see also
- implementation note 105 in Appendix H). The value of this entry is an
- array of two strings. The first string is a permanent identifier based
- on the contents of the file at the time it was originally created, and
- does not change when the file is incrementally updated. The second
- string is a changing identifier based on the file's contents at the
- time it was last updated. When a file is first written, both
- identifiers are set to the same value. If both identifiers match when a
- file reference is resolved, it is very likely that the correct file has
- been found; if only the first identifier matches, then a different
- version of the correct file has been found.
- To help ensure the uniqueness of file identifiers, it is recommend
- that they be computed using a message digest algorithm such as MD5
- (described in Internet RFC 1321, The MD5 Message-Digest Algorithm; see
- the Bibliography), using the following information (see implementation
- note 106 in Appendix H):
- - The current time
- - A string representation of the file's location, usually a pathname
- - The size of the file in bytes
- - The values of all entries in the file's document information
- dictionary (see Section 9.2.1, Document Information Dictionary )
- </blockquote>
- This stipulates only that the two IDs must be identical when the file is
- created and that they should be reasonably unique. Since it's difficult
- to get the file size at this point in the execution of pdfTeX and
- scanning the info dict is also difficult, we start with a simpler
- implementation using just the first two items.
- */
-void print_ID(str_number filename)
-{
- time_t t;
- size_t size;
- char time_str[32];
- md5_state_t state;
- md5_byte_t digest[16];
- char id[64];
- char *file_name;
- char pwd[4096];
- /* start md5 */
- md5_init(&state);
- /* get the time */
- t = time(NULL);
- size = strftime(time_str, sizeof(time_str), "%Y%m%dT%H%M%SZ", gmtime(&t));
- md5_append(&state, (const md5_byte_t *) time_str, size);
- /* get the file name */
- if (getcwd(pwd, sizeof(pwd)) == NULL)
- pdftex_fail("getcwd() failed (%s), (path too long?)", strerror(errno));
- file_name = makecstring(filename);
- md5_append(&state, (const md5_byte_t *) pwd, strlen(pwd));
- md5_append(&state, (const md5_byte_t *) "/", 1);
- md5_append(&state, (const md5_byte_t *) file_name, strlen(file_name));
- /* finish md5 */
- md5_finish(&state, digest);
- /* write the IDs */
- convertStringToHexString((char *) digest, id, 16);
- pdf_printf("/ID [<%s> <%s>]", id, id);
-}
-
-/* Print the /CreationDate entry.
-
- PDF Reference, third edition says about the expected date format:
- <blockquote>
- 3.8.2 Dates
-
- PDF defines a standard date format, which closely follows that of
- the international standard ASN.1 (Abstract Syntax Notation One),
- defined in ISO/IEC 8824 (see the Bibliography). A date is a string
- of the form
-
- (D:YYYYMMDDHHmmSSOHH'mm')
-
- where
-
- YYYY is the year
- MM is the month
- DD is the day (01-31)
- HH is the hour (00-23)
- mm is the minute (00-59)
- SS is the second (00-59)
- O is the relationship of local time to Universal Time (UT),
- denoted by one of the characters +, -, or Z (see below)
- HH followed by ' is the absolute value of the offset from UT
- in hours (00-23)
- mm followed by ' is the absolute value of the offset from UT
- in minutes (00-59)
-
- The apostrophe character (') after HH and mm is part of the syntax.
- All fields after the year are optional. (The prefix D:, although also
- optional, is strongly recommended.) The default values for MM and DD
- are both 01; all other numerical fields default to zero values. A plus
- sign (+) as the value of the O field signifies that local time is
- later than UT, a minus sign (-) that local time is earlier than UT,
- and the letter Z that local time is equal to UT. If no UT information
- is specified, the relationship of the specified time to UT is
- considered to be unknown. Whether or not the time zone is known, the
- rest of the date should be specified in local time.
-
- For example, December 23, 1998, at 7:52 PM, U.S. Pacific Standard
- Time, is represented by the string
-
- D:199812231952-08'00'
- </blockquote>
-
- The main difficulty is get the time zone offset. strftime() does this in ISO
- C99 (e.g. newer glibc) with %z, but we have to work with other systems (e.g.
- Solaris 2.5).
-*/
-
-static time_t start_time = 0;
-#define TIME_STR_SIZE 30
-static char start_time_str[TIME_STR_SIZE]; /* minimum size for time_str is 24: "D:YYYYmmddHHMMSS+HH'MM'" */
-
-static void makepdftime(time_t t, char *time_str)
-{
- struct tm lt, gmt;
- size_t size;
- int i, off, off_hours, off_mins;
-
- /* get the time */
- lt = *localtime(&t);
- size = strftime(time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", &lt);
- /* expected format: "YYYYmmddHHMMSS" */
- if (size == 0) {
- /* unexpected, contents of time_str is undefined */
- time_str[0] = '\0';
- return;
- }
-
- /* correction for seconds: %S can be in range 00..61,
- the PDF reference expects 00..59,
- therefore we map "60" and "61" to "59" */
- if (time_str[14] == '6') {
- time_str[14] = '5';
- time_str[15] = '9';
- time_str[16] = '\0'; /* for safety */
- }
-
- /* get the time zone offset */
- gmt = *gmtime(&t);
-
- /* this calculation method was found in exim's tod.c */
- off = 60 * (lt.tm_hour - gmt.tm_hour) + lt.tm_min - gmt.tm_min;
- if (lt.tm_year != gmt.tm_year) {
- off += (lt.tm_year > gmt.tm_year) ? 1440 : -1440;
- } else if (lt.tm_yday != gmt.tm_yday) {
- off += (lt.tm_yday > gmt.tm_yday) ? 1440 : -1440;
- }
-
- if (off == 0) {
- time_str[size++] = 'Z';
- time_str[size] = 0;
- } else {
- off_hours = off / 60;
- off_mins = abs(off - off_hours * 60);
- i = snprintf(&time_str[size], 9, "%+03d'%02d'", off_hours, off_mins);
- check_nprintf(i, 9);
- }
-}
-
-void init_start_time(void)
-{
- if (start_time == 0) {
- start_time = time((time_t *) NULL);
- makepdftime(start_time, start_time_str);
- }
-}
-
-void print_creation_date(void)
-{
- init_start_time();
- pdf_printf("/CreationDate (%s)\n", start_time_str);
-}
-
-void print_mod_date(void)
-{
- init_start_time();
- pdf_printf("/ModDate (%s)\n", start_time_str);
-}
-
-void getcreationdate(void)
-{
- /* put creation date on top of string pool and update pool_ptr */
- size_t len = strlen(start_time_str);
-
- init_start_time();
-
- if ((unsigned) (pool_ptr + len) >= (unsigned) pool_size) {
- pool_ptr = pool_size;
- /* error by str_toks that calls str_room(1) */
- return;
- }
-
- memcpy(&str_pool[pool_ptr], start_time_str, len);
- pool_ptr += len;
-}
-
-/* makecfilename
- input/ouput same as makecstring:
- input: string number
- output: C string with quotes removed.
- That means, file names that are legal on some operation systems
- cannot any more be used since pdfTeX version 1.30.4.
-*/
-char *makecfilename(str_number s)
-{
- char *name = makecstring(s);
- char *p = name;
- char *q = name;
-
- while (*p) {
- if (*p != '"')
- *q++ = *p;
- p++;
- }
- *q = '\0';
- return name;
-}
-
-/* function strips trailing zeros in string with numbers; */
-/* leading zeros are not stripped (as in real life) */
-char *stripzeros(char *a)
-{
- enum { NONUM, DOTNONUM, INT, DOT, LEADDOT, FRAC } s = NONUM, t = NONUM;
- char *p, *q, *r;
- for (p = q = r = a; *p != '\0';) {
- switch (s) {
- case NONUM:
- if (*p >= '0' && *p <= '9')
- s = INT;
- else if (*p == '.')
- s = LEADDOT;
- break;
- case DOTNONUM:
- if (*p != '.' && (*p < '0' || *p > '9'))
- s = NONUM;
- break;
- case INT:
- if (*p == '.')
- s = DOT;
- else if (*p < '0' || *p > '9')
- s = NONUM;
- break;
- case DOT:
- case LEADDOT:
- if (*p >= '0' && *p <= '9')
- s = FRAC;
- else if (*p == '.')
- s = DOTNONUM;
- else
- s = NONUM;
- break;
- case FRAC:
- if (*p == '.')
- s = DOTNONUM;
- else if (*p < '0' || *p > '9')
- s = NONUM;
- break;
- default:;
- }
- switch (s) {
- case DOT:
- r = q;
- break;
- case LEADDOT:
- r = q + 1;
- break;
- case FRAC:
- if (*p > '0')
- r = q + 1;
- break;
- case NONUM:
- if ((t == FRAC || t == DOT) && r != a) {
- q = r--;
- if (*r == '.') /* was a LEADDOT */
- *r = '0';
- r = a;
- }
- break;
- default:;
- }
- *q++ = *p++;
- t = s;
- }
- *q = '\0';
- return a;
-}
-
-void initversionstring(char **versions)
-{
- (void) asprintf(versions,
- "Compiled with libpng %s; using libpng %s\n"
- "Compiled with zlib %s; using zlib %s\n"
- "Compiled with %s version %s\n",
- PNG_LIBPNG_VER_STRING, png_libpng_ver,
- ZLIB_VERSION, zlib_version, xpdfString, xpdfVersion);
-}
-
-/*************************************************/
-/* Color Stack and Matrix Transformation Support */
-/*************************************************/
-
-/*
- In the following array and especially stack data structures are used.
- They have the following properties:
- - They automatically grow dynamically.
- - The size never decreases.
- - The variable with name ending in "size" contains the number how many
- entries the data structure can hold.
- - The variable with name ending in "used" contains the number of
- actually used entries.
- - Memory of strings in stack entries must be allocated and
- freed if the stack is cleared.
-*/
-
-/* Color Stack */
-
-#define STACK_INCREMENT 8
-#define MAX_COLORSTACKS 32768
-/* The colorstack number is stored in two bytes (info field of the node) */
-/* Condition (newcolorstack): MAX_COLORSTACKS mod STACK_INCREMENT = 0 */
-
-#define COLOR_DEFAULT "0 g 0 G"
-/* literal_modes, see pdftex.web */
-#define SET_ORIGIN 0
-#define DIRECT_PAGE 1
-#define DIRECT_ALWAYS 2
-
-/* remember shipout mode: page/form */
-static boolean page_mode;
-
-typedef struct {
- char **page_stack;
- char **form_stack;
- char *page_current;
- char *form_current;
- char *form_init;
- int page_size;
- int form_size;
- int page_used;
- int form_used;
- int literal_mode;
- boolean page_start;
-} colstack_type;
-
-static colstack_type *colstacks = NULL;
-static int colstacks_size = 0;
-static int colstacks_used = 0;
-
-/* Initialization is done, if the color stacks are used,
- init_colorstacks() is defined as macro to avoid unnecessary
- procedure calls.
-*/
-#define init_colorstacks() if (colstacks_size == 0) colstacks_first_init();
-static void colstacks_first_init(void)
-{
- colstacks_size = STACK_INCREMENT;
- colstacks = xtalloc(colstacks_size, colstack_type);
- colstacks_used = 1;
- colstacks[0].page_stack = NULL;
- colstacks[0].form_stack = NULL;
- colstacks[0].page_size = 0;
- colstacks[0].form_size = 0;
- colstacks[0].page_used = 0;
- colstacks[0].form_used = 0;
- colstacks[0].page_current = xstrdup(COLOR_DEFAULT);
- colstacks[0].form_current = xstrdup(COLOR_DEFAULT);
- colstacks[0].form_init = xstrdup(COLOR_DEFAULT);
- colstacks[0].literal_mode = DIRECT_ALWAYS;
- colstacks[0].page_start = true;
-}
-
-int colorstackused(void)
-{
- init_colorstacks();
- return colstacks_used;
-}
-
-/* newcolorstack()
- A new color stack is setup with the given parameters.
- The stack number is returned or -1 in case of error (no room).
-*/
-int newcolorstack(integer s, integer literal_mode, boolean page_start)
-{
- colstack_type *colstack;
- int colstack_num;
- char *str;
-
- init_colorstacks();
-
- /* make room */
- if (colstacks_used == MAX_COLORSTACKS) {
- return -1;
- }
- if (colstacks_used == colstacks_size) {
- colstacks_size += STACK_INCREMENT;
- /* If (MAX_COLORSTACKS mod STACK_INCREMENT = 0) then we don't
- need to check the case that size overruns MAX_COLORSTACKS. */
- colstacks = xreallocarray(colstacks, colstack_type, colstacks_size);
- }
- /* claim new color stack */
- colstack_num = colstacks_used++;
- colstack = &colstacks[colstack_num];
- /* configure the new color stack */
- colstack->page_stack = NULL;
- colstack->form_stack = NULL;
- colstack->page_size = 0;
- colstack->page_used = 0;
- colstack->form_size = 0;
- colstack->form_used = 0;
- colstack->literal_mode = literal_mode;
- colstack->page_start = page_start;
- str = makecstring(s);
- if (*str == 0) {
- colstack->page_current = NULL;
- colstack->form_current = NULL;
- colstack->form_init = NULL;
- } else {
- colstack->page_current = xstrdup(str);
- colstack->form_current = xstrdup(str);
- colstack->form_init = xstrdup(str);
- }
- return colstack_num;
-}
-
-#define get_colstack(n) (&colstacks[n])
-
-/* Puts a string on top of the string pool and updates pool_ptr. */
-static void put_cstring_on_str_pool(poolpointer start, char *str)
-{
- size_t len;
-
- if (str == NULL || *str == 0) {
- return;
- }
-
- len = strlen(str);
- pool_ptr = start + len;
- if (pool_ptr >= pool_size) {
- pool_ptr = pool_size;
- /* error by str_toks that calls str_room(1) */
- return;
- }
- memcpy(&str_pool[start], str, len);
-}
-
-integer colorstackset(int colstack_no, integer s)
-{
- colstack_type *colstack = get_colstack(colstack_no);
-
- if (page_mode) {
- xfree(colstack->page_current);
- colstack->page_current = xstrdup(makecstring(s));
- } else {
- xfree(colstack->form_current);
- colstack->form_current = xstrdup(makecstring(s));
- }
- return colstack->literal_mode;
-}
-
-integer colorstackcurrent(int colstack_no)
-{
- colstack_type *colstack = get_colstack(colstack_no);
-
- if (page_mode) {
- put_cstring_on_str_pool(pool_ptr, colstack->page_current);
- } else {
- put_cstring_on_str_pool(pool_ptr, colstack->form_current);
- }
- return colstack->literal_mode;
-}
-
-integer colorstackpush(int colstack_no, integer s)
-{
- colstack_type *colstack = get_colstack(colstack_no);
- char *str;
-
- if (page_mode) {
- if (colstack->page_used == colstack->page_size) {
- colstack->page_size += STACK_INCREMENT;
- colstack->page_stack = xretalloc(colstack->page_stack,
- colstack->page_size, char *);
- }
- colstack->page_stack[colstack->page_used++] = colstack->page_current;
- str = makecstring(s);
- if (*str == 0) {
- colstack->page_current = NULL;
- } else {
- colstack->page_current = xstrdup(str);
- }
- } else {
- if (colstack->form_used == colstack->form_size) {
- colstack->form_size += STACK_INCREMENT;
- colstack->form_stack = xretalloc(colstack->form_stack,
- colstack->form_size, char *);
- }
- colstack->form_stack[colstack->form_used++] = colstack->form_current;
- str = makecstring(s);
- if (*str == 0) {
- colstack->form_current = NULL;
- } else {
- colstack->form_current = xstrdup(str);
- }
- }
- return colstack->literal_mode;
-}
-
-integer colorstackpop(int colstack_no)
-{
- colstack_type *colstack = get_colstack(colstack_no);
-
- if (page_mode) {
- if (colstack->page_used == 0) {
- pdftex_warn("pop empty color page stack %u",
- (unsigned int) colstack_no);
- return colstack->literal_mode;
- }
- xfree(colstack->page_current);
- colstack->page_current = colstack->page_stack[--colstack->page_used];
- put_cstring_on_str_pool(pool_ptr, colstack->page_current);
- } else {
- if (colstack->form_used == 0) {
- pdftex_warn("pop empty color form stack %u",
- (unsigned int) colstack_no);
- return colstack->literal_mode;
- }
- xfree(colstack->form_current);
- colstack->form_current = colstack->form_stack[--colstack->form_used];
- put_cstring_on_str_pool(pool_ptr, colstack->form_current);
- }
- return colstack->literal_mode;
-}
-
-static void colorstackpagestart(void)
-{
- int i, j;
- colstack_type *colstack;
-
- if (page_mode) {
- /* see procedure pdf_out_colorstack_startpage */
- return;
- }
-
- for (i = 0; i < colstacks_used; i++) {
- colstack = &colstacks[i];
- for (j = 0; j < colstack->form_used; j++) {
- xfree(colstack->form_stack[j]);
- }
- colstack->form_used = 0;
- xfree(colstack->form_current);
- if (colstack->form_init == NULL) {
- colstack->form_current = NULL;
- } else {
- colstack->form_current = xstrdup(colstack->form_init);
- }
- }
-}
-
-integer colorstackskippagestart(int colstack_no)
-{
- colstack_type *colstack = get_colstack(colstack_no);
-
- if (!colstack->page_start) {
- return 1;
- }
- if (colstack->page_current == NULL) {
- return 0;
- }
- if (strcmp(COLOR_DEFAULT, colstack->page_current) == 0) {
- return 2;
- }
- return 0;
-}
-
-/* stack for \pdfsetmatrix */
-
-typedef struct {
- double a;
- double b;
- double c;
- double d;
- double e;
- double f;
-} matrix_entry;
-static matrix_entry *matrix_stack = 0;
-static int matrix_stack_size = 0;
-static int matrix_stack_used = 0;
-
-boolean matrixused(void)
-{
- return matrix_stack_used > 0;
-}
-
-/* stack for positions of \pdfsave */
-typedef struct {
- scaledpos pos;
- int matrix_stack;
-} pos_entry;
-static pos_entry *pos_stack = 0; /* the stack */
-static int pos_stack_size = 0; /* initially empty */
-static int pos_stack_used = 0; /* used entries */
-
-static void matrix_stack_room(void)
-{
- matrix_entry *new_stack;
-
- if (matrix_stack_used >= matrix_stack_size) {
- matrix_stack_size += STACK_INCREMENT;
- new_stack = xtalloc(matrix_stack_size, matrix_entry);
- memcpy((void *) new_stack, (void *) matrix_stack,
- matrix_stack_used * sizeof(matrix_entry));
- xfree(matrix_stack);
- matrix_stack = new_stack;
- }
-}
-
-void checkpdfsave(scaledpos pos)
-{
- pos_entry *new_stack;
-
- if (pos_stack_used >= pos_stack_size) {
- pos_stack_size += STACK_INCREMENT;
- new_stack = xtalloc(pos_stack_size, pos_entry);
- memcpy((void *) new_stack, (void *) pos_stack,
- pos_stack_used * sizeof(pos_entry));
- xfree(pos_stack);
- pos_stack = new_stack;
- }
- pos_stack[pos_stack_used].pos.h = pos.h;
- pos_stack[pos_stack_used].pos.v = pos.v;
- if (page_mode) {
- pos_stack[pos_stack_used].matrix_stack = matrix_stack_used;
- }
- pos_stack_used++;
-}
-
-void checkpdfrestore(scaledpos pos)
-{
- scaledpos diff;
- if (pos_stack_used == 0) {
- pdftex_warn("%s", "\\pdfrestore: missing \\pdfsave");
- return;
- }
- pos_stack_used--;
- diff.h = pos.h - pos_stack[pos_stack_used].pos.h;
- diff.v = pos.v - pos_stack[pos_stack_used].pos.v;
- if (diff.h != 0 || diff.v != 0) {
- pdftex_warn("Misplaced \\pdfrestore by (%dsp, %dsp)", (int) diff.h,
- (int) diff.v);
- }
- if (page_mode) {
- matrix_stack_used = pos_stack[pos_stack_used].matrix_stack;
- }
-}
-
-void pdfshipoutbegin(boolean shipping_page)
-{
- pos_stack_used = 0; /* start with empty stack */
-
- page_mode = shipping_page;
- if (shipping_page) {
- colorstackpagestart();
- }
-}
-
-void pdfshipoutend(boolean shipping_page)
-{
- if (pos_stack_used > 0) {
- pdftex_fail("%u unmatched \\pdfsave after %s shipout",
- (unsigned int) pos_stack_used,
- ((shipping_page) ? "page" : "form"));
- }
-}
-
-/* \pdfsetmatrix{a b c d}
- e := pos.h
- f := pos.v
- M_top: current active matrix at the top of
- the matrix stack
-
- The origin of \pdfsetmatrix is the current point.
- The annotation coordinate system is the original
- page coordinate system. When pdfTeX calculates
- annotation rectangles it does not take into
- account this transformations, it uses the original
- coordinate system. To get the corrected values,
- first we go back to the origin, perform the
- transformation and go back:
-
- ( 1 0 0 ) ( a b 0 ) ( 1 0 0 )
- ( 0 1 0 ) x ( c d 0 ) x ( 0 1 0 ) x M_top
- ( -e -f 1 ) ( 0 0 1 ) ( e f 1 )
-
- ( 1 0 0 ) ( a b 0 )
- = ( 0 1 0 ) x ( c d 0 ) x M_top
- ( e f 1 ) ( -e -f 1 )
-
- ( a b 0 )
- = ( c d 0 ) x M_top
- ( e(1-a)-fc f(1-d)-eb 1 )
-
-*/
-
-void pdfsetmatrix(poolpointer in, scaledpos pos)
-{
- /* Argument of \pdfsetmatrix starts with str_pool[in] and ends
- before str_pool[pool_ptr]. */
-
- matrix_entry x, *y, *z;
-
- if (page_mode) {
- if (sscanf((const char *) &str_pool[in], " %lf %lf %lf %lf ",
- &x.a, &x.b, &x.c, &x.d) != 4) {
- pdftex_warn("Unrecognized format of \\pdfsetmatrix{%s}",
- &str_pool[pool_ptr]);
- return;
- }
- /* calculate this transformation matrix */
- x.e = (double) pos.h * (1.0 - x.a) - (double) pos.v * x.c;
- x.f = (double) pos.v * (1.0 - x.d) - (double) pos.h * x.b;
- matrix_stack_room();
- z = &matrix_stack[matrix_stack_used];
- if (matrix_stack_used > 0) {
- y = &matrix_stack[matrix_stack_used - 1];
- z->a = x.a * y->a + x.b * y->c;
- z->b = x.a * y->b + x.b * y->d;
- z->c = x.c * y->a + x.d * y->c;
- z->d = x.c * y->b + x.d * y->d;
- z->e = x.e * y->a + x.f * y->c + y->e;
- z->f = x.e * y->b + x.f * y->d + y->f;
- } else {
- z->a = x.a;
- z->b = x.b;
- z->c = x.c;
- z->d = x.d;
- z->e = x.e;
- z->f = x.f;
- }
- matrix_stack_used++;
- }
-}
-
-/* Apply matrix to point (x,y)
-
- ( a b 0 )
- ( x y 1 ) x ( c d 0 ) = ( xa+yc+e xb+yd+f 1 )
- ( e f 1 )
-
- If \pdfsetmatrix wasn't used, then return the value unchanged.
-*/
-
-/* Return valeus for matrix tranform functions */
-static scaled ret_llx;
-static scaled ret_lly;
-static scaled ret_urx;
-static scaled ret_ury;
-
-scaled getllx(void)
-{
- return ret_llx;
-}
-
-scaled getlly(void)
-{
- return ret_lly;
-}
-
-scaled geturx(void)
-{
- return ret_urx;
-}
-
-scaled getury(void)
-{
- return ret_ury;
-}
-
-static int last_llx;
-static int last_lly;
-static int last_urx;
-static int last_ury;
-
-#define DO_ROUND(x) ((x > 0) ? (x + .5) : (x - .5))
-#define DO_MIN(a, b) ((a < b) ? a : b)
-#define DO_MAX(a, b) ((a > b) ? a : b)
-
-static void do_matrixtransform(scaled x, scaled y, scaled * retx, scaled * rety)
-{
- matrix_entry *m = &matrix_stack[matrix_stack_used - 1];
- double x_old = x;
- double y_old = y;
- double x_new = x_old * m->a + y_old * m->c + m->e;
- double y_new = x_old * m->b + y_old * m->d + m->f;
- *retx = (scaled) DO_ROUND(x_new);
- *rety = (scaled) DO_ROUND(y_new);
-}
-
-void matrixtransformrect(scaled llx, scaled lly, scaled urx, scaled ury)
-{
- scaled x1, x2, x3, x4, y1, y2, y3, y4;
-
- if (page_mode && matrix_stack_used > 0) {
- last_llx = llx;
- last_lly = lly;
- last_urx = urx;
- last_ury = ury;
- do_matrixtransform(llx, lly, &x1, &y1);
- do_matrixtransform(llx, ury, &x2, &y2);
- do_matrixtransform(urx, lly, &x3, &y3);
- do_matrixtransform(urx, ury, &x4, &y4);
- ret_llx = DO_MIN(DO_MIN(x1, x2), DO_MIN(x3, x4));
- ret_lly = DO_MIN(DO_MIN(y1, y2), DO_MIN(y3, y4));
- ret_urx = DO_MAX(DO_MAX(x1, x2), DO_MAX(x3, x4));
- ret_ury = DO_MAX(DO_MAX(y1, y2), DO_MAX(y3, y4));
- } else {
- ret_llx = llx;
- ret_lly = lly;
- ret_urx = urx;
- ret_ury = ury;
- }
-}
-
-void matrixtransformpoint(scaled x, scaled y)
-{
- if (page_mode && matrix_stack_used > 0) {
- do_matrixtransform(x, y, &ret_llx, &ret_lly);
- } else {
- ret_llx = x;
- ret_lly = y;
- }
-}
-
-void matrixrecalculate(scaled urx)
-{
- matrixtransformrect(last_llx, last_lly, urx, last_ury);
-}
-
-void check_buffer_overflow(int wsize)
-{
- int nsize;
- if (wsize > buf_size) {
- nsize = buf_size + buf_size / 5 + 5;
- if (nsize < wsize) {
- nsize = wsize + 5;
- }
- buffer = (unsigned char *) xreallocarray(buffer, char, nsize);
- buf_size = nsize;
- }
-}
-
-#define EXTRA_STRING 500
-
-void check_pool_overflow(int wsize)
-{
- int nsize;
- if ((wsize - 1) > pool_size) {
- nsize = pool_size + pool_size / 5 + EXTRA_STRING;
- if (nsize < wsize) {
- nsize = wsize + EXTRA_STRING;
- }
- str_pool = (unsigned char *) xreallocarray(str_pool, char, nsize);
- pool_size = nsize;
- }
-}
-
-#define max_integer 0x7FFFFFFF
-
-/* the return value is a decimal number with the point |dd| places from the back,
- |scaled_out| is the number of scaled points corresponding to that.
-*/
-
-scaled divide_scaled(scaled s, scaled m, integer dd)
-{
- register scaled q;
- register scaled r;
- int i;
- int sign = 1;
- if (s < 0) {
- sign = -sign;
- s = -s;
- }
- if (m < 0) {
- sign = -sign;
- m = -m;
- }
- if (m == 0) {
- pdf_error(maketexstring("arithmetic"),
- maketexstring("divided by zero"));
- } else if (m >= (max_integer / 10)) {
- pdf_error(maketexstring("arithmetic"), maketexstring("number too big"));
- }
- q = s / m;
- r = s % m;
- for (i = 1; i <= (int) dd; i++) {
- q = 10 * q + (10 * r) / m;
- r = (10 * r) % m;
- }
- /* rounding */
- if (2 * r >= m) {
- q++;
- r -= m;
- }
- return sign * q;
-}
-
-/* Same function, but using doubles instead of integers (faster) */
-
-scaled divide_scaled_n(double sd, double md, double n)
-{
- double dd, di = 0.0;
- dd = sd / md * n;
- if (dd > 0.0)
- di = floor(dd + 0.5);
- else if (dd < 0.0)
- di = -floor((-dd) + 0.5);
- return (scaled) di;
-}
-
-
-/* C print interface */
-
-void tprint(const char *s)
-{
- const unsigned char *ss = (const unsigned char*) s;
- while (*ss)
- print_char(*ss++);
-}
-
-void tprint_nl(const char *s)
-{
- print_nlp();
- tprint(s);
-}
-
-#define escape_char_code 45 /* escape character for token output */
-#define int_par(a) zeqtb[static_int_base+(a)].cint /* an integer parameter */
-#define escape_char int_par(escape_char_code)
-
-void tprint_esc(const char *s)
-{ /* prints escape character, then |s| */
- int c = -1; /* the escape character code */
- if (zeqtb != NULL) {
- c = escape_char;
- if (c >= 0)
- print_char(c);
- }
- tprint(s);
-}
-
-void tconfusion(const char *s)
-{
- confusion(maketexstring(s));
-}
-
-#ifdef MSVC
-
-# include <math.h>
-double rint(double x)
-{
- double c, f, d1, d2;
-
- c = ceil(x);
- f = floor(x);
- d1 = fabs(c - x);
- d2 = fabs(x - f);
- if (d1 > d2)
- return f;
- else
- return c;
-}
-
-#endif