diff options
Diffstat (limited to 'Build/source/texk/dvipdfm-x/pdfdev.c')
-rw-r--r-- | Build/source/texk/dvipdfm-x/pdfdev.c | 1849 |
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; -} |