diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2011-05-17 15:53:56 +0100 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2011-05-17 15:53:56 +0100 |
commit | 49921ad78b31af5ab8803d6de886d93106c0db0c (patch) | |
tree | 4b012cbab59b63b891ee6dffceadaf713b7800c8 /gs | |
parent | 97fbf9fd981cdda1d6db80c2a808e3935b1809f3 (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.c | 1 | ||||
-rw-r--r-- | gs/base/gdevpdte.c | 72 | ||||
-rw-r--r-- | gs/base/gdevpdtf.c | 5 | ||||
-rw-r--r-- | gs/base/gdevpdti.c | 5 | ||||
-rw-r--r-- | gs/base/gdevpdts.c | 4 | ||||
-rw-r--r-- | gs/base/gdevpdtt.c | 177 | ||||
-rw-r--r-- | gs/base/gdevpdtw.c | 4 | ||||
-rw-r--r-- | gs/base/gstext.c | 1 | ||||
-rw-r--r-- | gs/base/gxchar.c | 1 | ||||
-rw-r--r-- | gs/base/gxftype.h | 11 | ||||
-rw-r--r-- | gs/base/gxpaint.c | 1 |
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; } |