summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorL Peter Deutsch <lpd@ghostscript.com>2002-05-20 07:07:15 +0000
committerL Peter Deutsch <lpd@ghostscript.com>2002-05-20 07:07:15 +0000
commit1bba34e58daf93ae7afdb6a624d7bf00eb3132b7 (patch)
tree2546d903285fa685a272a761f293bd59a9a0a845
parent62597fffa3c3b38a4b775aefd455fcd522d73b17 (diff)
downloadghostpdl-1bba34e58daf93ae7afdb6a624d7bf00eb3132b7.tar.gz
Refactors the pdfwrite driver so that none of the structures, and very few
of the procedures, for handling text and fonts are visible to the main body of code, in preparation for a major rewrite of the text and font code. git-svn-id: http://svn.ghostscript.com/ghostscript/trunk@2651 a1074d23-0009-0410-80fe-cf8c14f379e6
-rw-r--r--gs/doc/Develop.htm1
-rw-r--r--gs/src/devs.mak18
-rw-r--r--gs/src/gdevpdf.c56
-rw-r--r--gs/src/gdevpdfb.c12
-rw-r--r--gs/src/gdevpdfd.c65
-rw-r--r--gs/src/gdevpdff.c21
-rw-r--r--gs/src/gdevpdff.h16
-rw-r--r--gs/src/gdevpdfs.c39
-rw-r--r--gs/src/gdevpdft.c234
-rw-r--r--gs/src/gdevpdft.h106
-rw-r--r--gs/src/gdevpdfu.c11
-rw-r--r--gs/src/gdevpdfw.c12
-rw-r--r--gs/src/gdevpdfx.h120
13 files changed, 445 insertions, 266 deletions
diff --git a/gs/doc/Develop.htm b/gs/doc/Develop.htm
index 241cebfe5..676eae0c8 100644
--- a/gs/doc/Develop.htm
+++ b/gs/doc/Develop.htm
@@ -1614,6 +1614,7 @@ Text and fonts:
<a href="../src/gdevpdff.h">src/gdevpdff.h</a>,
<a href="../src/gdevpdfs.c">src/gdevpdfs.c</a>,
<a href="../src/gdevpdft.c">src/gdevpdft.c</a>,
+<a href="../src/gdevpdft.h">src/gdevpdft.h</a>,
<a href="../src/gdevpdfw.c">src/gdevpdfw.c</a>.
<dt>
diff --git a/gs/src/devs.mak b/gs/src/devs.mak
index 3c14285c7..901768583 100644
--- a/gs/src/devs.mak
+++ b/gs/src/devs.mak
@@ -761,7 +761,6 @@ $(DD)pdfwrite.dev : $(DEVS_MAK) $(ECHOGS_XE) $(pdfwrite_)\
$(ADDMOD) $(DD)pdfwrite -include $(DD)pdftext
gdevpdfc_h=$(GLSRC)gdevpdfc.h
-gdevpdff_h=$(GLSRC)gdevpdff.h
gdevpdfg_h=$(GLSRC)gdevpdfg.h $(gscspace_h)
gdevpdfo_h=$(GLSRC)gdevpdfo.h $(gsparam_h)
gdevpdfx_h=$(GLSRC)gdevpdfx.h\
@@ -770,12 +769,12 @@ gdevpdfx_h=$(GLSRC)gdevpdfx.h\
$(GLOBJ)gdevpdf.$(OBJ) : $(GLSRC)gdevpdf.c $(GDEVH)\
$(fcntl__h) $(memory__h) $(string__h) $(time__h) $(unistd__h) $(gp_h)\
- $(gdevpdff_h) $(gdevpdfg_h) $(gdevpdfo_h) $(gdevpdfx_h)
+ $(gdevpdfg_h) $(gdevpdfo_h) $(gdevpdfx_h)
$(GLCC) $(GLO_)gdevpdf.$(OBJ) $(C_) $(GLSRC)gdevpdf.c
$(GLOBJ)gdevpdfb.$(OBJ) : $(GLSRC)gdevpdfb.c\
$(string__h) $(gx_h)\
- $(gdevpdff_h) $(gdevpdfg_h) $(gdevpdfo_h) $(gdevpdfx_h)\
+ $(gdevpdfg_h) $(gdevpdfo_h) $(gdevpdfx_h)\
$(gserrors_h) $(gxcspace_h)
$(GLCC) $(GLO_)gdevpdfb.$(OBJ) $(C_) $(GLSRC)gdevpdfb.c
@@ -858,6 +857,9 @@ $(GLOBJ)gdevpdfv.$(OBJ) : $(GLSRC)gdevpdfv.c $(GXERR) $(math__h) $(string__h)\
# we give them their own module name and file name prefix.
# However, logically they are part of pdfwrite and cannot be used separately.
+gdevpdff_h=$(GLSRC)gdevpdff.h
+gdevpdft_h=$(GLSRC)gdevpdft.h
+
pdftext1_=$(GLOBJ)gdevpdfe.$(OBJ) $(GLOBJ)gdevpdff.$(OBJ)
pdftext2_=$(GLOBJ)gdevpdfs.$(OBJ) $(GLOBJ)gdevpdft.$(OBJ) $(GLOBJ)gdevpdfw.$(OBJ)
pdftext10_=$(GLOBJ)gsfont0c.$(OBJ)
@@ -880,7 +882,7 @@ $(GLOBJ)gdevpdfe.$(OBJ) : $(GLSRC)gdevpdfe.c\
$(GLOBJ)gdevpdff.$(OBJ) : $(GLSRC)gdevpdff.c\
$(ctype__h) $(math__h) $(memory__h) $(string__h) $(gx_h)\
- $(gdevpdff_h) $(gdevpdfo_h) $(gdevpdfx_h) $(gdevpsf_h)\
+ $(gdevpdff_h) $(gdevpdfo_h) $(gdevpdft_h) $(gdevpdfx_h) $(gdevpsf_h)\
$(gserrors_h) $(gsmalloc_h) $(gsmatrix_h) $(gspath_h) $(gsutil_h)\
$(gxfcache_h) $(gxfcid_h) $(gxfixed_h) $(gxfont_h) $(gxfont1_h) $(gxfont42_h)\
$(gxpath_h)\
@@ -889,8 +891,8 @@ $(GLOBJ)gdevpdff.$(OBJ) : $(GLSRC)gdevpdff.c\
$(GLOBJ)gdevpdfs.$(OBJ) : $(GLSRC)gdevpdfs.c\
$(math__h) $(memory__h) $(string__h) $(gx_h)\
- $(gdevpdff_h) $(gdevpdfg_h) $(gdevpdfo_h) $(gdevpdfx_h) $(gdevpsf_h)\
- $(gserrors_h) $(gsmatrix_h) $(gsutil_h)\
+ $(gdevpdff_h) $(gdevpdfg_h) $(gdevpdfo_h) $(gdevpdft_h) $(gdevpdfx_h) $(gdevpsf_h)\
+ $(gscencs_h) $(gserrors_h) $(gsmatrix_h) $(gsutil_h)\
$(gxfcache_h) $(gxfcid_h) $(gxfcmap_h) $(gxfixed_h) $(gxfont_h)\
$(gxfont0_h) $(gxfont0c_h) $(gxfont1_h) $(gxfont42_h) $(gxpath_h)\
$(scommon_h)
@@ -898,14 +900,14 @@ $(GLOBJ)gdevpdfs.$(OBJ) : $(GLSRC)gdevpdfs.c\
$(GLOBJ)gdevpdft.$(OBJ) : $(GLSRC)gdevpdft.c\
$(math__h) $(memory__h) $(string__h) $(gx_h)\
- $(gdevpdff_h) $(gdevpdfg_h) $(gdevpdfx_h)\
+ $(gdevpdff_h) $(gdevpdfg_h) $(gdevpdft_h) $(gdevpdfx_h)\
$(gserrors_h) $(gxpath_h)\
$(scommon_h)
$(GLCC) $(GLO_)gdevpdft.$(OBJ) $(C_) $(GLSRC)gdevpdft.c
$(GLOBJ)gdevpdfw.$(OBJ) : $(GLSRC)gdevpdfw.c\
$(memory__h) $(string__h) $(gx_h)\
- $(gdevpdff_h) $(gdevpdfx_h) $(gdevpsf_h)\
+ $(gdevpdff_h) $(gdevpdft_h) $(gdevpdfx_h) $(gdevpsf_h)\
$(gsalloc_h) $(gsbittab_h) $(gserrors_h) $(gsmatrix_h) $(gsutil_h)\
$(gxfcid_h) $(gxfcmap_h) $(gxfont_h) $(gxfont0_h)\
$(scommon_h)
diff --git a/gs/src/gdevpdf.c b/gs/src/gdevpdf.c
index dfa57b697..a56b617ef 100644
--- a/gs/src/gdevpdf.c
+++ b/gs/src/gdevpdf.c
@@ -26,7 +26,6 @@
#include "gserrors.h"
#include "gxdevice.h"
#include "gdevpdfx.h"
-#include "gdevpdff.h"
#include "gdevpdfg.h" /* only for pdf_reset_graphics */
#include "gdevpdfo.h"
@@ -51,12 +50,6 @@ private
ENUM_PTRS_WITH(device_pdfwrite_enum_ptrs, gx_device_pdf *pdev)
{
index -= gx_device_pdf_num_ptrs + gx_device_pdf_num_strings;
- if (index < PDF_NUM_STD_FONTS)
- ENUM_RETURN(pdev->std_fonts[index].font);
- index -= PDF_NUM_STD_FONTS;
- if (index < PDF_NUM_STD_FONTS)
- ENUM_RETURN(pdev->std_fonts[index].pfd);
- index -= PDF_NUM_STD_FONTS;
if (index < NUM_RESOURCE_TYPES * NUM_RESOURCE_CHAINS)
ENUM_RETURN(pdev->resources[index / NUM_RESOURCE_CHAINS].chains[index % NUM_RESOURCE_CHAINS]);
index -= NUM_RESOURCE_TYPES * NUM_RESOURCE_CHAINS;
@@ -87,10 +80,6 @@ private RELOC_PTRS_WITH(device_pdfwrite_reloc_ptrs, gx_device_pdf *pdev)
{
int i, j;
- for (i = 0; i < PDF_NUM_STD_FONTS; ++i) {
- RELOC_PTR(gx_device_pdf, std_fonts[i].font);
- RELOC_PTR(gx_device_pdf, std_fonts[i].pfd);
- }
for (i = 0; i < NUM_RESOURCE_TYPES; ++i)
for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
RELOC_PTR(gx_device_pdf, resources[i].chains[j]);
@@ -208,10 +197,6 @@ const gx_device_pdf gs_pdfwrite_device =
{{0}}, /* asides */
{{0}}, /* streams */
{{0}}, /* pictures */
- 0, /* open_font */
- 0 /*false*/, /* use_open_font */
- 0, /* embedded_encoding_id */
- -1, /* max_embedded_code */
0, /* random_offset */
0, /* next_id */
0, /* Catalog */
@@ -224,9 +209,7 @@ const gx_device_pdf gs_pdfwrite_device =
0, /* contents_length_id */
0, /* contents_pos */
NoMarks, /* procsets */
- {pdf_text_state_default}, /* text */
- {{0}}, /* std_fonts */
- {0}, /* space_char_ids */
+ 0, /* text */
{{0}}, /* text_rotation */
0, /* pages */
0, /* num_pages */
@@ -304,13 +287,7 @@ pdf_reset_page(gx_device_pdf * pdev)
pdf_reset_graphics(pdev);
pdev->procsets = NoMarks;
memset(pdev->cs_Patterns, 0, sizeof(pdev->cs_Patterns)); /* simplest to create for each page */
- {
- static const pdf_text_state_t text_default = {
- pdf_text_state_default
- };
-
- pdev->text = text_default;
- }
+ pdf_reset_text_page(pdev->text);
}
/* Open a temporary file, with or without a stream. */
@@ -444,19 +421,12 @@ pdf_set_process_color_model(gx_device_pdf * pdev)
#endif
/*
- * Reset the text state parameters to initial values. This isn't a very
- * good place for this procedure, but the alternatives seem worse.
+ * Reset the text state parameters to initial values.
*/
void
pdf_reset_text(gx_device_pdf * pdev)
{
- pdev->text.character_spacing = 0;
- pdev->text.font = NULL;
- pdev->text.size = 0;
- pdev->text.word_spacing = 0;
- pdev->text.leading = 0;
- pdev->text.use_leading = false;
- pdev->text.render_mode = 0;
+ pdf_reset_text_state(pdev->text);
}
/*
@@ -523,11 +493,11 @@ pdf_open(gx_device * dev)
pdf_initialize_ids(pdev);
pdev->outlines_id = 0;
pdev->next_page = 0;
- memset(pdev->space_char_ids, 0, sizeof(pdev->space_char_ids));
+ pdev->text = pdf_text_data_alloc(mem);
pdev->pages =
gs_alloc_struct_array(mem, initial_num_pages, pdf_page_t,
&st_pdf_page_element, "pdf_open(pages)");
- if (pdev->pages == 0) {
+ if (pdev->text == 0 || pdev->pages == 0) {
code = gs_error_VMerror;
goto fail;
}
@@ -678,17 +648,9 @@ pdf_close_page(gx_device_pdf * pdev)
pdf_write_resource_objects(pdev, resourceFunction);
- /*
- * When Acrobat Reader 3 prints a file containing a Type 3 font with a
- * non-standard Encoding, it apparently only emits the subset of the
- * font actually used on the page. Thus, if the "Download Fonts Once"
- * option is selected, characters not used on the page where the font
- * first appears will not be defined, and hence will print as blank if
- * used on subsequent pages. Thus, we can't allow a Type 3 font to
- * add additional characters on subsequent pages.
- */
- if (pdev->CompatibilityLevel <= 1.2)
- pdev->use_open_font = false;
+ /* Close use of text on the page. */
+
+ pdf_close_text_page(pdev);
/* Accumulate text rotation. */
diff --git a/gs/src/gdevpdfb.c b/gs/src/gdevpdfb.c
index 98b3a6a87..942637a53 100644
--- a/gs/src/gdevpdfb.c
+++ b/gs/src/gdevpdfb.c
@@ -20,7 +20,6 @@
#include "gx.h"
#include "gserrors.h"
#include "gdevpdfx.h"
-#include "gdevpdff.h" /* for synthesized bitmap fonts */
#include "gdevpdfg.h"
#include "gdevpdfo.h" /* for data stream */
#include "gxcspace.h"
@@ -144,19 +143,11 @@ pdf_copy_mono(gx_device_pdf *pdev,
if (pres == 0) { /* Define the character in an embedded font. */
pdf_char_proc_t *pcp;
int y_offset;
- int max_y_offset =
- (pdev->open_font == 0 ? 0 :
- pdev->open_font->max_y_offset);
gs_image_t_init_mask(&image, false);
invert = 0xff;
pdf_make_bitmap_image(&image, x, y, w, h);
- y_offset =
- image.ImageMatrix.ty - (int)(pdev->text.current.y + 0.5);
- if (x < pdev->text.current.x ||
- y_offset < -max_y_offset || y_offset > max_y_offset
- )
- y_offset = 0;
+ y_offset = pdf_char_image_y_offset(pdev, x, y, h);
/*
* The Y axis of the text matrix is inverted,
* so we need to negate the Y offset appropriately.
@@ -173,7 +164,6 @@ pdf_copy_mono(gx_device_pdf *pdev,
code = pdf_begin_write_image(pdev, &writer, gs_no_id, w, h, NULL, true);
if (code < 0)
return code;
- pcp->rid = id;
pres = (pdf_resource_t *) pcp;
goto wr;
}
diff --git a/gs/src/gdevpdfd.c b/gs/src/gdevpdfd.c
index 3e8ce1963..fba4ac09c 100644
--- a/gs/src/gdevpdfd.c
+++ b/gs/src/gdevpdfd.c
@@ -175,51 +175,58 @@ pdf_must_put_clip_path(gx_device_pdf * pdev, const gx_clip_path * pcpath)
int
pdf_put_clip_path(gx_device_pdf * pdev, const gx_clip_path * pcpath)
{
+ int code;
stream *s = pdev->strm;
+ gs_id new_id;
+ /* Check for no update needed. */
if (pcpath == NULL) {
if (pdev->clip_path_id == pdev->no_clip_path_id)
return 0;
- stream_puts(s, "Q\nq\n");
- pdev->clip_path_id = pdev->no_clip_path_id;
+ new_id = pdev->no_clip_path_id;
} else {
if (pdev->clip_path_id == pcpath->id)
return 0;
+ new_id = pcpath->id;
if (gx_cpath_includes_rectangle(pcpath, fixed_0, fixed_0,
int2fixed(pdev->width),
int2fixed(pdev->height))
) {
if (pdev->clip_path_id == pdev->no_clip_path_id)
return 0;
- stream_puts(s, "Q\nq\n");
- pdev->clip_path_id = pdev->no_clip_path_id;
- } else {
- gdev_vector_dopath_state_t state;
- gs_cpath_enum cenum;
- gs_fixed_point vs[3];
- int pe_op;
-
- stream_puts(s, "Q\nq\n");
- gdev_vector_dopath_init(&state, (gx_device_vector *)pdev,
- gx_path_type_fill, NULL);
- /*
- * We have to break 'const' here because the clip path
- * enumeration logic uses some internal mark bits.
- * This is very unfortunate, but until we can come up with
- * a better algorithm, it's necessary.
- */
- gx_cpath_enum_init(&cenum, (gx_clip_path *) pcpath);
- while ((pe_op = gx_cpath_enum_next(&cenum, vs)) > 0)
- gdev_vector_dopath_segment(&state, pe_op, vs);
- pprints1(s, "%s n\n", (pcpath->rule <= 0 ? "W" : "W*"));
- if (pe_op < 0)
- return pe_op;
- pdev->clip_path_id = pcpath->id;
+ new_id = pdev->no_clip_path_id;
}
}
- pdev->text.font = 0;
- if (pdev->context == PDF_IN_TEXT)
- pdev->context = PDF_IN_STREAM;
+ /*
+ * The contents must be open already, so the following will only exit
+ * text or string context.
+ */
+ code = pdf_open_contents(pdev, PDF_IN_STREAM);
+ if (code < 0)
+ return 0;
+ stream_puts(s, "Q\nq\n");
+ if (new_id != pdev->no_clip_path_id) {
+ gdev_vector_dopath_state_t state;
+ gs_cpath_enum cenum;
+ gs_fixed_point vs[3];
+ int pe_op;
+
+ gdev_vector_dopath_init(&state, (gx_device_vector *)pdev,
+ gx_path_type_fill, NULL);
+ /*
+ * We have to break 'const' here because the clip path
+ * enumeration logic uses some internal mark bits.
+ * This is very unfortunate, but until we can come up with
+ * a better algorithm, it's necessary.
+ */
+ gx_cpath_enum_init(&cenum, (gx_clip_path *) pcpath);
+ while ((pe_op = gx_cpath_enum_next(&cenum, vs)) > 0)
+ gdev_vector_dopath_segment(&state, pe_op, vs);
+ pprints1(s, "%s n\n", (pcpath->rule <= 0 ? "W" : "W*"));
+ if (pe_op < 0)
+ return pe_op;
+ }
+ pdev->clip_path_id = new_id;
pdf_reset_graphics(pdev);
return 0;
}
diff --git a/gs/src/gdevpdff.c b/gs/src/gdevpdff.c
index 650ff52a9..2ae9815be 100644
--- a/gs/src/gdevpdff.c
+++ b/gs/src/gdevpdff.c
@@ -37,6 +37,7 @@
#include "gdevpdfx.h"
#include "gdevpdff.h"
#include "gdevpdfo.h"
+#include "gdevpdft.h"
#include "gdevpsf.h"
#include "scommon.h"
@@ -102,7 +103,7 @@ find_std_appearance(const gx_device_pdf *pdev, const gs_font_base *bfont,
int mask, int *psame)
{
bool has_uid = uid_is_UniqueID(&bfont->UID) && bfont->UID.id != 0;
- const pdf_std_font_t *psf = pdev->std_fonts;
+ const pdf_std_font_t *psf = pdev->text->f.std_fonts;
int i;
mask |= FONT_SAME_OUTLINES;
@@ -133,7 +134,7 @@ find_std_appearance(const gx_device_pdf *pdev, const gs_font_base *bfont,
}
/*
- * We register the fonts in pdev->std_fonts so that the pointers can
+ * We register the fonts in pdev->text->f.std_fonts so that the pointers can
* be weak (get set to 0 when the font is freed).
*/
private GS_NOTIFY_PROC(pdf_std_font_notify_proc);
@@ -160,13 +161,13 @@ pdf_std_font_notify_proc(void *vpsfn /*proc_data*/, void *event_data)
"[_] notify 0x%lx: gs_font 0x%lx, id %ld, index=%d\n",
(ulong)psfn, (ulong)font, font->id, psfn->index);
#ifdef DEBUG
- if (pdev->std_fonts[psfn->index].font != font)
+ if (pdev->text->f.std_fonts[psfn->index].font != font)
lprintf3("pdf_std_font_notify font = 0x%lx, std_fonts[%d] = 0x%lx\n",
(ulong)font, psfn->index,
- (ulong)pdev->std_fonts[psfn->index].font);
+ (ulong)pdev->text->f.std_fonts[psfn->index].font);
else
#endif
- pdev->std_fonts[psfn->index].font = 0;
+ pdev->text->f.std_fonts[psfn->index].font = 0;
gs_font_notify_unregister(font, pdf_std_font_notify_proc, vpsfn);
gs_free_object(pdev->pdf_memory, vpsfn, "pdf_std_font_notify_proc");
return 0;
@@ -184,8 +185,8 @@ pdf_unregister_fonts(gx_device_pdf *pdev)
int j;
for (j = 0; j < PDF_NUM_STD_FONTS; ++j)
- if (pdev->std_fonts[j].font != 0)
- gs_notify_unregister_calling(&pdev->std_fonts[j].font->notify_list,
+ if (pdev->text->f.std_fonts[j].font != 0)
+ gs_notify_unregister_calling(&pdev->text->f.std_fonts[j].font->notify_list,
pdf_std_font_notify_proc, NULL,
pdf_std_font_unreg_proc);
}
@@ -212,7 +213,7 @@ scan_for_standard_fonts(gx_device_pdf *pdev, const gs_font_dir *dir)
orig->key_name.size);
pdf_std_font_t *psf;
- if (i >= 0 && (psf = &pdev->std_fonts[i])->font == 0) {
+ if (i >= 0 && (psf = &pdev->text->f.std_fonts[i])->font == 0) {
pdf_std_font_notify_t *psfn =
gs_alloc_struct(pdev->pdf_memory, pdf_std_font_notify_t,
&st_pdf_std_font_notify,
@@ -409,7 +410,7 @@ pdf_find_orig_font(gx_device_pdf *pdev, gs_font *font, gs_matrix *pfmat)
if (font->base == font)
return -1;
}
- *pfmat = pdev->std_fonts[i].orig_matrix;
+ *pfmat = pdev->text->f.std_fonts[i].orig_matrix;
return i;
}
@@ -632,7 +633,7 @@ pdf_create_pdf_font(gx_device_pdf *pdev, gs_font *font, const gs_matrix *pomat,
else
embed = pdf_font_embed_status(pdev, base_font, &index, &base_same);
if (embed == FONT_EMBED_STANDARD) {
- psf = &pdev->std_fonts[index];
+ psf = &pdev->text->f.std_fonts[index];
if (psf->font != 0 || psf->pfd != 0) {
/*
* Use the standard font as the base font. Either base_font
diff --git a/gs/src/gdevpdff.h b/gs/src/gdevpdff.h
index dfc247fa7..629c946bb 100644
--- a/gs/src/gdevpdff.h
+++ b/gs/src/gdevpdff.h
@@ -169,7 +169,7 @@ struct pdf_font_descriptor_s {
/* ---------------- Font (resource) ---------------- */
-typedef struct pdf_char_proc_s pdf_char_proc_t; /* forward reference */
+/*typedef struct pdf_char_proc_s pdf_char_proc_t;*/
/*typedef struct pdf_font_s pdf_font_t;*/
typedef struct pdf_encoding_element_s {
gs_glyph glyph;
@@ -310,20 +310,6 @@ int pdf_set_text_matrix(P2(gx_device_pdf * pdev, const gs_matrix * pmat));
*/
int pdf_append_chars(P3(gx_device_pdf * pdev, const byte * str, uint size));
- /* For gdevpdfb.c */
-
-/* Begin a CharProc for an embedded (bitmap) font. */
-int pdf_begin_char_proc(P8(gx_device_pdf * pdev, int w, int h, int x_width,
- int y_offset, gs_id id, pdf_char_proc_t **ppcp,
- pdf_stream_position_t * ppos));
-
-/* End a CharProc. */
-int pdf_end_char_proc(P2(gx_device_pdf * pdev, pdf_stream_position_t * ppos));
-
-/* Put out a reference to an image as a character in an embedded font. */
-int pdf_do_char_image(P3(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
- const gs_matrix * pimat));
-
/* ---------------- Exported by gdevpdfs.c for gdevpdft.c ---------------- */
/*
diff --git a/gs/src/gdevpdfs.c b/gs/src/gdevpdfs.c
index 7a3122e0f..4248942d6 100644
--- a/gs/src/gdevpdfs.c
+++ b/gs/src/gdevpdfs.c
@@ -39,6 +39,7 @@
#include "gdevpdff.h"
#include "gdevpdfg.h"
#include "gdevpdfo.h" /* only to mark CMap as written */
+#include "gdevpdft.h"
#include "scommon.h"
/*
@@ -1408,16 +1409,15 @@ pdf_encode_glyph(gx_device_pdf *pdev, int chr, gs_glyph glyph,
if (HAS_DIFF(c) || IS_USED(c))
continue; /* slot already referenced */
font_glyph = ENCODE_NO_DIFF(c);
- if (font_glyph == gs_no_glyph)
- break;
- else if (font_glyph >= gs_c_min_std_encoding_glyph) {
- uint len;
- const char *str = gs_c_glyph_name(font_glyph, &len);
-
- if (len == 7 && !memcmp(str, ".notdef", 7))
- break;
- } else if (gs_font_glyph_is_notdef(bfont, font_glyph))
- break;
+ if (font_glyph == gs_no_glyph)
+ break;
+ else if (font_glyph >= gs_c_min_std_encoding_glyph) {
+ uint len;
+ const char *str = gs_c_glyph_name(font_glyph, &len);
+
+ if (len == 7 && !memcmp(str, ".notdef", 7))
+ break;
+ } else if (gs_font_glyph_is_notdef(bfont, font_glyph))
break;
}
if (c == 256) /* no .notdef positions left */
@@ -1456,6 +1456,7 @@ pdf_write_text_process_state(gx_device_pdf *pdev,
const pdf_text_process_state_t *ppts,
const gs_const_string *pstr)
{
+ pdf_text_state_t *const pts = &pdev->text->t;
int code;
/*
@@ -1463,7 +1464,7 @@ pdf_write_text_process_state(gx_device_pdf *pdev,
* settings of the text parameters to be lost. Therefore, we set the
* stroke parameters first.
*/
- if (pdev->text.render_mode != ppts->mode && ppts->mode != 0) {
+ if (pts->render_mode != ppts->mode && ppts->mode != 0) {
/* Write all the parameters for stroking. */
gs_imager_state *pis = pte->pis;
float save_width = pis->line_params.half_width;
@@ -1502,33 +1503,33 @@ pdf_write_text_process_state(gx_device_pdf *pdev,
if (code < 0)
return code;
- if (pdev->text.character_spacing != ppts->chars &&
- pstr->size + pdev->text.buffer_count > 1
+ if (pts->character_spacing != ppts->chars &&
+ pstr->size + pts->buffer_count > 1
) {
code = pdf_open_page(pdev, PDF_IN_TEXT);
if (code < 0)
return code;
pprintg1(pdev->strm, "%g Tc\n", ppts->chars);
- pdev->text.character_spacing = ppts->chars;
+ pts->character_spacing = ppts->chars;
}
- if (pdev->text.word_spacing != ppts->words &&
+ if (pts->word_spacing != ppts->words &&
(memchr(pstr->data, 32, pstr->size) ||
- memchr(pdev->text.buffer, 32, pdev->text.buffer_count))
+ memchr(pts->buffer, 32, pts->buffer_count))
) {
code = pdf_open_page(pdev, PDF_IN_TEXT);
if (code < 0)
return code;
pprintg1(pdev->strm, "%g Tw\n", ppts->words);
- pdev->text.word_spacing = ppts->words;
+ pts->word_spacing = ppts->words;
}
- if (pdev->text.render_mode != ppts->mode) {
+ if (pts->render_mode != ppts->mode) {
code = pdf_open_page(pdev, PDF_IN_TEXT);
if (code < 0)
return code;
pprintd1(pdev->strm, "%d Tr\n", ppts->mode);
- pdev->text.render_mode = ppts->mode;
+ pts->render_mode = ppts->mode;
}
return 0;
diff --git a/gs/src/gdevpdft.c b/gs/src/gdevpdft.c
index e0168a4c0..862d9d35f 100644
--- a/gs/src/gdevpdft.c
+++ b/gs/src/gdevpdft.c
@@ -25,8 +25,143 @@
#include "gdevpdfx.h"
#include "gdevpdff.h"
#include "gdevpdfg.h"
+#include "gdevpdft.h"
#include "scommon.h"
+/* ---------------- Text state management ---------------- */
+
+/* GC descriptor */
+gs_private_st_composite(st_pdf_text_data, pdf_text_data_t,
+ "pdf_text_data_t", pdf_text_data_enum_ptrs, pdf_text_data_reloc_ptrs);
+private
+ENUM_PTRS_WITH(pdf_text_data_enum_ptrs, pdf_text_data_t *ptd)
+{
+ index -= 2;
+ if (index < PDF_NUM_STD_FONTS)
+ ENUM_RETURN(ptd->f.std_fonts[index].font);
+ index -= PDF_NUM_STD_FONTS;
+ if (index < PDF_NUM_STD_FONTS)
+ ENUM_RETURN(ptd->f.std_fonts[index].pfd);
+ return 0;
+}
+case 0: ENUM_RETURN(ptd->t.font);
+case 1: ENUM_RETURN(ptd->f.open_font);
+ENUM_PTRS_END
+private RELOC_PTRS_WITH(pdf_text_data_reloc_ptrs, pdf_text_data_t *ptd)
+{
+ int i;
+
+ RELOC_VAR(ptd->t.font);
+ RELOC_VAR(ptd->f.open_font);
+ for (i = 0; i < PDF_NUM_STD_FONTS; ++i) {
+ RELOC_VAR(ptd->f.std_fonts[i].font);
+ RELOC_VAR(ptd->f.std_fonts[i].pfd);
+ }
+}
+RELOC_PTRS_END
+
+static const pdf_text_data_t td_default = {
+ pdf_text_data_default
+};
+
+/* For gdevpdf.c */
+
+pdf_text_data_t *
+pdf_text_data_alloc(gs_memory_t *mem)
+{
+ pdf_text_data_t *ptd =
+ gs_alloc_struct(mem, pdf_text_data_t, &st_pdf_text_data,
+ "pdf_text_alloc");
+
+ if (ptd == 0)
+ return 0;
+ *ptd = td_default;
+ return ptd;
+}
+
+void
+pdf_reset_text_page(pdf_text_data_t *ptd)
+{
+ ptd->t = td_default.t;
+}
+
+void
+pdf_reset_text_state(pdf_text_data_t *ptd)
+{
+ ptd->t.character_spacing = 0;
+ ptd->t.font = NULL;
+ ptd->t.size = 0;
+ ptd->t.word_spacing = 0;
+ ptd->t.leading = 0;
+ ptd->t.use_leading = false;
+ ptd->t.render_mode = 0;
+}
+
+void
+pdf_close_text_page(gx_device_pdf *pdev)
+{
+ /*
+ * When Acrobat Reader 3 prints a file containing a Type 3 font with a
+ * non-standard Encoding, it apparently only emits the subset of the
+ * font actually used on the page. Thus, if the "Download Fonts Once"
+ * option is selected, characters not used on the page where the font
+ * first appears will not be defined, and hence will print as blank if
+ * used on subsequent pages. Thus, we can't allow a Type 3 font to
+ * add additional characters on subsequent pages.
+ */
+ if (pdev->CompatibilityLevel <= 1.2)
+ pdev->text->f.use_open_font = false;
+}
+
+/* For gdevpdfb.c */
+
+int
+pdf_char_image_y_offset(const gx_device_pdf *pdev, int x, int y, int h)
+{
+ const pdf_text_data_t *const ptd = pdev->text;
+ int max_off, off;
+
+ if (x < ptd->t.current.x)
+ return 0;
+ max_off = (ptd->f.open_font == 0 ? 0 : ptd->f.open_font->max_y_offset);
+ off = (y + h) - (int)(ptd->t.current.y + 0.5);
+ if (off < -max_off || off > max_off)
+ off = 0;
+ return off;
+}
+
+/* For gdevpdfu.c */
+
+void
+pdf_from_stream_to_text(gx_device_pdf *pdev)
+{
+ pdf_text_data_t *ptd = pdev->text;
+
+ gs_make_identity(&ptd->t.matrix);
+ ptd->t.line_start.x = ptd->t.line_start.y = 0;
+ ptd->t.buffer_count = 0;
+}
+
+void
+pdf_from_string_to_text(gx_device_pdf *pdev)
+{
+ pdf_text_data_t *ptd = pdev->text;
+
+ pdf_put_string(pdev, ptd->t.buffer, ptd->t.buffer_count);
+ stream_puts(pdev->strm, (ptd->t.use_leading ? "'\n" : "Tj\n"));
+ ptd->t.use_leading = false;
+ ptd->t.buffer_count = 0;
+}
+
+void
+pdf_close_text_contents(gx_device_pdf *pdev)
+{
+ pdev->text->t.font = 0;
+}
+
+
+/* ---------------- Text processing ---------------- */
+
/* GC descriptors */
private_st_pdf_text_enum();
@@ -198,7 +333,9 @@ private int assign_char_code(P1(gx_device_pdf * pdev));
int
pdf_set_font_and_size(gx_device_pdf * pdev, pdf_font_t * font, floatp size)
{
- if (font != pdev->text.font || size != pdev->text.size) {
+ pdf_text_data_t *ptd = pdev->text;
+
+ if (font != ptd->t.font || size != ptd->t.size) {
int code = pdf_open_page(pdev, PDF_IN_TEXT);
stream *s = pdev->strm;
@@ -206,8 +343,8 @@ pdf_set_font_and_size(gx_device_pdf * pdev, pdf_font_t * font, floatp size)
return code;
pprints1(s, "/%s ", font->rname);
pprintg1(s, "%g Tf\n", size);
- pdev->text.font = font;
- pdev->text.size = size;
+ ptd->t.font = font;
+ ptd->t.size = size;
}
font->where_used |= pdev->used_mask;
return 0;
@@ -239,15 +376,16 @@ set_text_distance(gs_point *pdist, const gs_point *ppt, const gs_matrix *pmat)
int
pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
{
+ pdf_text_data_t *ptd = pdev->text;
stream *s = pdev->strm;
double sx = 72.0 / pdev->HWResolution[0],
sy = 72.0 / pdev->HWResolution[1];
int code;
- if (pmat->xx == pdev->text.matrix.xx &&
- pmat->xy == pdev->text.matrix.xy &&
- pmat->yx == pdev->text.matrix.yx &&
- pmat->yy == pdev->text.matrix.yy &&
+ if (pmat->xx == ptd->t.matrix.xx &&
+ pmat->xy == ptd->t.matrix.xy &&
+ pmat->yx == ptd->t.matrix.yx &&
+ pmat->yy == ptd->t.matrix.yy &&
/*
* If we aren't already in text context, BT will reset
* the text matrix.
@@ -257,30 +395,30 @@ pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
/* Use leading, Td or a pseudo-character. */
gs_point dist;
- set_text_distance(&dist, &pdev->text.current, pmat);
+ set_text_distance(&dist, &ptd->t.current, pmat);
if (dist.y == 0 && dist.x >= X_SPACE_MIN &&
dist.x <= X_SPACE_MAX &&
- pdev->text.font != 0 &&
- PDF_FONT_IS_SYNTHESIZED(pdev->text.font)
+ ptd->t.font != 0 &&
+ PDF_FONT_IS_SYNTHESIZED(ptd->t.font)
) { /* Use a pseudo-character. */
int dx = (int)dist.x;
int dx_i = dx - X_SPACE_MIN;
- byte space_char = pdev->text.font->spaces[dx_i];
+ byte space_char = ptd->t.font->spaces[dx_i];
if (space_char == 0) {
- if (pdev->text.font != pdev->open_font)
+ if (ptd->t.font != ptd->f.open_font)
goto not_spaces;
code = assign_char_code(pdev);
if (code <= 0)
goto not_spaces;
- space_char = pdev->open_font->spaces[dx_i] = (byte)code;
- if (pdev->space_char_ids[dx_i] == 0) {
+ space_char = ptd->f.open_font->spaces[dx_i] = (byte)code;
+ if (ptd->f.space_char_ids[dx_i] == 0) {
/* Create the space char_proc now. */
char spstr[3 + 14 + 1];
stream *s;
sprintf(spstr, "%d 0 0 0 0 0 d1\n", dx);
- pdev->space_char_ids[dx_i] = pdf_begin_separate(pdev);
+ ptd->f.space_char_ids[dx_i] = pdf_begin_separate(pdev);
s = pdev->strm;
pprintd1(s, "<</Length %d>>\nstream\n", strlen(spstr));
pprints1(s, "%sendstream\n", spstr);
@@ -288,8 +426,8 @@ pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
}
}
pdf_append_chars(pdev, &space_char, 1);
- pdev->text.current.x += dx * pmat->xx;
- pdev->text.current.y += dx * pmat->xy;
+ ptd->t.current.x += dx * pmat->xx;
+ ptd->t.current.y += dx * pmat->xy;
/* Don't change use_leading -- it only affects Y placement. */
return 0;
}
@@ -297,24 +435,24 @@ pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
code = pdf_open_page(pdev, PDF_IN_TEXT);
if (code < 0)
return code;
- set_text_distance(&dist, &pdev->text.line_start, pmat);
- if (pdev->text.use_leading) {
+ set_text_distance(&dist, &ptd->t.line_start, pmat);
+ if (ptd->t.use_leading) {
/* Leading was deferred: take it into account now. */
- dist.y -= pdev->text.leading;
+ dist.y -= ptd->t.leading;
}
if (dist.x == 0 && dist.y < 0) {
/* Use TL, if needed, + '. */
float dist_y = (float)-dist.y;
- if (fabs(pdev->text.leading - dist_y) > 0.0005) {
+ if (fabs(ptd->t.leading - dist_y) > 0.0005) {
pprintg1(s, "%g TL\n", dist_y);
- pdev->text.leading = dist_y;
+ ptd->t.leading = dist_y;
}
- pdev->text.use_leading = true;
+ ptd->t.use_leading = true;
} else {
/* Use Td. */
pprintg2(s, "%g %g Td\n", dist.x, dist.y);
- pdev->text.use_leading = false;
+ ptd->t.use_leading = false;
}
} else { /* Use Tm. */
code = pdf_open_page(pdev, PDF_IN_TEXT);
@@ -328,13 +466,13 @@ pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
pmat->xx * sx, pmat->xy * sy,
pmat->yx * sx, pmat->yy * sy,
pmat->tx * sx, pmat->ty * sy);
- pdev->text.matrix = *pmat;
- pdev->text.use_leading = false;
+ ptd->t.matrix = *pmat;
+ ptd->t.use_leading = false;
}
- pdev->text.line_start.x = pmat->tx;
- pdev->text.line_start.y = pmat->ty;
- pdev->text.current.x = pmat->tx;
- pdev->text.current.y = pmat->ty;
+ ptd->t.line_start.x = pmat->tx;
+ ptd->t.line_start.y = pmat->ty;
+ ptd->t.current.x = pmat->tx;
+ ptd->t.current.y = pmat->ty;
return 0;
}
@@ -344,11 +482,12 @@ pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
int
pdf_append_chars(gx_device_pdf * pdev, const byte * str, uint size)
{
+ pdf_text_data_t *ptd = pdev->text;
const byte *p = str;
uint left = size;
while (left)
- if (pdev->text.buffer_count == max_text_buffer) {
+ if (ptd->t.buffer_count == max_text_buffer) {
int code = pdf_open_page(pdev, PDF_IN_TEXT);
if (code < 0)
@@ -359,9 +498,9 @@ pdf_append_chars(gx_device_pdf * pdev, const byte * str, uint size)
if (code < 0)
return code;
- copy = min(max_text_buffer - pdev->text.buffer_count, left);
- memcpy(pdev->text.buffer + pdev->text.buffer_count, p, copy);
- pdev->text.buffer_count += copy;
+ copy = min(max_text_buffer - ptd->t.buffer_count, left);
+ memcpy(ptd->t.buffer + ptd->t.buffer_count, p, copy);
+ ptd->t.buffer_count += copy;
p += copy;
left -= copy;
}
@@ -374,32 +513,33 @@ pdf_append_chars(gx_device_pdf * pdev, const byte * str, uint size)
private int
assign_char_code(gx_device_pdf * pdev)
{
- pdf_font_t *font = pdev->open_font;
+ pdf_text_data_t *ptd = pdev->text;
+ pdf_font_t *font = ptd->f.open_font;
int c;
- if (pdev->embedded_encoding_id == 0)
- pdev->embedded_encoding_id = pdf_obj_ref(pdev);
- if (font == 0 || font->num_chars == 256 || !pdev->use_open_font) {
+ if (ptd->f.embedded_encoding_id == 0)
+ ptd->f.embedded_encoding_id = pdf_obj_ref(pdev);
+ if (font == 0 || font->num_chars == 256 || !ptd->f.use_open_font) {
/* Start a new synthesized font. */
int code = pdf_alloc_font(pdev, gs_no_id, &font, NULL, NULL);
char *pc;
if (code < 0)
return code;
- if (pdev->open_font == 0)
+ if (ptd->f.open_font == 0)
font->rname[0] = 0;
else
- strcpy(font->rname, pdev->open_font->rname);
+ strcpy(font->rname, ptd->f.open_font->rname);
for (pc = font->rname; *pc == 'Z'; ++pc)
*pc = '@';
if ((*pc)++ == 0)
*pc = 'A', pc[1] = 0;
- pdev->open_font = font;
- pdev->use_open_font = true;
+ ptd->f.open_font = font;
+ ptd->f.use_open_font = true;
}
c = font->num_chars++;
- if (c > pdev->max_embedded_code)
- pdev->max_embedded_code = c;
+ if (c > ptd->f.max_embedded_code)
+ ptd->f.max_embedded_code = c;
return c;
}
@@ -411,7 +551,7 @@ pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
pdf_resource_t *pres;
pdf_char_proc_t *pcp;
int char_code = assign_char_code(pdev);
- pdf_font_t *font = pdev->open_font;
+ pdf_font_t *font = pdev->text->f.open_font;
int code;
if (char_code < 0)
@@ -470,6 +610,8 @@ int
pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
const gs_matrix * pimat)
{
+ pdf_text_data_t *ptd = pdev->text;
+
pdf_set_font_and_size(pdev, pcp->font, 1.0);
{
gs_matrix tmat;
@@ -479,6 +621,6 @@ pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
pdf_set_text_matrix(pdev, &tmat);
}
pdf_append_chars(pdev, &pcp->char_code, 1);
- pdev->text.current.x += pcp->x_width * pdev->text.matrix.xx;
+ ptd->t.current.x += pcp->x_width * ptd->t.matrix.xx;
return 0;
}
diff --git a/gs/src/gdevpdft.h b/gs/src/gdevpdft.h
new file mode 100644
index 000000000..11aead3a3
--- /dev/null
+++ b/gs/src/gdevpdft.h
@@ -0,0 +1,106 @@
+/* Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied,
+ modified or distributed except as expressly authorized under the terms
+ of the license contained in the file LICENSE in this distribution.
+
+ For more information about licensing, please refer to
+ http://www.ghostscript.com/licensing/. For information on
+ commercial licensing, go to http://www.artifex.com/licensing/ or
+ contact Artifex Software, Inc., 101 Lucas Valley Road #110,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861.
+*/
+
+/* $Id: gdevpdft.h */
+/* Text definitions and state for pdfwrite. */
+
+#ifndef gdevpdft_INCLUDED
+# define gdevpdft_INCLUDED
+
+/* ================ Types and structures ================ */
+
+/* ------ Fonts ------ */
+
+/* Define the standard fonts. */
+#define PDF_NUM_STD_FONTS 14
+#define pdf_do_std_fonts(m)\
+ m("Courier", ENCODING_INDEX_STANDARD)\
+ m("Courier-Bold", ENCODING_INDEX_STANDARD)\
+ m("Courier-Oblique", ENCODING_INDEX_STANDARD)\
+ m("Courier-BoldOblique", ENCODING_INDEX_STANDARD)\
+ m("Helvetica", ENCODING_INDEX_STANDARD)\
+ m("Helvetica-Bold", ENCODING_INDEX_STANDARD)\
+ m("Helvetica-Oblique", ENCODING_INDEX_STANDARD)\
+ m("Helvetica-BoldOblique", ENCODING_INDEX_STANDARD)\
+ m("Symbol", ENCODING_INDEX_SYMBOL)\
+ m("Times-Roman", ENCODING_INDEX_STANDARD)\
+ m("Times-Bold", ENCODING_INDEX_STANDARD)\
+ m("Times-Italic", ENCODING_INDEX_STANDARD)\
+ m("Times-BoldItalic", ENCODING_INDEX_STANDARD)\
+ m("ZapfDingbats", ENCODING_INDEX_DINGBATS)
+
+/* Font-related definitions */
+#ifndef pdf_font_descriptor_DEFINED
+# define pdf_font_descriptor_DEFINED
+typedef struct pdf_font_descriptor_s pdf_font_descriptor_t;
+#endif
+typedef struct pdf_std_font_s {
+ gs_font *font; /* weak pointer, may be 0 */
+ pdf_font_descriptor_t *pfd; /* *not* a weak pointer */
+ gs_matrix orig_matrix;
+ gs_uid uid; /* UniqueID, not XUID */
+} pdf_std_font_t;
+
+/* Text state */
+typedef struct pdf_text_state_s {
+ /* Text state parameters */
+ float character_spacing; /* Tc */
+ pdf_font_t *font; /* for Tf */
+ floatp size; /* for Tf */
+ float word_spacing; /* Tw */
+ float leading; /* TL */
+ bool use_leading; /* true => use ', false => use Tj */
+ int render_mode; /* Tr */
+ /* Bookkeeping */
+ gs_matrix matrix; /* relative to device space, not user space */
+ gs_point line_start;
+ gs_point current;
+#define max_text_buffer 200 /* arbitrary, but overflow costs 5 chars */
+ byte buffer[max_text_buffer];
+ int buffer_count;
+} pdf_text_state_t;
+#define pdf_text_state_default\
+ 0, NULL, 0, 0, 0, 0 /*false*/, 0,\
+ { identity_matrix_body }, { 0, 0 }, { 0, 0 }, { 0 }, 0
+
+/* Font state */
+typedef struct pdf_font_state_s {
+ pdf_font_t *open_font; /* current Type 3 synthesized font */
+ bool use_open_font; /* if false, start new open_font */
+ long embedded_encoding_id;
+ int max_embedded_code; /* max Type 3 code used */
+ pdf_std_font_t std_fonts[PDF_NUM_STD_FONTS];
+ long space_char_ids[X_SPACE_MAX - X_SPACE_MIN + 1];
+} pdf_font_state_t;
+#define pdf_font_state_default\
+ 0, /* open_font */\
+ 0 /*false*/, /* use_open_font */\
+ 0, /* embedded_encoding_id */\
+ -1, /* max_embedded_code */\
+ {{0}}, /* std_fonts */\
+ {0} /* space_char_ids */
+
+/* Text data */
+/*typedef*/ struct pdf_text_data_s {
+ pdf_text_state_t t;
+ pdf_font_state_t f;
+} /*pdf_text_data_t*/;
+
+#define pdf_text_data_default\
+ { pdf_text_state_default },\
+ { pdf_font_state_default }
+
+#endif /* gdevpdft_INCLUDED */
diff --git a/gs/src/gdevpdfu.c b/gs/src/gdevpdfu.c
index 81be4e281..d6444380c 100644
--- a/gs/src/gdevpdfu.c
+++ b/gs/src/gdevpdfu.c
@@ -262,19 +262,14 @@ stream_to_text(gx_device_pdf * pdev)
pprintg2(pdev->strm, "q %g 0 0 %g 0 0 cm BT\n",
pdev->HWResolution[0] / 72.0, pdev->HWResolution[1] / 72.0);
pdev->procsets |= Text;
- gs_make_identity(&pdev->text.matrix);
- pdev->text.line_start.x = pdev->text.line_start.y = 0;
- pdev->text.buffer_count = 0;
+ pdf_from_stream_to_text(pdev);
return PDF_IN_TEXT;
}
/* Exit string context to text context. */
private int
string_to_text(gx_device_pdf * pdev)
{
- pdf_put_string(pdev, pdev->text.buffer, pdev->text.buffer_count);
- stream_puts(pdev->strm, (pdev->text.use_leading ? "'\n" : "Tj\n"));
- pdev->text.use_leading = false;
- pdev->text.buffer_count = 0;
+ pdf_from_string_to_text(pdev);
return PDF_IN_TEXT;
}
/* Exit text context to stream context. */
@@ -337,7 +332,7 @@ pdf_close_contents(gx_device_pdf * pdev, bool last)
if (last) { /* Exit from the clipping path gsave. */
pdf_open_contents(pdev, PDF_IN_STREAM);
stream_puts(pdev->strm, "Q\n");
- pdev->text.font = 0;
+ pdf_close_text_contents(pdev);
}
return pdf_open_contents(pdev, PDF_IN_NONE);
}
diff --git a/gs/src/gdevpdfw.c b/gs/src/gdevpdfw.c
index c3da4fb38..fceb842aa 100644
--- a/gs/src/gdevpdfw.c
+++ b/gs/src/gdevpdfw.c
@@ -30,6 +30,7 @@
#include "gxfont0.h"
#include "gdevpdfx.h"
#include "gdevpdff.h"
+#include "gdevpdft.h"
#include "gdevpsf.h"
#include "scommon.h"
@@ -96,7 +97,8 @@ pdf_write_synthesized_type3(gx_device_pdf *pdev, const pdf_font_t *pef)
pdf_open_separate(pdev, pdf_font_id(pef));
s = pdev->strm;
pprints1(s, "<</Type/Font/Name/%s/Subtype/Type3", pef->rname);
- pprintld1(s, "/Encoding %ld 0 R/CharProcs", pdev->embedded_encoding_id);
+ pprintld1(s, "/Encoding %ld 0 R/CharProcs",
+ pdev->text->f.embedded_encoding_id);
/* Write the CharProcs. */
{
@@ -119,7 +121,7 @@ pdf_write_synthesized_type3(gx_device_pdf *pdev, const pdf_font_t *pef)
if (ch) {
pprintld2(s, "/a%ld\n%ld 0 R", (long)ch,
- pdev->space_char_ids[w]);
+ pdev->text->f.space_char_ids[w]);
widths[ch] = w + X_SPACE_MIN;
}
}
@@ -832,11 +834,11 @@ pdf_write_font_resources(gx_device_pdf *pdev)
/* If required, write the Encoding for Type 3 bitmap fonts. */
- if (pdev->embedded_encoding_id) {
+ if (pdev->text->f.embedded_encoding_id) {
stream *s;
int i;
- pdf_open_separate(pdev, pdev->embedded_encoding_id);
+ pdf_open_separate(pdev, pdev->text->f.embedded_encoding_id);
s = pdev->strm;
/*
* Even though the PDF reference documentation says that a
@@ -846,7 +848,7 @@ pdf_write_font_resources(gx_device_pdf *pdev)
* BaseEncoding key is present.
*/
stream_puts(s, "<</Type/Encoding/Differences[0");
- for (i = 0; i <= pdev->max_embedded_code; ++i) {
+ for (i = 0; i <= pdev->text->f.max_embedded_code; ++i) {
if (!(i & 15))
stream_puts(s, "\n");
pprintd1(s, "/a%d", i);
diff --git a/gs/src/gdevpdfx.h b/gs/src/gdevpdfx.h
index 35f3e1f6e..e77e93666 100644
--- a/gs/src/gdevpdfx.h
+++ b/gs/src/gdevpdfx.h
@@ -164,30 +164,14 @@ typedef enum {
/* ------ Fonts ------ */
-/* Define the standard fonts. */
-#define PDF_NUM_STD_FONTS 14
-#define pdf_do_std_fonts(m)\
- m("Courier", ENCODING_INDEX_STANDARD)\
- m("Courier-Bold", ENCODING_INDEX_STANDARD)\
- m("Courier-Oblique", ENCODING_INDEX_STANDARD)\
- m("Courier-BoldOblique", ENCODING_INDEX_STANDARD)\
- m("Helvetica", ENCODING_INDEX_STANDARD)\
- m("Helvetica-Bold", ENCODING_INDEX_STANDARD)\
- m("Helvetica-Oblique", ENCODING_INDEX_STANDARD)\
- m("Helvetica-BoldOblique", ENCODING_INDEX_STANDARD)\
- m("Symbol", ENCODING_INDEX_SYMBOL)\
- m("Times-Roman", ENCODING_INDEX_STANDARD)\
- m("Times-Bold", ENCODING_INDEX_STANDARD)\
- m("Times-Italic", ENCODING_INDEX_STANDARD)\
- m("Times-BoldItalic", ENCODING_INDEX_STANDARD)\
- m("ZapfDingbats", ENCODING_INDEX_DINGBATS)
-
/* Define the range of synthesized space characters. */
#define X_SPACE_MIN 24
#define X_SPACE_MAX 150
-/* Define abstract types. The concrete types are in gdevpdff.h. */
-typedef struct pdf_font_s pdf_font_t;
+/* Define abstract types. */
+typedef struct pdf_char_proc_s pdf_char_proc_t; /* gdevpdff.h */
+typedef struct pdf_font_s pdf_font_t; /* gdevpdff.h */
+typedef struct pdf_text_data_s pdf_text_data_t; /* gdevpdft.h */
/* ------ Named objects ------ */
@@ -245,39 +229,6 @@ struct pdf_article_s {
/* ---------------- The device structure ---------------- */
-/* Text state */
-#ifndef pdf_font_descriptor_DEFINED
-# define pdf_font_descriptor_DEFINED
-typedef struct pdf_font_descriptor_s pdf_font_descriptor_t;
-#endif
-typedef struct pdf_std_font_s {
- gs_font *font; /* weak pointer, may be 0 */
- pdf_font_descriptor_t *pfd; /* *not* a weak pointer */
- gs_matrix orig_matrix;
- gs_uid uid; /* UniqueID, not XUID */
-} pdf_std_font_t;
-typedef struct pdf_text_state_s {
- /* State parameters */
- float character_spacing; /* Tc */
- pdf_font_t *font; /* for Tf */
- floatp size; /* for Tf */
- float word_spacing; /* Tw */
- float leading; /* TL */
- bool use_leading; /* true => use ', false => use Tj */
- int render_mode; /* Tr */
- /* Bookkeeping */
- gs_matrix matrix; /* relative to device space, not user space */
- gs_point line_start;
- gs_point current;
-#define max_text_buffer 200 /* arbitrary, but overflow costs 5 chars */
- byte buffer[max_text_buffer];
- int buffer_count;
-} pdf_text_state_t;
-
-#define pdf_text_state_default\
- 0, NULL, 0, 0, 0, 0 /*false*/, 0,\
- { identity_matrix_body }, { 0, 0 }, { 0, 0 }, { 0 }, 0
-
/* Resource lists */
#define NUM_RESOURCE_CHAINS 16
typedef struct pdf_resource_list_s {
@@ -421,10 +372,6 @@ struct gx_device_pdf_s {
* EP nest, we delete the object from the pictures file at that time.
*/
pdf_temp_file_t pictures;
- pdf_font_t *open_font; /* current Type 3 synthesized font */
- bool use_open_font; /* if false, start new open_font */
- long embedded_encoding_id;
- int max_embedded_code; /* max Type 3 code used */
long random_offset; /* for generating subset prefixes */
/* ................ */
long next_id;
@@ -441,9 +388,7 @@ struct gx_device_pdf_s {
long contents_length_id;
long contents_pos;
pdf_procset_t procsets; /* used on this page */
- pdf_text_state_t text;
- pdf_std_font_t std_fonts[PDF_NUM_STD_FONTS];
- long space_char_ids[X_SPACE_MAX - X_SPACE_MIN + 1];
+ pdf_text_data_t *text;
pdf_text_rotation_t text_rotation;
#define initial_num_pages 50
pdf_page_t *pages;
@@ -474,14 +419,13 @@ struct gx_device_pdf_s {
m(0,asides.strm) m(1,asides.strm_buf) m(2,asides.save_strm)\
m(3,streams.strm) m(4,streams.strm_buf)\
m(5,pictures.strm) m(6,pictures.strm_buf) m(7,pictures.save_strm)\
- m(8,open_font)\
- m(9,Catalog) m(10,Info) m(11,Pages)\
- m(12,text.font) m(13,pages)\
- m(14,cs_Patterns[0])\
- m(15,cs_Patterns[1]) m(16,cs_Patterns[3]) m(17,cs_Patterns[4])\
- m(18,last_resource)\
- m(19,articles) m(20,Dests) m(21,named_objects) m(22,open_graphics)
-#define gx_device_pdf_num_ptrs 23
+ m(8,Catalog) m(9,Info) m(10,Pages)\
+ m(11,text) m(12,pages)\
+ m(13,cs_Patterns[0])\
+ m(14,cs_Patterns[1]) m(15,cs_Patterns[3]) m(16,cs_Patterns[4])\
+ m(17,last_resource)\
+ m(18,articles) m(19,Dests) m(20,named_objects) m(21,open_graphics)
+#define gx_device_pdf_num_ptrs 22
#define gx_device_pdf_do_strings(m) /* do nothing */
#define gx_device_pdf_num_strings 0
#define st_device_pdf_max_ptrs\
@@ -842,4 +786,44 @@ int pdf_scan_token_composite(P3(const byte **pscan, const byte * end,
int pdf_replace_names(P3(gx_device_pdf *pdev, const gs_param_string *from,
gs_param_string *to));
+/* ================ Text module procedures ================ */
+
+/* ---------------- Exported by gdevpdfw.c ---------------- */
+
+/* For gdevpdf.c */
+
+/* Write out the font resources when wrapping up the output. */
+int pdf_write_font_resources(P1(gx_device_pdf *pdev));
+
+/* ---------------- Exported by gdevpdft.c ---------------- */
+
+/* For gdevpdf.c */
+
+pdf_text_data_t *pdf_text_data_alloc(gs_memory_t *mem);
+void pdf_reset_text_page(pdf_text_data_t *ptd);
+void pdf_reset_text_state(pdf_text_data_t *ptd);
+void pdf_close_text_page(gx_device_pdf *pdev);
+
+/* For gdevpdfb.c */
+
+int pdf_char_image_y_offset(const gx_device_pdf *pdev, int x, int y, int h);
+
+/* Begin a CharProc for an embedded (bitmap) font. */
+int pdf_begin_char_proc(P8(gx_device_pdf * pdev, int w, int h, int x_width,
+ int y_offset, gs_id id, pdf_char_proc_t **ppcp,
+ pdf_stream_position_t * ppos));
+
+/* End a CharProc. */
+int pdf_end_char_proc(P2(gx_device_pdf * pdev, pdf_stream_position_t * ppos));
+
+/* Put out a reference to an image as a character in an embedded font. */
+int pdf_do_char_image(P3(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
+ const gs_matrix * pimat));
+
+/* For gdevpdfu.c */
+
+void pdf_from_stream_to_text(gx_device_pdf *pdev);
+void pdf_from_string_to_text(gx_device_pdf *pdev);
+void pdf_close_text_contents(gx_device_pdf *pdev);
+
#endif /* gdevpdfx_INCLUDED */