summaryrefslogtreecommitdiff
path: root/gs
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2011-05-17 15:53:56 +0100
committerKen Sharp <ken.sharp@artifex.com>2011-05-17 15:53:56 +0100
commit49921ad78b31af5ab8803d6de886d93106c0db0c (patch)
tree4b012cbab59b63b891ee6dffceadaf713b7800c8 /gs
parent97fbf9fd981cdda1d6db80c2a808e3935b1809f3 (diff)
Add another new font type 'ft_PCL_user_defined' for the PCL bitmap
font. Update various parts of the code to treat the new font the same as a PostScript type 3 font. In pdfwrite, if we capture a CharpProcs, and its for a PCL bitmap font then add a cache entry. We do NOT do this for most other fonts, only when rendering a glyph. When assembling text, if the font is a PCL bitmap font, tehn after checking to see if we've already used it, check to see if there is a cache entry. If the PCL job has reused this character code with a different bitmap it will haev flushed the cache entry. If we font this has happened then capture the new glyph. NB if we are capturing a new definition (font->used[[] is valid) then we know this is a redefinition so capture into a different font using the old style 'default' implementation.
Diffstat (limited to 'gs')
-rw-r--r--gs/base/gdevpdtd.c1
-rw-r--r--gs/base/gdevpdte.c72
-rw-r--r--gs/base/gdevpdtf.c5
-rw-r--r--gs/base/gdevpdti.c5
-rw-r--r--gs/base/gdevpdts.c4
-rw-r--r--gs/base/gdevpdtt.c177
-rw-r--r--gs/base/gdevpdtw.c4
-rw-r--r--gs/base/gstext.c1
-rw-r--r--gs/base/gxchar.c1
-rw-r--r--gs/base/gxftype.h11
-rw-r--r--gs/base/gxpaint.c1
11 files changed, 238 insertions, 44 deletions
diff --git a/gs/base/gdevpdtd.c b/gs/base/gdevpdtd.c
index d6a9c1e54..6540d37e4 100644
--- a/gs/base/gdevpdtd.c
+++ b/gs/base/gdevpdtd.c
@@ -379,6 +379,7 @@ pdf_compute_font_descriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd)
/* Type 3 fonts may use a FontMatrix in PDF, so we don't
* need to deal with non-standard matrices
*/
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
case ft_user_defined:
break;
diff --git a/gs/base/gdevpdte.c b/gs/base/gdevpdte.c
index 90bfd675e..c7d28889a 100644
--- a/gs/base/gdevpdte.c
+++ b/gs/base/gdevpdte.c
@@ -25,6 +25,8 @@
#include "gxfont0.h"
#include "gxfont0c.h"
#include "gxpath.h" /* for getting current point */
+#include "gxchar.h" /* for gx_compute_text_oversampling & gx_lookup_cached_char */
+#include "gxfcache.h" /* for gx_lookup_fm_pair */
#include "gdevpsf.h"
#include "gdevpdfx.h"
#include "gdevpdfg.h"
@@ -59,6 +61,7 @@ pdf_process_string_aux(pdf_text_enum_t *penum, gs_string *pstr,
case ft_encrypted:
case ft_encrypted2:
case ft_user_defined:
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
break;
default:
@@ -184,6 +187,7 @@ pdf_used_charproc_resources(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
if (pdev->CompatibilityLevel >= 1.2)
return 0;
if (pdfont->FontType == ft_user_defined ||
+ pdfont->FontType == ft_PCL_user_defined ||
pdfont->FontType == ft_GL2_stick_user_defined) {
pdf_resource_enum_data_t data;
@@ -233,6 +237,7 @@ pdf_encode_string_element(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_
if (code < 0)
return code; /* can't get name of glyph */
if (font->FontType != ft_user_defined &&
+ font->FontType != ft_PCL_user_defined &&
font->FontType != ft_GL2_stick_user_defined) {
/* The standard 14 fonts don't have a FontDescriptor. */
code = (pdfont->base_font != 0 ?
@@ -657,6 +662,7 @@ pdf_char_widths(gx_device_pdf *const pdev,
if (pwidths == 0)
pwidths = &widths;
if ((font->FontType != ft_user_defined &&
+ font->FontType != ft_PCL_user_defined &&
font->FontType != ft_GL2_stick_user_defined)&& real_widths[ch] == 0) {
/* Might be an unused char, or just not cached. */
gs_glyph glyph = pdfont->u.simple.Encoding[ch].glyph;
@@ -684,7 +690,8 @@ pdf_char_widths(gx_device_pdf *const pdev,
real_widths[ch] = pwidths->real_width.w;
}
} else {
- if (font->FontType == ft_user_defined || font->FontType == ft_GL2_stick_user_defined) {
+ if (font->FontType == ft_user_defined || font->FontType == ft_PCL_user_defined ||
+ font->FontType == ft_GL2_stick_user_defined) {
if (!(pdfont->used[ch >> 3] & 0x80 >> (ch & 7)))
return gs_error_undefined; /* The charproc was not accumulated. */
if (!pdev->charproc_just_accumulated &&
@@ -696,7 +703,8 @@ pdf_char_widths(gx_device_pdf *const pdev,
}
pwidths->Width.w = pdfont->Widths[ch];
pwidths->Width.v = pdfont->u.simple.v[ch];
- if (font->FontType == ft_user_defined || font->FontType == ft_GL2_stick_user_defined) {
+ if (font->FontType == ft_user_defined || font->FontType == ft_PCL_user_defined ||
+ font->FontType == ft_GL2_stick_user_defined) {
pwidths->real_width.w = real_widths[ch * 2];
pwidths->Width.xy.x = pwidths->Width.w;
pwidths->Width.xy.y = 0;
@@ -730,6 +738,7 @@ pdf_char_widths_to_uts(pdf_font_resource_t *pdfont /* may be NULL for non-Type3
pdf_glyph_widths_t *pwidths)
{
if (pdfont && (pdfont->FontType == ft_user_defined ||
+ pdfont->FontType == ft_PCL_user_defined ||
pdfont->FontType == ft_GL2_stick_user_defined)) {
gs_matrix *pmat = &pdfont->u.simple.s.type3.FontMatrix;
@@ -783,14 +792,59 @@ process_text_return_width(const pdf_text_enum_t *pte, gs_font_base *font,
if (code < 0)
return code;
}
- if ((font->FontType == ft_user_defined || font->FontType == ft_GL2_stick_user_defined) &&
+ if ((font->FontType == ft_user_defined ||
+ font->FontType == ft_PCL_user_defined ||
+ font->FontType == ft_GL2_stick_user_defined) &&
(i > 0 || !pdev->charproc_just_accumulated) &&
!(pdfont->u.simple.s.type3.cached[ch >> 3] & (0x80 >> (ch & 7))))
code = gs_error_undefined;
- else
- code = pdf_char_widths((gx_device_pdf *)pte->dev,
- ppts->values.pdfont, ch, font,
- &cw);
+ else {
+ if (font->FontType == ft_PCL_user_defined) {
+ /* Check the cache, if the glyph has been flushed, assume that
+ * it has been redefined, and do not use the current glyph.
+ * Additional code in pdf_text_process will also spot this
+ * condition and will not capture the glyph in this font.
+ */
+ /* Cache checking code copied from gxchar.c, show_proceed,
+ * case 0, 'plain char'.
+ */
+ gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
+ gs_font *pfont = (pte->fstack.depth < 0 ? pte->current_font :
+ pte->fstack.items[pte->fstack.depth].font);
+ int wmode = rfont->WMode;
+ gs_log2_scale_point log2_scale;
+ int alpha_bits, depth;
+ gs_fixed_point subpix_origin;
+ cached_fm_pair *pair;
+
+ /* Copied from compute_glyph_raster_params */
+ alpha_bits = (*dev_proc(pte->dev, get_alpha_bits)) (pte->dev, go_text);
+ if (pte->fapi_log2_scale.x != -1)
+ log2_scale = pte->fapi_log2_scale;
+ else
+ gx_compute_text_oversampling(pte, pte->current_font, alpha_bits, &log2_scale);
+ depth = (log2_scale.x + log2_scale.y == 0 ?
+ 1 : min(log2_scale.x + log2_scale.y, alpha_bits));
+ subpix_origin.x = subpix_origin.y = 0;
+ /* End of code copied from compute_glyph_raster_params */
+
+ code = gx_lookup_fm_pair(pfont, &ctm_only(pte->pis), &log2_scale,
+ false, &pair);
+ if (code < 0)
+ return code;
+ if (gx_lookup_cached_char(pfont, pair, ch, wmode,
+ depth, &subpix_origin) == 0)
+ /* Character is not in cache, must have been redefined. */
+ code = gs_error_undefined;
+ else
+ /* Character is in cache, go ahead and use it */
+ code = pdf_char_widths((gx_device_pdf *)pte->dev,
+ ppts->values.pdfont, ch, font, &cw);
+ } else
+ /* Not a PCL bitmap font, we don't need to worry abou redefined glyphs */
+ code = pdf_char_widths((gx_device_pdf *)pte->dev,
+ ppts->values.pdfont, ch, font, &cw);
+ }
if (code < 0) {
if (i)
break;
@@ -879,7 +933,9 @@ process_text_modify_width(pdf_text_enum_t *pte, gs_font *font,
pdf_font_resource_t *pdfont3 = NULL;
int code;
- if (font->FontType == ft_user_defined || font->FontType == ft_GL2_stick_user_defined) {
+ if (font->FontType == ft_user_defined ||
+ font->FontType == ft_PCL_user_defined ||
+ font->FontType == ft_GL2_stick_user_defined) {
code = pdf_attached_font_resource(pdev, font, &pdfont3, NULL, NULL, NULL, NULL);
if (code < 0)
return code;
diff --git a/gs/base/gdevpdtf.c b/gs/base/gdevpdtf.c
index b5ec32b6a..79e592b4c 100644
--- a/gs/base/gdevpdtf.c
+++ b/gs/base/gdevpdtf.c
@@ -67,6 +67,7 @@ case 8: switch (pdfont->FontType) {
case ft_encrypted:
case ft_encrypted2:
case ft_TrueType:
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
case ft_user_defined:
ENUM_RETURN(pdfont->u.simple.v);
@@ -77,6 +78,7 @@ case 8: switch (pdfont->FontType) {
ENUM_RETURN(0);
}
case 9: switch (pdfont->FontType) {
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
case ft_user_defined:
ENUM_RETURN(pdfont->u.simple.s.type3.char_procs);
@@ -87,6 +89,7 @@ case 9: switch (pdfont->FontType) {
ENUM_RETURN(0);
}
case 10: switch (pdfont->FontType) {
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
case ft_user_defined:
ENUM_RETURN(pdfont->u.simple.s.type3.cached);
@@ -97,6 +100,7 @@ case 10: switch (pdfont->FontType) {
ENUM_RETURN(0);
}
case 11: switch (pdfont->FontType) {
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
case ft_user_defined:
ENUM_RETURN(pdfont->u.simple.s.type3.Resources);
@@ -124,6 +128,7 @@ RELOC_PTRS_WITH(pdf_font_resource_reloc_ptrs, pdf_font_resource_t *pdfont)
RELOC_CONST_STRING_VAR(pdfont->u.type0.CMapName);
RELOC_VAR(pdfont->u.type0.DescendantFont);
break;
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
case ft_user_defined:
RELOC_VAR(pdfont->u.simple.Encoding);
diff --git a/gs/base/gdevpdti.c b/gs/base/gdevpdti.c
index 0ea880e84..a7dde7fd4 100644
--- a/gs/base/gdevpdti.c
+++ b/gs/base/gdevpdti.c
@@ -328,6 +328,7 @@ pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
* go back to collecting the bitmap into our fallback font.
*/
if ((show_enum->current_font->FontType == ft_user_defined ||
+ show_enum->current_font->FontType == ft_PCL_user_defined ||
show_enum->current_font->FontType == ft_GL2_stick_user_defined) && allowed_op &&
show_enum->current_font->FontMatrix.xx == 1 && show_enum->current_font->FontMatrix.xy == 0 &&
show_enum->current_font->FontMatrix.yx == 0 && show_enum->current_font->FontMatrix.yy == 1) {
@@ -475,7 +476,9 @@ pdf_mark_glyph_names(const pdf_font_resource_t *pdfont, const gs_memory_t *memor
if (pdfont->u.simple.Encoding[i].glyph != GS_NO_GLYPH)
pdfont->mark_glyph(memory, pdfont->u.simple.Encoding[i].glyph, pdfont->mark_glyph_data);
}
- if (pdfont->FontType == ft_user_defined || pdfont->FontType == ft_GL2_stick_user_defined) {
+ if (pdfont->FontType == ft_user_defined ||
+ pdfont->FontType == ft_PCL_user_defined ||
+ pdfont->FontType == ft_GL2_stick_user_defined) {
const pdf_char_proc_ownership_t *pcpo = pdfont->u.simple.s.type3.char_procs;
for (; pcpo != NULL; pcpo = pcpo->font_next)
diff --git a/gs/base/gdevpdts.c b/gs/base/gdevpdts.c
index 972801437..70e73e827 100644
--- a/gs/base/gdevpdts.c
+++ b/gs/base/gdevpdts.c
@@ -681,7 +681,9 @@ bool pdf_compare_text_state_for_charpath(pdf_text_state_t *pts, gx_device_pdf *p
if(text->size != pts->buffer.count_chars)
return(false);
- if(font->FontType == ft_user_defined || font->FontType == ft_GL2_stick_user_defined)
+ if(font->FontType == ft_user_defined ||
+ font->FontType == ft_PCL_user_defined ||
+ font->FontType == ft_GL2_stick_user_defined)
return(false);
/* check to ensure the new text has the same data as the saved text */
diff --git a/gs/base/gdevpdtt.c b/gs/base/gdevpdtt.c
index 7a8b3ddd2..906fb0937 100644
--- a/gs/base/gdevpdtt.c
+++ b/gs/base/gdevpdtt.c
@@ -149,6 +149,7 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
pgste = penum->pte_default;
if ((penum->current_font->FontType == ft_user_defined ||
+ penum->current_font->FontType == ft_PCL_user_defined ||
penum->current_font->FontType == ft_GL2_stick_user_defined) &&
penum->outer_CID == GS_NO_GLYPH &&
!(pgste->text.operation & TEXT_DO_CHARWIDTH)) {
@@ -414,7 +415,9 @@ gdev_pdf_text_begin(gx_device * dev, gs_imager_state * pis,
pdev->last_charpath_op = text->operation & TEXT_DO_ANY_CHARPATH;
}
- if(font->FontType == ft_user_defined || font->FontType == ft_GL2_stick_user_defined)
+ if(font->FontType == ft_user_defined ||
+ font->FontType == ft_PCL_user_defined ||
+ font->FontType == ft_GL2_stick_user_defined)
user_defined = 1;
/* We need to know whether any of the glyphs in a string using a composite font
@@ -604,6 +607,7 @@ font_cache_elem_array_sizes(gx_device_pdf *pdev, gs_font *font,
case ft_encrypted2:
case ft_user_defined:
case ft_GL2_stick_user_defined:
+ case ft_PCL_user_defined:
case ft_disk_based:
case ft_Chameleon:
case ft_TrueType:
@@ -634,7 +638,8 @@ alloc_font_cache_elem_arrays(gx_device_pdf *pdev, pdf_font_cache_elem_t *e,
e->real_widths = (num_widths > 0 ? (double *)gs_alloc_bytes(pdev->pdf_memory,
num_widths * sizeof(*e->real_widths) *
((font->FontType == ft_user_defined ||
- font->FontType == ft_GL2_stick_user_defined) ? 2 : 1),
+ font->FontType == ft_GL2_stick_user_defined ||
+ font->FontType == ft_PCL_user_defined) ? 2 : 1),
"alloc_font_cache_elem_arrays") : NULL);
if (e->glyph_usage == NULL || (num_widths !=0 && e->real_widths == NULL)) {
gs_free_object(pdev->pdf_memory, e->glyph_usage,
@@ -707,13 +712,14 @@ pdf_attach_font_resource(gx_device_pdf *pdev, gs_font *font,
int num_chars, num_widths, len;
pdf_font_cache_elem_t *e, **pe = pdf_locate_font_cache_elem(pdev, font);
- /* Allow the HPGL2 stick font to have a type 3 font attached, it *is* a
+ /* Allow the HPGL2 stick font to be attached to a type 3 font, it *is* a
* type 3 font, its just identified differently so that we can choose not
- * to capture it elsewhere
+ * to capture it elsewhere. Same for PCL bitmap fonts.
*/
if (pdfont->FontType != font->FontType &&
(pdfont->FontType != ft_user_defined ||
- font->FontType != ft_GL2_stick_user_defined))
+ (font->FontType != ft_PCL_user_defined &&
+ font->FontType != ft_GL2_stick_user_defined)))
return_error(gs_error_unregistered); /* Must not happen. */
font_cache_elem_array_sizes(pdev, font, &num_widths, &num_chars);
len = (num_chars + 7) / 8;
@@ -768,6 +774,7 @@ pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat)
case ft_encrypted2:
case ft_CID_encrypted:
case ft_user_defined:
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
/*
* Type 1 fonts are supposed to use a standard FontMatrix of
@@ -804,7 +811,9 @@ pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat)
while (base_font->base != base_font)
base_font = base_font->base;
- if (font->FontType == ft_user_defined || font->FontType == ft_GL2_stick_user_defined)
+ if (font->FontType == ft_user_defined ||
+ font->FontType == ft_PCL_user_defined ||
+ font->FontType == ft_GL2_stick_user_defined)
*pmat = base_font->FontMatrix;
else if (base_font->orig_FontMatrix.xx != 0 || base_font->orig_FontMatrix.xy != 0 ||
base_font->orig_FontMatrix.yx != 0 || base_font->orig_FontMatrix.yy != 0)
@@ -939,6 +948,7 @@ pdf_is_compatible_encoding(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
}
return false;
case ft_user_defined:
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
if (pdfont->u.simple.Encoding == NULL)
return false; /* Not sure. Happens with 020-01.ps . */
@@ -975,6 +985,7 @@ pdf_font_has_glyphs(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
switch (pdfont->FontType) {
case ft_composite:
case ft_user_defined:
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
/* Unused case. */
return false;
@@ -1290,6 +1301,7 @@ pdf_make_font_resource(gx_device_pdf *pdev, gs_font *font,
font_alloc = pdf_font_simple_alloc;
break;
case ft_user_defined:
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
code = pdf_make_font3_resource(pdev, font, ppdfont);
if (code < 0)
@@ -1405,6 +1417,7 @@ pdf_is_simple_font(gs_font *font)
font->FontType == ft_encrypted2 ||
font->FontType == ft_TrueType ||
font->FontType == ft_user_defined ||
+ font->FontType == ft_PCL_user_defined ||
font->FontType == ft_GL2_stick_user_defined);
}
@@ -1777,7 +1790,9 @@ pdf_obtain_font_resource_encoded(gx_device_pdf *pdev, gs_font *font,
if (*ppdfont != 0) {
gs_font_base *cfont = pdf_font_resource_font(*ppdfont, false);
- if (font->FontType != ft_user_defined && font->FontType != ft_GL2_stick_user_defined ) {
+ if (font->FontType != ft_user_defined &&
+ font->FontType != ft_PCL_user_defined &&
+ font->FontType != ft_GL2_stick_user_defined ) {
code = gs_copied_can_copy_glyphs((gs_font *)cfont, font,
&cgp->s[cgp->unused_offset].glyph, cgp->num_unused_chars,
sizeof(pdf_char_glyph_pair_t), true);
@@ -2035,7 +2050,9 @@ pdf_obtain_parent_type0_font_resource(gx_device_pdf *pdev, pdf_font_resource_t *
gs_char
pdf_find_glyph(pdf_font_resource_t *pdfont, gs_glyph glyph)
{
- if (pdfont->FontType != ft_user_defined && pdfont->FontType != ft_GL2_stick_user_defined)
+ if (pdfont->FontType != ft_user_defined &&
+ pdfont->FontType != ft_PCL_user_defined &&
+ pdfont->FontType != ft_GL2_stick_user_defined)
return GS_NO_CHAR;
else {
pdf_encoding_element_t *pet = pdfont->u.simple.Encoding;
@@ -2102,7 +2119,9 @@ float pdf_calculate_text_size(gs_imager_state *pis, pdf_font_resource_t *pdfont,
{
gs_font_base *cfont = pdf_font_resource_font(pdfont, false);
- if (pdfont->FontType == ft_user_defined || pdfont->FontType == ft_GL2_stick_user_defined)
+ if (pdfont->FontType == ft_user_defined ||
+ pdfont->FontType == ft_PCL_user_defined ||
+ pdfont->FontType == ft_GL2_stick_user_defined)
orig_matrix = pdfont->u.simple.s.type3.FontMatrix;
else if (cfont != 0) {
/*
@@ -2642,6 +2661,7 @@ static int install_charproc_accumulator(gx_device_pdf *pdev, gs_text_enum_t *pte
pdev->charproc_ctm = penum->pis->ctm;
if ((penum->current_font->FontType == ft_user_defined ||
+ penum->current_font->FontType == ft_PCL_user_defined ||
penum->current_font->FontType == ft_GL2_stick_user_defined) &&
penum->outer_CID == GS_NO_GLYPH &&
!(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) {
@@ -2697,7 +2717,6 @@ static int complete_charproc(gx_device_pdf *pdev, gs_text_enum_t *pte,
{
gs_const_string gnstr;
int code;
- unsigned char unknown_glyph[10];
code = pdf_choose_output_glyph_hame(pdev, penum, &gnstr, pte_default->returned.current_glyph);
if (code < 0) {
@@ -2705,6 +2724,7 @@ static int complete_charproc(gx_device_pdf *pdev, gs_text_enum_t *pte,
}
if ((penum->current_font->FontType == ft_user_defined ||
+ penum->current_font->FontType == ft_PCL_user_defined ||
penum->current_font->FontType == ft_GL2_stick_user_defined) &&
stell(pdev->strm) == 0)
{
@@ -2749,10 +2769,10 @@ static int complete_charproc(gx_device_pdf *pdev, gs_text_enum_t *pte,
}
/* Nasty hackery. The PCL 'stick font' is drawn by constructing a path, and then stroking it.
- * The stroke width is calculated under the influence of the device default matrix, whic
- * ensures it is the same, not matter what size the font is drawn at. Of course we are
+ * The stroke width is calculated under the influence of the device default matrix, which
+ * ensures it is the same, no matter what size the font is drawn at. Of course we are
* capturing the glyph under an identity matrix, so using the device matrix blows it up.
- * What we do is replace the get_initial_matrix method for teh course of the charproc
+ * What we do is replace the get_initial_matrix method for the course of the charproc
* accumulation *only*, and return a more sensible 'device' matrix.
* We know that the Charproc CTM is a combination of the font point size, and the default device
* matrix, so we just take off the default matrix, and invert the font scaling.
@@ -2816,6 +2836,7 @@ pdf_text_process(gs_text_enum_t *pte)
}
}
if ((penum->current_font->FontType == ft_user_defined ||
+ penum->current_font->FontType == ft_PCL_user_defined ||
penum->current_font->FontType == ft_GL2_stick_user_defined) &&
(penum->text.operation & TEXT_DO_ANY_CHARPATH)
&& !pdev->type3charpath) {
@@ -2832,14 +2853,18 @@ pdf_text_process(gs_text_enum_t *pte)
top:
pte_default = penum->pte_default;
/* pte_default is a signal that we can't handle the glyph in the current
- * font 'natively. This means either a type 3 font (for PostScript we
+ * font 'natively'. This means either a type 3 font (for PostScript we
* need to return to the PS interpreter to run the BuildChar), or a font
* type we can't or don't support in PDF. In the latter case we have the
- * BuildChar render the glyph and store it in the cache, and then we pull
- * the bitmap and store it in a Type 3 font. NB if the glyph is uncached
- * the it just ends up in the output as a bitmap image.
+ * BuildChar render the glyph and store it in the cache, spot the usage
+ * in the pdfwrite image routine and we store the resluting bitmap in a
+ * Type 3 font. NB if the glyph is uncached then it just ends up in the
+ * output as a bitmap image.
*/
if (pte_default) {
+ gs_char *cdata;
+
+ cdata = (gs_char *)pte->text.data.chars;
if (penum->charproc_accum) {
/* We've been accumulating a Type 3 CharProc, so now we need to
* finish off and store it in the font.
@@ -2853,14 +2878,32 @@ pdf_text_process(gs_text_enum_t *pte)
goto default_impl;
}
- /* If this is a type 3 font, and the BuildChar is not gs_no_build_char then
- * assume we're a PCL type 3 font. If so, and we're not doing a charpath, then
- * we want to accumulate the BuildChar into a font.
- */
- if (penum->current_font->procs.build_char != gs_no_build_char && penum->current_font->FontType == ft_user_defined
- && operation & TEXT_FROM_CHARS && !pdev->type3charpath)
- early_accumulator = 1;
- if (penum->current_font->FontType == ft_GL2_stick_user_defined) {
+ /* Sepcial checks for PCL bitmap fonts, or the HP/GL-2 stick font */
+ if (penum->current_font->FontType == ft_PCL_user_defined
+ && operation & TEXT_FROM_CHARS && !pdev->type3charpath &&
+ cdata[pte->index] <= 255) {
+ /* We can only get to this point with the character already in use
+ * if we detected in process_text_return_width that the glyph had
+ * been flushed from teh cache. If this happens with PCL bitmap
+ * fonts then we assume that the 'slot' has been reused. In this
+ * case we cannot add the glyph to the current font. By not
+ * capturing at this level the bitmap will still be added to a
+ * type 3 font, but a new one. Best we can do as PS/PDF do not
+ * allow redefinition of fonts.
+ */
+ pdf_font_resource_t *pdfont;
+
+ code = pdf_attached_font_resource(pdev, (gs_font *)penum->current_font, &pdfont, NULL, NULL, NULL, NULL);
+ if (code < 0)
+ return code;
+
+ if (pdfont->u.simple.s.type3.cached[cdata[pte->index] >> 3] & (0x80 >> (cdata[pte->index] & 7)))
+ early_accumulator = 0;
+ else
+ early_accumulator = 1;
+ }
+ if (penum->current_font->FontType == ft_GL2_stick_user_defined
+ && operation & TEXT_FROM_CHARS && !pdev->type3charpath) {
/* Check for anamorphic sacling, we msut not cache stick font
* in this case, as the stroke width will vary with the scaling.
*/
@@ -2896,14 +2939,11 @@ pdf_text_process(gs_text_enum_t *pte)
early_accumulator = 1;
}
if (early_accumulator) {
- gs_char *cdata;
-
- cdata = (gs_char *)pte->text.data.chars;
if (cdata[pte->index] <= 255) {
gs_state *pgs = (gs_state *)penum->pis;
gs_text_enum_procs_t const *save_procs = pte_default->procs;
gs_text_enum_procs_t special_procs = *pte_default->procs;
- void *save_proc = pdev->procs.get_initial_matrix;
+ void (*save_proc)(gx_device *, gs_matrix *) = pdev->procs.get_initial_matrix;
special_procs.set_cache = pdf_text_set_cache;
pte_default->procs = &special_procs;
@@ -2939,6 +2979,70 @@ pdf_text_process(gs_text_enum_t *pte)
return code;
code = complete_charproc(pdev, pte, pte_default, penum, false);
+ if (penum->current_font->FontType == ft_PCL_user_defined)
+ {
+ /* PCL bitmap fonts can have glyphs 'reused'. We can't handle
+ * handle this in a single PDF font, so we need to know when
+ * it has happened and fall back to the 'default' implementation.
+ * In order to do this, we create a cached character representation
+ * and add it to the cache. If the glyph is reused then the
+ * act of redefining it will remove this entry from the cache.
+ * We check if the glyph is in the cache in process_text_return_width
+ * and come back into this code. In the test above for PCL bitmap
+ * fonts we also check to see if the PDF font already has a
+ *'used' entry. If it does we know that its a redefinition, and
+ * we don't try to capture the glyph.
+ */
+ cached_char *cc;
+ cached_fm_pair *pair;
+ gs_log2_scale_point log2_scale;
+ gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
+ int wmode = rfont->WMode;
+
+ /* This code copied from show_cache_setup */
+ gs_memory_t *mem = penum->memory;
+ gx_device_memory *dev =
+ gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
+ "show_cache_setup(dev_cache)");
+
+ if (dev == 0) {
+ gs_free_object(mem, dev, "show_cache_setup(dev_cache)");
+ return_error(gs_error_VMerror);
+ }
+ gs_make_mem_mono_device(dev, mem, penum->dev);
+ dev->HWResolution[0] = pgs->device->HWResolution[0];
+ dev->HWResolution[1] = pgs->device->HWResolution[1];
+ /* Retain these devices. */
+ gx_device_retain((gx_device *)dev, true);
+ /* end of code copied from show_cache_setup */
+
+ /* This copied from set_cache */
+ code = gx_alloc_char_bits(pte->current_font->dir, dev, NULL,
+ 0, 0, &pte->fapi_log2_scale, 1, &cc);
+ if (code < 0)
+ return code;
+
+ /* The following code is copied from show_update, case sws_cache */
+ code = gx_lookup_fm_pair(pte->current_font, &ctm_only(pte->pis),
+ &pte->fapi_log2_scale, false, &pair);
+ if (code < 0)
+ return code;
+
+ /* These members of the cached character are required
+ * in order to find the cache entry later
+ */
+ cc->code = penum->returned.current_char;
+ cc->wmode = wmode;
+ log2_scale.x = log2_scale.y = 0;
+ code = gx_add_cached_char(pte->current_font->dir, dev,
+ cc, pair, &log2_scale);
+ if (code < 0)
+ return code;
+ /* End of code from show_update */
+
+ /* Finally, dispose of the device, which we don't actually need */
+ gx_device_retain((gx_device *)dev, false);
+ }
pte_default->procs = save_procs;
size = pte->text.size - pte->index;
if (code < 0)
@@ -2951,12 +3055,18 @@ pdf_text_process(gs_text_enum_t *pte)
}
/* Now we run the default text procedure to see what happens.
- * Non-PS type 3 fonts and the PCL stick font are handled above.
+ * PCL bitmap fonts and the HP/GL-2 stick font are handled above.
* 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. Otherwise we just
* run the BuildChar, and later capture the cached bitmap for incorporation
- * into a type 3 font.
+ * into a type 3 font. Note that sometimes we will handle PCL or HP/GL-2
+ * fonts by not capturing them above, and they will come through here.
+ * The stick font will not be captured as a font at all, just vectors
+ * stored into the content stream (for osme kinds of scale/shear),
+ * bitmap fonts will be captured in the pdfwrite image routine. These
+ * are added to a type 3 font in the same way as glyphs which need to
+ * be rendered.
*/
pdev->pte = pte_default; /* CAUTION: See comment in gdevpdfx.h . */
code = gs_text_process(pte_default);
@@ -2965,7 +3075,8 @@ pdf_text_process(gs_text_enum_t *pte)
/* If the BuildChar returned TEXT_PROCESS_RENDER then we want to try and
* capture this as a type 3 font, so start the accumulator now. Note
- * that the setcachedevice handling can still abort this later.
+ * that the setcachedevice handling can still abort this later. In which
+ * case we get the rendered bitmap, just as for non type 3 fonts.
*/
if (code == TEXT_PROCESS_RENDER && !pdev->type3charpath) {
int code1;
@@ -2996,6 +3107,7 @@ pdf_text_process(gs_text_enum_t *pte)
case ft_encrypted2:
case ft_TrueType:
case ft_user_defined:
+ case ft_PCL_user_defined:
case ft_GL2_stick_user_defined:
/* The data may be either glyphs or characters. */
process = process_plain_text;
@@ -3056,6 +3168,7 @@ pdf_text_process(gs_text_enum_t *pte)
skip:
if (code < 0 ||
((pte->current_font->FontType == ft_user_defined ||
+ pte->current_font->FontType == ft_PCL_user_defined ||
pte->current_font->FontType == ft_GL2_stick_user_defined) &&
code != TEXT_PROCESS_INTERVENE &&
penum->index < penum->text.size)) {
diff --git a/gs/base/gdevpdtw.c b/gs/base/gdevpdtw.c
index 1ae42ff52..a877efd8a 100644
--- a/gs/base/gdevpdtw.c
+++ b/gs/base/gdevpdtw.c
@@ -161,6 +161,7 @@ pdf_write_encoding(gx_device_pdf *pdev, const pdf_font_resource_t *pdfont, long
if (code < 0)
return code; /* Must not happen */
if (code == 0 && (pdfont->FontType == ft_user_defined ||
+ pdfont->FontType == ft_PCL_user_defined ||
pdfont->FontType == ft_GL2_stick_user_defined)) {
/* PDF 1.4 spec Appendix H Note 42 says that
* Acrobat 4 can't properly handle Base Encoding.
@@ -562,7 +563,7 @@ pdf_write_font_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
if (pdfont->FontType == ft_composite ||
((pdfont->FontType == ft_encrypted || pdfont->FontType == ft_encrypted2 ||
pdfont->FontType == ft_TrueType || pdfont->FontType == ft_user_defined ||
- pdfont->FontType == ft_GL2_stick_user_defined) &&
+ pdfont->FontType == ft_GL2_stick_user_defined || pdfont->FontType == ft_PCL_user_defined ) &&
pdf_simple_font_needs_ToUnicode(pdfont))
) {
pdf_resource_t *prcmap;
@@ -574,6 +575,7 @@ pdf_write_font_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
}
if (pdev->CompatibilityLevel >= 1.2 &&
(pdfont->FontType == ft_user_defined ||
+ pdfont->FontType == ft_PCL_user_defined ||
pdfont->FontType == ft_GL2_stick_user_defined) &&
pdfont->u.simple.s.type3.Resources != NULL &&
pdfont->u.simple.s.type3.Resources->elements != NULL) {
diff --git a/gs/base/gstext.c b/gs/base/gstext.c
index 59c31c6e5..417884bf2 100644
--- a/gs/base/gstext.c
+++ b/gs/base/gstext.c
@@ -243,6 +243,7 @@ gs_text_begin(gs_state * pgs, const gs_text_params_t * text,
Note : FontType 3 throws error in setcachedevice. */
if (pgs->font->FontType != ft_user_defined &&
pgs->font->FontType != ft_GL2_stick_user_defined &&
+ pgs->font->FontType != ft_PCL_user_defined &&
pgs->font->FontMatrix.xx == 0 && pgs->font->FontMatrix.xy == 0 &&
pgs->font->FontMatrix.yx == 0 && pgs->font->FontMatrix.yy == 0)
return_error(gs_error_undefinedresult); /* sic! : CPSI compatibility */
diff --git a/gs/base/gxchar.c b/gs/base/gxchar.c
index d137aed76..9ba9b6e32 100644
--- a/gs/base/gxchar.c
+++ b/gs/base/gxchar.c
@@ -612,6 +612,7 @@ set_cache_device(gs_show_enum * penum, gs_state * pgs, floatp llx, floatp lly,
gx_path box_path;
if (penum->current_font->FontType != ft_user_defined &&
+ penum->current_font->FontType != ft_PCL_user_defined &&
penum->current_font->FontType != ft_GL2_stick_user_defined &&
penum->current_font->FontType != ft_CID_user_defined) {
/* Most fonts don't paint outside bbox,
diff --git a/gs/base/gxftype.h b/gs/base/gxftype.h
index 921293155..d5cbb5626 100644
--- a/gs/base/gxftype.h
+++ b/gs/base/gxftype.h
@@ -46,7 +46,16 @@ typedef enum {
* font was just a ft_user_defined but this allows us to tell the
* difference.
*/
- ft_GL2_stick_user_defined = 52
+ ft_GL2_stick_user_defined = 52,
+ /* Another special case. PCL bitmap fonts differ from PS type 3 fonts in
+ * that 'slots' (character codes) can be resued, which can't be done with
+ * PS/PDF type 3 fonts. Not a problem for rendering since we just clear
+ * the glyph from the caceh, which means the new definition gets rendered
+ * as required. However pdfwrite needs to know that this is not a regular
+ * type 3 font, otherwise it won't know to look out for the cache entry
+ * being freed, and will reuse the original definition
+ */
+ ft_PCL_user_defined = 53
} font_type;
/* Define the bitmap font behaviors. */
diff --git a/gs/base/gxpaint.c b/gs/base/gxpaint.c
index 4621a0a07..7e06251ed 100644
--- a/gs/base/gxpaint.c
+++ b/gs/base/gxpaint.c
@@ -26,6 +26,7 @@ static bool caching_an_outline_font(const gs_state * pgs)
return pgs->in_cachedevice > 1 &&
pgs->font != NULL &&
pgs->font->FontType != ft_user_defined &&
+ pgs->font->FontType != ft_PCL_user_defined &&
pgs->font->FontType != ft_GL2_stick_user_defined &&
pgs->font->FontType != ft_CID_user_defined;
}