[gs-cvs] gs/src
L. Peter Deutsch
lpd at casper.ghostscript.com
Tue Jul 9 07:29:37 PDT 2002
Update of /cvs/ghostscript/gs/src
In directory casper:/tmp/cvs-serv21419/src
Modified Files:
gdevpdtc.c gdevpdte.c gdevpdtf.c gdevpdti.c gdevpdts.c
gdevpdts.h gdevpdtt.c gdevpdtt.h gdevpdtw.c
Log Message:
Fixes the last (?) major batch of problems in the new pdfwrite text code.
We think this code is now good enough for general testing: search for PDTEXT
in src/devs.mak for information on how to enable it.
Index: gdevpdtc.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdtc.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- gdevpdtc.c 28 Jun 2002 22:36:19 -0000 1.5
+++ gdevpdtc.c 9 Jul 2002 14:29:35 -0000 1.6
@@ -107,11 +107,11 @@
const gs_matrix *psmat =
&curr.fstack.items[curr.fstack.depth - 1].font->FontMatrix;
gs_matrix fmat;
+ int used = 0;
- gs_matrix_multiply(&curr.current_font->FontMatrix, psmat,
- &fmat);
+ gs_matrix_multiply(&curr.current_font->FontMatrix, psmat, &fmat);
code = pdf_encode_process_string(&curr, &str, &fmat, &text_state,
- &index);
+ &used);
if (code < 0)
return code;
gs_text_enum_copy_dynamic(pte, (gs_text_enum_t *)&curr, true);
@@ -188,8 +188,9 @@
{
pdf_font_descriptor_t *pfd = pdsubf->FontDescriptor;
gs_text_enum_t scan = *pte;
- double w = 0;
+ gs_point w;
+ w.x = w.y = 0;
for ( ; ; ) {
gs_char chr;
gs_glyph glyph;
@@ -205,6 +206,8 @@
code = pdf_font_used_glyph(pfd, glyph, subfont);
if (code < 0)
return code;
+ if (cid >= pdsubf->count)
+ cid = 0, code = 1; /* undefined CID */
if (code == 0 /* just copied */ || pdsubf->Widths[cid] == 0) {
pdf_glyph_widths_t widths;
@@ -212,20 +215,27 @@
if (code < 0)
return code;
if (code == 0) { /* OK to cache */
- pdsubf->Widths[cid] = widths.Width;
- pdsubf->real_widths[cid] = widths.real_width;
+ pdsubf->Widths[cid] = widths.Width.w;
+ pdsubf->real_widths[cid] = widths.real_width.w;
}
- w += widths.real_width;
- } else
- w += pdsubf->real_widths[cid];
- if (cid < pdsubf->count)
- pdsubf->used[cid >> 3] |= 0x80 >> (cid & 7);
+ w.x += widths.real_width.xy.x;
+ w.y += widths.real_width.xy.y;
+ if (pdsubf->u.cidfont.CIDToGIDMap != 0) {
+ gs_font_cid2 *subfont2 = (gs_font_cid2 *)subfont;
+
+ pdsubf->u.cidfont.CIDToGIDMap[cid] =
+ subfont2->cidata.CIDMap_proc(subfont2, glyph);
+ }
+ } else {
+ if (font->WMode)
+ w.y += pdsubf->real_widths[cid];
+ else
+ w.x += pdsubf->real_widths[cid];
+ }
+ pdsubf->used[cid >> 3] |= 0x80 >> (cid & 7);
}
}
- if (font->WMode)
- pwxy->x = 0, pwxy->y = w;
- else
- pwxy->x = w, pwxy->y = 0;
+ *pwxy = w;
return 0;
}
@@ -297,10 +307,8 @@
it's too much trouble to calculate the width to pass to
pdf_append_chars.
******/
- if (((text_state.members & TEXT_ADD_TO_ALL_WIDTHS) &&
- text_state.values.character_spacing != 0) ||
- ((text_state.members & TEXT_ADD_TO_SPACE_WIDTH) &&
- text_state.values.word_spacing != 0)
+ if (text_state.values.character_spacing != 0 ||
+ text_state.values.word_spacing != 0
)
return_error(gs_error_rangecheck);
@@ -366,6 +374,7 @@
gs_const_string str;
int acode;
gs_point dist;
+ double scale = 0.001 * text_state.values.size;
text = pte->text;
if (text.operation & TEXT_DO_DRAW)
@@ -376,8 +385,8 @@
return code;
str.data = vdata;
str.size = size;
- if ((acode = pdf_set_text_process_state(pdev, pte, &text_state, &str)) < 0 ||
- (acode = pdf_text_distance_transform(wxy.x, wxy.y,
+ if ((acode = pdf_set_text_process_state(pdev, pte, &text_state)) < 0 ||
+ (acode = pdf_text_distance_transform(wxy.x * scale, wxy.y * scale,
pdev->text->text_state,
&dist)) < 0 ||
(acode = pdf_append_chars(pdev, str.data, str.size, dist.x, dist.y)) < 0
@@ -396,35 +405,14 @@
uint size)
{
gx_device_pdf *const pdev = (gx_device_pdf *)pte->dev;
- gs_font *font = pte->current_font; /* Type 0, fmap_CMap */
- gs_font_type0 *const pfont = (gs_font_type0 *)font;
- gs_font *subfont = pfont->data.FDepVector[0];
pdf_font_resource_t *pdfont; /* Type 0, fmap_CMap */
- pdf_font_resource_t *pdsubf; /* CIDFont */
- int code;
-
- /* Create pdf font resources for the composite font and the CIDFont. */
- /****** SOME OF THIS IS REDUNDANT -- SEE pdf_make_font_resource ******/
+ /* Create a pdf font resource for the composite font and the subfont. */
+ int code = pdf_make_font_resource(pdev, pte->current_font, &pdfont);
- code = pdf_make_font_resource(pdev, subfont, &pdsubf);
- if (code < 0)
- return code;
- code = pdf_make_font_resource(pdev, font, &pdfont);
if (code < 0)
return code;
- pdfont->u.type0.DescendantFont = pdsubf;
- /* Copy the subfont name to the composite font. */
- /****** FIXME ******
- pdf_put_name(pdev, chars, size);
- if (pef->sub_font_type == ft_CID_encrypted &&
- pef->cmapname[0] == '/'
- ) {
- stream_putc(s, '-');
- pdf_put_name_chars(pdev, (const byte*) (pef->cmapname + 1),
- strlen(pef->cmapname + 1));
- }
- ****** FIXME ******/
- return process_cmap_text_common(pte, vdata, vbuf, size, pdfont, pdsubf);
+ return process_cmap_text_common(pte, vdata, vbuf, size, pdfont,
+ pdfont->u.type0.DescendantFont);
}
/* ---------------- CIDFont ---------------- */
@@ -454,7 +442,8 @@
/*
* PDF doesn't support glyphshow directly: we need to create a Type 0
* font with an Identity CMap. Make sure all the glyph numbers fit
- * into 16 bits. (Eventually we should support wider glyphs too.)
+ * into 16 bits. (Eventually we should support wider glyphs too,
+ * but this would require a different CMap.)
*/
{
int i;
@@ -503,7 +492,6 @@
return code;
pdfont->u.cidfont.glyphshow_font = font0;
}
- font0->data.FDepVector[0] = scaled_font;
/* Now handle the glyphshow as a show in the Type 0 font. */
Index: gdevpdte.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdte.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- gdevpdte.c 28 Jun 2002 22:36:19 -0000 1.6
+++ gdevpdte.c 9 Jul 2002 14:29:35 -0000 1.7
@@ -21,6 +21,7 @@
#include "gx.h"
#include "gserrors.h"
#include "gxfcmap.h"
+#include "gxfcopy.h"
#include "gxfont.h"
#include "gxfont0.h"
#include "gxfont0c.h"
@@ -38,6 +39,9 @@
* Given a text string and a simple gs_font, process it in chunks
* determined by pdf_encode_string.
*/
+private int pdf_char_widths(pdf_font_resource_t *pdfont, int ch,
+ gs_font_base *font,
+ pdf_glyph_widths_t *pwidths /* may be NULL */);
private int pdf_encode_string(gx_device_pdf *pdev, gs_font_base *font,
const gs_string *pstr, int *pindex,
pdf_font_resource_t **ppdfont);
@@ -119,6 +123,7 @@
pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch];
gs_glyph glyph =
font->procs.encode_char((gs_font *)font, ch, GLYPH_SPACE_NAME);
+ gs_glyph copied_glyph;
gs_const_string gnstr;
if (glyph == GS_NO_GLYPH || glyph == pet->glyph)
@@ -138,10 +143,20 @@
break; /* can't copy the glyph */
pet->glyph = glyph;
pet->str = gnstr;
- pet->is_difference =
- glyph != cfont->procs.encode_char((gs_font *)cfont, ch,
- GLYPH_SPACE_NAME);
+ /*
+ * 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);
+ /* Cache the width if possible. */
+ DISCARD(pdf_char_widths(pdfont, ch, font, NULL));
}
if (i > *pindex)
code = 0;
@@ -160,17 +175,16 @@
* necessary glyphs. penum->current_font provides the gs_font for getting
* glyph metrics, but this font's Encoding is not used.
*/
-private int process_text_return_width(const gs_text_params_t *ptp,
+private int process_text_return_width(const gs_text_enum_t *pte,
gs_font_base *font,
- pdf_font_resource_t *pdfont,
- const gs_matrix *pfmat,
+ pdf_text_process_state_t *ppts,
+ const gs_const_string *pstr,
+ int *pindex, gs_point *pdpt);
+private int process_text_modify_width(gs_text_enum_t *pte,
+ gs_font_base *font,
+ pdf_text_process_state_t *ppts,
const gs_const_string *pstr,
int *pindex, gs_point *pdpt);
-private int process_text_add_width(gs_text_enum_t *pte,
- gs_font_base *font, const gs_matrix *pfmat,
- pdf_text_process_state_t *ppts,
- const gs_const_string *pstr,
- int *pindex, gs_point *pdpt);
private int
pdf_process_string(pdf_text_enum_t *penum, gs_string *pstr,
pdf_font_resource_t *pdfont, const gs_matrix *pfmat,
@@ -219,51 +233,8 @@
pdfont->u.simple.LastChar = chr;
}
- if (text->operation & TEXT_REPLACE_WIDTHS) {
- gs_point w;
-
- /* Cancel word and character spacing. */
- ppts->members |= TEXT_STATE_SET_CHARACTER_SPACING |
- TEXT_STATE_SET_WORD_SPACING;
- ppts->values.character_spacing = ppts->values.word_spacing = 0;
- code = pdf_set_text_process_state(pdev, pte, ppts,
- (gs_const_string *)pstr);
- if (code < 0)
- return code;
- w.x = w.y = 0;
- for (i = 0; i < pstr->size; *pindex = ++i, pte->xy_index++) {
- gs_point d, dpt;
-
- gs_text_replaced_width(&pte->text, pte->xy_index, &d);
- w.x += d.x, w.y += d.y;
- gs_distance_transform(d.x, d.y, &ctm_only(pte->pis), &dpt);
- if (text->operation & TEXT_DO_DRAW) {
- code = pdf_append_chars(pdev, pstr->data + i, 1, dpt.x, dpt.y);
- if (code < 0)
- return code;
- }
- ppts->values.matrix.tx += dpt.x;
- ppts->values.matrix.ty += dpt.y;
- if (i + 1 < pstr->size) {
- code = pdf_set_text_state_values(pdev, &ppts->values,
- TEXT_STATE_SET_MATRIX);
- if (code < 0)
- return code;
- }
- }
- pte->returned.total_width = w;
- if (text->operation & TEXT_RETURN_WIDTH)
- code = gx_path_add_point(pte->path,
- float2fixed(ppts->values.matrix.tx),
- float2fixed(ppts->values.matrix.ty));
- return code;
- }
-
- /* Bring the text-related parameters in the output up to date. */
- code = pdf_set_text_process_state(pdev, pte, ppts,
- (gs_const_string *)pstr);
- if (code < 0)
- return code;
+ if (text->operation & TEXT_REPLACE_WIDTHS)
+ mask |= TEXT_REPLACE_WIDTHS;
/*
* The only operations left to handle are TEXT_DO_DRAW and
@@ -279,7 +250,7 @@
if (!(text->operation & (TEXT_DO_DRAW | TEXT_RETURN_WIDTH)))
return 0;
- code = process_text_return_width(&pte->text, font, pdfont, pfmat,
+ code = process_text_return_width(pte, font, ppts,
(gs_const_string *)pstr,
pindex, &width_pt);
if (code < 0)
@@ -299,20 +270,9 @@
}
}
if (mask) {
- /*
- * Cancel the word and character spacing, since we're going
- * to emulate them.
- */
- ppts->members = TEXT_STATE_SET_CHARACTER_SPACING |
- TEXT_STATE_SET_WORD_SPACING;
- ppts->values.character_spacing = ppts->values.word_spacing = 0;
- code = pdf_set_text_process_state(pdev, pte, ppts,
- (gs_const_string *)pstr);
- if (code < 0)
- return code;
- code = process_text_add_width(pte, font, pfmat, ppts,
- (gs_const_string *)pstr,
- pindex, &width_pt);
+ code = process_text_modify_width(pte, font, ppts,
+ (gs_const_string *)pstr,
+ pindex, &width_pt);
if (code < 0)
return code;
}
@@ -351,12 +311,23 @@
if (code < 0)
return code;
if (code == 0) {
- pdfont->Widths[ch] = pwidths->Width;
- pdfont->real_widths[ch] = pwidths->real_width;
+ pdfont->Widths[ch] = pwidths->Width.w;
+ pdfont->real_widths[ch] = pwidths->real_width.w;
}
} else {
- pwidths->Width = pdfont->Widths[ch];
- pwidths->real_width = pdfont->real_widths[ch];
+ pwidths->Width.w = pdfont->Widths[ch];
+ pwidths->real_width.w = pdfont->real_widths[ch];
+ if (font->WMode) {
+ pwidths->Width.xy.x = 0;
+ pwidths->Width.xy.y = pwidths->Width.w;
+ pwidths->real_width.xy.x = 0;
+ pwidths->real_width.xy.y = pwidths->real_width.w;
+ } else {
+ pwidths->Width.xy.x = pwidths->Width.w;
+ pwidths->Width.xy.y = 0;
+ pwidths->real_width.xy.x = pwidths->real_width.w;
+ pwidths->real_width.xy.y = 0;
+ }
code = 0;
}
return code;
@@ -367,43 +338,55 @@
* character had real_width != Width, otherwise 0.
*/
private int
-process_text_return_width(const gs_text_params_t *ptp, gs_font_base *font,
- pdf_font_resource_t *pdfont, const gs_matrix *pfmat,
+process_text_return_width(const gs_text_enum_t *pte, gs_font_base *font,
+ pdf_text_process_state_t *ppts,
const gs_const_string *pstr,
int *pindex, gs_point *pdpt)
{
- int i, w;
- gs_matrix smat;
+ int i;
+ gs_point w;
+ double scale = 0.001 * ppts->values.size;
gs_point dpt;
int num_spaces = 0;
int space_char =
- (ptp->operation & TEXT_ADD_TO_SPACE_WIDTH ?
- ptp->space.s_char : -1);
+ (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
+ pte->text.space.s_char : -1);
int widths_differ = 0;
- for (i = *pindex, w = 0; i < pstr->size; ++i) {
+ for (i = *pindex, w.x = w.y = 0; i < pstr->size; ++i) {
pdf_glyph_widths_t cw;
- int code = pdf_char_widths(pdfont, pstr->data[i], font, &cw);
+ int code = pdf_char_widths(ppts->values.pdfont, pstr->data[i], font,
+ &cw);
if (code < 0)
return code;
- w += cw.real_width;
- if (cw.real_width != cw.Width)
+ w.x += cw.real_width.xy.x;
+ w.y += cw.real_width.xy.y;
+ if (cw.real_width.xy.x != cw.Width.xy.x ||
+ cw.real_width.xy.y != cw.Width.xy.y
+ )
widths_differ = 1;
if (pstr->data[i] == space_char)
++num_spaces;
}
- pdf_font_orig_matrix((gs_font *)font, &smat);
- gs_distance_transform(w / 1000.0 / smat.xx, 0.0, pfmat, &dpt);
- if (ptp->operation & TEXT_ADD_TO_ALL_WIDTHS) {
+ 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 - *pindex;
+ gs_point tpt;
- dpt.x += ptp->delta_all.x * num_chars;
- dpt.y += ptp->delta_all.y * num_chars;
+ gs_distance_transform(pte->text.delta_all.x, pte->text.delta_all.y,
+ &ctm_only(pte->pis), &tpt);
+ dpt.x += tpt.x * num_chars;
+ dpt.y += tpt.y * num_chars;
}
- if (ptp->operation & TEXT_ADD_TO_SPACE_WIDTH) {
- dpt.x += ptp->delta_space.x * num_spaces;
- dpt.y += ptp->delta_space.y * num_spaces;
+ if (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
+ gs_point tpt;
+
+ gs_distance_transform(pte->text.delta_space.x, pte->text.delta_space.y,
+ &ctm_only(pte->pis), &tpt);
+ dpt.x += tpt.x * num_spaces;
+ dpt.y += tpt.y * num_spaces;
}
*pindex = i;
*pdpt = dpt;
@@ -411,37 +394,33 @@
return widths_differ;
}
/*
- * Emulate TEXT_ADD_TO_ALL_WIDTHS and/or TEXT_ADD_TO_SPACE_WIDTH.
+ * Emulate TEXT_ADD_TO_ALL_WIDTHS and/or TEXT_ADD_TO_SPACE_WIDTH,
+ * and implement TEXT_REPLACE_WIDTHS if requested.
* We know that the Tw and Tc values are zero. Uses and updates
* ppts->values.matrix; uses ppts->values.pdfont.
*/
private int
-process_text_add_width(gs_text_enum_t *pte, gs_font_base *font,
- const gs_matrix *pfmat,
- pdf_text_process_state_t *ppts,
- const gs_const_string *pstr,
- int *pindex, gs_point *pdpt)
+process_text_modify_width(gs_text_enum_t *pte, gs_font_base *font,
+ pdf_text_process_state_t *ppts,
+ const gs_const_string *pstr,
+ int *pindex, gs_point *pdpt)
{
gx_device_pdf *const pdev = (gx_device_pdf *)pte->dev;
int i, w;
- gs_matrix smat;
- double scale;
+ double scale = 0.001 * ppts->values.size;
int space_char =
(pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
pte->text.space.s_char : -1);
int code = 0;
gs_point start, total;
- pdf_font_orig_matrix((gs_font *)font, &smat);
- scale = 0.001 / smat.xx;
start.x = ppts->values.matrix.tx;
start.y = ppts->values.matrix.ty;
total.x = total.y = 0; /* user space */
/*
* Note that character widths are in design space, but text.delta_*
- * values and the width value returned in *pdpt are in user space
- * (design space scaled by *pfmat), and the width values for
- * pdf_append_chars are in device space.
+ * values and the width value returned in *pdpt are in user space,
+ * and the width values for pdf_append_chars are in device space.
*/
for (i = *pindex, w = 0; i < pstr->size; ++i) {
pdf_glyph_widths_t cw; /* design space */
@@ -452,28 +431,48 @@
if (code < 0)
break;
if (pte->text.operation & TEXT_DO_DRAW) {
- gs_distance_transform(cw.Width * scale, 0.0, pfmat, &did);
+ gs_distance_transform(cw.Width.xy.x * scale,
+ cw.Width.xy.y * scale,
+ &ppts->values.matrix, &did);
code = pdf_append_chars(pdev, &pstr->data[i], 1, did.x, did.y);
if (code < 0)
break;
} else
did.x = did.y = 0;
- gs_distance_transform(cw.real_width * scale, 0.0, pfmat, &wanted);
- if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
- wanted.x += pte->text.delta_all.x;
- wanted.y += pte->text.delta_all.y;
- }
- if (pstr->data[i] == space_char) {
- wanted.x += pte->text.delta_space.x;
- wanted.y += pte->text.delta_space.y;
+ if (pte->text.operation & TEXT_REPLACE_WIDTHS) {
+ gs_point dpt;
+
+ gs_text_replaced_width(&pte->text, pte->xy_index++, &dpt);
+ gs_distance_transform(dpt.x, dpt.y, &ctm_only(pte->pis), &wanted);
+ } else {
+ gs_distance_transform(cw.real_width.xy.x * scale,
+ cw.real_width.xy.y * scale,
+ &ppts->values.matrix, &wanted);
+ if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
+ gs_point tpt;
+
+ gs_distance_transform(pte->text.delta_all.x,
+ pte->text.delta_all.y,
+ &ctm_only(pte->pis), &tpt);
+ wanted.x += tpt.x;
+ wanted.y += tpt.y;
+ }
+ if (pstr->data[i] == space_char) {
+ gs_point tpt;
+
+ gs_distance_transform(pte->text.delta_space.x,
+ pte->text.delta_space.y,
+ &ctm_only(pte->pis), &tpt);
+ wanted.x += tpt.x;
+ wanted.y += tpt.y;
+ }
}
total.x += wanted.x;
total.y += wanted.y;
if (wanted.x != did.x || wanted.y != did.y) {
ppts->values.matrix.tx = start.x + total.x;
ppts->values.matrix.ty = start.y + total.y;
- code = pdf_set_text_state_values(pdev, &ppts->values,
- TEXT_STATE_SET_MATRIX);
+ code = pdf_set_text_state_values(pdev, &ppts->values);
if (code < 0)
break;
}
Index: gdevpdtf.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdtf.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- gdevpdtf.c 3 Jul 2002 13:58:14 -0000 1.8
+++ gdevpdtf.c 9 Jul 2002 14:29:35 -0000 1.9
@@ -539,14 +539,15 @@
code = pdf_compute_BaseFont(pdev, pdsubf);
if (code < 0)
return code;
+ fname = pdsubf->BaseFont;
if (pdsubf->FontType == ft_CID_encrypted)
extra = 1 + pdfont->u.type0.CMapName.size;
}
else if (pdfont->FontDescriptor == 0) {
/* Type 3 font, or has its BaseFont computed in some other way. */
return 0;
- }
- fname = *pdf_font_descriptor_base_name(pdsubf->FontDescriptor);
+ } else
+ fname = *pdf_font_descriptor_base_name(pdsubf->FontDescriptor);
size = fname.size;
data = gs_alloc_string(pdev->pdf_memory, size + extra,
"pdf_compute_BaseFont");
@@ -591,7 +592,8 @@
}
pdfont->BaseFont.data = fname.data = data;
pdfont->BaseFont.size = fname.size = size;
- *pdf_font_descriptor_name(pdsubf->FontDescriptor) = fname;
+ if (pdsubf->FontDescriptor)
+ *pdf_font_descriptor_name(pdsubf->FontDescriptor) = fname;
return 0;
}
@@ -640,7 +642,7 @@
(code = pdf_base_font_alloc(pdev, &pdfont->base_font, pfont, true)) < 0
)
return code;
- pdfont->BaseFont.data = (byte *)psfi->fname;
+ pdfont->BaseFont.data = (byte *)psfi->fname; /* break const */
pdfont->BaseFont.size = strlen(psfi->fname);
pdfont->copied_font = pdf_base_font_font(pdfont->base_font);
set_is_MM_instance(pdfont, pfont);
Index: gdevpdti.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdti.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- gdevpdti.c 28 Jun 2002 22:36:19 -0000 1.3
+++ gdevpdti.c 9 Jul 2002 14:29:35 -0000 1.4
@@ -284,12 +284,7 @@
values.matrix.ty -= pcp->y_offset;
values.render_mode = 0;
values.word_spacing = 0;
- pdf_set_text_state_values(pdev, &values,
- TEXT_STATE_SET_CHARACTER_SPACING |
- TEXT_STATE_SET_FONT_AND_SIZE |
- TEXT_STATE_SET_MATRIX |
- TEXT_STATE_SET_RENDER_MODE |
- TEXT_STATE_SET_WORD_SPACING);
+ pdf_set_text_state_values(pdev, &values);
pdf_append_chars(pdev, &ch, 1, pdfont->Widths[ch] * pimat->xx, 0.0);
return 0;
}
Index: gdevpdts.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdts.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- gdevpdts.c 28 Jun 2002 22:36:19 -0000 1.8
+++ gdevpdts.c 9 Jul 2002 14:29:35 -0000 1.9
@@ -32,6 +32,8 @@
* on the font's writing direction), until forced to emit them. This
* happens when changing text state parameters, when the buffer is full, or
* when exiting text mode.
+ *
+ * Note that movement distances are measured in unscaled text space.
*/
typedef struct pdf_text_move_s {
int index; /* within buffer.chars */
@@ -74,8 +76,6 @@
pdf_text_buffer_t buffer;
int wmode; /* WMode of in.font */
/* State relative to content stream */
- int members; /* which members of 'out' to update, */
- /* TEXT_STATE_SET_xxx (see gdevpdts.h) */
pdf_text_state_values_t out; /* see above */
double leading; /* TL (not settable, only used internally) */
bool use_leading; /* if true, use T* or ' */
@@ -88,7 +88,6 @@
{ TEXT_BUFFER_DEFAULT }, /* buffer */
0, /* wmode */
/* State relative to content stream */
- 0, /* members */
{ TEXT_STATE_VALUES_DEFAULT }, /* out */
0, /* leading */
0 /*false*/, /* use_leading */
@@ -116,21 +115,21 @@
int pos = pts->buffer.count_chars;
double rounded;
- if (dw == 0)
- return 0;
- if (count == MAX_TEXT_BUFFER_MOVES)
- return -1;
+ if (count > 0 && pts->buffer.moves[count - 1].index == pos) {
+ /* Merge adjacent moves. */
+ dw += pts->buffer.moves[--count].amount;
+ }
/* Round dw if it's very close to an integer. */
if (fabs(dw - (rounded = floor(dw + 0.5))) < fabs(dw * 0.001))
dw = rounded;
- if (count > 0 && pts->buffer.moves[count - 1].index == pos) {
- /* Merge adjacent moves. */
- pts->buffer.moves[count - 1].amount += dw;
- } else {
+ if (dw != 0) {
+ if (count == MAX_TEXT_BUFFER_MOVES)
+ return -1;
pts->buffer.moves[count].index = pos;
pts->buffer.moves[count].amount = dw;
- pts->buffer.count_moves = count + 1;
+ ++count;
}
+ pts->buffer.count_moves = count;
return 0;
}
@@ -174,11 +173,12 @@
if (matrix_is_compatible(pmat, &pts->in.matrix)) {
pdf_font_resource_t *const pdfont = pts->in.pdfont;
+ double dx = pmat->tx - pts->in.matrix.tx,
+ dy = pmat->ty - pts->in.matrix.ty;
gs_point dist;
double dw, dnotw, tdw;
- set_text_distance(&dist, pmat->tx - pts->in.matrix.tx,
- pmat->ty - pts->in.matrix.ty, pmat);
+ set_text_distance(&dist, dx, dy, pmat);
if (pts->wmode)
dw = dist.y, dnotw = dist.x;
else
@@ -187,20 +187,12 @@
pdfont->FontType == ft_user_defined
) {
/* Use a pseudo-character. */
- int dspace = (int)dw;
- int code = pdf_space_char(pdev, pdfont, dspace);
+ int code = pdf_space_char(pdev, pdfont, (int)dw);
if (code >= 0) {
byte space_char = (byte)code;
- if (pts->wmode)
- pdf_append_chars(pdev, &space_char, 1,
- dspace * pts->in.matrix.yx,
- dspace * pts->in.matrix.yy);
- else
- pdf_append_chars(pdev, &space_char, 1,
- dspace * pts->in.matrix.xx,
- dspace * pts->in.matrix.xy);
+ pdf_append_chars(pdev, &space_char, 1, dx, dy);
goto finish;
}
}
@@ -264,7 +256,7 @@
}
} else { /* Use Tm. */
/*
- * See stream_to_text in gdevpdf.c for why we need the following
+ * See stream_to_text in gdevpdfu.c for why we need the following
* matrix adjustments.
*/
double sx = 72.0 / pdev->HWResolution[0],
@@ -317,6 +309,7 @@
pdf_text_state_t *pts = ptd->text_state;
pts->out = ts_default.out;
+ pts->leading = 0;
}
/*
@@ -348,63 +341,52 @@
return 0; /* nothing to output */
/* Bring text state parameters up to date. */
- if (pts->members) {
- if (pts->members & TEXT_STATE_SET_CHARACTER_SPACING) {
- if (pts->out.character_spacing != pts->in.character_spacing) {
- pprintg1(s, "%g Tc\n", pts->in.character_spacing);
- pts->out.character_spacing = pts->in.character_spacing;
- }
- pts->members -= TEXT_STATE_SET_CHARACTER_SPACING;
- }
+
+ if (pts->out.character_spacing != pts->in.character_spacing) {
+ pprintg1(s, "%g Tc\n", pts->in.character_spacing);
+ pts->out.character_spacing = pts->in.character_spacing;
+ }
+
+ /*
+ * NOTE: we must update the font before the matrix, because
+ * pdf_set_text_matrix assumes out.pdfont == in.pdfont.
+ */
+ if (pts->out.pdfont != pts->in.pdfont || pts->out.size != pts->in.size) {
+ pdf_font_resource_t *pdfont = pts->in.pdfont;
+
+ pprints1(s, "/%s ", ((pdf_resource_t *)pts->in.pdfont)->rname);
+ pprintg1(s, "%g Tf\n", pts->in.size);
+ pts->out.pdfont = pdfont;
+ pts->out.size = pts->in.size;
/*
- * NOTE: we must update the font before the matrix, because
- * pdf_set_text_matrix assumes out.pdfont == in.pdfont.
+ * In PDF, the only place to specify WMode is in the CMap
+ * (a.k.a. Encoding) of a Type 0 font.
*/
- if (pts->members & TEXT_STATE_SET_FONT_AND_SIZE) {
- if (pts->out.pdfont != pts->in.pdfont ||
- pts->out.size != pts->in.size
- ) {
- pdf_font_resource_t *pdfont = pts->in.pdfont;
+ pts->wmode =
+ (pdfont->FontType == ft_composite ?
+ pdfont->u.type0.WMode : 0);
+ ((pdf_resource_t *)pdfont)->where_used |= pdev->used_mask;
+ }
- pprints1(s, "/%s ", ((pdf_resource_t *)pts->in.pdfont)->rname);
- pprintg1(s, "%g Tf\n", pts->in.size);
- pts->out.pdfont = pdfont;
- pts->out.size = pts->in.size;
- /*
- * In PDF, the only place to specify WMode is in the CMap
- * (a.k.a. Encoding) of a Type 0 font.
- */
- pts->wmode =
- (pdfont->FontType == ft_composite ?
- pdfont->u.type0.WMode : 0);
- ((pdf_resource_t *)pdfont)->where_used |= pdev->used_mask;
- }
- pts->members -= TEXT_STATE_SET_FONT_AND_SIZE;
- }
- if (pts->members & TEXT_STATE_SET_MATRIX) {
- /*
- * NOTE: pdf_set_text_matrix may add characters to the buffer.
- */
- code = pdf_set_text_matrix(pdev);
- if (code < 0)
- return code;
- pts->members -= TEXT_STATE_SET_MATRIX;
- }
- if (pts->members & TEXT_STATE_SET_RENDER_MODE) {
- if (pts->out.render_mode != pts->in.render_mode) {
- pprintg1(s, "%g Tr\n", pts->in.render_mode);
- pts->out.render_mode = pts->in.render_mode;
- }
- pts->members -= TEXT_STATE_SET_RENDER_MODE;
- }
- if (pts->members & TEXT_STATE_SET_WORD_SPACING) {
- if (pts->out.word_spacing == pts->in.word_spacing)
- pts->members -= TEXT_STATE_SET_WORD_SPACING;
- else if (memchr(pts->buffer.chars, 32, pts->buffer.count_chars)) {
- pprintg1(s, "%g Tw\n", pts->in.word_spacing);
- pts->out.word_spacing = pts->in.word_spacing;
- pts->members -= TEXT_STATE_SET_WORD_SPACING;
- }
+ /*
+ * NOTE: pdf_set_text_matrix may add characters to the buffer.
+ */
+ if (memcmp(&pts->in.matrix, &pts->out.matrix, sizeof(pts->in.matrix))) {
+ /* pdf_set_text_matrix sets out.matrix = in.matrix */
+ code = pdf_set_text_matrix(pdev);
+ if (code < 0)
+ return code;
+ }
+
+ if (pts->out.render_mode != pts->in.render_mode) {
+ pprintg1(s, "%g Tr\n", pts->in.render_mode);
+ pts->out.render_mode = pts->in.render_mode;
+ }
+
+ if (pts->out.word_spacing != pts->in.word_spacing) {
+ if (memchr(pts->buffer.chars, 32, pts->buffer.count_chars)) {
+ pprintg1(s, "%g Tw\n", pts->in.word_spacing);
+ pts->out.word_spacing = pts->in.word_spacing;
}
}
@@ -470,64 +452,45 @@
}
/*
- * Set text state values (as seen by client).
+ * Read the stored client view of text state values.
+ */
+void
+pdf_get_text_state_values(gx_device_pdf *pdev, pdf_text_state_values_t *ptsv)
+{
+ *ptsv = pdev->text->text_state->in;
+}
+
+/*
+ * Set the stored client view of text state values.
*/
int
-pdf_set_text_state_values(gx_device_pdf *pdev, pdf_text_state_values_t *ptsv,
- int members)
+pdf_set_text_state_values(gx_device_pdf *pdev,
+ const pdf_text_state_values_t *ptsv)
{
pdf_text_state_t *pts = pdev->text->text_state;
- int reset = members & pts->members;
-
- if (members & TEXT_STATE_SET_MATRIX) {
- int code = add_text_delta_move(pdev, &ptsv->matrix);
-
- if (code >= 0)
- members &= ~TEXT_STATE_SET_MATRIX;
- }
- if ((reset & TEXT_STATE_SET_CHARACTER_SPACING) &&
- pts->in.character_spacing == ptsv->character_spacing)
- members -= TEXT_STATE_SET_CHARACTER_SPACING;
- if ((reset & TEXT_STATE_SET_FONT_AND_SIZE) &&
- pts->in.pdfont == ptsv->pdfont && pts->in.size == ptsv->size)
- members -= TEXT_STATE_SET_FONT_AND_SIZE;
- if ((reset & TEXT_STATE_SET_RENDER_MODE) &&
- pts->in.render_mode == ptsv->render_mode)
- members -= TEXT_STATE_SET_RENDER_MODE;
- if ((reset & TEXT_STATE_SET_WORD_SPACING) &&
- pts->in.word_spacing == ptsv->word_spacing)
- members -= TEXT_STATE_SET_WORD_SPACING;
-
- if (pts->buffer.count_chars > 0 && members != 0) {
- int code = sync_text_state(pdev);
+ if (pts->buffer.count_chars > 0) {
+ int code;
+ if (pts->in.character_spacing == ptsv->character_spacing &&
+ pts->in.pdfont == ptsv->pdfont && pts->in.size == ptsv->size &&
+ pts->in.render_mode == ptsv->render_mode &&
+ pts->in.word_spacing == ptsv->word_spacing
+ ) {
+ if (!memcmp(&pts->in.matrix, &ptsv->matrix,
+ sizeof(pts->in.matrix)))
+ return 0;
+ /* add_text_delta_move sets pts->in.matrix if successful */
+ code = add_text_delta_move(pdev, &ptsv->matrix);
+ if (code >= 0)
+ return 0;
+ }
+ code = sync_text_state(pdev);
if (code < 0)
return code;
}
- if (members & TEXT_STATE_SET_CHARACTER_SPACING)
- pts->in.character_spacing = ptsv->character_spacing;
- else
- ptsv->character_spacing = pts->in.character_spacing;
- if (members & TEXT_STATE_SET_FONT_AND_SIZE)
- pts->in.pdfont = ptsv->pdfont, pts->in.size = ptsv->size;
- else
- ptsv->pdfont = pts->in.pdfont, ptsv->size = pts->in.size;
- if (members & TEXT_STATE_SET_MATRIX)
- pts->in.matrix = ptsv->matrix;
- else
- ptsv->matrix = pts->in.matrix;
- if (members & TEXT_STATE_SET_RENDER_MODE)
- pts->in.render_mode = ptsv->render_mode;
- else
- ptsv->render_mode = pts->in.render_mode;
- if (members & TEXT_STATE_SET_WORD_SPACING)
- pts->in.word_spacing = ptsv->word_spacing;
- else
- ptsv->word_spacing = pts->in.word_spacing;
-
- pts->members |= members;
+ pts->in = *ptsv;
return 0;
}
Index: gdevpdts.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdts.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- gdevpdts.h 28 Jun 2002 22:36:19 -0000 1.4
+++ gdevpdts.h 9 Jul 2002 14:29:35 -0000 1.5
@@ -22,6 +22,11 @@
#include "gsmatrix.h"
+/*
+ * See gdevpdtt.h for a discussion of the multiple coordinate systems that
+ * the text code must use.
+ */
+
/* ================ Types and structures ================ */
#ifndef pdf_text_state_DEFINED
@@ -36,17 +41,17 @@
*/
typedef struct pdf_text_state_values_s {
float character_spacing; /* Tc */
-#define TEXT_STATE_SET_CHARACTER_SPACING 1
pdf_font_resource_t *pdfont; /* for Tf */
double size; /* for Tf */
-#define TEXT_STATE_SET_FONT_AND_SIZE 2
- gs_matrix matrix; /* Tm et al (relative to device space, */
- /* not user space) */
-#define TEXT_STATE_SET_MATRIX 4
+ /*
+ * The matrix is the transformation from text space to user space, which
+ * in pdfwrite text output is the same as device space. Thus this
+ * matrix combines the effect of the PostScript CTM and the FontMatrix,
+ * scaled by the inverse of the font size value.
+ */
+ gs_matrix matrix; /* Tm et al */
int render_mode; /* Tr */
-#define TEXT_STATE_SET_RENDER_MODE 8
float word_spacing; /* Tw */
-#define TEXT_STATE_SET_WORD_SPACING 16
} pdf_text_state_values_t;
#define TEXT_STATE_VALUES_DEFAULT\
0, /* character_spacing */\
@@ -102,12 +107,16 @@
const pdf_text_state_values_t *ptsv);
/*
- * Set text state values (as seen by client). Also update any values in
- * *ptsv that are not being set.
+ * Read the stored client view of text state values.
+ */
+void pdf_get_text_state_values(gx_device_pdf *pdev,
+ pdf_text_state_values_t *ptsv);
+
+/*
+ * Set the stored client view of text state values.
*/
int pdf_set_text_state_values(gx_device_pdf *pdev,
- pdf_text_state_values_t *ptsv,
- int members);
+ const pdf_text_state_values_t *ptsv);
/*
* Transform a distance from unscaled text space (text space ignoring the
Index: gdevpdtt.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdtt.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- gdevpdtt.c 28 Jun 2002 22:36:19 -0000 1.5
+++ gdevpdtt.c 9 Jul 2002 14:29:35 -0000 1.6
@@ -406,9 +406,9 @@
font->procs.encode_char(font, (gs_char)i,
GLYPH_SPACE_INDEX);
- if (glyph == gs_no_glyph ||
- (glyph >= gs_min_cid_glyph &&
- glyph <= gs_min_cid_glyph + 0xff)
+ if (glyph == GS_NO_GLYPH ||
+ (glyph >= GS_MIN_CID_GLYPH &&
+ glyph <= GS_MIN_CID_GLYPH + 0xff)
)
continue;
/* Can't embed, punt. */
@@ -518,6 +518,7 @@
sx = pdev->HWResolution[0] / 72.0,
sy = pdev->HWResolution[1] / 72.0;
float size;
+ float c_s = 0, w_s = 0;
int mask = 0;
int code = gx_path_current_point(penum->path, &cpt);
@@ -546,40 +547,33 @@
/* Try to find a reasonable size value. This isn't necessary, */
/* but it's worth a little effort. */
- size = fabs(tmat.yy) / sy;
+ size = hypot(tmat.yx, tmat.yy) / sy;
if (size < 0.01)
- size = fabs(tmat.xx) / sx;
+ size = hypot(tmat.xx, tmat.xy) / sx;
if (size < 0.01)
size = 1;
/* Check for spacing parameters we can handle, and transform them. */
- ppts->members = TEXT_STATE_SET_FONT_AND_SIZE |
- TEXT_STATE_SET_MATRIX | TEXT_STATE_SET_RENDER_MODE;
-
if (penum->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
gs_point pt;
code = transform_delta_inverse(&penum->text.delta_all, &smat, &pt);
- if (code >= 0 && pt.y == 0) {
- ppts->values.character_spacing = pt.x * size;
- ppts->members |= TEXT_STATE_SET_CHARACTER_SPACING;
- } else
+ if (code >= 0 && pt.y == 0)
+ c_s = pt.x * size;
+ else
mask |= TEXT_ADD_TO_ALL_WIDTHS;
}
-
+
if (penum->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
gs_point pt;
code = transform_delta_inverse(&penum->text.delta_space, &smat, &pt);
- if (code >= 0 && pt.y == 0 && penum->text.space.s_char == 32) {
- ppts->values.word_spacing = pt.x * size;
- ppts->members |= TEXT_STATE_SET_WORD_SPACING;
- } else {
+ if (code >= 0 && pt.y == 0 && penum->text.space.s_char == 32)
+ w_s = pt.x * size;
+ else
mask |= TEXT_ADD_TO_SPACE_WIDTH;
- }
}
-
/* Store the updated values. */
tmat.xx /= size;
@@ -589,19 +583,23 @@
tmat.tx += fixed2float(cpt.x);
tmat.ty += fixed2float(cpt.y);
+ ppts->values.character_spacing = c_s;
ppts->values.pdfont = pdfont;
ppts->values.size = size;
ppts->values.matrix = tmat;
ppts->values.render_mode = (font->PaintType == 0 ? 0 : 1);
+ ppts->values.word_spacing = w_s;
ppts->font = font;
- return mask;
+ code = pdf_set_text_process_state(pdev, (const gs_text_enum_t *)penum,
+ ppts);
+ return (code < 0 ? code : mask);
}
/*
* Set up commands to make the output state match the processing state.
* General graphics state commands are written now; text state commands
- * are written later. Update ppts->values to reflect all current values.
+ * are written later.
*/
private double
font_matrix_scaling(const gs_font *font)
@@ -612,8 +610,7 @@
int
pdf_set_text_process_state(gx_device_pdf *pdev,
const gs_text_enum_t *pte, /* for pdcolor, pis */
- pdf_text_process_state_t *ppts,
- const gs_const_string *pstr)
+ pdf_text_process_state_t *ppts)
{
/*
* Setting the stroke parameters may exit text mode, causing the
@@ -655,15 +652,15 @@
/* Now set all the other parameters. */
- return pdf_set_text_state_values(pdev, &ppts->values, ppts->members);
+ return pdf_set_text_state_values(pdev, &ppts->values);
}
/*
* Get the widths (unmodified and possibly modified) of a glyph in a (base)
* font. Return 1 if the width was defaulted to MissingWidth.
*/
-private int store_glyph_width(int *pwidth, int wmode, double scale,
- const gs_glyph_info_t *pinfo);
+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, gs_glyph glyph,
gs_font_base *font, pdf_glyph_widths_t *pwidths)
@@ -674,31 +671,43 @@
* orig_scale is 1.0 for TrueType, 0.001 or 1.0/2048 for Type 1.
*/
double scale = font_orig_scale((const gs_font *)pdf_font_resource_font(pdfont)) * 1000.0;
- int code;
+ int code, rcode = 0;
- if (glyph != gs_no_glyph &&
+ if (glyph != GS_NO_GLYPH &&
(code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
(GLYPH_INFO_WIDTH0 << wmode) |
GLYPH_INFO_OUTLINE_WIDTHS,
- &info)) >= 0 &&
- (code = store_glyph_width(&pwidths->Width, wmode, scale, &info)) >= 0 &&
- (/*
- * Only ask for modified widths if they are different, i.e.,
- * if GLYPH_INFO_OUTLINE_WIDTHS was set in the response.
- */
- (info.members & GLYPH_INFO_OUTLINE_WIDTHS) == 0 ||
- (code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
- GLYPH_INFO_WIDTH0 << wmode,
- &info)) >= 0) &&
- (code = store_glyph_width(&pwidths->real_width, wmode, scale, &info)) >= 0
+ &info)) != gs_error_undefined
) {
+ if (code < 0 ||
+ (code = store_glyph_width(&pwidths->Width, wmode, scale, &info)) < 0
+ )
+ return code;
+ rcode |= code;
+ /*
+ * Only ask for modified widths if they are different, i.e.,
+ * if GLYPH_INFO_OUTLINE_WIDTHS was set in the response.
+ */
+ if ((info.members & GLYPH_INFO_OUTLINE_WIDTHS) != 0 &&
+ (code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
+ GLYPH_INFO_WIDTH0 << wmode,
+ &info)) != gs_error_undefined
+ ) {
+ if (code < 0 ||
+ (code = store_glyph_width(&pwidths->real_width, wmode, scale, &info)) < 0
+ )
+ return code;
+ rcode |= code;
+ } else
+ pwidths->real_width = pwidths->Width;
/*
* If the character is .notdef, don't cache the width,
* just in case this is an incrementally defined font.
*/
- return (gs_font_glyph_is_notdef(font, glyph) ? 1 : 0);
- } else {
- /* Try for MissingWidth. */
+ return (gs_font_glyph_is_notdef(font, glyph) ? 1 : rcode);
+ }
+ /* Try for MissingWidth. */
+ {
gs_point scale2;
const gs_point *pscale = 0;
gs_font_info_t finfo;
@@ -709,7 +718,17 @@
FONT_INFO_MISSING_WIDTH, &finfo);
if (code < 0)
return code;
- pwidths->Width = pwidths->real_width = finfo.MissingWidth;
+ if (wmode) {
+ pwidths->Width.xy.x = pwidths->real_width.xy.x = 0;
+ pwidths->Width.w = pwidths->real_width.w =
+ pwidths->Width.xy.y = pwidths->real_width.xy.y =
+ finfo.MissingWidth * pscale->y;
+ } else {
+ pwidths->Width.w = pwidths->real_width.w =
+ pwidths->Width.xy.x = pwidths->real_width.xy.x =
+ finfo.MissingWidth * pscale->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.
@@ -718,18 +737,19 @@
}
}
private int
-store_glyph_width(int *pwidth, int wmode, double scale,
+store_glyph_width(pdf_glyph_width_t *pwidth, int wmode, double scale,
const gs_glyph_info_t *pinfo)
{
double w, v;
- if (wmode && (w = pinfo->width[wmode].y) != 0)
- v = pinfo->width[wmode].x;
+ pwidth->xy = pinfo->width[wmode];
+ if (wmode)
+ w = pwidth->xy.y, v = pwidth->xy.x;
else
- w = pinfo->width[wmode].x, v = pinfo->width[wmode].y;
+ w = pwidth->xy.x, v = pwidth->xy.y;
if (v != 0)
- return_error(gs_error_rangecheck);
- *pwidth = (int)(w * scale);
+ return 1;
+ pwidth->w = (int)(w * scale);
return 0;
}
Index: gdevpdtt.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdtt.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- gdevpdtt.h 27 Jun 2002 04:19:57 -0000 1.3
+++ gdevpdtt.h 9 Jul 2002 14:29:35 -0000 1.4
@@ -25,6 +25,62 @@
* gdevpdtt.c, gdevpdtc.c, and gdevpdte.c.
*/
+/* ---------------- Coordinate systems ---------------- */
+
+/*
+
+ The current text code has to deal with 6 different coordinate systems.
+ This situation is complex, confusing, and fragile, but despite literally
+ years of struggle we have been unable to understand how to simplify it.
+
+ 1) PostScript user space at the time a text operator is invoked. The
+ width values for ashow, xshow, etc. are specified in this space: these
+ values appear in the delta_all, delta_space, x_widths, and y_widths
+ members of the text member of the common part of the text enumerator
+ (pdf_text_enum_t).
+
+ 2) Device space. For the pdfwrite device, this is a straightforward space
+ with (0,0) in the lower left corner. The usual resolution is 720 dpi,
+ but this is user-settable to provide a tradeoff between file size and
+ bitmap resolution (for rendered Patterns and fonts that have to be
+ converted to bitmaps).
+
+ 3) PDF user space. During the processing of text operators, this is
+ always the same as the default PDF user space, in which 1 unit = 1/72",
+ because an Acrobat quirk apparently requires this. (See stream_to_text
+ in gdevpdfu.c.)
+
+ 4) Font design space. This is the space in which the font's character
+ outlines and advance widths are specified, including the width values
+ returned by font->procs.glyph_info and by pdf_char_widths.
+
+ 5) PDF unscaled text space. This space is used for the PDF width
+ adjustment values (Tc, Tw, and TL parameters, and " operator) and
+ positioning coordinates (Td and TD operators).
+
+ 6) PDF text space. This space is used for the width adjustments for the
+ TJ operator.
+
+ The following convert between these spaces:
+
+ - The PostScript CTM (pte->pis->ctm) maps #1 to #2.
+
+ - The mapping from #3 to #2 is a scaling by pdev->HWResolution / 72.
+
+ - The mapping from #5 to #6 is a scaling by the size member of
+ pdf_text_state_values_t, which is the size value for the Tf operator.
+
+ - The matrix member of pdf_text_state_values_t maps #5 to #2, which is the
+ matrix for the Tm operator or its abbreviations.
+
+ - The FontMatrix of a font maps #4 to #1.
+
+ Note that the PDF text matrix (set by the Tm operator) maps #5 to #3.
+ However, this is not actually stored anywhere: it is computed by
+ multiplying the #5->#2 matrix by the #2->#3 scaling.
+
+*/
+
/* ---------------- Types and structures ---------------- */
/* Define the text enumerator. */
@@ -46,16 +102,24 @@
*/
typedef struct pdf_text_process_state_s {
pdf_text_state_values_t values;
- int members; /* which values need to be set */
gs_font *font;
} pdf_text_process_state_t;
/*
- * Define the structure used to return glyph width information.
+ * Define the structure used to return glyph width information. Note that
+ * there are two different sets of width information: real-number (x,y)
+ * values, which give the true advance width, and an integer value, which
+ * gives an X advance width for WMode = 0 or a Y advance width for WMode = 1.
+ * The return value from pdf_glyph_width() indicates which of these is/are
+ * valid.
*/
+typedef struct pdf_glyph_width_s {
+ int w;
+ gs_point xy;
+} pdf_glyph_width_t;
typedef struct pdf_glyph_widths_s {
- int Width; /* unmodified, for Widths */
- int real_width; /* possibly modified, for rendering */
+ pdf_glyph_width_t Width; /* unmodified, for Widths */
+ pdf_glyph_width_t real_width; /* possibly modified, for rendering */
} pdf_glyph_widths_t;
/* ---------------- Procedures ---------------- */
@@ -84,29 +148,30 @@
/*
* Compute the cached values in the text processing state from the text
- * parameters, current_font, and pis->ctm. Return either an error code (<
- * 0) or a mask of operation attributes that the caller must emulate.
- * Currently the only such attributes are TEXT_ADD_TO_ALL_WIDTHS and
- * TEXT_ADD_TO_SPACE_WIDTH. Note that this procedure fills in all the
- * values in ppts->values, not just the ones that need to be set now.
+ * parameters, pdfont, and pis->ctm. Return either an error code (< 0) or a
+ * mask of operation attributes that the caller must emulate. Currently the
+ * only such attributes are TEXT_ADD_TO_ALL_WIDTHS and
+ * TEXT_ADD_TO_SPACE_WIDTH.
*/
int pdf_update_text_state(pdf_text_process_state_t *ppts,
const pdf_text_enum_t *penum,
- pdf_font_resource_t *pdfont, const gs_matrix *pfmat);
+ pdf_font_resource_t *pdfont,
+ const gs_matrix *pfmat);
/*
* Set up commands to make the output state match the processing state.
* General graphics state commands are written now; text state commands
- * are written later. Update ppts->values to reflect all current values.
+ * are written later.
*/
int pdf_set_text_process_state(gx_device_pdf *pdev,
- const gs_text_enum_t *pte, /* for pdcolor, pis */
- pdf_text_process_state_t *ppts,
- const gs_const_string *pstr);
+ const gs_text_enum_t *pte, /*for pdcolor, pis*/
+ pdf_text_process_state_t *ppts);
/*
* Get the widths (unmodified and possibly modified) of a glyph in a (base)
- * font. Return 1 if the width should not be cached.
+ * font. If the width is cachable (implying that the w values area valid),
+ * return 0; if only the xy values are valid, or the width is not cachable
+ * for some other reason, return 1.
*/
int pdf_glyph_widths(pdf_font_resource_t *pdfont, gs_glyph glyph,
gs_font_base *font, pdf_glyph_widths_t *pwidths);
Index: gdevpdtw.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpdtw.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- gdevpdtw.c 28 Jun 2002 01:48:41 -0000 1.4
+++ gdevpdtw.c 9 Jul 2002 14:29:35 -0000 1.5
@@ -180,7 +180,12 @@
{
stream *s = pdev->strm;
- pprints1(s, "/Encoding %s", pdfont->u.type0.Encoding_name);
+ /*
+ * The Encoding name might be missing if an error occurred when
+ * creating the font resource.
+ */
+ if (pdfont->u.type0.Encoding_name[0])
+ pprints1(s, "/Encoding %s", pdfont->u.type0.Encoding_name);
pprintld1(s, "/DescendantFonts[%ld 0 R]",
pdf_font_id(pdfont->u.type0.DescendantFont));
stream_puts(s, "/Subtype/Type0>>\n");
More information about the gs-cvs
mailing list