summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Melichev <igor.melichev@artifex.com>2003-04-08 16:31:56 +0000
committerIgor Melichev <igor.melichev@artifex.com>2003-04-08 16:31:56 +0000
commit29cdc09da0289621708768e72c4bbb2e7ecd8c8c (patch)
treeee19fef341f7280b84672e11f456e2feeb0df2e3
parent3039782b15ae2727157e31ba42ff830322d0f1f2 (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.c14
-rw-r--r--gs/src/gdevpdfd.c8
-rw-r--r--gs/src/gdevpdfg.c2
-rw-r--r--gs/src/gdevpdfu.c4
-rw-r--r--gs/src/gdevpdfx.h35
-rw-r--r--gs/src/gdevpdt.h5
-rw-r--r--gs/src/gdevpdte.c176
-rw-r--r--gs/src/gdevpdtf.c12
-rw-r--r--gs/src/gdevpdtf.h6
-rw-r--r--gs/src/gdevpdti.c243
-rw-r--r--gs/src/gdevpdti.h3
-rw-r--r--gs/src/gdevpdts.c26
-rw-r--r--gs/src/gdevpdts.h17
-rw-r--r--gs/src/gdevpdtt.c328
-rw-r--r--gs/src/gdevpdtt.h11
-rw-r--r--gs/src/gdevpdtw.c122
-rw-r--r--gs/src/gdevpdtw.h6
-rw-r--r--gs/src/gsstruct.h13
-rw-r--r--gs/src/gxchar.c13
-rw-r--r--gs/src/gxchar.h2
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 */