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/base/gdevpdtt.c | |
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/base/gdevpdtt.c')
-rw-r--r-- | gs/base/gdevpdtt.c | 177 |
1 files changed, 145 insertions, 32 deletions
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)) { |