[gs-cvs] rev 8217 - in trunk/gs: lib src

leonardo at ghostscript.com leonardo at ghostscript.com
Wed Aug 29 19:36:53 PDT 2007


Author: leonardo
Date: 2007-08-29 19:36:52 -0700 (Wed, 29 Aug 2007)
New Revision: 8217

Modified:
   trunk/gs/lib/opdfread.ps
   trunk/gs/lib/pdf_font.ps
   trunk/gs/lib/pdf_ops.ps
   trunk/gs/src/gdevpdte.c
   trunk/gs/src/gdevpdti.c
   trunk/gs/src/gdevpdtt.c
   trunk/gs/src/gdevpdtt.h
Log:
Fix (pdfwrite) : Properly handle FontMatrix of a Type 3 font.

DETAILS :

Bug 689267 "File converted to PDF displays badly in Acrobat".

Patch from SaGS. His explanation is quoted below.

Part #1: pdfwrite fixes (gdevpdti.c, gdevpdte.c, gdevpdtt.h, gdevpdtt.c :

- Generalize pdfwrite computations for glyph widths and placement, 
  which currently assume an [s 0 0 s tx ty]-type original (= ignoring 
  changes made by makefont & similar) FontMatrix, to work with an 
  arbitrary matrix.

- Fix: the "wy" operand of "d0"/"d1" in Type 3 charproc streams must 
  be zero. Note: other parts of the code already consider wy == 0, 
  and don't need to be changed.

- Remove font_orig_scale() and pdf_font3_scale(), which are not used 
  anymore. Their simple presence is a sign of the assumption that 
  font matrices are simple scalings.

