summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlgs/lib/pdf_ops.ps
diff options
context:
space:
mode:
authorReinhard Kotucha <reinhard.kotucha@web.de>2008-02-21 22:07:42 +0000
committerReinhard Kotucha <reinhard.kotucha@web.de>2008-02-21 22:07:42 +0000
commitf90099230db6de68f2285dca3d08174bda872f7a (patch)
tree48fbfd44b5c240a4430dd4a54b286de5f1102583 /Master/tlpkg/tlgs/lib/pdf_ops.ps
parent2deea5f17b0505ffeb480154ace47e0a72863c97 (diff)
tlpkg/tlgs: Subset of Ghostscript added.
git-svn-id: svn://tug.org/texlive/trunk@6709 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/tlpkg/tlgs/lib/pdf_ops.ps')
-rw-r--r--Master/tlpkg/tlgs/lib/pdf_ops.ps727
1 files changed, 727 insertions, 0 deletions
diff --git a/Master/tlpkg/tlgs/lib/pdf_ops.ps b/Master/tlpkg/tlgs/lib/pdf_ops.ps
new file mode 100644
index 00000000000..41ca168b320
--- /dev/null
+++ b/Master/tlpkg/tlgs/lib/pdf_ops.ps
@@ -0,0 +1,727 @@
+% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
+%
+% This software is provided AS-IS with no warranty, either express or
+% implied.
+%
+% This software is distributed under license and may not be copied,
+% modified or distributed except as expressly authorized under the terms
+% of the license contained in the file LICENSE in this distribution.
+%
+% For more information about licensing, please refer to
+% http://www.ghostscript.com/licensing/. For information on
+% commercial licensing, go to http://www.artifex.com/licensing/ or
+% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
+% San Rafael, CA 94903, U.S.A., +1(415)492-9861.
+
+% $Id: pdf_ops.ps 8156 2007-07-31 14:19:45Z alexcher $
+% Definitions for most of the PDF operators.
+
+.currentglobal true .setglobal
+
+% Define pdfmark. Don't allow it to be bound in.
+% Also don't define it in systemdict, because this leads some Adobe code
+% to think this interpreter is a distiller.
+% (If this interpreter really is a distiller, don't do this.)
+systemdict /pdfmark known not
+ { userdict /pdfmark { cleartomark } bind put } if
+
+/renderingintentdict mark
+ /Perceptual 0
+ /RelativeColorimetric 1
+ /Saturation 2
+ /AbsoluteColorimetric 3
+.dicttomark readonly def
+
+userdict /GS_PDF_ProcSet 127 dict dup begin
+
+% ---------------- Abbreviations ---------------- %
+
+/bdef { bind def } bind def
+
+% ---------------- Graphics state stack ---------------- %
+
+% PDF adds a number of parameters to the graphics state.
+% We implement this by pushing and popping a dictionary
+% each time we do a PDF gsave or grestore.
+% The keys in this dictionary are as follows:
+% self % identifies the dictionary as one of ours
+% ClipRect % (optional)
+% Show
+% TextSaveMatrix % matrix at time of BT (iff within BT/ET)
+% (The following correspond directly to PDF state parameters.)
+% AlphaIsShape
+% FillConstantAlpha
+% FillColor
+% FillColorSpace
+% FillOverprint
+% SoftMask
+% StrokeConstantAlpha
+% StrokeColor
+% StrokeColorSpace
+% StrokeOverprint
+% TextSpacing
+% TextHScaling
+% Leading
+% TextFont
+% TextLineMatrix
+% TextMatrix
+% TextRise
+% TextRenderingMode
+% WordSpacing
+
+/nodict 1 dict def
+nodict /self { //nodict } executeonly put
+nodict readonly pop
+
+/dictbeginpage { % <initialdict> dictbeginpage -
+ //nodict 20 dict .copydict begin { def } forall
+ graphicsbeginpage textbeginpage
+} bdef
+/endpage { % - endpage -
+ showpage end
+} bdef
+
+/graphicsbeginpage {
+ initgraphics
+ currentdict /ClipRect knownoget { aload pop rectclip } if
+ 0 g 0 G false op false OP 0 OPM
+ 1 ca 1 CA null SMask false AIS /Compatible BM true TK
+} bdef
+
+/gput % <value> <key> gput -
+ { exch currentdict //nodict eq { /self dup load end 5 dict begin def } if
+ % If we're in a Level 1 system, we need to grow the
+ % dictionary explicitly.
+ currentdict length currentdict maxlength ge %eq
+ { currentdict dup length 3 mul 2 idiv 1 add dict .copydict end begin
+ }
+ if def
+ } bdef
+
+% Restore graphics state, but do not modify path. Paths are not part
+% of the PDF graphics state; see 4.4.1 of PDF reference 3rd ed.
+/grestore_nopath {
+ % Collect the upath with an identity CTM
+ matrix setmatrix .getpath
+ % Save the CTM, set identity during the uappend, then set the CTM
+ grestore matrix currentmatrix matrix setmatrix
+ exch newpath { exec } forall setmatrix
+} bdef
+
+/q {
+ gsave //nodict begin
+} bdef
+% Some PDF files have excess Q operators!
+/Q {
+ currentdict /self .knownget {
+ exec //nodict eq { end grestore_nopath false } { true } ifelse
+ } {
+ true % formaterror -- not a gsave dict
+ } ifelse
+ { (\n **** File has imbalanced q/Q operators \(too many Q's\) ****\n)
+ pdfformaterror
+ } if
+} bdef
+
+% Save PDF gstate
+/qstate { % - qstate <qstate>
+ gstate
+} bdef
+
+% Set PDF gstate
+/setqstate { % <qstate> setqstate -
+ { matrix setmatrix //false upath } stopped {
+ pop setgstate newpath
+ } {
+ % Save the CTM, set identity during the uappend, then set the CTM
+ exch setgstate matrix currentmatrix matrix setmatrix
+ exch newpath uappend setmatrix
+ } ifelse
+} bdef
+
+% ---------------- Color setting ---------------- %
+
+/fcput % <color> <colorspace> fcput -
+ { /FillColorSpace gput /FillColor gput
+ } bdef
+/scput % <color> <colorspace> scput -
+ { /StrokeColorSpace gput /StrokeColor gput
+ } bdef
+/csput % <colorspace> csput -
+ { csset 2 copy fcput scput
+ } bdef
+
+/csdevgray [/DeviceGray] readonly def
+/csdevrgb [/DeviceRGB] readonly def
+/csdevcmyk [/DeviceCMYK] readonly def
+/cspattern [/Pattern] readonly def
+/nullpattern1 mark
+ /PatternType 1 /PaintType 1 /TilingType 3 /BBox [0 0 1 1]
+ /XStep 1 /YStep 1 /PaintProc { pop } bind
+.dicttomark readonly def
+/nullpattern2 nullpattern1 dup length dict copy readonly def
+
+% Each entry in the color space dictionary is a procedure of the form
+% <cspace> -proc- <cspace> <initial-color>
+/CSdict mark
+ /DeviceGray { pop //csdevgray 0 } bind
+ /DeviceRGB { pop //csdevrgb [0 0 0] cvx } bind
+ /DeviceCMYK { pop //csdevcmyk [0 0 0 1] cvx } bind
+ /CIEBasedA { 0 } bind
+ /CIEBasedABC { [0 0 0] cvx } bind
+ /ICCBased { [ 1 index 1 oget /N get { 0 } repeat ] cvx } bind
+ /Separation { 1 } bind
+ /DeviceN { % What is the correct value??
+ [ 1 index 1 get length { 1 } repeat ] cvx
+ } bind
+ /Indexed { 0 } bind
+ /Pattern {
+ dup type /nametype eq 1 index length 1 eq or {
+ pop //cspattern //nullpattern1 matrix makepattern
+ } {
+ //nullpattern2 matrix makepattern 1 index 1 get csset
+ % Stack: patternspace nullpattern basecolor basespace
+ pop [ 3 1 roll dup type /arraytype eq { aload pop } if
+ counttomark -1 roll ] cvx
+ } ifelse
+ } bind
+.dicttomark readonly def
+/csset % <cspace> csset <color> <cspace>
+ { dup dup type /nametype ne { 0 get } if //CSdict exch get exec exch
+ } bdef
+
+/g { //csdevgray fcput } bdef
+/G { //csdevgray scput } bdef
+/rg { 3 array astore cvx //csdevrgb fcput } bdef
+/RG { 3 array astore cvx //csdevrgb scput } bdef
+/k { 4 array astore cvx //csdevcmyk fcput } bdef
+/K { 4 array astore cvx //csdevcmyk scput } bdef
+/cs { csset fcput } bdef
+/CS { csset scput } bdef
+/ri { //renderingintentdict exch .knownget { .setrenderingintent } if } bdef
+% We have to break up sc according to the number of operands.
+/sc1 { /FillColor gput } bdef
+/SC1 { /StrokeColor gput } bdef
+% We have to avoid storing into a color array associated with an outer
+% gsave level, so we do a kind of "copy on write".
+/sc* {
+ currentdict /FillColor .knownget {
+ astore pop
+ } {
+ /FillColor load
+ % FillColor may contain either a single value or an array.
+ dup type /arraytype eq { length }{ pop 1 } ifelse
+ array astore cvx /FillColor gput
+ } ifelse
+} bdef
+/SC* {
+ currentdict /StrokeColor .knownget {
+ astore pop
+ } {
+ /StrokeColor load
+ % StrokeColor may contain either a single value or an array.
+ dup type /arraytype eq { length }{ pop 1 } ifelse
+ array astore cvx /StrokeColor gput
+ } ifelse
+} bdef
+
+% ---------------- Overprint/transparency setting ---------------- %
+
+/op { /FillOverprint gput } bdef
+/OP { /StrokeOverprint gput } bdef
+/OPM {
+ /.setoverprintmode where { pop .setoverprintmode } { pop } ifelse
+} bdef
+/ca { /FillConstantAlpha gput } bdef
+/CA { /StrokeConstantAlpha gput } bdef
+/SMask { /SoftMask gput } bdef
+/AIS { /AlphaIsShape gput } bdef
+/BM {
+ /.setblendmode where {
+ pop [ exch dup type /nametype ne { aload pop } if /Normal ] {
+ { .setblendmode } .internalstopped not { exit } if pop
+ } forall
+ } {
+ pop
+ } ifelse
+} bdef
+/TK {
+ /.settextknockout where { pop .settextknockout } { pop } ifelse
+} bdef
+
+% ---------------- Color installation ---------------- %
+
+% Establish a given color (and color space) as current.
+/.settransparencyparams { % <alpha> <smask> .settransparencyparams -
+ PDFusingtransparency {
+ /.inittransparencymask where {
+ pop AlphaIsShape {
+ 1 .setopacityalpha 0 .inittransparencymask exch .setshapealpha 1
+ } {
+ 1 .setshapealpha 1 .inittransparencymask exch .setopacityalpha 0
+ } ifelse
+ % Set the soft mask by rendering the XObject. Doing this every time
+ % is obviously very inefficient; we'll improve it later.
+ .settransparencymask
+ } {
+ pop pop
+ } ifelse
+ } {
+ pop pop
+ } ifelse
+} bdef
+/.settransparencymask { % <paramdict> <masknum> .settransparencymask -
+ exch dup null eq {
+ PDFusingtransparency {
+ pop .inittransparencymask
+ } {
+ dup /Draw get exec
+ } ifelse
+ } {
+ dup /Draw get exec
+ } ifelse
+} bdef
+% (Non-mask) images must execute setfillblend.
+/setfillblend {
+ FillOverprint setoverprint
+ FillConstantAlpha SoftMask .settransparencyparams
+} def
+/setfillstate {
+ FillColor FillColorSpace setgcolor setfillblend
+} def
+/setstrokestate {
+ StrokeColor StrokeColorSpace setgcolor StrokeOverprint setoverprint
+ StrokeConstantAlpha SoftMask .settransparencyparams
+} def
+/Cdict 15 dict dup begin % <color...> <colorspace> -proc- -
+ /DeviceGray { pop setgray } bdef
+ /DeviceRGB { pop setrgbcolor } bdef
+ /DeviceCMYK { pop setcmykcolor } bdef
+ /CIEBasedA { setgcolorspace setcolor } bdef
+ /CIEBasedABC /CIEBasedA load def
+ /CIEBasedDEF /CIEBasedA load def
+ /CIEBasedDEFG /CIEBasedA load def
+ /ICCBased /CIEBasedA load def
+ /Separation /CIEBasedA load def
+ /DeviceN /CIEBasedA load def
+ /Indexed /CIEBasedA load def
+ /Pattern
+ { setgcolorspace
+
+ % Since multiple patterns may share
+ % same data stream, we need to ensure
+ % that the stream is at 0 position.
+ % Making this consistently with resolveshading,
+ % which applies ReusableStreamDecode filter
+ % to the PS stream, which represents the
+ % PDF stream in dynamics.
+
+ dup /Shading knownoget {
+ dup /ShadingType oget 4 ge {
+ /DataSource knownoget {
+ dup type /filetype eq {
+ 0 setfileposition
+ } {
+ pop
+ } ifelse
+ } if
+ } {
+ pop
+ } ifelse
+ } if
+
+ dup /Matrix knownoget not { matrix } if
+ gsave DefaultQstate setqstate makepattern grestore setcolor
+ } bdef
+end def
+/setgcolor % (null | <color...>) <colorspace> setgcolor -
+ { 1 index null eq
+ { pop pop }
+ { dup 0 get //Cdict exch get exec }
+ ifelse
+ } bdef
+% Compare the old and new color spaces in an attempt to avoid expensive
+% reloads of CIEBased color spaces.
+/PCSdict 15 dict dup begin % <colorspace> -proc- <colorspace|pdfcspace>
+ /CIEBasedA { dup 1 get /PDFColorSpace .knownget { exch pop } if } bdef
+ /CIEBasedABC /CIEBasedA load def
+ /CIEBasedDEF /CIEBasedA load def
+ /CIEBasedDEFG /CIEBasedA load def
+ /Indexed {
+ dup 1 get dup pdfcolorspace 2 copy ne { 3 1 roll } if pop pop
+ } bdef
+end def
+/pdfcolorspace { % <colorspace> pdfcolorspace <colorspace|pdfcspace>
+ dup type /arraytype eq {
+ //PCSdict 1 index 0 get .knownget { exec } if
+ } if
+} bdef
+/setgcolorspace { % <colorspace> setgcolorspace -
+ dup pdfcolorspace currentcolorspace pdfcolorspace eq {
+ pop
+ } {
+ setcolorspace
+ } ifelse
+} bdef
+/fsexec % <fillop|strokeop> fsexec -
+ { % Preserve the current point, if any.
+ { currentpoint } stopped
+ { $error /newerror false put cvx exec }
+ { 3 -1 roll cvx exec moveto }
+ ifelse
+ } bdef
+
+% ---------------- Path painting and clipping ---------------- %
+
+/S { setstrokestate /stroke fsexec } bdef
+/f { setfillstate /fill fsexec } bdef
+/f* { setfillstate /eofill fsexec } bdef
+/n { newpath } bdef % don't allow n to get bound in
+/s { closepath S } bdef
+/B { gsave setfillstate fill grestore S } bdef
+/b { closepath B } bdef
+/B* { gsave setfillstate eofill grestore S } bdef
+/b* { closepath B* } bdef
+
+% Clipping:
+
+/Wdict 4 dict dup begin
+/S { gsave setstrokestate stroke grestore n } bdef
+/f { gsave setfillstate fill grestore n } bdef
+/f* { gsave setfillstate eofill grestore n } bdef
+/n { end clip newpath } bdef
+end readonly def
+/W { //Wdict begin } bdef
+/W*dict 4 dict dup begin
+Wdict { def } forall
+/n { end eoclip newpath } bdef
+end readonly def
+/W* { //W*dict begin } bdef
+
+% ---------------- Text control ---------------- %
+
+/textbeginpage
+ { /TextSpacing 0 def % 0 Tc
+ /TextLeading 0 def % 0 TL
+ /TextRenderingMode 0 def % 0 Tr
+ /TextRise 0 def % 0 Ts
+ /WordSpacing 0 def % 0 Tw
+ /TextHScaling 1.0 def % 100 Tz
+ /TextFont null def
+ /Show { showfirst } def
+ } bdef
+
+% Contrary to the statement in the PDF manual, BT and ET *can* be nested,
+% if the CharProc for a Type 3 font does a BT/ET itself.
+% Since we always call the CharProc inside a q/Q, we simply ensure that
+% the text state is saved and restored like the rest of the extended
+% graphics state.
+
+/settextmatrix {
+ TextMatrix concat
+ TextHScaling 1 ne { TextHScaling 1 scale } if
+ TextRise 0 ne { 0 TextRise translate } if
+ TextFont dup null eq { pop } { setfont } ifelse
+} bdef
+/settextstate {
+ % The text state can be set even outside BT/ET.
+ currentdict /TextSaveMatrix known {
+ TextSaveMatrix setmatrix settextmatrix
+ } if
+} bdef
+/settextposition {
+ % Update the TextMatrix translation.
+ gsave TextSaveMatrix setmatrix
+ currentpoint TextRise sub TextMatrix 4 2 getinterval astore pop
+ % We would like to do "grestore currentpoint translate"
+ % here, but some PDF files set a singular text matrix
+ % (0 0 0 0 <x> <y> Tm), so we can't do this.
+ TextTempMatrix identmatrix setmatrix currentpoint
+ grestore
+ TextTempMatrix currentmatrix 4 2 getinterval astore pop
+ TextTempMatrix setmatrix
+} bdef
+
+/BT {
+ currentdict /TextLineMatrix .knownget
+ { identmatrix pop TextMatrix identmatrix pop }
+ { matrix /TextLineMatrix gput matrix /TextMatrix gput }
+ ifelse
+ { showfirst } /Show gput
+ currentdict /TextSaveMatrix .knownget not {
+ matrix dup /TextSaveMatrix gput
+ } if currentmatrix pop settextmatrix
+ matrix /TextTempMatrix gput % see settextposition
+} bdef
+/ET {
+ TextRenderingMode 4 ge { clip newpath } if
+ TextSaveMatrix setmatrix
+ currentdict /TextSaveMatrix undef
+} bdef
+/Tc { /TextSpacing gput { showfirst } /Show gput } bdef
+/TL { /TextLeading gput } bdef
+/Tr { dup .settextrenderingmode /TextRenderingMode gput { showfirst } /Show gput } bdef
+/Ts { /TextRise gput settextstate } bdef
+/Tw { /WordSpacing gput { showfirst } /Show gput } bdef
+/Tz { 100 div /TextHScaling gput settextstate} bdef
+
+% ---------------- Font control ---------------- %
+
+/Tf { % <font> <scale> Tf -
+ dup 0 eq {
+ (\n **** Warning: Invalid 0.0 font scale given for Tf ****\n)
+ pdfformaterror
+ pop 0.00000001 % handle invalid scale by using a really small value
+ } if
+ 1 index type /dicttype ne {
+ selectfont currentfont
+ } {
+ dup 1 eq { pop } { scalefont } ifelse
+ }
+ ifelse
+ /TextFont gput settextstate
+} bdef
+
+% Read a CFF font.
+/FRD % <resname> <file> FRD -
+ { /FontSetInit /ProcSet findresource begin //true ReadData
+ } bdef
+
+% Copy a font, removing its FID. If changed is true, also remove
+% the UniqueID and XUID, if any. If the original dictionary doesn't have
+% the keys being removed, don't copy it.
+/.copyfontdict % <font> <changed> .copyfontdict <dict>
+ { 1 index /FID known
+ 1 index { 2 index /UniqueID known or 2 index /XUID known or } if
+ { % We add 1 to the length just in case the original
+ % didn't have a FID.
+ exch dup length 1 add dict exch
+ { % Stack: changed newfont key value
+ 1 index /FID eq 4 index
+ { 2 index /UniqueID eq or 2 index /XUID eq or }
+ if not { 3 copy put } if pop pop
+ }
+ forall exch
+ }
+ if pop
+ } bdef
+
+% Insert a new Encoding or Metrics into a font if necessary.
+% Return a possibly updated font, and a flag to indicate whether
+% the font was actually copied.
+/.updatefontmetrics { % <font> <Metrics|null> .updatefontmetrics
+ % <font'> <copied>
+ dup //null ne {
+ exch //true .copyfontdict dup /Metrics 4 -1 roll put //true
+ } {
+ pop //false
+ } ifelse
+} bdef
+
+/.updatefontencoding { % <font> <Encoding|null> .updatefontencoding
+ % <font'> <copied>
+ dup //null ne { dup 2 index /Encoding get ne } { //false } ifelse {
+ exch //false .copyfontdict dup /Encoding 4 -1 roll put //true
+ } {
+ pop //false
+ } ifelse
+} bdef
+
+% Duplicate keys in CharString dictionary according to GlyphMap: <</new_glyph /old_glyph>>
+% We have to do this because PDF fonts can associate multiple widths with the same glyph
+% but Metrics dictionary works by the glyph name.
+/.update_charstring { % <font> <GlyphMap> .update_charstring <font'> <copied>
+ dup //null ne {
+ exch //true .copyfontdict % map font
+ dup dup /CharStrings get % map font font cstr
+ dup length % map font font cstr len
+ 4 index length add % map font font cstr len+map_len
+ dict copy dup begin % map font font cstr'
+ /CharStrings exch put % map font
+ exch { % font /new /old
+ currentdict exch .knownget {
+ def
+ } {
+ currentdict /.notdef .knownget {
+ def
+ } {
+ pop
+ % The font has no .notdef.
+ % Could not resolve the conflict,
+ % but either the font is invalid or the glyph name is never used.
+ } ifelse
+ } ifelse
+ } forall
+ end //true
+ } {
+ pop //false
+ } ifelse
+} bdef
+
+/.updatefont { % <font> <Encoding|null> <Metrics|null> <GlyphMap|null>
+ % .updatefont <font'> <copied>
+ 4 2 roll % <Metrics|null> <GlyphMap> <font> <Encoding|null>
+ .updatefontencoding % <Metrics|null> <GlyphMap> <font> bool
+ 4 1 roll exch % bool <Metrics|null> <font> <GlyphMap>
+ .update_charstring % bool <Metrics|null> <font> bool
+ 3 1 roll exch % bool bool <font> <Metrics|null>
+ .updatefontmetrics % bool bool <font> bool
+ 4 2 roll or or % <font> is_copied
+} bdef
+
+% ---------------- Text positioning ---------------- %
+
+/Td {
+ TextLineMatrix transform TextLineMatrix 4 2 getinterval astore pop
+ TextLineMatrix TextMatrix copy pop settextstate
+} bdef
+/TD { dup neg /TextLeading gput Td } bdef
+/T* { 0 TextLeading neg Td } bdef
+/Tm {
+ TextLineMatrix astore TextMatrix copy pop settextstate
+} bdef
+
+% ---------------- Text painting ---------------- %
+
+/Vexch {
+ rootfont /WMode knownoget { 1 eq { exch } if } if
+} bind def
+
+/textrenderingprocs [ % (0 is handled specially)
+ % Painting-only modes
+ { tf } { tS } { tB } { tn }
+ % Clipping modes
+ { gsave tf grestore tW }
+ { gsave tS grestore tW }
+ { gsave tB grestore tW }
+ { tW }
+] readonly def
+/setshowstate
+ { WordSpacing 0 eq TextSpacing 0 eq and
+ { TextRenderingMode 0 eq currentdevice .devicename /pdfwrite eq or {
+ { setfillstate show }
+ } {
+ TextRenderingMode 3 eq {
+ % Some PDF files execute 'tm' with a singular matrix,
+ % and then use the text rendering mode 3.
+ % The graphics library currently cannot handle text
+ % operations when the CTM is singular.
+ % Work around this here.
+ {
+ matrix currentmatrix dup dup
+ dup 0 get 0 eq 1 index 1 get 0 eq and {
+ dup dup 2 get 0 eq { 0 }{ 1 } ifelse 1 put
+ } if
+ dup 2 get 0 eq 1 index 3 get 0 eq and {
+ dup dup 1 get 0 eq { 3 }{ 2 } ifelse 1 put
+ } if
+ setmatrix
+ 2 index setfillstate show % Tr was set to graphic state.
+ setmatrix
+ % now set the currentpoint using the original matrix
+ gsave nulldevice
+ setmatrix
+ false charpath currentpoint newpath
+ grestore
+ moveto
+ }
+ } {
+ { false charpath textrenderingprocs TextRenderingMode get exec }
+ } ifelse
+ } ifelse
+ }
+ { 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
+ }
+ { { 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
+ }
+ 4 -1 roll cshow pop pop
+ textrenderingprocs TextRenderingMode get exec
+ }
+ }
+ ifelse
+ }
+ ifelse /Show gput
+ } bdef
+/showfirst { setshowstate Show } def
+
+/Tj {
+ 0 0 moveto Show settextposition
+} bdef
+/' { T* Tj } bdef
+/" { exch Tc exch Tw T* Tj } bdef
+/TJ {
+ 0 0 moveto {
+ dup type /stringtype eq {
+ Show
+ } { -1000 div
+ currentfont /ScaleMatrix .knownget { 0 get mul } if
+ 0 Vexch rmoveto
+ } ifelse
+ } forall settextposition
+} bdef
+
+/tf { setfillstate currentpoint fill moveto } bdef
+/tn { currentpoint newpath moveto } bdef % Obsolete, never used.
+% For stroking characters, temporarily restore the graphics CTM so that
+% the line width will be transformed properly.
+/Tmatrix matrix def
+/tS
+ { setstrokestate
+ currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke
+ setmatrix moveto
+ } bdef
+/tB { gsave tf grestore tS } bdef
+% This does the wrong thing if there have been multiple text operations
+% within a single BT/ET pair, but it's a start.
+/tW { } bdef
+
+% Text formatting and painting for the AcroForm field without appearance streams.
+/Tform { % <MaxLen> (V) <Ff> <Q> Tform -
+ clippath pathbbox 4 2 roll pop pop % MaxLen (V) Ff Q dx dy
+ currentfont /ScaleMatrix .knownget { 3 get } { 1 } ifelse % MaxLen (V) Ff Q dx dy yy
+ currentfont /FontBBox get dup 1 get neg exch 3 get % MaxLen (V) Ff Q dx dy yy desc asc
+ dup 0 ne { div } { pop pop 0 } ifelse % MaxLen (V) Ff Q dx dy yy desc/asc
+ 1 index mul % MaxLen (V) Ff Q dx dy yy desc/asc*yy
+
+ 4 index 16#1000 and 0 ne { % multiline
+ 8 { pop } repeat (Multiline form fields are not yet implemented.) =
+ } {
+ 4 index 16#1000000 and 0 ne { % comb
+ 8 { pop } repeat (Combed form fields are not yet implemented.) =
+ } { % plain text
+ 3 1 roll sub add 2 div % MaxLen (V) Ff Q dx (dy-yy+desc)/2
+ 0 exch moveto % MaxLen (V) Ff Q dx
+ 1 index 0 ne {
+ 3 index stringwidth pop % MaxLen (V) Ff Q dx w
+ sub exch 1 eq { 2 div } { 2 sub } ifelse % MaxLen (V) Ff (dx-w)/2
+ 0 rmoveto % MaxLen (V) Ff
+ pop % MaxLen (V)
+ } {
+ pop pop pop % MaxLen (V)
+ 2 0 rmoveto
+ } ifelse
+ exch pop Show % -
+ } ifelse
+ } ifelse
+} bdef
+
+end readonly put % GS_PDF_ProcSet
+
+.setglobal