home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / Vyzkuste / gs / gs650w32.exe / gs6.50 / lib / pdf_draw.ps < prev    next >
Text File  |  2000-12-05  |  33KB  |  1,110 lines

  1. %    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of AFPL Ghostscript.
  3. % AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  4. % distributor accepts any responsibility for the consequences of using it, or
  5. % for whether it serves any particular purpose or works at all, unless he or
  6. % she says so in writing.  Refer to the Aladdin Free Public License (the
  7. % "License") for full details.
  8. % Every copy of AFPL Ghostscript must include a copy of the License, normally
  9. % in a plain ASCII text file named PUBLIC.  The License grants you the right
  10. % to copy, modify and redistribute AFPL Ghostscript, but only under certain
  11. % conditions described in the License.  Among other things, the License
  12. % requires that the copyright notice and this notice be preserved on all
  13. % copies.
  14.  
  15. % $Id: pdf_draw.ps,v 1.22.2.1 2000/10/26 13:04:54 igorm Exp $
  16. % pdf_draw.ps
  17. % PDF drawing operations (graphics, text, and images).
  18.  
  19. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  20. .currentglobal true .setglobal
  21. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  22. GS_PDF_ProcSet begin
  23. pdfdict begin
  24.  
  25. % For simplicity, we use a single interpretation dictionary for all
  26. % PDF graphics operations, even though this is too liberal.
  27. /drawopdict 100 dict def
  28.  
  29. % ================================ Graphics ================================ %
  30.  
  31. % ---------------- Functions ---------------- %
  32.  
  33. % Note that resolvefunction converts a PDF Function to a PostScript Function;
  34. % resolve*fnproc converts a PDF function to a PostScript procedure.
  35.  
  36. /fnrdict mark
  37.   0 { .resolvefn0 }
  38.   2 { }
  39.   3 { .resolvefn3 }
  40.   4 { .resolvefn4 }
  41. .dicttomark readonly def
  42.  
  43. /.resolvefn0 {
  44.         % Don't lose our place in PDFfile.
  45.   PDFfile fileposition exch
  46.   dup true resolvestream
  47.         % The stream isn't positionable, so read all the data now.
  48.         % Stack: filepos fndict stream
  49.   1 index /Range oget length 2 idiv 2 index /BitsPerSample oget mul
  50.   2 index /Size oget { mul } forall
  51.   7 add 8 idiv string
  52.   1 index exch readstring pop exch closefile
  53.         % Stack: filepos fndict data
  54.   exch dup length 1 add dict .copydict
  55.   dup /DataSource 4 -1 roll put
  56.   exch PDFfile exch setfileposition
  57. } bdef
  58.  
  59. /.resolvefn3 {
  60.   dup length dict .copydict
  61.   dup /Bounds 2 copy knownoget { put } { pop pop } ifelse
  62.   dup /Encode 2 copy knownoget { put } { pop pop } ifelse
  63.   dup /Functions 2 copy oget mark exch dup {
  64.     oforce .resolvefn
  65.   } forall
  66.   counttomark -1 roll astore exch pop put
  67. } bdef
  68.  
  69. /.resolvefn4 {
  70.   PDFfile fileposition exch
  71.   dup true resolvestream 
  72.         % Stack: filepos fndict stream
  73.   1 index /Length oget string readstring pop
  74.   exch dup length dict copy dup /Function undef
  75.   exch token not {
  76.     () /rangecheck cvx signalerror
  77.   } if
  78.   exch token {
  79.     /rangecheck cvx signalerror
  80.   } if
  81.         % Use .bind to avoid idiom recognition.
  82.   .bind
  83.   1 index /Function 3 -1 roll put
  84.   exch PDFfile exch setfileposition
  85. } bdef
  86. currentdict /tfopdict undef
  87.  
  88. /.resolvefn {        % <fndict> .resolvefn <fndict'>
  89.   dup /FunctionType oget //fnrdict exch get exec
  90. } bdef
  91.  
  92. /resolvefunction {    % <fndict> resolvefunction <function>
  93.   .resolvefn
  94.   DEBUG { (%Function: ) print dup === flush } if
  95. } bdef
  96.  
  97. /resolvefnproc {    % <fndict> resolvefnproc <proc>
  98.   resolvefunction .buildfunction
  99. } bdef
  100.  
  101. /resolveidfnproc {    % <fndict> resolveidfnproc <proc>
  102.   dup /Identity eq { pop { } } { resolvefnproc } ifelse
  103. } bdef
  104.  
  105. /resolvedefaultfnproc {    % <fndict> <default> resolved'fnproc <proc>
  106.   1 index /Default eq { exch pop } { pop resolveidfnproc } ifelse
  107. } bdef
  108.  
  109. % ---------------- Shadings ---------------- %
  110.  
  111. /shrdict mark
  112.   /ColorSpace {
  113.     resolvecolorspace
  114.   }
  115.   /Function {
  116.     dup type /dicttype eq {
  117.       resolvefunction
  118.     } {
  119.       [ exch { resolvefunction } forall ]
  120.     } ifelse
  121.   }
  122. .dicttomark readonly def
  123.  
  124. /resolveshading {    % <shadingstream> resolveshading <shading>
  125.   PDFfile fileposition exch
  126.   mark exch {
  127.     oforce //shrdict 2 index .knownget { exec } if
  128.   } forall .dicttomark
  129.   dup /ShadingType get 4 ge {
  130.     dup dup true resolvestream
  131.         % Make a reusable stream so that the shading doesn't
  132.         % reposition PDFfile at unexpected times.
  133.     /ReusableStreamDecode filter /DataSource exch put
  134.   } if exch PDFfile exch setfileposition
  135. } bdef
  136. /resolvesh {        % <shname> resolveshading <shading>
  137.   Page /Shading rget {
  138.     resolveshading
  139.   } {
  140.     null
  141.   }ifelse
  142. } bdef
  143.  
  144. % ---------------- Halftones ---------------- %
  145.  
  146. /spotfunctions mark
  147.   /Round {
  148.     abs exch abs 2 copy add 1 le {
  149.       dup mul exch dup mul add 1 exch sub 
  150.     } {
  151.       1 sub dup mul exch 1 sub dup mul add 1 sub
  152.     } ifelse
  153.   }
  154.   /Diamond {
  155.     abs exch abs 2 copy add .75 le {
  156.       dup mul exch dup mul add 1 exch sub
  157.     } {
  158.       2 copy add 1.23 le {
  159.     .85 mul add 1 exch sub
  160.       } {
  161.     1 sub dup mul exch 1 sub dup mul add 1 sub
  162.       } ifelse
  163.     } ifelse
  164.   }
  165.   /Ellipse {
  166.     abs exch abs 2 copy 3 mul exch 4 mul add 3 sub dup 0 lt {
  167.       pop dup mul exch .75 div dup mul add 4 div 1 exch sub
  168.     } {
  169.       dup 1 gt {
  170.     pop 1 exch sub dup mul exch 1 exch sub
  171.     .75 div dup mul add 4 div 1 sub
  172.       } {
  173.     .5 exch sub exch pop exch pop
  174.       } ifelse
  175.     } ifelse
  176.   }
  177.   /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub }
  178.   /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub }
  179.   /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub }
  180.   /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub }
  181.   /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub }
  182.   /Line { exch pop abs neg }
  183.   /LineX { pop }
  184.   /LineY { exch pop }
  185.   /Square { abs exch abs 2 copy lt { exch } if pop neg }
  186.   /Cross { abs exch abs 2 copy gt { exch } if pop neg }
  187.   /Rhomboid { abs exch abs 0.9 mul add 2 div }
  188.   /DoubleDot { 2 {360 mul sin 2 div exch } repeat add }
  189.   /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg }
  190.   /SimpleDot { dup mul exch dup mul add 1 exch sub }
  191.   /InvertedSimpleDot { dup mul exch dup mul add 1 sub }
  192.   /CosineDot { 180 mul cos exch 180 mul cos add 2 div }
  193.   /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add }
  194.   /InvertedDouble {
  195.     exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
  196.   }
  197. .dicttomark readonly def
  198.  
  199. /htrdict mark
  200.   1 { .resolveht1 }
  201.   5 { .resolveht5 }
  202.     % We don't support types 6, 10, or 16 yet.
  203. .dicttomark readonly def
  204.  
  205. /.resolveht1 {
  206.   mark exch {
  207.     oforce
  208.     1 index /SpotFunction eq {
  209.       dup type /nametype eq
  210.     { //spotfunctions exch get } { resolvefnproc }
  211.       ifelse
  212.     } {
  213.       1 index /TransferFunction eq {
  214.     resolveidfnproc
  215.       } if
  216.     } ifelse
  217.   } forall .dicttomark
  218. } bdef
  219.  
  220. /.resolveht5 {
  221.   mark exch {
  222.     oforce dup type /dicttype eq { resolvehalftone } if
  223.   } forall .dicttomark
  224. } bdef
  225.  
  226. /resolvehalftone {    % <dict> resolvehalftone <halftone>
  227.   dup /HalftoneType get //htrdict exch get exec
  228. } bdef
  229.  
  230. % ---------------- Graphics state management ---------------- %
  231.  
  232. /cmmatrix matrix def
  233. drawopdict begin
  234.             % Graphics state stack
  235.   /q { q } def
  236.   /Q { Q } def
  237.             % Graphics state setting
  238.   /cm { //cmmatrix astore concat } def
  239.   /i /setflat load def
  240.   /J /setlinecap load def
  241.   /d /setdash load def
  242.   /j /setlinejoin load def
  243.   /w /setlinewidth load def
  244.   /M /setmiterlimit load def
  245.   /gs { gs } def
  246. end
  247.  
  248. % Each entry in this dictionary is
  249. %    <gsres> <value> -proc- <gsres>
  250. /gsbg {
  251.   /BGDefault load resolvedefaultfnproc setblackgeneration
  252. } bdef
  253. /gsucr {
  254.   /UCRDefault load resolvedefaultfnproc setundercolorremoval
  255. } bdef
  256. /gstr {
  257.   dup type /arraytype eq {
  258.     { oforce /TRDefault load resolvedefaultfnproc } forall
  259.     setcolortransfer
  260.   } {
  261.     /TRDefault load resolvedefaultfnproc settransfer
  262.   } ifelse
  263. } bdef
  264. /gsparamdict mark
  265.   /SA { setstrokeadjust }
  266.   /OP { 1 index /op known not { dup op } if OP }
  267.     % The PDF 1.3 specification says that the name /Default is only
  268.     % recognized for {BG,UCR,TR}2.  However, PDF 1.3 files produced
  269.     % by Adobe Acrobat Distiller 4.0 for Windows use the name /Default
  270.     % with the older keys, so we have to implement this.
  271.   /BG { 1 index /BG2 known { pop } { gsbg } ifelse }
  272.   /UCR { 1 index /UCR2 known { pop } { gsucr } ifelse }
  273.   /TR { 1 index /TR2 known { pop } { gstr } ifelse }
  274.   /HT {
  275.     dup /Default eq {
  276.       pop .setdefaultscreen
  277.     } {
  278.     %****** DOESN'T IMPLEMENT THE STREAM CASE YET ******
  279.       resolvehalftone sethalftone
  280.     } ifelse
  281.   }
  282.   /HTP {
  283.     % HTP may be present even if this isn't a DPS interpreter.
  284.     /sethalftonephase where { pop aload pop sethalftonephase } { pop } ifelse
  285.   }
  286.     % PDF 1.3
  287.   /Font { aload pop Tf }
  288.   /LW { setlinewidth }
  289.   /LC { setlinecap }
  290.   /LJ { setlinejoin }
  291.   /ML { setmiterlimit }
  292.   /D { aload pop setdash }
  293.   /RI { ri }
  294.   /op { op }
  295.   /OPM { OPM }
  296.   /BG2 { gsbg }
  297.   /UCR2 { gsucr }
  298.   /TR2 { gstr }
  299.   /FL { setflat }
  300.   /SM {
  301.     % SM may be present even if this is only a Level 2 interpreter.
  302.     /setsmoothness where { pop setsmoothness } { pop } ifelse
  303.   }
  304.     % PDF 1.4
  305.     % All of these require the "transparency" feature in the interpreter.
  306.   /ca { ca }
  307.   /CA { CA }
  308.   /SMask { gssmask }
  309.   /AIS { AIS }
  310.   /BM { BM }
  311.   /TK { TK }
  312. .dicttomark readonly def
  313. /gs {            % <gsres> gs -
  314.   Page /ExtGState rget {
  315.     % We keep the dictionary on the stack during the forall so that
  316.     % keys that interact with each other have access to it.
  317.     dup {
  318.       oforce exch gsparamdict exch .knownget { exec } { pop } ifelse
  319.     } forall pop
  320.   } if
  321. } bdef
  322.  
  323. % ------ Transparency support ------ %
  324.  
  325. /gssmask {
  326.   dup /None eq {
  327.     null
  328.   } {
  329.     % Preprocess the SMask value into a parameter dictionary for
  330.     % .begintransparencymask, with added /BBox and /Draw keys.
  331.     mark exch        % Stack: mark smaskdict
  332.     dup /S oget /Subtype exch 3 2 roll
  333.             % Stack: mark ... smaskdict
  334.     dup /BC knownoget { /Background exch 3 2 roll } if
  335.     dup /TR knownoget {
  336.       resolveidfnproc /TransferFunction exch 3 2 roll
  337.     } if    
  338.     dup /G oget dup /BBox oget /BBox exch 4 2 roll
  339.     /.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll
  340.     pop .dicttomark
  341.   } ifelse SMask
  342. } bdef
  343.  
  344. % This procedure is called to actually render the soft mask.
  345. /.execmaskgroup {    % <masknum> <paramdict> <formdict> .execmaskgroup -
  346.     % Save our place in PDFfile, and do a gsave to avoid resetting
  347.     % the color space.
  348.   gsave PDFfile fileposition 4 1 roll
  349.     % We have to select the group's color space so that the
  350.     % background color will be interpreted correctly.
  351.   dup /Group oget /CS knownoget { csresolve setcolorspace } if
  352.   exch dup /BBox get aload pop .begintransparencymask {
  353.     dup /Resources knownoget { oforce } { 0 dict } ifelse
  354.     exch false resolvestream
  355.     .execgroup .endtransparencymask
  356.   } .internalstopped {
  357.     .discardtransparencymask stop
  358.   } if
  359.   PDFfile exch setfileposition grestore
  360. } bdef
  361. % Paint a Form+Group XObject, either for a transparency mask or for a Do.
  362. /.execgroup {        % <resdict> <stream> .execgroup -
  363.   gsave
  364.   1 .setopacityalpha 1 .setshapealpha
  365.   0 .inittransparencymask 1 .inittransparencymask
  366.   /Compatible .setblendmode
  367.     % Execute the body of the Form, similar to DoForm.
  368.   pdfopdict .pdfruncontext
  369.   grestore
  370. } bdef
  371.  
  372. % .paintgroupform implements the Form PaintProc in the case where the
  373. % Form XObject dictionary includes a Group key.  See .paintform below.
  374. /.paintgroupform {    % <resdict> <stream> <formdict> .paintform -
  375.   mark exch dup /Group oget
  376.   dup /CS knownoget { csresolve setcolorspace } if
  377.   dup /I knownoget { /Isolated exch 4 2 roll } if
  378.   dup /K knownoget { /Knockout exch 4 2 roll } if
  379.   pop counttomark 1 add 1 roll .dicttomark
  380.         % Stack: resdict stream formdict paramdict
  381.   exch /BBox oget aload pop
  382.   .begintransparencygroup {
  383.     .execgroup
  384.   } .internalstopped {
  385.     .discardtransparencygroup stop
  386.   } if .endtransparencygroup
  387. } bdef
  388.  
  389. % Make an ImageType 103 (soft-masked) image.
  390. /makesoftmaskimage {    % <datasource> <imagemask> <SMask> makesoftmaskimage
  391.             %   <datasource> <imagemask>, updates currentdict =
  392.             %   imagedict
  393.         % See the ImageType 3 case of makemaskimage below.
  394.         % SMask is a stream, another Image XObject.
  395.         % Stack: datasource imagemask(false) smaskstreamdict
  396.   PDFfile fileposition exch
  397.   dup /Matte knownoget { /Matte exch def } if
  398.   dup length dict makeimagedict pop
  399.         % In order to prevent the two data sources from being
  400.         % aliased, we need to make at least one a reusable stream.
  401.         % We pick the mask, since it's smaller (in case we need to
  402.         % read all its data now).
  403.         % Stack: datasource imagemask(false) savedpos
  404.         % maskdict is currentdict
  405.   /DataSource DataSource mark
  406.     /Intent 1
  407.     /AsyncRead true
  408.   .dicttomark .reusablestreamdecode def
  409.   PDFfile exch setfileposition
  410.   currentdict end currentdict end
  411.   5 dict begin
  412.   /ImageType 103 def
  413.   /DataDict exch def
  414.   dup /InterleaveType 3 put
  415.   DataDict /Matte .knownget {
  416.     /Matte exch def
  417.   } if
  418.   AlphaIsShape { /ShapeMaskDict } { /OpacityMaskDict } ifelse exch def
  419.   /ColorSpace DataDict /ColorSpace get def
  420. } bdef
  421.  
  422. % ---------------- Color setting ---------------- %
  423.  
  424. /01_1 [0 1] readonly def
  425. /01_3 [0 1 0 1 0 1] readonly def
  426. /01_4 [0 1 0 1 0 1 0 1] readonly def
  427.  
  428. % The keys here are resolved (PostScript, not PDF) color space names.
  429. /csncompdict mark
  430.   /DeviceGray { pop 1 }
  431.   /DeviceRGB { pop 3 }
  432.   /DeviceCMYK { pop 4 }
  433.   /CIEBasedA { pop 1 }
  434.   /CIEBasedABC { pop 3 }
  435.   /Separation { pop 1 }
  436.   /DeviceN { 2 oget length }
  437. .dicttomark readonly def
  438.  
  439. % Perhaps some of the values in the following need to be modified
  440. % depending on the WhitePoint value....
  441. /cslabinit mark
  442.   /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]
  443.   /MatrixABC [1 1 1 1 0 0 0 0 -1]
  444.   /DecodeLMN [
  445.     {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse
  446.      0.9505 mul} bind
  447.     {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse
  448.      } bind
  449.     {dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse
  450.      1.0890 mul} bind
  451.   ]
  452. .dicttomark readonly def
  453.  
  454. /csrdict mark
  455.   /DeviceGray {
  456.     /DefaultGray Page /ColorSpace rget { exch pop resolvecolorspace } if
  457.   }
  458.   /DeviceRGB {
  459.     /DefaultRGB Page /ColorSpace rget { exch pop resolvecolorspace } if
  460.   }
  461.   /DeviceCMYK { }
  462.   /CalGray {
  463.     1 oget 6 dict begin
  464.     dup /Gamma knownoget {
  465.       /exp load 2 packedarray cvx /DecodeA exch def
  466.     } if
  467.     dup /BlackPoint knownoget { /BlackPoint exch def } if
  468.     dup /WhitePoint knownoget { /WhitePoint exch def } if
  469.     pop [ /CIEBasedA currentdict end ]
  470.   }
  471.   /CalRGB {
  472.     1 oget 6 dict begin
  473.     dup /Gamma knownoget {
  474.       [ exch { /exp load 2 packedarray cvx } forall
  475.       ] /DecodeABC exch def
  476.     } if
  477.     dup /Matrix knownoget { /MatrixABC exch def } if
  478.     dup /BlackPoint knownoget { /BlackPoint exch def } if
  479.     dup /WhitePoint knownoget { /WhitePoint exch def } if
  480.     pop [ /CIEBasedABC currentdict end ]
  481.   }
  482.   /CalCMYK {
  483.     pop /DeviceCMYK        % not defined by Adobe
  484.   }
  485.   /Lab {
  486.     1 oget 6 dict begin
  487.     dup /Range knownoget not { [-100 100 -100 100] } if
  488.     [0 100 null null null null] dup 2 4 -1 roll putinterval
  489.     /RangeABC exch def
  490.     //cslabinit { def } forall
  491.     dup /BlackPoint knownoget { /BlackPoint exch def } if
  492.     dup /WhitePoint knownoget { /WhitePoint exch def } if
  493.     pop [ /CIEBasedABC currentdict end ]
  494.   }
  495.   /ICCBased {
  496.         % Since the PostScript interpreter doesn't support these yet,
  497.         % always substitute an alternate space.
  498.     1 oget dup /Alternate knownoget {
  499.       exch pop
  500.     } {
  501.       /N get { null /DeviceGray null /DeviceRGB /DeviceCMYK } exch get
  502.     } ifelse resolvecolorspace
  503.   }
  504.   /Separation {
  505.     aload pop exch oforce resolvecolorspace exch oforce resolvefnproc
  506.     4 array astore
  507.   }
  508.   /DeviceN {
  509.     aload pop 3 -1 roll oforce
  510.     3 -1 roll oforce resolvecolorspace
  511.     3 -1 roll oforce resolvefnproc
  512.     4 array astore
  513.   }
  514.   /Indexed {
  515.     aload pop 3 -1 roll oforce resolvecolorspace
  516.         % If the underlying space is a Lab space, we must scale
  517.         % the output of the lookup table as part of DecodeABC.
  518.     dup dup type /arraytype eq { 0 get } if /CIEBasedABC eq {
  519.       dup 1 get /DecodeLMN known {
  520.     1 get dup length dict copy
  521.     begin /DecodeABC [ 0 2 4 {
  522.       RangeABC 1 index 1 add get RangeABC 2 index get sub /mul load
  523.       RangeABC 3 index get /add load
  524.       DecodeABC 6 -1 roll 2 idiv get [ 6 1 roll aload pop ] cvx
  525.     } for ] def
  526.     /RangeABC //01_3 def
  527.     currentdict end /CIEBasedABC exch 2 array astore
  528.       } if
  529.     } if
  530.     3 1 roll
  531.     oforce dup type /stringtype ne {
  532.         % The color lookup table is a stream.
  533.         % Get its contents.  Don't lose our place in PDFfile.
  534.         % Stack: /Indexed basespace hival lookup
  535.     PDFfile fileposition 5 1 roll true resolvestream
  536.         % Stack: filepos /Indexed basespace hival lookupstream
  537.     1 index 1 add
  538.         % Stack: filepos /Indexed basespace hival lookupstream len
  539.     3 index
  540.       dup dup type /arraytype eq { 0 get } if
  541.       //csncompdict exch get exec mul
  542.     string readstring pop
  543.         % Stack: filepos /Indexed basespace hival table
  544.     5 -1 roll PDFfile exch setfileposition
  545.     }
  546.     if 4 array astore
  547.   }
  548.   /Pattern {
  549.     dup type /nametype ne {
  550.       dup length 1 gt {
  551.     1 oget resolvecolorspace
  552.     /Pattern exch 2 array astore
  553.       } if
  554.     } if
  555.   }
  556. .dicttomark readonly def
  557.  
  558. /cssubst {        % <csname> cssubst <cspace'> true
  559.             % <csname> cssubst false
  560.   dup resolvecolorspace
  561.   dup 1 index ne { exch pop true } { pop pop false } ifelse
  562. } bdef
  563.  
  564. /csnames mark
  565.   /DeviceGray dup  /DeviceRGB dup  /DeviceCMYK dup  /Pattern dup
  566. .dicttomark readonly def
  567. /csresolve {        % <csresourcename> csresolve <cspace>
  568.   dup Page /ColorSpace rget {
  569.     exch pop resolvecolorspace
  570.   } {
  571.     //csnames 1 index known not { /undefined cvx signalerror } if
  572.   } ifelse
  573. } bdef
  574. /resolvecolorspace {    % <cspace> resolvecolorspace <cspace'>
  575.   dup dup type /arraytype eq { 0 get } if
  576.   //csrdict exch .knownget {
  577.     exec dup type /nametype ne { dup length 1 eq { 0 get } if } if
  578.   } {
  579.     csresolve
  580.   } ifelse
  581. } bdef
  582.  
  583. /scresolve {    % <c0> ... scresolve <multi>
  584.         % We can't really make sc[n] and SC[N] work, because
  585.         % the color space information isn't available at
  586.         % conversion time; so we hack it by assuming that
  587.         % all the operands on the stack are used, and that
  588.         % if the top operand is a name, it's a Pattern resource.
  589.   dup type /nametype eq
  590.     { Page /Pattern rget { resolvepattern } { null } ifelse }
  591.   if
  592.   dup type /dicttype eq {
  593.         % Check the PaintType, if any (shading patterns don't
  594.         % have one).
  595.     dup /PaintType .knownget { 2 eq } { false } ifelse
  596.   } {
  597.     .pdfcount 1 gt
  598.   } ifelse
  599. } bdef
  600.  
  601. /.pdfpaintproc {         % <patdict> <resdict> .pdfpaintproc -
  602.   DEBUG { (%Begin PaintProc) = flush } if
  603.     % For uncolored patterns, we have to unbind the current
  604.     % color and color space before running the PaintProc.
  605.     % There's no harm in doing this for colored patterns,
  606.     % so for simplicity, we always do it.
  607.   PDFfile fileposition 3 1 roll
  608.   q
  609.   null sc1 null SC1
  610.   exch false resolvestream pdfopdict .pdfruncontext
  611.   Q
  612.   DEBUG { (%End PaintProc) = flush } if
  613.   PDFfile exch setfileposition
  614. } bdef
  615.  
  616. /resolvepattern {    % <patternstreamdict> resolvepattern <patterndict>
  617.         % Don't do the resolvestream now: just capture the data
  618.         % from the file if necessary.
  619.   dup length dict copy
  620.   dup /FilePosition .knownget {
  621.     1 index /File get dup fileposition 3 1 roll
  622.         % Stack: dict savepos pos file
  623.     dup 3 -1 roll setfileposition
  624.     dup 3 index /Length oget string readstring pop
  625.         % Stack: dict savepos file string
  626.     3 1 roll exch setfileposition
  627.     1 index /File 3 -1 roll put
  628.     dup /FilePosition undef
  629.   } if
  630.   dup /Shading knownoget {
  631.     resolveshading 1 index /Shading 3 -1 roll put
  632.   } if
  633.   dup /PaintProc [
  634.         % Bind the resource dictionary into the PaintProc.
  635.     2 index /Resources knownoget { oforce } { 0 dict } ifelse
  636.     /.pdfpaintproc cvx
  637.   ] cvx put
  638.   DEBUG {
  639.     (%Pattern: ) print dup === flush
  640.   } if
  641. } bdef
  642.  
  643. drawopdict begin
  644.   /g { /DeviceGray cssubst { cs sc1 } { g } ifelse } bdef
  645.   /rg { /DeviceRGB cssubst { cs sc* } { rg } ifelse } bdef
  646.   /k { k } bdef
  647.   /cs { csresolve cs } bdef
  648.   /sc { scresolve { sc* } { sc1 } ifelse } bdef
  649.   /scn /sc load def
  650.   /G { /DeviceGray cssubst { CS SC1 } { G } ifelse } bdef
  651.   /RG { /DeviceRGB cssubst { CS SC* } { RG } ifelse } bdef
  652.   /K { K } bdef
  653.   /CS { csresolve CS } bdef
  654.   /ri { ri } bdef
  655.   /SC { scresolve { SC* } { SC1 } ifelse } bdef
  656.   /SCN /SC load def
  657. end
  658.  
  659. % ---------------- Paths ---------------- %
  660.  
  661. drawopdict begin
  662.             % Path construction
  663.   /m /moveto load def
  664.   /l /lineto load def
  665.   /c /curveto load def
  666.   /v { currentpoint 6 2 roll curveto } def
  667.   /y { 2 copy curveto } def
  668.   /re {
  669.    4 2 roll moveto  exch dup 0 rlineto  0 3 -1 roll rlineto  neg 0 rlineto
  670.    closepath
  671.   } def
  672.   /h /closepath load def
  673.             % Path painting and clipping
  674.   /n { n } def
  675.   /S { S } def
  676.   /s { s } def
  677.   /f { f } def
  678.   /f* { f* } def
  679.   /B { B } def
  680.   /b { b } def
  681.   /B* { B* } def
  682.   /b* { b* } def
  683.   /W { W } def
  684.   /W* { W* } def
  685.   /sh { resolvesh shfill } def
  686. end
  687.  
  688. % ---------------- XObjects ---------------- %
  689.  
  690. /xobjectprocs mark        % <dict> -proc- -
  691.   /Image { DoImage }
  692.   /Form { DoForm }
  693.   /PS { DoPS }
  694. .dicttomark readonly def
  695.  
  696. % Note that the keys in defaultdecodedict are resolved (PostScript, not PDF)
  697. % color space names.
  698. /defaultdecodedict mark
  699.   /DeviceGray { pop //01_1 } bind
  700.   /DeviceRGB { pop //01_3 } bind
  701.   /DeviceCMYK { pop //01_4 } bind
  702.   /CIEBasedA { 1 get /RangeA .knownget not { //01_1 } if } bind
  703.   /CIEBasedABC { 1 get /RangeABC .knownget not { //01_3 } if } bind
  704.   /Separation { pop //01_1 } bind
  705.   /DeviceN {
  706.     1 oget length [ exch {0 1} repeat ] readonly
  707.   } bind
  708.   /Indexed {
  709.     pop [ 0 1 BitsPerComponent bitshift 1 sub ]
  710.   } bind
  711. .dicttomark readonly def
  712.  
  713. /checkaltimage {    % <resdict> checkaltimage <resdict[']>
  714.   Printed {
  715.     dup /Alternates knownoget {
  716.       {
  717.     dup /DefaultForPrinting knownoget {
  718.       {
  719.         /Image oget exch pop exit
  720.       } {
  721.         pop
  722.       } ifelse
  723.     } {
  724.       pop
  725.     } ifelse
  726.       } forall
  727.     } if
  728.   } if
  729. } bdef
  730.  
  731. /makeimagedict {    % <resdict> <newdict> makeimagedict <imagemask>
  732.             % On return, newdict' is currentdict
  733.   begin
  734.   /Width 2 copy oget def
  735.   /Height 2 copy oget def
  736.   /BitsPerComponent 2 copy oget def
  737.   /Interpolate 2 copy knownoget { def } { pop } ifelse
  738.   makeimagekeys
  739. } bdef
  740. /makeimagekeys {    % <resdict> makeimagekeys <imagemask>
  741.         % newdict is currentdict
  742.         % Assumes Width, Height, BPC, Interpolate already copied.
  743.   /ImageType 1 def
  744.   /ImageMatrix Width 0 0
  745.         % Handle 0-height images specially.
  746.     Height dup 0 eq { pop 1 } if neg 0 1 index neg
  747.     6 array astore def
  748.   dup /ImageMask knownoget dup { and } if {
  749.         % Image mask
  750.         % Decode is required for the PostScript image operators.
  751.     /Decode 2 copy knownoget not { //01_1 } if def
  752.         % BitsPerComponent may be missing for masks.
  753.         % The spec requires it, but some producers omit it, and
  754.         % Acrobat Reader doesn't care.
  755.     /BitsPerComponent 2 copy known { pop } { 1 def } ifelse
  756.     true
  757.   } {
  758.         % Opaque image
  759.     dup /ColorSpace oget resolvecolorspace /ColorSpace exch def
  760.         % Decode is required for the PostScript image operators.
  761.     /Decode 2 copy knownoget not {
  762.       ColorSpace //defaultdecodedict
  763.       ColorSpace dup type /arraytype eq { 0 get } if get exec
  764.     } if def
  765.     false
  766.   } ifelse
  767.         % Even though we're going to read data,
  768.         % pass false to resolvestream so that
  769.         % it doesn't try to use Length (which may not be present).
  770.   exch false resolvestream /DataSource exch def
  771. } bdef
  772.  
  773. /DoImage {
  774.   checkaltimage dup length 6 add dict
  775.   1 index /SMask knownoget { 1 index exch /SMask exch put } if
  776.   1 index /Mask knownoget { 1 index exch /Mask exch put } if
  777.   makeimagedict doimage
  778. } bdef
  779. /makemaskimage {    % <datasource> <imagemask> <Mask> makemaskimage
  780.             %   <datasource> <imagemask>, updates currentdict =
  781.             %   imagedict
  782.   dup type /arraytype eq {
  783.     /ImageType 4 def
  784.     /MaskColor exch def
  785.   } {
  786.         % Mask is a stream, another Image XObject.
  787.         % Stack: datasource imagemask(false) maskstreamdict
  788.     PDFfile fileposition exch
  789.     dup length dict makeimagedict pop
  790.         % In order to prevent the two data sources from being
  791.         % aliased, we need to make at least one a reusable stream.
  792.         % We pick the mask, since it's smaller (in case we need to
  793.         % read all its data now).
  794.         % Stack: datasource imagemask(false) savedpos
  795.         % maskdict is currentdict
  796.     /DataSource DataSource mark
  797.       /Intent 1
  798.       /AsyncRead true
  799.     .dicttomark .reusablestreamdecode def
  800.     PDFfile exch setfileposition
  801.     currentdict end currentdict end
  802.     5 dict begin
  803.     /ImageType 3 def
  804.     /InterleaveType 3 def
  805.     /DataDict exch def
  806.     /MaskDict exch def
  807.     /ColorSpace DataDict /ColorSpace get def
  808.   } ifelse
  809. } bdef
  810. /doimage {    % <imagemask> doimage -
  811.         % imagedict is currentdict, gets popped from dstack
  812.   DataSource exch
  813.   PDFversion 1.4 ge { currentdict /SMask knownoget } { false } ifelse {
  814.     makesoftmaskimage
  815.   } {
  816.     currentdict /Mask knownoget {
  817.       makemaskimage
  818.     } if
  819.   } ifelse
  820.         % Stack: datasource imagemask
  821.    { currentdict end setfillstate imagemask }
  822.    { ColorSpace setcolorspace currentdict end setfillblend image }
  823.   ifelse
  824.         % Close the input stream, unless it is PDFfile or
  825.         % PDFsource.
  826.   dup dup PDFfile eq exch PDFsource eq or { pop } { closefile } ifelse
  827. } bdef
  828.  
  829. /.paintform {    % <formdict> <resdict> <stream> .paintform -
  830.   3 -1 roll dup /Group known {
  831.     .paintgroupform
  832.   } {
  833.     pop pdfopdict .pdfruncontext
  834.   } ifelse
  835. } bdef
  836. /DoForm {
  837.   dup length dict copy
  838.   dup [ 2 index /Resources knownoget { oforce } { 0 dict } ifelse
  839.   3 index false /resolvestream cvx
  840.   /.paintform cvx
  841.   ] cvx /PaintProc exch put
  842.   execform
  843. } bdef
  844.  
  845. /DoPS {
  846.   true resolvestream cvx exec
  847. } bdef
  848.  
  849. drawopdict begin
  850.   /Do {
  851.     PDFfile fileposition exch
  852.     dup Page /XObject rget { 
  853.       exch pop dup /Subtype get xobjectprocs exch get
  854.         % Don't leave extra objects on the stack while executing
  855.         % the definition of the form.
  856.       3 -1 roll 2 .execn
  857.     } {
  858.         % This should cause an error, but Acrobat Reader can
  859.         % continue, so we do too.
  860.       (%stderr) (w) file
  861.       dup (****************Undefined XObject resource: ) writestring 
  862.       dup 3 -1 roll write===
  863.       flushfile
  864.     } ifelse
  865.     PDFfile exch setfileposition
  866.   } bdef
  867. end
  868.  
  869. % ---------------- In-line images ---------------- %
  870.  
  871. % Undo the abbreviations in an in-line image dictionary.
  872. % Note that we must look inside array values.
  873. % /I is context-dependent.
  874. /unabbrevkeydict mark
  875.   /BPC /BitsPerComponent  /CS /ColorSpace  /D /Decode  /DP /DecodeParms
  876.   /F /Filter  /H /Height  /I /Interpolate  /IM /ImageMask  /W /Width
  877. .dicttomark readonly def
  878. /unabbrevvaluedict mark
  879.   /AHx /ASCIIHexDecode  /A85 /ASCII85Decode  /CC /CalCMYK
  880.   /CCF /CCITTFaxDecode  /CG /CalGray  /CR /CalRGB
  881.   /DCT /DCTDecode  /CMYK /DeviceCMYK  /Fl /FlateDecode
  882.   /G /DeviceGray  /RGB /DeviceRGB
  883.   /I /Indexed  /LZW /LZWDecode  /RL /RunLengthDecode
  884. .dicttomark readonly def
  885. /unabbrevtypedict mark
  886.   /nametype {
  887.     //unabbrevvaluedict 1 index .knownget { exch pop } if
  888.   }
  889.   /arraytype {
  890.     dup 0 1 2 index length 1 sub {
  891.       2 copy get unabbrevvalue put dup
  892.     } for pop
  893.   }
  894. .dicttomark readonly def
  895. /unabbrevvalue {    % <obj> unabbrevvalue <obj'>
  896.   oforce //unabbrevtypedict 1 index type .knownget { exec } if
  897. } bdef
  898.  
  899. drawopdict begin
  900.   /BI { mark } bdef
  901.   /ID {
  902.     counttomark 2 idiv dup 6 add dict begin {
  903.       exch //unabbrevkeydict 1 index .knownget { exch pop } if
  904.       exch unabbrevvalue def
  905.     } repeat pop
  906.     /File PDFsource def
  907.     currentdict makeimagekeys doimage    
  908.     % The Adobe documentation says that the data following ID
  909.     % consists of "lines", and some PDF files (specifically, some files
  910.     % produced by PCL2PDF from Visual Software) contain garbage bytes
  911.     % between the last byte of valid data and an EOL.  Therefore, we
  912.     % skip such garbage bytes here.
  913.     {
  914.       PDFsource read {
  915.     dup 10 eq exch 13 eq or { exit } if
  916.       } {
  917.         exit
  918.       } ifelse
  919.     } loop
  920.     PDFsource token pop /EI ne { /ID cvx /syntaxerror signalerror } if
  921.   } bdef
  922. end
  923.  
  924. % ================================ Text ================================ %
  925.  
  926. drawopdict begin
  927.             % Text control
  928.   /BT { BT } def
  929.   /ET { ET } def
  930.   /Tc { Tc } def
  931.   /TL { TL } def
  932.   /Tr { Tr } def
  933.   /Ts { Ts } def
  934.   /Tw { Tw } def
  935.   /Tz { Tz } def
  936.             % Text positioning
  937.   /Td { Td } def
  938.   /TD { TD } def
  939.   /Tm { Tm } def
  940.   /T* { T* } def
  941.             % Text painting
  942.   /Tj { Tj } def
  943.   /' { ' } def
  944.   /" { " } def
  945.   /TJ { TJ } def
  946. end
  947.  
  948. % ============================== Annotations ============================== %
  949.  
  950.  
  951.  
  952. % Get and normalize an annotation's rectangle.
  953. /annotrect {        % <annot> annotrect <x> <y> <w> <h>
  954.   /Rect get aload pop
  955.   exch 3 index sub dup 0 lt { dup 5 -1 roll add 4 1 roll neg } if
  956.   exch 2 index sub dup 0 lt { dup 4 -1 roll add 3 1 roll neg } if
  957. } bdef
  958.  
  959. % Set an annotation color.
  960. /annotsetcolor {    % <annot> annotsetcolor -
  961.   /C knownoget { aload pop setrgbcolor } { 0 setgray } ifelse
  962. } bdef
  963.  
  964. % Draw the border.  Currently, we ignore requests for beveling, and we
  965. % don't round the corners of rectangles.
  966. /strokeborder {        % <annot> <width> <dash> strokeborder -
  967.   1 index 0 ne {    % do not draw if border width is 0
  968.     gsave
  969.     2 index annotsetcolor
  970.     0 setdash dup setlinewidth
  971.     exch annotrect
  972.     2 { 4 index sub 4 1 roll } repeat
  973.     2 { 4 index 0.5 mul add 4 1 roll } repeat
  974.     rectstroke pop
  975.     grestore
  976.   } {
  977.     pop pop pop
  978.   } ifelse
  979. } bdef
  980.  
  981. % Draw an annotation border.
  982. /drawborder {        % <annot> drawborder -
  983.   gsave
  984.   dup /BS knownoget {
  985.     dup /W knownoget not { 1 } if
  986.     [] 2 index /S knownoget {
  987.       /D eq { 2 index /D knownoget not { [3] } if exch pop } if
  988.     } if 3 -1 roll pop strokeborder
  989.   } {
  990.     dup /Border knownoget {
  991.       dup 2 get
  992.       exch dup length 3 gt { 3 get } { pop [] } ifelse
  993.       strokeborder
  994.     } {
  995.       pop
  996.     } ifelse
  997.   } ifelse
  998.   grestore
  999. } bdef
  1000.  
  1001. %
  1002. %   The PDF annotation F (flags) integer is bit encoded.
  1003. %   Bit 1 (LSB) Invisible:  1 --> Do not display if no handler.
  1004. %         Note:  We have no handlers but we ignore this bit.
  1005. %   Bit 2 Hidden:  1 --> Do not display.  We will not display if this bit is set.
  1006. %   Bit 3 Print:  1 --> Display if printing.  We will display if this bit set
  1007. %         (and not hidden) and Printed is true
  1008. %   Bit 4 NoZoom:  1 --> Do not zoom annotation even if image is zoomed.
  1009. %   Bit 5 NoRotate:  1 --> Do not rotate annotation even if image is rotated.
  1010. %   Bit 6 NoView:  0 --> Display if this is a 'viewer'.  We will display
  1011. %         if this bit is not set (and not hidden) and Printed is false
  1012. %   Bit 7 Read Only - 1 --> No interaction.  We ignore this bit
  1013. %
  1014. /annotvisible {            % <annot> annotvisible <visible>
  1015.   /F knownoget not { 0 } if         % Get flag value
  1016.   dup 2 and 0 eq              % Check hidden flag
  1017.   exch dup 4 and 0 ne Printed and    % Check print flag
  1018.   exch 64 and 0 eq Printed not and    % Check noview flag
  1019.   or                    % Combine print and view
  1020.   and                     % Combine with 'hidden' flag test
  1021. } bdef
  1022.  
  1023. /drawwidget {            % <scalefactor> <annot> drawwidget -
  1024.     dup /AP knownoget {
  1025.     % Always use the Normal appearance.
  1026.       /N oget
  1027.         % Acrobat Distiller produces files in which this Form
  1028.         % XObject lacks Type and Subtype keys.  This is illegal,
  1029.         % but Acrobat Reader accepts it.  The only way we can
  1030.         % tell whether this is a Form or a set of sub-appearances
  1031.         % is by testing for the stream Length key.
  1032.       dup /Length known not {
  1033.     1 index /AS knownoget not { () } if
  1034.         % Stack: annot Ndict AS
  1035.     2 copy knownoget {
  1036.       exch pop exch pop
  1037.     } {
  1038.         % Pick any one.
  1039.       pop { exch pop oforce exit } forall
  1040.     } ifelse
  1041.       } if
  1042.         % Acrobat Distiller produces files in which this Form
  1043.         % XObject lack FormType and Matrix keys.  This is illegal,
  1044.         % but Acrobat Reader accepts it.  Patch this up now.
  1045.       dup /FormType known not  {
  1046.     dup length 1 add dict copy dup /FormType 1 put
  1047.       } if
  1048.       dup /Matrix known not  {
  1049.     dup length 1 add dict copy dup /Matrix matrix put
  1050.       } if
  1051.     1 index annotrect pop pop translate
  1052.     2 index dup scale        % Apply scale factor
  1053.       DoForm
  1054.   } if pop pop
  1055. } bdef
  1056.  
  1057. %
  1058. %  For stamp object we have to determine the size of the output rectangle
  1059. %  and the size of the BBox for the stamp image.  From these we calculate
  1060. %  a scale factor for drawing the stamp.
  1061. %
  1062. /calcstampscale {        % <annot> calcstampscale scale
  1063.   dup annotrect 4 -2 roll pop pop pop    % get x width
  1064.   dup 0 lt { neg } if        % get magnitude
  1065.   exch /AP knownoget {
  1066.     /N knownoget {
  1067.       /BBox knownoget {
  1068.          aload pop 4 -2 roll pop pop pop
  1069.          div
  1070.       } {
  1071.         pop 1            % default to unity scaling
  1072.       } ifelse            % if we have /BBox
  1073.     } {
  1074.       pop 1
  1075.     } ifelse            % if we have /N
  1076.   } {
  1077.     pop 1
  1078.   } ifelse            % if we have /AP
  1079. } bdef
  1080.  
  1081. /drawlink {            % <annot> drawlink -
  1082.   dup drawborder
  1083.   1 exch drawwidget
  1084. } bdef
  1085.  
  1086. % Draw an annotation.
  1087. /drawannottypes mark
  1088.   /Link { drawlink } bind
  1089.   /Stamp { dup calcstampscale exch drawwidget } bind
  1090. .dicttomark readonly def
  1091. /drawannot {        % <annot> drawannot -
  1092.   dup annotvisible {
  1093.     gsave
  1094.     dup dup /Subtype get //drawannottypes exch .knownget {
  1095.       exec
  1096.     } {
  1097.       1 exch drawwidget        % Use drawwidget for everything else
  1098.     } ifelse            % type known
  1099.     grestore
  1100.   } if pop            % annotvisible
  1101. } bdef
  1102. currentdict /drawannottypes undef
  1103.  
  1104. end            % pdfdict
  1105. end            % GS_PDF_ProcSet
  1106. .setglobal
  1107.