- Minor: remove a dead variable ("int code = 0; ... return code;"). 
  This variable is never changed, because there's another "int code" 
  inside the "for", but it is confusing and takes a lot of research 
  to figure out the behaviour is OK and no usefull error code is 
  lost (it's the 2nd time I stumble against this...)

Notes:
  - All non-Adobe PDF viewers that I tested (Evince/ Fedora 7, 
    Foxit Reader 2.0/ Windows, Jaws PDF Editor 3.5/ Windows, and 
    Ghostscript -r8204) have problems with "weird" font matrices.
    The bug in ghostscript is addressed below.
  - I do have an alternate patch, which "normalises" the 
    FontMatrix, for better viewers compatibility . But this method 
    cannot work when fonts are not embedded: cannot "normalize" 
    something stored in an external file.

 part #2: PDF interpreter fixes (pdf_font.ps, pdf_ops.ps) :

- Force the "wy" parameter of "d0", not only of "d1", in Type 3 
  charproc streams to 0. Comment changed to suggest this is an action 
  is expected to be done as part of enforcing the metrics stored in 
  the PDF (which always imply wy == 0), and not some strange 
  behaviour in Reader.

- A detail in PDF1.7 Ref 5.3.3 "Text Space Details" states that "wy" 
  (or "wx" in WMode 1) must be forced to 0 in PDF text space too, not 
  only in PDF glyph space. To implement this with non-[s 0 0 s tx ty] 
  font matrices, a different method is used: decode "show" strings 
  and extract glyph widths with "cshow", put these into an array, 
  then render the text with "x/yshow".
  - since "wy/x" = 0 in glyph space, the code does not need to use 
    "idtransform", a "div" by "FontMatrix.xx" is sufficient;
  - use a trick (see comment in code) when "FontMatrix.xx" = 0.

CIDFonts are not changed. Those with a "straight" matrix continue to 
work, but there's no improvement if they have a weird "/FontMatrix". 
I think this would require a radical change, and the result will be 
much slower than it is now.

part #3: supplemental ps2write fixes (in opdfread.ps).

- opdfread.ps assumed the FontMatrix is a simple scaling by 0.001;
  generalize the computations to work with an arbitrary matrix.

- Implement a detail of PDF1.7 Ref 5.3.3 "Text Space Details" (nuking 
  the "wy" in text space) if a non-[s 0 0 s tx ty] "/FontMatrix". 
  Similar to the change in the main PDF interpreter, but shorter 
  because opdfread.ps does not handle vertical writing or CID fonts. 

Also "wy" in "d0"/"d1" is already 0 (see patch for pdfwrite), so 
needs no adjustment.

EXPECTED DIFFERENCES :

pdfwrite :
prfmm.pdf - A 1-pixel shift of 1 glyph, probably due to a different rounding. Mot important.


Modified: trunk/gs/lib/opdfread.ps
===================================================================
--- trunk/gs/lib/opdfread.ps	2007-08-29 17:36:36 UTC (rev 8216)
+++ trunk/gs/lib/opdfread.ps	2007-08-30 02:36:52 UTC (rev 8217)
@@ -1342,8 +1342,15 @@
         /Encoding exch put                              % s fr f
         1 index /Metrics //knownget exec {              % s fr f M
           2 index /Subtype get /TrueType ne {
-            % Adjust Metrics for fonts converted from TrueTypes by 3d party.
-            1 index /FontMatrix get 0 get 0.001 div
+            1 index /FontMatrix get 0 get
+            dup 0 eq {
+	      % FontMatrix[0] == 0, so cannot downscale by it
+	      % HACK: downscale by FontMatrix[1], and will get the target value of wx as wy
+	      pop
+	      1 index /FontMatrix get 1 get
+	      dup 0 eq { pop 1 } if % sorry, FontMatrix is singular so cannot enforce the PDF metrics
+            } if
+            0.001 div
             //ScaleMetrics exec
           } if
           1 index exch /Metrics exch put                % s fr f
@@ -3130,6 +3137,7 @@
 /SetFont  % <resource_name> <size> SetFont -
 { dup //GraphicState exch /FontSize exch put
   //ResolveAndSetFont exec
+  //GraphicState /FontMatrixNonHV currentfont /FontMatrix get 1 get 0 ne put
 } bind def
 
 /ShowText  % <string> ShowText -
@@ -3137,15 +3145,42 @@
     //GraphicState /WordSpacing get 0
     32
     //GraphicState /CharacterSpacing get 0
-    6 5 roll awidthshow
+    6 5 roll
+    //GraphicState /FontMatrixNonHV get {
+      % Use xshow to force wy in text space to be 0 (PDF1.7 5.3.3 "Text Space Details")
+      %stack: wordspacing_wx wordspacing_wy space_char charspacing_wx charspacing_wy string
+      [                                         % wwx wwy sp cwx cwy str [
+        7 -2 roll pop				% sp cwx cwy str [ ww
+        5 -2 roll pop				% sp str [ ww cw
+        5 -1 roll                               % str [ ww cw sp
+        {                                       % str [ ... ww cw sp c wx wy
+          exch % will be removed, unless FontMatrix.xx == 0 (FontMatrixNonHV already true)
+          pop					% str [ ... ww cw sp c w
+          3 index add                           % str [ ... ww cw sp c w+cw
+          exch 2 index eq { 3 index add } if    % str [ ... ww cw sp w+cw[+ww]
+          4 1 roll                              % str [ ... w+cw[+ww] ww cw sp
+        }
+        currentfont /FontMatrix get 0 get 0 ne {
+          1 1 index length 1 sub getinterval cvx % drop the "exch"
+        } if
+        5 index                                 % str [ ww cw sp {cshowproc} str
+        cshow                                   % str [ widths... ww cw sp
+      pop pop pop ]                             % str [widths...]
+      xshow
+    } {
+      awidthshow
+    } ifelse
   } {
     //GraphicState /CharacterSpacing get 0 eq
+    //GraphicState /FontMatrixNonHV get not and
     //GraphicState /WordSpacing get 0 eq and {
       true charpath
     } {
       % Emulate with "{ charpath } cshow".
       % Not sure how it works with CID fonts.
       {                                                 % c wx wy
+        exch % will be removed, unless FontMatrixNonHV && FontMatrix.xx == 0
+        pop 0						% (PDF1.7 5.3.3 "Text Space Details")
         currentpoint 5 4 roll                           % wx wy x y c
         ( ) dup 0 3 index put true charpath             % wx wy x y c
         5 1 roll                                        % c wx wy x y
@@ -3155,6 +3190,11 @@
           //GraphicState /WordSpacing get 0 rmoveto
         } if
       }
+      //GraphicState /FontMatrixNonHV get dup not exch {
+        pop currentfont /FontMatrix get 0 get 0 ne
+      } if {
+        1 1 index length 1 sub getinterval cvx
+      } if
       exch cshow
     } ifelse
   } ifelse

Modified: trunk/gs/lib/pdf_font.ps
===================================================================
--- trunk/gs/lib/pdf_font.ps	2007-08-29 17:36:36 UTC (rev 8216)
+++ trunk/gs/lib/pdf_font.ps	2007-08-30 02:36:52 UTC (rev 8217)
@@ -212,7 +212,24 @@
                 % character space, but the FontMatrix may specify
                 % some other scale factor.  Compensate for this here,
                 % by scaling the Widths if necessary.
-      0.001 2 index /FontMatrix get 0 get div
+      0.001 2 index /FontMatrix get 0 get
+      dup 0 eq {
+		% FontMatrix.xx == 0, so we cannot scale down by xx.
+		% - FontMatrix[0] == 0 implies either FontMatrix[1] <> 0 or 
+		%   FontMatrix cannot be inverted. In the 1st case we have 
+		%   FontMatrixNonHV == true and will render text with cshow + xshow. 
+		%   In the 2nd case, metrics in the PDF Font object cannot be enforced 
+		%   [by altering metrics in PS glyph space].
+		% HACK:
+		% - we scale down by FontMatrix[1];
+		% - given the format of Metrics entries we use, wy = 0 in glyph space;
+		% - as a result, the cshow procedure receives as wy the value we 
+		%   need for wx (all of this in PS user space).
+	pop
+	2 index /FontMatrix get 1 get
+	dup 0 eq { pop 1 } if % sorry, no way to enforce PDF metrics by altering the font
+      } if
+      div
                 % Stack: font font-res mscale
       /FirstChar 2 index /FirstChar oget def
       /LastChar  2 index /LastChar  oget def
@@ -799,6 +816,15 @@
     FontName currentdict end definefont exch pop
 } bdef
 /.adjustcharwidth {	% <wx> <wy> .adjustcharwidth <wx'> <wy'>
+  % Enforce the metrics, in glyph space, to the values found in the PDF Font object
+  % - force wy == 0 (assumed, and not stored in the PDF font)
+  %   Even though PDF1.3-1.7 specifications state that this must be 0,
+  %   Distiller sometimes creates Type3 fonts with non-zero wy. We set
+  %   it to 0 since this is apparently what Acrobat Reader 4 and 5 do.
+  %   PDF1.2 does not mention this restriction, it only says
+  %   "see setcharwidth/ setcachedevice in the PostScript Reference".
+  % - get wx from the Widths array (do nothing if not present)
+  pop 0
   /Widths where {
     begin
     CharCode FirstChar ge CharCode LastChar le and {
@@ -1519,16 +1545,6 @@
     .adjustcharwidth setcharwidth
   } bdef
   /d1 {
-    4 index 0 ne {
-      % invalid wy parameter for d1 in Type3 font (must be 0)
-      % Even though the PDF 1.4 specification states that this must be 0,
-      % Distiller sometimes creates Type3 fonts with non-zero wy. We set
-      % it to 0 since this is apparently what Acrobat Reader 4 and 5 do,
-      % but if the specification is ever changed to allow non-zero wy, this
-      % will not work.
-      5 -1 roll pop 0 5 1 roll	  % set wy to 0
-    } if
-
     2 copy                           % ... llx lly urx ury | urx ury 
     0 ne exch 0 ne                   % ... llx lly urx ury | ury!=0 urx!=0
     3 index 6 index eq and           % ... llx lly urx ury | ury!=0 (urx!=0 && llx==urx)

Modified: trunk/gs/lib/pdf_ops.ps
===================================================================
--- trunk/gs/lib/pdf_ops.ps	2007-08-29 17:36:36 UTC (rev 8216)
+++ trunk/gs/lib/pdf_ops.ps	2007-08-30 02:36:52 UTC (rev 8217)
@@ -61,6 +61,8 @@
 %	TextRise
 %	TextRenderingMode
 %	WordSpacing
+% (The following is cached information derived from other graphics state params)
+%	FontMatrixNonHV % TextFont.FontMatrix alters horz/vert glyph advance vector direction
 
 /nodict 1 dict def
 nodict /self { //nodict } executeonly put
@@ -401,6 +403,7 @@
    /WordSpacing 0 def		% 0 Tw
    /TextHScaling 1.0 def	% 100 Tz
    /TextFont null def
+   /FontMatrixNonHV //false def
    /Show { showfirst } def
  } bdef
 
@@ -460,6 +463,62 @@
 
 % ---------------- Font control ---------------- %
 
+% Test if the FontMatrix could transform a horizontal/vertical (depending
+% on writing mode) advance vector in glyph space into one with a different
+% direction in text space.
+% - if FontMatrix = [a b c d tx ty], this condition translates to:
+%       b != 0 for horizontal writing mode
+%       c != 0 for vertical writing mode
+% - when false, we automatically have wy/x == 0 in text space whenever wy/x == 0
+%   in glyph space, and can avoid the slow method that is otherwise necessary
+%   to implement zeroing wy/x cf PDF Ref 5.3.3 "Text space details"
+    % Worker procedure for testing a single font matrix
+/?FontMatrixNonHV {		    % ?horz <<fontdict>> -- ?horz ?nonhv
+    /FontMatrix .knownget {
+	1 index { 1 } { 2 } ifelse get 0 ne
+    } {
+	//false
+    } ifelse
+} bdef
+    % Worker procedure for recursive checking of font matrices
+/?FontMatrixNonHV {		    % {self} ?horz <<font>> -- {self} ?horz ?nonhv
+    2 copy //?FontMatrixNonHV exec {	    % check the font's own FontMatrix
+	pop pop //true
+    } {
+	% look for descendents/ components
+	pop				    % {self} ?horz <<font>>
+	dup /FontType get
+	dup 0 eq {			    % Type 0: look into FDepVector
+	    pop /FDepVector get 2 index	    % {self} ?horz [fonts..] {testproc}
+	} {
+	    9 eq {			    % Type 9 (CIDFontType 0): check FDArray
+		/FDArray get //?FontMatrixNonHV
+	    } {				    % all others: nothing more to check
+		pop {} {}
+	    } ifelse
+	} ifelse
+	%stack: {self} ?horz [fonts..] {testproc}
+	//false 5 2 roll {		    % {testproc} false {self} ?horz <<subfont>>
+	    4 index exec {
+		4 -1 roll pop //true 4 1 roll
+		exit
+	    } if
+	} forall
+	%stack: {testproc} ?nonhv {self} ?horz
+	4 2 roll exch pop
+    } ifelse
+} bdef
+    % Main procedure
+/?FontMatrixNonHV {		% <<rootfont>> -- ?nonhv
+    //?FontMatrixNonHV exch
+    % determine WMode
+    dup /WMode .knownget { 0 eq } { //true } ifelse % {proc} <<rootfont>> ?horz
+    exch
+    % call the worker procedure
+    //?FontMatrixNonHV exec
+    exch pop exch pop
+} bdef
+
 /Tf {		% <font> <scale> Tf -
   dup 0 eq {
     (\n   **** Warning: Invalid 0.0 font scale given for Tf ****\n)
@@ -472,6 +531,12 @@
     dup 1 eq { pop } { scalefont } ifelse
   }
   ifelse
+  dup ?FontMatrixNonHV dup FontMatrixNonHV ne {
+    /FontMatrixNonHV gput
+    { showfirst } /Show gput
+  } {
+    pop
+  } ifelse
   /TextFont gput settextstate
 } bdef
 
@@ -590,7 +655,7 @@
    { tW }
 ] readonly def
 /setshowstate
- { WordSpacing 0 eq TextSpacing 0 eq and
+ { WordSpacing 0 eq TextSpacing 0 eq and FontMatrixNonHV not and
     { TextRenderingMode 0 eq currentdevice .devicename /pdfwrite eq or {
         { setfillstate show }
       } {
@@ -625,25 +690,57 @@
     }
     { TextRenderingMode 0 eq TextRenderingMode 3 eq or currentdevice .devicename /pdfwrite eq or
        % Tr was set to graphic state.
-       { WordSpacing 0 eq
-          { { setfillstate TextSpacing 0 Vexch 3 -1 roll ashow } }
-	  { TextSpacing 0 eq
-            { { setfillstate WordSpacing 0 Vexch 32 4 -1 roll widthshow } }
-            { { setfillstate WordSpacing 0 Vexch 32
-                 TextSpacing 0 Vexch 6 -1 roll awidthshow } }
-	    ifelse
-	  }
-	 ifelse
+       { FontMatrixNonHV {
+           {
+             setfillstate
+             [ TextSpacing WordSpacing 3 index
+               {					    % str [... weach wword c undef|ythis xthis|undef
+		 exch % will be removed, unless FontMatrix.xx/yy == 0 (FontMatrixNonHV already true)
+                 Vexch pop                                  % str [... weach wword c wthis
+                 3 index add exch 32 eq {1 index add} if    % str [... weach wword w
+                 3 1 roll                                   % str [... w weach wword
+               }
+               % for the "exch" removed or not below, see comment in pdf_font.ps::getfontmetrics
+	       currentfont /FontMatrix get 0 3 Vexch pop get 0 ne {
+	         1 1 index length 1 sub getinterval cvx
+	       } if
+	       cshow pop pop ]
+             { xshow } { yshow } Vexch pop exec
+           }
+         } {
+           WordSpacing 0 eq
+            { { setfillstate TextSpacing 0 Vexch 3 -1 roll ashow } }
+	    { TextSpacing 0 eq
+              { { setfillstate WordSpacing 0 Vexch 32 4 -1 roll widthshow } }
+              { { setfillstate WordSpacing 0 Vexch 32
+                   TextSpacing 0 Vexch 6 -1 roll awidthshow } }
+	      ifelse
+	    }
+	   ifelse
+         } ifelse
        }
        { { WordSpacing TextSpacing
 			% Implement the combination of t3 and false charpath.
 			% Note that we must use cshow for this, because we
 			% can't parse multi-byte strings any other way.
-			% Stack: string xword xchar
-	    { pop pop (x) dup 0 3 index put false charpath
-			% Stack: xword xchar ccode
-             3 copy 32 eq { add } { exch pop } ifelse 0 Vexch rmoveto pop
+			% Stack: string wword wchar
+	    {
+	     exch % will be removed, unless FontMatrixNonHV && FontMatrix.xx/yy == 0
+			% Stack: str wword wchar ccode xthis ythis
+	     Vexch pop currentpoint 6 3 roll
+			% Stack: str wthis xorig yorig wword wchar ccode
+	     (x) dup 0 3 index put //false charpath
+             3 copy 32 eq { add } { exch pop } ifelse
+			% Stack: str wthis xorig yorig wword wchar ccode wextra
+             7 -3 roll moveto add
+             0 Vexch rmoveto pop
 	    }
+            % for the "exch" removed or not below, see comment in pdf_font.ps::getfontmetrics
+	    FontMatrixNonHV dup not exch {
+	      currentfont /FontMatrix get 0 3 Vexch pop get 0 ne
+	    } if {
+	      1 1 index length 1 sub getinterval cvx
+	    } if
 	   4 -1 roll cshow pop pop
 	   textrenderingprocs TextRenderingMode get exec
 	 }

Modified: trunk/gs/src/gdevpdte.c
===================================================================
--- trunk/gs/src/gdevpdte.c	2007-08-29 17:36:36 UTC (rev 8216)
+++ trunk/gs/src/gdevpdte.c	2007-08-30 02:36:52 UTC (rev 8217)
@@ -657,6 +657,33 @@
 }
 
 /*
+ * Convert glyph widths (.Width.xy and .real_widths.xy) from design to PDF text space
+ * Zero-out one of Width.xy.x/y per PDF Ref 5.3.3 "Text Space Details"
+ */
+private void
+pdf_char_widths_to_uts(pdf_font_resource_t *pdfont /* may be NULL for non-Type3 */,
+		       pdf_glyph_widths_t *pwidths)
+{
+    if (pdfont && pdfont->FontType == ft_user_defined) {
+	gs_matrix *pmat = &pdfont->u.simple.s.type3.FontMatrix;
+
+	pwidths->Width.xy.x *= pmat->xx; /* formula simplified based on wy in glyph space == 0 */
+	pwidths->Width.xy.y  = 0.0; /* WMode == 0 for PDF Type 3 fonts */
+	gs_distance_transform(pwidths->real_width.xy.x, pwidths->real_width.xy.y, pmat, &pwidths->real_width.xy);
+    } else {
+	/*
+	 * For other font types:
+	 * - PDF design->text space is a simple scaling by 0.001.
+	 * - The Width.xy.x/y that should be zeroed-out per 5.3.3 "Text Space Details" is already 0.
+	 */
+	pwidths->Width.xy.x /= 1000.0;
+	pwidths->Width.xy.y /= 1000.0;
+	pwidths->real_width.xy.x /= 1000.0;
+	pwidths->real_width.xy.y /= 1000.0;
+    }
+}
+
+/*
  * Compute the total text width (in user space).  Return 1 if any
  * character had real_width != Width, otherwise 0.
  */
@@ -668,7 +695,6 @@
 {
     int i;
     gs_point w;
-    double scale;
     gs_point dpt;
     int num_spaces = 0;
     int space_char =
@@ -681,13 +707,8 @@
     code = pdf_attached_font_resource(pdev, (gs_font *)font, &pdfont, NULL, NULL, NULL, NULL);
     if (code < 0)
 	return code;
-    if (font->FontType == ft_user_defined) {
-	pdf_font3_scale(pdev, (gs_font *)font, &scale);
-	scale *= ppts->values.size;
-    } else
-	scale = 0.001 * ppts->values.size;
     for (i = 0, w.x = w.y = 0; i < pstr->size; ++i) {
-	pdf_glyph_widths_t cw;
+	pdf_glyph_widths_t cw; /* in PDF text space */
 	gs_char ch = pstr->data[i];
 
 	{  const gs_glyph *gdata_i = (gdata != NULL ? gdata + i : 0);
@@ -710,6 +731,7 @@
 	    *accepted = 0;
 	    return code;
 	}
+	pdf_char_widths_to_uts(pdfont, &cw);
 	w.x += cw.real_width.xy.x;
 	w.y += cw.real_width.xy.y;
 	if (cw.real_width.xy.x != cw.Width.xy.x ||
@@ -720,7 +742,7 @@
 	    ++num_spaces;
     }
     *accepted = i;
-    gs_distance_transform(w.x * scale, w.y * scale,
+    gs_distance_transform(w.x * ppts->values.size, w.y * ppts->values.size,
 			  &ppts->values.matrix, &dpt);
     if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
 	int num_chars = *accepted;
@@ -784,20 +806,14 @@
 			  gs_point *pdpt, const gs_glyph *gdata, bool composite)
 {
     gx_device_pdf *const pdev = (gx_device_pdf *)pte->dev;
-    double scale;
     int space_char =
 	(pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH ?
 	 pte->text.space.s_char : -1);
-    int code = 0;
     gs_point start, total;
+    pdf_font_resource_t *pdfont3 = NULL;
 
-    if (font->FontType == ft_user_defined) {
-	gx_device_pdf *pdev = (gx_device_pdf *)pte->dev;
-
-	pdf_font3_scale(pdev, font, &scale);
-	scale *= ppts->values.size;
-    } else
-	scale = 0.001 * ppts->values.size;
+    if (font->FontType == ft_user_defined)
+	pdf_attached_font_resource(pdev, font, &pdfont3, NULL, NULL, NULL, NULL);
     pte->text.data.bytes = pstr->data;
     pte->text.size = pstr->size;
     pte->index = 0;
@@ -812,7 +828,7 @@
      * and the width values for pdf_append_chars are in device space.
      */
     for (;;) {
-	pdf_glyph_widths_t cw;	/* design space */
+	pdf_glyph_widths_t cw;	/* design space, then converted to PDF text space */
 	gs_point did, wanted, tpt;	/* user space */
 	gs_point v = {0, 0}; /* design space */
 	gs_char chr;
@@ -942,9 +958,10 @@
 		    break;
 	    }
 	}
+	pdf_char_widths_to_uts(pdfont3, &cw); /* convert design->text space */
 	if (pte->text.operation & TEXT_DO_DRAW) {
-	    gs_distance_transform(cw.Width.xy.x * scale,
-				  cw.Width.xy.y * scale,
+	    gs_distance_transform(cw.Width.xy.x * ppts->values.size,
+				  cw.Width.xy.y * ppts->values.size,
 				  &ppts->values.matrix, &did);
 	    gs_distance_transform((font->WMode ? 0 : ppts->values.character_spacing),
 				  (font->WMode ? ppts->values.character_spacing : 0),
@@ -974,8 +991,8 @@
 		return_error(gs_error_unregistered);
 	    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,
+	    gs_distance_transform(cw.real_width.xy.x * ppts->values.size,
+				  cw.real_width.xy.y * ppts->values.size,
 				  &ppts->values.matrix, &wanted);
 	    if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
 		gs_distance_transform(pte->text.delta_all.x,
@@ -1004,7 +1021,7 @@
 	pdev->charproc_just_accumulated = false;
     }
     *pdpt = total;
-    return code;
+    return 0;
 }
 
 /*

Modified: trunk/gs/src/gdevpdti.c
===================================================================
--- trunk/gs/src/gdevpdti.c	2007-08-29 17:36:36 UTC (rev 8216)
+++ trunk/gs/src/gdevpdti.c	2007-08-30 02:36:52 UTC (rev 8217)
@@ -479,11 +479,11 @@
 	is defined to paint glyphs with the current color."
 	However comparefiles/Bug687044.ps doesn't follow that. */
 	pdev->skip_colors = false; 
-	pprintg2(pdev->strm, "%g %g d0\n", (float)pw[0], (float)pw[1]);
+	pprintg1(pdev->strm, "%g 0 d0\n", (float)pw[0]);
     } else {
 	pdev->skip_colors = true;
 	pprintg6(pdev->strm, "%g %g %g %g %g %g d1\n", 
-	    (float)pw[0], (float)pw[1], (float)pw[2], 
+	    (float)pw[0], (float)0.0, (float)pw[2], 
 	    (float)pw[3], (float)pw[4], (float)pw[5]);
 	pdfont->u.simple.s.type3.cached[ch >> 3] |= 0x80 >> (ch & 7);
     }

Modified: trunk/gs/src/gdevpdtt.c
===================================================================
--- trunk/gs/src/gdevpdtt.c	2007-08-29 17:36:36 UTC (rev 8216)
+++ trunk/gs/src/gdevpdtt.c	2007-08-30 02:36:52 UTC (rev 8217)
@@ -700,18 +700,6 @@
     }
 }
 
-int
-font_orig_scale(const gs_font *font, double *sx)
-{   
-    gs_matrix mat;
-    int code = pdf_font_orig_matrix(font, &mat);
-
-    if (code < 0)
-	return code;
-    *sx = mat.xx;
-    return 0;
-}
-
 /* 
  * Check the Encoding compatibility 
  */
@@ -1233,16 +1221,6 @@
     return 1;
 }
 
-/* Get a synthesized Type 3 font scale. */
-void 
-pdf_font3_scale(gx_device_pdf *pdev, gs_font *font, double *scale)
-{
-    pdf_font_resource_t *pdfont;
-
-    pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
-    *scale = pdfont->u.simple.s.type3.FontMatrix.xx;
-}
-
 /*
  * Check for simple font.
  */
@@ -2073,13 +2051,12 @@
 }
 
 private int
-store_glyph_width(pdf_glyph_width_t *pwidth, int wmode, double scale,
+store_glyph_width(pdf_glyph_width_t *pwidth, int wmode, const gs_matrix *scale,
 		  const gs_glyph_info_t *pinfo)
 {
     double w, v;
 
-    pwidth->xy.x = pinfo->width[wmode].x * scale;
-    pwidth->xy.y = pinfo->width[wmode].y * scale;
+    gs_distance_transform(pinfo->width[wmode].x, pinfo->width[wmode].y, scale, &pwidth->xy);
     if (wmode)
 	w = pwidth->xy.y, v = pwidth->xy.x;
     else
@@ -2087,13 +2064,12 @@
     if (v != 0)
 	return 1;
     pwidth->w = w;
-    pwidth->v.x = pinfo->v.x * scale;
-    pwidth->v.y = pinfo->v.y * scale;
+    gs_distance_transform(pinfo->v.x, pinfo->v.y, scale, &pwidth->v);
     return 0;
 }
 
 private int
-get_missing_width(gs_font_base *cfont, int wmode, double scale_c, 
+get_missing_width(gs_font_base *cfont, int wmode, const gs_matrix *scale_c,
 		    pdf_glyph_widths_t *pwidths)
 {
     gs_font_info_t finfo;
@@ -2104,19 +2080,19 @@
     if (code < 0)
 	return code;
     if (wmode) {
-	pwidths->Width.xy.x = pwidths->real_width.xy.x = 0;
-	pwidths->Width.xy.y = pwidths->real_width.xy.y =
-		- finfo.MissingWidth * scale_c;
+	gs_distance_transform(0.0, -finfo.MissingWidth, scale_c, &pwidths->real_width.xy);
+	pwidths->Width.xy.x = 0;
+	pwidths->Width.xy.y = pwidths->real_width.xy.y;
 	pwidths->Width.w = pwidths->real_width.w =
 		pwidths->Width.xy.y;
 	pwidths->Width.v.x = - pwidths->Width.xy.y / 2;
 	pwidths->Width.v.y = - pwidths->Width.xy.y;
     } else {
-	pwidths->Width.xy.x = pwidths->real_width.xy.x =
-		finfo.MissingWidth * scale_c;
+	gs_distance_transform(finfo.MissingWidth, 0.0, scale_c, &pwidths->real_width.xy);
+	pwidths->Width.xy.x = pwidths->real_width.xy.x;
+	pwidths->Width.xy.y = 0;
 	pwidths->Width.w = pwidths->real_width.w =
 		pwidths->Width.xy.x;
-	pwidths->Width.xy.y = pwidths->real_width.xy.y = 0;
 	pwidths->Width.v.x = pwidths->Width.v.y = 0;
     }
     /*
@@ -2142,11 +2118,7 @@
     gs_font_base *cfont = pdf_font_resource_font(pdfont, false);
     gs_font *ofont = orig_font;
     gs_glyph_info_t info;
-    /*
-     * orig_scale is 1.0 for TrueType, 0.001 or 1.0/2048 for Type 1.
-     */
-    double sxc, sxo;
-    double scale_c, scale_o;
+    gs_matrix scale_c, scale_o;
     int code, rcode = 0;
     gs_point v;
     int allow_cdevproc_callout = (orig_font->FontType == ft_CID_TrueType 
@@ -2155,19 +2127,19 @@
 
     if (ofont->FontType == ft_composite)
 	return_error(gs_error_unregistered); /* Must not happen. */
-    code = font_orig_scale((const gs_font *)cfont, &sxc);
+    code = pdf_font_orig_matrix((const gs_font *)cfont, &scale_c);
     if (code < 0)
 	return code;
-    code = font_orig_scale(ofont, &sxo);
+    code = pdf_font_orig_matrix(ofont, &scale_o);
     if (code < 0)
 	return code;
-    scale_c = sxc * 1000.0;
-    scale_o = sxo * 1000.0;
+    gs_matrix_scale(&scale_c, 1000.0, 1000.0, &scale_c);
+    gs_matrix_scale(&scale_o, 1000.0, 1000.0, &scale_o);
     pwidths->Width.v.x = pwidths->Width.v.y = 0;
     pwidths->real_width.v.x = pwidths->real_width.v.y = 0;
     pwidths->replaced_v = false;
     if (glyph == GS_NO_GLYPH)
-	return get_missing_width(cfont, wmode, scale_c, pwidths);
+	return get_missing_width(cfont, wmode, &scale_c, pwidths);
     code = cfont->procs.glyph_info((gs_font *)cfont, glyph, NULL,
 				    GLYPH_INFO_WIDTH0 |
 				    (GLYPH_INFO_WIDTH0 << wmode) |
@@ -2179,7 +2151,7 @@
        So make a compatibe data here.
      */
     if (code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode))) {
-	code = get_missing_width(cfont, wmode, scale_c, pwidths);
+	code = get_missing_width(cfont, wmode, &scale_c, pwidths);
 	if (code < 0)
 	    v.y = 0;
 	else 
@@ -2187,7 +2159,7 @@
 	if (wmode && pdf_is_CID_font(ofont)) {
 	    pdf_glyph_widths_t widths1;
 
-	    if (get_missing_width(cfont, 0, scale_c, &widths1) < 0)
+	    if (get_missing_width(cfont, 0, &scale_c, &widths1) < 0)
 		v.x = 0;
 	    else
 		v.x = widths1.Width.w / 2;
@@ -2196,30 +2168,28 @@
     } else if (code < 0)
 	return code;
     else {
-	code = store_glyph_width(&pwidths->Width, wmode, scale_c, &info);
+	code = store_glyph_width(&pwidths->Width, wmode, &scale_c, &info);
 	if (code < 0)
 	    return code;
 	rcode |= code;
-	if (info.members & (GLYPH_INFO_VVECTOR0 << wmode)) {
-	    v.y = info.v.y * scale_c;
-	} else
-	    v.y = 0;
+	if (info.members  & (GLYPH_INFO_VVECTOR0 << wmode))
+	    gs_distance_transform(info.v.x, info.v.y, &scale_c, &v);
+	else 
+	    v.x = v.y = 0;
 	if (wmode && pdf_is_CID_font(ofont)) {
 	    if (info.members & (GLYPH_INFO_WIDTH0 << wmode)) {
-		v.x = info.width[0].x * scale_c / 2;
+		gs_point xy;
+
+		gs_distance_transform(info.width[0].x, info.width[0].y, &scale_c, &xy);
+		v.x = xy.x / 2;
 	    } else {
 		pdf_glyph_widths_t widths1;
 		
-		if (get_missing_width(cfont, 0, scale_c, &widths1) < 0)
+		if (get_missing_width(cfont, 0, &scale_c, &widths1) < 0)
 		    v.x = 0;
 		else
 		    v.x = widths1.Width.w / 2;
 	    }
-	} else {
-	    if (info.members  & (GLYPH_INFO_VVECTOR0 << wmode)) {
-		v.x = info.v.x * scale_c;
-	    } else
-		v.x = 0;
 	}
     }
     pwidths->Width.v = v;
@@ -2263,12 +2233,11 @@
 	    pwidths->replaced_v = true;
 	else 
 	    info.v.x = info.v.y = 0;
-	code = store_glyph_width(&pwidths->real_width, wmode, scale_o, &info);
+	code = store_glyph_width(&pwidths->real_width, wmode, &scale_o, &info);
 	if (code < 0)
 	    return code;
 	rcode |= code;
-	pwidths->real_width.v.x = info.v.x * scale_o;
-	pwidths->real_width.v.y = info.v.y * scale_o;
+	gs_distance_transform(info.v.x, info.v.y, &scale_o, &pwidths->real_width.v);
     }
     return rcode;
 }

Modified: trunk/gs/src/gdevpdtt.h
===================================================================
--- trunk/gs/src/gdevpdtt.h	2007-08-29 17:36:36 UTC (rev 8216)
+++ trunk/gs/src/gdevpdtt.h	2007-08-30 02:36:52 UTC (rev 8217)
@@ -161,7 +161,6 @@
  * Compute and return the orig_matrix of a font.
  */
 int pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat);
-int font_orig_scale(const gs_font *font, double *sx);
 
 /* 
  * Check the Encoding compatibility 
@@ -270,9 +269,6 @@
  */
 bool pdf_is_CID_font(gs_font *font);
 
-/* Get a synthesized Type 3 font scale. */
-void pdf_font3_scale(gx_device_pdf *pdev, gs_font *font, double *scale);
-
 /* Release a text characters colloction. */
 void pdf_text_release_cgp(pdf_text_enum_t *penum);
 



More information about the gs-cvs mailing list