Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
%    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
2
% 
3
% This software is provided AS-IS with no warranty, either express or
4
% implied.
5
% 
6
% This software is distributed under license and may not be copied,
7
% modified or distributed except as expressly authorized under the terms
8
% of the license contained in the file LICENSE in this distribution.
9
% 
10
% For more information about licensing, please refer to
11
% http://www.ghostscript.com/licensing/. For information on
12
% commercial licensing, go to http://www.artifex.com/licensing/ or
13
% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
% San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
 
16
% $Id: pdf_ops.ps,v 1.41 2005/09/28 04:33:27 dan Exp $
17
% Definitions for most of the PDF operators.
18
 
19
.currentglobal true .setglobal
20
 
21
% Define pdfmark.  Don't allow it to be bound in.
22
% Also don't define it in systemdict, because this leads some Adobe code
23
% to think this interpreter is a distiller.
24
% (If this interpreter really is a distiller, don't do this.)
25
systemdict /pdfmark known not
26
 { userdict /pdfmark { cleartomark } bind put } if
27
 
28
userdict /GS_PDF_ProcSet 127 dict dup begin
29
 
30
% ---------------- Abbreviations ---------------- %
31
 
32
/bdef { bind def } bind def
33
 
34
% ---------------- Graphics state stack ---------------- %
35
 
36
% PDF adds a number of parameters to the graphics state.
37
% We implement this by pushing and popping a dictionary
38
% each time we do a PDF gsave or grestore.
39
% The keys in this dictionary are as follows:
40
%	self			% identifies the dictionary as one of ours
41
%	ClipRect		% (optional)
42
%	Show
43
%	TextSaveMatrix		% matrix at time of BT (iff within BT/ET)
44
% (The following correspond directly to PDF state parameters.)
45
%	AlphaIsShape
46
%	FillConstantAlpha
47
%	FillColor
48
%	FillColorSpace
49
%	FillOverprint
50
%	SoftMask
51
%	StrokeConstantAlpha
52
%	StrokeColor
53
%	StrokeColorSpace
54
%	StrokeOverprint
55
%	TextSpacing
56
%	TextHScaling
57
%	Leading
58
%	TextFont
59
%	TextLineMatrix
60
%	TextMatrix
61
%	TextRise
62
%	TextRenderingMode
63
%	WordSpacing
64
 
65
/nodict 1 dict def
66
nodict /self { //nodict } executeonly put
67
nodict readonly pop
68
 
69
/dictbeginpage {	% <initialdict> dictbeginpage -
70
  //nodict 20 dict .copydict begin { def } forall
71
  graphicsbeginpage textbeginpage
72
} bdef
73
/endpage {	% - endpage -
74
  showpage end
75
} bdef
76
 
77
/graphicsbeginpage {
78
  initgraphics
79
  currentdict /ClipRect knownoget { aload pop rectclip } if
80
 
81
  1 ca  1 CA  null SMask  false AIS  /Compatible BM  true TK
82
} bdef
83
 
84
/gput		% <value> <key> gput -
85
 { exch currentdict //nodict eq { /self dup load end 5 dict begin def } if
86
		% If we're in a Level 1 system, we need to grow the
87
		% dictionary explicitly.
88
   currentdict length currentdict maxlength ge %eq
89
    { currentdict dup length 3 mul 2 idiv 1 add dict .copydict end begin 
90
    }
91
   if def
92
 } bdef
93
 
94
% Restore graphics state, but do not modify path. Paths are not part
95
% of the PDF graphics state; see 4.4.1 of PDF reference 3rd ed.
96
/grestore_nopath {
97
  % Collect the upath with an identity CTM
98
  { matrix setmatrix //false upath } stopped {
99
    pop grestore newpath
100
  } {
101
    % Save the CTM, set identity during the uappend, then set the CTM
102
    grestore matrix currentmatrix matrix setmatrix
103
    exch newpath uappend setmatrix
104
  } ifelse
105
} bdef
106
 
107
/q {
108
  gsave //nodict begin
109
} bdef
110
% Some PDF files have excess Q operators!
111
/Q {
112
  currentdict /self .knownget {
113
    exec //nodict eq { end grestore_nopath false } { true } ifelse
114
  } {
115
    true	% formaterror -- not a gsave dict
116
  } ifelse
117
  { (\n   **** File has imbalanced q/Q operators \(too many Q's\) ****\n)
118
    pdfformaterror
119
  } if
120
} bdef
121
 
122
% Save PDF gstate
123
/qstate {       % - qstate <qstate>
124
  gstate
125
} bdef
126
 
127
% Set PDF gstate
128
/setqstate {    % <qstate> setqstate -
129
  { matrix setmatrix //false upath } stopped {
130
    pop setgstate newpath
131
  } {
132
    % Save the CTM, set identity during the uappend, then set the CTM
133
    exch setgstate matrix currentmatrix matrix setmatrix
134
    exch newpath uappend setmatrix
135
  } ifelse
136
} bdef
137
 
138
% ---------------- Color setting ---------------- %
139
 
140
/fcput		% <color> <colorspace> fcput -
141
 { /FillColorSpace gput /FillColor gput
142
 } bdef
143
/scput		% <color> <colorspace> scput -
144
 { /StrokeColorSpace gput /StrokeColor gput
145
 } bdef
146
/csput		% <colorspace> csput -
147
 { csset 2 copy fcput scput
148
 } bdef
149
 
150
/csdevgray [/DeviceGray] readonly def
151
/csdevrgb [/DeviceRGB] readonly def
152
/csdevcmyk [/DeviceCMYK] readonly def
153
/cspattern [/Pattern] readonly def
154
/nullpattern1 mark
155
   /PatternType 1 /PaintType 1 /TilingType 3 /BBox [0 0 0 0]
156
   /XStep 1 /YStep 1 /PaintProc { }
157
.dicttomark readonly def
158
/nullpattern2 nullpattern1 dup length dict copy readonly def
159
 
160
% Each entry in the color space dictionary is a procedure of the form
161
%	<cspace> -proc- <cspace> <initial-color>
162
/CSdict mark
163
  /DeviceGray { pop //csdevgray 0 } bind
164
  /DeviceRGB { pop //csdevrgb [0 0 0] cvx } bind
165
  /DeviceCMYK { pop //csdevcmyk [0 0 0 1] cvx } bind
166
  /CIEBasedA { 0 } bind
167
  /CIEBasedABC { [0 0 0] cvx } bind
168
  /ICCBased { [ 1 index 1 oget /N get { 0 } repeat ] cvx } bind
169
  /Separation { 1 } bind
170
  /DeviceN {	% What is the correct value??
171
    [ 1 index 1 get length { 1 } repeat ] cvx
172
  } bind
173
  /Indexed { 0 } bind
174
  /Pattern {
175
    dup type /nametype eq 1 index length 1 eq or {
176
      pop //cspattern //nullpattern1 matrix makepattern
177
    } {
178
      //nullpattern2 matrix makepattern 1 index 1 get csset
179
		% Stack: patternspace nullpattern basecolor basespace
180
      pop [ 3 1 roll dup type /arraytype eq { aload pop } if
181
      counttomark -1 roll ] cvx
182
    } ifelse
183
  } bind
184
.dicttomark readonly def
185
/csset			% <cspace> csset <color> <cspace>
186
 { dup dup type /nametype ne { 0 get } if //CSdict exch get exec exch
187
 } bdef
188
 
189
/g { //csdevgray fcput } bdef
190
/G { //csdevgray scput } bdef
191
/rg { 3 array astore cvx //csdevrgb fcput } bdef
192
/RG { 3 array astore cvx //csdevrgb scput } bdef
193
/k { 4 array astore cvx //csdevcmyk fcput } bdef
194
/K { 4 array astore cvx //csdevcmyk scput } bdef
195
/cs { csset fcput } bdef
196
/CS { csset scput } bdef
197
/ri { pop } bdef
198
% We have to break up sc according to the number of operands.
199
/sc1 { /FillColor gput } bdef
200
/SC1 { /StrokeColor gput } bdef
201
% We have to avoid storing into a color array associated with an outer
202
% gsave level, so we do a kind of "copy on write".
203
/sc* {
204
  currentdict /FillColor .knownget {
205
    astore pop
206
  } {
207
    /FillColor load
208
    % FillColor may contain either a single value or an array.
209
    dup type /arraytype eq { length }{ pop 1 } ifelse
210
    array astore cvx /FillColor gput
211
  } ifelse
212
} bdef
213
/SC* {
214
  currentdict /StrokeColor .knownget {
215
    astore pop
216
  } {
217
    /StrokeColor load
218
    % StrokeColor may contain either a single value or an array.
219
    dup type /arraytype eq { length }{ pop 1 } ifelse
220
    array astore cvx /StrokeColor gput
221
  } ifelse
222
} bdef
223
 
224
% ---------------- Overprint/transparency setting ---------------- %
225
 
226
/op { /FillOverprint gput } bdef
227
/OP { /StrokeOverprint gput } bdef
228
/OPM {
229
  /.setoverprintmode where { pop .setoverprintmode } { pop } ifelse
230
} bdef
231
/ca { /FillConstantAlpha gput } bdef
232
/CA { /StrokeConstantAlpha gput } bdef
233
/SMask { /SoftMask gput } bdef
234
/AIS { /AlphaIsShape gput } bdef
235
/BM {
236
  /.setblendmode where {
237
    pop [ exch dup type /nametype ne { aload pop } if /Normal ] {
238
      { .setblendmode } .internalstopped not { exit } if pop
239
    } forall
240
  } {
241
    pop
242
  } ifelse
243
} bdef
244
/TK {
245
  /.settextknockout where { pop .settextknockout } { pop } ifelse
246
} bdef
247
 
248
% ---------------- Color installation ---------------- %
249
 
250
% Establish a given color (and color space) as current.
251
/.settransparencyparams {	% <alpha> <smask> .settransparencyparams -
252
  /.inittransparencymask where {
253
    pop AlphaIsShape {
254
      1 .setopacityalpha 0 .inittransparencymask exch .setshapealpha 1
255
    } {
256
      1 .setshapealpha 1 .inittransparencymask exch .setopacityalpha 0
257
    } ifelse
258
	% Set the soft mask by rendering the XObject.  Doing this every time
259
	% is obviously very inefficient; we'll improve it later.
260
    .settransparencymask    
261
  } {
262
    pop pop
263
  } ifelse
264
} bdef
265
/.settransparencymask {		% <paramdict> <masknum> .settransparencymask -
266
  exch dup null eq {
267
    pop .inittransparencymask
268
  } {
269
    dup /Draw get exec
270
  } ifelse
271
} bdef
272
% (Non-mask) images must execute setfillblend.
273
/setfillblend {
274
  FillOverprint setoverprint
275
  FillConstantAlpha SoftMask .settransparencyparams
276
} def
277
/setfillstate {
278
  FillColor FillColorSpace setgcolor setfillblend
279
} def
280
/setstrokestate {
281
  StrokeColor StrokeColorSpace setgcolor StrokeOverprint setoverprint
282
  StrokeConstantAlpha SoftMask .settransparencyparams
283
} def
284
/Cdict 15 dict dup begin	% <color...> <colorspace> -proc- -
285
  /DeviceGray { pop setgray } bdef
286
  /DeviceRGB { pop setrgbcolor } bdef
287
  /DeviceCMYK { pop setcmykcolor } bdef
288
  /CIEBasedA { setgcolorspace setcolor } bdef
289
  /CIEBasedABC /CIEBasedA load def
290
  /CIEBasedDEF /CIEBasedA load def
291
  /CIEBasedDEFG /CIEBasedA load def
292
  /ICCBased /CIEBasedA load def
293
  /Separation /CIEBasedA load def
294
  /DeviceN /CIEBasedA load def
295
  /Indexed /CIEBasedA load def
296
  /Pattern
297
   { setgcolorspace
298
 
299
     % Since multiple patterns may share
300
     % same data stream, we need to ensure
301
     % that the stream is at 0 position.
302
     % Making this consistently with resolveshading,
303
     % which applies ReusableStreamDecode filter
304
     % to the PS stream, which represents the
305
     % PDF stream in dynamics.
306
 
307
     dup /Shading knownoget {
308
       dup /ShadingType oget 4 ge {
309
         /DataSource knownoget {
310
           dup type /filetype eq {
311
 
312
           } {
313
             pop
314
           } ifelse
315
         } if
316
       } {
317
        pop
318
       } ifelse
319
     } if
320
 
321
     dup /Matrix knownoget not { matrix } if
322
     gsave DefaultQstate setqstate makepattern grestore setcolor
323
   } bdef
324
end def
325
/setgcolor	% (null | <color...>) <colorspace> setgcolor -
326
 { 1 index null eq
327
    { pop pop }
328
    { dup 0 get //Cdict exch get exec }
329
   ifelse
330
 } bdef
331
% Compare the old and new color spaces in an attempt to avoid expensive
332
% reloads of CIEBased color spaces.
333
/PCSdict 15 dict dup begin	% <colorspace> -proc- <colorspace|pdfcspace>
334
  /CIEBasedA { dup 1 get /PDFColorSpace .knownget { exch pop } if } bdef
335
  /CIEBasedABC /CIEBasedA load def
336
  /CIEBasedDEF /CIEBasedA load def
337
  /CIEBasedDEFG /CIEBasedA load def
338
  /Indexed {
339
    dup 1 get dup pdfcolorspace 2 copy ne { 3 1 roll } if pop pop
340
  } bdef
341
end def
342
/pdfcolorspace {	% <colorspace> pdfcolorspace <colorspace|pdfcspace>
343
  dup type /arraytype eq {
344
    //PCSdict 1 index 0 get .knownget { exec } if
345
  } if
346
} bdef
347
/setgcolorspace {	% <colorspace> setgcolorspace -
348
  dup pdfcolorspace currentcolorspace pdfcolorspace eq {
349
    pop
350
  } {
351
    setcolorspace
352
  } ifelse
353
} bdef
354
/fsexec		% <fillop|strokeop> fsexec -
355
 {		% Preserve the current point, if any.
356
    { currentpoint } stopped
357
    { $error /newerror false put   cvx exec }
358
    { 3 -1 roll cvx exec moveto }
359
   ifelse
360
 } bdef
361
 
362
% ---------------- Path painting and clipping ---------------- %
363
 
364
/S { setstrokestate /stroke fsexec } bdef
365
/f { setfillstate /fill fsexec } bdef
366
/f* { setfillstate /eofill fsexec } bdef
367
/n { newpath } bdef		% don't allow n to get bound in
368
/s { closepath S } bdef
369
/B { gsave setfillstate fill grestore S } bdef
370
/b { closepath B } bdef
371
/B* { gsave setfillstate eofill grestore S } bdef
372
/b* { closepath B* } bdef
373
 
374
% Clipping:
375
 
376
/Wdict 4 dict dup begin
377
/S { gsave setstrokestate stroke grestore n } bdef
378
/f { gsave setfillstate fill grestore n } bdef
379
/f* { gsave setfillstate eofill grestore n } bdef
380
/n { end clip newpath } bdef
381
end readonly def
382
/W { //Wdict begin } bdef
383
/W*dict 4 dict dup begin
384
Wdict { def } forall
385
/n { end eoclip newpath } bdef
386
end readonly def
387
/W* { //W*dict begin } bdef
388
 
389
% ---------------- Text control ---------------- %
390
 
391
/textbeginpage
392
 { /TextSpacing 0 def		% 0 Tc
393
   /TextLeading 0 def		% 0 TL
394
   /TextRenderingMode 0 def	% 0 Tr
395
   /TextRise 0 def		% 0 Ts
396
   /WordSpacing 0 def		% 0 Tw
397
   /TextHScaling 1.0 def	% 100 Tz
398
   /TextFont null def
399
   /Show { showfirst } def
400
 } bdef
401
 
402
% Contrary to the statement in the PDF manual, BT and ET *can* be nested,
403
% if the CharProc for a Type 3 font does a BT/ET itself.
404
% Since we always call the CharProc inside a q/Q, we simply ensure that
405
% the text state is saved and restored like the rest of the extended
406
% graphics state.
407
 
408
/settextmatrix {
409
  TextMatrix concat
410
  TextHScaling 1 ne { TextHScaling 1 scale } if
411
  TextRise 0 ne { 0 TextRise translate } if
412
  TextFont dup null eq { pop } { setfont } ifelse
413
} bdef
414
/settextstate {
415
	% The text state can be set even outside BT/ET.
416
  currentdict /TextSaveMatrix known {
417
    TextSaveMatrix setmatrix settextmatrix
418
  } if
419
} bdef
420
/settextposition {
421
		% Update the TextMatrix translation.
422
  gsave TextSaveMatrix setmatrix
423
  currentpoint TextRise sub TextMatrix 4 2 getinterval astore pop
424
		% We would like to do "grestore currentpoint translate"
425
		% here, but some PDF files set a singular text matrix
426
		% (0 0 0 0 <x> <y> Tm), so we can't do this.
427
  TextTempMatrix identmatrix setmatrix currentpoint
428
  grestore
429
  TextTempMatrix currentmatrix 4 2 getinterval astore pop
430
  TextTempMatrix setmatrix
431
} bdef
432
 
433
/BT {
434
  currentdict /TextLineMatrix .knownget
435
    { identmatrix pop TextMatrix identmatrix pop }
436
    { matrix /TextLineMatrix gput matrix /TextMatrix gput }
437
  ifelse
438
  { showfirst } /Show gput
439
  currentdict /TextSaveMatrix .knownget not {
440
    matrix dup /TextSaveMatrix gput
441
  } if currentmatrix pop settextmatrix
442
  matrix /TextTempMatrix gput		% see settextposition
443
} bdef
444
/ET {
445
  TextRenderingMode 4 ge { clip newpath } if
446
  TextSaveMatrix setmatrix
447
  currentdict /TextSaveMatrix undef
448
} bdef
449
/Tc { /TextSpacing gput { showfirst } /Show gput } bdef
450
/TL { /TextLeading gput } bdef
451
/Tr { dup .settextrenderingmode /TextRenderingMode gput { showfirst } /Show gput } bdef
452
/Ts { /TextRise gput settextstate } bdef
453
/Tw { /WordSpacing gput { showfirst } /Show gput } bdef
454
/Tz { 100 div /TextHScaling gput settextstate} bdef
455
 
456
% ---------------- Font control ---------------- %
457
 
458
/Tf {		% <font> <scale> Tf -
459
  dup 0 eq {
460
    (\n   **** Warning: Invalid 0.0 font scale given for Tf ****\n)
461
    pdfformaterror
462
    pop 0.00000001	% handle invalid scale by using a really small value
463
  } if
464
  dup 1 eq { pop } { scalefont } ifelse
465
  /TextFont gput settextstate
466
} bdef
467
 
468
% Read a CFF font.
469
/FRD		% <resname> <file> FRD -
470
 { /FontSetInit /ProcSet findresource begin //true ReadData
471
 } bdef
472
 
473
% Copy a font, removing its FID.  If changed is true, also remove
474
% the UniqueID and XUID, if any.  If the original dictionary doesn't have
475
% the keys being removed, don't copy it.
476
/.copyfontdict		% <font> <changed> .copyfontdict <dict>
477
 { 1 index /FID known
478
   1 index { 2 index /UniqueID known or 2 index /XUID known or } if
479
    {		% We add 1 to the length just in case the original
480
		% didn't have a FID.
481
      exch dup length 1 add dict exch
482
       {		% Stack: changed newfont key value
483
	 1 index /FID eq 4 index
484
	  { 2 index /UniqueID eq or 2 index /XUID eq or }
485
	 if not { 3 copy put } if pop pop
486
       }
487
      forall exch
488
    }
489
   if pop
490
 } bdef
491
 
492
% Insert a new Encoding or Metrics into a font if necessary.
493
% Return a possibly updated font, and a flag to indicate whether
494
% the font was actually copied.
495
/.updatefontmetrics {	% <font> <Metrics|null> .updatefontmetrics
496
			%   <font'> <copied>
497
  dup //null ne {
498
    exch //true .copyfontdict dup /Metrics 4 -1 roll put //true
499
  } {
500
    pop //false
501
  } ifelse
502
} bdef
503
 
504
/.updatefontencoding {	% <font> <Encoding|null> .updatefontencoding
505
			%   <font'> <copied>
506
  dup //null ne { dup 2 index /Encoding get ne } { //false } ifelse {
507
    exch //false .copyfontdict dup /Encoding 4 -1 roll put //true
508
  } {
509
    pop //false
510
  } ifelse
511
} bdef
512
 
513
% Duplicate keys in CharString dictionary according to GlyphMap: <</new_glyph /old_glyph>>
514
% We have to do this because PDF fonts can associate multiple widths with the same glyph
515
% but Metrics dictionary works by the glyph name.
516
/.update_charstring {	% <font> <GlyphMap> .update_charstring  <font'> <copied>
517
  dup //null ne {
518
    exch //true .copyfontdict       % map font
519
    dup dup /CharStrings get        % map font font cstr
520
    dup length                      % map font font cstr len
521
    4 index length add              % map font font cstr len+map_len
522
    dict copy dup begin             % map font font cstr'
523
    /CharStrings exch put           % map font
524
    exch {                          % font /new /old
525
      currentdict exch .knownget {
526
        def
527
      } {
528
        currentdict /.notdef .knownget {
529
          def
530
        } {
531
          pop
532
          % The font has no .notdef.
533
          % Could not resolve the conflict,
534
          % but either the font is invalid or the glyph name is never used.
535
        } ifelse
536
      } ifelse
537
    } forall
538
    end //true
539
  } {
540
    pop //false
541
  } ifelse
542
} bdef
543
 
544
/.updatefont {	      % <font> <Encoding|null> <Metrics|null> <GlyphMap|null>
545
                      %        .updatefont <font'> <copied>
546
  4 2 roll            % <Metrics|null> <GlyphMap> <font> <Encoding|null>
547
  .updatefontencoding % <Metrics|null> <GlyphMap> <font> bool
548
  4 1 roll exch       % bool <Metrics|null> <font> <GlyphMap>
549
  .update_charstring  % bool <Metrics|null> <font> bool
550
  3 1 roll exch       % bool bool <font> <Metrics|null>
551
  .updatefontmetrics  % bool bool <font> bool
552
  4 2 roll or or      % <font> is_copied
553
} bdef
554
 
555
% ---------------- Text positioning ---------------- %
556
 
557
/Td {
558
  TextLineMatrix transform TextLineMatrix 4 2 getinterval astore pop
559
  TextLineMatrix TextMatrix copy pop settextstate
560
} bdef
561
/TD { dup neg /TextLeading gput Td } bdef
562
/T* { 0 TextLeading neg Td } bdef
563
/Tm {
564
  TextLineMatrix astore TextMatrix copy pop settextstate
565
} bdef
566
 
567
% ---------------- Text painting ---------------- %
568
 
569
/Vexch {
570
  rootfont /WMode knownoget { 1 eq { exch } if } if
571
} bind def
572
 
573
/textrenderingprocs [		% (0 is handled specially)
574
	% Painting-only modes
575
   { tf } { tS } { tB } { tn }
576
	% Clipping modes
577
   { gsave tf grestore tW }
578
   { gsave tS grestore tW }
579
   { gsave tB grestore tW }
580
   { tW }
581
] readonly def
582
/setshowstate
583
 { WordSpacing 0 eq TextSpacing 0 eq and
584
    { TextRenderingMode 0 eq {
585
        { setfillstate show }
586
      } {
587
        TextRenderingMode 3 eq {
588
            	% Some PDF files execute 'tm' with a singular matrix,
589
		% and then use the text rendering mode 3.
590
		% The graphics library currently cannot handle text
591
		% operations when the CTM is singular.
592
		% Work around this here.
593
	  {	
594
            matrix currentmatrix dup
595
            dup 0 get 0 eq 1 index 1 get 0 eq and {
596
              dup dup 2 get 0 eq { 0 }{ 1 } ifelse 1 put
597
            } if
598
            dup 2 get 0 eq 1 index 3 get 0 eq and {
599
              dup dup 1 get 0 eq { 3 }{ 2 } ifelse 1 put
600
            } if
601
            setmatrix
602
            1 index setfillstate show % Tr was set to graphic state.
603
            setmatrix 
604
	    % now set the currentpoint using the original matrix
605
            false charpath currentpoint newpath moveto
606
          }
607
        } {
608
          { false charpath textrenderingprocs TextRenderingMode get exec }
609
        } ifelse
610
      } ifelse
611
    }
612
    { TextRenderingMode 0 eq TextRenderingMode 3 eq or
613
       % Tr was set to graphic state.
614
       { WordSpacing 0 eq
615
          { { setfillstate TextSpacing 0 Vexch 3 -1 roll ashow } }
616
	  { TextSpacing 0 eq
617
            { { setfillstate WordSpacing 0 Vexch 32 4 -1 roll widthshow } }
618
            { { setfillstate WordSpacing 0 Vexch 32
619
                 TextSpacing 0 Vexch 6 -1 roll awidthshow } }
620
	    ifelse
621
	  }
622
	 ifelse
623
       }
624
       { { WordSpacing TextSpacing
625
			% Implement the combination of t3 and false charpath.
626
			% Note that we must use cshow for this, because we
627
			% can't parse multi-byte strings any other way.
628
			% Stack: string xword xchar
629
	    { pop pop (x) dup 0 3 index put false charpath
630
			% Stack: xword xchar ccode
631
             3 copy 32 eq { add } { exch pop } ifelse 0 Vexch rmoveto pop
632
	    }
633
	   4 -1 roll cshow pop pop
634
	   textrenderingprocs TextRenderingMode get exec
635
	 }
636
       }
637
      ifelse
638
    }
639
   ifelse /Show gput
640
 } bdef
641
/showfirst { setshowstate Show } def
642
 
643
/Tj {
644
 
645
} bdef
646
/' { T* Tj } bdef
647
/" { exch Tc exch Tw T* Tj } bdef
648
/TJ {
649
 
650
    dup type /stringtype eq {
651
      Show
652
    } { -1000 div
653
      currentfont /ScaleMatrix .knownget { 0 get mul } if
654
 
655
    } ifelse
656
  } forall settextposition
657
} bdef
658
 
659
/tf { setfillstate currentpoint fill moveto } bdef
660
/tn { currentpoint newpath moveto } bdef % Obsolete, never used.
661
% For stroking characters, temporarily restore the graphics CTM so that
662
% the line width will be transformed properly.
663
/Tmatrix matrix def
664
/tS
665
 { setstrokestate
666
   currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke
667
   setmatrix moveto
668
 } bdef
669
/tB { gsave tf grestore tS } bdef
670
% This does the wrong thing if there have been multiple text operations
671
% within a single BT/ET pair, but it's a start.
672
/tW { } bdef
673
 
674
end readonly put		% GS_PDF_ProcSet
675
 
676
.setglobal