% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.% % This file is part of Aladdin Ghostscript.% % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author% or distributor accepts any responsibility for the consequences of using it,% or for whether it serves any particular purpose or works at all, unless he% or she says so in writing. Refer to the Aladdin Ghostscript Free Public% License (the "License") for full details.% % Every copy of Aladdin Ghostscript must include a copy of the License,% normally in a plain ASCII text file named PUBLIC. The License grants you% the right to copy, modify and redistribute Aladdin Ghostscript, but only% under certain conditions described in the License. Among other things, the% License requires that the copyright notice and this notice be preserved on% all copies.% $Id: pdf_ops.ps,v 1.2 2000/03/10 03:57:03 lpd Exp $% 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 } ifuserdict /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% Show% TextSaveMatrix % matrix at time of BT% (The following correspond directly to PDF state parameters.)% FillColor% FillColorSpace% StrokeColor% StrokeColorSpace% TextSpacing% TextHScaling% Leading% TextFont% TextLineMatrix% TextMatrix% TextRise% TextRenderingMode% WordSpacing/nodict 1 dict defnodict /self { //nodict } executeonly putnodict readonly pop/beginpage { //nodict 20 dict .copydict begin graphicsbeginpage textbeginpage } bdef/endpage { showpage end } bdef/graphicsbeginpage { initgraphics 0 g 0 G } 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/q { gsave //nodict begin} bdef% Some PDF files have excess Q operators!/Q { currentdict /self .knownget { exec //nodict eq { end grestore } if } if} bdef% ---------------- Color setting ---------------- %/fcput % <color> <colorspace> fcput - { /FillColorSpace gput /FillColor gput } bdef/scput % <color> <colorspace> scput - { /StrokeColorSpace gput /StrokeColor gput } 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 0 0] /XStep 1 /YStep 1 /PaintProc { }.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 /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 { pop } bdef% We have to break up sc according to the number of operands./sc1 { /FillColor gput } bdef/SC1 { /StrokeColor gput } bdef/sc* { /FillColor load astore pop } bdef/SC* { /StrokeColor load astore pop } bdef% ---------------- Color installation ---------------- %% Establish a given color (and color space) as current./setfillcolor { FillColor FillColorSpace setgcolor } def/setstrokecolor { StrokeColor StrokeColorSpace setgcolor } def/Cdict 15 dict dup begin % <color...> <colorspace> -proc- - /DeviceGray { pop setgray } bdef /DeviceRGB { pop setrgbcolor } bdef /DeviceCMYK { pop setcmykcolor } bdef /CIEBasedA { dup currentcolorspace eq { pop } { setcolorspace } ifelse setcolor } bdef /CIEBasedABC /CIEBasedA load def /CIEBasedDEF /CIEBasedA load def /CIEBasedDEFG /CIEBasedA load def /Separation /CIEBasedA load def /DeviceN /CIEBasedA load def /Indexed /CIEBasedA load def /Pattern { dup currentcolorspace eq { pop } { setcolorspace } ifelse dup /Matrix .knownget not { matrix } if makepattern setcolor } bdefend def/setgcolor % (null | <color...>) <colorspace> setgcolor - { 1 index null eq { pop pop } { dup 0 get //Cdict exch get exec } 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 { setstrokecolor /stroke fsexec } bdef/f { setfillcolor /fill fsexec } bdef/f* { setfillcolor /eofill fsexec } bdef/n { newpath } bdef % don't allow n to get bound in/s { closepath S } bdef/B { gsave setfillcolor fill grestore S } bdef/b { closepath B } bdef/B* { gsave setfillcolor eofill grestore S } bdef/b* { closepath B* } bdef% Clipping:/Wdict 4 dict dup begin/S { gsave setstrokecolor stroke grestore n } bdef/f { gsave setfillcolor fill grestore n } bdef/f* { gsave setfillcolor eofill grestore n } bdef/n { end clip newpath } bdefend readonly def/W { //Wdict begin } bdef/W*dict 4 dict dup beginWdict { def } forall/n { end eoclip newpath } bdefend 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 { TextSaveMatrix setmatrix settextmatrix} bdef/settextposition { % Update the TextMatrix translation. gsave TextSaveMatrix setmatrix currentpoint TextMatrix 4 2 getinterval astore pop grestore currentpoint translate} 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} bdef/ET { TextSaveMatrix setmatrix} bdef/Tc { /TextSpacing gput { showfirst } /Show gput } bdef/TL { /TextLeading gput } bdef/Tr { /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 1 eq { pop } { scalefont } ifelse /TextFont gput settextstate} bdef% Read a CFF font./FRD % <resdict> <file> FRD - { /FontSetInit /ProcSet findresource begin 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/.updatefont { % <font> <Encoding|null> <Metrics|null> .updatefont % <font'> <copied> 3 -1 roll exch .updatefontmetrics % Stack: enc|null font' copied 3 1 roll exch .updatefontencoding 3 -1 roll or} 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 ---------------- %/textrenderingprocs [ % (0 is handled specially) { tf } { tS } { tB } { tn } % We don't know what the clipping modes mean.... 4 copy] readonly def/setshowstate { WordSpacing 0 eq TextSpacing 0 eq and { TextRenderingMode 0 eq { { setfillcolor show } } { { false charpath textrenderingprocs TextRenderingMode get exec } } ifelse } { TextRenderingMode 0 eq { WordSpacing 0 eq { { setfillcolor TextSpacing exch 0 exch ashow } } { TextSpacing 0 eq { { setfillcolor WordSpacing exch 0 exch 32 exch widthshow } } { { setfillcolor WordSpacing exch TextSpacing exch 0 32 4 2 roll 0 exch 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 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 rmoveto } ifelse } forall settextposition} bdef/tf { setfillcolor currentpoint fill moveto } bdef/tn { currentpoint newpath moveto } bdef% For stroking characters, temporarily restore the graphics CTM so that% the line width will be transformed properly./Tmatrix matrix def/tS { setstrokecolor currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke setmatrix moveto } bdef/tB { gsave tf grestore tS } bdefend readonly put % GS_PDF_ProcSet.setglobal
% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved.
%
% This file is part of Aladdin Ghostscript.
%
% Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
% or distributor accepts any responsibility for the consequences of using it,
% or for whether it serves any particular purpose or works at all, unless he
% or she says so in writing. Refer to the Aladdin Ghostscript Free Public
% License (the "License") for full details.
%
% Every copy of Aladdin Ghostscript must include a copy of the License,
% normally in a plain ASCII text file named PUBLIC. The License grants you
% the right to copy, modify and redistribute Aladdin Ghostscript, but only
% under certain conditions described in the License. Among other things, the
% License requires that the copyright notice and this notice be preserved on
% all copies.
% $Id: pdf_ops.ps,v 1.2 2000/03/10 03:57:03 lpd Exp $
% 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
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
% Show
% TextSaveMatrix % matrix at time of BT
% (The following correspond directly to PDF state parameters.)
% FillColor
% FillColorSpace
% StrokeColor
% StrokeColorSpace
% TextSpacing
% TextHScaling
% Leading
% TextFont
% TextLineMatrix
% TextMatrix
% TextRise
% TextRenderingMode
% WordSpacing
/nodict 1 dict def
nodict /self { //nodict } executeonly put
nodict readonly pop
/beginpage
{ //nodict 20 dict .copydict begin graphicsbeginpage textbeginpage
} bdef
/endpage
{ showpage end
} bdef
/graphicsbeginpage { initgraphics 0 g 0 G } 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
/q {
gsave //nodict begin
} bdef
% Some PDF files have excess Q operators!
/Q {
currentdict /self .knownget { exec //nodict eq { end grestore } if } if
} bdef
% ---------------- Color setting ---------------- %
/fcput % <color> <colorspace> fcput -
{ /FillColorSpace gput /FillColor gput
} bdef
/scput % <color> <colorspace> scput -
{ /StrokeColorSpace gput /StrokeColor gput
} 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 0 0]
/XStep 1 /YStep 1 /PaintProc { }
.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
/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 { pop } bdef
% We have to break up sc according to the number of operands.
/sc1 { /FillColor gput } bdef
/SC1 { /StrokeColor gput } bdef
/sc* { /FillColor load astore pop } bdef
/SC* { /StrokeColor load astore pop } bdef
% ---------------- Color installation ---------------- %
% Establish a given color (and color space) as current.
/setfillcolor { FillColor FillColorSpace setgcolor } def
/setstrokecolor { StrokeColor StrokeColorSpace setgcolor } def
/Cdict 15 dict dup begin % <color...> <colorspace> -proc- -
/DeviceGray { pop setgray } bdef
/DeviceRGB { pop setrgbcolor } bdef
/DeviceCMYK { pop setcmykcolor } bdef
/CIEBasedA
{ dup currentcolorspace eq { pop } { setcolorspace } ifelse setcolor } bdef
/CIEBasedABC /CIEBasedA load def
/CIEBasedDEF /CIEBasedA load def
/CIEBasedDEFG /CIEBasedA load def
/Separation /CIEBasedA load def
/DeviceN /CIEBasedA load def
/Indexed /CIEBasedA load def
/Pattern
{ dup currentcolorspace eq { pop } { setcolorspace } ifelse
dup /Matrix .knownget not { matrix } if makepattern setcolor
} bdef
end def
/setgcolor % (null | <color...>) <colorspace> setgcolor -
{ 1 index null eq
{ pop pop }
{ dup 0 get //Cdict exch get exec }
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 { setstrokecolor /stroke fsexec } bdef
/f { setfillcolor /fill fsexec } bdef
/f* { setfillcolor /eofill fsexec } bdef
/n { newpath } bdef % don't allow n to get bound in
/s { closepath S } bdef
/B { gsave setfillcolor fill grestore S } bdef
/b { closepath B } bdef
/B* { gsave setfillcolor eofill grestore S } bdef
/b* { closepath B* } bdef
% Clipping:
/Wdict 4 dict dup begin
/S { gsave setstrokecolor stroke grestore n } bdef
/f { gsave setfillcolor fill grestore n } bdef
/f* { gsave setfillcolor 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 {
TextSaveMatrix setmatrix settextmatrix
} bdef
/settextposition {
% Update the TextMatrix translation.
gsave TextSaveMatrix setmatrix
currentpoint TextMatrix 4 2 getinterval astore pop
grestore currentpoint translate
} 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
} bdef
/ET {
TextSaveMatrix setmatrix
} bdef
/Tc { /TextSpacing gput { showfirst } /Show gput } bdef
/TL { /TextLeading gput } bdef
/Tr { /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 1 eq { pop } { scalefont } ifelse
/TextFont gput settextstate
} bdef
% Read a CFF font.
/FRD % <resdict> <file> FRD -
{ /FontSetInit /ProcSet findresource begin 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
/.updatefont { % <font> <Encoding|null> <Metrics|null> .updatefont
% <font'> <copied>
3 -1 roll exch .updatefontmetrics
% Stack: enc|null font' copied
3 1 roll exch .updatefontencoding 3 -1 roll or
} 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 ---------------- %
/textrenderingprocs [ % (0 is handled specially)
{ tf } { tS } { tB } { tn }
% We don't know what the clipping modes mean....
4 copy
] readonly def
/setshowstate
{ WordSpacing 0 eq TextSpacing 0 eq and
{ TextRenderingMode 0 eq
{ { setfillcolor show } }
{ { false charpath textrenderingprocs TextRenderingMode get exec } }
ifelse
}
{ TextRenderingMode 0 eq
{ WordSpacing 0 eq
{ { setfillcolor TextSpacing exch 0 exch ashow } }
{ TextSpacing 0 eq
{ { setfillcolor WordSpacing exch 0 exch 32 exch widthshow } }
{ { setfillcolor WordSpacing exch TextSpacing exch 0 32 4 2 roll 0 exch 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 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 rmoveto
} ifelse
} forall settextposition
} bdef
/tf { setfillcolor currentpoint fill moveto } bdef
/tn { currentpoint newpath moveto } bdef
% For stroking characters, temporarily restore the graphics CTM so that
% the line width will be transformed properly.
/Tmatrix matrix def
/tS
{ setstrokecolor
currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke
setmatrix moveto
} bdef
/tB { gsave tf grestore tS } bdef
end readonly put % GS_PDF_ProcSet
.setglobal