diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2011-04-29 16:42:30 +0100 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2011-04-29 16:42:30 +0100 |
commit | 947e90ad0229b6333d6eb61e7f54ac33b200ab28 (patch) | |
tree | df392ae62ad81fdeb2d775c6a1369b9689995dac | |
parent | 1553ea878b414b4ac389f7cec4c2076bc52be966 (diff) | |
download | ghostpdl-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.c | 48 | ||||
-rw-r--r-- | gs/base/gdevpdfb.h | 1 | ||||
-rw-r--r-- | gs/base/gdevpdfx.h | 118 | ||||
-rw-r--r-- | gs/base/gdevpdti.c | 26 | ||||
-rw-r--r-- | gs/base/gdevpdtt.c | 493 | ||||
-rw-r--r-- | gs/base/gdevpdtt.h | 4 |
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; |