summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/pdfdev.c
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2020-07-25 22:06:35 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2020-07-25 22:06:35 +0000
commitc44cc0e342ab0ab537882d1f6b312a770c519f18 (patch)
treebfe3d00b70fbc5b3301a19178818804d17548577 /Build/source/texk/dvipdfm-x/pdfdev.c
parent66279a58ec36789c4d363e2d4598176d99f43c66 (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.c1414
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--;
}