diff options
author | Igor Melichev <igor.melichev@artifex.com> | 2003-04-08 16:31:56 +0000 |
---|---|---|
committer | Igor Melichev <igor.melichev@artifex.com> | 2003-04-08 16:31:56 +0000 |
commit | 29cdc09da0289621708768e72c4bbb2e7ecd8c8c (patch) | |
tree | ee19fef341f7280b84672e11f456e2feeb0df2e3 | |
parent | 3039782b15ae2727157e31ba42ff830322d0f1f2 (diff) |
pdfwrite : Don't convert Type 3 fonts to raster fonts.
DETAILS :
The main work is done with pdf_install_charproc_accum and
pdf_end_charproc_accum. They forward a BuildChar/BuildGlyph output
to a separate graphic stream. See the big comment at the end of pdf_text_process.
The new function gx_default_text_restore_state restores graphic
state of PS interpreter when we discontinue the default text enumeration
after executing a PS charproc. New state variable gx_device_pdf::accum_char_proc
sets a special mode for graphic handlers.
We ever clip BuildChar/BuildGlyph with a FontBBox or with character bbox
specified in setcachedevice*. Doing so with calling gx_clip_to_rectangle
from pdf_text_set_cache, because we need to avoid the
current PS clipping path to interfere the character proc.
Possibly a better way is to install an infinite (i.e. absenting) clipping box,
wnen setcharwidth is used instead setcachedevice*.
but we don't know how to. Due to that the distilled 238-01.ps
renders some differently than undistilled one, and in most cases
it appears closer to what CPSI does.
An additional optimization : In sync_text_state the condition for matrix
sinchronization is done weaker : with empty text buffer the
synchronization is not needed.
git-svn-id: http://svn.ghostscript.com/ghostscript/trunk@3788 a1074d23-0009-0410-80fe-cf8c14f379e6
-rw-r--r-- | gs/src/gdevpdf.c | 14 | ||||
-rw-r--r-- | gs/src/gdevpdfd.c | 8 | ||||
-rw-r--r-- | gs/src/gdevpdfg.c | 2 | ||||
-rw-r--r-- | gs/src/gdevpdfu.c | 4 | ||||
-rw-r--r-- | gs/src/gdevpdfx.h | 35 | ||||
-rw-r--r-- | gs/src/gdevpdt.h | 5 | ||||
-rw-r--r-- | gs/src/gdevpdte.c | 176 | ||||
-rw-r--r-- | gs/src/gdevpdtf.c | 12 | ||||
-rw-r--r-- | gs/src/gdevpdtf.h | 6 | ||||
-rw-r--r-- | gs/src/gdevpdti.c | 243 | ||||
-rw-r--r-- | gs/src/gdevpdti.h | 3 | ||||
-rw-r--r-- | gs/src/gdevpdts.c | 26 | ||||
-rw-r--r-- | gs/src/gdevpdts.h | 17 | ||||
-rw-r--r-- | gs/src/gdevpdtt.c | 328 | ||||
-rw-r--r-- | gs/src/gdevpdtt.h | 11 | ||||
-rw-r--r-- | gs/src/gdevpdtw.c | 122 | ||||
-rw-r--r-- | gs/src/gdevpdtw.h | 6 | ||||
-rw-r--r-- | gs/src/gsstruct.h | 13 | ||||
-rw-r--r-- | gs/src/gxchar.c | 13 | ||||
-rw-r--r-- | gs/src/gxchar.h | 2 |
20 files changed, 759 insertions, 287 deletions
diff --git a/gs/src/gdevpdf.c b/gs/src/gdevpdf.c index cfb56e07f..d4426f4a5 100644 --- a/gs/src/gdevpdf.c +++ b/gs/src/gdevpdf.c @@ -28,6 +28,7 @@ #include "gdevpdfx.h" #include "gdevpdfg.h" /* only for pdf_reset_graphics */ #include "gdevpdfo.h" +#include "gdevpdt.h" /* Define the default language level and PDF compatibility level. */ /* Acrobat 4 (PDF 1.3) is the default. */ @@ -244,7 +245,13 @@ const gx_device_pdf gs_pdfwrite_device = }, 0, /* vgstack_depth */ {0}, /* vg_initial */ - false /* vg_initial_set */ + false, /* vg_initial_set */ + 0, /* accum_char_proc */ + PDF_IN_NONE, /* accum_char_proc_context_save */ + 0, /* accum_char_proc_text_state_save */ + 0, /* accum_char_proc_clip_path_save */ + 0, /* accum_char_proc_clip_path_id_save */ + 0 /* accum_char_proc_vgstack_depth_save */ }; /* ---------------- Device open/close ---------------- */ @@ -496,10 +503,13 @@ pdf_open(gx_device * dev) pdev->outlines_id = 0; pdev->next_page = 0; pdev->text = pdf_text_data_alloc(mem); + pdev->accum_char_proc_text_state_save = pdf_text_state_alloc(mem); + pdev->pages = gs_alloc_struct_array(mem, initial_num_pages, pdf_page_t, &st_pdf_page_element, "pdf_open(pages)"); - if (pdev->text == 0 || pdev->pages == 0) { + if (pdev->text == 0 || pdev->pages == 0 || + pdev->accum_char_proc_text_state_save == 0) { code = gs_error_VMerror; goto fail; } diff --git a/gs/src/gdevpdfd.c b/gs/src/gdevpdfd.c index a591bedcb..9d0e792e5 100644 --- a/gs/src/gdevpdfd.c +++ b/gs/src/gdevpdfd.c @@ -88,8 +88,10 @@ private int pdf_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, fixed y1, gx_path_type_t type) { + gx_device_pdf *pdev = (gx_device_pdf *)vdev; fixed xmax = int2fixed(vdev->width), ymax = int2fixed(vdev->height); - fixed xmin = 0, ymin = 0; + fixed xmin = (pdev->accum_char_proc ? -xmax : 0); + fixed ymin = (pdev->accum_char_proc ? -ymax : 0); /* * If we're doing a stroke operation, expand the checking box by the @@ -283,7 +285,7 @@ pdf_put_clip_path(gx_device_pdf * pdev, const gx_clip_path * pcpath) if (code < 0) return 0; /* Use Q to unwind the old clipping path. */ - if (pdev->vgstack_depth > 0) { + if (pdev->vgstack_depth > pdev->accum_char_proc_vgstack_depth_save) { code = pdf_restore_viewer_state(pdev, s); if (code < 0) return 0; @@ -395,7 +397,7 @@ gdev_pdf_fill_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath } new_clip = pdf_must_put_clip_path(pdev, pcpath); if (have_path || pdev->context == PDF_IN_NONE || new_clip) { - if (new_clip) + if (new_clip) code = pdf_unclip(pdev); else code = pdf_open_page(pdev, PDF_IN_STREAM); diff --git a/gs/src/gdevpdfg.c b/gs/src/gdevpdfg.c index 6bb46598e..dfad29b69 100644 --- a/gs/src/gdevpdfg.c +++ b/gs/src/gdevpdfg.c @@ -107,7 +107,7 @@ int pdf_restore_viewer_state(gx_device_pdf *pdev, stream *s) { const int i = --pdev->vgstack_depth; - if (i < 0) + if (i < pdev->accum_char_proc_vgstack_depth_save) return_error(gs_error_unregistered); /* Must not happen. */ stream_puts(s, "Q\n"); pdf_load_viewer_state(pdev, pdev->vgstack + i); diff --git a/gs/src/gdevpdfu.c b/gs/src/gdevpdfu.c index 7058b2404..1b388afcd 100644 --- a/gs/src/gdevpdfu.c +++ b/gs/src/gdevpdfu.c @@ -342,7 +342,7 @@ pdf_close_contents(gx_device_pdf * pdev, bool last) return 0; if (last) { /* Exit from the clipping path gsave. */ pdf_open_contents(pdev, PDF_IN_STREAM); - stream_puts(pdev->strm, "Q\n"); + stream_puts(pdev->strm, "Q\n"); /* See none_to_stream. */ pdf_close_text_contents(pdev); } return pdf_open_contents(pdev, PDF_IN_NONE); @@ -706,7 +706,7 @@ pdf_unclip(gx_device_pdf * pdev) if (code < 0) return code; - if (pdev->vgstack_depth > 0) { + if (pdev->vgstack_depth > pdev->accum_char_proc_vgstack_depth_save) { code = pdf_restore_viewer_state(pdev, pdev->strm); if (code < 0) return code; diff --git a/gs/src/gdevpdfx.h b/gs/src/gdevpdfx.h index e39abcdcf..9fb381c2a 100644 --- a/gs/src/gdevpdfx.h +++ b/gs/src/gdevpdfx.h @@ -74,6 +74,11 @@ typedef struct cos_object_procs_s cos_object_procs_t; typedef const cos_object_procs_t *cos_type_t; #define cos_types_DEFINED +#ifndef pdf_text_state_DEFINED +# define pdf_text_state_DEFINED +typedef struct pdf_text_state_s pdf_text_state_t; +#endif + /* ---------------- Resources ---------------- */ typedef enum { @@ -500,13 +505,21 @@ struct gx_device_pdf_s { gs_text_enum_t *pte; /* * The viewer's graphic state stack. - * We need only 2 elements : one for stream context, - * and another one for text context. + * We need only 4 elements : one for stream context, + * another one for text context, + * the third one for clipping in char procs, + * the fourth one for text context in char procs, */ - pdf_viewer_state vgstack[2]; + pdf_viewer_state vgstack[4]; int vgstack_depth; pdf_viewer_state vg_initial; /* Initial values for viewer's graphic state */ bool vg_initial_set; + bool accum_char_proc; + pdf_context_t accum_char_proc_context_save; + pdf_text_state_t *accum_char_proc_text_state_save; + gx_path *accum_char_proc_clip_path_save; + gs_id accum_char_proc_clip_path_id_save; + int accum_char_proc_vgstack_depth_save; }; #define is_in_page(pdev)\ @@ -527,8 +540,10 @@ struct gx_device_pdf_s { m(18,articles) m(19,Dests) m(20,global_named_objects)\ m(21, local_named_objects) m(22,NI_stack) m(23,Namespace_stack)\ m(24,open_graphics) m(25,font_cache) m(26,clip_path)\ - m(27,PageLabels) m(28,PageLabels_current_label) -#define gx_device_pdf_num_ptrs 29 + m(27,PageLabels) m(28,PageLabels_current_label)\ + m(29,accum_char_proc_text_state_save)\ + m(30,accum_char_proc_clip_path_save) +#define gx_device_pdf_num_ptrs 31 #define gx_device_pdf_do_strings(m) /* do nothing */ #define gx_device_pdf_num_strings 0 #define st_device_pdf_max_ptrs\ @@ -932,6 +947,8 @@ int pdf_close_text_document(gx_device_pdf *pdev); /* For gdevpdf.c */ pdf_text_data_t *pdf_text_data_alloc(gs_memory_t *mem); +void pdf_set_text_state_default(pdf_text_state_t *pts); +void pdf_text_state_copy(pdf_text_state_t *pts_to, pdf_text_state_t *pts_from); void pdf_reset_text_page(pdf_text_data_t *ptd); void pdf_reset_text_state(pdf_text_data_t *ptd); void pdf_close_text_page(gx_device_pdf *pdev); @@ -952,6 +969,14 @@ int pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos); int pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp, const gs_matrix * pimat); +/* Install charproc accumulator for a Type 3 font. */ +int pdf_install_charproc_accum(gx_device_pdf *pdev, gs_font *font, const double *pw, + gs_text_cache_control_t control, gs_char ch, gs_const_string *gnstr, + gs_id *id, pdf_stream_position_t *charproc_pos); +/* Complete charproc accumulation for aType 3 font. */ +int pdf_end_charproc_accum(gx_device_pdf *pdev, gs_id id, pdf_stream_position_t *ppos); + + /* For gdevpdfu.c */ int pdf_from_stream_to_text(gx_device_pdf *pdev); diff --git a/gs/src/gdevpdt.h b/gs/src/gdevpdt.h index da03ee27e..8f77c98d2 100644 --- a/gs/src/gdevpdt.h +++ b/gs/src/gdevpdt.h @@ -36,6 +36,11 @@ /* ---------------- Utility (for gdevpdf.c) ---------------- */ /* + * Allocate and initialize text state bookkeeping. + */ +pdf_text_state_t *pdf_text_state_alloc(gs_memory_t *mem); + +/* * Allocate and initialize the text data structure. */ pdf_text_data_t *pdf_text_data_alloc(gs_memory_t *mem); /* gdevpdts.h */ diff --git a/gs/src/gdevpdte.c b/gs/src/gdevpdte.c index a9ac77ddd..39e7fd0e7 100644 --- a/gs/src/gdevpdte.c +++ b/gs/src/gdevpdte.c @@ -64,6 +64,7 @@ pdf_encode_process_string(pdf_text_enum_t *penum, gs_string *pstr, case ft_TrueType: case ft_encrypted: case ft_encrypted2: + case ft_user_defined: break; default: return_error(gs_error_rangecheck); @@ -156,23 +157,37 @@ pdf_encode_string(gx_device_pdf *pdev, const pdf_text_enum_t *penum, code = font->procs.glyph_name(font, glyph, &gnstr); if (code < 0) return code; /* can't get name of glyph */ - /* The standard 14 fonts don't have a FontDescriptor. */ - code = (pdfont->base_font != 0 ? - pdf_base_font_copy_glyph(pdfont->base_font, glyph, (gs_font_base *)font) : - pdf_font_used_glyph(pdfont->FontDescriptor, glyph, (gs_font_base *)font)); - if (code == gs_error_undefined) - continue; /* notdef */ - if (code < 0) - return code; - if (pdfont->base_font == NULL && ccfont != NULL && - gs_copy_glyph_options(font, glyph, (gs_font *)ccfont, COPY_GLYPH_NO_NEW) != 1) { + if (font->FontType != ft_user_defined) { + /* The standard 14 fonts don't have a FontDescriptor. */ + code = (pdfont->base_font != 0 ? + pdf_base_font_copy_glyph(pdfont->base_font, glyph, (gs_font_base *)font) : + pdf_font_used_glyph(pdfont->FontDescriptor, glyph, (gs_font_base *)font)); + if (code == gs_error_undefined) + continue; /* notdef */ + if (code < 0) + return code; + if (pdfont->base_font == NULL && ccfont != NULL && + gs_copy_glyph_options(font, glyph, (gs_font *)ccfont, COPY_GLYPH_NO_NEW) != 1) { + /* + * The "complete" copy of the font appears incomplete + * due to incrementally added glyphs. Drop the "complete" + * copy now and continue with subset font only. + */ + ccfont = NULL; + pdf_font_descriptor_drop_complete_font(pdfont->FontDescriptor); + } /* - * The "complete" copy of the font appears incomplete - * due to incrementally added glyphs. Drop the "complete" - * copy now and continue with subset font only. + * We arbitrarily allow the first encoded character in a given + * position to determine the encoding associated with the copied + * font. */ - ccfont = NULL; - pdf_font_descriptor_drop_complete_font(pdfont->FontDescriptor); + copied_glyph = cfont->procs.encode_char((gs_font *)cfont, ch, + GLYPH_SPACE_NAME); + if (glyph != copied_glyph && + gs_copied_font_add_encoding((gs_font *)cfont, ch, glyph) < 0 + ) + pet->is_difference = true; + pdfont->used[ch >> 3] |= 0x80 >> (ch & 7); } if (need_ToUnicode) { code = pdf_add_ToUnicode(pdev, font, pdfont, glyph, ch); @@ -181,18 +196,6 @@ pdf_encode_string(gx_device_pdf *pdev, const pdf_text_enum_t *penum, } pet->glyph = glyph; pet->str = gnstr; - /* - * We arbitrarily allow the first encoded character in a given - * position to determine the encoding associated with the copied - * font. - */ - copied_glyph = cfont->procs.encode_char((gs_font *)cfont, ch, - GLYPH_SPACE_NAME); - if (glyph != copied_glyph && - gs_copied_font_add_encoding((gs_font *)cfont, ch, glyph) < 0 - ) - pet->is_difference = true; - pdfont->used[ch >> 3] |= 0x80 >> (ch & 7); } *ppdfont = pdfont; return 0; @@ -282,6 +285,21 @@ process_text_estimate_bbox(pdf_text_enum_t *pte, gs_font_base *font, return 0; } +private void +adjust_first_last_char(pdf_font_resource_t *pdfont, byte *str, int size) +{ + int i; + + for (i = 0; i < size; ++i) { + int chr = str[i]; + + if (chr < pdfont->u.simple.FirstChar) + pdfont->u.simple.FirstChar = chr; + if (chr > pdfont->u.simple.LastChar) + pdfont->u.simple.LastChar = chr; + } +} + /* * Internal procedure to process a string in a non-composite font. * Doesn't use or set pte->{data,size,index}; may use/set pte->xy_index; @@ -296,7 +314,7 @@ private int process_text_return_width(const pdf_text_enum_t *pte, gs_font_base *font, pdf_text_process_state_t *ppts, const gs_const_string *pstr, - gs_point *pdpt); + gs_point *pdpt, int *accepted); private int pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr, pdf_font_resource_t *pdfont, const gs_matrix *pfmat, @@ -305,10 +323,10 @@ pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr, gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev; gs_font_base *font = (gs_font_base *)penum->current_font; const gs_text_params_t *text = &penum->text; - int i; int code = 0, mask; gs_point width_pt; gs_rect text_bbox; + int accepted; if (pfmat == 0) pfmat = &font->FontMatrix; @@ -320,7 +338,8 @@ pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr, /* * Acrobat Reader can't handle text with huge coordinates, - * so skip the text if it is outside the clip bbox. + * so skip the text if it is outside the clip bbox + * (Note : it ever fails with type 3 fonts). */ code = process_text_estimate_bbox(penum, font, (gs_const_string *)pstr, pfmat, &text_bbox, &width_pt); @@ -356,20 +375,6 @@ pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr, return code; mask = code; - /* - * For incrementally loaded fonts, expand FirstChar..LastChar - * if needed. - */ - - for (i = 0; i < pstr->size; ++i) { - int chr = pstr->data[i]; - - if (chr < pdfont->u.simple.FirstChar) - pdfont->u.simple.FirstChar = chr; - if (chr > pdfont->u.simple.LastChar) - pdfont->u.simple.LastChar = chr; - } - if (text->operation & TEXT_REPLACE_WIDTHS) mask |= TEXT_REPLACE_WIDTHS; @@ -387,17 +392,18 @@ pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr, return 0; code = process_text_return_width(penum, font, ppts, (gs_const_string *)pstr, - &width_pt); + &width_pt, &accepted); if (code < 0) return code; if (code == 0) { /* No characters with redefined widths -- the fast case. */ if (text->operation & TEXT_DO_DRAW) { - code = pdf_append_chars(pdev, pstr->data, pstr->size, + code = pdf_append_chars(pdev, pstr->data, accepted, width_pt.x, width_pt.y, false); if (code < 0) return code; - penum->index += pstr->size; + adjust_first_last_char(pdfont, pstr->data + penum->index, accepted); + penum->index += accepted; } } else { /* Use the slow case. Set mask to any non-zero value. */ @@ -405,9 +411,16 @@ pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr, } } if (mask) { + /* process_text_modify_width destroys text parameters, save them now. */ + int index0 = penum->index; + gs_text_params_t text = penum->text; + code = process_text_modify_width(penum, (gs_font *)font, ppts, (gs_const_string *)pstr, &width_pt); + adjust_first_last_char(pdfont, pstr->data, penum->index); + penum->text = text; + penum->index += index0; if (code < 0) return code; } @@ -452,7 +465,7 @@ pdf_char_widths(gx_device_pdf *const pdev, return_error(gs_error_unregistered); /* Must not happen. */ if (pwidths == 0) pwidths = &widths; - if (real_widths[ch] == 0) { + if (real_widths[ch] == 0 && font->FontType != ft_user_defined) { /* Might be an unused char, or just not cached. */ gs_glyph glyph = pdfont->u.simple.Encoding[ch].glyph; @@ -479,10 +492,18 @@ pdf_char_widths(gx_device_pdf *const pdev, real_widths[ch] = pwidths->real_width.w; } } else { + if (font->FontType == ft_user_defined && + !(pdfont->used[ch >> 3] & 0x80 >> (ch & 7))) + return gs_error_undefined; pwidths->Width.w = pdfont->Widths[ch]; pwidths->real_width.w = real_widths[ch]; pwidths->Width.v = pdfont->u.simple.v[ch]; - if (font->WMode) { + if (font->FontType == ft_user_defined) { + pwidths->Width.xy.x = pwidths->Width.w; + pwidths->Width.xy.y = 0; + pwidths->real_width.xy.x = real_widths[ch * 2 + 0]; + pwidths->real_width.xy.y = real_widths[ch * 2 + 1]; + } else if (font->WMode) { pwidths->Width.xy.x = 0; pwidths->Width.xy.y = pwidths->Width.w; pwidths->real_width.xy.x = 0; @@ -506,26 +527,37 @@ private int process_text_return_width(const pdf_text_enum_t *pte, gs_font_base *font, pdf_text_process_state_t *ppts, const gs_const_string *pstr, - gs_point *pdpt) + gs_point *pdpt, int *accepted) { int i; gs_point w; - double scale = 0.001 * ppts->values.size; + double scale; gs_point dpt; int num_spaces = 0; int space_char = (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ? pte->text.space.s_char : -1); - int widths_differ = 0; + int widths_differ = 0, code; + if (font->FontType == ft_user_defined) { + code = font_orig_scale((gs_font *)font, &scale); + if (code < 0) + return code; + scale *= ppts->values.size; + } else + scale = 0.001 * ppts->values.size; for (i = 0, w.x = w.y = 0; i < pstr->size; ++i) { pdf_glyph_widths_t cw; - int code = pdf_char_widths((gx_device_pdf *)pte->dev, + + code = pdf_char_widths((gx_device_pdf *)pte->dev, ppts->values.pdfont, pstr->data[i], font, &cw); - - if (code < 0) + if (code < 0) { + if (i) + break; + *accepted = 0; return code; + } w.x += cw.real_width.xy.x; w.y += cw.real_width.xy.y; if (cw.real_width.xy.x != cw.Width.xy.x || @@ -535,10 +567,11 @@ process_text_return_width(const pdf_text_enum_t *pte, gs_font_base *font, if (pstr->data[i] == space_char) ++num_spaces; } + *accepted = i; gs_distance_transform(w.x * scale, w.y * scale, &ppts->values.matrix, &dpt); if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) { - int num_chars = pstr->size; + int num_chars = *accepted; gs_point tpt; gs_distance_transform(pte->text.delta_all.x, pte->text.delta_all.y, @@ -572,6 +605,7 @@ pdf_glyph_origin(pdf_font_resource_t *pdfont, int ch, int WMode, gs_point *p) case ft_encrypted: case ft_encrypted2: case ft_TrueType: + case ft_user_defined: *p = pdfont->u.simple.v[ch]; break; default: @@ -592,14 +626,22 @@ process_text_modify_width(pdf_text_enum_t *pte, gs_font *font, gs_point *pdpt) { gx_device_pdf *const pdev = (gx_device_pdf *)pte->dev; - double scale = 0.001 * ppts->values.size; + double scale; int space_char = (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ? pte->text.space.s_char : -1); int code = 0; gs_point start, total; bool composite = (ppts->values.pdfont->FontType == ft_composite); + int index0 = pte->index; + if (font->FontType == ft_user_defined) { + code = font_orig_scale((gs_font *)font, &scale); + if (code < 0) + return code; + scale *= ppts->values.size; + } else + scale = 0.001 * ppts->values.size; pte->text.data.bytes = pstr->data; pte->text.size = pstr->size; pte->index = 0; @@ -618,10 +660,13 @@ process_text_modify_width(pdf_text_enum_t *pte, gs_font *font, gs_char chr; gs_glyph glyph; int code, index = pte->index; + gs_text_enum_t pte1 = *(gs_text_enum_t *)pte; - code = pte->orig_font->procs.next_char_glyph((gs_text_enum_t *)pte, &chr, &glyph); - if (code == 2) /* end of string */ + code = pte1.orig_font->procs.next_char_glyph(&pte1, &chr, &glyph); + if (code == 2) { /* end of string */ + gs_text_enum_copy_dynamic((gs_text_enum_t *)pte, &pte1, true); break; + } if (code < 0) return code; if (composite) /* from process_cmap_text */ @@ -630,8 +675,12 @@ process_text_modify_width(pdf_text_enum_t *pte, gs_font *font, code = pdf_char_widths((gx_device_pdf *)pte->dev, ppts->values.pdfont, chr, (gs_font_base *)font, &cw); - if (code < 0) + if (code < 0) { + if (index > 0) + break; return code; + } + gs_text_enum_copy_dynamic((gs_text_enum_t *)pte, &pte1, true); pdf_glyph_origin(ppts->values.pdfont, chr, font->WMode, &v); if (v.x != 0 || v.y != 0) { gs_point glyph_origin_shift; @@ -705,7 +754,12 @@ process_text_modify_width(pdf_text_enum_t *pte, gs_font *font, return code; } -private int +/* + * Get character code from a glyph code. + * An usage of this function is very undesirable, + * because a glyph may be unlisted in Encoding. + */ +int pdf_encode_glyph(gs_font_base *bfont, gs_glyph glyph0, byte *buf, int buf_size, int *char_code_length) { diff --git a/gs/src/gdevpdtf.c b/gs/src/gdevpdtf.c index f5cf38dc2..fa9635518 100644 --- a/gs/src/gdevpdtf.c +++ b/gs/src/gdevpdtf.c @@ -103,6 +103,11 @@ 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_user_defined: + RELOC_VAR(pdfont->u.simple.Encoding); + RELOC_VAR(pdfont->u.simple.v); + RELOC_VAR(pdfont->u.simple.s.type3.char_procs); + break; case ft_CID_encrypted: RELOC_VAR(pdfont->u.cidfont.Widths2); RELOC_VAR(pdfont->u.cidfont.v); @@ -113,9 +118,6 @@ RELOC_PTRS_WITH(pdf_font_resource_reloc_ptrs, pdf_font_resource_t *pdfont) default: RELOC_VAR(pdfont->u.simple.Encoding); RELOC_VAR(pdfont->u.simple.v); - /* falls through */ - case ft_user_defined: - RELOC_VAR(pdfont->u.simple.s.type3.char_procs); break; } } @@ -362,7 +364,7 @@ font_resource_simple_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, *ppfres = pfres; return 0; } -private int +int font_resource_encoded_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, gs_id rid, font_type ftype, pdf_font_write_contents_proc_t write_contents) @@ -639,7 +641,7 @@ pdf_font_type0_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, /* ------ Type 3 ------ */ -/* Allocate a Type 3 font resource. */ +/* Allocate a Type 3 font resource for sinthesyzed bitmap fonts. */ int pdf_font_type3_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, pdf_font_write_contents_proc_t write_contents) diff --git a/gs/src/gdevpdtf.h b/gs/src/gdevpdtf.h index 30da860dc..8bf3f53d9 100644 --- a/gs/src/gdevpdtf.h +++ b/gs/src/gdevpdtf.h @@ -221,8 +221,10 @@ struct pdf_font_resource_s { struct /*type3*/ { gs_int_rect FontBBox; + gs_matrix FontMatrix; pdf_char_proc_t *char_procs; int max_y_offset; + bool bitmap_font; } type3; } s; @@ -312,6 +314,10 @@ int pdf_font_cidfont_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, gs_id rid, pdf_font_descriptor_t *pfd); int pdf_obtain_cidfont_widths_arrays(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, int wmode, double **w, double **v); +int font_resource_encoded_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres, + gs_id rid, font_type ftype, + pdf_font_write_contents_proc_t write_contents); + /* * Return the (copied, subset or complete) font associated with a font resource. * If this font resource doesn't have a descriptor (Type 0, Type 3, or diff --git a/gs/src/gdevpdti.c b/gs/src/gdevpdti.c index 6709d15f5..a1ecf4ccb 100644 --- a/gs/src/gdevpdti.c +++ b/gs/src/gdevpdti.c @@ -20,6 +20,7 @@ #include "string_.h" #include "gx.h" #include "gserrors.h" +#include "gsutil.h" #include "gdevpdfx.h" #include "gdevpdtf.h" #include "gdevpdti.h" @@ -36,13 +37,14 @@ struct pdf_char_proc_s { pdf_font_resource_t *font; pdf_char_proc_t *char_next; /* next char_proc for same font */ int y_offset; /* of character (0,0) */ - byte char_code; + gs_char char_code; + gs_const_string char_name; }; /* The descriptor is public for pdf_resource_type_structs. */ -gs_public_st_suffix_add2(st_pdf_char_proc, pdf_char_proc_t, +gs_public_st_suffix_add2_string1(st_pdf_char_proc, pdf_char_proc_t, "pdf_char_proc_t", pdf_char_proc_enum_ptrs, pdf_char_proc_reloc_ptrs, - st_pdf_resource, font, char_next); + st_pdf_resource, font, char_next, char_name); /* Define the state structure for tracking bitmap fonts. */ /*typedef struct pdf_bitmap_fonts_s pdf_bitmap_fonts_t;*/ @@ -62,8 +64,6 @@ pdf_char_proc_id(const pdf_char_proc_t *pcp) return pdf_resource_id((const pdf_resource_t *)pcp); } -private int write_contents_bitmap(gx_device_pdf *, pdf_font_resource_t *); - /* Assign a code for a char_proc. */ private int assign_char_code(gx_device_pdf * pdev, int width) @@ -80,13 +80,19 @@ assign_char_code(gx_device_pdf * pdev, int width) /* Start a new synthesized font. */ char *pc; - code = pdf_font_type3_alloc(pdev, &pdfont, write_contents_bitmap); + code = pdf_font_type3_alloc(pdev, &pdfont, pdf_write_contents_bitmap); if (code < 0) return code; + pdfont->u.simple.s.type3.bitmap_font = true; if (pbfs->open_font == 0) pdfont->rname[0] = 0; else strcpy(pdfont->rname, pbfs->open_font->rname); + pdfont->u.simple.s.type3.FontBBox.p.x = 0; + pdfont->u.simple.s.type3.FontBBox.p.y = 0; + pdfont->u.simple.s.type3.FontBBox.q.x = 1000; + pdfont->u.simple.s.type3.FontBBox.q.y = 1000; + gs_make_identity(&pdfont->u.simple.s.type3.FontMatrix); /* * We "increment" the font name as a radix-26 "number". * This cannot possibly overflow. @@ -114,32 +120,54 @@ assign_char_code(gx_device_pdf * pdev, int width) return c; } -/* Write the contents of a Type 3 bitmap font resource. */ -private int -write_contents_bitmap(gx_device_pdf *pdev, pdf_font_resource_t *pdfont) +/* Write the contents of a Type 3 bitmap or vector font resource. */ +int +pdf_write_contents_bitmap(gx_device_pdf *pdev, pdf_font_resource_t *pdfont) { stream *s = pdev->strm; - - pprintld1(s, "/Encoding %ld 0 R/CharProcs", - pdev->text->bitmap_fonts->bitmap_encoding_id); - - /* Write the CharProcs. */ - { - const pdf_char_proc_t *pcp; - - stream_puts(s, "<<"); - /* Write real characters. */ - for (pcp = pdfont->u.simple.s.type3.char_procs; pcp; - pcp = pcp->char_next - ) { - pprintld2(s, "/a%ld\n%ld 0 R", (long)pcp->char_code, + const pdf_char_proc_t *pcp; + long diff_id = 0; + int code, i; + + if (pdfont->u.simple.s.type3.bitmap_font) + diff_id = pdev->text->bitmap_fonts->bitmap_encoding_id; + else { + /* See comment in pdf_write_encoding. */ + diff_id = pdf_obj_ref(pdev); + } + code = pdf_write_encoding_ref(pdev, pdfont, diff_id); + if (code < 0) + return code; + stream_puts(s, "/CharProcs <<"); + /* Write real characters. */ + for (pcp = pdfont->u.simple.s.type3.char_procs; pcp; + pcp = pcp->char_next + ) { + if (pdfont->u.simple.s.type3.bitmap_font) + pprintld2(s, "/a%ld %ld 0 R\n", (long)pcp->char_code, pdf_char_proc_id(pcp)); + else { + pdf_put_name(pdev, pcp->char_name.data, pcp->char_name.size); + pprintld1(s, " %ld 0 R\n", pdf_char_proc_id(pcp)); } - stream_puts(s, ">>"); } - - stream_puts(s, "/FontMatrix[1 0 0 1 0 0]"); - return pdf_finish_write_contents_type3(pdev, pdfont); + stream_puts(s, ">>"); + pprintg6(s, "/FontMatrix[%g %g %g %g %g %g]", + (float)pdfont->u.simple.s.type3.FontMatrix.xx, + (float)pdfont->u.simple.s.type3.FontMatrix.xy, + (float)pdfont->u.simple.s.type3.FontMatrix.yx, + (float)pdfont->u.simple.s.type3.FontMatrix.yy, + (float)pdfont->u.simple.s.type3.FontMatrix.tx, + (float)pdfont->u.simple.s.type3.FontMatrix.ty); + code = pdf_finish_write_contents_type3(pdev, pdfont); + if (code < 0) + return code; + if (!pdfont->u.simple.s.type3.bitmap_font && diff_id > 0) { + code = pdf_write_encoding(pdev, pdfont, diff_id, 0); + if (code < 0) + return code; + } + return 0; } /* ---------------- Public ---------------- */ @@ -199,39 +227,31 @@ pdf_char_image_y_offset(const gx_device_pdf *pdev, int x, int y, int h) return off; } -/* Begin a CharProc for a synthesized (bitmap) font. */ -int -pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width, - int y_offset, gs_id id, pdf_char_proc_t ** ppcp, - pdf_stream_position_t * ppos) +/* Begin a CharProc for a synthesized font. */ +private int +pdf_begin_char_proc_gerneric(gx_device_pdf * pdev, pdf_font_resource_t *pdfont, + gs_id id, gs_char char_code, gs_const_string *gnstr, + pdf_char_proc_t ** ppcp, pdf_stream_position_t * ppos) { pdf_resource_t *pres; pdf_char_proc_t *pcp; - int char_code = assign_char_code(pdev, x_width); - pdf_bitmap_fonts_t *const pbfs = pdev->text->bitmap_fonts; - pdf_font_resource_t *font = pbfs->open_font; /* Type 3 */ + /* fixme : obsolete naming. It's not exactly a bitmap font. Should be text->type3_fonts. */ int code; - if (char_code < 0) - return char_code; code = pdf_begin_resource(pdev, resourceCharProc, id, &pres); if (code < 0) return code; pcp = (pdf_char_proc_t *) pres; - pcp->font = font; - pcp->char_next = font->u.simple.s.type3.char_procs; - font->u.simple.s.type3.char_procs = pcp; + pcp->font = pdfont; + pcp->char_next = pdfont->u.simple.s.type3.char_procs; + pdfont->u.simple.s.type3.char_procs = pcp; pcp->char_code = char_code; - pcp->y_offset = y_offset; - font->u.simple.s.type3.FontBBox.p.y = - min(font->u.simple.s.type3.FontBBox.p.y, y_offset); - font->u.simple.s.type3.FontBBox.q.x = - max(font->u.simple.s.type3.FontBBox.q.x, w); - font->u.simple.s.type3.FontBBox.q.y = - max(font->u.simple.s.type3.FontBBox.q.y, y_offset + h); - font->u.simple.s.type3.max_y_offset = - max(font->u.simple.s.type3.max_y_offset, h + (h >> 2)); - *ppcp = pcp; + if (gnstr == 0) { + pcp->char_name.data = 0; + pcp->char_name.size = 0; + } else + pcp->char_name = *gnstr; + { stream *s = pdev->strm; @@ -245,6 +265,32 @@ pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width, stream_puts(s, "<</Length >>stream\n"); ppos->start_pos = stell(s); } + *ppcp = pcp; + return 0; +} + +/* Begin a CharProc for a synthesized (bitmap) font. */ +int +pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width, + int y_offset, gs_id id, pdf_char_proc_t ** ppcp, + pdf_stream_position_t * ppos) +{ + int char_code = assign_char_code(pdev, x_width); + pdf_bitmap_fonts_t *const pbfs = pdev->text->bitmap_fonts; + pdf_font_resource_t *font = pbfs->open_font; /* Type 3 */ + int code = pdf_begin_char_proc_gerneric(pdev, font, id, char_code, NULL, ppcp, ppos); + + if (code < 0) + return code; + (*ppcp)->y_offset = y_offset; + font->u.simple.s.type3.FontBBox.p.y = + min(font->u.simple.s.type3.FontBBox.p.y, y_offset); + font->u.simple.s.type3.FontBBox.q.x = + max(font->u.simple.s.type3.FontBBox.q.x, w); + font->u.simple.s.type3.FontBBox.q.y = + max(font->u.simple.s.type3.FontBBox.q.y, y_offset + h); + font->u.simple.s.type3.max_y_offset = + max(font->u.simple.s.type3.max_y_offset, h + (h >> 2)); return 0; } @@ -320,3 +366,100 @@ pdf_write_bitmap_fonts_Encoding(gx_device_pdf *pdev) } return 0; } + +/* + * Install charproc accumulator for a Type 3 font. + */ +int +pdf_install_charproc_accum(gx_device_pdf *pdev, gs_font *font, const double *pw, + gs_text_cache_control_t control, gs_char ch, gs_const_string *gnstr, + gs_id *pid, pdf_stream_position_t *charproc_pos) +{ + pdf_char_proc_t *pcp; + gs_id id = gs_next_ids(1); + pdf_font_resource_t *pdfont; + byte *glyph_usage; + double *real_widths; + int char_cache_size, width_cache_size; + int code; + + code = pdf_attached_font_resource(pdev, font, &pdfont, + &glyph_usage, &real_widths, &char_cache_size, &width_cache_size); + if (code < 0) + return code; + if (ch != GS_NO_CHAR) { + int i; + gs_glyph glyph0 = font->procs.encode_char(font, ch, GLYPH_SPACE_NAME); + + if (ch >= char_cache_size || ch >= width_cache_size) + return_error(gs_error_unregistered); + real_widths[ch * 2 ] = pdfont->Widths[ch] = pw[font->WMode ? 6 : 0]; + real_widths[ch * 2 + 1] = pw[font->WMode ? 7 : 1]; + glyph_usage[ch / 8] |= 0x80 >> (ch & 7); + pdfont->used[ch >> 3] |= 0x80 >> (ch & 7); + if (pdfont->u.simple.v != NULL && font->WMode) { + pdfont->u.simple.v[ch].x = pw[8]; + pdfont->u.simple.v[ch].y = pw[9]; + } + for (i = 0; i < 256; i++) { + gs_glyph glyph = font->procs.encode_char(font, i, GLYPH_SPACE_NAME); + + if (glyph == glyph0) { + real_widths[i * 2 ] = real_widths[ch * 2 ]; + real_widths[i * 2 + 1] = real_widths[ch * 2 + 1]; + glyph_usage[i / 8] |= 0x80 >> (i & 7); + pdfont->used[i >> 3] |= 0x80 >> (i & 7); + pdfont->u.simple.v[i] = pdfont->u.simple.v[ch]; + pdfont->Widths[i] = pdfont->Widths[ch]; + } + } + } + pdev->accum_char_proc_context_save = pdev->context; + pdf_text_state_copy(pdev->accum_char_proc_text_state_save, pdev->text->text_state); + pdf_set_text_state_default(pdev->text->text_state); + pdev->accum_char_proc_clip_path_save = pdev->clip_path; + pdev->accum_char_proc_clip_path_id_save = pdev->clip_path_id; + pdev->accum_char_proc_vgstack_depth_save = pdev->vgstack_depth; + pdev->clip_path = 0; + pdev->clip_path_id = pdev->no_clip_path_id; + code = pdf_begin_char_proc_gerneric(pdev, pdfont, id, ch, gnstr, &pcp, charproc_pos); + if (code < 0) + return code; + *pid = id; + pdev->accum_char_proc = true; + pdev->context = PDF_IN_STREAM; + if (control == TEXT_SET_CHAR_WIDTH) + pprintg2(pdev->strm, "%g %g d0\n", (float)pw[0], (float)pw[1]); + else + pprintg6(pdev->strm, "%g %g %g %g %g %g d1\n", + (float)pw[0], (float)pw[1], (float)pw[2], + (float)pw[3], (float)pw[4], (float)pw[5]); + return 0; +} + +/* + * Complete charproc accumulation for a Type 3 font. + */ +int +pdf_end_charproc_accum(gx_device_pdf *pdev, gs_id id, pdf_stream_position_t *ppos) +{ + int code = pdf_open_contents(pdev, PDF_IN_STREAM), code1; + + while (pdev->vgstack_depth > pdev->accum_char_proc_vgstack_depth_save) { + code1 = pdf_restore_viewer_state(pdev, pdev->strm); + if (code >= 0) + code = code1; + } + if (pdev->clip_path != 0) + gx_path_free(pdev->clip_path, "pdf_end_charproc_accum"); + pdev->clip_path = pdev->accum_char_proc_clip_path_save; + pdev->clip_path_id = pdev->accum_char_proc_clip_path_id_save; + pdev->accum_char_proc_vgstack_depth_save = 0; + code1 = pdf_end_char_proc(pdev, ppos); + if (code >= 0) + code = code1; + pdev->context = pdev->accum_char_proc_context_save; + pdf_text_state_copy(pdev->text->text_state, pdev->accum_char_proc_text_state_save); + pdev->accum_char_proc = false; + return code; +} diff --git a/gs/src/gdevpdti.h b/gs/src/gdevpdti.h index 9dd52dffd..7b48d2fb7 100644 --- a/gs/src/gdevpdti.h +++ b/gs/src/gdevpdti.h @@ -72,4 +72,7 @@ pdf_bitmap_fonts_t *pdf_bitmap_fonts_alloc(gs_memory_t *mem); */ int pdf_write_bitmap_fonts_Encoding(gx_device_pdf *pdev); +/* Write the contents of a Type 3 bitmap font resource. */ +int pdf_write_contents_bitmap(gx_device_pdf *pdev, pdf_font_resource_t *pdfont); + #endif /* gdevpdti_INCLUDED */ diff --git a/gs/src/gdevpdts.c b/gs/src/gdevpdts.c index 7b7c4b26d..1172be0d2 100644 --- a/gs/src/gdevpdts.c +++ b/gs/src/gdevpdts.c @@ -285,12 +285,30 @@ pdf_text_state_alloc(gs_memory_t *mem) } /* + * Set the text state to default values. + */ +void +pdf_set_text_state_default(pdf_text_state_t *pts) +{ + *pts = ts_default; +} + +/* + * Copy the text state. + */ +void +pdf_text_state_copy(pdf_text_state_t *pts_to, pdf_text_state_t *pts_from) +{ + *pts_to = *pts_from; +} + +/* * Reset the text state to its condition at the beginning of the page. */ void pdf_reset_text_page(pdf_text_data_t *ptd) { - *ptd->text_state = ts_default; + pdf_set_text_state_default(ptd->text_state); } /* @@ -398,9 +416,9 @@ sync_text_state(gx_device_pdf *pdev) ((pdf_resource_t *)pdfont)->where_used |= pdev->used_mask; } - if (memcmp(&pts->in.matrix, &pts->out.matrix.xx, sizeof(pts->in.matrix)) || - pts->start.x != pts->out_pos.x || - pts->start.y != pts->out_pos.y) { + if (memcmp(&pts->in.matrix, &pts->out.matrix, sizeof(pts->in.matrix)) || + ((pts->start.x != pts->out_pos.x || pts->start.y != pts->out_pos.y) && + (pts->buffer.count_chars != 0 || pts->buffer.count_moves != 0))) { /* pdf_set_text_matrix sets out.matrix = in.matrix */ code = pdf_set_text_matrix(pdev); if (code < 0) diff --git a/gs/src/gdevpdts.h b/gs/src/gdevpdts.h index 15b443b0c..1c38ca1d4 100644 --- a/gs/src/gdevpdts.h +++ b/gs/src/gdevpdts.h @@ -63,23 +63,6 @@ typedef struct pdf_text_state_values_s { /* ================ Procedures ================ */ -/* ------ Exported for gdevpdf.c ------ */ - -/* - * Allocate and initialize text state bookkeeping. - */ -pdf_text_state_t *pdf_text_state_alloc(gs_memory_t *mem); - -/* - * Reset the text state at the beginning of the page. - */ -void pdf_reset_text_page(pdf_text_data_t *ptd); - -/* - * Reset the text state after a grestore. - */ -void pdf_reset_text_state(pdf_text_data_t *ptd); - /* ------ Exported for gdevpdfu.c ------ */ /* diff --git a/gs/src/gdevpdtt.c b/gs/src/gdevpdtt.c index 1f3e354e3..fb7b15aea 100644 --- a/gs/src/gdevpdtt.c +++ b/gs/src/gdevpdtt.c @@ -27,6 +27,7 @@ #include "gxfcopy.h" #include "gxfcmap.h" #include "gxpath.h" /* for getting current point */ +#include "gxchar.h" #include "gdevpdfx.h" #include "gdevpdfg.h" #include "gdevpdtx.h" @@ -34,6 +35,7 @@ #include "gdevpdtf.h" #include "gdevpdts.h" #include "gdevpdtt.h" +#include "gdevpdti.h" /* ================ Text enumerator ================ */ @@ -102,6 +104,68 @@ pdf_text_set_cache(gs_text_enum_t *pte, const double *pw, default: return_error(gs_error_rangecheck); } + if (penum->current_font->FontType == ft_user_defined && + !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) { + int code; + gs_font *font = penum->orig_font; + gs_char ch; + gs_glyph glyph; + gs_const_string gnstr; + gs_matrix m; + + if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) { + byte buf[1]; + int char_code_length; + + glyph = pte->text.data.d_glyph; + code = pdf_encode_glyph((gs_font_base *)font, glyph, + buf, sizeof(buf), &char_code_length); + if (code < 0) { + /* Must not happen, becuse pdf_encode_glyph was passed in process_plain_text.*/ + ch = GS_NO_CHAR; + } else if (char_code_length != 1) { + /* Must not happen with type 3 fonts.*/ + ch = GS_NO_CHAR; + } else + ch = buf[0]; + } else { + ch = penum->text.data.bytes[penum->index]; + glyph = font->procs.encode_char(font, ch, GLYPH_SPACE_NAME); + /* + * If glyph == GS_NO_GLYPH, we should replace it with + * a notdef glyph, but we don't know how to do with Type 3 fonts. + */ + } + if (glyph != GS_NO_GLYPH && ch != GS_NO_CHAR) { + gs_fixed_rect clip_box; + gs_show_enum *const penum_s = (gs_show_enum *)penum->pte_default; + + code = font->procs.glyph_name(font, glyph, &gnstr); + if (code < 0) + return_error(gs_error_unregistered); /* Must not happen. */ + gs_make_identity(&m); + gs_matrix_fixed_from_matrix(&penum->pis->ctm, &m); + if (control != TEXT_SET_CHAR_WIDTH) { + clip_box.p.x = float2fixed(pw[2]); + clip_box.p.y = float2fixed(pw[3]); + clip_box.q.x = float2fixed(pw[4]); + clip_box.q.y = float2fixed(pw[5]); + } else { + gs_font_base *bfont = (gs_font_base *)font; + + clip_box.p.x = float2fixed(bfont->FontBBox.p.x); + clip_box.p.y = float2fixed(bfont->FontBBox.p.y); + clip_box.q.x = float2fixed(bfont->FontBBox.q.x); + clip_box.q.y = float2fixed(bfont->FontBBox.q.y); + } + code = gx_clip_to_rectangle(penum_s->pgs, &clip_box); + if (code < 0) + return code; + return pdf_install_charproc_accum(pdev, pte->orig_font, + pw, control, ch, &gnstr, + &penum->charproc_id, &penum->charproc_pos); + } + } if (penum->pte_default) { if (penum->pte_default->text.operation & TEXT_DO_CHARWIDTH /* See process_cmap_text.*/) return gs_text_set_cache(penum->pte_default, pw, TEXT_SET_CHAR_WIDTH); @@ -139,6 +203,7 @@ private const gs_text_enum_procs_t pdf_text_procs = { pdf_text_set_cache, pdf_text_retry, pdf_text_release }; + int gdev_pdf_text_begin(gx_device * dev, gs_imager_state * pis, const gs_text_params_t *text, gs_font * font, @@ -216,6 +281,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_id = 0; code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs, dev, pis, text, font, path, pdcolor, pcpath, mem); if (code < 0) { @@ -337,7 +403,8 @@ alloc_font_cache_elem_arrays(gx_device_pdf *pdev, pdf_font_cache_elem_t *e, len, "alloc_font_cache_elem_arrays"); e->real_widths = (num_widths > 0 ? (double *)gs_alloc_bytes(pdev->pdf_memory, - num_widths * sizeof(*e->real_widths), + num_widths * sizeof(*e->real_widths) * + (font->FontType == ft_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, @@ -455,6 +522,7 @@ pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat) case ft_encrypted: case ft_encrypted2: case ft_CID_encrypted: + case ft_user_defined: /* * Type 1 fonts are supposed to use a standard FontMatrix of * [0.001 0 0 0.001 0 0], with a 1000-unit cell. However, @@ -479,7 +547,9 @@ pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat) while (base_font->base != base_font) base_font = base_font->base; - if (base_font->FontMatrix.xx == 1.0/2048 && + if (font->FontType == ft_user_defined) + *pmat = base_font->FontMatrix; + else if (base_font->FontMatrix.xx == 1.0/2048 && base_font->FontMatrix.xy == 0 && base_font->FontMatrix.yx == 0 && any_abs(base_font->FontMatrix.yy) == 1.0/2048 @@ -494,7 +564,7 @@ pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat) } } -private int +int font_orig_scale(const gs_font *font, double *sx) { gs_matrix mat; @@ -544,6 +614,10 @@ pdf_is_compatible_encoding(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, } } return false; + case ft_user_defined: + if (pdfont->u.simple.Encoding == NULL) + return false; /* Not sure. Happens with 020-01.ps . */ + /* fall through */ case ft_encrypted: case ft_encrypted2: case ft_TrueType: @@ -696,7 +770,6 @@ pdf_make_font_resource(gx_device_pdf *pdev, gs_font *font, int BaseEncoding = ENCODING_INDEX_UNKNOWN; pdf_font_embed_t embed; pdf_font_descriptor_t *pfd = 0; - pdf_resource_type_t rtype; int (*font_alloc)(gx_device_pdf *, pdf_font_resource_t **, gs_id, pdf_font_descriptor_t *); gs_font *base_font = font; /* A roudiment from old code. Keep it for a while. */ @@ -727,15 +800,32 @@ pdf_make_font_resource(gx_device_pdf *pdev, gs_font *font, switch (font->FontType) { case ft_CID_encrypted: case ft_CID_TrueType: - rtype = resourceCIDFont; font_alloc = pdf_font_cidfont_alloc; break; case ft_encrypted: case ft_encrypted2: case ft_TrueType: - rtype = resourceFont; font_alloc = pdf_font_simple_alloc; break; + case ft_user_defined: + { + const gs_font_base *bfont = (const gs_font_base *)font; + + code = font_resource_encoded_alloc(pdev, &pdfont, gs_no_id, + ft_user_defined, pdf_write_contents_bitmap); + if (code < 0) + return code; + pdfont->u.simple.s.type3.bitmap_font = false; + pdfont->u.simple.BaseEncoding = pdf_refine_encoding_index( + bfont->nearest_encoding_index, true); + pdfont->u.simple.s.type3.FontBBox.p.x = (int)bfont->FontBBox.p.x; + pdfont->u.simple.s.type3.FontBBox.p.y = (int)bfont->FontBBox.p.y; + pdfont->u.simple.s.type3.FontBBox.q.x = (int)bfont->FontBBox.q.x; + pdfont->u.simple.s.type3.FontBBox.q.y = (int)bfont->FontBBox.q.y; + pdfont->u.simple.s.type3.FontMatrix = bfont->FontMatrix; + *ppdfont = pdfont; + return 1; + } case ft_composite: { /* Composite fonts don't have descriptors. */ @@ -813,7 +903,7 @@ pdf_make_font_resource(gx_device_pdf *pdev, gs_font *font, return code; code = 1; - if (rtype == resourceFont) /* i.e. not CIDFont */ + if (!pdf_is_CID_font(font)) pdfont->u.simple.BaseEncoding = BaseEncoding; *ppdfont = pdfont; @@ -828,7 +918,8 @@ pdf_is_simple_font(gs_font *font) { return (font->FontType == ft_encrypted || font->FontType == ft_encrypted2 || - font->FontType == ft_TrueType); + font->FontType == ft_TrueType || + font->FontType == ft_user_defined); } /* @@ -983,10 +1074,13 @@ pdf_obtain_font_resource(const gs_text_enum_t *penum, ofont = font0->data.FDepVector[0]; } else cfont = pdf_font_resource_font(*ppdfont, false); - code = gs_copied_can_copy_glyphs((gs_font *)cfont, ofont, + if (font->FontType != ft_user_defined) { + code = gs_copied_can_copy_glyphs((gs_font *)cfont, ofont, glyphs + glyphs_offset, num_unused_chars, false); - if (code < 0) - goto out; + if (code < 0) + goto out; + } else + code = 1; if (code == 0) *ppdfont = 0; else if(!pdf_is_compatible_encoding(pdev, *ppdfont, font, @@ -1272,13 +1366,63 @@ pdf_set_text_process_state(gx_device_pdf *pdev, return pdf_set_text_state_values(pdev, &ppts->values); } +private int +store_glyph_width(pdf_glyph_width_t *pwidth, int wmode, double scale, + const gs_glyph_info_t *pinfo) +{ + double w, v; + + pwidth->xy.x = pinfo->width[wmode].x * scale; + pwidth->xy.y = pinfo->width[wmode].y * scale; + if (wmode) + w = pwidth->xy.y, v = pwidth->xy.x; + else + w = pwidth->xy.x, v = pwidth->xy.y; + if (v != 0) + return 1; + pwidth->w = w; + pwidth->v.x = pinfo->v.x * scale; + pwidth->v.y = pinfo->v.y * scale; + return 0; +} + +private int +get_missing_width(gs_font_base *cfont, int wmode, double scale_c, + pdf_glyph_widths_t *pwidths) +{ + gs_font_info_t finfo; + int code; + + code = cfont->procs.font_info((gs_font *)cfont, NULL, + FONT_INFO_MISSING_WIDTH, &finfo); + if (code < 0) + return code; + if (wmode) { + pwidths->Width.xy.x = pwidths->real_width.xy.x = 0; + pwidths->Width.xy.y = pwidths->real_width.xy.y = + finfo.MissingWidth * scale_c; + pwidths->Width.w = pwidths->real_width.w = + pwidths->Width.xy.y; + } else { + pwidths->Width.xy.x = pwidths->real_width.xy.x = + finfo.MissingWidth * scale_c; + pwidths->Width.w = pwidths->real_width.w = + pwidths->Width.xy.x; + pwidths->Width.xy.y = pwidths->real_width.xy.y = 0; + } + /* + * Don't mark the width as known, just in case this is an + * incrementally defined font. + */ + return 1; +} + + /* * Get the widths (unmodified from the copied font, * and possibly modified from the original font) of a given glyph. * Return 1 if the width was defaulted to MissingWidth. */ -private int store_glyph_width(pdf_glyph_width_t *pwidth, int wmode, - double scale, const gs_glyph_info_t *pinfo); int pdf_glyph_widths(pdf_font_resource_t *pdfont, int wmode, gs_glyph glyph, gs_font *orig_font, pdf_glyph_widths_t *pwidths) @@ -1292,6 +1436,7 @@ pdf_glyph_widths(pdf_font_resource_t *pdfont, int wmode, gs_glyph glyph, double sxc, sxo; double scale_c, scale_o; int code, rcode = 0; + gs_point v; if (ofont->FontType == ft_composite) { gs_font_type0 *const pfont = (gs_font_type0 *)ofont; @@ -1309,91 +1454,45 @@ pdf_glyph_widths(pdf_font_resource_t *pdfont, int wmode, gs_glyph glyph, pwidths->Width.v.x = pwidths->Width.v.y = 0; pwidths->real_width.v.x = pwidths->real_width.v.y = 0; pwidths->replaced_v = false; - if (glyph != GS_NO_GLYPH && - (code = cfont->procs.glyph_info((gs_font *)cfont, glyph, NULL, - (GLYPH_INFO_WIDTH0 << wmode) | - GLYPH_INFO_OUTLINE_WIDTHS | + if (glyph == GS_NO_GLYPH) + return get_missing_width(cfont, wmode, scale_c, pwidths); + code = cfont->procs.glyph_info((gs_font *)cfont, glyph, NULL, + (GLYPH_INFO_WIDTH0 << wmode) | + GLYPH_INFO_OUTLINE_WIDTHS | + (GLYPH_INFO_VVECTOR0 << wmode), + &info); + if (code == gs_error_undefined) + return get_missing_width(cfont, wmode, scale_c, pwidths); + else if (code < 0) + return code; + code = store_glyph_width(&pwidths->Width, wmode, scale_c, &info); + if (code < 0) + return code; + rcode |= code; + v = info.v; + if (code > 0) + pwidths->Width.xy.x = pwidths->Width.xy.y = pwidths->Width.w = 0; + rcode |= code; + code = ofont->procs.glyph_info(ofont, glyph, NULL, + (GLYPH_INFO_WIDTH0 << wmode) | (GLYPH_INFO_VVECTOR0 << wmode), - &info)) != gs_error_undefined - ) { - gs_point v; - - if (code < 0 || - (code = store_glyph_width(&pwidths->Width, wmode, - scale_c, &info)) < 0 - ) - return code; - if (code > 0) - pwidths->Width.xy.x = pwidths->Width.xy.y = pwidths->Width.w = 0; - v = info.v; - rcode |= code; - if ((code = ofont->procs.glyph_info(ofont, glyph, NULL, - (GLYPH_INFO_WIDTH0 << wmode) | - (GLYPH_INFO_VVECTOR0 << wmode), - &info)) != gs_error_undefined - ) { - if ((info.members & (GLYPH_INFO_VVECTOR0 << wmode)) != 0) - pwidths->replaced_v = true; - if (code < 0 || - (code = store_glyph_width(&pwidths->real_width, wmode, - scale_o, &info)) < 0 - ) - return code; - rcode |= code; - pwidths->Width.v = v; - pwidths->real_width.v = info.v; - } else - pwidths->real_width = pwidths->Width; - return rcode; - } - /* Try for MissingWidth. */ - { - gs_font_info_t finfo; - - code = cfont->procs.font_info((gs_font *)cfont, NULL, - FONT_INFO_MISSING_WIDTH, &finfo); + &info); + if (code == gs_error_undefined) + pwidths->real_width = pwidths->Width; + else if (code < 0) + return code; + else { + if ((info.members & (GLYPH_INFO_VVECTOR0 << wmode)) != 0) + pwidths->replaced_v = true; + code = store_glyph_width(&pwidths->real_width, wmode, scale_o, &info); if (code < 0) return code; - if (wmode) { - pwidths->Width.xy.x = pwidths->real_width.xy.x = 0; - pwidths->Width.xy.y = pwidths->real_width.xy.y = - finfo.MissingWidth * scale_c; - pwidths->Width.w = pwidths->real_width.w = - pwidths->Width.xy.y; - } else { - pwidths->Width.xy.x = pwidths->real_width.xy.x = - finfo.MissingWidth * scale_c; - pwidths->Width.w = pwidths->real_width.w = - pwidths->Width.xy.x; - pwidths->Width.xy.y = pwidths->real_width.xy.y = 0; - } - /* - * Don't mark the width as known, just in case this is an - * incrementally defined font. - */ - return 1; + rcode |= code; + pwidths->Width.v = v; + pwidths->real_width.v = info.v; } + return rcode; } -private int -store_glyph_width(pdf_glyph_width_t *pwidth, int wmode, double scale, - const gs_glyph_info_t *pinfo) -{ - double w, v; - - pwidth->xy.x = pinfo->width[wmode].x * scale; - pwidth->xy.y = pinfo->width[wmode].y * scale; - if (wmode) - w = pwidth->xy.y, v = pwidth->xy.x; - else - w = pwidth->xy.x, v = pwidth->xy.y; - if (v != 0) - return 1; - pwidth->w = w; - pwidth->v.x = pinfo->v.x * scale; - pwidth->v.y = pinfo->v.y * scale; - return 0; -} - /* ---------------- Main entry ---------------- */ /* @@ -1423,6 +1522,8 @@ pdf_text_process(gs_text_enum_t *pte) gs_text_enum_t *pte_default; PROCESS_TEXT_PROC((*process)); int code = -1; /* to force default implementation */ + gx_device_pdf *pdev = (gx_device_pdf *)penum->dev; + bool charproc = pdev->accum_char_proc; #define BUF_SIZE 100 /* arbitrary > 0 */ /* @@ -1431,12 +1532,27 @@ pdf_text_process(gs_text_enum_t *pte) top: pte_default = penum->pte_default; if (pte_default) { - gx_device_pdf *pdev = (gx_device_pdf *)penum->dev; - + if (penum->charproc_id) { + code = pdf_end_charproc_accum(pdev, penum->charproc_id, &penum->charproc_pos); + if (code < 0) + return code; + penum->charproc_id = 0; + 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; + goto top; + } 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 . */ - gs_text_enum_copy_dynamic(pte, pte_default, true); + if (pte->current_font->FontType != ft_user_defined) + gs_text_enum_copy_dynamic(pte, pte_default, true); + else { + penum->returned.current_char = pte_default->returned.current_char; + penum->returned.current_glyph = pte_default->returned.current_glyph; + } if (code) return code; gs_text_release(pte_default, "pdf_text_process"); @@ -1454,6 +1570,7 @@ pdf_text_process(gs_text_enum_t *pte) case ft_encrypted: case ft_encrypted2: case ft_TrueType: + case ft_user_defined: /* The data may be either glyphs or characters. */ process = process_plain_text; break; @@ -1504,9 +1621,11 @@ pdf_text_process(gs_text_enum_t *pte) code = process(pte, vdata, buf, size); gs_free_string(pte->memory, buf, size, "pdf_text_process"); } - skip: - if (code < 0) { + if (code < 0 || + (pte->current_font->FontType == ft_user_defined && + code != TEXT_PROCESS_INTERVENE && + penum->index < penum->text.size)) { if (code == gs_error_unregistered) /* Debug purpose only. */ return code; if (code == gs_error_VMerror) @@ -1522,4 +1641,17 @@ pdf_text_process(gs_text_enum_t *pte) if (penum->pte_default && !code) goto top; return code; + /* + * This function uses an unobvious algorithm while handling type 3 fonts. + * It runs 'process' to copy text until a glyph, which was not copied to + * output font. Then it installs pte_default and falls back to default + * implementation with PS interpreter callout. The callout executes + * BuildChar/BuildGlyph with setcachedevice. The latter calls + * pdf_install_charproc_accum, which sets up an accumulator + * of graphic objects to a pdf_begin_resource stream. + * When the callout completes, pdf_text_process calls pdf_end_charproc_accum + * and later resumes the normal (non-default) text enumeration, repeating the + * the "callouted" glyph AT SECOND TIME. We can't do without the second pass + * becauase in the first pass the glyph widths is unknown. + */ } diff --git a/gs/src/gdevpdtt.h b/gs/src/gdevpdtt.h index 143800847..233461209 100644 --- a/gs/src/gdevpdtt.h +++ b/gs/src/gdevpdtt.h @@ -88,6 +88,8 @@ typedef struct pdf_text_enum_s { gs_text_enum_common; gs_text_enum_t *pte_default; gs_fixed_point origin; + gs_id charproc_id; + pdf_stream_position_t charproc_pos; } pdf_text_enum_t; #define private_st_pdf_text_enum()\ extern_st(st_gs_text_enum);\ @@ -140,6 +142,7 @@ typedef struct pdf_glyph_widths_s { * Compute and return the orig_matrix of a font. */ int pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat); +int font_orig_scale(const gs_font *font, double *sx); /* * Create or find a font resource object for a text. @@ -245,4 +248,12 @@ int pdf_add_ToUnicode(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_t *pdfont, gs_glyph glyph, gs_char ch); +/* + * Get character code from a glyph code. + * An usage of this function is very undesirable, + * because a glyph may be unlisted in Encoding. + */ +int pdf_encode_glyph(gs_font_base *bfont, gs_glyph glyph0, + byte *buf, int buf_size, int *char_code_length); + #endif /* gdevpdtt_INCLUDED */ diff --git a/gs/src/gdevpdtw.c b/gs/src/gdevpdtw.c index 6b31f4bd2..f162d1542 100644 --- a/gs/src/gdevpdtw.c +++ b/gs/src/gdevpdtw.c @@ -29,6 +29,10 @@ #include "gdevpdti.h" /* for writing bitmap fonts Encoding */ #include "gdevpdtw.h" +private const char *const encoding_names[] = { + KNOWN_REAL_ENCODING_NAMES +}; + /* ================ Font resource writing ================ */ /* ---------------- Private ---------------- */ @@ -78,59 +82,103 @@ pdf_different_encoding_element(const pdf_font_resource_t *pdfont, int ch, int en return 0; } +/* Find an index of a different encoding element. */ +int +pdf_different_encoding_index(const pdf_font_resource_t *pdfont, int ch0) +{ + gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding; + int ch, code; + + for (ch = ch0; ch < 256; ++ch) { + code = pdf_different_encoding_element(pdfont, ch, base_encoding); + if (code < 0) + return code; /* Must not happen */ + if (code) + break; + } + return ch; +} + +/* Write Encoding differencrs. */ +int +pdf_write_encoding(gx_device_pdf *pdev, const pdf_font_resource_t *pdfont, long id, int ch) +{ + stream *s; + gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding; + int prev = 256, code; + + pdf_open_separate(pdev, id); + s = pdev->strm; + stream_puts(s, "<</Type/Encoding"); + if (base_encoding > 0) + pprints1(s, "/BaseEncoding/%s", encoding_names[base_encoding]); + stream_puts(s, "/Differences["); + for (; ch < 256; ++ch) { + code = pdf_different_encoding_element(pdfont, ch, base_encoding); + if (code < 0) + return code; /* Must not happen */ + if (code == 0 && pdfont->FontType == ft_user_defined) { + /* PDF 1.4 spec Appendix H Note 42 says that + * Acrobat 4 can't properly handle Base Encoding. + * Enforce writing differences against that. + */ + if (pdfont->used[ch >> 3] & 0x80 >> (ch & 7)) + if (pdfont->u.simple.Encoding[ch].str.size) + code = 1; + } + if (code) { + if (ch != prev + 1) + pprintd1(s, "\n%d", ch); + pdf_put_name(pdev, pdfont->u.simple.Encoding[ch].str.data, + pdfont->u.simple.Encoding[ch].str.size); + prev = ch; + } + } + stream_puts(s, "]>>\n"); + pdf_end_separate(pdev); + return 0; +} + +/* Write Encoding reference. */ +int +pdf_write_encoding_ref(gx_device_pdf *pdev, + const pdf_font_resource_t *pdfont, long id) +{ + stream *s = pdev->strm; + + if (id != 0) + pprintld1(s, "/Encoding %ld 0 R", id); + else if (pdfont->u.simple.BaseEncoding > 0) { + gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding; + pprints1(s, "/Encoding/%s", encoding_names[base_encoding]); + } + return 0; +} + /* Write the Subtype and Encoding for a simple font. */ private int pdf_write_simple_contents(gx_device_pdf *pdev, const pdf_font_resource_t *pdfont) { stream *s = pdev->strm; - static const char *const encoding_names[] = { - KNOWN_REAL_ENCODING_NAMES - }; - gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding; long diff_id = 0; int ch = (pdfont->u.simple.Encoding ? 0 : 256); int code = 0; - for (; ch < 256; ++ch) { - code = pdf_different_encoding_element(pdfont, ch, base_encoding); - if (code < 0) - return code; /* Must not happen */ - if (code) - break; - } + ch = pdf_different_encoding_index(pdfont, ch); if (ch < 256) - pprintld1(s, "/Encoding %ld 0 R", - (diff_id = pdf_obj_ref(pdev))); - else if (base_encoding > 0) - pprints1(s, "/Encoding/%s", encoding_names[base_encoding]); + diff_id = pdf_obj_ref(pdev); + code = pdf_write_encoding_ref(pdev, pdfont, diff_id); + if (code < 0) + return code; pprints1(s, "/Subtype/%s>>\n", (pdfont->FontType == ft_TrueType ? "TrueType" : pdfont->u.simple.s.type1.is_MM_instance ? "MMType1" : "Type1")); pdf_end_separate(pdev); if (diff_id) { - int prev = 256; - - pdf_open_separate(pdev, diff_id); - s = pdev->strm; - stream_puts(s, "<</Type/Encoding"); - if (base_encoding > 0) - pprints1(s, "/BaseEncoding/%s", encoding_names[base_encoding]); - stream_puts(s, "/Differences["); - for (; ch < 256; ++ch) { - code = pdf_different_encoding_element(pdfont, ch, base_encoding); - if (code < 0) - return code; /* Must not happen */ - if (code) { - if (ch != prev + 1) - pprintd1(s, "\n%d", ch); - pdf_put_name(pdev, pdfont->u.simple.Encoding[ch].str.data, - pdfont->u.simple.Encoding[ch].str.size); - prev = ch; - } - } - stream_puts(s, "]>>\n"); - pdf_end_separate(pdev); + code = pdf_write_encoding(pdev, pdfont, diff_id, ch); + if (code < 0) + return code; } return 0; } diff --git a/gs/src/gdevpdtw.h b/gs/src/gdevpdtw.h index e04d49cc2..05397d2d2 100644 --- a/gs/src/gdevpdtw.h +++ b/gs/src/gdevpdtw.h @@ -39,7 +39,11 @@ int pdf_write_contents_std(gx_device_pdf *pdev, pdf_font_resource_t *pdfont), pdf_write_contents_simple(gx_device_pdf *pdev, pdf_font_resource_t *pdfont), pdf_write_contents_cid0(gx_device_pdf *pdev, pdf_font_resource_t *pdfont), - pdf_write_contents_cid2(gx_device_pdf *pdev, pdf_font_resource_t *pdfont); + pdf_write_contents_cid2(gx_device_pdf *pdev, pdf_font_resource_t *pdfont), + pdf_different_encoding_index(const pdf_font_resource_t *pdfont, int ch0), + pdf_write_encoding(gx_device_pdf *pdev, const pdf_font_resource_t *pdfont, long id, int ch), + pdf_write_encoding_ref(gx_device_pdf *pdev, const pdf_font_resource_t *pdfont, long id); + /* ---------------- CMap resource writing ---------------- */ diff --git a/gs/src/gsstruct.h b/gs/src/gsstruct.h index 13cb85bc7..2dc452bc7 100644 --- a/gs/src/gsstruct.h +++ b/gs/src/gsstruct.h @@ -838,6 +838,19 @@ extern void reloc_const_bytestring(gs_const_bytestring *pbs, gc_state_t *gcst); #define gs_private_st_suffix_add2(stname, stype, sname, penum, preloc, supstname, e1, e2)\ gs__st_suffix_add2(private_st, stname, stype, sname, penum, preloc, supstname, e1, e2) + /* Suffix subclasses with 2 additional pointers and 1 string. */ + +#define gs__st_suffix_add2_string1(scope_st, stname, stype, sname, penum, preloc, supstname, e1, e2, e3)\ + BASIC_PTRS(penum) {\ + GC_OBJ_ELT2(stype, e1, e2),\ + GC_STRING_ELT(stype, e3)\ + };\ + gs__st_basic_super(scope_st, stname, stype, sname, penum, preloc, &supstname, 0) +#define gs_public_st_suffix_add2_string1(stname, stype, sname, penum, preloc, supstname, e1, e2, e3)\ + gs__st_suffix_add2_string1(public_st, stname, stype, sname, penum, preloc, supstname, e1, e2, e3) +#define gs_private_st_suffix_add2_string1(stname, stype, sname, penum, preloc, supstname, e1, e2, e3)\ + gs__st_suffix_add2_string1(private_st, stname, stype, sname, penum, preloc, supstname, e1, e2, e3) + /* Suffix subclasses with 2 additional pointers and finalization. */ /* See above regarding finalization and subclasses. */ diff --git a/gs/src/gxchar.c b/gs/src/gxchar.c index 370889b16..321225576 100644 --- a/gs/src/gxchar.c +++ b/gs/src/gxchar.c @@ -224,6 +224,19 @@ gx_default_text_begin(gx_device * dev, gs_imager_state * pis, return 0; } +/* An auxiliary functions for pdfwrite to process type 3 fonts. */ +int +gx_default_text_restore_state(gs_text_enum_t *pte) +{ + gs_show_enum *penum; + gs_state *pgs; + + if (SHOW_IS(pte, TEXT_DO_NONE)) + return 0; + penum = (gs_show_enum *)pte; + pgs = penum->pgs; + return gs_grestore(pgs); +} /* ------ Width/cache setting ------ */ private int diff --git a/gs/src/gxchar.h b/gs/src/gxchar.h index d8b7b0a84..c2478fe25 100644 --- a/gs/src/gxchar.h +++ b/gs/src/gxchar.h @@ -135,6 +135,6 @@ int gx_image_cached_char(gs_show_enum *, cached_char *); void gx_compute_text_oversampling(const gs_show_enum * penum, const gs_font *pfont, int alpha_bits, gs_log2_scale_point *p_log2_scale); int set_char_width(gs_show_enum *penum, gs_state *pgs, floatp wx, floatp wy); - +int gx_default_text_restore_state(gs_text_enum_t *pte); #endif /* gxchar_INCLUDED */ |