[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