summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2011-04-29 16:42:30 +0100
committerKen Sharp <ken.sharp@artifex.com>2011-04-29 16:42:30 +0100
commit947e90ad0229b6333d6eb61e7f54ac33b200ab28 (patch)
treedf392ae62ad81fdeb2d775c6a1369b9689995dac
parent1553ea878b414b4ac389f7cec4c2076bc52be966 (diff)
downloadghostpdl-Type3_PCL.tar.gz
initial changes for capturing PCL type 3 fonts in pdfwriteType3_PCL
Seems to be OK now with PS/PCL, does not crash any longer with PCL, but capture is incorrect.
-rw-r--r--gs/base/gdevpdfb.c48
-rw-r--r--gs/base/gdevpdfb.h1
-rw-r--r--gs/base/gdevpdfx.h118
-rw-r--r--gs/base/gdevpdti.c26
-rw-r--r--gs/base/gdevpdtt.c493
-rw-r--r--gs/base/gdevpdtt.h4
6 files changed, 464 insertions, 226 deletions
diff --git a/gs/base/gdevpdfb.c b/gs/base/gdevpdfb.c
index 6008cd592..2220d4c69 100644
--- a/gs/base/gdevpdfb.c
+++ b/gs/base/gdevpdfb.c
@@ -18,14 +18,14 @@
#include "gserrors.h"
#include "gdevpdfx.h"
#include "gdevpdfg.h"
-#include "gdevpdfo.h" /* for data stream */
+#include "gdevpdfo.h" /* for data stream */
#include "gxcspace.h"
#include "gxdcolor.h"
#include "gxpcolor.h"
#include "gxhldevc.h"
#include "gxchar.h"
-#include "gdevpdtf.h" /* Required to include gdevpdti.h */
-#include "gdevpdti.h" /* For pdf_charproc_x_offset */
+#include "gdevpdtf.h" /* Required to include gdevpdti.h */
+#include "gdevpdti.h" /* For pdf_charproc_x_offset */
#include "gsptype1.h"
/* We need this color space type for constructing temporary color spaces. */
@@ -140,6 +140,30 @@ pdf_copy_mono(gx_device_pdf *pdev,
int x_offset, y_offset;
double width;
+ if(id != gx_no_bitmap_id && sourcex == 0 && show_enum &&
+ pdev->type3_accum_status == 1)
+ {
+ /* We should only get here if we had started accumulating a type 3 CharProc
+ * but ended up rendering an existing cached glyph. This can happen if
+ * we glyphshow a type 3 glyph, and the glyph does not exist so we use
+ * the /.notdef *and* we've already cached the /.notdef. In this case
+ * we want to abort the charproc accumulation.
+ * Ideally we would note that in the text enumerator, but that's a
+ * pdfwrite text enumerator, and we can't access that here. So in a
+ * rather kludgy manner we pas the status to and fro via the device.
+ * QL CET 136-01.ps exhibits this.
+ */
+ pdf_resource_t *pres = pdev->accumulating_substream_resource;
+
+ code = pdf_exit_substream(pdev);
+ if (code < 0)
+ return code;
+ code = pdf_cancel_resource(pdev, pres, resourceCharProc);
+ if (code < 0)
+ return code;
+ pdf_forget_resource(pdev, pres, resourceCharProc);
+ pdev->type3_accum_status = 2;
+ }
/* Update clipping. */
if (pdf_must_put_clip_path(pdev, pcpath)) {
code = pdf_open_page(pdev, PDF_IN_STREAM);
@@ -162,7 +186,7 @@ pdf_copy_mono(gx_device_pdf *pdev,
else
pdev->char_width.x = fixed2float(show_enum->wxy.x);
pres = pdf_find_resource_by_gs_id(pdev, resourceCharProc, id);
- if (pres == 0) { /* Define the character in an embedded font. */
+ if (pres == 0) { /* Define the character in an embedded font. */
gs_image_t_init_mask(&image, false);
invert = 0xff;
x_offset = x - (int)show_enum->pis->current_point.x;
@@ -318,7 +342,7 @@ pdf_copy_mono(gx_device_pdf *pdev,
pdf_end_image_binary(pdev, &writer, writer.height);
if (!pres) {
switch ((code = pdf_end_write_image(pdev, &writer))) {
- default: /* error */
+ default: /* error */
return code;
case 1:
return 0;
@@ -327,11 +351,11 @@ pdf_copy_mono(gx_device_pdf *pdev,
true);
}
}
- writer.end_string = ""; /* no Q */
+ writer.end_string = ""; /* no Q */
switch ((code = pdf_end_write_image(pdev, &writer))) {
- default: /* error */
+ default: /* error */
return code;
- case 0: /* not possible */
+ case 0: /* not possible */
return_error(gs_error_Fatal);
case 1:
break;
@@ -383,7 +407,7 @@ pdf_copy_color_data(gx_device_pdf * pdev, const byte * base, int sourcex,
bool in_line;
if (code < 0)
- return code; /* can't happen */
+ return code; /* can't happen */
gs_image_t_init(pim, pcs);
pdf_make_bitmap_image(pim, x, y, w, h);
pim->BitsPerComponent = 8;
@@ -466,7 +490,7 @@ gdev_pdf_copy_color(gx_device * dev, const byte * base, int sourcex,
&image, &writer, 0);
switch (code) {
default:
- return code; /* error */
+ return code; /* error */
case 1:
return 0;
case 0:
@@ -598,10 +622,10 @@ gdev_pdf_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
tile_id, 0, 0, tw, th, &image, &writer, -1);
switch (code) {
default:
- return code; /* error */
+ return code; /* error */
case 1:
break;
- case 0: /* not possible */
+ case 0: /* not possible */
return_error(gs_error_Fatal);
}
end = pdf_stell(pdev);
diff --git a/gs/base/gdevpdfb.h b/gs/base/gdevpdfb.h
index 7e4a094e1..840189f92 100644
--- a/gs/base/gdevpdfb.h
+++ b/gs/base/gdevpdfb.h
@@ -233,6 +233,7 @@ const gx_device_pdf PDF_DEVICE_IDENT =
0, /* accumulating_substream_resource */
{0,0,0,0,0,0,0,0,0}, /* charproc_ctm */
0, /* charproc_just_accumulated */
+ 0, /* type3_accum_status */
0, /* accumulating_a_global_object */
0, /* cgp */
0, /* substituted_pattern_count */
diff --git a/gs/base/gdevpdfx.h b/gs/base/gdevpdfx.h
index bd3c1b5a9..5d9f2ebe0 100644
--- a/gs/base/gdevpdfx.h
+++ b/gs/base/gdevpdfx.h
@@ -134,7 +134,7 @@ typedef enum {
resourceMetadata,
resourceICC,
resourceAnnotation,
- resourceNone /* Special, used when this isn't a resource at all
+ resourceNone /* Special, used when this isn't a resource at all
* eg when we execute a resource we've just written, such as
* a Pattern.
*/
@@ -145,17 +145,17 @@ typedef enum {
0, "/Font", "/CMap", "/FontDescriptor", "/Group", "/Mask", 0, 0, 0, 0, 0,\
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
#define PDF_RESOURCE_TYPE_STRUCTS\
- &st_pdf_color_space, /* gdevpdfg.h / gdevpdfc.c */\
- &st_pdf_resource, /* see below */\
+ &st_pdf_color_space, /* gdevpdfg.h / gdevpdfc.c */\
+ &st_pdf_resource, /* see below */\
&st_pdf_pattern,\
&st_pdf_resource,\
- &st_pdf_x_object, /* see below */\
+ &st_pdf_x_object, /* see below */\
&st_pdf_resource,\
- &st_pdf_font_resource, /* gdevpdff.h / gdevpdff.c */\
- &st_pdf_char_proc, /* gdevpdff.h / gdevpdff.c */\
- &st_pdf_font_resource, /* gdevpdff.h / gdevpdff.c */\
+ &st_pdf_font_resource, /* gdevpdff.h / gdevpdff.c */\
+ &st_pdf_char_proc, /* gdevpdff.h / gdevpdff.c */\
+ &st_pdf_font_resource, /* gdevpdff.h / gdevpdff.c */\
&st_pdf_resource,\
- &st_pdf_font_descriptor, /* gdevpdff.h / gdevpdff.c */\
+ &st_pdf_font_descriptor, /* gdevpdff.h / gdevpdff.c */\
&st_pdf_resource,\
&st_pdf_resource,\
&st_pdf_resource,\
@@ -167,13 +167,13 @@ typedef enum {
*/
#define pdf_resource_common(typ)\
- typ *next; /* next resource of this type */\
- pdf_resource_t *prev; /* previously allocated resource */\
- gs_id rid; /* optional ID key */\
+ typ *next; /* next resource of this type */\
+ pdf_resource_t *prev; /* previously allocated resource */\
+ gs_id rid; /* optional ID key */\
bool named;\
bool global; /* ps2write only */\
char rname[1/*R*/ + (sizeof(long) * 8 / 3 + 1) + 1/*\0*/];\
- ulong where_used; /* 1 bit per level of content stream */\
+ ulong where_used; /* 1 bit per level of content stream */\
cos_object_t *object
typedef struct pdf_resource_s pdf_resource_t;
struct pdf_resource_s {
@@ -193,8 +193,8 @@ extern_st(st_pdf_resource);
typedef struct pdf_x_object_s pdf_x_object_t;
struct pdf_x_object_s {
pdf_resource_common(pdf_x_object_t);
- int width, height; /* specified width and height for images */
- int data_height; /* actual data height for images */
+ int width, height; /* specified width and height for images */
+ int data_height; /* actual data height for images */
};
#define private_st_pdf_x_object() /* in gdevpdfu.c */\
gs_private_st_suffix_add0(st_pdf_x_object, pdf_x_object_t,\
@@ -213,8 +213,8 @@ typedef enum {
/* ------ Fonts ------ */
/* Define abstract types. */
-typedef struct pdf_char_proc_s pdf_char_proc_t; /* gdevpdff.h */
-typedef struct pdf_char_proc_ownership_s pdf_char_proc_ownership_t; /* gdevpdff.h */
+typedef struct pdf_char_proc_s pdf_char_proc_t; /* gdevpdff.h */
+typedef struct pdf_char_proc_ownership_s pdf_char_proc_ownership_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 */
@@ -280,8 +280,8 @@ typedef struct pdf_stream_position_s {
* and one for the whole document (for AutoRotate /All).
*/
typedef struct pdf_text_rotation_s {
- long counts[5]; /* 0, 90, 180, 270, other */
- int Rotate; /* computed rotation, -1 means none */
+ long counts[5]; /* 0, 90, 180, 270, other */
+ int Rotate; /* computed rotation, -1 means none */
} pdf_text_rotation_t;
#define pdf_text_rotation_angle_values 0, 90, 180, 270, -1
@@ -289,8 +289,8 @@ typedef struct pdf_text_rotation_s {
* Define document and page information derived from DSC comments.
*/
typedef struct pdf_page_dsc_info_s {
- int orientation; /* -1 .. 3 */
- int viewing_orientation; /* -1 .. 3 */
+ int orientation; /* -1 .. 3 */
+ int viewing_orientation; /* -1 .. 3 */
gs_rect bounding_box;
} pdf_page_dsc_info_t;
@@ -312,7 +312,7 @@ typedef struct pdf_page_s {
bool NumCopies_set; /* ps2write only. */
int NumCopies; /* ps2write only. */
} pdf_page_t;
-#define private_st_pdf_page() /* in gdevpdf.c */\
+#define private_st_pdf_page() /* in gdevpdf.c */\
gs_private_st_ptrs2(st_pdf_page, pdf_page_t, "pdf_page_t",\
pdf_page_enum_ptrs, pdf_page_reloc_ptrs, Page, Annots)
@@ -325,7 +325,7 @@ typedef struct pdf_temp_file_s {
FILE *file;
stream *strm;
byte *strm_buf;
- stream *save_strm; /* save pdev->strm while writing here */
+ stream *save_strm; /* save pdev->strm while writing here */
} pdf_temp_file_t;
#ifndef gx_device_pdf_DEFINED
@@ -340,12 +340,12 @@ typedef struct pdf_font_cache_elem_s pdf_font_cache_elem_t;
struct pdf_font_cache_elem_s {
pdf_font_cache_elem_t *next;
gs_id font_id;
- int num_chars; /* safety purpose only */
- int num_widths; /* safety purpose only */
+ int num_chars; /* safety purpose only */
+ int num_widths; /* safety purpose only */
struct pdf_font_resource_s *pdfont;
byte *glyph_usage;
- double *real_widths; /* [count] (not used for Type 0) */
- gx_device_pdf *pdev; /* For pdf_remove_font_cache_elem */
+ double *real_widths; /* [count] (not used for Type 0) */
+ gx_device_pdf *pdev; /* For pdf_remove_font_cache_elem */
};
#define private_st_pdf_font_cache_elem()\
@@ -360,7 +360,7 @@ struct pdf_font_cache_elem_s {
* immediately when it is generated.
*/
typedef struct pdf_viewer_state_s {
- int transfer_not_identity; /* bitmask */
+ int transfer_not_identity; /* bitmask */
gs_id transfer_ids[4];
float opacity_alpha; /* state.opacity.alpha */
float shape_alpha; /* state.shape.alpha */
@@ -389,22 +389,22 @@ typedef struct pdf_viewer_state_s {
* a contents stream accumulation mode (charproc, Type 1 pattern).
*/
typedef struct pdf_substream_save_s {
- pdf_context_t context;
- pdf_text_state_t *text_state;
- gx_path *clip_path;
- gs_id clip_path_id;
- int vgstack_bottom;
- stream *strm;
- cos_dict_t *substream_Resources;
- pdf_procset_t procsets;
- bool skip_colors;
+ pdf_context_t context;
+ pdf_text_state_t *text_state;
+ gx_path *clip_path;
+ gs_id clip_path_id;
+ int vgstack_bottom;
+ stream *strm;
+ cos_dict_t *substream_Resources;
+ pdf_procset_t procsets;
+ bool skip_colors;
pdf_resource_t *font3;
- pdf_resource_t *accumulating_substream_resource;
- bool charproc_just_accumulated;
- bool accumulating_a_global_object;
+ pdf_resource_t *accumulating_substream_resource;
+ bool charproc_just_accumulated;
+ bool accumulating_a_global_object;
pdf_resource_t *pres_soft_mask_dict;
- gs_const_string objname;
- int last_charpath_op;
+ gs_const_string objname;
+ int last_charpath_op;
} pdf_substream_save;
#define private_st_pdf_substream_save()\
@@ -419,7 +419,7 @@ typedef struct pdf_substream_save_s {
typedef enum {
pdf_compress_none,
- pdf_compress_LZW, /* not currently used, thanks to Unisys */
+ pdf_compress_LZW, /* not currently used, thanks to Unisys */
pdf_compress_Flate
} pdf_compression_type;
@@ -461,13 +461,13 @@ struct gx_device_pdf_s {
bool ResourcesBeforeUsage; /* PS2WRITE only. */
bool HavePDFWidths; /* PS2WRITE only. */
bool HaveStrokeColor; /* PS2WRITE only. */
- bool ProduceDSC; /* PS2WRITE only. */
+ bool ProduceDSC; /* PS2WRITE only. */
bool HaveTransparency;
bool PatternImagemask; /* The target viewer|printer handles imagemask
with pattern color. */
- bool PDFX; /* Generate PDF/X */
- bool PDFA; /* Generate PDF/A */
- bool AbortPDFAX; /* Abort generation of PDFA or X, produce regular PDF */
+ bool PDFX; /* Generate PDF/X */
+ bool PDFA; /* Generate PDF/A */
+ bool AbortPDFAX; /* Abort generation of PDFA or X, produce regular PDF */
long MaxClipPathSize; /* The maximal number of elements of a clipping path
that the target viewer|printer can handle. */
long MaxViewerMemorySize;
@@ -500,7 +500,7 @@ struct gx_device_pdf_s {
int overprint_mode;
gs_id halftone_id;
gs_id transfer_ids[4];
- int transfer_not_identity; /* bitmask */
+ int transfer_not_identity; /* bitmask */
gs_id black_generation_id, undercolor_removal_id;
/* Following are set when device is opened. */
pdf_compression_type compression;
@@ -549,13 +549,13 @@ struct gx_device_pdf_s {
pdf_context_t context;
long contents_length_id;
long contents_pos;
- pdf_procset_t procsets; /* used on this page */
+ pdf_procset_t procsets; /* used on this page */
pdf_text_data_t *text;
pdf_text_rotation_t text_rotation;
#define initial_num_pages 50
pdf_page_t *pages;
int num_pages;
- ulong used_mask; /* for where_used: page level = 1 */
+ ulong used_mask; /* for where_used: page level = 1 */
pdf_resource_list_t resources[NUM_RESOURCE_TYPES];
/* cs_Patterns[0] is colored; 1,3,4 are uncolored + Gray,RGB,CMYK */
pdf_resource_t *cs_Patterns[5];
@@ -628,7 +628,7 @@ struct gx_device_pdf_s {
*/
pdf_viewer_state vgstack[11];
int vgstack_depth;
- int vgstack_bottom; /* Stack bottom for the current substream. */
+ int vgstack_bottom; /* Stack bottom for the current substream. */
pdf_viewer_state vg_initial; /* Initial values for viewer's graphic state */
bool vg_initial_set;
@@ -657,6 +657,10 @@ struct gx_device_pdf_s {
bool charproc_just_accumulated; /* A flag for controlling
the glyph variation recognition.
Used only with uncached charprocs. */
+ int type3_accum_status; /* This is just a means of passing the status of the
+ * type 3 font accumulator which is stored in a
+ * pdfwrite text enumerator to pdf_copy_mono, in case
+ * we want to abort the accumulation. */
bool accumulating_a_global_object; /* ps2write only.
Accumulating a global object (such as a named Form,
so that resources used in it must also be global.
@@ -742,7 +746,7 @@ struct gx_device_pdf_s {
NUM_RESOURCE_TYPES * NUM_RESOURCE_CHAINS /* resources[].chains[] */ +\
MAX_OUTLINE_DEPTH * 2 /* outline_levels[].{first,last}.action */
-#define private_st_device_pdfwrite() /* in gdevpdf.c */\
+#define private_st_device_pdfwrite() /* in gdevpdf.c */\
gs_private_st_composite_final(st_device_pdfwrite, gx_device_pdf,\
"gx_device_pdf", device_pdfwrite_enum_ptrs, device_pdfwrite_reloc_ptrs,\
device_pdfwrite_finalize)
@@ -1017,7 +1021,7 @@ void pdf_remove_masked_image_converter(gx_device_pdf *pdev, pdf_lcvd_t *cvd, boo
/* ------ Miscellaneous output ------ */
-#define PDF_MAX_PRODUCER 200 /* adhoc */
+#define PDF_MAX_PRODUCER 200 /* adhoc */
/* Generate the default Producer string. */
void pdf_store_default_Producer(char buf[PDF_MAX_PRODUCER]);
@@ -1079,10 +1083,10 @@ typedef struct pdf_data_writer_s {
* the << and any desired dictionary keys.
*/
#define DATA_STREAM_NOT_BINARY 0 /* data are text, not binary */
-#define DATA_STREAM_BINARY 1 /* data are binary */
-#define DATA_STREAM_COMPRESS 2 /* OK to compress data */
-#define DATA_STREAM_NOLENGTH 4 /* Skip the length reference and filter names writing. */
-#define DATA_STREAM_ENCRYPT 8 /* Encrypt data. */
+#define DATA_STREAM_BINARY 1 /* data are binary */
+#define DATA_STREAM_COMPRESS 2 /* OK to compress data */
+#define DATA_STREAM_NOLENGTH 4 /* Skip the length reference and filter names writing. */
+#define DATA_STREAM_ENCRYPT 8 /* Encrypt data. */
int pdf_begin_data_stream(gx_device_pdf *pdev, pdf_data_writer_t *pdw,
int options, gs_id object_id);
int pdf_append_data_stream_filters(gx_device_pdf *pdev, pdf_data_writer_t *pdw,
@@ -1277,7 +1281,7 @@ int pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
int pdf_start_charproc_accum(gx_device_pdf *pdev);
/* Install charproc accumulator for a Type 3 font. */
int pdf_set_charproc_attrs(gx_device_pdf *pdev, gs_font *font, const double *pw, int narg,
- gs_text_cache_control_t control, gs_char ch);
+ gs_text_cache_control_t control, gs_char ch, bool scale_100);
/* Complete charproc accumulation for aType 3 font. */
int pdf_end_charproc_accum(gx_device_pdf *pdev, gs_font *font, const pdf_char_glyph_pairs_t *cgp,
gs_glyph glyph, gs_char output_char_code, const gs_const_string *gnstr);
diff --git a/gs/base/gdevpdti.c b/gs/base/gdevpdti.c
index 7e702af3e..18a45fc3e 100644
--- a/gs/base/gdevpdti.c
+++ b/gs/base/gdevpdti.c
@@ -26,7 +26,7 @@
#include "gdevpdtw.h"
#include "gdevpdtt.h"
#include "gdevpdfo.h"
-#include "gxchar.h" /* For gs_show_enum */
+#include "gxchar.h" /* For gs_show_enum */
/* ---------------- Private ---------------- */
@@ -35,10 +35,10 @@
struct pdf_char_proc_s {
pdf_resource_common(pdf_char_proc_t);
pdf_char_proc_ownership_t *owner_fonts; /* fonts using this charproc. */
- int y_offset; /* of character (0,0) */
- int x_offset; /* of character (0,0) */
+ int y_offset; /* of character (0,0) */
+ int x_offset; /* of character (0,0) */
gs_point real_width; /* Not used with synthesised bitmap fonts. */
- gs_point v; /* Not used with synthesised bitmap fonts. */
+ gs_point v; /* Not used with synthesised bitmap fonts. */
};
/* The descriptor is public for pdf_resource_type_structs. */
@@ -48,11 +48,11 @@ gs_public_st_suffix_add1(st_pdf_char_proc, pdf_char_proc_t,
struct pdf_char_proc_ownership_s {
pdf_char_proc_t *char_proc;
- pdf_char_proc_ownership_t *font_next; /* next char_proc for same font */
- pdf_char_proc_ownership_t *char_next; /* next char_proc for same charproc */
+ pdf_char_proc_ownership_t *font_next; /* next char_proc for same font */
+ pdf_char_proc_ownership_t *char_next; /* next char_proc for same charproc */
pdf_font_resource_t *font;
- gs_char char_code; /* Character code in PDF font. */
- gs_glyph glyph; /* Glyph id in Postscript font. */
+ gs_char char_code; /* Character code in PDF font. */
+ gs_glyph glyph; /* Glyph id in Postscript font. */
gs_const_string char_name;
bool duplicate_char_name;
};
@@ -563,7 +563,7 @@ pdf_start_charproc_accum(gx_device_pdf *pdev)
*/
int
pdf_set_charproc_attrs(gx_device_pdf *pdev, gs_font *font, const double *pw, int narg,
- gs_text_cache_control_t control, gs_char ch)
+ gs_text_cache_control_t control, gs_char ch, bool scale_100)
{
pdf_font_resource_t *pdfont;
pdf_resource_t *pres = pdev->accumulating_substream_resource;
@@ -599,9 +599,11 @@ pdf_set_charproc_attrs(gx_device_pdf *pdev, gs_font *font, const double *pw, int
* operator. We write the scale matrix here because this is *after* the
* 'd1' has been emitted above, and so does not affect it.
*/
- code = stream_puts(pdev->strm, "0.01 0 0 0.01 0 0 cm\n");
- if (code < 0)
- return code;
+ if (scale_100) {
+ code = stream_puts(pdev->strm, "0.01 0 0 0.01 0 0 cm\n");
+ if (code < 0)
+ return code;
+ }
return 0;
}
diff --git a/gs/base/gdevpdtt.c b/gs/base/gdevpdtt.c
index 6f0343226..9b40c9522 100644
--- a/gs/base/gdevpdtt.c
+++ b/gs/base/gdevpdtt.c
@@ -22,13 +22,13 @@
#include "gscedata.h"
#include "gsmatrix.h"
#include "gzstate.h"
-#include "gxfcache.h" /* for orig_fonts list */
+#include "gxfcache.h" /* for orig_fonts list */
#include "gxfont.h"
#include "gxfont0.h"
#include "gxfcid.h"
#include "gxfcopy.h"
#include "gxfcmap.h"
-#include "gxpath.h" /* for getting current point */
+#include "gxpath.h" /* for getting current point */
#include "gxchar.h"
#include "gxstate.h"
#include "gdevpdfx.h"
@@ -95,6 +95,7 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
gs_text_cache_control_t control)
{
pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
+ gs_text_enum_t *pgste;
gx_device_pdf *pdev = (gx_device_pdf *)pte->dev;
gs_matrix m;
@@ -108,8 +109,13 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
* NOT the identity, but we want the cache device values to be in
* font co-ordinate space, so we need to undo that scale here.
*/
- gs_matrix_scale(&ctm_only(pte->pis), .01, .01, &m);
- gs_distance_transform(pw[0], pw[1], &m, &pdev->char_width);
+ if (penum->pte_default != NULL){
+ gs_matrix_scale(&ctm_only(pte->pis), .01, .01, &m);
+ gs_distance_transform(pw[0], pw[1], &m, &pdev->char_width);
+ } else {
+ pdev->char_width.x = pw[0];
+ pdev->char_width.y = pw[1];
+ }
break;
case TEXT_SET_CACHE_DEVICE2:
/*
@@ -122,8 +128,13 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
* NOT the identity, but we want the cache device values to be in
* font co-ordinate space, so we need to undo that scale here.
*/
- gs_matrix_scale(&ctm_only(pte->pis), .01, .01, &m);
- gs_distance_transform(pw[0], pw[1], &m, &pdev->char_width);
+ if (penum->pte_default != NULL){
+ gs_matrix_scale(&ctm_only(pte->pis), .01, .01, &m);
+ gs_distance_transform(pw[0], pw[1], &m, &pdev->char_width);
+ } else {
+ pdev->char_width.x = pw[0];
+ pdev->char_width.y = pw[1];
+ }
if (penum->cdevproc_callout) {
memcpy(penum->cdevproc_result, pw, sizeof(penum->cdevproc_result));
return 0;
@@ -133,11 +144,14 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
return_error(gs_error_rangecheck);
}
if (penum->pte_default == NULL)
- return_error(gs_error_unregistered); /* Must not happen. */
+ pgste = (gs_text_enum_t *)penum;
+ else
+ pgste = penum->pte_default;
+// return_error(gs_error_unregistered); /* Must not happen. */
if (penum->current_font->FontType == ft_user_defined &&
penum->outer_CID == GS_NO_GLYPH &&
- !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) {
+ !(pgste->text.operation & TEXT_DO_CHARWIDTH)) {
int code;
gs_glyph glyph;
@@ -151,12 +165,12 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
control == TEXT_SET_CACHE_DEVICE ? 6 : 10), i;
/* Check to verify the structure type is really gs_show_enum */
- if (gs_object_type(penum->pte_default->memory, penum->pte_default) != &st_gs_show_enum) {
+ if (gs_object_type(pgste->memory, pgste) != &st_gs_show_enum) {
/* Must not happen with PS interpreter.
Other clients should conform. */
return_error(gs_error_unregistered);
}
- penum_s = (gs_show_enum *)penum->pte_default;
+ penum_s = (gs_show_enum *)pgste;
/* BuildChar could change the scale before calling setcachedevice (Bug 687290).
We must scale the setcachedevice arguments because we assumed
identity scale before entering the charproc.
@@ -198,16 +212,18 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
* needs to be in the 100x100 space so that it doesn't clip
* out marking operations.
*/
- gs_matrix_scale(&ctm_only(penum_s->pgs), .01, .01, &m);
- for (i = 0; i < narg; i += 2) {
- gs_point p;
-
- gs_point_transform(pw[i], pw[i + 1], &m, &p);
- pw1[i] = p.x;
- pw1[i + 1] = p.y;
+ if (penum->pte_default != NULL){
+ gs_matrix_scale(&ctm_only(penum_s->pgs), .01, .01, &m);
+ for (i = 0; i < narg; i += 2) {
+ gs_point p;
+
+ gs_point_transform(pw[i], pw[i + 1], &m, &p);
+ pw1[i] = p.x;
+ pw1[i + 1] = p.y;
+ }
}
code = pdf_set_charproc_attrs(pdev, pte->current_font,
- pw1, narg, control, penum->output_char_code);
+ pw1, narg, control, penum->output_char_code, penum->pte_default != NULL);
if (code < 0)
return code;
/* Prevent writing the clipping path to charproc.
@@ -250,7 +266,7 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
gs_matrix_multiply((gs_matrix *)&pdev->charproc_ctm, (gs_matrix *)&penum->pis->ctm, &m);
gs_matrix_fixed_from_matrix(&penum->pis->ctm, &m);
- penum->charproc_accum = false;
+ penum->charproc_accum = aborted;
}
}
if (penum->pte_default) {
@@ -408,7 +424,7 @@ gdev_pdf_text_begin(gx_device * dev, gs_imager_state * pis,
return_error(gs_error_VMerror), "gdev_pdf_text_begin");
penum->rc.free = rc_free_text_enum;
penum->pte_default = 0;
- penum->charproc_accum = false;
+ penum->charproc_accum = idle;
penum->cdevproc_callout = false;
penum->returned.total_width.x = penum->returned.total_width.y = 0;
penum->cgp = NULL;
@@ -459,7 +475,7 @@ gdev_pdf_text_begin(gx_device * dev, gs_imager_state * pis,
return_error(gs_error_VMerror), "gdev_pdf_text_begin");
penum->rc.free = rc_free_text_enum;
penum->pte_default = 0;
- penum->charproc_accum = false;
+ penum->charproc_accum = idle;
penum->cdevproc_callout = false;
penum->returned.total_width.x = penum->returned.total_width.y = 0;
penum->cgp = NULL;
@@ -503,17 +519,17 @@ pdf_font_cache_elem_id(gs_font *font)
{
#if 0
/*
- * For compatibility with Ghostscript rasterizer's
- * cache logic we use UniqueID to identify fonts.
+ * For compatibility with Ghostscript rasterizer's
+ * cache logic we use UniqueID to identify fonts.
* Note that with buggy documents, which don't
- * undefine UniqueID redefining a font,
- * Ghostscript PS interpreter can occasionaly
- * replace cache elements on insufficient cache size,
- * taking glyphs from random fonts with random metrics,
- * therefore the compatibility isn't complete.
+ * undefine UniqueID redefining a font,
+ * Ghostscript PS interpreter can occasionaly
+ * replace cache elements on insufficient cache size,
+ * taking glyphs from random fonts with random metrics,
+ * therefore the compatibility isn't complete.
*/
/*
- * This branch is incompatible with pdf_notify_remove_font.
+ * This branch is incompatible with pdf_notify_remove_font.
*/
if (font->FontType == ft_composite || font->PaintType != 0 ||
!uid_is_valid(&(((gs_font_base *)font)->UID)))
@@ -728,7 +744,7 @@ int
pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat)
{
switch (font->FontType) {
- case ft_composite: /* subfonts have their own FontMatrix */
+ case ft_composite: /* subfonts have their own FontMatrix */
case ft_TrueType:
case ft_CID_TrueType:
/* The TrueType FontMatrix is 1 unit per em, which is what we want. */
@@ -747,7 +763,7 @@ pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat)
* replacing FontMatrix like this :
*
* /f12 /Times-Roman findfont
- * copyfont % (remove FID)
+ * copyfont % (remove FID)
* dup /FontMatrix [0.012 0 0 0.012 0 0] put
* definefont
* /f12 1 selectfont
@@ -1393,7 +1409,7 @@ pdf_next_char_glyph(gs_text_enum_t *penum, const gs_string *pstr,
{
int code = font->procs.next_char_glyph(penum, char_code, glyph);
- if (code == 2) /* end of string */
+ if (code == 2) /* end of string */
return code;
if (code < 0)
return code;
@@ -1561,9 +1577,9 @@ pdf_make_text_glyphs_table(pdf_text_enum_t *penum, const gs_string *pstr,
for (;;) {
code = pdf_next_char_glyph(&scan, pstr, font, font_is_simple,
&char_code, &cid, &glyph);
- if (code == 2) /* end of string */
+ if (code == 2) /* end of string */
break;
- if (code == 3) /* no glyph */
+ if (code == 3) /* no glyph */
continue;
if (code < 0)
return code;
@@ -1838,9 +1854,9 @@ pdf_mark_text_glyphs(const gs_text_enum_t *penum, const gs_string *pstr,
int code = pdf_next_char_glyph(&scan, pstr, font, font_is_simple,
&char_code, &cid, &glyph);
- if (code == 2) /* end of string */
+ if (code == 2) /* end of string */
break;
- if (code == 3) /* no glyph */
+ if (code == 3) /* no glyph */
continue;
if (code < 0)
return code;
@@ -2044,7 +2060,7 @@ transform_delta_inverse(const gs_point *pdelta, const gs_matrix *pmat,
/* Check for numerical fuzz. */
code = gs_distance_transform(ppt->x, 0.0, pmat, &delta);
if (code < 0)
- return 0; /* punt */
+ return 0; /* punt */
if (fabs(delta.x - pdelta->x) < 0.01 && fabs(delta.y - pdelta->y) < 0.01) {
/* Close enough to y == 0: device space error < 0.01 pixel. */
ppt->y = 0;
@@ -2210,7 +2226,7 @@ pdf_update_text_state(pdf_text_process_state_t *ppts,
*/
int
pdf_set_text_process_state(gx_device_pdf *pdev,
- const gs_text_enum_t *pte, /* for pdcolor, pis */
+ const gs_text_enum_t *pte, /* for pdcolor, pis */
pdf_text_process_state_t *ppts)
{
/*
@@ -2524,6 +2540,188 @@ pdf_default_text_begin(gs_text_enum_t *pte, const gs_text_params_t *text,
pte->memory, ppte);
}
+static int install_PS_charproc_accumulator(gx_device_pdf *pdev, gs_text_enum_t *pte,
+ gs_text_enum_t *pte_default, pdf_text_enum_t *const penum)
+{
+ int code;
+
+ penum->returned.current_char = pte_default->returned.current_char;
+ penum->returned.current_glyph = pte_default->returned.current_glyph;
+ pdev->charproc_ctm = penum->pis->ctm;
+ if (penum->current_font->FontType == ft_user_defined &&
+ penum->outer_CID == GS_NO_GLYPH &&
+ !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) {
+ /* The condition above must be consistent with one in pdf_text_set_cache,
+ which decides to apply pdf_set_charproc_attrs. */
+ gs_matrix m;
+ pdf_font_resource_t *pdfont;
+
+ code = pdf_start_charproc_accum(pdev);
+ if (code < 0)
+ return code;
+
+ /* We need to give FreeType some room for accuracy when
+ * retrieving the outline. We will use a scale factor of 100
+ * (see below). Because this appears to the regular path
+ * handling code as if it were at the page level, the co-ords
+ * would be clipped frequently, so we temporarily hack the
+ * width and height of the device here to ensure it doesn't.
+ * Note that this requires some careful manipulation of the
+ * CTM in various places, which want numbers in the font
+ * co-ordinate space, not the scaled user space.
+ */
+ pdev->width *= 100;
+ pdev->height *= 100;
+
+ pdf_viewer_state_from_imager_state(pdev, pte->pis, pte->pdcolor);
+ /* Set line params to unallowed values so that
+ they'll synchronize with writing them out on the first use.
+ Doing so because PDF viewer inherits them from the
+ contents stream when executing the charproc,
+ but at this moment we don't know in what contexts
+ it will be used. */
+ pdev->state.line_params.half_width = -1;
+ pdev->state.line_params.start_cap = gs_cap_unknown;
+ pdev->state.line_params.end_cap = gs_cap_unknown;
+ pdev->state.line_params.dash_cap = gs_cap_unknown;
+ pdev->state.line_params.join = gs_join_unknown;
+ pdev->state.line_params.miter_limit = -1;
+ pdev->state.line_params.dash.pattern_size = -1;
+ /* Must set an identity CTM for the charproc accumulation.
+ The function show_proceed (called from gs_text_process above)
+ executed gsave, so we are safe to change CTM now.
+ Note that BuildChar may change CTM before calling setcachedevice. */
+ gs_make_identity(&m);
+ /* See comment above, we actually want to use a scale factor
+ * of 100 in order to give FreeType some room in the fixed
+ * precision calculations when retrieing the outline. So in
+ * fact we don't use the identity CTM, but a 100x100 matrix
+ * Originally tried 1000, but that was too likely to cause
+ * clipping or arithmetic overflow.
+ */
+ gs_matrix_scale(&m, 100, 100, &m);
+ gs_matrix_fixed_from_matrix(&penum->pis->ctm, &m);
+
+ /* Choose a character code to use with the charproc. */
+ code = pdf_choose_output_char_code(pdev, penum, &penum->output_char_code);
+ if (code < 0)
+ return code;
+ code = pdf_attached_font_resource(pdev, penum->current_font, &pdfont, NULL, NULL, NULL, NULL);
+ if (code < 0)
+ return code;
+ pdev->font3 = (pdf_resource_t *)pdfont;
+ pdev->substream_Resources = pdfont->u.simple.s.type3.Resources;
+ penum->charproc_accum = started;
+ return TEXT_PROCESS_RENDER;
+ }
+ return 0;
+}
+
+static int install_charproc_accumulator(gx_device_pdf *pdev, gs_text_enum_t *pte,
+ gs_text_enum_t *pte_default, pdf_text_enum_t *const penum)
+{
+ int code;
+
+ pdev->charproc_ctm = penum->pis->ctm;
+ if (penum->current_font->FontType == ft_user_defined &&
+ penum->outer_CID == GS_NO_GLYPH &&
+ !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) {
+ /* The condition above must be consistent with one in pdf_text_set_cache,
+ which decides to apply pdf_set_charproc_attrs. */
+ gs_matrix m;
+ pdf_font_resource_t *pdfont;
+
+ code = pdf_start_charproc_accum(pdev);
+ if (code < 0)
+ return code;
+
+ pdf_viewer_state_from_imager_state(pdev, pte->pis, pte->pdcolor);
+ /* Set line params to unallowed values so that
+ they'll synchronize with writing them out on the first use.
+ Doing so because PDF viewer inherits them from the
+ contents stream when executing the charproc,
+ but at this moment we don't know in what contexts
+ it will be used. */
+ pdev->state.line_params.half_width = -1;
+ pdev->state.line_params.start_cap = gs_cap_unknown;
+ pdev->state.line_params.end_cap = gs_cap_unknown;
+ pdev->state.line_params.dash_cap = gs_cap_unknown;
+ pdev->state.line_params.join = gs_join_unknown;
+ pdev->state.line_params.miter_limit = -1;
+ pdev->state.line_params.dash.pattern_size = -1;
+ /* Must set an identity CTM for the charproc accumulation.
+ The function show_proceed (called from gs_text_process above)
+ executed gsave, so we are safe to change CTM now.
+ Note that BuildChar may change CTM before calling setcachedevice. */
+ gs_make_identity(&m);
+
+ /* Choose a character code to use with the charproc. */
+ code = pdf_choose_output_char_code(pdev, penum, &penum->output_char_code);
+ if (code < 0)
+ return code;
+ code = pdf_attached_font_resource(pdev, penum->current_font, &pdfont, NULL, NULL, NULL, NULL);
+ if (code < 0)
+ return code;
+ pdev->font3 = (pdf_resource_t *)pdfont;
+ pdev->substream_Resources = pdfont->u.simple.s.type3.Resources;
+ penum->charproc_accum = started;
+ return TEXT_PROCESS_RENDER;
+ }
+ return 0;
+}
+
+static int complete_charproc(gx_device_pdf *pdev, gs_text_enum_t *pte,
+ gs_text_enum_t *pte_default, pdf_text_enum_t *const penum,
+ bool was_PS_type3)
+{
+ gs_const_string gnstr;
+ int code;
+
+ code = pdf_choose_output_glyph_hame(pdev, penum, &gnstr, pte_default->returned.current_glyph);
+ if (code < 0)
+ return code;
+
+ if ((penum->current_font->FontType == ft_user_defined) && stell(pdev->strm) == 0)
+ {
+ char glyph[256], FontName[gs_font_name_max + 1], KeyName[256];
+ int len;
+
+ len = min(gs_font_name_max, gnstr.size);
+ memcpy(glyph, gnstr.data, len);
+ glyph[len] = 0x00;
+ len = min(gs_font_name_max, penum->current_font->font_name.size);
+ memcpy(FontName, penum->current_font->font_name.chars, len);
+ FontName[len] = 0x00;
+ len = min(gs_font_name_max, penum->current_font->key_name.size);
+ memcpy(KeyName, penum->current_font->key_name.chars, len);
+ KeyName[len] = 0x00;
+
+ emprintf4(pdev->memory,
+ "ERROR: Page %d used undefined glyph '%s' from type 3 font '%s', key '%s'\n",
+ pdev->next_page, glyph, FontName, KeyName);
+ stream_puts(pdev->strm, "0 0 0 0 0 0 d1\n");
+ }
+
+ /* See below, we scaled the device height and width to prevent
+ * clipping of the CharProc operations, now we need to undo that.
+ */
+ pdev->width /= 100;
+ pdev->height /= 100;
+ code = pdf_end_charproc_accum(pdev, penum->current_font, penum->cgp,
+ pte_default->returned.current_glyph, penum->output_char_code, &gnstr);
+ if (code < 0)
+ return code;
+ penum->charproc_accum = idle;
+ if (penum->pte_default)
+ code = gx_default_text_restore_state(pte_default);
+ if (code < 0)
+ return code;
+ gs_text_release(pte_default, "pdf_text_process");
+ penum->pte_default = 0;
+
+ return 0;
+}
+
/*
* Continue processing text. This is the 'process' procedure in the text
* enumerator. Per the check in pdf_text_begin, we know the operation is
@@ -2539,7 +2737,7 @@ pdf_text_process(gs_text_enum_t *pte)
PROCESS_TEXT_PROC((*process));
int code;
gx_device_pdf *pdev = (gx_device_pdf *)penum->dev;
-#define BUF_SIZE 100 /* arbitrary > 0 */
+#define BUF_SIZE 100 /* arbitrary > 0 */
/* Use a union to ensure alignment. */
union bu_ {
byte bytes[BUF_SIZE];
@@ -2547,7 +2745,7 @@ pdf_text_process(gs_text_enum_t *pte)
gs_glyph glyphs[BUF_SIZE / sizeof(gs_glyph)];
} buf;
- if (!penum->pte_default && !penum->charproc_accum) {
+ if (!penum->pte_default && penum->charproc_accum != started) {
/* Don't need to sync before exiting charproc. */
code = pdf_prepare_text_drawing(pdev, pte);
if (code == gs_error_rangecheck) {
@@ -2568,11 +2766,11 @@ pdf_text_process(gs_text_enum_t *pte)
if (penum->current_font->FontType == ft_user_defined && (penum->text.operation & TEXT_DO_ANY_CHARPATH)
&& !pdev->type3charpath) {
pdev->type3charpath = true;
- if (!penum->charproc_accum)
+ if (penum->charproc_accum != started)
goto default_impl;
}
- code = -1; /* to force default implementation */
+ code = -1; /* to force default implementation */
/*
* If we fell back to the default implementation, continue using it.
@@ -2580,130 +2778,137 @@ pdf_text_process(gs_text_enum_t *pte)
top:
pte_default = penum->pte_default;
if (pte_default) {
- if (penum->charproc_accum) {
- gs_const_string gnstr;
+ gs_text_enum_procs_t *orig;
+ bool accumulator_started = 0;
- code = pdf_choose_output_glyph_hame(pdev, penum, &gnstr, pte_default->returned.current_glyph);
+ if (penum->charproc_accum == started) {
+ code = complete_charproc(pdev, pte, pte_default, penum, true);
if (code < 0)
return code;
- if ((penum->current_font->FontType == ft_user_defined) && stell(pdev->strm) == 0)
- {
- char glyph[256], FontName[gs_font_name_max + 1], KeyName[256];
- int len;
-
- len = min(gs_font_name_max, gnstr.size);
- memcpy(glyph, gnstr.data, len);
- glyph[len] = 0x00;
- len = min(gs_font_name_max, penum->current_font->font_name.size);
- memcpy(FontName, penum->current_font->font_name.chars, len);
- FontName[len] = 0x00;
- len = min(gs_font_name_max, penum->current_font->key_name.size);
- memcpy(KeyName, penum->current_font->key_name.chars, len);
- KeyName[len] = 0x00;
-
- emprintf4(pdev->memory,
- "ERROR: Page %d used undefined glyph '%s' from type 3 font '%s', key '%s'\n",
- pdev->next_page, glyph, FontName, KeyName);
- stream_puts(pdev->strm, "0 0 0 0 0 0 d1\n");
- }
-
- /* See below, we scaled the device height and width to prevent
- * clipping of the CharProc operations, now we need to undo that.
- */
- pdev->width /= 100;
- pdev->height /= 100;
- code = pdf_end_charproc_accum(pdev, penum->current_font, penum->cgp,
- pte_default->returned.current_glyph, penum->output_char_code, &gnstr);
- if (code < 0)
- return code;
- penum->charproc_accum = false;
- code = gx_default_text_restore_state(pte_default);
- if (code < 0)
- return code;
- gs_text_release(pte_default, "pdf_text_process");
- penum->pte_default = 0;
if (!pdev->type3charpath)
goto top;
else
goto default_impl;
}
+ /* We need to have any type 3 PCL font actually call the pdfwrite
+ * set_cache routine, so we need to patch that up here.
+ * (when using PS fonts, we have exited back to show and will rerun
+ * the CharProc in a 'pdfwrite' context). First save the existing
+ * set_cache.
+ */
+ orig = (gs_text_enum_procs_t *)pte_default->procs;
+ if (penum->current_font->FontType == ft_user_defined &&
+ penum->outer_CID == GS_NO_GLYPH &&
+ !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)
+ && !pdev->type3charpath && penum->charproc_accum == idle) {
+ gs_text_enum_procs_t special;
+
+ /* Now, patch the procs and start the accumulator */
+ special = *pte_default->procs;
+ special.set_cache = pdf_text_set_cache;
+ pte_default->procs = &special;
+
+// code = pdf_start_charproc_accum(pdev);
+
+ code = install_charproc_accumulator(pdev, pte, pte_default, penum);
+ if (code < 0)
+ return code;
+ penum->charproc_accum = started;
+ accumulator_started = 1;
+ }
+ /* Take note of the accumulator status in the enumerator. Its possible
+ * that we will end upusing a cached bitmap, in which case we will abort
+ * the accumulator. But the enumerator isn't available when we discover
+ * that we have a cached bitmap, so we need to store the status in
+ * the device.
+ */
+ pdev->type3_accum_status = penum->charproc_accum;
+ /* Now we run the default text procedure to see what ahppens. If its a
+ * PCL type 3 font or any non-type 3 PostScript font, then the glyph
+ * will be rendered. If its a PostScript type 3 font (and some other kinds)
+ * then it will return TEXT_PROCESS_RENDER and we need to exit
+ * to the interpreter to run the glyph description
+ */
pdev->pte = pte_default; /* CAUTION: See comment in gdevpdfx.h . */
code = gs_text_process(pte_default);
- pdev->pte = NULL; /* CAUTION: See comment in gdevpdfx.h . */
+ pdev->pte = NULL; /* CAUTION: See comment in gdevpdfx.h . */
pdev->charproc_just_accumulated = false;
+ /* Set the enumerator charproc accumulator to the same as the device one.
+ * If we aborted the accumulator because we were running a cached bitmap
+ * then we need to know so that we don't try and close it again.
+ */
+ penum->charproc_accum = pdev->type3_accum_status;
+ /* Put back the default set_cache, in case we had changed it. */
+ pte_default->procs = orig;
if (code == TEXT_PROCESS_RENDER && !pdev->type3charpath) {
- penum->returned.current_char = pte_default->returned.current_char;
- penum->returned.current_glyph = pte_default->returned.current_glyph;
- pdev->charproc_ctm = penum->pis->ctm;
- if (penum->current_font->FontType == ft_user_defined &&
- penum->outer_CID == GS_NO_GLYPH &&
- !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) {
- /* The condition above must be consistent with one in pdf_text_set_cache,
- which decides to apply pdf_set_charproc_attrs. */
- gs_matrix m;
- pdf_font_resource_t *pdfont;
-
- code = pdf_start_charproc_accum(pdev);
+ /* If we haven't already started the accumulator, then do so now */
+ if (penum->charproc_accum == idle){
+ code = install_PS_charproc_accumulator(pdev, pte, pte_default, penum);
if (code < 0)
return code;
-
- /* We need to give FreeType some room for accuracy when
- * retrieving the outline. We will use a scale factor of 100
- * (see below). Because this appears to the regular path
- * handling code as if it were at the page level, the co-ords
- * would be clipped frequently, so we temporarily hack the
- * width and height of the device here to ensure it doesn't.
- * Note that this requires some careful manipulation of the
- * CTM in various places, which want numbers in the font
- * co-ordinate space, not the scaled user space.
+ }else {
+ /* Otherwise, we did start it, but we actually want the more
+ * extensive PS/PDF handling. So first discard the existing one
*/
- pdev->width *= 100;
- pdev->height *= 100;
-
- pdf_viewer_state_from_imager_state(pdev, pte->pis, pte->pdcolor);
- /* Set line params to unallowed values so that
- they'll synchronize with writing them out on the first use.
- Doing so because PDF viewer inherits them from the
- contents stream when executing the charproc,
- but at this moment we don't know in what contexts
- it will be used. */
- pdev->state.line_params.half_width = -1;
- pdev->state.line_params.start_cap = gs_cap_unknown;
- pdev->state.line_params.end_cap = gs_cap_unknown;
- pdev->state.line_params.dash_cap = gs_cap_unknown;
- pdev->state.line_params.join = gs_join_unknown;
- pdev->state.line_params.miter_limit = -1;
- pdev->state.line_params.dash.pattern_size = -1;
- /* Must set an identity CTM for the charproc accumulation.
- The function show_proceed (called from gs_text_process above)
- executed gsave, so we are safe to change CTM now.
- Note that BuildChar may change CTM before calling setcachedevice. */
- gs_make_identity(&m);
- /* See comment above, we actually want to use a scale factor
- * of 100 in order to give FreeType some room in the fixed
- * precision calculations when retrieing the outline. So in
- * fact we don't use the identity CTM, but a 100x100 matrix
- * Originally tried 1000, but that was too likely to cause
- * clipping or arithmetic overflow.
- */
- gs_matrix_scale(&m, 100, 100, &m);
- gs_matrix_fixed_from_matrix(&penum->pis->ctm, &m);
+ pdf_resource_t *pres = pdev->accumulating_substream_resource;
- /* Choose a character code to use with the charproc. */
- code = pdf_choose_output_char_code(pdev, penum, &penum->output_char_code);
+ code = pdf_exit_substream(pdev);
if (code < 0)
return code;
- code = pdf_attached_font_resource(pdev, penum->current_font, &pdfont, NULL, NULL, NULL, NULL);
+ code = pdf_cancel_resource(pdev, pres, resourceCharProc);
if (code < 0)
return code;
- pdev->font3 = (pdf_resource_t *)pdfont;
- pdev->substream_Resources = pdfont->u.simple.s.type3.Resources;
- penum->charproc_accum = true;
- return TEXT_PROCESS_RENDER;
- } else
- code += 0; /* A fgood place for breakpoint. */
+ pdf_forget_resource(pdev, pres, resourceCharProc);
+
+ /* And then start up the PS/PDF accumulator */
+ code = install_PS_charproc_accumulator(pdev, pte, pte_default, penum);
+ if (code < 0)
+ return code;
+ }
+ return TEXT_PROCESS_RENDER;
}
+ else {
+ /* We aren't about to run a glyph description in the interpreter
+ * so either it was a PCL type 3, or some other type being turned
+ * into a type 3. If its a type 3 and we started the accumulator,
+ * then we need to complete the capture (PCL only I hope!)
+ */
+ if (penum->current_font->FontType == ft_user_defined &&
+ penum->outer_CID == GS_NO_GLYPH &&
+ !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)
+ && !pdev->type3charpath && penum->charproc_accum == started
+ && stell(pdev->strm) != 0)
+ {
+ penum->pte_default = 0;
+ penum->output_char_code = pte_default->returned.current_char;
+ code = complete_charproc(pdev, pte, pte_default, penum, true);
+ if (code < 0)
+ return code;
+ if (!pdev->type3charpath)
+ goto top;
+ else
+ goto default_impl;
+ } else {
+ /* Belt and braces code, we should not reach this. However, if
+ * we had started the accumulator, are not about to execute a
+ * glyph description in the interpreter, and are not dealing
+ * with a type 3 font, then just discard the accumulator now.
+ */
+ if (penum->charproc_accum == started) {
+ pdf_resource_t *pres = pdev->accumulating_substream_resource;
+
+ code = pdf_exit_substream(pdev);
+ if (code < 0)
+ return code;
+ code = pdf_cancel_resource(pdev, pres, resourceCharProc);
+ if (code < 0)
+ return code;
+ pdf_forget_resource(pdev, pres, resourceCharProc);
+ }
+ }
+ }
+
gs_text_enum_copy_dynamic(pte, pte_default, true);
if (code)
return code;
diff --git a/gs/base/gdevpdtt.h b/gs/base/gdevpdtt.h
index e0fef5232..a4f099d97 100644
--- a/gs/base/gdevpdtt.h
+++ b/gs/base/gdevpdtt.h
@@ -99,12 +99,14 @@ struct pdf_char_glyph_pairs_s {
pdf_char_glyph_pair_t s[1]; /* Variable length. */
};
+typedef enum {idle, started, aborted} type3_accum_status;
+
/* Define the text enumerator. */
typedef struct pdf_text_enum_s {
gs_text_enum_common;
gs_text_enum_t *pte_default;
gs_fixed_point origin;
- bool charproc_accum;
+ type3_accum_status charproc_accum;
bool cdevproc_callout;
double cdevproc_result[10];
pdf_char_glyph_pairs_t *cgp;