diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2020-07-25 22:06:35 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2020-07-25 22:06:35 +0000 |
commit | c44cc0e342ab0ab537882d1f6b312a770c519f18 (patch) | |
tree | bfe3d00b70fbc5b3301a19178818804d17548577 /Build/source/texk/dvipdfm-x/pdfdev.c | |
parent | 66279a58ec36789c4d363e2d4598176d99f43c66 (diff) |
Place static variables into a single struct. Various minor improvements (S. Hirata).
git-svn-id: svn://tug.org/texlive/trunk@55945 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipdfm-x/pdfdev.c')
-rw-r--r-- | Build/source/texk/dvipdfm-x/pdfdev.c | 1414 |
1 files changed, 752 insertions, 662 deletions
diff --git a/Build/source/texk/dvipdfm-x/pdfdev.c b/Build/source/texk/dvipdfm-x/pdfdev.c index a8e19e5282e..27d7192f20f 100644 --- a/Build/source/texk/dvipdfm-x/pdfdev.c +++ b/Build/source/texk/dvipdfm-x/pdfdev.c @@ -53,33 +53,245 @@ #include "pdfdev.h" -/* Not working yet... */ -double -pdf_dev_scale (void) +struct dev_param { - return 1.0; -} + /* 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[7]; /* 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; + + /* if >= 0, index of a dev_font that really has the resource and used_chars */ + int real_font_index; + + 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 */ + + /* Compatibility */ + int mapc; /* Nasty workaround for Omega */ + + /* There are no font metric format supporting four-bytes + * charcter code. So we should provide an option to specify + * UCS group and plane. + */ + int ucs_group; + int ucs_plane; + + int is_unicode; +}; /* * Unit conversion, formatting and others. */ #define TEX_ONE_HUNDRED_BP 6578176 -static struct { - double dvi2pts; +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. */ -} dev_unit = { - 0.0, - 658, - 2 }; +#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; + int num_phys_fonts; + char format_buffer[FORMAT_BUF_SIZE+1]; + + /* Just to support pdf:bcontent special... + * Text position adjustment inside the pdf:bcontent and pdf:econtent. + */ + pdf_coord *dev_coords; + int num_dev_coords; + int max_dev_coords; +}; -double -dev_unit_dviunit (void) +/* + * 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 (1.0/dev_unit.dvi2pts); + 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 @@ -91,8 +303,8 @@ 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(b) ( (spt_t) round( (b) / dev_unit.dvi2pts ) ) -#define spt2bpt(s) ( (s) * dev_unit.dvi2pts ) +#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 @@ -194,28 +406,36 @@ p_dtoa (double value, int prec, char *buf) } static int -dev_sprint_bp (char *buf, spt_t value, spt_t *error) +dev_sprint_bp (pdf_dev *p, char *buf, spt_t value, spt_t *error) { double value_in_bp; double error_in_bp; - int prec = dev_unit.precision; + int prec; + + ASSERT(p); + + prec = p->unit.precision; - value_in_bp = spt2bpt(value); + value_in_bp = spt2bpt(p, value); if (error) { error_in_bp = value_in_bp - dround_at(value_in_bp, prec); - *error = bpt2spt(error_in_bp); + *error = bpt2spt(p, error_in_bp); } return p_dtoa(value_in_bp, prec, buf); } /* They are affected by precision (set at device initialization). */ -int -pdf_sprint_matrix (char *buf, const pdf_tmatrix *M) +static size_t +pdf_dev_sprint_matrix (pdf_dev *p, char *buf, const pdf_tmatrix *M) { - int len; - int prec2 = MIN(dev_unit.precision + 2, DEV_PRECISION_MAX); - int prec0 = MAX(dev_unit.precision, 2); + 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++] = ' '; @@ -233,52 +453,59 @@ pdf_sprint_matrix (char *buf, const pdf_tmatrix *M) return len; } -int -pdf_sprint_rect (char *buf, const pdf_rect *rect) +static size_t +pdf_dev_sprint_rect (pdf_dev *p, char *buf, const pdf_rect *rect) { - int len; + size_t len; + + ASSERT(p); - len = p_dtoa(rect->llx, dev_unit.precision, buf); + len = p_dtoa(rect->llx, p->unit.precision, buf); buf[len++] = ' '; - len += p_dtoa(rect->lly, dev_unit.precision, buf+len); + len += p_dtoa(rect->lly, p->unit.precision, buf+len); buf[len++] = ' '; - len += p_dtoa(rect->urx, dev_unit.precision, buf+len); + len += p_dtoa(rect->urx, p->unit.precision, buf+len); buf[len++] = ' '; - len += p_dtoa(rect->ury, dev_unit.precision, buf+len); + len += p_dtoa(rect->ury, p->unit.precision, buf+len); buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ return len; } -int -pdf_sprint_coord (char *buf, const pdf_coord *p) +static size_t +pdf_dev_sprint_coord (pdf_dev *p, char *buf, const pdf_coord *c) { - int len; + size_t len; + + ASSERT(p); - len = p_dtoa(p->x, dev_unit.precision, buf); + len = p_dtoa(c->x, p->unit.precision, buf); buf[len++] = ' '; - len += p_dtoa(p->y, dev_unit.precision, buf+len); + len += p_dtoa(c->y, p->unit.precision, buf+len); buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ return len; } -int -pdf_sprint_length (char *buf, double value) +static size_t +pdf_dev_sprint_length (pdf_dev *p, char *buf, double value) { - int len; + size_t len; + + ASSERT(p); - len = p_dtoa(value, dev_unit.precision, buf); + len = p_dtoa(value, p->unit.precision, buf); buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ return len; } - -int -pdf_sprint_number (char *buf, double value) +static size_t +pdf_dev_sprint_number (pdf_dev *p, char *buf, double value) { - int len; + size_t len; + + ASSERT(p); len = p_dtoa(value, DEV_PRECISION_MAX, buf); buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ @@ -286,228 +513,21 @@ pdf_sprint_number (char *buf, double value) return len; } - -static struct -{ - /* 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; - -} dev_param = { - 1, /* autorotate */ - 1, /* 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 - -static int motion_state = GRAPHICS_MODE; - -#define FORMAT_BUF_SIZE 4096 -static char format_buffer[FORMAT_BUF_SIZE]; - -/* - * 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) - -static struct { - - /* 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; -} text_state = { - -1, /* font */ - 0, /* offset */ - 0, 0, /* ref_x, ref_y */ - 0, 0, /* raise, leading */ - {0.0, 1.0, 0}, - - 0.0, /* Experimental boldness param */ - - 0, /* dir_mode */ - - /* internal */ - 0, /* force_reset */ - 0 /* 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[7]; /* 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; - - /* if >= 0, index of a dev_font that really has the resource and used_chars */ - int real_font_index; - - 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 */ - - /* Compatibility */ - int mapc; /* Nasty workaround for Omega */ - - /* There are no font metric format supporting four-bytes - * charcter code. So we should provide an option to specify - * UCS group and plane. - */ - int ucs_group; - int ucs_plane; - - int is_unicode; -}; -static struct dev_font *dev_fonts = NULL; - -static int num_dev_fonts = 0; -static int max_dev_fonts = 0; -static int num_phys_fonts = 0; - -#define CURRENTFONT() ((text_state.font_id < 0) ? NULL : &(dev_fonts[text_state.font_id])) -#define GET_FONT(n) (&(dev_fonts[(n)])) - +/* 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 (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) +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) { @@ -542,22 +562,22 @@ dev_set_text_matrix (spt_t xpos, spt_t ypos, double slant, double extend, int ro tm.c = 0.0; tm.d = -extend; break; } - tm.e = xpos * dev_unit.dvi2pts; - tm.f = ypos * dev_unit.dvi2pts; - - format_buffer[len++] = ' '; - len += pdf_sprint_matrix(format_buffer+len, &tm); - format_buffer[len++] = ' '; - format_buffer[len++] = 'T'; - format_buffer[len++] = 'm'; - - pdf_doc_add_page_content(format_buffer, len); /* op: Tm */ - - text_state.ref_x = xpos; - text_state.ref_y = ypos; - text_state.matrix.slant = slant; - text_state.matrix.extend = extend; - text_state.matrix.rotate = rotate; + 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; } /* @@ -566,81 +586,88 @@ dev_set_text_matrix (spt_t xpos, spt_t ypos, double slant, double extend, int ro */ static void -reset_text_state (void) +reset_text_state (pdf_dev *p) { + ASSERT(p); + /* * We need to reset the line matrix to handle slanted fonts. */ - pdf_doc_add_page_content(" BT", 3); /* op: BT */ + 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 (text_state.force_reset || - text_state.matrix.slant != 0.0 || - text_state.matrix.extend != 1.0 || - ROTATE_TEXT(text_state.matrix.rotate)) { - dev_set_text_matrix(0, 0, - text_state.matrix.slant, - text_state.matrix.extend, - text_state.matrix.rotate); + 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); } - text_state.ref_x = 0; - text_state.ref_y = 0; - text_state.offset = 0; - text_state.force_reset = 0; + 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 -text_mode (void) +pdf_dev_text_mode (pdf_dev *p) { - switch (motion_state) { + ASSERT(p); + + switch (p->motion_state) { case TEXT_MODE: break; case STRING_MODE: - pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ + dev_out(p, p->text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ break; case GRAPHICS_MODE: - reset_text_state(); + reset_text_state(p); break; } - motion_state = TEXT_MODE; - text_state.offset = 0; + p->motion_state = TEXT_MODE; + p->text_state.offset = 0; } -void -graphics_mode (void) +static void +pdf_dev_graphics_mode (pdf_dev *p) { - switch (motion_state) { + switch (p->motion_state) { case GRAPHICS_MODE: break; case STRING_MODE: - pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ + dev_out(p, p->text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ /* continue */ case TEXT_MODE: - if (text_state.bold_param != 0.0) { + if (p->text_state.bold_param != 0.0) { /* fake-bold "2 Tr" is still active */ - pdf_doc_add_page_content(" 0 Tr", 5); /* op: Tr */ - text_state.bold_param = 0.0; - } - pdf_doc_add_page_content(" ET", 3); /* op: ET */ - text_state.force_reset = 0; - text_state.font_id = -1; + 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; } - motion_state = GRAPHICS_MODE; + p->motion_state = GRAPHICS_MODE; } static void -start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) +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; - delx = xpos - text_state.ref_x; - dely = ypos - text_state.ref_y; + ASSERT(p); + + delx = xpos - p->text_state.ref_x; + dely = ypos - p->text_state.ref_y; /* * Precompensating for line transformation matrix. * @@ -697,10 +724,10 @@ start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) * We must care about rotation here but not extend/slant... * The extend and slant actually is font matrix. */ - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_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; break; case TEXT_WMODE_HV: @@ -716,10 +743,10 @@ start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) /* * e = (e_user_y, -e_user_x) */ - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_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_dely = -error_dely; break; case TEXT_WMODE_HH: @@ -731,10 +758,10 @@ start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) desired_delx = (spt_t)((delx - dely*slant)/extend); desired_dely = dely; - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_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: @@ -745,10 +772,10 @@ start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) desired_delx = delx; desired_dely = (spt_t)((dely + delx*slant)/extend); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_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_HD: /* Horizontal font in down-to-up mode: rot = +90 @@ -760,10 +787,10 @@ start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) desired_delx = -(spt_t)(-(dely + delx*slant)/extend); desired_dely = -delx; - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_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; @@ -776,48 +803,50 @@ start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) desired_delx = -delx; desired_dely = -(spt_t)((dely + delx*slant)/extend); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_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); error_delx = -error_delx; error_dely = -error_dely; break; } - pdf_doc_add_page_content(format_buffer, len); /* op: */ + 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. */ - pdf_doc_add_page_content(text_state.is_mb ? " Td[<" : " Td[(", 5); /* op: Td */ + dev_out(p, p->text_state.is_mb ? " Td[<" : " Td[(", 5); /* op: Td */ /* Error correction */ - text_state.ref_x = xpos - error_delx; - text_state.ref_y = ypos - error_dely; + p->text_state.ref_x = xpos - error_delx; + p->text_state.ref_y = ypos - error_dely; - text_state.offset = 0; + p->text_state.offset = 0; } static void -string_mode (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) +pdf_dev_string_mode (pdf_dev *p, spt_t xpos, spt_t ypos, double slant, double extend, int rotate) { - switch (motion_state) { + ASSERT(p); + + switch (p->motion_state) { case STRING_MODE: break; case GRAPHICS_MODE: - reset_text_state(); + reset_text_state(p); /* continue */ case TEXT_MODE: - if (text_state.force_reset) { - dev_set_text_matrix(xpos, ypos, slant, extend, rotate); - pdf_doc_add_page_content(text_state.is_mb ? "[<" : "[(", 2); /* op: */ - text_state.force_reset = 0; + 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(xpos, ypos, slant, extend, rotate); + start_string(p, xpos, ypos, slant, extend, rotate); } break; } - motion_state = STRING_MODE; + p->motion_state = STRING_MODE; } /* @@ -833,7 +862,7 @@ string_mode (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) */ static int -dev_set_font (int font_id) +pdf_dev_set_font (pdf_dev *p, int font_id) { struct dev_font *font; struct dev_font *real_font; @@ -842,35 +871,37 @@ dev_set_font (int font_id) int len; int vert_dir, vert_font; + ASSERT(p); + /* text_mode() must come before text_state.is_mb is changed. */ - text_mode(); + pdf_dev_text_mode(p); - font = GET_FONT(font_id); + font = GET_FONT(p, font_id); ASSERT(font); /* Caller should check font_id. */ if (font->real_font_index >= 0) - real_font = GET_FONT(font->real_font_index); + real_font = GET_FONT(p, font->real_font_index); else real_font = font; - text_state.is_mb = (font->format == PDF_FONTTYPE_COMPOSITE) ? 1 : 0; + p->text_state.is_mb = (font->format == PDF_FONTTYPE_COMPOSITE) ? 1 : 0; vert_font = font->wmode ? 1 : 0; - if (dev_param.autorotate) { - vert_dir = text_state.dir_mode; + 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 != text_state.matrix.slant || - font->extend != text_state.matrix.extend || - ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { - text_state.force_reset = 1; + 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; } - text_state.matrix.slant = font->slant; - text_state.matrix.extend = font->extend; - text_state.matrix.rotate = text_rotate; + p->text_state.matrix.slant = font->slant; + p->text_state.matrix.extend = font->extend; + p->text_state.matrix.rotate = text_rotate; if (!real_font->resource) { real_font->resource = pdf_get_font_reference(real_font->font_id); @@ -884,66 +915,33 @@ dev_set_font (int font_id) real_font->used_on_this_page = 1; } - font_scale = (double) font->sptsize * dev_unit.dvi2pts; - len = sprintf(format_buffer, " /%s", real_font->short_name); /* space not necessary. */ - format_buffer[len++] = ' '; - len += p_dtoa(font_scale, MIN(dev_unit.precision+1, DEV_PRECISION_MAX), format_buffer+len); - format_buffer[len++] = ' '; - format_buffer[len++] = 'T'; - format_buffer[len++] = 'f'; - pdf_doc_add_page_content(format_buffer, len); /* op: Tf */ - - if (font->bold > 0.0 || font->bold != text_state.bold_param) { + font_scale = (double) font->sptsize * p->unit.dvi2pts; + len = sprintf(p->format_buffer, " /%s", real_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(format_buffer, " 0 Tr"); + len = sprintf(p->format_buffer, " 0 Tr"); else - len = sprintf(format_buffer, " 2 Tr %.6f w", font->bold); /* _FIXME_ */ - pdf_doc_add_page_content(format_buffer, len); /* op: Tr w */ + len = sprintf(p->format_buffer, " 2 Tr %.6f w", font->bold); /* _FIXME_ */ + dev_out(p, p->format_buffer, len); /* op: Tr w */ } - text_state.bold_param = font->bold; + p->text_state.bold_param = font->bold; - text_state.font_id = font_id; + p->text_state.font_id = font_id; return 0; } - -/* Access text state parameters. +/* 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. */ -#if 0 -int -pdf_dev_currentfont (void) -{ - return text_state.font_id; -} - -double -pdf_dev_get_font_ptsize (int font_id) -{ - struct dev_font *font; - - font = GET_FONT(font_id); - if (font) { - return font->sptsize * dev_unit.dvi2pts; - } - - return 1.0; -} -#endif - -int -pdf_dev_get_font_wmode (int font_id) -{ - struct dev_font *font; - - font = GET_FONT(font_id); - if (font) { - return font->wmode; - } - - return 0; -} - static unsigned char sbuf0[FORMAT_BUF_SIZE]; static unsigned char sbuf1[FORMAT_BUF_SIZE]; @@ -1048,37 +1046,6 @@ handle_multibyte_string (struct dev_font *font, return 0; } - -static pdf_coord *dev_coords = NULL; -static int num_dev_coords = 0; -static int max_dev_coords = 0; - -void pdf_dev_get_coord(double *xpos, double *ypos) -{ - if (num_dev_coords > 0) { - *xpos = dev_coords[num_dev_coords-1].x; - *ypos = dev_coords[num_dev_coords-1].y; - } else { - *xpos = *ypos = 0.0; - } -} - -void pdf_dev_push_coord(double xpos, double ypos) -{ - if (num_dev_coords >= max_dev_coords) { - max_dev_coords += 4; - dev_coords = RENEW(dev_coords, max_dev_coords, pdf_coord); - } - dev_coords[num_dev_coords].x = xpos; - dev_coords[num_dev_coords].y = ypos; - num_dev_coords++; -} - -void pdf_dev_pop_coord(void) -{ - if (num_dev_coords > 0) num_dev_coords--; -} - /* * ctype: * -1 input string contains 2-byte Freetype glyph index values @@ -1097,35 +1064,36 @@ pdf_dev_set_string (spt_t xpos, spt_t ypos, spt_t width, int font_id, int ctype) { - struct dev_font *font; - struct dev_font *real_font; + pdf_dev *p = current_device(); + struct dev_font *font; + struct dev_font *real_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; + int length, i, len = 0; + spt_t kern, delh, delv; + spt_t text_xorigin; + spt_t text_yorigin; - if (font_id < 0 || font_id >= num_dev_fonts) { - ERROR("Invalid font: %d (%d)", font_id, num_dev_fonts); + 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 != text_state.font_id) { - dev_set_font(font_id); + if (font_id != p->text_state.font_id) { + pdf_dev_set_font(p, font_id); } - font = CURRENTFONT(); + font = CURRENTFONT(p); if (!font) { ERROR("Currentfont not set."); return; } if (font->real_font_index >= 0) - real_font = GET_FONT(font->real_font_index); + real_font = GET_FONT(p, font->real_font_index); else real_font = font; - text_xorigin = text_state.ref_x; - text_yorigin = text_state.ref_y; + text_xorigin = p->text_state.ref_x; + text_yorigin = p->text_state.ref_y; str_ptr = instr_ptr; length = instr_len; @@ -1148,9 +1116,9 @@ pdf_dev_set_string (spt_t xpos, spt_t ypos, } } - if (num_dev_coords > 0) { - xpos -= bpt2spt(dev_coords[num_dev_coords-1].x); - ypos -= bpt2spt(dev_coords[num_dev_coords-1].y); + if (p->num_dev_coords > 0) { + xpos -= bpt2spt(p, p->dev_coords[p->num_dev_coords-1].x); + ypos -= bpt2spt(p, p->dev_coords[p->num_dev_coords-1].y); } /* @@ -1168,17 +1136,17 @@ pdf_dev_set_string (spt_t xpos, spt_t ypos, * (in 1000 units per em) but dvipdfmx does not take into account of this... */ - if (text_state.dir_mode==0) { + if (p->text_state.dir_mode==0) { /* Left-to-right */ - delh = text_xorigin + text_state.offset - xpos; + delh = text_xorigin + p->text_state.offset - xpos; delv = ypos - text_yorigin; - } else if (text_state.dir_mode==1) { + } else if (p->text_state.dir_mode==1) { /* Top-to-bottom */ - delh = ypos - text_yorigin + text_state.offset; + delh = ypos - text_yorigin + p->text_state.offset; delv = xpos - text_xorigin; } else { /* Bottom-to-top */ - delh = ypos + text_yorigin + text_state.offset; + delh = ypos + text_yorigin + p->text_state.offset; delv = xpos + text_xorigin; } @@ -1192,10 +1160,10 @@ pdf_dev_set_string (spt_t xpos, spt_t ypos, */ #define WORD_SPACE_MAX(f) (spt_t) (3.0 * (f)->extend * (f)->sptsize) - if (text_state.force_reset || - labs(delv) > dev_unit.min_bp_val || + if (p->text_state.force_reset || + labs(delv) > p->unit.min_bp_val || labs(delh) > WORD_SPACE_MAX(font)) { - text_mode(); + pdf_dev_text_mode(p); kern = 0; } else { kern = (spt_t) (1000.0 / font->extend * delh / font->sptsize); @@ -1205,28 +1173,28 @@ pdf_dev_set_string (spt_t xpos, spt_t ypos, * 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 (motion_state != STRING_MODE) - string_mode(xpos, ypos, - font->slant, font->extend, text_state.matrix.rotate); + 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(). */ - text_state.offset -= + p->text_state.offset -= (spt_t) (kern * font->extend * (font->sptsize / 1000.0)); - format_buffer[len++] = text_state.is_mb ? '>' : ')'; + p->format_buffer[len++] = p->text_state.is_mb ? '>' : ')'; if (font->wmode) - len += p_itoa(-kern, format_buffer + len); + len += p_itoa(-kern, p->format_buffer + len); else { - len += p_itoa( kern, format_buffer + len); + len += p_itoa( kern, p->format_buffer + len); } - format_buffer[len++] = text_state.is_mb ? '<' : '('; - pdf_doc_add_page_content(format_buffer, len); /* op: */ + p->format_buffer[len++] = p->text_state.is_mb ? '<' : '('; + dev_out(p, p->format_buffer, len); /* op: */ len = 0; } - if (text_state.is_mb) { + if (p->text_state.is_mb) { if (FORMAT_BUF_SIZE - len < 2 * length) ERROR("Buffer overflow..."); for (i = 0; i < length; i++) { @@ -1234,68 +1202,94 @@ pdf_dev_set_string (spt_t xpos, spt_t ypos, first = (str_ptr[i] >> 4) & 0x0f; second = str_ptr[i] & 0x0f; - format_buffer[len++] = ((first >= 10) ? first + 'W' : first + '0'); - format_buffer[len++] = ((second >= 10) ? second + 'W' : second + '0'); + 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(format_buffer + len, + 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. */ - pdf_doc_add_page_content(format_buffer, len); /* op: */ + dev_out(p, p->format_buffer, len); /* op: */ - text_state.offset += width; + 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) { - dev_unit.precision = 0; + p->unit.precision = 0; } else if (precision > DEV_PRECISION_MAX) { - dev_unit.precision = DEV_PRECISION_MAX; + p->unit.precision = DEV_PRECISION_MAX; } else { - dev_unit.precision = precision; + p->unit.precision = precision; } - dev_unit.dvi2pts = dvi2pts; - dev_unit.min_bp_val = (int) ROUND(1.0/(ten_pow[dev_unit.precision]*dvi2pts), 1); - if (dev_unit.min_bp_val < 0) - dev_unit.min_bp_val = -dev_unit.min_bp_val; + 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; - dev_param.colormode = (black_and_white ? 0 : 1); + p->param.colormode = (black_and_white ? 0 : 1); - graphics_mode(); + pdf_dev_graphics_mode(p); pdf_color_clear_stack(); pdf_dev_init_gstates(); - num_dev_fonts = max_dev_fonts = 0; - dev_fonts = NULL; - num_dev_coords = max_dev_coords = 0; - dev_coords = NULL; + p->num_dev_fonts = p->max_dev_fonts = 0; + p->fonts = NULL; + p->num_dev_coords = 0; + p->max_dev_coords = 0; + p->dev_coords = NULL; + + return; } void pdf_close_device (void) { - if (dev_fonts) { + pdf_dev *p = current_device(); + + if (p->fonts) { int i; - for (i = 0; i < num_dev_fonts; i++) { - if (dev_fonts[i].tex_name) - RELEASE(dev_fonts[i].tex_name); - if (dev_fonts[i].resource) - pdf_release_obj(dev_fonts[i].resource); - dev_fonts[i].tex_name = NULL; - dev_fonts[i].resource = NULL; + 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(dev_fonts); + RELEASE(p->fonts); + p->fonts = NULL; } - if (dev_coords) RELEASE(dev_coords); + if (p->dev_coords) + RELEASE(p->dev_coords); + p->dev_coords = NULL; pdf_dev_clear_gstates(); } @@ -1307,22 +1301,23 @@ pdf_close_device (void) void pdf_dev_reset_fonts (int newpage) { - int i; + pdf_dev *p = current_device(); + int i; - for (i = 0; i < num_dev_fonts; i++) { - dev_fonts[i].used_on_this_page = 0; + for (i = 0; i < p->num_dev_fonts; i++) { + p->fonts[i].used_on_this_page = 0; } - text_state.font_id = -1; + p->text_state.font_id = -1; - text_state.matrix.slant = 0.0; - text_state.matrix.extend = 1.0; - text_state.matrix.rotate = TEXT_WMODE_HH; + p->text_state.matrix.slant = 0.0; + p->text_state.matrix.extend = 1.0; + p->text_state.matrix.rotate = TEXT_WMODE_HH; if (newpage) - text_state.bold_param = 0.0; + p->text_state.bold_param = 0.0; - text_state.is_mb = 0; + p->text_state.is_mb = 0; } void @@ -1335,29 +1330,14 @@ pdf_dev_reset_color (int force) pdf_dev_set_color(fc, 0x20, force); } -#if 0 -/* Not working */ -void -pdf_dev_set_origin (double phys_x, double phys_y) -{ - pdf_tmatrix M0, M1; - - pdf_dev_currentmatrix(&M0); - pdf_dev_currentmatrix(&M1); - pdf_invertmatrix(&M1); - M0.e = phys_x; M0.f = phys_y; - pdf_concatmatrix(&M1, &M0); - - pdf_dev_concat(&M1); -} -#endif - void pdf_dev_bop (const pdf_tmatrix *M) { - graphics_mode(); + pdf_dev *p = current_device(); + + pdf_dev_graphics_mode(p); - text_state.force_reset = 0; + p->text_state.force_reset = 0; pdf_dev_gsave(); pdf_dev_concat(M); @@ -1370,9 +1350,10 @@ pdf_dev_bop (const pdf_tmatrix *M) void pdf_dev_eop (void) { - int depth; + pdf_dev *p = current_device(); + int depth; - graphics_mode(); + pdf_dev_graphics_mode(p); depth = pdf_dev_current_depth(); if (depth != 1) { @@ -1433,6 +1414,7 @@ print_fontmap (const char *font_name, fontmap_rec *mrec) 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; @@ -1445,11 +1427,11 @@ pdf_dev_locate_font (const char *font_name, spt_t ptsize) return -1; } - for (i = 0; i < num_dev_fonts; i++) { - if (strcmp(font_name, dev_fonts[i].tex_name) == 0) { - if (ptsize == dev_fonts[i].sptsize) + for (i = 0; i < p->num_dev_fonts; i++) { + if (strcmp(font_name, p->fonts[i].tex_name) == 0) { + if (ptsize == p->fonts[i].sptsize) return i; /* found a dev_font that matches the request */ - if (dev_fonts[i].format != PDF_FONTTYPE_BITMAP) + if (p->fonts[i].format != PDF_FONTTYPE_BITMAP) break; /* new dev_font will share pdf resource with /i/ */ } } @@ -1458,12 +1440,12 @@ pdf_dev_locate_font (const char *font_name, spt_t ptsize) * Make sure we have room for a new one, even though we may not * actually create one. */ - if (num_dev_fonts >= max_dev_fonts) { - max_dev_fonts += 16; - dev_fonts = RENEW(dev_fonts, max_dev_fonts, struct dev_font); + 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 = &dev_fonts[num_dev_fonts]; + font = &p->fonts[p->num_dev_fonts]; /* New font */ mrec = pdf_lookup_fontmap_record(font_name); @@ -1471,20 +1453,20 @@ pdf_dev_locate_font (const char *font_name, spt_t ptsize) if (dpx_conf.verbose_level > 1) print_fontmap(font_name, mrec); - font->font_id = pdf_font_findresource(font_name, ptsize * dev_unit.dvi2pts, mrec); + font->font_id = pdf_font_findresource(font_name, ptsize * p->unit.dvi2pts, mrec); if (font->font_id < 0) return -1; /* We found device font here. */ - if (i < num_dev_fonts) { + if (i < p->num_dev_fonts) { font->real_font_index = i; - strcpy(font->short_name, dev_fonts[i].short_name); + strcpy(font->short_name, p->fonts[i].short_name); } else { font->real_font_index = -1; font->short_name[0] = 'F'; - p_itoa(num_phys_fonts + 1, &font->short_name[1]); /* NULL terminated here */ - num_phys_fonts++; + p_itoa(p->num_phys_fonts + 1, &font->short_name[1]); /* NULL terminated here */ + p->num_phys_fonts++; } font->used_on_this_page = 0; @@ -1543,33 +1525,33 @@ pdf_dev_locate_font (const char *font_name, spt_t ptsize) } } - return num_dev_fonts++; + return p->num_dev_fonts++; } /* This does not remember current stroking width. */ static int -dev_sprint_line (char *buf, spt_t width, +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 * dev_unit.dvi2pts; + w = width * p->unit.dvi2pts; - len += p_dtoa(w, MIN(dev_unit.precision+1, DEV_PRECISION_MAX), buf+len); + 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(buf+len, p0_x, NULL); + len += dev_sprint_bp(p, buf+len, p0_x, NULL); buf[len++] = ' '; - len += dev_sprint_bp(buf+len, p0_y, NULL); + len += dev_sprint_bp(p, buf+len, p0_y, NULL); buf[len++] = ' '; buf[len++] = 'm'; buf[len++] = ' '; - len += dev_sprint_bp(buf+len, p1_x, NULL); + len += dev_sprint_bp(p, buf+len, p1_x, NULL); buf[len++] = ' '; - len += dev_sprint_bp(buf+len, p1_y, NULL); + len += dev_sprint_bp(p, buf+len, p1_y, NULL); buf[len++] = ' '; buf[len++] = 'l'; buf[len++] = ' '; @@ -1583,35 +1565,36 @@ dev_sprint_line (char *buf, spt_t width, void pdf_dev_set_rule (spt_t xpos, spt_t ypos, spt_t width, spt_t height) { - int len = 0; - double width_in_bp; + pdf_dev *p = current_device(); + int len = 0; + double width_in_bp; - if (num_dev_coords > 0) { - xpos -= bpt2spt(dev_coords[num_dev_coords-1].x); - ypos -= bpt2spt(dev_coords[num_dev_coords-1].y); + if (p->num_dev_coords > 0) { + xpos -= bpt2spt(p, p->dev_coords[p->num_dev_coords-1].x); + ypos -= bpt2spt(p, p->dev_coords[p->num_dev_coords-1].y); } - graphics_mode(); + pdf_dev_graphics_mode(p); - format_buffer[len++] = ' '; - format_buffer[len++] = 'q'; - format_buffer[len++] = ' '; + 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) * dev_unit.dvi2pts; + 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 = dev_unit.dvi2pts * xpos; - rect.lly = dev_unit.dvi2pts * ypos; - rect.urx = dev_unit.dvi2pts * width; - rect.ury = dev_unit.dvi2pts * height; - len += pdf_sprint_rect(format_buffer+len, &rect); - format_buffer[len++] = ' '; - format_buffer[len++] = 'r'; - format_buffer[len++] = 'e'; - format_buffer[len++] = ' '; - format_buffer[len++] = 'f'; + 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: @@ -1619,22 +1602,22 @@ pdf_dev_set_rule (spt_t xpos, spt_t ypos, spt_t width, spt_t height) * device resolution. See, PDF Reference Manual 4th ed., sec. 4.3.2, * "Details of Graphics State Parameters", p. 185. */ - if (height < dev_unit.min_bp_val) { + 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(format_buffer+len, + len += dev_sprint_line(p, p->format_buffer+len, height, xpos, ypos + height/2, xpos + width, ypos + height/2); } else { - if (width < dev_unit.min_bp_val) { + 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(format_buffer+len, + len += dev_sprint_line(p, p->format_buffer+len, width, xpos + width/2, ypos, @@ -1642,9 +1625,9 @@ pdf_dev_set_rule (spt_t xpos, spt_t ypos, spt_t width, spt_t height) ypos + height); } } - format_buffer[len++] = ' '; - format_buffer[len++] = 'Q'; - pdf_doc_add_page_content(format_buffer, len); /* op: q re f Q */ + 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. */ @@ -1653,16 +1636,17 @@ 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 * dev_unit.dvi2pts; - dev_y = y_user * dev_unit.dvi2pts; - if (text_state.dir_mode) { - p0.x = dev_x - dev_unit.dvi2pts * depth; - p0.y = dev_y - dev_unit.dvi2pts * width; - p1.x = dev_x + dev_unit.dvi2pts * height; + 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; @@ -1670,11 +1654,11 @@ pdf_dev_set_rect (pdf_rect *rect, p3.y = p2.y; } else { p0.x = dev_x; - p0.y = dev_y - dev_unit.dvi2pts * depth; - p1.x = dev_x + dev_unit.dvi2pts * width; + 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 + dev_unit.dvi2pts * height; + p2.y = dev_y + p->unit.dvi2pts * height; p3.x = p0.x; p3.y = p2.y; } @@ -1711,20 +1695,22 @@ pdf_dev_set_rect (pdf_rect *rect, int pdf_dev_get_dirmode (void) { - return text_state.dir_mode; + 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(); + font = CURRENTFONT(p); vert_font = (font && font->wmode) ? 1 : 0; - if (dev_param.autorotate) { + if (p->param.autorotate) { vert_dir = text_dir; } else { vert_dir = vert_font; @@ -1732,48 +1718,51 @@ pdf_dev_set_dirmode (int text_dir) text_rotate = (vert_font << 2)|vert_dir; if (font && - ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { - text_state.force_reset = 1; + ANGLE_CHANGES(text_rotate, p->text_state.matrix.rotate)) { + p->text_state.force_reset = 1; } - text_state.matrix.rotate = text_rotate; - text_state.dir_mode = text_dir; + p->text_state.matrix.rotate = text_rotate; + p->text_state.dir_mode = text_dir; } static void -dev_set_param_autorotate (int auto_rotate) +dev_set_param_autorotate (pdf_dev *p, int auto_rotate) { struct dev_font *font; int text_rotate, vert_font, vert_dir; - font = CURRENTFONT(); + ASSERT(p); + + font = CURRENTFONT(p); vert_font = (font && font->wmode) ? 1 : 0; if (auto_rotate) { - vert_dir = text_state.dir_mode; + vert_dir = p->text_state.dir_mode; } else { vert_dir = vert_font; } text_rotate = (vert_font << 2)|vert_dir; - if (ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { - text_state.force_reset = 1; + if (ANGLE_CHANGES(text_rotate, p->text_state.matrix.rotate)) { + p->text_state.force_reset = 1; } - text_state.matrix.rotate = text_rotate; - dev_param.autorotate = auto_rotate; + 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 = dev_param.autorotate; + value = p->param.autorotate; break; case PDF_DEV_PARAM_COLORMODE: - value = dev_param.colormode; + value = p->param.colormode; break; default: ERROR("Unknown device parameter: %d", param_type); @@ -1785,12 +1774,14 @@ pdf_dev_get_param (int param_type) 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(value); + dev_set_param_autorotate(p, value); break; case PDF_DEV_PARAM_COLORMODE: - dev_param.colormode = value; /* 0 for B&W */ + p->param.colormode = value; /* 0 for B&W */ break; default: ERROR("Unknown device parameter: %d", param_type); @@ -1802,56 +1793,52 @@ pdf_dev_set_param (int param_type, int value) int pdf_dev_put_image (int id, - transform_info *p, + transform_info *ti, double ref_x, double ref_y) { + pdf_dev *p = current_device(); char *res_name; pdf_tmatrix M, M1; pdf_rect r; int len = 0; - if (num_dev_coords > 0) { - ref_x -= dev_coords[num_dev_coords-1].x; - ref_y -= dev_coords[num_dev_coords-1].y; + if (p->num_dev_coords > 0) { + ref_x -= p->dev_coords[p->num_dev_coords-1].x; + ref_y -= p->dev_coords[p->num_dev_coords-1].y; } - pdf_copymatrix(&M, &(p->matrix)); + 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 (dev_param.autorotate && - text_state.dir_mode) { + 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; } - graphics_mode(); + pdf_dev_graphics_mode(p); pdf_dev_gsave(); - pdf_ximage_scale_image(id, &M1, &r, p); + pdf_ximage_scale_image(id, &M1, &r, ti); pdf_concatmatrix(&M, &M1); pdf_dev_concat(&M); /* Clip */ - if (p->flags & INFO_DO_CLIP) { -#if 0 - pdf_dev_newpath(); - pdf_dev_moveto(r.llx, r.lly); - pdf_dev_lineto(r.urx, r.lly); - pdf_dev_lineto(r.urx, r.ury); - pdf_dev_lineto(r.llx, r.ury); - pdf_dev_closepath(); - pdf_dev_clip(); - pdf_dev_newpath(); -#else + if (ti->flags & INFO_DO_CLIP) { pdf_dev_rectclip(r.llx, r.lly, r.urx - r.llx, r.ury - r.lly); -#endif } res_name = pdf_ximage_get_resname(id); - len = sprintf(work_buffer, " /%s Do", res_name); - pdf_doc_add_page_content(work_buffer, len); /* op: Do */ + { + 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); + } pdf_dev_grestore(); @@ -1861,19 +1848,19 @@ pdf_dev_put_image (int id, if (dvi_is_tracking_boxes()) { pdf_tmatrix P; - int i; - pdf_rect rect; - pdf_coord corner[4]; + int i; + pdf_rect rect; + pdf_coord corner[4]; pdf_dev_set_rect(&rect, 65536 * ref_x, 65536 * ref_y, - 65536 * (r.urx - r.llx), 65536 * (r.ury - r.lly), 0); + 65536 * (r.urx - r.llx), 65536 * (r.ury - r.lly), 0); corner[0].x = rect.llx; corner[0].y = rect.lly; corner[1].x = rect.llx; corner[1].y = rect.ury; corner[2].x = rect.urx; corner[2].y = rect.ury; corner[3].x = rect.urx; corner[3].y = rect.lly; - pdf_copymatrix(&P, &(p->matrix)); + pdf_copymatrix(&P, &(ti->matrix)); for (i = 0; i < 4; ++i) { corner[i].x -= rect.llx; corner[i].y -= rect.lly; @@ -1888,13 +1875,13 @@ pdf_dev_put_image (int id, rect.ury = corner[0].y; for (i = 0; i < 4; ++i) { if (corner[i].x < rect.llx) - rect.llx = corner[i].x; + rect.llx = corner[i].x; if (corner[i].x > rect.urx) - rect.urx = corner[i].x; + rect.urx = corner[i].x; if (corner[i].y < rect.lly) - rect.lly = corner[i].y; + rect.lly = corner[i].y; if (corner[i].y > rect.ury) - rect.ury = corner[i].y; + rect.ury = corner[i].y; } pdf_doc_expand_box(&rect); @@ -1903,7 +1890,6 @@ pdf_dev_put_image (int id, return 0; } - void transform_info_clear (transform_info *info) { @@ -1926,7 +1912,8 @@ transform_info_clear (transform_info *info) void pdf_dev_begin_actualtext (uint16_t *unicodes, int count) { - int len, i, pdf_doc_enc = 1; + 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) */ @@ -1937,41 +1924,144 @@ pdf_dev_begin_actualtext (uint16_t *unicodes, int count) } } - graphics_mode(); + pdf_dev_graphics_mode(p); - len = sprintf(work_buffer, "\n/Span<</ActualText("); - if (!pdf_doc_enc) { - len += sprintf(work_buffer + len, "\xFE\xFF"); - } - pdf_doc_add_page_content(work_buffer, len); + 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(work_buffer + len, "\\%c", c); + len += sprintf(buf + len, "\\%c", c); } else if (c < ' ') { - len += sprintf(work_buffer + len, "\\%03o", c); + len += sprintf(buf + len, "\\%03o", c); } else { - len += sprintf(work_buffer + len, "%c", c); + len += sprintf(buf + len, "%c", c); } } - pdf_doc_add_page_content(work_buffer, len); + dev_out(p, buf, len); ++unicodes; } - len = sprintf(work_buffer, ")>>BDC"); - pdf_doc_add_page_content(work_buffer, len); + dev_out(p, ") >> BDC", 8); } void pdf_dev_end_actualtext (void) { - graphics_mode(); + 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; +} + +/* Saved text position compensation */ +void +pdf_dev_get_coord (double *xpos, double *ypos) +{ + pdf_dev *p = current_device(); + + if (p->num_dev_coords > 0) { + *xpos = p->dev_coords[p->num_dev_coords-1].x; + *ypos = p->dev_coords[p->num_dev_coords-1].y; + } else { + *xpos = *ypos = 0.0; + } +} + +void +pdf_dev_push_coord (double xpos, double ypos) +{ + pdf_dev *p = current_device(); + + if (p->num_dev_coords >= p->max_dev_coords) { + p->max_dev_coords += 4; + p->dev_coords = RENEW(p->dev_coords, p->max_dev_coords, pdf_coord); + } + p->dev_coords[p->num_dev_coords].x = xpos; + p->dev_coords[p->num_dev_coords].y = ypos; + p->num_dev_coords++; +} + +void +pdf_dev_pop_coord (void) +{ + pdf_dev *p = current_device(); - pdf_doc_add_page_content(" EMC", 4); + if (p->num_dev_coords > 0) + p->num_dev_coords--; } |