summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/pdfdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdfm-x/pdfdev.c')
-rw-r--r--Build/source/texk/dvipdfm-x/pdfdev.c1849
1 files changed, 0 insertions, 1849 deletions
diff --git a/Build/source/texk/dvipdfm-x/pdfdev.c b/Build/source/texk/dvipdfm-x/pdfdev.c
deleted file mode 100644
index 29980b5ade8..00000000000
--- a/Build/source/texk/dvipdfm-x/pdfdev.c
+++ /dev/null
@@ -1,1849 +0,0 @@
-/* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
-
- Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
- the dvipdfmx project team.
-
- Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
-
- 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 USA.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-
-#include "system.h"
-#include "mem.h"
-#include "error.h"
-#include "dpxconf.h"
-
-#include "mfileio.h"
-#include "numbers.h"
-
-#include "pdfdoc.h"
-#include "pdfobj.h"
-
-#include "pdffont.h"
-#include "fontmap.h"
-#include "cmap.h"
-#include "pdfximage.h"
-
-#include "pdfdraw.h"
-#include "pdfcolor.h"
-
-#include "pdflimits.h"
-
-#include "pdfdev.h"
-
-struct dev_param
-{
- /* Text composition (direction) mode is ignored (always same
- * as font's writing mode) if autorotate is unset (value zero).
- */
- int autorotate;
-
- /*
- * Ignore color migrated to here. This is device's capacity.
- * colormode 0 for ignore colors
- */
- int colormode;
-
-};
-
-/*
- * Text handling routines.
- */
-
-/* Motion state:
- * GRAPHICS_MODE Initial state (not within BT/ET block nor in string)
- * TEXT_MODE Text section is started via BT operator but not
- * in string.
- * STRING_MODE In string. A string or array of strings are currently
- * in process. May started '[', '<' or '('.
- */
-#define GRAPHICS_MODE 1
-#define TEXT_MODE 2
-#define STRING_MODE 3
-
-/*
- * In PDF, vertical text positioning is always applied when current font
- * is vertical font. While ASCII pTeX manages current writing direction
- * and font's WMode separately.
- *
- * 000/101 WMODE_HH/VV h(v) font, h(v) direction.
- * 001 WMODE_HV -90 deg. rotated
- * 100 WMODE_VH +90 deg. rotated
- * 011 WMODE_HD +90 deg. rotated
- * 111 WMODE_VD 180 deg. rotated
-
- * In MetaPost PostScript file processing (mp_mode = 1), only HH/VV mode
- * is applied.
- */
-#define TEXT_WMODE_HH 0
-#define TEXT_WMODE_HV 1
-#define TEXT_WMODE_VH 4
-#define TEXT_WMODE_VV 5
-#define TEXT_WMODE_HD 3
-#define TEXT_WMODE_VD 7
-
-#define ANGLE_CHANGES(m1,m2) ((abs((m1)-(m2)) % 5) == 0 ? 0 : 1)
-#define ROTATE_TEXT(m) ((m) != TEXT_WMODE_HH && (m) != TEXT_WMODE_VV)
-
-struct text_state {
-
- /* Current font.
- * This is index within dev_fonts.
- */
- int font_id;
-
- /* Dvipdfmx does compression of text by doing text positioning
- * in relative motion and uses string array [(foo) -250 (bar)]
- * with kerning (negative kern is used for white space as suited
- * for TeX). This is offset within current string.
- */
- spt_t offset;
-
- /* This is reference point of strings.
- * It may include error correction induced by rounding.
- */
- spt_t ref_x;
- spt_t ref_y;
-
- /* Using text raise and leading is highly recommended for
- * text extraction to work properly. But not implemented yet.
- * We can't do consice output for \TeX without this.
- */
- spt_t raise; /* unused */
- spt_t leading; /* unused */
-
- /* This is not always text matrix but rather font matrix.
- * We do not use horizontal scaling in PDF text state parameter
- * since they always apply scaling in fixed direction regardless
- * of writing mode.
- */
- struct {
- double slant;
- double extend;
- int rotate; /* TEXT_WMODE_XX */
- } matrix;
-
- /* Fake bold parameter:
- * If bold_param is positive, use text rendering mode
- * fill-then-stroke with stroking line width specified
- * by bold_param.
- */
- double bold_param;
-
- /* Text composition (direction) mode. */
- int dir_mode;
-
- /* internal */
-
- /* Flag indicating text matrix to be forcibly reset.
- * Enabled if synthetic font features (slant, extend, etc)
- * are used for current font or when text rotation mode
- * changes.
- */
- int force_reset;
-
- /* This information is duplicated from dev[font_id].format.
- * Set to 1 if font is composite (Type0) font.
- */
- int is_mb;
-};
-
-#define PDF_FONTTYPE_SIMPLE 1
-#define PDF_FONTTYPE_BITMAP 2
-#define PDF_FONTTYPE_COMPOSITE 3
-
-struct dev_font {
- /* Needs to be big enough to hold name "Fxxx"
- * where xxx is number of largest font
- */
- char short_name[16]; /* Resource name */
- int used_on_this_page;
-
- char *tex_name; /* String identifier of this font */
- spt_t sptsize; /* Point size */
-
- /* Returned values from font/encoding layer:
- *
- * The font_id and enc_id is font and encoding (CMap) identifier
- * used in pdf_font or encoding/cmap layer.
- * The PDF object "resource" is an indirect reference object
- * pointing font resource of this font. The used_chars is somewhat
- * misleading, this is actually used_glyphs in CIDFont for Type0
- * and is 65536/8 bytes binary data with each bits representing
- * whether the glyph is in-use or not. It is 256 char array for
- * simple font.
- */
- int font_id;
- int enc_id;
-
- pdf_obj *resource;
- char *used_chars;
-
- /* Font format:
- * simple, composite or bitmap.
- */
- int format;
-
- /* Writing mode:
- * Non-zero for vertical. Duplicated from CMap.
- */
- int wmode;
-
- /* Syntetic Font:
- *
- * We use text matrix for creating extended or slanted font,
- * but not with font's FontMatrix since TrueType and Type0
- * font don't support them.
- */
- double extend;
- double slant;
- double bold; /* Boldness prameter */
-};
-
-/*
- * Unit conversion, formatting and others.
- */
-
-#define TEX_ONE_HUNDRED_BP 6578176
-struct dev_unit {
- double dvi2pts; /* multiplier for DVI unit to bpt conversion */
- int min_bp_val; /* Shortest resolvable distance in the output PDF. */
- int precision; /* Number of decimal digits (in fractional part) kept. */
-};
-
-#define FORMAT_BUF_SIZE 4096
-struct pdf_dev {
- int motion_state;
- struct dev_param param;
- struct dev_unit unit;
- struct text_state text_state;
- struct dev_font *fonts;
- int num_dev_fonts;
- int max_dev_fonts;
- char format_buffer[FORMAT_BUF_SIZE+1];
-};
-
-/*
- * For a moment declare as static variable here
- * 2020/07/23 Most of the static variables put into single struct pdev
- */
-static pdf_dev pdev;
-
-static pdf_dev *
-current_device (void)
-{
- return &pdev;
-}
-
-static void
-dev_out (pdf_dev *p, const char *str, size_t len)
-{
- pdf_doc_add_page_content(str, len);
-}
-
-static double
-pdf_dev_unit_dviunit (pdf_dev *p)
-{
- ASSERT(p);
-
- return (1.0 / p->unit.dvi2pts);
-}
-
-#define DEV_PRECISION_MAX 8
-static uint32_t ten_pow[10] = {
- 1u, 10u, 100u, 1000u, 10000u, 100000u, 1000000u, 10000000u, 100000000u, 1000000000u
-};
-
-static double ten_pow_inv[10] = {
- 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, 0.00000001, 0.000000001
-};
-
-#define bpt2spt(p, b) ( (spt_t) round( (b) / (p)->unit.dvi2pts ) )
-#define spt2bpt(p, s) ( (s) * (p)->unit.dvi2pts )
-#define dround_at(v,p) (ROUND( (v), ten_pow_inv[(p)] ))
-
-static int
-p_itoa (int value, char *buf)
-{
- int sign, ndigits;
- char *p = buf;
-
- if (value < 0) {
- *p++ = '-';
- value = -value;
- sign = 1;
- } else {
- sign = 0;
- }
-
- ndigits = 0;
- /* Generate at least one digit in reverse order */
- do {
- p[ndigits++] = (value % 10) + '0';
- value /= 10;
- } while (value != 0);
-
- /* Reverse the digits */
- {
- int i;
-
- for (i = 0; i < ndigits / 2 ; i++) {
- char tmp = p[i];
- p[i] = p[ndigits-i-1];
- p[ndigits-i-1] = tmp;
- }
- }
- p[ndigits] = '\0';
-
- return (sign ? ndigits + 1 : ndigits);
-}
-
-/* NOTE: Acrobat 5 and prior uses 16.16 fixed point representation for
- * real numbers.
- */
-static int
-p_dtoa (double value, int prec, char *buf)
-{
- const int32_t p[10] = { 1, 10, 100, 1000, 10000,
- 100000, 1000000, 10000000,
- 100000000, 1000000000 };
- double i, f;
- int32_t g;
- char *c = buf;
- int n;
-
- if (value < 0) {
- value = -value;
- *c++ = '-';
- n = 1;
- } else {
- n = 0;
- }
-
- f = modf(value, &i);
- g = (int32_t) (f * p[prec] + 0.5);
-
- if (g == p[prec]) {
- g = 0;
- i += 1;
- }
-
- if (i) {
- int m = sprintf(c, "%.0f", i);
- c += m;
- n += m;
- } else if (g == 0) {
- *(c = buf) = '0';
- n = 1;
- }
-
- if (g) {
- int j = prec;
-
- *c++ = '.';
-
- while (j--) {
- c[j] = (g % 10) + '0';
- g /= 10;
- }
- c += prec - 1;
- n += 1 + prec;
-
- while (*c == '0') {
- c--;
- n--;
- }
- }
-
- *(++c) = 0;
-
- return n;
-}
-
-static int
-dev_sprint_bp (pdf_dev *p, char *buf, spt_t value, spt_t *error)
-{
- double value_in_bp;
- double error_in_bp;
- int prec;
-
- ASSERT(p);
-
- prec = p->unit.precision;
-
- value_in_bp = spt2bpt(p, value);
- if (error) {
- error_in_bp = value_in_bp - dround_at(value_in_bp, prec);
- *error = bpt2spt(p, error_in_bp);
- }
-
- return p_dtoa(value_in_bp, prec, buf);
-}
-
-/* They are affected by precision (set at device initialization). */
-static size_t
-pdf_dev_sprint_matrix (pdf_dev *p, char *buf, const pdf_tmatrix *M)
-{
- size_t len;
- int prec0, prec2;
-
- ASSERT(p);
-
- prec2 = MIN(p->unit.precision + 2, DEV_PRECISION_MAX);
- prec0 = MAX(p->unit.precision, 2);
-
- len = p_dtoa(M->a, prec2, buf);
- buf[len++] = ' ';
- len += p_dtoa(M->b, prec2, buf+len);
- buf[len++] = ' ';
- len += p_dtoa(M->c, prec2, buf+len);
- buf[len++] = ' ';
- len += p_dtoa(M->d, prec2, buf+len);
- buf[len++] = ' ';
- len += p_dtoa(M->e, prec0, buf+len);
- buf[len++] = ' ';
- len += p_dtoa(M->f, prec0, buf+len);
- buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */
-
- return len;
-}
-
-static size_t
-pdf_dev_sprint_rect (pdf_dev *p, char *buf, const pdf_rect *rect)
-{
- size_t len;
-
- ASSERT(p);
-
- len = p_dtoa(rect->llx, p->unit.precision, buf);
- buf[len++] = ' ';
- len += p_dtoa(rect->lly, p->unit.precision, buf+len);
- buf[len++] = ' ';
- len += p_dtoa(rect->urx, p->unit.precision, buf+len);
- buf[len++] = ' ';
- len += p_dtoa(rect->ury, p->unit.precision, buf+len);
- buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */
-
- return len;
-}
-
-static size_t
-pdf_dev_sprint_coord (pdf_dev *p, char *buf, const pdf_coord *c)
-{
- size_t len;
-
- ASSERT(p);
-
- len = p_dtoa(c->x, p->unit.precision, buf);
- buf[len++] = ' ';
- len += p_dtoa(c->y, p->unit.precision, buf+len);
- buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */
-
- return len;
-}
-
-static size_t
-pdf_dev_sprint_length (pdf_dev *p, char *buf, double value)
-{
- size_t len;
-
- ASSERT(p);
-
- len = p_dtoa(value, p->unit.precision, buf);
- buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */
-
- return len;
-}
-
-static size_t
-pdf_dev_sprint_number (pdf_dev *p, char *buf, double value)
-{
- size_t len;
-
- ASSERT(p);
-
- len = p_dtoa(value, DEV_PRECISION_MAX, buf);
- buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */
-
- return len;
-}
-
-/* Text handling */
-#define CURRENTFONT(p) (((p)->text_state.font_id < 0) ? \
- NULL : &((p)->fonts[(p)->text_state.font_id]))
-#define GET_FONT(p, n) (&((p)->fonts[(n)]))
-
-static void
-dev_set_text_matrix (pdf_dev *p,
- spt_t xpos, spt_t ypos,
- double slant, double extend, int rotate)
-{
- pdf_tmatrix tm;
- int len = 0;
-
- ASSERT(p);
-
- /* slant is negated for vertical font so that right-side
- * is always lower. */
- switch (rotate) {
- case TEXT_WMODE_VH:
- /* Vertical font */
- tm.a = slant ; tm.b = 1.0;
- tm.c = -extend; tm.d = 0.0 ;
- break;
- case TEXT_WMODE_HV:
- /* Horizontal font */
- tm.a = 0.0; tm.b = -extend;
- tm.c = 1.0; tm.d = -slant ;
- break;
- case TEXT_WMODE_HH:
- /* Horizontal font */
- tm.a = extend; tm.b = 0.0;
- tm.c = slant ; tm.d = 1.0;
- break;
- case TEXT_WMODE_VV:
- /* Vertical font */
- tm.a = 1.0; tm.b = -slant;
- tm.c = 0.0; tm.d = extend;
- break;
- case TEXT_WMODE_HD:
- /* Horizontal font */
- tm.a = 0.0; tm.b = extend;
- tm.c = -1.0; tm.d = slant ;
- break;
- case TEXT_WMODE_VD:
- /* Vertical font */
- tm.a = -1.0; tm.b = slant;
- tm.c = 0.0; tm.d = -extend;
- break;
- }
- tm.e = xpos * p->unit.dvi2pts;
- tm.f = ypos * p->unit.dvi2pts;
-
- p->format_buffer[len++] = ' ';
- len += pdf_dev_sprint_matrix(p, p->format_buffer+len, &tm);
- p->format_buffer[len++] = ' ';
- p->format_buffer[len++] = 'T';
- p->format_buffer[len++] = 'm';
-
- dev_out(p, p->format_buffer, len); /* op: Tm */
-
- p->text_state.ref_x = xpos;
- p->text_state.ref_y = ypos;
- p->text_state.matrix.slant = slant;
- p->text_state.matrix.extend = extend;
- p->text_state.matrix.rotate = rotate;
-}
-
-/*
- * reset_text_state() outputs a BT and does any necessary coordinate
- * transformations to get ready to ship out text.
- */
-
-static void
-reset_text_state (pdf_dev *p)
-{
- ASSERT(p);
-
- /*
- * We need to reset the line matrix to handle slanted fonts.
- */
- dev_out(p, " BT", 3); /* op: BT */
- /*
- * text_state.matrix is identity at top of page.
- * This sometimes write unnecessary "Tm"s when transition from
- * GRAPHICS_MODE to TEXT_MODE occurs.
- */
- if (p->text_state.force_reset ||
- p->text_state.matrix.slant != 0.0 ||
- p->text_state.matrix.extend != 1.0 ||
- ROTATE_TEXT(p->text_state.matrix.rotate)) {
- dev_set_text_matrix(p, 0, 0,
- p->text_state.matrix.slant,
- p->text_state.matrix.extend,
- p->text_state.matrix.rotate);
- }
- p->text_state.ref_x = 0;
- p->text_state.ref_y = 0;
- p->text_state.offset = 0;
- p->text_state.force_reset = 0;
-}
-
-static void
-pdf_dev_text_mode (pdf_dev *p)
-{
- ASSERT(p);
-
- switch (p->motion_state) {
- case TEXT_MODE:
- break;
- case STRING_MODE:
- dev_out(p, p->text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */
- break;
- case GRAPHICS_MODE:
- reset_text_state(p);
- break;
- }
- p->motion_state = TEXT_MODE;
- p->text_state.offset = 0;
-}
-
-static void
-pdf_dev_graphics_mode (pdf_dev *p)
-{
- switch (p->motion_state) {
- case GRAPHICS_MODE:
- break;
- case STRING_MODE:
- dev_out(p, p->text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */
- /* continue */
- case TEXT_MODE:
- if (p->text_state.bold_param != 0.0) {
- /* fake-bold "2 Tr" is still active */
- dev_out(p, " 0 Tr", 5); /* op: Tr */
- p->text_state.bold_param = 0.0;
- }
- dev_out(p, " ET", 3); /* op: ET */
- p->text_state.force_reset = 0;
- p->text_state.font_id = -1;
- break;
- }
- p->motion_state = GRAPHICS_MODE;
-}
-
-static void
-start_string (pdf_dev *p,
- spt_t xpos, spt_t ypos, double slant, double extend, int rotate)
-{
- spt_t delx, dely, error_delx, error_dely;
- spt_t desired_delx, desired_dely;
- int len = 0;
-
- ASSERT(p);
-
- delx = xpos - p->text_state.ref_x;
- dely = ypos - p->text_state.ref_y;
- /*
- * Precompensating for line transformation matrix.
- *
- * Line transformation matrix L for horizontal font in horizontal
- * mode and it's inverse I is
- *
- * | e 0| | 1/e 0|
- * L_hh = | | , I_hh = | |
- * | s 1| |-s/e 1|
- *
- * For vertical font in vertical mode,
- *
- * | 1 -s| | 1 s/e|
- * L_vv = | | , I_vv = | |
- * | 0 e| | 0 1/e|
- *
- * For vertical font in horizontal mode,
- *
- * | s 1| | 0 1|
- * L_vh = | | = L_vv x | |
- * |-e 0| |-1 0|
- *
- * | 0 -1|
- * I_vh = | | x I_vv
- * | 1 0|
- *
- * For horizontal font in vertical mode,
- *
- * | 0 -e| | 0 -1|
- * L_hv = | | = L_hh x | |
- * | 1 -s| | 1 0|
- *
- * | 0 1|
- * I_hv = | | x I_hh
- * |-1 0|
- *
- */
- switch (rotate) {
- case TEXT_WMODE_VH:
- /* Vertical font in horizontal mode: rot = +90
- * | 0 -1/e|
- * d_user = d x I_vh = d x | |
- * | 1 s/e|
- */
- desired_delx = dely;
- desired_dely = (spt_t) (-(delx - dely*slant)/extend);
-
- /* error_del is in device space
- *
- * | 0 1|
- * e = e_user x | | = (-e_user_y, e_user_x)
- * |-1 0|
- *
- * We must care about rotation here but not extend/slant...
- * The extend and slant actually is font matrix.
- */
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_dely);
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_delx);
- error_delx = -error_delx;
- break;
- case TEXT_WMODE_HV:
- /* Horizontal font in vertical mode: rot = -90
- *
- * |-s/e 1|
- * d_user = d x I_hv = d x | |
- * |-1/e 0|
- */
- desired_delx = (spt_t)(-(dely + delx*slant)/extend);
- desired_dely = delx;
-
- /*
- * e = (e_user_y, -e_user_x)
- */
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_dely);
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_delx);
- error_dely = -error_dely;
- break;
- case TEXT_WMODE_HH:
- /* Horizontal font in horizontal mode:
- * | 1/e 0|
- * d_user = d x I_hh = d x | |
- * |-s/e 1|
- */
- desired_delx = (spt_t)((delx - dely*slant)/extend);
- desired_dely = dely;
-
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_delx);
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_dely);
- break;
- case TEXT_WMODE_VV:
- /* Vertical font in vertical mode:
- * | 1 s/e|
- * d_user = d x I_vv = d x | |
- * | 0 1/e|
- */
- desired_delx = delx;
- desired_dely = (spt_t)((dely + delx*slant)/extend);
-
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_delx);
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_dely);
- break;
- case TEXT_WMODE_HD:
- /* Horizontal font in down-to-up mode: rot = +90
- *
- * | s/e -1|
- * d_user = d x -I_hv = d x | |
- * | 1/e 0|
- */
- desired_delx = -(spt_t)(-(dely + delx*slant)/extend);
- desired_dely = -delx;
-
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_dely);
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_delx);
- error_delx = -error_delx;
- error_dely = -error_dely;
- break;
- case TEXT_WMODE_VD:
- /* Vertical font in down-to-up mode: rot = 180
- * |-1 -s/e|
- * d_user = d x -I_vv = d x | |
- * | 0 -1/e|
- */
- desired_delx = -delx;
- desired_dely = -(spt_t)((dely + delx*slant)/extend);
-
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_delx, &error_delx);
- p->format_buffer[len++] = ' ';
- len += dev_sprint_bp(p, p->format_buffer+len, desired_dely, &error_dely);
- error_delx = -error_delx;
- error_dely = -error_dely;
- break;
- }
- dev_out(p, p->format_buffer, len); /* op: */
- /*
- * dvipdfm wrongly using "TD" in place of "Td".
- * The TD operator set leading, but we are not using T* etc.
- */
- dev_out(p, p->text_state.is_mb ? " Td[<" : " Td[(", 5); /* op: Td */
-
- /* Error correction */
- p->text_state.ref_x = xpos - error_delx;
- p->text_state.ref_y = ypos - error_dely;
-
- p->text_state.offset = 0;
-}
-
-static void
-pdf_dev_string_mode (pdf_dev *p, spt_t xpos, spt_t ypos, double slant, double extend, int rotate)
-{
- ASSERT(p);
-
- switch (p->motion_state) {
- case STRING_MODE:
- break;
- case GRAPHICS_MODE:
- reset_text_state(p);
- /* continue */
- case TEXT_MODE:
- if (p->text_state.force_reset) {
- dev_set_text_matrix(p, xpos, ypos, slant, extend, rotate);
- dev_out(p, p->text_state.is_mb ? "[<" : "[(", 2); /* op: */
- p->text_state.force_reset = 0;
- } else {
- start_string(p, xpos, ypos, slant, extend, rotate);
- }
- break;
- }
- p->motion_state = STRING_MODE;
-}
-
-/*
- * The purpose of the following routine is to force a Tf only
- * when it's actually necessary. This became a problem when the
- * VF code was added. The VF spec says to instantiate the
- * first font contained in the VF file before drawing a virtual
- * character. However, that font may not be used for
- * many characters (e.g. small caps fonts). For this reason,
- * dev_select_font() should not force a "physical" font selection.
- * This routine prevents a PDF Tf font selection until there's
- * really a character in that font.
- */
-
-static int
-pdf_dev_set_font (pdf_dev *p, int font_id)
-{
- struct dev_font *font;
- int text_rotate;
- double font_scale;
- int len;
- int vert_dir, vert_font;
-
- ASSERT(p);
-
- /* text_mode() must come before text_state.is_mb is changed. */
- pdf_dev_text_mode(p);
-
- font = GET_FONT(p, font_id);
- ASSERT(font); /* Caller should check font_id. */
-
- p->text_state.is_mb = (font->format == PDF_FONTTYPE_COMPOSITE) ? 1 : 0;
-
- vert_font = font->wmode ? 1 : 0;
- if (p->param.autorotate) {
- vert_dir = p->text_state.dir_mode;
- } else {
- vert_dir = vert_font;
- }
- text_rotate = (vert_font << 2)|vert_dir;
-
- if (font->slant != p->text_state.matrix.slant ||
- font->extend != p->text_state.matrix.extend ||
- ANGLE_CHANGES(text_rotate, p->text_state.matrix.rotate)) {
- p->text_state.force_reset = 1;
- }
- p->text_state.matrix.slant = font->slant;
- p->text_state.matrix.extend = font->extend;
- p->text_state.matrix.rotate = text_rotate;
-
- if (!font->resource) {
- font->resource = pdf_get_font_reference(font->font_id);
- font->used_chars = pdf_get_font_usedchars(font->font_id);
- }
-
- if (!font->used_on_this_page) {
- pdf_doc_add_page_resource("Font",
- font->short_name,
- pdf_link_obj(font->resource));
- font->used_on_this_page = 1;
- }
-
- font_scale = (double) font->sptsize * p->unit.dvi2pts;
- len = sprintf(p->format_buffer, " /%s", font->short_name); /* space not necessary. */
- p->format_buffer[len++] = ' ';
- len += p_dtoa(font_scale, MIN(p->unit.precision+1, DEV_PRECISION_MAX),
- p->format_buffer+len);
- p->format_buffer[len++] = ' ';
- p->format_buffer[len++] = 'T';
- p->format_buffer[len++] = 'f';
- dev_out(p, p->format_buffer, len); /* op: Tf */
-
- if (font->bold > 0.0 || font->bold != p->text_state.bold_param) {
- if (font->bold <= 0.0)
- len = sprintf(p->format_buffer, " 0 Tr");
- else
- len = sprintf(p->format_buffer, " 2 Tr %.6f w", font->bold); /* _FIXME_ */
- dev_out(p, p->format_buffer, len); /* op: Tr w */
- }
- p->text_state.bold_param = font->bold;
-
- p->text_state.font_id = font_id;
-
- return 0;
-}
-
-/* These tmp buffers can't be removed since the pointer to this can be
- * used as the return value of handle_multibyte_string(): str_ptr can point these.
- */
-static unsigned char sbuf0[FORMAT_BUF_SIZE];
-
-static int
-handle_multibyte_string (struct dev_font *font, const unsigned char **str_ptr, int *str_len)
-{
- const unsigned char *p;
- int length;
-
- p = *str_ptr;
- length = *str_len;
-
- /*
- * Font is double-byte font. Output is assumed to be 16-bit fixed length
- * encoding.
- * TODO: A character decomposed to multiple characters.
- */
- if (font->enc_id >= 0) {
- const unsigned char *inbuf;
- unsigned char *outbuf;
- int inbytesleft, outbytesleft;
- CMap *cmap;
-
- cmap = CMap_cache_get(font->enc_id);
- inbuf = p;
- outbuf = sbuf0;
- inbytesleft = length;
- outbytesleft = FORMAT_BUF_SIZE;
-
- CMap_decode(cmap, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
- if (inbytesleft != 0) {
- WARN("CMap conversion failed. (%d bytes remains)", inbytesleft);
- return -1;
- }
- length = FORMAT_BUF_SIZE - outbytesleft;
- p = sbuf0;
- }
-
- *str_ptr = p;
- *str_len = length;
- return 0;
-}
-
-void
-pdf_dev_set_string (spt_t xpos, spt_t ypos,
- const void *instr_ptr, int instr_len, spt_t width, int font_id)
-{
- pdf_dev *p = current_device();
- struct dev_font *font;
- const unsigned char *str_ptr; /* Pointer to the reencoded string. */
- int length, i, len = 0;
- spt_t kern, delh, delv;
- spt_t text_xorigin;
- spt_t text_yorigin;
-
- if (font_id < 0 || font_id >= p->num_dev_fonts) {
- ERROR("Invalid font: %d (%d)", font_id, p->num_dev_fonts);
- return;
- }
- if (font_id != p->text_state.font_id) {
- pdf_dev_set_font(p, font_id);
- }
-
- font = CURRENTFONT(p);
- if (!font) {
- ERROR("Currentfont not set.");
- return;
- }
-
- text_xorigin = p->text_state.ref_x;
- text_yorigin = p->text_state.ref_y;
-
- str_ptr = instr_ptr;
- length = instr_len;
-
- if (font->format == PDF_FONTTYPE_COMPOSITE) {
- if (handle_multibyte_string(font, &str_ptr, &length) < 0) {
- ERROR("Error in converting input string...");
- return;
- }
- if (font->used_chars != NULL) {
- for (i = 0; i < length; i += 2) {
- unsigned short cid = (str_ptr[i] << 8) | str_ptr[i + 1];
- add_to_used_chars2(font->used_chars, cid);
- }
- }
- } else {
- if (font->used_chars != NULL) {
- for (i = 0; i < length; i++)
- font->used_chars[str_ptr[i]] = 1;
- }
- }
-
- /*
- * Kern is in units of character units, i.e., 1000 = 1 em.
- *
- * Positive kern means kerning (reduce excess white space).
- *
- * The following formula is of the form a*x/b where a, x, and b are signed long
- * integers. Since in integer arithmetic (a*x) could overflow and a*(x/b) would
- * not be accurate, we use floating point arithmetic rather than trying to do
- * this all with integer arithmetic.
- *
- * 1000.0 / (font->extend * font->sptsize) is caluculated each times...
- * Is accuracy really a matter? Character widths are always rounded to integer
- * (in 1000 units per em) but dvipdfmx does not take into account of this...
- */
-
- if (p->text_state.dir_mode==0) {
- /* Left-to-right */
- delh = text_xorigin + p->text_state.offset - xpos;
- delv = ypos - text_yorigin;
- } else if (p->text_state.dir_mode==1) {
- /* Top-to-bottom */
- delh = ypos - text_yorigin + p->text_state.offset;
- delv = xpos - text_xorigin;
- } else {
- /* Bottom-to-top */
- delh = ypos + text_yorigin + p->text_state.offset;
- delv = xpos + text_xorigin;
- }
-
- /* White-space more than 3em is not considered as a part of single text.
- * So we will break string mode in that case.
- * Dvipdfmx spend most of time processing strings with kern = 0 (but far
- * more times in font handling).
- * You may want to use pre-calculated value for WORD_SPACE_MAX.
- * More text compression may be possible by replacing kern with space char
- * when -kern is equal to space char width.
- */
-#define WORD_SPACE_MAX(f) (spt_t) (3.0 * (f)->extend * (f)->sptsize)
-
- if (p->text_state.force_reset ||
- labs(delv) > p->unit.min_bp_val ||
- labs(delh) > WORD_SPACE_MAX(font)) {
- pdf_dev_text_mode(p);
- kern = 0;
- } else {
- kern = (spt_t) (1000.0 / font->extend * delh / font->sptsize);
- }
-
- /* Inaccucary introduced by rounding of character width appears within
- * single text block. There are point_size/1000 rounding error per character.
- * If you really care about accuracy, you should compensate this here too.
- */
- if (p->motion_state != STRING_MODE)
- pdf_dev_string_mode(p, xpos, ypos,
- font->slant, font->extend, p->text_state.matrix.rotate);
- else if (kern != 0) {
- /*
- * Same issues as earlier. Use floating point for simplicity.
- * This routine needs to be fast, so we don't call sprintf() or strcpy().
- */
- p->text_state.offset -=
- (spt_t) (kern * font->extend * (font->sptsize / 1000.0));
- p->format_buffer[len++] = p->text_state.is_mb ? '>' : ')';
- if (font->wmode)
- len += p_itoa(-kern, p->format_buffer + len);
- else {
- len += p_itoa( kern, p->format_buffer + len);
- }
- p->format_buffer[len++] = p->text_state.is_mb ? '<' : '(';
- dev_out(p, p->format_buffer, len); /* op: */
- len = 0;
- }
-
- if (p->text_state.is_mb) {
- if (FORMAT_BUF_SIZE - len < 2 * length)
- ERROR("Buffer overflow...");
- for (i = 0; i < length; i++) {
- int first, second;
-
- first = (str_ptr[i] >> 4) & 0x0f;
- second = str_ptr[i] & 0x0f;
- p->format_buffer[len++] = ((first >= 10) ? first + 'W' : first + '0');
- p->format_buffer[len++] = ((second >= 10) ? second + 'W' : second + '0');
- }
- } else {
- len += pdfobj_escape_str(p->format_buffer + len,
- FORMAT_BUF_SIZE - len, str_ptr, length);
- }
- /* I think if you really care about speed, you should avoid memcopy here. */
- dev_out(p, p->format_buffer, len); /* op: */
-
- p->text_state.offset += width;
-}
-
-void
-pdf_init_device (double dvi2pts, int precision, int black_and_white)
-{
- pdf_dev *p = current_device();
-
- p->motion_state = GRAPHICS_MODE;
- p->unit.dvi2pts = 0.0;
- p->unit.min_bp_val = 658;
- p->unit.precision = 2;
- p->param.autorotate = 1;
- p->param.colormode = 1;
- p->text_state.font_id = -1;
- p->text_state.offset = 0;
- p->text_state.matrix.slant = 0;
- p->text_state.matrix.extend = 0;
- p->text_state.matrix.rotate = 0;
- p->text_state.bold_param = 0;
- p->text_state.dir_mode = 0;
- p->text_state.force_reset = 0;
- p->text_state.is_mb = 0;
-
- if (precision < 0 ||
- precision > DEV_PRECISION_MAX)
- WARN("Number of decimal digits out of range [0-%d].",
- DEV_PRECISION_MAX);
-
- if (precision < 0) {
- p->unit.precision = 0;
- } else if (precision > DEV_PRECISION_MAX) {
- p->unit.precision = DEV_PRECISION_MAX;
- } else {
- p->unit.precision = precision;
- }
- p->unit.dvi2pts = dvi2pts;
- p->unit.min_bp_val = (int) ROUND(1.0/(ten_pow[p->unit.precision]*dvi2pts), 1);
- if (p->unit.min_bp_val < 0)
- p->unit.min_bp_val = -p->unit.min_bp_val;
-
- p->param.colormode = (black_and_white ? 0 : 1);
-
- pdf_dev_graphics_mode(p);
- pdf_color_clear_stack();
- pdf_dev_init_gstates();
-
- p->num_dev_fonts = p->max_dev_fonts = 0;
- p->fonts = NULL;
-
- return;
-}
-
-void
-pdf_close_device (void)
-{
- pdf_dev *p = current_device();
-
- if (p->fonts) {
- int i;
-
- for (i = 0; i < p->num_dev_fonts; i++) {
- if (p->fonts[i].tex_name)
- RELEASE(p->fonts[i].tex_name);
- if (p->fonts[i].resource)
- pdf_release_obj(p->fonts[i].resource);
- p->fonts[i].tex_name = NULL;
- p->fonts[i].resource = NULL;
- }
- RELEASE(p->fonts);
- p->fonts = NULL;
- }
- pdf_dev_clear_gstates();
-}
-
-/*
- * BOP, EOP, and FONT section.
- * BOP and EOP manipulate some of the same data structures
- * as the font stuff.
- */
-void
-pdf_dev_reset_fonts (int newpage)
-{
- pdf_dev *p = current_device();
- int i;
-
- for (i = 0; i < p->num_dev_fonts; i++) {
- p->fonts[i].used_on_this_page = 0;
- }
-
- p->text_state.font_id = -1;
-
- p->text_state.matrix.slant = 0.0;
- p->text_state.matrix.extend = 1.0;
- p->text_state.matrix.rotate = TEXT_WMODE_HH;
-
- if (newpage)
- p->text_state.bold_param = 0.0;
-
- p->text_state.is_mb = 0;
-}
-
-void
-pdf_dev_reset_color (int force)
-{
- pdf_color *sc, *fc;
-
- pdf_color_get_current(&sc, &fc);
- pdf_dev_set_color(sc, 0, force);
- pdf_dev_set_color(fc, 0x20, force);
-}
-
-void
-pdf_dev_bop (const pdf_tmatrix *M)
-{
- pdf_dev *p = current_device();
-
- pdf_dev_graphics_mode(p);
-
- p->text_state.force_reset = 0;
-
- pdf_dev_gsave();
- pdf_dev_concat(M);
-
- pdf_dev_reset_fonts(1);
- pdf_dev_reset_color(0);
- pdf_dev_reset_xgstate(0);
-}
-
-void
-pdf_dev_eop (void)
-{
- pdf_dev *p = current_device();
- int depth;
-
- pdf_dev_graphics_mode(p);
-
- depth = pdf_dev_current_depth();
- if (depth != 1) {
- WARN("Unbalenced q/Q nesting...: %d", depth);
- pdf_dev_grestore_to(0);
- } else {
- pdf_dev_grestore();
- }
-}
-
-static void
-print_fontmap (const char *font_name, fontmap_rec *mrec)
-{
- if (!mrec)
- return;
-
- MESG("\n");
-
- MESG("fontmap: %s -> %s", font_name, mrec->font_name);
- if (mrec->enc_name)
- MESG("(%s)", mrec->enc_name);
- if (mrec->opt.extend != 1.0)
- MESG("[extend:%g]", mrec->opt.extend);
- if (mrec->opt.slant != 0.0)
- MESG("[slant:%g]", mrec->opt.slant);
- if (mrec->opt.bold != 0.0)
- MESG("[bold:%g]", mrec->opt.bold);
- if (mrec->opt.flags & FONTMAP_OPT_NOEMBED)
- MESG("[noemb]");
- if (mrec->opt.mapc >= 0)
- MESG("[map:<%02x>]", mrec->opt.mapc);
- if (mrec->opt.charcoll)
- MESG("[csi:%s]", mrec->opt.charcoll);
- if (mrec->opt.index)
- MESG("[index:%d]", mrec->opt.index);
-
- switch (mrec->opt.style) {
- case FONTMAP_STYLE_BOLD:
- MESG("[style:bold]");
- break;
- case FONTMAP_STYLE_ITALIC:
- MESG("[style:italic]");
- break;
- case FONTMAP_STYLE_BOLDITALIC:
- MESG("[style:bolditalic]");
- break;
- }
- MESG("\n");
-
-}
-
-/* _FIXME_
- * Font is identified with font_name and point_size as in DVI here.
- * However, except for PDF_FONTTYPE_BITMAP, we can share the
- * short_name, resource and used_chars between multiple instances
- * of the same font at different sizes.
- */
-int
-pdf_dev_locate_font (const char *font_name, spt_t ptsize)
-{
- pdf_dev *p = current_device();
- int i;
- fontmap_rec *mrec;
- struct dev_font *font;
-
- if (!font_name)
- return -1;
-
- if (ptsize == 0) {
- ERROR("pdf_dev_locate_font() called with the zero ptsize.");
- return -1;
- }
-
- for (i = 0; i < p->num_dev_fonts; i++) {
- if (!strcmp(font_name, p->fonts[i].tex_name) &&
- ptsize == p->fonts[i].sptsize) {
- return i; /* found a dev_font that matches the request */
- }
- }
-
- /*
- * Make sure we have room for a new one, even though we may not
- * actually create one.
- */
- if (p->num_dev_fonts >= p->max_dev_fonts) {
- p->max_dev_fonts += 16;
- p->fonts = RENEW(p->fonts, p->max_dev_fonts, struct dev_font);
- }
-
- font = &p->fonts[p->num_dev_fonts];
-
- /* New font */
- mrec = pdf_lookup_fontmap_record(font_name);
-
- if (dpx_conf.verbose_level > 1)
- print_fontmap(font_name, mrec);
-
- font->font_id = pdf_font_findresource(font_name, ptsize * p->unit.dvi2pts);
- if (font->font_id < 0) {
- font->font_id = pdf_font_load_font(font_name, ptsize * p->unit.dvi2pts, mrec);
- if (font->font_id < 0)
- return -1;
- }
-
- pdf_font_resource_name(font->font_id, font->short_name);
-
- font->used_on_this_page = 0;
-
- font->tex_name = NEW(strlen(font_name) + 1, char);
- strcpy(font->tex_name, font_name);
- font->sptsize = ptsize;
-
- switch (pdf_get_font_subtype(font->font_id)) {
- case PDF_FONT_FONTTYPE_TYPE3:
- font->format = PDF_FONTTYPE_BITMAP;
- break;
- case PDF_FONT_FONTTYPE_TYPE0:
- font->format = PDF_FONTTYPE_COMPOSITE;
- break;
- default:
- font->format = PDF_FONTTYPE_SIMPLE;
- break;
- }
-
- font->wmode = pdf_get_font_wmode (font->font_id);
- font->enc_id = pdf_get_font_encoding(font->font_id);
-
- font->resource = NULL; /* Don't ref obj until font is actually used. */
- font->used_chars = NULL;
-
- font->extend = 1.0;
- font->slant = 0.0;
- font->bold = 0.0;
- if (mrec) {
- font->extend = mrec->opt.extend;
- font->slant = mrec->opt.slant;
- font->bold = mrec->opt.bold;
- }
-
- return p->num_dev_fonts++;
-}
-
-
-/* This does not remember current stroking width. */
-static int
-dev_sprint_line (pdf_dev *p, char *buf, spt_t width,
- spt_t p0_x, spt_t p0_y, spt_t p1_x, spt_t p1_y)
-{
- int len = 0;
- double w;
-
- w = width * p->unit.dvi2pts;
-
- len += p_dtoa(w, MIN(p->unit.precision+1, DEV_PRECISION_MAX), buf+len);
- buf[len++] = ' ';
- buf[len++] = 'w';
- buf[len++] = ' ';
- len += dev_sprint_bp(p, buf+len, p0_x, NULL);
- buf[len++] = ' ';
- len += dev_sprint_bp(p, buf+len, p0_y, NULL);
- buf[len++] = ' ';
- buf[len++] = 'm';
- buf[len++] = ' ';
- len += dev_sprint_bp(p, buf+len, p1_x, NULL);
- buf[len++] = ' ';
- len += dev_sprint_bp(p, buf+len, p1_y, NULL);
- buf[len++] = ' ';
- buf[len++] = 'l';
- buf[len++] = ' ';
- buf[len++] = 'S';
-
- return len;
-}
-
-/* Not optimized. */
-#define PDF_LINE_THICKNESS_MAX 5.0
-void
-pdf_dev_set_rule (spt_t xpos, spt_t ypos, spt_t width, spt_t height)
-{
- pdf_dev *p = current_device();
- int len = 0;
- double width_in_bp;
-
- pdf_dev_graphics_mode(p);
-
- p->format_buffer[len++] = ' ';
- p->format_buffer[len++] = 'q';
- p->format_buffer[len++] = ' ';
- /* Don't use too thick line. */
- width_in_bp = ((width < height) ? width : height) * p->unit.dvi2pts;
- if (width_in_bp < 0.0 || /* Shouldn't happen */
- width_in_bp > PDF_LINE_THICKNESS_MAX) {
- pdf_rect rect;
-
- rect.llx = p->unit.dvi2pts * xpos;
- rect.lly = p->unit.dvi2pts * ypos;
- rect.urx = p->unit.dvi2pts * width;
- rect.ury = p->unit.dvi2pts * height;
- len += pdf_dev_sprint_rect(p, p->format_buffer+len, &rect);
- p->format_buffer[len++] = ' ';
- p->format_buffer[len++] = 'r';
- p->format_buffer[len++] = 'e';
- p->format_buffer[len++] = ' ';
- p->format_buffer[len++] = 'f';
- } else {
- if (width > height) {
- /* NOTE:
- * A line width of 0 denotes the thinnest line that can be rendered at
- * device resolution. See, PDF Reference Manual 4th ed., sec. 4.3.2,
- * "Details of Graphics State Parameters", p. 185.
- */
- if (height < p->unit.min_bp_val) {
- WARN("Too thin line: height=%ld (%g bp)", height, width_in_bp);
- WARN("Please consider using \"-d\" option.");
- }
- len += dev_sprint_line(p, p->format_buffer+len,
- height,
- xpos,
- ypos + height/2,
- xpos + width,
- ypos + height/2);
- } else {
- if (width < p->unit.min_bp_val) {
- WARN("Too thin line: width=%ld (%g bp)", width, width_in_bp);
- WARN("Please consider using \"-d\" option.");
- }
- len += dev_sprint_line(p, p->format_buffer+len,
- width,
- xpos + width/2,
- ypos,
- xpos + width/2,
- ypos + height);
- }
- }
- p->format_buffer[len++] = ' ';
- p->format_buffer[len++] = 'Q';
- dev_out(p, p->format_buffer, len); /* op: q re f Q */
-}
-
-/* Rectangle in device space coordinate. */
-void
-pdf_dev_set_rect (pdf_rect *rect,
- spt_t x_user, spt_t y_user,
- spt_t width, spt_t height, spt_t depth)
-{
- pdf_dev *p = current_device();
- double dev_x, dev_y;
- pdf_coord p0, p1, p2, p3;
- double min_x, min_y, max_x, max_y;
-
- dev_x = x_user * p->unit.dvi2pts;
- dev_y = y_user * p->unit.dvi2pts;
- if (p->text_state.dir_mode) {
- p0.x = dev_x - p->unit.dvi2pts * depth;
- p0.y = dev_y - p->unit.dvi2pts * width;
- p1.x = dev_x + p->unit.dvi2pts * height;
- p1.y = p0.y;
- p2.x = p1.x;
- p2.y = dev_y;
- p3.x = p0.x;
- p3.y = p2.y;
- } else {
- p0.x = dev_x;
- p0.y = dev_y - p->unit.dvi2pts * depth;
- p1.x = dev_x + p->unit.dvi2pts * width;
- p1.y = p0.y;
- p2.x = p1.x;
- p2.y = dev_y + p->unit.dvi2pts * height;
- p3.x = p0.x;
- p3.y = p2.y;
- }
-
- pdf_dev_transform(&p0, NULL); /* currentmatrix */
- pdf_dev_transform(&p1, NULL);
- pdf_dev_transform(&p2, NULL);
- pdf_dev_transform(&p3, NULL);
-
- min_x = MIN(p0.x , p1.x);
- min_x = MIN(min_x, p2.x);
- min_x = MIN(min_x, p3.x);
-
- max_x = MAX(p0.x , p1.x);
- max_x = MAX(max_x, p2.x);
- max_x = MAX(max_x, p3.x);
-
- min_y = MIN(p0.y , p1.y);
- min_y = MIN(min_y, p2.y);
- min_y = MIN(min_y, p3.y);
-
- max_y = MAX(p0.y , p1.y);
- max_y = MAX(max_y, p2.y);
- max_y = MAX(max_y, p3.y);
-
- rect->llx = min_x;
- rect->lly = min_y;
- rect->urx = max_x;
- rect->ury = max_y;
-
- return;
-}
-
-int
-pdf_dev_get_dirmode (void)
-{
- pdf_dev *p = current_device();
- return p->text_state.dir_mode;
-}
-
-void
-pdf_dev_set_dirmode (int text_dir)
-{
- pdf_dev *p = current_device();
- struct dev_font *font;
- int text_rotate;
- int vert_dir, vert_font;
-
- font = CURRENTFONT(p);
-
- vert_font = (font && font->wmode) ? 1 : 0;
- if (p->param.autorotate) {
- vert_dir = text_dir;
- } else {
- vert_dir = vert_font;
- }
- text_rotate = (vert_font << 2)|vert_dir;
-
- if (font &&
- ANGLE_CHANGES(text_rotate, p->text_state.matrix.rotate)) {
- p->text_state.force_reset = 1;
- }
-
- p->text_state.matrix.rotate = text_rotate;
- p->text_state.dir_mode = text_dir;
-}
-
-static void
-dev_set_param_autorotate (pdf_dev *p, int auto_rotate)
-{
- struct dev_font *font;
- int text_rotate, vert_font, vert_dir;
-
- ASSERT(p);
-
- font = CURRENTFONT(p);
-
- vert_font = (font && font->wmode) ? 1 : 0;
- if (auto_rotate) {
- vert_dir = p->text_state.dir_mode;
- } else {
- vert_dir = vert_font;
- }
- text_rotate = (vert_font << 2)|vert_dir;
-
- if (ANGLE_CHANGES(text_rotate, p->text_state.matrix.rotate)) {
- p->text_state.force_reset = 1;
- }
- p->text_state.matrix.rotate = text_rotate;
- p->param.autorotate = auto_rotate;
-}
-
-int
-pdf_dev_get_param (int param_type)
-{
- pdf_dev *p = current_device();
- int value = 0;
-
- switch (param_type) {
- case PDF_DEV_PARAM_AUTOROTATE:
- value = p->param.autorotate;
- break;
- case PDF_DEV_PARAM_COLORMODE:
- value = p->param.colormode;
- break;
- default:
- ERROR("Unknown device parameter: %d", param_type);
- }
-
- return value;
-}
-
-void
-pdf_dev_set_param (int param_type, int value)
-{
- pdf_dev *p = current_device();
-
- switch (param_type) {
- case PDF_DEV_PARAM_AUTOROTATE:
- dev_set_param_autorotate(p, value);
- break;
- case PDF_DEV_PARAM_COLORMODE:
- p->param.colormode = value; /* 0 for B&W */
- break;
- default:
- ERROR("Unknown device parameter: %d", param_type);
- }
-
- return;
-}
-
-
-/* rect returned */
-int
-pdf_dev_put_image (int id, transform_info *ti, double ref_x, double ref_y, pdf_rect *rect)
-{
- pdf_dev *p = current_device();
- char *res_name;
- pdf_tmatrix M, M1;
- pdf_rect r;
- int len = 0;
-
- pdf_copymatrix(&M, &(ti->matrix));
- M.e += ref_x; M.f += ref_y;
- /* Just rotate by -90, but not tested yet. Any problem if M has scaling? */
- if (p->param.autorotate &&
- p->text_state.dir_mode) {
- double tmp;
- tmp = -M.a; M.a = M.b; M.b = tmp;
- tmp = -M.c; M.c = M.d; M.d = tmp;
- }
-
- pdf_dev_graphics_mode(p);
- pdf_dev_gsave();
-
- pdf_ximage_scale_image(id, &M1, &r, ti);
- pdf_concatmatrix(&M, &M1);
- pdf_dev_concat(&M);
-
- /* Clip */
- if (ti->flags & INFO_DO_CLIP) {
- pdf_dev_rectclip(r.llx, r.lly, r.urx - r.llx, r.ury - r.lly);
- }
-
- res_name = pdf_ximage_get_resname(id);
- {
- char *buf;
-
- buf = NEW(strlen(res_name)+6, char);
- len = sprintf(buf, " /%s Do", res_name);
- dev_out(p, buf, len); /* op: Do */
- RELEASE(buf);
- }
- if (rect) {
- pdf_rect r1;
-
- /* Sorry for ugly code. */
- pdf_dev_set_rect(&r1,
- bpt2spt(p, r.llx), bpt2spt(p, r.lly),
- bpt2spt(p, r.urx - r.llx), bpt2spt(p, r.ury - r.lly), 0);
- rect->llx = r1.llx; rect->lly = r1.lly;
- rect->urx = r1.urx; rect->ury = r1.ury;
- }
-
- pdf_dev_grestore();
-
- pdf_doc_add_page_resource("XObject",
- res_name,
- pdf_ximage_get_reference(id));
-
- return 0;
-}
-
-void
-transform_info_clear (transform_info *info)
-{
- /* Physical dimensions */
- info->width = 0.0;
- info->height = 0.0;
- info->depth = 0.0;
-
- info->bbox.llx = 0.0;
- info->bbox.lly = 0.0;
- info->bbox.urx = 0.0;
- info->bbox.ury = 0.0;
-
- /* Transformation matrix */
- pdf_setmatrix(&(info->matrix), 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
-
- info->flags = 0;
-}
-
-void
-pdf_dev_begin_actualtext (uint16_t *unicodes, int count)
-{
- pdf_dev *p = current_device();
- int len, i, pdf_doc_enc = 1;
-
- /* check whether we can use PDFDocEncoding for this string
- (we punt on the 0x80..0xA0 range that does not directly correspond to unicode) */
- for (i = 0; i < count; i++) {
- if (unicodes[i] > 0xff || (unicodes[i] > 0x7f && unicodes[i] < 0xa1)) {
- pdf_doc_enc = 0;
- break;
- }
- }
-
- pdf_dev_graphics_mode(p);
-
- dev_out(p, "\n/Span << /ActualText (", 23);
- if (!pdf_doc_enc)
- dev_out(p, "\xFE\xFF", 2);
-
- while (count-- > 0) {
- unsigned char s[2] = { *unicodes >> 8, *unicodes & 0xff };
- char buf[32];
- i = pdf_doc_enc; /* if using PDFDocEncoding, we only care about the low 8 bits,
- so start with the second byte of our pair */
- len = 0;
- for (; i < 2; i++) {
- unsigned char c = s[i];
- if (c == '(' || c == ')' || c == '\\') {
- len += sprintf(buf + len, "\\%c", c);
- } else if (c < ' ') {
- len += sprintf(buf + len, "\\%03o", c);
- } else {
- len += sprintf(buf + len, "%c", c);
- }
- }
- dev_out(p, buf, len);
- ++unicodes;
- }
-
- dev_out(p, ") >> BDC", 8);
-}
-
-void
-pdf_dev_end_actualtext (void)
-{
- pdf_dev *p = current_device();
-
- pdf_dev_graphics_mode(p);
-
- dev_out(p, " EMC", 4);
-}
-
-/* Compatibility functions.... For other files still using old interface */
-void
-graphics_mode (void)
-{
- pdf_dev *p = current_device();
-
- pdf_dev_graphics_mode(p);
-}
-
-double
-dev_unit_dviunit (void)
-{
- pdf_dev *p = current_device();
- return pdf_dev_unit_dviunit(p);
-}
-
-int
-pdf_sprint_matrix (char *buf, const pdf_tmatrix *M)
-{
- pdf_dev *p = current_device();
- return (int) pdf_dev_sprint_matrix(p, buf, M);
-}
-
-int
-pdf_sprint_rect (char *buf, const pdf_rect *rect)
-{
- pdf_dev *p = current_device();
- return (int) pdf_dev_sprint_rect(p, buf, rect);
-}
-
-int
-pdf_sprint_coord (char *buf, const pdf_coord *c)
-{
- pdf_dev *p = current_device();
- return (int) pdf_dev_sprint_coord(p, buf, c);
-}
-
-int
-pdf_sprint_length (char *buf, double value)
-{
- pdf_dev *p = current_device();
- return (int) pdf_dev_sprint_length(p, buf, value);
-}
-
-int
-pdf_sprint_number (char *buf, double value)
-{
- pdf_dev *p = current_device();
- return (int) pdf_dev_sprint_number(p, buf, value);
-}
-
-/* Access text state parameters. */
-int
-pdf_dev_get_font_wmode (int font_id)
-{
- pdf_dev *p = current_device();
- struct dev_font *font;
-
- font = GET_FONT(p, font_id);
- if (font) {
- return font->wmode;
- }
-
- return 0;
-}
-
-int
-pdf_dev_font_minbytes (int font_id)
-{
- pdf_dev *p = current_device();
- struct dev_font *font;
- int minbytes = 1;
-
- font = GET_FONT(p, font_id);
- if (font && font->format == PDF_FONTTYPE_COMPOSITE) {
- CMap *cmap;
-
- cmap = CMap_cache_get(font->enc_id);
- minbytes = CMap_get_profile(cmap, CMAP_PROF_TYPE_INBYTES_MIN);
- }
-
- return minbytes;
-}