summaryrefslogtreecommitdiff
path: root/gs/base/gdevpdtt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/base/gdevpdtt.c')
-rw-r--r--gs/base/gdevpdtt.c493
1 files changed, 349 insertions, 144 deletions
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;