Mini Shell

Direktori : /usr/share/ghostscript/Resource/Init/
Upload File :
Current File : //usr/share/ghostscript/Resource/Init/pdf_draw.ps

% Copyright (C) 2001-2021 Artifex Software, Inc.
% 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.
%
% Refer to licensing information at http://www.artifex.com or contact
% Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
% CA 94945, U.S.A., +1(415)492-9861, for further information.
%

% pdf_draw.ps
% PDF drawing operations (graphics, text, and images).

/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal //true .setglobal
/GS_PDF_ProcSet load begin
pdfdict begin

% For simplicity, we use a single interpretation dictionary for all
% PDF graphics operations, even though this is too liberal.
/drawopdict 100 dict def

% ================================ Graphics ================================ %

% ---------------- Functions ---------------- %

% Note that resolvefunction converts a PDF Function to a PostScript Function;
% resolve*fnproc converts a PDF function to a PostScript procedure.
% We need to process all required and optional parameters to resolve any
% use of indirect references.

/fnrdict mark
  0 { .resolvefn0 }
  2 { .resolvefn2 }
  3 { .resolvefn3 }
  4 { .resolvefn4 }
.dicttomark readonly def

/.resolvefn0 {
  dup length 1 add dict .copydict	% make room for DataSource
  % now resolve any indirect references
  dup /Size 2 copy knownoget { put } { pop pop } ifelse
  dup /BitsPerSample 2 copy knownoget { put } { pop pop } ifelse
  dup /Order 2 copy knownoget { put } { pop pop } ifelse
  dup /Encode 2 copy knownoget { put } { pop pop } ifelse
  dup /Decode 2 copy knownoget { put } { pop pop } ifelse

                % Don't lose our place in PDFfile.
  PDFfile fileposition exch
  dup //true resolvestream
                % The stream isn't positionable, so read all the data now.
                % Stack: filepos fndict stream
  1 index /Range get length 2 idiv 2 index /BitsPerSample get mul
  2 index /Size get { mul } forall
  7 add 8 idiv
  dup 65535 le {
    string 1 index exch readstring pop
  } {
    1 index exch () /SubFileDecode filter /ReusableStreamDecode filter
  } ifelse
  exch closefile
                % Stack: filepos fndict data
  exch dup /DataSource 4 -1 roll put
  exch PDFfile exch setfileposition
} bind executeonly def

/.resolvefn2 {
  dup length dict .copydict
  dup /C0 2 copy knownoget { put } { pop pop } ifelse
  dup /C1 2 copy knownoget { put } { pop pop } ifelse
  dup /N 2 copy knownoget { put } { pop pop } ifelse
} bind executeonly def

/.resolvefn3 {
  dup length dict .copydict
  dup /Bounds 2 copy knownoget { put } { pop pop } ifelse
  dup /Encode 2 copy knownoget { put } { pop pop } ifelse
  dup /Functions 2 copy oget mark exch dup {
    oforce .resolvefn
  } forall
  counttomark -1 roll astore exch pop put
} bind executeonly def

/.resolvefn4 {
  PDFfile fileposition exch             % filepos fndict
  dup //true resolvestream              % filepos fndict stream
  exch dup length dict copy             % filepos stream fndict2
  dup /Function undef                   % filepos stream fndict2
  exch dup token not {
    () /rangecheck cvx signalerror
  } if
  exch token {
    /rangecheck cvx signalerror
  } if
                % Use .bind to avoid idiom recognition.
  .bind
  1 index /Function 3 -1 roll put
  exch PDFfile exch setfileposition
} bind executeonly def

/.resolvefn {		% <fndict> .resolvefn <fndict'>
  dup length dict .copydict
  dup /Domain 2 copy knownoget { put } { pop pop } ifelse
  dup /Range 2 copy knownoget { put } { pop pop } ifelse
  dup /FunctionType oget //fnrdict exch get exec
} bind executeonly def

/resolvefunction {	% <fndict> resolvefunction <function>
  .resolvefn
  PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Function: ) print dup === flush } if } if
} bind executeonly def

/resolvefnproc {	% <fndict> resolvefnproc <proc>
  resolvefunction .buildfunction
} bind executeonly def

/resolveidfnproc {	% <fndict> resolveidfnproc <proc>
  dup /Identity eq { pop { } } { resolvefnproc } ifelse
} bind executeonly def

/resolvedefaultfnproc {	% <fndict> <default> resolved'fnproc <proc>
  1 index /Default eq { exch pop } { pop resolveidfnproc } ifelse
} bind executeonly def

%% A BBox where width or height (or both) is 0 should still paint one pixel
%% See the ISO 32000-2:2017 spec, section 8.7.4.3, p228 'BBox' and 8.7.3.1
/FixPatternBBox
{
  dup aload pop
  3 index 2 index sub 0 eq {
    3 index 0.000001 add 3 -1 roll pop exch
  } if
  2 index 1 index sub 0 eq {
    2 index 0.000001 add exch pop
  }if
  5 -1 roll astore
}bind executeonly def

% ---------------- Shadings ---------------- %

/shrdict mark
  /Coords {
    aload
    5 1 roll
    4 { % Bug 694542
      dup type dup /integertype ne exch /realtype ne and {
         (   **** Error: replacing malformed number ') pdfformaterror pdfstring cvs pdfformaterror
         (' with 0.\n) pdfformaterror
         (               Output may be incorrect.\n) pdfformaterror
         0
      } if
      4 1 roll
    } repeat
    5 -1 roll
    astore
  } bind executeonly
  /BBox {
    dup dup dup aload pop normrect_elems
    5 -1 roll astore
    FixPatternBBox
  } bind executeonly
  /ColorSpace {
    resolvecolorspace
  } bind executeonly
  /Function {
    dup type /dicttype eq {
      resolvefunction
    } {
      [ exch { oforce resolvefunction } forall ]
    } ifelse
  } bind executeonly
  /Extend {
    mark exch {oforce} forall ]
  } bind executeonly
.dicttomark readonly def

/resolveshading {	% <shadingstream> resolveshading <shading>
  dup /.shading_dict .knownget {
    exch pop
    dup /ShadingType get 4 ge {
      dup /DataSource get 0 setfileposition
    } if
  } {
    dup
    PDFfile fileposition exch
    mark exch {
      oforce //shrdict 2 index .knownget { exec } if
    } forall .dicttomark
    dup /ShadingType get 4 ge {
      dup dup //true resolvestream
                % Make a reusable stream so that the shading doesn't
                % reposition PDFfile at unexpected times.
      /ReusableStreamDecode filter /DataSource exch put
    } if
    exch PDFfile exch setfileposition
    dup 3 1 roll /.shading_dict exch put
  } ifelse
} bind executeonly def
/resolvesh {		% <shname> resolvesh <shading>
                        % <shname> resolvesh <null>
  Page /Shading rget {
  %% Horrible hacky fix, see /DoImage later in ths file for more information
  %%
  dup /ColorSpace known {
    dup /ColorSpace get dup type /arraytype eq {
      exch dup length dict copy exch
      dup length array copy /ColorSpace exch 2 index 3 1 roll put
    } {pop} ifelse
  } if

    resolveshading
  } {
    //null
  }ifelse
} bind executeonly def

% ---------------- Halftones ---------------- %

/spotfunctions mark
  /Round {
    abs exch abs 2 copy add 1 le {
      dup mul exch dup mul add 1 exch sub
    } {
      1 sub dup mul exch 1 sub dup mul add 1 sub
    } ifelse
  } bind executeonly
  /Diamond {
    abs exch abs 2 copy add .75 le {
      dup mul exch dup mul add 1 exch sub
    } {
      2 copy add 1.23 le {
        .85 mul add 1 exch sub
      } {
        1 sub dup mul exch 1 sub dup mul add 1 sub
      } ifelse
    } ifelse
  } bind executeonly
  /Ellipse {
    abs exch abs 2 copy 3 mul exch 4 mul add 3 sub dup 0 lt {
      pop dup mul exch .75 div dup mul add 4 div 1 exch sub
    } {
      dup 1 gt {
        pop 1 exch sub dup mul exch 1 exch sub
        .75 div dup mul add 4 div 1 sub
      } {
        .5 exch sub exch pop exch pop
      } ifelse
    } ifelse
  } bind executeonly
  /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub } bind executeonly
  /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub } bind executeonly
  /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub } bind executeonly
  /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub } bind executeonly
  /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub } bind executeonly
  /Line { exch pop abs neg } bind executeonly
  /LineX { pop } bind executeonly
  /LineY { exch pop } bind executeonly
  /Square { abs exch abs 2 copy lt { exch } if pop neg } bind executeonly
  /Cross { abs exch abs 2 copy gt { exch } if pop neg } bind executeonly
  /Rhomboid { abs exch abs 0.9 mul add 2 div } bind executeonly
  /DoubleDot { 2 {360 mul sin 2 div exch } repeat add } bind executeonly
  /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg } bind executeonly
  /SimpleDot { dup mul exch dup mul add 1 exch sub } bind executeonly
  /InvertedSimpleDot { dup mul exch dup mul add 1 sub } bind executeonly
  /CosineDot { 180 mul cos exch 180 mul cos add 2 div } bind executeonly
  /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add } bind executeonly
  /InvertedDouble {
    exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
  } bind executeonly
.dicttomark readonly def

/.resolveht1 {
  mark exch {
    oforce
    1 index /SpotFunction eq {
      dup type /arraytype eq {
        %% check all the names in the array in turn, stop when we find
        %% the first one we recognise.
        {
          //spotfunctions exch .knownget {
            exit
          } if
        } forall
        dup type /nametype eq {
          %% If we didn't find any that we recognise, then use
          %% the default halftone's spot function
          .setdefaulthalftone currenthalftone dup /SpotFunction .knownget {
            exch pop
          }{
            /GraySpotFunction .knownget not {
              //spotfunctions /Round get
            } if
          }ifelse
        } if
      }{
        dup type /nametype eq
          { //spotfunctions exch get } { resolvefnproc }
        ifelse
      } ifelse
    } {
      1 index /TransferFunction eq {
        resolveidfnproc
      } if
    } ifelse
  } forall .dicttomark
} bind executeonly def

/.resolveht5 {
  mark exch {
    oforce dup type /dicttype eq { resolvehalftone } if
  } forall .dicttomark
} bind executeonly def

/.resolveht6 {
  %% resolvestream will reposition PDFfile. If we are in the middle
  %% of reading a content stream from PDFfile when we execute this,
  %% then reading the next buffer will read from the wrong place. We
  %% must save and restore the position of PDFfile. See the definition
  %% of resolvestream. Bug #695886
  PDFfile fileposition exch
  mark exch { oforce } forall .dicttomark
  dup dup //false resolvestream /ReusableStreamDecode filter
  /Thresholds exch put
  dup /TransferFunction .knownget {
    resolveidfnproc
    1 index exch /TransferFunction exch put
  } if
  exch PDFfile exch setfileposition
} bind executeonly def

/htrdict mark
  1 //.resolveht1
  5 //.resolveht5
  6 //.resolveht6
 10 //.resolveht6
 16 //.resolveht6
.dicttomark readonly def

currentdict /.resolveht1 undef
currentdict /.resolveht5 undef
currentdict /.resolveht6 undef

/resolvehalftone {	% <dict> resolvehalftone <halftone>
  dup /HalftoneType oget
  dup //htrdict exch .knownget {
    exch pop exec
  } {
    =string cvs
    (   **** Error: Incorrect halftone type ) exch concatstrings
    (. Using defailt.\n) concatstrings pdfformaterror
    (               Output may be incorrect.\n) pdfformaterror
    gsave .setdefaulthalftone currenthalftone grestore
  } ifelse
} bind executeonly def

% ---------------- Graphics state management ---------------- %

/cmmatrix matrix def
drawopdict begin
                        % Graphics state stack
  /q { q } executeonly def
  /Q { Q } executeonly def
                        % Graphics state setting
  /cm { //cmmatrix astore
        .getpath
        exch concat
        newpath { exec } forall
        % If inside a BT/ET block, we need to update the TextSaveMatrix
        currentdict /TextSaveMatrix .knownget {
          //cmmatrix exch dup concatmatrix pop
        } if
        % And if we ha\ve done a gsave inside a text block, we need to update
        % that matrix instead.
        currentdict /qTextSaveMatrix .knownget {
         //cmmatrix exch dup concatmatrix pop
        } if
      } bind executeonly def

  /i { 1 .min setflat } bind executeonly def
  /J { setlinecap } bind 0 get def
  /d { setdash } bind 0 get def
  /j { setlinejoin } bind 0 get def
  /w { setlinewidth } bind 0 get def
  /M { 1 .max setmiterlimit } bind executeonly def
  /gs { gs } executeonly def
end

% Each entry in this dictionary is
%	<gsres> <value> -proc- <gsres>
/gsbg {
  /BGDefault load resolvedefaultfnproc setblackgeneration
} bind executeonly def
/gsucr {
  /UCRDefault load resolvedefaultfnproc setundercolorremoval
} bind executeonly def
/gstr {
  dup type /arraytype eq {
    { oforce /TRDefault load resolvedefaultfnproc } forall
    setcolortransfer
  } {
    /TRDefault load resolvedefaultfnproc settransfer
  } ifelse
} bind executeonly def
/gsparamdict mark
  /SA { setstrokeadjust } executeonly
  /OP { 1 index /op known not { dup op } if OP } executeonly
        % The PDF 1.3 specification says that the name /Default is only
        % recognized for {BG,UCR,TR}2.  However, PDF 1.3 files produced
        % by Adobe Acrobat Distiller 4.0 for Windows use the name /Default
        % with the older keys, so we have to implement this.
  /BG { 1 index /BG2 known { pop } { gsbg } ifelse } executeonly
  /UCR { 1 index /UCR2 known { pop } { gsucr } ifelse } executeonly
  /TR { 1 index /TR2 known { pop } { gstr } ifelse } executeonly

  % Some functions used to implement phases of HT and HTP
  /sethalftones {
    % As is so often the case, if we get an error we need to clean up the stack, but we can't
    % use mark/cleartomark, because the action which caused the error may have left a mark
    % on the stack. So we need to define our own mark. On an error we'll clean up the stack
    % until we reach this unique key on the stack
    /SethalftonesMark exch

    dup /Default eq {
      pop .setdefaulthalftone pop
    }
    {
      {resolvehalftone} stopped
      {
        (\n   **** Error resolving halftone. Ignoring the halftone, output may be incorrect.\n)
        pdfformaterror
        % Clean up the stack by checking every entry until we find our unique key
        {/SethalftonesMark eq {exit} if} loop
      }
      {
        {sethalftone} stopped
        {
          (\n   **** Error setting halftone. Ignoring the halftone, output may be incorrect.\n)
          pdfformaterror
          % Clean up the stack by checking every entry until we find our unique key
          {/SethalftonesMark eq {exit} if} loop
        }
        {
          pop
        }ifelse
      }ifelse
    } ifelse
  } bind executeonly def
  /sethalftonephases {
      {aload pop -1 2 index 2 index .setscreenphase pop pop} stopped
      {
        (\n   **** Error setting halftone phase. Ignoring the phase, output may be incorrect.\n)
        pdfformaterror
      } if
  } bind executeonly def

  /HT {
    dup sethalftones .swapcolors sethalftones .swapcolors
    % the transfer function may dependent on the halftone, so make sure
    % it is set if included in the graphic state (otherwise this is
    % subject to order of a dictionary forall, which is unpredictable)
    dup /TR2 .knownget {
      dup /Default eq { oforce gsparamdict /TR2 get exec } { pop } ifelse
    } {
      dup /TR .knownget {
        /dup /Default eq { oforce gsparamdict /TR get exec } { pop } ifelse
      } if
    } ifelse
  } executeonly
  /HTP {
    % HTP may be present even if this isn't a DPS interpreter.
    dup sethalftonephases .swapcolors sethalftonephases .swapcolors
  } executeonly
        % PDF 1.3
  % The font is an indirect reference, not a resource name
  /Font { aload pop exch oforce resourcefont exch Tf }
  /LW { setlinewidth } executeonly
  /LC { setlinecap } executeonly
  /LJ { setlinejoin } executeonly
  /ML { 1 .max setmiterlimit } executeonly
  /D { aload pop setdash } executeonly
  /RI { ri } executeonly
  /op { op } executeonly
  /OPM { OPM } executeonly
  /BG2 { gsbg } executeonly
  /UCR2 { gsucr } executeonly
  /TR2 { gstr } executeonly
  /FL { 1 .min setflat } executeonly
  /SM {
        % SM may be present even if this is only a Level 2 interpreter.
    /setsmoothness where { pop setsmoothness } { pop } ifelse
  } executeonly
        % PDF 1.4
        % All of these require the "transparency" feature in the interpreter.
  /ca { ca } executeonly
  /CA { CA } executeonly
  /SMask {
    {gssmask} PDFSTOPONERROR { exec //false } { stopped } ifelse
    {
      pop (\n   **** Error in SMask during ExtGState. Ignoring the mask, output may be incorrect.\n)
      pdfformaterror
    } if
  } executeonly
  /AIS { AIS } executeonly
  /BM { BM } executeonly
  /TK { TK } executeonly
  /UseBlackPtComp { UseBlackPtComp } executeonly
  /HTO {
    % PDF 2.0, supposed to be 'similar' to halftone phase but using a different
    % co-ordiate system. Treat the same for now and fix if anyone ever complains.
    aload pop transform cvi exch cvi exch 2 array astore
    dup sethalftonephases .swapcolors sethalftonephases .swapcolors
  } executeonly
.dicttomark readonly def
/gs {			% <gsres> gs -
  Page /ExtGState rget {
        % We keep the dictionary on the stack during the forall so that
        % keys that interact with each other have access to it.
    dup {
      oforce exch gsparamdict exch .knownget { exec } { pop } ifelse
    } forall pop
  } {
    //pdfdict /.gs_warning_issued known not {
      (\n   **** Error 'gs' ignored -- ExtGState missing from Resources.\n)
      pdfformaterror
      (        Output may be incorrect.\n) pdfformaterror
      //pdfdict /.gs_warning_issued //true .forceput
      PDFSTOPONERROR { /gs /undefined signalerror } if
    } executeonly if
  } executeonly
  ifelse
} bind executeonly def

% ------ Transparency support ------ %

/gssmask {
  {
   dup type /dicttype eq
   {
     dup /G knownogetdict
     {pop}
     {
        (   **** Error: Ignoring invalid transparency SMask group\n)
        pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
        % replace the invalid SMask object
        pop /None
     } ifelse
    } if

    dup /None eq 1 index //null eq or PDFusingtransparency not or {
      pop //null

      .currentSMask //null ne {
        % get rid of the current SMask (Bug 695471)
        //false			% colorspace not set
        << /Subtype /None >>	% Special type for this purpose
        0 0 0 0			% fake BBox
        .begintransparencymaskgroup
      } if
      exit
    } if
        % Preprocess the SMask value into a parameter dictionary for
        % .begintransparencymaskgroup, with added /BBox and /Draw keys.
    mark exch		% Stack: mark smaskdict
    dup /S oget /Subtype exch 3 2 roll
                        % Stack: mark ... smaskdict
    dup /BC knownoget {
      dup /Background exch 4 2 roll
      1 index /G oget /Group knownoget not {
        (   **** Error: Ignoring a transparency group XObject without /Group attribute.\n)
        pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
        cleartomark //null exit
      } if
      gsave //nodict begin
        dup /CS knownoget {
          exch pop
          resolvecolorspace dup setgcolorspace csput
        }
        {
          % Group attributes dictionaries are supposed to contain a /CS
          % entry, but Acrobat apparently also handles a /ColorSpace....
          /ColorSpace knownoget {
            (   **** Error: A transparency group XObject has a /ColorSpace instead of /CS attribute.\n)
            pdfformaterror
            resolvecolorspace dup setgcolorspace csput
          }
          {
            (   **** Error: Ignoring a transparency group XObject without /CS attribute.\n)
            pdfformaterror
            (               Output may be incorrect.\n) pdfformaterror
            cleartomark //null exit
          }ifelse
        } ifelse
        aload pop setcolor [ currentgray ]
      end grestore
      /GrayBackground exch 3 2 roll
    } if
    dup /TR knownoget {
      dup /Identity eq {
        pop
      } {
        resolvefnproc /TransferFunction exch 3 2 roll
      } ifelse
    } if
    dup /G oget
    dup /BBox oget oforce_array
    1 index /Matrix knownoget {
      oforce_array .bbox_transform 4 array astore
    } if
    /BBox exch 4 2 roll
    % Because we don't execute the group form stream until we find
    % out whether we're actually going to draw through it, we need
    % to save the current gstate with the other parameters, so
    % we can subsequently execute it in the correct graphics state.
    % We need to concatenate the Matrix in this gstate as per the PDF
    % spec 7.5.4 (p. 552 in the PDF 1.7 Ref) (bug 694455).
    gsave
    dup /Matrix knownoget {
      matrix currentmatrix matrix concatmatrix setmatrix
    } if
    /GroupGState gstate currentgstate 6 2 roll
    grestore
    /GroupMat matrix currentmatrix 8 2 roll
%    /GroupExtGState 1 dict
%    10 2 roll

    /.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll
    pop
    .dicttomark
    exit
  } loop
  SMask
} bind executeonly def

% Functions specific to the Device* colorspaces to force the switch to
% the Device* colorspace so that the SMask will not get a CIEBased* colorspace
% in the case when UseCIEColor changes the Device* colorspace to something else.
% Also see the logic in pdf_main.ps:pdfopen that similarly defines these resources.
/forceDefaultCS <<
  {
    currentcolorspace setcolorspace	% this will switch to Device colorspace
  } bind executeonly
  /DeviceGray exch
  /DeviceRGB 1 index
  /DeviceCMYK 1 index
>>
def

% This procedure is called to actually render the soft mask.
/.execmaskgroup {	% <masknum> <paramdict> <formdict> .execmaskgroup -
    % Save our place in PDFfile. Do not use gsave-grestore when creating
    % a soft mask with .begintransparencygroup because high level devices
    % need to modify the graphic state by storing the soft mask ID.
    % Save the ExtGState (//nodict begin) BEFORE changing the colorspace
  //nodict begin
  matrix currentmatrix 4 1 roll
  mark currentcolor counttomark dup 4 add exch roll pop
  currentcolorspace 4 1 roll .getuseciecolor 4 1 roll
  .swapcolors mark currentcolor counttomark dup 4 add exch roll pop currentcolorspace 4 1 roll .swapcolors
  currentuserparams /OverrideICC get 4 1 roll
  mark /OverrideICC //true .dicttomark setuserparams

  % We can't simply set the group's gstate here because
  % we can't use gsave/grestore. So we actually set it
  % in .execgroup. But the matrix needs set here for
  % .begintransparencymaskgroup to correctly work.
  % It might seem we should also set the colorspace
  % in case the group doesn't have one, *but* empirical
  % suggests that is not the case - fts_26_2600.pdf and
  % fts_26_2603.pdf render incorrectly if we set the
  % colrospace
  1 index /GroupMat .knownget { setmatrix } if

  PDFfile fileposition 4 1 roll
        % We have to select the group's color space so that the
        % background color will be interpreted correctly.
        % [save/restore]DefaultCS make sure that the SMask logic sees
        % the Device* spaces, not CIEBased* that UseCIEColor may have
        % established.
  //false .setuseciecolor	% SMask gets processed without UseCIEColor
  dup /Group oget /CS knownoget {
    resolvecolorspace dup setgcolorspace csput
    //true		% use currentcolorspace
  } {
    % Group attributes dictionaries are supposed to contain a /CS
    % entry, but Acrobat apparently also handles a /ColorSpace....
    dup /Group oget /ColorSpace knownoget {
    (   **** Error: A transparency group attribute dictionary has a /ColorSpace instead of /CS attribute.\n)
    pdfformaterror
      resolvecolorspace dup setgcolorspace csput
      //true		% use currentcolorspace
    }
    {
      % inheriting the colorspace -- make sure Device* spaces are not CIEBased
      forceDefaultCS currentcolorspace 0 get .knownget { exec } if
      //false		% no defined colorspace
    } ifelse
  } ifelse
  3 -1 roll dup
  dup 4 1 roll /BBox get aload pop .begintransparencymaskgroup
  exch dup /Resources knownoget { oforce } { 2 dict } ifelse
  3 -1 roll /GroupGState .knownget { 1 index /GroupGState 3 -1 roll put} if
  exch //false resolvestream
  1 index exch

  %% Get the current colour space and colour values (as an array), we need to pass these to .execgroup
  %% as well, so that it can restore them, in case the colour space gets changed by transparency
  %% graphics state stuff.
  mark currentcolor counttomark array astore exch pop
  currentcolorspace 4 2 roll

  .execgroup
  % We have to remove these in case the Form XObject is subsequently used as
  % a form rather than a group - they remain in the paramdict for the SMask
  % so this will all still work if the SMask is re-evaluated.
  /GroupGState undef

  .endtransparencymask
  PDFfile exch setfileposition
  mark exch /OverrideICC exch .dicttomark setuserparams
  .swapcolors setcolorspace setcolor .swapcolors
  .setuseciecolor setcolorspace setcolor
  setmatrix
  end	% restore colorspace, color and ExtGState (end)
  .currentSMask /Processed //true put % special setting to tell us it has been rendered
} bind executeonly def

% Paint a Form+Group XObject, either for a transparency mask or for a Do.
/.execgroup {		% [colour values] <colour space> <resdict> <stream> .execgroup -
  pdfemptycount 3 1 roll
  /pdfemptycount count 5 sub store
  gsave //nodict begin

  % We have to set the gstate correctly for lazy evaluation of a softmask group.
  % we also must restore the color(space) as setup in .execmaskgroup or paintformgroup.
  % This stuff must be done here, as .execmaskgroup can't use gsave/grestore to
  % manipulate the gstates, due to the requirements of .begintransparencymaskgroup.
  % We also must set the ExtGState values.
  % It may seem redundant to do the color(space) twice (once here and once in
  % .execmaskgroup) but we have to set it in .execmaskgroup for the background
  % color and set it here once in the correct gstate.
  1 index
  /GroupGState .knownget { setgstate } if

  newpath //null SMask
  1 CA 1 ca
  /Compatible .setblendmode
        % Execute the body of the Form, similar to DoForm.
  pdfopdict

  %% Restore the colour space (passed in on the stack) and current colour
  %%
  6 -2 roll
  setcolorspace
  aload pop setcolor

  .pdfruncontext
  end grestore

  % check for extra garbage on the operand stack and clean it up
  count pdfemptycount sub dup 0 ne {
    (   **** Error: Transparency Group, Form XObject execution corrupted the stack.\n) pdfformaterror
    (               Output may be incorrect.\n) pdfformaterror
    PDFSTOPONERROR {
       /.execgroup cvx /rangecheck signalerror
    } {
      dup 0 gt {
        { pop } repeat
      }{
        pop
      } ifelse
    } ifelse
  } {
    pop
  } ifelse

  /pdfemptycount exch store
} bind executeonly def

/.beginformgroup {	% groupdict bbox .beginformgroup -
  exch mark exch			% bbox mark groupdict
  dup /CS knownoget { resolvecolorspace dup setgcolorspace /CS exch 3 2 roll} if
  dup /I knownoget { /Isolated exch 3 2 roll } if
  dup /K knownoget { /Knockout exch 3 2 roll } if
  pop .dicttomark
                % Stack: bbox paramdict
  exch aload pop
  .begintransparencygroup
} bind executeonly def

/.beginpagegroup {	% groupdict bbox .beginformgroup -
  currentcolorspace 3 1 roll
  exch mark exch			% bbox mark groupdict
  dup /CS knownoget { resolvecolorspace dup setgcolorspace /CS exch 3 2 roll} if
  dup /I knownoget { /Isolated exch 3 2 roll } if
  dup /K knownoget { /Knockout exch 3 2 roll } if
  pop .dicttomark
                % Stack: bbox paramdict
  exch aload pop
  .begintransparencypagegroup
  setcolorspace
} bind executeonly def

% .paintgroupform implements the Form PaintProc in the case where the
% Form XObject dictionary includes a Group key.  See .paintform below.
/.paintgroupform {	% <resdict> <stream> <formdict> .paintgroupform -
  %% Pass the current color space, and an array with the current color vales
  %% as arguments to .execgroup
  mark currentcolor counttomark array astore exch pop
  currentcolorspace 5 2 roll
  dup /Group oget dup type /dicttype eq {
    exch /BBox oget dup type /arraytype eq {
                % Stack: resdict stream groupdict bbox
      .beginformgroup
      .execgroup
      .endtransparencygroup
    }{
      (   **** Error: Form XObject has a BBox entry with an invalid type.\n) pdfformaterror
      (               Ignoring transparency Group, output may be incorrect.\n) pdfformaterror
      pop pop pop pop pop pop
    } ifelse
  } {
    (   **** Error: Form XObject has a Group entry with an invalid type.\n) pdfformaterror
    (               Ignoring transparency Group, output may be incorrect.\n) pdfformaterror
    pop pop pop pop pop pop
  } ifelse
} bind executeonly def

% Make an ImageType 103 (soft-masked) image.
/makesoftmaskimage {	% <datasource> <imagemask> <SMask> makesoftmaskimage
                        %   <datasource> <imagemask>, updates currentdict =
                        %   imagedict
                % See the ImageType 3 case of makemaskimage below.
                % SMask is a stream, another Image XObject.
                % Stack: datasource imagemask(false) smaskstreamdict
  PDFfile fileposition exch
  dup /Matte knownoget { /Matte exch def } if
  dup length dict makeimagedict pop
                % In order to prevent the two data sources from being
                % aliased, we need to make at least one a reusable stream.
                % We pick the mask, since it's smaller (in case we need to
                % read all its data now).
                % Stack: datasource imagemask(false) savedpos
                % maskdict is currentdict
  /DataSource DataSource mark
    /Intent 1
    /AsyncRead //true
  .dicttomark {.reusablestreamdecode} stopped {pop} if def
  PDFfile exch setfileposition
  currentdict end currentdict end
  5 dict begin
  /ImageType 103 def
  /DataDict exch def
  dup /InterleaveType 3 put
  DataDict /Matte knownoget {
    /Matte exch def
  } if
  .currentalphaisshape
  { /ShapeMaskDict } { /OpacityMaskDict } ifelse exch def
  /ColorSpace DataDict /ColorSpace get def
} bind executeonly def

% ---------------- Color setting ---------------- %

/01_1 [0 1] readonly def
/01_3 [0 1 0 1 0 1] readonly def
/01_4 [0 1 0 1 0 1 0 1] readonly def

% The keys here are resolved (PostScript, not PDF) color space names.
/csncompdict 9 dict begin
  /DeviceGray { pop 1 } bind executeonly def
  /DeviceRGB { pop 3 } bind executeonly def
  /DeviceCMYK { pop 4 } bind executeonly def
  /CIEBasedA //DeviceGray def
  /CIEBasedABC //DeviceRGB def
  /CalGray //DeviceGray def
  /CalRGB //DeviceRGB def
  /Lab //DeviceRGB def
  /ICCBased { 1 oget /N oget } bind executeonly def
  /Separation //DeviceGray def
  /DeviceN { 1 oget length } bind executeonly def
  /Indexed  //DeviceGray def
currentdict end readonly def

% <colorspace> csncomp <n>
/csncomp {
  dup dup type /arraytype eq { 0 oget } if
  //csncompdict exch get exec
} bind executeonly def

currentdict /csncompdict undef

/ICCBased-resolve {
  PDFfile fileposition exch
  dup dup 1 oget
  mark exch { oforce } forall .dicttomark
  dup dup //true resolvestream
  {
    /ReusableStreamDecode filter
  } stopped
  {
    pop null
%    (   **** Error: Failed to read ICC profile for an ICCBased colour space.\n) pdfformaterror
%    (               Falling back to a colour space determined by the /N value.\n) pdfformaterror
  }if
  /DataSource exch put
  dup /.hash 0 put	% placeholder for use by seticc icc_profile_cache key
  % Check that the number of components (/N) defined in the ICCBased
  % dictionry matches the actual profile. Bug #696120
  dup /N get
  1 index
  %% If we get an error reading the profile, just assume that /N is correct
  %% If its genuinely faulty we will use an alternate based on /N.
  {.numicc_components} stopped {pop dup} if
  dup 3 -1 roll ne {
    %% /N and the actual number of components don't match. Ensure
    %% that we have a valid number of components from the ICC
    %% profile. Certain kinds of profile can't determine the numebr of components
    %% and in ths case we must not override the /N value.
    dup 0 gt {
         (   **** Error: ICCbased space /N value does not match the ICC profile.\n) pdfformaterror
         (                 Using the number of channels from the profile.\n) pdfformaterror
         (                 Output may be incorrect.\n) pdfformaterror
        1 index dup /N get /OrigN exch put
        1 index exch /N exch put
    }{
      pop
    } ifelse
  } {
    pop
  } ifelse

  1 exch put
  exch PDFfile exch setfileposition
  % Resolve alternate color space
  dup 1 get			% Get colorspace dictionary
  dup /Alternate .knownget {	% Check for alternate color space
    oforce resolvecolorspace /Alternate exch put 	% resolve and replace
  } {
    pop 			% remove colorspace dictionary
  } ifelse
} bind executeonly def

/csrdict 13 dict begin
  /DeviceGray { } bind executeonly def
  /DeviceRGB { } bind executeonly def
  /DeviceCMYK { } bind executeonly def

  /CalGray { 1 oget [ exch /CalGray exch ] } bind executeonly def
  /CalRGB { 1 oget [ exch /CalRGB exch ] } bind executeonly def
  /Lab { 1 oget [ exch /Lab exch ] } bind executeonly def

  /CalCMYK {
    pop /DeviceCMYK		% not defined by Adobe
  } bind executeonly def

  /ICCBased {
    dup 1 get type /dicttype ne {	% don't resolve more than once
      ICCBased-resolve
    } if
  } bind executeonly def

  /Separation {
    aload pop exch oforce resolvecolorspace
                % Contrary to PDF manuals up to v.1.5, Acrobat Distiller 3.01
                % can use /Identity name here instead of a function.
    exch oforce resolveidfnproc

    %% Make sure the ink name is not an indirect object....
    3 -1 roll oforce 3 1 roll

    4 array astore
  } bind executeonly def

  /DeviceN {
    [ exch aload pop ]			% Copy into a new array
    dup dup 1 oget			% Resolve Names array
    [ exch { oforce } forall ]		% resolve each of the names
    1 exch put
    dup dup 2 oget resolvecolorspace
    2 exch put
    dup dup 3 oget resolvefnproc
    3 exch put
    dup length 4 gt {			% Check for attributes dict
      dup dup 4 oget			% devn_array devn_array attr_dict
      dup /Colorants knownoget		% Check for Colorants Dict
        {	% Create a new attribute dict with only a Colorants dict entry.
                % Resolve all of the Colorant dict entries.  This is needed
                % to prevent a conflict if we attempt to resolve the tint
                % transform functions of the Colorant color spaces multiple
                % times.
          exch pop			% Remove old attributes dict
          << exch			% Start new attributes dict
                % Build new Colorants dict with resolved entries
          << exch { oforce resolvecolorspace } forall >>
          /Colorants exch >>		% Finish new attributes dict
        } if
                            % devn_array devn_array <<..attributes..>>
      1 index 4 oget /Process knownoget {
        dup /ColorSpace knownoget {
          1 index exch resolvecolorspace /ColorSpace exch put
        } if
                            % devn_array devn_array <<..attributes..>> <<..Process..>>
        1 index
        /Process 3 -1 roll
        put
      } if
      4 exch put			% Put resolved or new attributes dict
    } if
  } bind executeonly def

  /Indexed {
    aload pop
    %% Resolve 'hival' in case it is an indirect reference. This is kind of
    %% dumb, it just makes the file bigger, but it *is* legal.
    3 1 roll oforce 3 -1 roll

    1 index -1 eq {
      exch pop 255 exch
      (   **** Error: Highest color index given as -1. Assuming this actually means 255.\n) pdfformaterror
      (               Output may be incorrect.\n) pdfformaterror
    } if
    3 -1 roll oforce resolvecolorspace
                % Stack: /Indexed hival lookup basespace
                % If the underlying space is a Lab space, we must scale
                % the output of the lookup table as part of DecodeABC.
    dup dup type /arraytype eq { 0 get } if /CIEBasedABC eq {
      dup 1 get /DecodeLMN known {
        1 get dup length dict copy
        begin /DecodeABC [ 0 2 4 {
          RangeABC 1 index 1 add get RangeABC 2 index get sub /mul load
          RangeABC 3 index get /add load
          DecodeABC 6 -1 roll 2 idiv get [ 6 1 roll aload pop ] cvx
        } for ] def
        /RangeABC //01_3 def
        currentdict end /CIEBasedABC exch 2 array astore
      } if
    } if
    3 1 roll  % Stack: /Indexed csp comp table
    oforce dup type /stringtype ne {
                % The color lookup table is a stream.
                % Get its contents.  Don't lose our place in PDFfile.
                % Stack: /Indexed basespace hival lookup
        PDFfile fileposition 5 1 roll
        dup /Filter oknown not { % For Bug691941.pdf and similar lossage
          dup /Length knownoget not { 0 } if
        } {
          0
        } ifelse
                % Stack: filepos /Indexed basespace hival lookup Length
        2 index 1 add
                % Stack: filepos /Indexed basespace hival lookup Length len
        4 index csncomp mul .max string
                % Stack: filepos /Indexed basespace hival lookup (...)
        exch //true resolvestream
        1 index readstring not {
          % The string is padded with 0s
          (   **** Error: Short look-up table in the Indexed color space was padded with 0's.\n)
          pdfformaterror
          (               Output may be incorrect.\n) pdfformaterror
        } if
        pop
                % Stack: filepos /Indexed basespace hival (...)
        PDFfile 6 -1 roll setfileposition
    } if
    4 array astore
                % Stack: [filepos /Indexed basespace hival (...)]
                % Replace the PDFColorSpace with the Indexed space if needed.
    dup 1 get
    dup type /arraytype eq {
      dup length 2 ge {
        dup 1 get type /dicttype eq {
          dup 1 get /PDFColorSpace known {
            dup 1 get /PDFColorSpace 3 index put
          } if
        } if
      } if
    } if pop
  } bind executeonly def

  /I { % Bug 689815
    (   **** Error: The name /Indexed cannot be abbreviated to /I in the color space\n)
    pdfformaterror
    (               Output may be incorrect.\n) pdfformaterror
    dup 0 /Indexed put
    //Indexed exec
  } bind executeonly def

  /Pattern {
    dup type /nametype ne {
      dup length 1 gt {
        1 oget resolvecolorspace
        /Pattern exch 2 array astore
      } if
    } if
  } bind executeonly def

currentdict end readonly def

/cssubst {		% <csname> cssubst <cspace'> true
                        % <csname> cssubst false
  dup resolvecolorspace
  dup 1 index ne { exch pop //true } { pop pop //false } ifelse
} bind executeonly def

/csnames mark
  /DeviceGray dup  /DeviceRGB dup  /DeviceCMYK dup  /Pattern dup
.dicttomark readonly def
/csresolve {		% <csresourcename> csresolve <cspace> <true> | <false>
  dup type /nametype ne {
    (\n   **** Error: CS/cs (setcolorspace) operand not a name: ) pdfformaterror
    dup stderrfile dup 3 -1 roll write==only flushfile
    ( ****\n) pdfformaterror
    (                 Output may be incorrect.\n) pdfformaterror
    dup type /arraytype eq {	% Adobe InDesign + PDF Library has array
      resolvecolorspace
    } if //true
  } {
    dup Page /ColorSpace rget {
      exch pop resolvecolorspace //true
    } {
      //csnames 1 index known {
        //true
      } {
        (   **** Error: Undefined space resource: /)
        exch .namestring concatstrings (\n) concatstrings pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
        //false
      } ifelse
    } ifelse
  } ifelse
} bind executeonly def

/resolvecolorspace {	% <cspace> resolvecolorspace <cspace'>
  dup type /dicttype eq {
      dup /N known {
      (   **** ICCBased color space is a bare stream dictionary\n) pdfformatwarning
      [ /ICCBased 3 -1 roll ] ICCBased-resolve exec
      //false
    } {
      dup /ColorSpace knownoget {
        (   **** Error: unrecognised color space <</ColorSpace /Device...>>\n) pdfformaterror
        (                 Output may be incorrect.\n) pdfformaterror
        exch pop //true
      } {
        //true
      } ifelse
    } ifelse
  } {
    //true
  } ifelse {
    dup dup type /arraytype eq { 0 get } if
    dup type /packedarraytype eq {exch pop exec dup} if

    //csrdict exch .knownget  {
      exec dup type /nametype ne { dup length 1 eq { 0 get } if } if
    } {
      dup type /nametype eq {
        csresolve not { /DeviceRGB } if   % Arbitrary
      } {
        csset exch pop
      } ifelse
    } ifelse
  } if
} bind executeonly def

/scresolve {	% <c0> ... scresolve <multi>
                % We can't really make sc[n] and SC[N] work, because
                % the color space information isn't available at
                % conversion time; so we hack it by assuming that
                % all the operands on the stack are used, and that
                % if the top operand is a name, it's a Pattern resource.
  dup type /nametype eq
    { Page /Pattern rget { resolvepattern } { //null } ifelse }
  if
  dup type /dicttype eq {
                % Check the PaintType, if any (shading patterns don't
                % have one).
    dup /PaintType knownoget { 2 eq } { //false } ifelse
  } {
    .pdfcount 1 gt
  } ifelse
} bind executeonly def

%% Bug #696017 When we begin a text block, we switch to a special set of marking operations
%% for paths, these ops don't use the current CTM, but the 'SavedTextMatrix', in order to
%% correctly position marks which are illegally present inside a text block. But, if we are
%% executing a PaintProc (eg for a pattern) we *don't* want to do that or the pattern will be wrong.
%% So we moved the .pdfpaintproc to .actual_pdfpaintproc, and redefined .pdfpaintproc to test
%% the current value of /m. We always switch to the regular marking operations, but if the definition
%% of /m at the start of the PaintProc was a special text version, then we switch back to that after we
%% finished running the PaintProc.

/.actual_pdfpaintproc {         % <patdict> <resdict> .pdfpaintproc -
  PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Begin PaintProc) print dup === flush } if } if
  PDFfile fileposition 3 1 roll
  q
  1 index /PaintType oget 1 eq {
    % For colored patterns, set default fill and stroke colors.
    0 g 0 G
  } {
    % For uncolored patterns, we have to unbind the current
    % color and color space before running the PaintProc.
    % Not true since moving the ExtGState parameters into the gstate.
    %    //null sc1 //null SC1
  } ifelse

  % Save old values on opstack, set pdfemptycount to new value.
  pdfemptycount countdictstack mark

  %% We can't simply 'def' into the dictionary saved by 'q' above, we need to
  %% call gput to copy it and store inside it. Stupid or what....
  /pdfemptycount count 3 sub gput 5 3 roll
  %
  % Stack: ... <old emptycount> <dictcount> mark <patdict> <resdict>
  %                                                  |
  %           New empty count points here -----------+

  exch //false resolvestream pdfopdict .pdfruncontext
  cleartomark

  //false
  { countdictstack
    2 index le { exit } if
    currentdict /n known not or
    currentdict /n known currentdict /self known or{
      Q
    }{
      (\n   **** Error: File has unbalanced q/Q operators \(too many Q's\)\n               Output may be incorrect.\n)
      //pdfdict /.Qqwarning_issued .knownget
      {
        {
          pop
        }
        {
          currentglobal //pdfdict gcheck .setglobal
          //pdfdict /.Qqwarning_issued //true .forceput
          .setglobal
          pdfformaterror
        } executeonly ifelse
      } executeonly
      {
        currentglobal //pdfdict gcheck .setglobal
        //pdfdict /.Qqwarning_issued //true .forceput
        .setglobal
        pdfformaterror
      } executeonly ifelse
      end
    } executeonly ifelse
  } executeonly loop
  {
    (\n   **** Error: File has unbalanced q/Q operators \(too many q's\)\n               Output may be incorrect.\n)
    //pdfdict /.Qqwarning_issued .knownget
    {
      {
        pop
      }
      {
        currentglobal //pdfdict gcheck .setglobal
        //pdfdict /.Qqwarning_issued //true .forceput
        .setglobal
        pdfformaterror
      } executeonly ifelse
    } executeonly
    {
      currentglobal //pdfdict gcheck .setglobal
      //pdfdict /.Qqwarning_issued //true .forceput
      .setglobal
      pdfformaterror
    } executeonly ifelse
  } executeonly if
  pop

  % restore pdfemptycount
  /pdfemptycount exch def

  Q
  PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%End PaintProc) print dup === flush } if } if
  PDFfile exch setfileposition
} bind executeonly odef

/.pdfpaintproc {
    %% Get the /m from pdfopdict (must be present)
    %% and check its a packedarray
    pdfopdict /m get dup type /packedarraytype eq {
      %% The non-text version of /m is executeonly, so if we can't read it, its not a text block.
      dup rcheck {
        %% get the initial element of the packedarray
        %% and check its a name
        0 get dup type /nametype eq {
          %% If the name is inside_text_m then we are in a text block
          /inside_text_m eq
          }{
             pop //false
          } ifelse
        }{
          pop //false
        } ifelse
    }{
      pop //false
    } ifelse
    %% rearrange the operands, move the boolean to the back
    3 1 roll
    %% Uncopnditionally use the normal marking ops
     switch_to_normal_marking_ops
    .actual_pdfpaintproc
    %% If we were in a text block, restore the text marking ops.
    {
      switch_to_text_marking_ops
    } if
}bind executeonly odef

/resolvepattern {	% <patternstreamdict> resolvepattern <patterndict>
                % Don't do the resolvestream now: just capture the data
                % from the file if necessary.
  dup length dict copy
  dup /FilePosition .knownget {
    1 index /File get dup fileposition 3 1 roll
                % Stack: dict savepos pos file
    dup 3 -1 roll setfileposition
    dup 3 index /Length knownoget {
      dup 65535 le {
        dup 0 eq {
          pop pop ()
        } {
          string readstring pop
        } ifelse
      } {
        () /SubFileDecode filter /ReusableStreamDecode filter
      } ifelse
    } {
      0 (endstream) /SubFileDecode filter /ReusableStreamDecode filter
    } ifelse
                % Stack: dict savepos file string
    3 1 roll exch setfileposition
    1 index /File 3 -1 roll put
    dup /FilePosition undef
  } if
  dup /Shading knownoget {
    resolveshading 1 index /Shading 3 -1 roll put
  } if
  dup /PaintProc [
                % Bind the resource dictionary into the PaintProc.
    2 index /Resources knownoget { oforce } { 0 dict } ifelse
    /.pdfpaintproc cvx
  ] cvx put
  dup /BBox 2 copy knownoget { normrect FixPatternBBox put } { pop pop } ifelse
  dup /.pattern_uses_transparency  1 index patternusestransparency put
  PDFDEBUG { //pdfdict /PDFSTEPcount .knownget { 1 le } { //true } ifelse { (%Pattern: ) print dup === flush } if } if
} bind executeonly def

/ignore_color_op  (   **** Error: Ignoring a color operation in a cached context.\n               Output may be incorrect.\n) readonly def

drawopdict begin
  /g  { .incachedevice { % Bug 689302
          pop //ignore_color_op pdfformaterror
        } {
          /DeviceGray cssubst { cs sc1 } { g } ifelse
        } ifelse
      } bind executeonly def

  /rg { .incachedevice {
          pop pop pop //ignore_color_op pdfformaterror
        } {
          /DeviceRGB cssubst { cs sc* } { rg } ifelse
        } ifelse
      } bind executeonly def

  /k  { .incachedevice {
          pop pop pop pop //ignore_color_op pdfformaterror
        } {
          k
        } ifelse
      } bind executeonly def

  /cs { .incachedevice {
          pop //ignore_color_op pdfformaterror
        } {
          csresolve { cs } if
        } ifelse
      } bind executeonly def

  /sc { .incachedevice {
          .pdfcount { pop } repeat //ignore_color_op pdfformaterror
        } {
          scresolve 1 index //null eq {
            pop pop
            //ignore_color_op pdfformaterror
          } {
            { sc*_and_set } { sc1_and_set } ifelse
          } ifelse
        } ifelse
      } bind executeonly def

  /scn /sc load def

  /G  { .incachedevice {
          pop //ignore_color_op pdfformaterror
        } {
          /DeviceGray cssubst { CS SC1 } { G } ifelse
        } ifelse
      } bind executeonly def

  /RG { .incachedevice {
          pop pop pop //ignore_color_op pdfformaterror
        } {
          /DeviceRGB cssubst { CS SC* } { RG } ifelse
        } ifelse
      } bind executeonly def

  /K  { .incachedevice {
          pop pop pop pop //ignore_color_op pdfformaterror
        } {
          K
        } ifelse
      } bind executeonly def

  /CS { .incachedevice {
          pop //ignore_color_op pdfformaterror
        } {
          csresolve { CS } if
        } ifelse
      } bind executeonly def

  /ri { .incachedevice {
          pop //ignore_color_op pdfformaterror
        } {
          ri
        } ifelse
      } bind executeonly def

  /SC { .incachedevice {
          .pdfcount { pop } repeat //ignore_color_op pdfformaterror
        } {
          scresolve 1 index //null eq {
            pop pop
            //ignore_color_op pdfformaterror
          }{
            { SC*_and_set } { SC1_and_set } ifelse
          }ifelse
        } ifelse
      } bind executeonly def

  /SCN /SC load def
end

currentdict /ignore_color_op undef

% ---------------- Paths ---------------- %

drawopdict begin
                        % Path construction
  /m { { moveto }  stopped { count pdfemptycount sub 2 .min { pop } repeat 0 0 moveto } if } bind executeonly def
  /l { { lineto }  stopped { count pdfemptycount sub 2 .min { pop } repeat } if } bind executeonly def
  /c { { curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bind executeonly def

  /v { count pdfemptycount sub 4 ge {
         { currentpoint 6 2 roll curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat  } if
       } {
         count pdfemptycount sub { pop } repeat
       } ifelse
     } bind executeonly def
  /y { { 2 copy curveto } stopped { count pdfemptycount sub 6 .min { pop } repeat } if } bind executeonly def

  /re {
   4 2 roll moveto  exch dup 0 rlineto  0 3 -1 roll rlineto  neg 0 rlineto
   closepath
  } bind executeonly def

  /h { closepath } bind 0 get def
                        % Path painting and clipping
  /n { n } executeonly def
  /S { S } executeonly def
  /s { s } executeonly def
  /f { f } executeonly def
  /f* { f* } executeonly def
  /B { B } executeonly def
  /b { b } executeonly def
  /B* { B* } executeonly def
  /b* { b* } executeonly def
  /W { W } executeonly def
  /W* { W* } executeonly def

  /sh_save 1 array def

  /do_shade {
    0 .setoverprintmode
    { dup /.shading .knownget {
        exch pop
      } {
       .buildshading_and_shfill
      } ifelse
    } stopped {
      pop
      (   **** Error: Ignoring invalid smooth shading object, output may be incorrect.\n)
      pdfformaterror
    } if
  } bind executeonly def

  /sh {
      OFFlevels length 0 eq {
        setsmaskstate resolvesh
        //sh_save 0 save put
        PDFusingtransparency {
          gsave
          dup /BBox knownoget {
            { oforce } forall
            4 2 roll moveto exch 0 lineto 0 exch lineto closepath
          } {
            clippath
          } ifelse
          % If we get an error, just emit an empty box
          { pathbbox } stopped { 0 0 0 0 } if
          4 array astore
          grestore
          //null
          setup_trans
          //do_shade exec
          teardown_trans
        } {
          //do_shade exec
        } ifelse
        //sh_save 0 get restore
      } {
        pop
      } ifelse
    } bind executeonly def
  currentdict dup /sh_save undef /sh_group undef
end

% ---------------- XObjects ---------------- %

/xobjectprocs mark		% <dict> -proc- -
  /Image { DoImage } executeonly
  /Form { DoForm } executeonly
  /PS { DoPS } executeonly
.dicttomark readonly def

% Note that the keys in defaultdecodedict are resolved (PostScript, not PDF)
% color space names.
/defaultdecodedict mark
  /DeviceGray { pop //01_1 } bind executeonly
  /DeviceRGB { pop //01_3 } bind executeonly
  /DeviceCMYK { pop //01_4 } bind executeonly
  /CIEBasedA { 1 get /RangeA knownoget not { //01_1 } if } bind executeonly
  /CIEBasedABC { 1 get /RangeABC knownoget not { //01_3 } if } bind executeonly
  /CalGray { pop //01_1 } bind executeonly
  /CalRGB { pop //01_3 } bind executeonly
  /Lab { 1 get /Range knownoget not { [-100 100 -100 100] } {aload pop 0 100 6 2 roll 6 array astore}ifelse } bind executeonly
  /ICCBased {
     1 oget dup /Range knownoget {
       exch pop
     }{
       /N get [ exch {0 1} repeat ] readonly
     } ifelse
  } bind executeonly
  /Separation { pop //01_1 } bind executeonly
  /DeviceN {
    1 oget length [ exch {0 1} repeat ] readonly
  } bind executeonly
  /Indexed {
    pop [ 0 1 BitsPerComponent bitshift 1 sub ]
  } bind executeonly
.dicttomark readonly def

/checkaltimage {	% <resdict> checkaltimage <resdict[']>
  Printed {
    dup /Alternates knownoget {
      {
        dup /DefaultForPrinting knownoget {
          {
            /Image oget exch pop exit
          } {
            pop
          } ifelse
        } {
          pop
        } ifelse
      } forall
    } if
  } if
} bind executeonly def

% <string> <index> getu16 <integer>
/getu16 {
  2 copy get 8 bitshift 3 1 roll 1 add get add
} bind executeonly def

% <string> <index> getu32 <integer>
/getu32 {
  2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
} bind executeonly def

/jp2_csp_dict mark
  12 { /DeviceCMYK }       % CMYK
  14 { [ /Lab << /WhitePoint [ 0.9505 1 1.0890 ] readonly >> ] }              % LAB, WhitePoint == D65
  16 { /sRGBICC /ColorSpace findresource } bind executeonly
  17 { /sGrayICC /ColorSpace findresource } bind executeonly
  18 3 index               % YCC is converted to RGB
% 19                       % CIEJab not supportec by PDF 1.7
  20 { /esRGBICC /ColorSpace findresource } bind executeonly                   % e-sRGB
  21 { /rommRGBICC /ColorSpace findresource} bind executeonly                  % ROMMRGB
  24 { /esRGBICC /ColorSpace findresource } bind executeonly                   % e-sYCC
.dicttomark readonly def

% Process jp2 blocks (aka boxes). All procedures have the signature
% <file> <length> -> ... <file> <flush_length>
/jp2_tag_dict 10 dict begin

  /jp2h { % descend into a sub-stream, don't return.
    () /SubFileDecode filter 0
  } bind executeonly def

  /ihdr {
    14 sub                                   % file len-14
    1 index (1234567890abcd) readstring pop  % file len-14 (14)
    /JPXComponents 1 index 8 getu16          % file len-14 (14) /JPXComponents NC
    def                                      % file len-14 (14)
    10 get
    %% If the BPC is 255 then each component has variable depth
    %% we can't handle this, but JasPer is known to produce
    %% images whcih declare this, but are actually all equal, we cater
    %% for that in the bpcc box below.
    dup 16#FF eq not {
      16#7F and 1 add
      dup 12 eq { pop 16 } if
      /BitsPerComponent exch def               % file len-14
    } {pop} ifelse
  } bind executeonly def

  %% if the ihdr has a BPC of 255 then we get a bpcc box which
  %% gives the bpc for each component individually. We cannot
  %% actually deal with differing component depths, but it
  %% seems JasPer produces images with this box where all the
  %% component depths are in fact the same.
  /bpcc {
    JPXComponents sub
    1 index JPXComponents string readstring pop
    dup 0 get /BitsPerComponent exch def
    1 1 JPXComponents 1 sub {
      1 index exch get BitsPerComponent eq not {
        (   **** Error: JPX image colour channels do not all have the same colour depth\n)
        pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
      } if
    } for

    pop
    /BitsPerComponent BitsPerComponent 1 add def
  } bind executeonly def

  /colr {
    currentdict /ColorSpace known not {
      3 sub
      1 index (123) readstring pop      % file len-3 (3)
      0 get dup 1 eq {
        pop 4 sub                          % file len-7
        1 index (1234) readstring pop    % file len-16 (4)
        0 getu32                           % file len-16 enum
        //jp2_csp_dict exch .knownget {
          exec /ColorSpace exch def        % file len-7
        } {
          (   **** Error: Unknown enumerated color space in JPX stream.\n)
          pdfformaterror
          (               Output may be incorrect.\n) pdfformaterror
        } ifelse
      } {
        dup 2 eq exch 3 eq or {
          1 index exch () /SubFileDecode filter /ReusableStreamDecode filter
          /JPXICC exch def
          0                                % file 0
        } {
          (   **** Error: Unknown color space method in JPX stream.\n)
          pdfformaterror
          (               Output may be incorrect.\n) pdfformaterror
        } ifelse
      } ifelse
    } if
  } bind executeonly def

  % Palette colors are decoded by the library.
  /pclr {
    4 sub
    1 index (1234) readstring pop
    3 get 16#7F and 1 add
    /BitsPerComponent exch def
  } bind executeonly def

  /cdef {
    pop
    dup (12) readstring pop
    0 getu16 {
      dup (123456) readstring pop
      2 getu16
      dup 3 lt {
        { /JPXColors /JPXOpacity /JPXPremult } exch get
          currentdict 1 index .knownget { 1 add } { 1 } ifelse def
      } {
        pop
      } ifelse
    } repeat
    0
  } bind executeonly def

currentdict end readonly def

% Parse jp2 file format to get color space and image depth info.
% <file> get_jp2_csp -
/get_jp2_csp {
  {
    dup (01234567) readstring pop        % f (LBoxTBox)
    dup length 8 lt {
      pop exit
    } if
    dup 4 4 getinterval exch             % f (TBox) (LBoxTBox)
    0 getu32                             % f (TBox) LBox
    dup 0 eq {
      pop pop exit % cannot happen
    } {
      dup 1 eq {
        pop 1 index (01234567) readstring pop
        4 getu32                         % f (TBox) LBox
        16 sub
      } {
        8 sub
      } ifelse
    } ifelse                             % f (TBox) LBox-8..16

    PDFDEBUG {
      2 copy 2 packedarray //== exec            % f (TBox) LBox-8..16
    } if

    //jp2_tag_dict 3 -1 roll .knownget {
      exec
    } if                                  % f flush

    dup 0 ne {
      1 index exch                        % f f flush
      () /SubFileDecode filter flushfile % skip unwanted blocks
    } {
      pop
    } ifelse
  } loop
  pop
} bind executeonly def

currentdict /jp2_tag_dict .undef
currentdict /jp2_csp_dict .undef

% Add a key-value pair to the last /DecodeParms dictionary
% Copy the objects to avoid spoiling shared ones.
% <resdict> <key> <value> -> <resdict>
/add-to-last-param {
  2 index /DecodeParms knownoget {
    dup {} eq {
      pop //false
    } {
      //true
    } ifelse
  } {
    //false
  } ifelse {
    dup type /arraytype eq {
      [ exch { oforce } forall
        dup //null eq { pop 1 dict } if
      ]
      dup dup length 1 sub get           % <resdict> <key> <value> []   <<>>
    } {
      dup length 1 add dict copy dup     % <resdict> <key> <value> <<>> <<>>
    } ifelse
    4 2 roll put                         % <resdict> obj
  } {
                                         % <resdict> <key> <value>
    mark 3 1 roll .dicttomark            % <resdict> obj
    1 index /Filter knownoget {
      dup type /arraytype eq {
        length array                     % <resdict> obj [...]
        dup dup length 1 sub             % <resdict> obj [...] [...] len-1
        4 -1 roll put                    % <resdict> [... obj]
      } {
        pop
      } ifelse
    } if
  } ifelse
  1 index exch
  /DecodeParms exch put                  % <resdict>
} bind executeonly def

% Add a key-value pair to the all the /DecodeParms
% dictionaries (i.e. handle the array)
% Copy the objects to avoid spoiling shared ones.
% <resdict> <patch dict> -> <resdict>
/add-to-all-params {
  1 index                         % <resdict> <patch dict> <resdict>
  /Filter knownoget
  {                               % <resdict> <patch dict> </name or [array]>
    dup type /arraytype eq
    {
      length                      % <resdict> <patch dict> <len>
      dup 0 gt
      {
        2 index /DecodeParms
        knownoget
        {
          oforce_recursive          % resolve indirect references
          exch pop                  % <resdict> <patch dict> [array]
          [
            exch
            {
              dup type /dicttype eq
              {
                mark exch {} forall .dicttomark
              }
              {
                pop 1 dict
              } ifelse
            } forall
          ]                         % <resdict> <patch dict> [array]
        }
        {                           % <resdict> <patch dict> <len>
          % create an array of dictionaries
          [
            0 1 4 -1 roll 1 sub
            { pop 1 dict } for
          ]
                                    % <resdict> <patch dict> [array]
        } ifelse
        dup                         % <resdict> <patch dict> [array] [array]
        {                           % <resdict> <patch dict> [array] [dict]
          2 index                   % <resdict> <patch dict> [array] [dict] <patch dict>
          {                         % <resdict> <patch dict> [array] [dict] </key> <value>
            2 index                 % <resdict> <patch dict> [array] [dict] </key> <value> [dict]
            3 1 roll
            put
          } forall
          pop
        } forall
                                    % <resdict> <patch dict> [array]
        exch pop
                                  % <resdict> [dict/array]
        1 index exch /DecodeParms exch put
      }
      {
        pop pop
      } ifelse
    }
    {                             % <resdict> <patch dict> </name>
      pop
      1 index
      /DecodeParms knownoget
      {
        oforce_recursive
        dup type /dicttype eq
        {
          mark exch {} forall .dicttomark
        }
        {
          pop 1 dict
        } ifelse
      }
      {
        1 dict
      } ifelse                    % <resdict> <patch dict> [dict]

      1 index                     % <resdict> <patch dict> [dict] <patch dict>
      {                           % <resdict> <patch dict> [dict] </key> <value>
        2 index
        3 1 roll put
      } forall
      exch pop
                                  % <resdict> [dict/array]
      1 index exch /DecodeParms exch put
    } ifelse
  }
  {pop} ifelse
} bind def

/last-ditch-bpc-csp {
  currentdict /BitsPerComponent oknown not {
    (   **** Error: image has no /BitsPerComponent key; assuming 8 bit.\n)
   pdfformaterror
    (               Output may be incorrect.\n) pdfformaterror
    /BitsPerComponent 8 def
  } if

  currentdict /ColorSpace knownoget not {
    dup /ColorSpace knownoget not {
      (   **** Error: image has no /ColorSpace key; assuming /DeviceRGB.\n)
      pdfformaterror
      (               Output may be incorrect.\n) pdfformaterror
      /DeviceRGB
    } if
  } if
  resolvecolorspace

  %% This section is to deal with the horrible pair of files in Bug #696690 and Bug #696120
  %% These files have ICCBased spaces where the value of /N and the number of components
  %% in the profile differ. In addition the profile in Bug #696690 is invalid. In the
  %% case of Bug #696690 the /N value is correct, and the profile is wrong, in the case
  %% of Bug #696120 the /N value is incorrect and the profile is correct.
  %% We 'suspect' that Acrobat uses the fact that Bug #696120 is a pure image to detect
  %% that the /N is incorrect, we can't be sure whether it uses the profile or just uses
  %% the /N to decide on a device space. What we now do is; If the /N and device profile
  %% number of components don't match, we assume the device profile is correct and patch
  %% /N to be the same as the profile (see /ICCBased-resolve), but we save the original
  %% value of /N in /OrigN. In setcolor, if the space is a genuine ICCBased space
  %% (not a replacement for a device profile) we call set_dev_color which will actually
  %% exercise the profile. If that fails we return an error. Here we run setcolor in a
  %% stopped context, and if it fails we check to see if there is a /OrigN (ths occurs
  %% only if the /N was different to the number of components in the profile). If there
  %% is a /OrigN then prefer that to the profile, otherwise they agreed, so just use
  %% /N and select a device space. If we can't select a device space with the correct
  %% number of components, give up and throw an error. See also 'Cdict' in pdf_ops.ps.
  dup type /arraytype eq {
    dup 0 get /ICCBased eq {
      gsave
      dup setcolorspace dup 1 get /N get
       1 sub mark exch 0 1 3 -1 roll
       {pop 0} for
      {setcolor} stopped
      grestore
      {
        cleartomark
        1 get
        dup /OrigN .knownget {exch pop}{/N get} ifelse
        [//null /DeviceGray //null /DeviceRGB /DeviceCMYK] exch
        {get} stopped
        {
          (   **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print
          /setcolorspace cvx /undefined signalerror
        }
        {
          dup //null eq {
            (   **** Error: Unable to set an ICCBased colour space, and cannot set an alternate from the number of components.\n) print
            /setcolorspace cvx /undefined signalerror
          }{
            ICCProfileNError not {
              (   **** Warning : Error setting an ICCBased colour space, using /N to set an alternate device space.\n) print
              (                  Output may be incorrect.\n) print
            } if
          } ifelse
        }ifelse
        /ICCProfileNError //true def
      }{cleartomark}ifelse
    } if
  } if
  /ColorSpace exch def
} bind executeonly def

/get-smask-in-data { % <dict> -> <int>
  /SMaskInData knownoget {
    dup dup 1 ne exch 2 ne and {
      pop 0
    } if
  } {
    0
  } ifelse
} bind executeonly def

/makeimagedict {	% <resdict> <newdict> makeimagedict <imagemask?>
                        % On return, newdict' is currentdict
  begin
  /Width 2 copy oget def
  /Height 2 copy oget def
                % Handle missing BitsPerComponent later.
  /BitsPerComponent 2 copy knownoget { cvi def } { pop } ifelse
  /Interpolate 2 copy knownoget { def } { pop } ifelse
  makeimagekeys
} bind executeonly def

/makeimagekeys {	% <resdict> makeimagekeys <imagemask>
                % newdict is currentdict
                % Assumes Width, Height, BPC, Interpolate already copied.
  /ImageType 1 def
  /ImageMatrix Width 0 0
                % Handle 0-height images specially.
    Height dup 0 eq { pop 1 } if neg 0 1 index neg
    6 array astore def

  %% If the image has a rendering intent, get its numeric equivalent
  %% from renderingintentdict, and save it in the dictionary we pass
  %% on to render images.
  dup /Intent knownoget {
    //.renderingintentdict exch .knownget { /Intent exch def } if
  } if

  dup /ImageMask knownoget dup { and } if {
                % Image mask
                % Decode is required for the PostScript image operators.
                % AI8 writes bogus decode array [0 1 0 0 0 0 0 0]
    /Decode 2 copy knownoget { 0 2 getinterval } { //01_1 } ifelse def
                % BitsPerComponent is optional for masks.
    /BitsPerComponent 2 copy known { pop } { 1 def } ifelse
                % Even though we're going to read data,
                % pass false to resolvestream so that
                % it doesn't try to use Length (which may not be present).

    % Bug 701083: We add a /ErrsAsEOD key to the DecodeParms here too.
    <</ErrsAsEOD //true>> //add-to-all-params exec
    //false resolvestream /DataSource exch def
    //true
  } {
                % Opaque image
    dup /Filter knownoget {
      dup type /arraytype eq {
        dup length
        dup 0 gt {
          1 sub get oforce
        } {
          pop
        } ifelse
      } if
      /JPXDecode eq
    } {
      //false
    } ifelse {
      % /JPXDecode tricks

      % Previously we only ran the code to extract the Color Space and Bits Per Component
      % from the JOX stream if the image dict had either BPC or ColorSpace undefined.
      % However, while this is correct for the ColorSpace, its *not* correct for the BPC.
      % According to the spec we should ignore any BPC in the image dicitonary and
      % always use the BPC from the JPX stream.
      % Now the code in get_jp2_csp always overwrites the ColorSpace (in the image resource dict)
      % which technically is fine, because the image dictionary entry must be either not present or the
      % same as the JPX stream. However, this doesn't work, so instead we just save the existing
      % color space (if any). Then after extracting the color space and BPC from the JPX stream
      % we put back the saved color space, but only if there was one previously.
      dup /ColorSpace oknown {
        dup dup /ColorSpace get /ImageDictColorSpace exch put
      } if
      dup /IDFlag known {
        (   **** Warning: PDF spec bans inline JPX images.\n) pdfformatwarning
        % Inline stream is not positionable. Cannot get ColorSpace.
      } {
        % Drop the last filter (JPXDecode) from the pipeline
        dup dup length dict copy
        dup /Filter oget
        dup type /arraytype eq {
          dup length 1 gt {
            dup length 1 sub 0 exch getinterval
            1 index exch /Filter exch put

            dup /DecodeParms knownoget {
              dup type /arraytype eq {
                dup length 1 gt {
                  dup length 1 sub 0 exch getinterval
                  1 index exch /DecodeParms exch put
                } {
                  pop
                  dup /DecodeParms undef
                } ifelse
              } {
                pop
                dup /DecodeParms undef
              } ifelse
            } if
          } {
            pop
            dup /Filter undef
            dup /DecodeParms undef
          } ifelse
        } {
          pop
          dup /Filter undef
          dup /DecodeParms undef
        } ifelse

        //false resolvestream get_jp2_csp

        currentdict /ColorSpace oknown not {
          currentdict /JPXICC .knownget {
             [ /ICCBased mark
                 /DataSource 5 -1 roll
                 /N currentdict /JPXColors .knownget not {
                   currentdict /JPXComponents get
                 } if
               .dicttomark
             ] /ColorSpace exch def
          } if
        } if

        { /JPXICC /JPXColors /JPXComponents /JPXOpacity /JPXPremult } {
          currentdict exch undef
        } forall

      } ifelse

      % If we had a Color Space in the image dictionary before we read the JPX
      % stream, put it back now. We mujst do this before last-ditch-bpc-csp
      % because that resolves any indirect references to the color space.
      dup /ImageDictColorSpace known {
        dup /ImageDictColorSpace get currentdict /ColorSpace 3 -1 roll put
      } if

      //last-ditch-bpc-csp exec

      dup /ColorSpace oknown {
        % Propagate known color space to the filter
        /ColorSpace currentdict /ColorSpace get //add-to-last-param exec
      } if

      /Decode 2 copy knownoget not {
        ColorSpace //defaultdecodedict
        ColorSpace dup type /arraytype eq { 0 get } if get exec
      } if def

      dup get-smask-in-data dup 0 ne {
        PDFusingtransparency {
          currentdict dup length dict copy begin
          {/Mask/SMask/SMaskInData/Name} { currentdict exch undef } forall
          2 eq {
            /Matte [ Decode length 2 idiv { 0 } repeat ] def
          } if
          /Decode //01_1 def
          /ColorSpace /DeviceGray def
          {/File /FilePosition /Filter /Length /DecodeParms /FFilter /FDecodeParms } {
            2 copy knownoget {
              def
            } {
              pop
            } ifelse
          } forall
          currentdict /Alpha //true //add-to-last-param exec pop
          /SMask currentdict end def
        } {
          pop
        } ifelse
      } {
        pop
      } ifelse
    } { % not JPX image
      //last-ditch-bpc-csp exec
      /Decode 2 copy knownoget not {
        ColorSpace //defaultdecodedict
        ColorSpace dup type /arraytype eq { 0 get } if get exec
      } if def

    } ifelse % fi JPX tricks

    % Add a /Height key containing the image height to the DecodeParms
    % for any Filters we will apply. If there are no DecodeParms for any
    % filter, create one and add a /Height key. This is to solve the problem
    % in Bug #695116 where a JPEG image has a bad height, which is later
    % fixed up using a DNL marker. By placing the image height from the
    % PDF in the DecodeParms we can use it in the DCTDecode filter to
    % work around this.
    % Bug 701083: We add a /ErrsAsEOD key to the DecodeParms here too.
    << /Height 2 index /Height oget round cvi /ErrsAsEOD //true >>  //add-to-all-params exec

                % Even though we're going to read data,
                % pass false to resolvestream so that
                % it doesn't try to use Length (which may not be present).
    //false resolvestream /DataSource exch def
    //false
  } ifelse
} bind executeonly def

currentdict /add-to-last-param undef
currentdict /add-to-all-params undef
currentdict /last-ditch-bpc-csp undef

/DoImage {
  %% Bug #696439. This is incredibly icky. When we find indirect obects we resolve them
  %% and store the resolved object in the containing object. This means that we retain
  %% the image dicionary here until the end of job. Potentially wasteful. Even worse though
  %% is the case where the image has a ColorSpace which is not an indirect object, but *is*
  %% an ICCBased colour space. In ths case we end up resolving the colour space and storing it
  %% here. Unfortunately, we use a ReusableStreamDecode filter on the ICC profile, which means
  %% we end up retaining the memory for that too. ICC profiles can be large, and if there are a
  %% lot of places where they get used, we can exhaust memory.
  %% Here we check if the ColorSpace is an array object, if it is we *copy* the image dictionary
  %% and use the copy instead. The copy is (eventually) discarded so we don't retain the ICC profile
  %% and don't exhaust memory. Note that we have to copy the actual colour space array too, copying
  %% the dictionary just copies the opriginal array as well.
  %%
  dup /ColorSpace known {
    dup /ColorSpace get dup type /arraytype eq {
      exch dup length dict copy exch
      dup length array copy /ColorSpace exch 2 index 3 1 roll put
    } {pop} ifelse
  } if

  checkaltimage dup length 6 add dict  % <<image>> <<>>
  1 index /SMask knownoget {           % <<image>> <<>> <<sm>>
    dup 3 index ne {                   % <<image>> <<>> <<sm>> <<sm>>
      1 index exch /SMask exch put
    } {
      pop
      (   **** Error: ignoring recursive /SMask attribute.\n) pdfformaterror
      (               Output may be incorrect.\n) pdfformaterror
    } ifelse
  } if
  1 index /Mask knownoget {
    dup type dup /dicttype eq exch /arraytype eq or { % Bug #703681
      1 index exch /Mask exch put
    } {
      pop
      (   **** Error: Ignoring Mask attribute that is not an array or a dictionary.\n)
      pdfformaterror
    } ifelse
  } if
  makeimagedict doimagesmask
} bind executeonly def
/makemaskimage {	% <datasource> <imagemask> <Mask> makemaskimage
                        %   <datasource> <imagemask>, updates currentdict =
                        %   imagedict
  dup type /arraytype eq {
    /ImageType 4 def
                % Check that every element of the Mask is an integer.
    //false 1 index {
      type /integertype ne or
    } forall {
      oforce_array
      //false 1 index {
        type /integertype ne or
      } forall {
        (\n   **** Error: Some elements of Mask array are not integers.\n)
        pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
        [ exch { 0.5 add cvi } forall ]  % following AR4, 5, 6 implementation
      } if
    } if
      % Check elements of array are within 0::(2**BitsPerComponent)-1
      % This is a PostScript error, but AR tries to fix the Mask.
    1 BitsPerComponent bitshift 1 sub //false 2 index {
      % stack: max_value result_bool value
      dup 0 lt exch 3 index gt or or
    } forall exch pop
    {
      (   **** Error: Some elements of Mask array are out of range.\n)
      pdfformaterror
      (               Output may be incorrect.\n) pdfformaterror

      ColorSpace dup type /arraytype eq { 0 oget } if /Indexed eq
      BitsPerComponent 1 eq and
      {
        % AR9 treats Indexed 1 bpc images specially. Bug 692852 see also 697919 and 689717.
        dup 0 oget
        dup 0 lt exch 1 BitsPerComponent bitshift ge or {
          % First component is invalid - AR9 ignores the mask
          pop //null
        } {
          % Second component is invalid; AR9 replaces it with 1.
          [ exch 0 oget 1 ]
        } ifelse
      }
      {
        BitsPerComponent 1 eq {
          dup length 2 gt {
            % There are too many Mask entries, discard the Mask array
            pop //null
          }{
            % Bug 701468 and 689717, the latter requires us to set the Mask values
            % so that the value is calculated from the BPC, the other requires us
            % to ignore the Mask. The only difference between the two files is the
            % actual range of the Mask values. This may yet need more work.
            % Note! Both files are technically invalid....

            aload 3 1 roll eq {
              % There's only one Mask value, but its illegal, substitute with the
              % calculated maximum.
              [ exch { 1 BitsPerComponent bitshift 1 sub and } forall ]
            } {
              % The Mask values are not the same. This is a 2 colour image, if
              % we mask off any range then the result will be blank, so ignore the Mask
              pop //null
            } ifelse
          } ifelse
        } {
          % We think AR5, AR9 do this for most other cases. Originally Bug 690786,
          % but that is actually handled in the /Indexed case above.
          [ exch { 1 BitsPerComponent bitshift 1 sub and } forall ]
        } ifelse
      } ifelse
    } if

    dup //null ne {
      /MaskColor exch def
    } {
      pop
      /ImageType 1 def
    } ifelse
  } {
                % Mask is a stream, another Image XObject.
                % Stack: datasource imagemask(false) maskstreamdict
    PDFfile fileposition exch
    dup length dict makeimagedict pop
                % In order to prevent the two data sources from being
                % aliased, we need to make at least one a reusable stream.
                % We pick the mask, since it's smaller (in case we need to
                % read all its data now).
                % Stack: datasource imagemask(false) savedpos
                % maskdict is currentdict
    /DataSource DataSource mark
      /Intent 1
      /AsyncRead //true
    .dicttomark {.reusablestreamdecode} stopped {pop} if def
    PDFfile exch setfileposition
    currentdict end currentdict end
    5 dict begin
    /ImageType 3 def
    /InterleaveType 3 def
    /DataDict exch def
    /MaskDict exch def
    /ColorSpace DataDict /ColorSpace get def
  } ifelse
} bind executeonly def

/doimagesmask { % <imagemask> doimagesmask -
  PDFusingtransparency not
  /PreserveSMask /GetDeviceParam .special_op { exch pop } { //false } ifelse
  or {
    % not using transparency OR the device supports SMask (e.g. pdfwrite)
    doimage
  } {
    currentdict /SMask knownoget {
      % We are doing transparency and SMask is present in the image
      % stack: <imagemask> <SMask>
      % Normalize /Matte attribute for .begintransparencymaskimage
      dup /Matte .knownget {
        oforce dup //null eq {
          pop dup /Matte undef
        } {
          1 index /Matte [ 4 -1 roll { oforce } forall ] put
        } ifelse
      } if
      .begintransparencymaskimage
      PDFfile fileposition exch
      gsave //nodict begin
      //null .setSMask
      1 CA 1 ca
      /Compatible .setblendmode
      DoImage
      end grestore
      PDFfile exch setfileposition
      0 .endtransparencymask
      << /Subtype /Group /Isolated //true
         /.image_with_SMask //true
         % pdfwrite needs : see gs/src/ztrans.c, gs/src/gdevpdft.c
         % Code to deal with a Matte in the SMask. We know the image dictionary must have an SMask
         % entry if we get here, so we don't need to check its existence. Just pull it out and see if
         % the SMask has a Matte entry. If it does, get the ColorSpace from the parent image and
         % put a /CS key with that colour space in the Group that we manufacture. Bug #700686
         % We also need to actually set the current colour space to be the same as the group
         % code only picks up the current colour space, not the space from the dictionary.
         currentdict /SMask get /Matte known {/CS currentdict /ColorSpace get dup pdfopdict /cs get exec } if
      >> 0 0 1 1
      gsave 1 1 moveto 0 0 lineto
      % If we get an error, just emit an empty box
      { pathbbox } stopped { 0 0 0 0 } if
      4 array astore grestore
      /image
      setup_trans
      .begintransparencygroup
      .currentstrokeconstantalpha .currentfillconstantalpha 3 -1 roll
      1 .setfillconstantalpha 1 .setstrokeconstantalpha
      doimage
      .setfillconstantalpha .setstrokeconstantalpha
      .endtransparencygroup
      % tell the compositor we're done with the SMask.
      % Note that any SMask in the ExtGState should be reapplied
      % by the next call to setfill(stroke)state AND this relies
      % on our lazy evaulation of SMask groups
      //false << /Subtype /None >> 0 0 0 0 .begintransparencymaskgroup
    } {
      % We don't have an SMask in the image but there might be an SMask in the ExtGState
      .currentSMask //null ne {
        % the image doesn't have an SMask, but the ExtGState does, force a group.
        << /Subtype /Group /Isolated //true >> 0 0 1 1
        .begintransparencygroup
        .currentstrokeconstantalpha .currentfillconstantalpha 3 -1 roll
        1 .setfillconstantalpha 1 .setstrokeconstantalpha
        doimage
        .setfillconstantalpha .setstrokeconstantalpha
        .endtransparencygroup
      } {
        doimage
      } ifelse
    } ifelse
  } ifelse
} bind executeonly def

% For development needs we define a special option for running with a new handler
% for images with a soft mask.
//systemdict /NEW_IMAGE3X .knownget not { //false } if {
  /doimagesmask { % <imagemask> doimagesmask -
    doimage
  } bind executeonly def
} if

/ValidateDecode { % <<image dict>> -imagemask- ValidateDecode <<image dict>>
  exch
  dup /Decode .knownget {
    dup length                      % -imagemask- <<image dict>> [Decode] length
    4 -1 roll                       % <<image dict>> [Decode] length -imagemask-
    {
      1                             % ImageMask Decode arrays must be [0 1] or [1 0]
    }
    {
      mark currentcolor counttomark % <<image dict>> [Decode] length [ ... component_count
      dup 2 add 1 roll              % <<image dict>> [Decode] length component_count [ ....
      cleartomark                   % <<image dict>> [Decode] length component_count
    } ifelse
    2 mul dup                       % <<image dict>> [Decode] length comp_count*2 comp_count*2
    3 1 roll                        % <<image dict>> [Decode] comp_count*2 length comp_count*2
     eq {                           % <<image dict>> length of Decode matches colour space requirement
      pop pop                       % <<image dict>> remove [Decode] and comp_count*2
    }{                              % <<image dict>> Decode array incorrect
      dup 2 index length            % <<image dict>> [Decode] comp_count*2 comp_count*2 length
      exch sub 0 gt {               % Decode is too long
      (\n   **** Warning:  Decode array for an image is too long\n) pdfformatwarning
      (                  Output may be incorrect.\n) pdfformatwarning
        0 exch                      % <<image dict>> [Decode] 0 comp_count*2
        getinterval                 % <<image dict>> [subarray of Decode]
        1 index exch /Decode exch   % <<image dict>> <<image dict>> /Decode [subarray]
        put                         % <<image dict>>
      }{
                                    % Decode is too short, Acrobat throws errors on this
        (\n   **** ERROR:  Decode array for an image is too short\n) pdfformaterror
        (                Output may be incorrect.\n) pdfformaterror
        pop pop                     % remove [Decode] and comp_count*2
      } ifelse
    } ifelse
  } {
    exch pop
  }ifelse
}bind executeonly def

/doimage {	% <imagemask> doimage -
                % imagedict is currentdict, gets popped from dstack
  %% We must save the colour space, in case it gets changed. I did try doing this
  %% at a higher level (/Do) but that caused numerous problems with pdfwrite.
  currentcolorspace exch
  %% save the current rendering intent
  .currentrenderintent exch

  %% Check the image dictionary to see if there is a /Intent
  currentdict /Intent known {
    %% and set the current rendering intent to match if so
    Intent .setrenderingintent
  } if

  DataSource exch
  currentdict /SMask known PDFusingtransparency and {
    /PreserveSMask /GetDeviceParam .special_op {
      pop pop
      currentdict /SMask oget
      makesoftmaskimage
    } if
  } if
  currentdict /Mask knownoget {
      makemaskimage
  } if
                % Stack: datasource imagemask
  { currentdict end setsmaskstate //true ValidateDecode { imagemask } }
  { ColorSpace setgcolorspace currentdict end setsmaskstate //false ValidateDecode { image } }
  ifelse
  PDFSTOPONERROR { exec //false } { stopped } ifelse {
    dup type /dicttype eq { pop } if % Sometimes image fails to restore the stack
    $error /errorname get dup /ioerror eq {
      pop (\n   **** Error: File has insufficient data for an image.\n)
      pdfformaterror
    (               Output may be incorrect.\n) pdfformaterror
    } {
      (\n   **** Error: File encountered ')
      exch 40 string cvs concatstrings
      (' error while processing an image.\n) concatstrings
      pdfformaterror
      (               Output may be incorrect.\n) pdfformaterror
    } ifelse
  } if
                % Close the input stream, unless it is PDFfile or
                % PDFsource.
  dup dup PDFfile eq exch PDFsource eq or { pop } { closefile } ifelse

  %% restore the rendering intent
  .setrenderingintent

  %% and restore the colour space. We need to do this in a stopped context because
  %% if we are rendering a glyph, the cache device will throw an error if we try
  %% to change colour space (even when the new space is the same as the old space)
  %% We can't tell if we are rendering a bitmap for a glyph, and its hard to compare
  %% colour spaces, so just ignore errors for now.
  {setcolorspace} stopped {pop} if

  teardown_trans
} bind executeonly def

/.paintform {	% <formdict> <resdict> <stream> .paintform -
  1 index /FormResDict gput  % For broken forms that inherit resources from the context.
  3 -1 roll dup /Group oknown PDFusingtransparency and {
    .paintgroupform
  } {
    pop pdfopdict .pdfruncontext
  } ifelse
} bind executeonly def

/IncrementAppearanceNumber {
  //pdfdict /AppearanceNumber .knownget {
    1 add //pdfdict /AppearanceNumber 3 -1 roll .forceput
  } executeonly
  {
    //pdfdict /AppearanceNumber 0 .forceput
  } executeonly ifelse
}bind executeonly odef

/MakeAppearanceName {
  //pdfdict /AppearanceNumber get
  10 string cvs
  dup length 10 add string dup 0 (\{FormName) putinterval
  dup 3 -1 roll
  9 exch putinterval
  dup dup length 1 sub (\}) putinterval
} bind executeonly def

/MakeNewAppearanceName {
  IncrementAppearanceNumber
  MakeAppearanceName
}bind executeonly def

/DoAppearance {
%% Might need to rethink this. The problem is that if the page has a CropBox, we apply
%% that as an initial clip. When we run the form, we don't apply the /Rect from the
%% annotation, which means that the form could be out of the clip, which results in
%% content going missing. Resetting the clip prevents this.
  gsave initclip
  MakeNewAppearanceName
  .pdfFormName
  //pdfdict /.PreservePDFForm known {//pdfdict /.PreservePDFForm get} {//false}ifelse exch
  //pdfdict /.PreservePDFForm //true .forceput
  DoForm
  //pdfdict /.PreservePDFForm 3 -1 roll .forceput
  grestore
} bind executeonly odef

%% We don't want to do any high level forms stuff if the source
%% is PDF because :
%% 1) Transparent forms are handled separately and we don't want to ge confused
%% 2) PDF forms are too llikely to trip over the limitations in our support
%% 3) Its highly unusual to find a PDF file which uses forms sensibly.
%%
%% So we have a special PDF version of execform which doesn't do high level forms.

pdfdict
/.PDFexecform {
        % This is a separate operator so that the stacks will be restored
        % properly if an error occurs.
  dup /Matrix get concat
  dup /BBox get aload pop
  exch 3 index sub exch 2 index sub rectclip
  dup /PaintProc get
  1 index /Implementation known not {
    1 index dup /Implementation //null .forceput readonly pop
  } executeonly if
  exec
} .bind executeonly put

pdfdict
/PDFexecform {
  gsave { //.PDFexecform exec } stopped
  grestore {stop} if
} .bind executeonly put

/DoForm {
  %% save the current value, if its true we will set it to false later, in order
  %% to prevent us preserving Forms which are used *from* an annotation /Appearance.
  //pdfdict /.PreservePDFForm known {//pdfdict /.PreservePDFForm get} {//false}ifelse exch

  %% We may alter the Default* colour spaces, if the Resources
  %% ColorSpace entry contains one of them. But we don't want that
  %% to become the new default, we want to revert to any existing
  %% definition, or the Device space. The Default* spaces are defined
  %% as ColorSpace resources, so the only way to handle them is to
  %% save and restore round the definitions
  3 dict dup begin
  /saved_DG /DefaultGray /ColorSpace findresource def
  /saved_DRGB /DefaultRGB /ColorSpace findresource def
  /saved_DCMYK /DefaultCMYK /ColorSpace findresource def
  end
  exch

    % Adobe 2nd edition of the PDF 1.3 spec makes /FormType
    % and /Matrix keys optional. Cope with the missing keys.
  begin <<
  currentdict /FormType known not { /FormType 1 } if
  currentdict /Matrix   known not
  { /Matrix { 1 0 0 1 0 0 } cvlit }
  {
    0 1 Matrix length 1 sub
    {
      dup Matrix exch get type dup
      /integertype eq exch
      /realtype eq or not
      {
        (\n   **** Error: Invalid element in /Form XObject matrix.\n)
        pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
        Matrix exch 0.00 put
      }
      { pop }
      ifelse
    } for
  } ifelse
  currentdict /BBox known not {
        (\n   **** Error: Required entry /BBox not present in Form.\n)
        pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
        /BBox [0 1 0 1]
  } if
  currentdict end { oforce } forall
  >>
  dup [ 2 index /Resources knownoget { oforce } { 0 dict } ifelse

  %% Ugly hackery for Default* colour spaces in forms
  %%
  dup /ColorSpace knownoget {
    oforce {
      //false 3 1 roll
      exch dup /DefaultGray eq
      {
      pop exec resolvecolorspace dup csncomp 1 eq {
        dup type /nametype eq { 1 array astore } if
        /DefaultGray exch /ColorSpace defineresource pop
        pop //true
      }{
        pop
        (   **** Error: ignoring invalid /DefaultGray color space.\n)
        pdfformaterror
        (                 Output may be incorrect.\n) pdfformaterror
      } ifelse
      }{
        dup /DefaultRGB eq {
          pop exec resolvecolorspace dup csncomp 3 eq {
            dup type /nametype eq { 1 array astore } if
            /DefaultRGB exch /ColorSpace defineresource pop
            pop //true
          }{
            pop
            (   **** Error: ignoring invalid /DefaultRGB color space in Form Resources.\n)
            pdfformaterror
            (                 Output may be incorrect.\n) pdfformaterror
          } ifelse
        }{
          /DefaultCMYK eq {
            exec resolvecolorspace dup csncomp 4 eq {
              dup type /nametype eq { 1 array astore } if
              /DefaultCMYK exch /ColorSpace defineresource pop
              pop //true
            }{
              pop
              (   **** Error: ignoring invalid /DefaultCMYK color space in Form Resources.\n)
              pdfformaterror
              (                 Output may be incorrect.\n) pdfformaterror
            } ifelse
          }{
            pop
          } ifelse
        } ifelse
      }ifelse
      { % if using color space substitution, "transition" the current color space
        currentcolorspace dup length 1 eq {  % always an array
          0 get
          dup /DeviceGray eq 1 index /DeviceRGB eq or 1 index /DeviceCMYK eq or {
            /Pattern setcolorspace setcolorspace
          } {
            pop
          } ifelse
        } {
          pop
        } ifelse
      } if
    } forall
  } if

  3 index
  % /Contents for the stream is not per the spec, but Acrobat handles it
  dup /Contents knownoget
  {
      % We want to make it's a dictionary, and represents a stream
      dup type /dicttype eq
      {
        dup /FilePosition known
        {
            PDFSTOPONERROR { /DoForm cvx /undefinedresource signalerror } if
            (   **** Error: Invalid Form definition. Output may be incorrect.\n) pdfformaterror
            exch pop
        }
        {pop} ifelse
      }
      {
        pop
      }
      ifelse
  }if
  //false /resolvestream cvx
  /.paintform cvx
  ] cvx /PaintProc exch put
    % Adjust pdfemptycount since we have an extra dictionary on the stack
  pdfemptycount countdictstack 3 -1 roll
  /pdfemptycount count 4 sub store

  //pdfdict /.PreservePDFForm known {//pdfdict /.PreservePDFForm get}{//false} ifelse
  {
    %% We must *not* preserve any subsidiary forms (curently at least) as PDF
    %% form preservation doesn't really work. This is used just for Annotation
    %% Appearances currently, and if they should happen to use a form, we do not
    %% want to preserve it.
    //pdfdict /.PreservePDFForm //false .forceput
    /q cvx /execform cvx 5 -2 roll
  } executeonly
  {
    /q cvx /PDFexecform cvx 5 -2 roll
  } ifelse

  4 .execn
  % Restore pdfemptycount
  0
  { countdictstack
    2 index le { exit } if
    currentdict /n known not { 1 add } if
    countdictstack
    Q
    countdictstack eq {end} if
  } loop
  1 gt {
    (   **** Error: Form stream has unbalanced q/Q operators \(too many q's\)\n)
    pdfformaterror
    (               Output may be incorrect.\n) pdfformaterror
  } if
  pop
  /pdfemptycount exch store

  % We've now seen Form XObjects leaving junk on the stack, so we
  % can't assume that when we finish the form the stack will be restored
  % nor can we assume that the junk won't include a 'mark' so we an't
  % simply do a cleartomark. Instead clear the stack until we get back
  % to a dictionary which contains /saved_DG. We can still get errors;
  % if the stream removes too many objects from the stack we will end
  % up with a stackunderflow, but there's nothing we can do about that.
  dup type /dicttype eq not {
    //true
  } {
    dup /saved_DG known {
      //false
    } {
      //true
    } ifelse
  } ifelse
  {
    (   **** Error: Form stream left garbage on the stack, attempting to recover.\n) pdfformaterror
    (               Output may be incorrect.\n) pdfformaterror
    {
      dup type /dicttype eq not {
        pop
      } {
        dup /saved_DG known {
          exit
        } {
          pop
        } ifelse
      } ifelse
    } loop
  } if

  %% Put back pre-existing Default* ColorSpace definitions.
    dup type /dicttype eq {
    begin
    saved_DG /DefaultGray exch /ColorSpace defineresource pop
    saved_DRGB /DefaultRGB exch /ColorSpace defineresource pop
    saved_DCMYK /DefaultCMYK exch /ColorSpace defineresource pop
    end
  } if
  //pdfdict /.PreservePDFForm 3 -1 roll .forceput
} bind executeonly odef

/_dops_save 1 array def

/DoPS {
  DOPS
   {
     //_dops_save 0 save put
     //true resolvestream cvx exec
     //_dops_save 0 get restore
   }
   { pop }
  ifelse
} bind executeonly def

currentdict /_dops_save undef

/ocg_pocs 4 dict begin
  /AllOn {
    //true exch {
      oforce dup type /dicttype eq {
        /OFF known not and
      } {
        pop
      } ifelse
    } forall
  } bind executeonly def
  /AnyOn {
    //false exch {
      oforce dup type /dicttype eq {
        /OFF known not or
      } {
        pop
      } ifelse
    } forall
  } bind executeonly def
  /AnyOff {
    //AllOn exec not
  } bind executeonly def
  /AllOff {
    //AnyOn exec not
  } bind executeonly def
currentdict end readonly def

% Check whether OCG or OCMD is visible
% <dict> oc-is-visible <bool>
/ocg-is-visible {
  dup /Type knownoget {
    /OCMD eq {
      dup /OCGs knownoget not { {} } if      % OC OCGs
      dup type /dicttype eq { 1 array astore } if
      //true 1 index { //null eq and } forall {
         pop pop //true  % all nulls => show
      } {
        exch /P knownoget not { /AnyOn } if  % OCGs P
        //ocg_pocs exch get exec             % bool
      } ifelse
    } {
      dup /OFF known not % OFF is inserted by process_trailer_attrs
      {
        %% /OC is not in the OCProperties /OFF array, so we need to
        %% test its usage. We may eventually have to add a /ON to the dictionary
        %% if the OCProperties /ON array defines the /OC, I think that should override
        % the Usage, but I don't have an example to test.
        /Usage .knownget {
          oforce
          /Printed where {
            /Printed get
          } {
            //false
          }ifelse
          {
            %% We are behaving as a printer, check the Print state
            /Print .knownget {
              /PrintState .knownget {
                oforce
                /OFF eq {
                  //false
                }{
                  //true
                } ifelse
              }{
                //true
              } ifelse
            }{
              %% If we don't know, assume its visible
              //true
            } ifelse
          }{
            %% We are behaving as a viewer, check the View state
            /View .knownget {
              oforce
              /ViewState .knownget {
                /OFF eq {
                  //false
                }{
                  //true
                } ifelse
              }{
                //true
              } ifelse
            }{
              %% If we don't know, assume its visible
              //true
            } ifelse
          } ifelse
        }{
          %% If we don't know, assume its visible
          //true
        } ifelse
      }{
        pop //false
      }ifelse
    } ifelse
  } {
    /OFF known not % OFF is inserted by process_trailer_attrs
  } ifelse
} bind executeonly def

drawopdict begin
  /Do {                                                  % /Name
    %% Bug 695897 This file has nested text blocks and also a Do image inside
    %% a text block. Here we attempt to detect and recover from this by setting the
    %% CTM to the matrix we saved before the text block. NB we update the 'TextSaveMatrix'
    %% or 'qTextSaveMatrix' whenever a 'cm' is issued, even if we are in a text block, so
    %% these matrices 'ought' to be correct.
    %% Of course, the file is badly broken, but 'Acrobat can open it....'
    currentdict /TextSaveMatrix known {
      gsave
      (   **** Error: Executing Do inside a text block, attempting to recover\n) pdfformaterror
      currentdict /TextSaveMatrix get setmatrix
      (               Output may be incorrect.\n) pdfformaterror
    } if
    currentdict /qTextSaveMatrix known {
      gsave
      (   **** Error: Executing Do inside a text block, attempting to recover\n) pdfformaterror
      (               Output may be incorrect.\n) pdfformaterror
      currentdict /qTextSaveMatrix get setmatrix
    } if
    setsmaskstate
    PDFfile fileposition exch                      % pos /Name

    % Bug #698226, Acrobat signals an error for recursive XObjects in a PDF file
    % but continues. This is true even if the XObject is not a simple self-reference
    % (eg /Fm1 -> /Fm2 -> /Fm3 -> /Fm1).
    % Normally when dealing with recursion we would put a dictionary on the stack, store the
    % object numbers encoutnered in it, and check each new object number to see if we've
    % already seen it. This doesn't work well for XObjects, because the operand stack can be
    % in any state when we run a Do. So we make a new dictionary in pdfdict to hold the
    % object numbers.
    % We also don't usually know the object number of a Form, we just get given its name
    % so we need a new routine to return the object number. This is because the parent XObject
    % might reference teh object by one name, while the child references it by another, we
    % can't permit clashes.
    %
    % Start by getting the object number for a Form XObject
    dup Page /XObject obj_get dup 0 eq not {
      % Now get the recording dictionary and see if that object number has been seen
      //pdfdict /Recursive_XObject_D get 1 index known {
        (   **** Error: Recursive XObject detected, ignoring ") print 1 index 256 string cvs print (", object number ) print 256 string cvs print (\n) print
        (               Output may be incorrect.\n) pdfformaterror
        //false
      }{
        % We haven't seen it yet, so record it.
        //pdfdict /Recursive_XObject_D get 1 index //null put
        3 1 roll
        //true
      }ifelse
    }
    {
      % I don't think this should be possible, but just in case
        (   **** Error: Unable to determine object number for ) print exch 256 string cvs print ( so ignoring it) print
        (               Output may be incorrect.\n) pdfformaterror
      //false
    } ifelse

    % If we could get the object number, and we haven't already seen it, then execute it.
    {
      dup Page /XObject rget {
        exch pop                                     % pos obj
        OFFlevels length 0 eq {
          dup /OC knownoget { ocg-is-visible } { //true } ifelse
        } {
          //false
        } ifelse {
          dup /Subtype oget //xobjectprocs exch get   % pos obj {proc}
          % Don't leave extra objects on the stack while executing
          % the definition of the form.
          3 -1 roll                                  % obj {proc} pos
          2 .execn                                   % pos
        } {
          pop                                        % pos
        } ifelse
      } {
          % This should cause an error, but Acrobat Reader can
          % continue, so we do too.
        (   **** Error: Undefined XObject resource: )
        exch =string cvs concatstrings (\n) concatstrings
        pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
      } ifelse
      PDFfile exch setfileposition
      //pdfdict /Recursive_XObject_D get exch undef
    }{
      % Otherwise ignore it and tidy up the stacks
      pop pop
    } ifelse
  } bind executeonly def
end

currentdict /xobjectprocs .undef
currentdict /ocg_pocs .undef

% ---------------- In-line images ---------------- %

% Undo the abbreviations in an in-line image dictionary.
% Note that we must look inside array values.
% /I is context-dependent.
/unabbrevkeydict mark
  /BPC /BitsPerComponent  /CS /ColorSpace  /D /Decode  /DP /DecodeParms
  /F /Filter  /H /Height  /I /Interpolate  /IM /ImageMask  /W /Width
.dicttomark readonly def
/unabbrevvaluedict mark
  /AHx /ASCIIHexDecode  /A85 /ASCII85Decode  /CC /CalCMYK
  /CCF /CCITTFaxDecode  /CG /CalGray  /CR /CalRGB
  /DCT /DCTDecode  /CMYK /DeviceCMYK  /Fl /FlateDecode
  /G /DeviceGray  /RGB /DeviceRGB
  /I /Indexed  /LZW /LZWDecode  /RL /RunLengthDecode
.dicttomark readonly def
/unabbrevtypedict mark
  /nametype {
    //unabbrevvaluedict 1 index .knownget { exch pop } if
  }
  /arraytype {
    dup 0 1 2 index length 1 sub {
      2 copy get unabbrevvalue put dup
    } for pop
  }
.dicttomark readonly def
/unabbrevvalue {	% <obj> unabbrevvalue <obj'>
  oforce //unabbrevtypedict 1 index type .knownget { exec } if
} bind executeonly def

/is_space_dict << 0 0 9 9 10 10 12 12 13 13 32 32 >> readonly def

drawopdict begin
  /BI { mark } bind executeonly def
  /ID {
    gsave
    %% Bug 696547, related to Bug 695897 (see /Do above) This file has an inline image inside
    %% a text block. Here we attempt to detect and recover from this by setting the
    %% CTM to the matrix we saved before the text block. NB we update the 'TextSaveMatrix'
    %% or 'qTextSaveMatrix' whenever a 'cm' is issued, even if we are in a text block, so
    %% these matrices 'ought' to be correct.
    %% Of course, the file is badly broken, but 'Acrobat can open it....'
    currentdict /TextSaveMatrix known {
      (   **** Error: Executing ID inside a text block, attempting to recover\n) pdfformaterror
      currentdict /TextSaveMatrix get setmatrix
      (               Output may be incorrect.\n) pdfformaterror
    } if
    currentdict /qTextSaveMatrix known {
      (   **** Error: Executing ID inside a text block, attempting to recover\n) pdfformaterror
      (               Output may be incorrect.\n) pdfformaterror
      currentdict /qTextSaveMatrix get setmatrix
    } if

    counttomark 2 idiv dup 7 add dict begin {
      exch //unabbrevkeydict 1 index .knownget { exch pop } if
      exch unabbrevvalue def
    } repeat pop
    /IDFlag //true def  % flag for stream processing.
    /File PDFsource def
    currentdict makeimagekeys
    OFFlevels length 0 eq {
      gsave 1 1 moveto 0 0 lineto
      % If we get an error, just emit an empty box
      { pathbbox } stopped { 0 0 0 0 } if
      4 array astore grestore
      /image
      setup_trans
      doimage
    } {
      pop Width
      currentdict /ImageMask knownoget dup { and } if not {
        ColorSpace oforce csncomp mul
        BitsPerComponent mul
      } if
      7 add 8 idiv Height mul
      DataSource exch () /SubFileDecode filter flushfile
      end
    } ifelse
        % The Adobe documentation says that the data following ID
        % consists of "lines", and some PDF files (specifically, some files
        % produced by PCL2PDF from Visual Software) contain garbage bytes
        % between the last byte of valid data and an EOL.
        % Some files (PDFOUT v3.8d by GenText) have EI immediately following
        % the stream. Some have no EOL and garbage bytes.
        % Sometimes (bug 690300) CCITTDecode filter consumes 'E' in 'EI'.
        % Therefore, we search for <start>I<sp|end> or <start|sp>EI<sp|end>
    PDFsource read not {
      /ID cvx /syntaxerror signalerror
    } if
    dup 73 eq {
      pop 10 69 73     % Seed to: <sp>EI
    } {
      10 10 3 -1 roll  % Seed to: <sp><sp><any>
    } ifelse
    { PDFsource read not dup { 10 exch } if
      //is_space_dict 2 index known
      3 index 73 eq and 4 index 69 eq and
      //is_space_dict 6 index known and {
        pop pop pop pop pop exit
      } {
          {
            pop pop pop /ID cvx /syntaxerror signalerror
          } {
            4 -1 roll pop
          } ifelse
      } ifelse
    } loop
    grestore
  } bind executeonly def
end

currentdict /is_space_dict undef

% ================================ Text ================================ %

drawopdict begin
                        % Text control
  /BT { BT } executeonly def
  /ET { ET } executeonly def
  /Tc { Tc } executeonly def
  /TL { TL } executeonly def
  /Tr { Tr } executeonly def
  /Ts { Ts } executeonly def
  /Tw { Tw } executeonly def
  /Tz { Tz } executeonly def
                        % Text positioning
  /Td { Td } executeonly def
  /TD { TD } executeonly def
  /Tm { Tm } executeonly def
  /T* { T* } executeonly def
                        % Text painting
  /Tj { Tj } executeonly def
  /' { ' } executeonly def
  /" { " } executeonly def
  /TJ { TJ } executeonly def

  /Tform { Tform } executeonly def  % Text formatting and painting for AcroForm
                        % without appearance streams.
end

% ======================= Invalid operators ============================ %

drawopdict begin
  /QBT {
    Q BT
    (   **** Error: invalid operator QBT processed as Q BT .\n)
    pdfformaterror  % Bug 690089
    (               Output may be incorrect.\n) pdfformaterror
  } executeonly def

  /. {
    0.
    (   **** Error: invalid operator . processed as number 0. .\n)
    pdfformaterror  % Bug 690730
    (               Output may be incorrect.\n) pdfformaterror
  } executeonly def
end

% ============================== Annotations ============================== %

% Create links from separate widget annotations to the parent field nodes.
% Surprisingly, separate widget annotations don't have a link to the parent
% from which they inherit some data.
/link_widget_annots { % <<parent>> <<kid>> -> <<parent>> <<kid>>
  dup /Kids knownoget {
    { oforce
      dup type /dicttype eq {
        link_widget_annots
      } if
      pop
    } forall
  } if
  dup /Parent oknown not {
    2 copy exch /ParentField exch put
  } if
} bind executeonly def

% Get and normalize an annotation's rectangle.
/annotrect {		% <annot> annotrect <x> <y> <w> <h>
  /Rect oget oforce_recursive aload pop
  exch 3 index sub dup 0 lt { dup 5 -1 roll add 4 1 roll neg } if
  exch 2 index sub dup 0 lt { dup 4 -1 roll add 3 1 roll neg } if
} bind executeonly def

% Set an annotation color.
% If the /C array is empty we don't want to draw the annotation
%
/annotsetcolor {	% <annot> annotsetcolor bool
  /C knownoget {
    dup length 4 eq {
      aload pop setcmykcolor //true
    }{
      dup length 3 eq {
        aload pop setrgbcolor //true
      }{
        dup length 1 eq {
          aload pop setgray //true
        } {
          dup length 0 eq {
            pop
            //false
          }{
            (   **** Error: invalid color specified for annotation /C entry)
            pdfformaterror //false
            (               Output may be incorrect.\n) pdfformaterror
          } ifelse
        } ifelse
      } ifelse
    } ifelse
  }
  { 0 setgray //true} ifelse
} bind executeonly def

% Set an annotation color.
% If the /C array is empty we don't want to draw the annotation
%
/annotsetinteriorcolor {	% <annot> annotsetcolor bool
  /IC knownoget {
    dup length 4 eq {
      aload pop setcmykcolor //true
    }{
      dup length 3 eq {
        aload pop setrgbcolor //true
      }{
        dup length 1 eq {
          aload pop setgray //true
        } {
          dup length 0 eq {
            pop
            //false
          }{
            (   **** Error: invalid color specified for annotation /C entry)
            pdfformaterror //false
            (               Output may be incorrect.\n) pdfformaterror
          } ifelse
        } ifelse
      } ifelse
    } ifelse
  }
  { //false } ifelse
} bind executeonly def

% Draw the border.  Currently, we ignore requests for beveling, and we
% don't round the corners of rectangles.
/strokeborder {		% <annot> <width> <dash> strokeborder -
  1 index 0 ne {	% do not draw if border width is 0
    gsave
%    2 index annotsetcolor
%    {
      0 setdash dup setlinewidth
      exch dup annotrect
      5 -1 roll /RD knownoget {
        applyRD
      } if
      2 { 4 index sub 4 1 roll } repeat
      2 { 4 index 0.5 mul add 4 1 roll } repeat
      rectstroke pop
      grestore
%    } {
%      pop pop pop
%    } ifelse
  } {
    pop pop pop
  }ifelse
} bind executeonly def

% Draw an annotation border.
/drawborder {		% <annot> drawborder -
  gsave
  dup /BS known 1 index /Border known or {
    dup /BS knownoget {
      dup type /dicttype ne   % <annot> <border> <bad?>
    } {
      dup /Border oget
      dup type /arraytype eq {
        dup length 3 lt
      } {
        //true
      } ifelse                % <annot> [border] <bad?>
    } ifelse {
      (   **** Error: Invalid annotation border object, border has not been drawn.\n)
      pdfformaterror
      (               Output may be incorrect.\n) pdfformaterror
      pop { 0 0 0 }
    } if
    dup type /dicttype eq {
      dup /W knownoget not { 1 } if
      % Per PDF1.6 Reference table 8.13, /W in the border style dictionary is
      % expressed in points (an absolute unit), so compensate here for any
      % scaling of the PostScript user space done due to /UserUnit.
      % Scaling due to -dPDFFitPage is not undone, to keep the correct border width
      % compared to the size of the surrounding marks.
      //systemdict /NoUserUnit .knownget not { //false } if not
      //systemdict /PDFFitPage known not and
      % Don't apply USerUnit if we are passing it to the device
      /PassUserUnit /GetDeviceParam .special_op {exch pop} {//false} ifelse not and
      {	% UserUnit is ignored if -dPDFFitPage
        Page /UserUnit knownoget { div } if
      } if
      {} 2 index /S knownoget {
        /D eq { 2 index /D knownoget not { {3} } if exch pop } if
      } if
      3 -1 roll pop strokeborder
    } {
      dup 2 get
      exch dup length 3 gt { 3 get } { pop {} } ifelse
      strokeborder
    } ifelse
  } {
    1 {} strokeborder
  } ifelse
  grestore
} bind executeonly def

% stroke the path of an annotation border.
/strokeborderpath {		% <annot> strokeborderpath -
  gsave
  dup /BS known 1 index /Border known or {
    dup /BS knownoget {
      dup type /dicttype ne   % <annot> <border> <bad?>
    } {
      dup /Border oget
      dup type /arraytype eq {
        dup length 3 lt
      } {
        //true
      } ifelse                % <annot> [border] <bad?>
    } ifelse {
      (   **** Error: Invalid annotation border object, border has not been drawn.\n)
      pdfformaterror
      (               Output may be incorrect.\n) pdfformaterror
      pop { 0 0 0 }
    } if
    dup type /dicttype eq {
      dup /W knownoget not { 1 } if
      % Per PDF1.6 Reference table 8.13, /W in the border style dictionary is
      % expressed in points (an absolute unit), so compensate here for any
      % scaling of the PostScript user space done due to /UserUnit.
      % Scaling due to -dPDFFitPage is not undone, to keep the correct border width
      % compared to the size of the surrounding marks.
      //systemdict /NoUserUnit .knownget not { //false } if not
      //systemdict /PDFFitPage known not and
      % Don't apply USerUnit if we are passing it to the device
      /PassUserUnit /GetDeviceParam .special_op {exch pop} {//false} ifelse not and
      {	% UserUnit is ignored if -dPDFFitPage
        Page /UserUnit knownoget { div } if
      } if
      {} 2 index /S knownoget {
        /D eq { 2 index /D knownoget not { {3} } if exch pop } if
      } if
      3 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
      3 -1 roll pop
%      2 index annotsetcolor {
      0 setdash setlinewidth stroke
%      } if
    } {
      dup 2 get
      % If element 3 of the /Border array is 0, then don't draw the border
      dup 0 ne {
        exch dup length 3 gt { 3 get } { pop {} } ifelse
        3 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
%        2 index annotsetcolor {
        0 setdash setlinewidth stroke
%        } if
      }{
       pop pop
      } ifelse
    } ifelse
  } {
    dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
    1 {}
%    2 index annotsetcolor {
    0 setdash setlinewidth stroke
%    } if
  } ifelse
  pop
  grestore
} bind executeonly def

/fillborderpath {		% <annot> fillborderpath -
  gsave
  dup /ca knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
  annotsetinteriorcolor
  {fill} if
  grestore
}bind executeonly def

%
%   The PDF annotation F (flags) integer is bit encoded.
%   Bit 1 (LSB) Invisible:  1 --> Do not display if no handler.
%         Note:  We have no handlers but we ignore this bit.
%   Bit 2 Hidden:  1 --> Do not display.  We will not display if this bit is set.
%   Bit 3 Print:  1 --> Display if printing.  We will display if this bit set
%         (and not hidden) and Printed is true
%   Bit 4 NoZoom:  1 --> Do not zoom annotation even if image is zoomed.
%   Bit 5 NoRotate:  1 --> Do not rotate annotation even if image is rotated.
%   Bit 6 NoView:  0 --> Display if this is a 'viewer'.  We will display
%         if this bit is not set (and not hidden) and Printed is false
%   Bit 7 Read Only - 1 --> No interaction.  We ignore this bit
%
%   AR8 and AR9 print 3D annotations even if Print flag is off. Bug 691486.
%
/annotvisible {			% <annot> annotvisible <visible>
  dup /Subtype knownoget { /3D eq } { //false } ifelse % 3D annot
  exch /F knownoget not { 0 } if  % Get flag value
  dup 2 and 0 eq {
    /Printed load {
      4 and 4 eq or               % Printed or 3D
    } {
      32 and 0 eq exch pop        % not NoView
    } ifelse
  } {
    pop pop //false                            % Hidden
  } ifelse
} bind executeonly def

/set_bc_color <<
 1 { 0 get oforce setgray } bind executeonly
 3 { { oforce } forall setrgbcolor } bind executeonly
 4 { { oforce } forall setcmykcolor } bind executeonly
>> readonly def

% Get an inherited attribute from a node through /Parent and /ParentField
% links. The latter is set at start-up to access parents of annotations and
% defaults at AcroForm.
/fget	% <field> <key> fget <value> -true-
 {	% <field> <key> fget -false-
   {
     2 copy knownoget {
       exch pop exch pop //true exit
     } {
       exch
       dup /Parent knownoget {
         exch pop exch
       } {
         /ParentField knownoget {
           exch
         } {
           pop //false exit
         } ifelse
       } ifelse
     } ifelse
   } loop
 } bind executeonly def

% <annot> foo <annot>
/make_tx_da {
  dup /AP << /N 10 dict dup cvx begin >> put
  /Subtype /Form def
  /BBox [ 0 0 4 index /Rect oget { oforce } forall  3 -1 roll sub abs 3 1 roll sub abs exch ] def
  /Resources 1 index /DR fget not { 0 dict } if def
  /File 1 index /V fget not { () } if length
     2 index /DA fget not { () } if length add
     500 add 65535 .min  string dup 3 1 roll def
  /NullEncode filter    % <annot> file

  dup (BT ) writestring
  1 index /DA fget not {
    1 index /V fget {
      <EFBBBF> anchorsearch {
        pop /Helvetica findfont
        12 scalefont setfont
      } {
        <FEFF> anchorsearch {
          pop pop /FallBackFont /Identity-UTF16-H [/CIDFallBack] composefont 12 scalefont setfont
        } {
          pop /Helvetica findfont
          % re-encode the font to PDFDocEncoding
          dup length dict begin
          {
            1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse
          } forall
          /Encoding /PDFDocEncoding /Encoding findresource def
          /FontName /Helvetica-PDFDocEncoding def
          currentdict
          end
          /Helvetica-PDFDocEncoding exch definefont
          12 scalefont setfont
        }ifelse
      }ifelse
    } if
    ()
  }if

  [ exch
    { token {
        dup /Tf eq {
          2 index 0 eq {
            /BBox load 3 get
            0.75 mul   % empirical constant
            4 -1 roll pop 3 1 roll
          } if
        } if
        exch
      } {
        exit
      } ifelse
    } loop
  ]
  { 1 index exch write== } forall
  dup 2 index /MaxLen fget not { 0 } if write=
  dup 2 index /V fget not { () } if write==
  dup 2 index /Ff fget not { 0 } if write=
  dup 2 index /Q fget not { 0 } if write=
  dup (Tform ET) write=
  dup .fileposition /Length exch def
  /File File 0 Length getinterval def
  closefile             % <annot>
  end
} bind executeonly def

/can-regenerate-ap { % <annot> -> <bool>
  //false exch
  NeedAppearances {
    dup /FT fget {
     dup /Tx eq {
       pop
       dup /V oknown {
         pop not 1
       } if
     } {
       /Ch eq {
         dup /V oknown {
           pop not 1
         } if
       } if
     } ifelse
    } if
  } if
  pop
} bind executeonly def

/drawwidget {			% <scalefactor_x> <scalefactor_y> <annot> drawwidget -

%% This code checks to see if we can geenrate an appearance stream for the
%% given widget, and if we can it ignores the given Appearance stream, so that
%% we generate one instead. This seems wrong to me, if we've been given an
%% appearance stream we should use it, no synthesize something else. Several
%% files in our regression test suite render 'incorrectly' when compared to
%% Acrobat with this removed, clearly Acrobat always ignores appearances. However
%% several other files are rendered better when we *don't* ignore the Appearance
%% So on balance I'm choosing to honour the appearance.
%%
%  dup /UpdatedAP known not {
%    dup can-regenerate-ap {
%      dup /AP undef
%    } if
%  } if

  % Acrobat doesn't draw Widget annotations unles they have both /FT
  % (which is defined as required) and /T keys present. Annoyingly
  % these can either be inherited from the Form Definition Field
  % dictionary (via the AcroForm tree) or present directly in the
  % annotation, so we need to check the annotation to make sure its
  % a Widget, then follow any /Parent key up to the root node
  % extracting and storing any FT or T keys as we go (we only care if
  % these are present, their value is immaterial). If after all that
  % both keys are not present, then we don't draw the annotation.

  dup /Subtype get /Widget eq {
    dup /FT known 1 index /T known and not {
      dup
      {
        dup /FT knownoget {
          /FT exch 3 index 3 1 roll put
        } if
        dup /T knownoget {
          /T exch 3 index 3 1 roll put
        } if
        /Parent knownoget not {
          exit
        } if
      } loop
    } if
    dup /FT known 1 index /T known and {
      //true
    } {
      (   **** Warning: A Widget annotation dictionary lacks either the FT or T key.\n)
      pdfformaterror
      (               Acrobat ignores such annotations, annotation will not be rendered.\n)
      pdfformaterror
      (               Output may not be as expected.\n) pdfformaterror
      //false
    } ifelse
  } {
    //true
  }ifelse

  {
    dup /AP knownoget {
      dup /N known not {
        (   **** Error: Appearance dictionary (AP) lacks the mandatory normal (N) appearance.\n)
        pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
      } if
      //false
      [/N /R /D] {
          % stack: scalex scaley annot appearance false key
        2 index exch knownogetdict {
          exch not exit
        } if
      } forall
          % stack: scalex scaley annot appearance value true
          % stack: scalex scaley annot appearance false
      dup {
        pop exch pop
                % Acrobat Distiller produces files in which this Form
                % XObject lacks Type and Subtype keys.  This is illegal,
                % but Acrobat Reader accepts it.  The only way we can
                % tell whether this is a Form or a set of sub-appearances
                % is by testing for the stream Length or File key.
                % If the stream lacks Length key, try File key.
        dup /Length knownoget { type /integertype eq } { //false } ifelse
        1 index /File knownoget { type /filetype eq or } if {
                  % If this is a form then simply use it
          //true
        } {
          1 index /AS knownoget not {
                  % If we do not have AS then use any appearance
            { exch pop oforce exit } forall //true
          } {
                  % Stack: annot Ndict AS
                  % Get the specified appearance.  If no appearance, then
                  % display nothing - set stack = false.
            knownoget
          } ifelse
        } ifelse
      } {
        exch pop	% discard useless AP dictionary
      } ifelse

                % Stack: scalex scaley annot appearance true
                % Stack: scalex scaley annot false
      {
        dup type /dicttype eq {
                % Draw appearance
                % Initialize graphic following "7.4.4 Appearance Streams"
          q graphicsbeginpage textbeginpage
          1 index annotrect pop pop translate
          3 index 3 index scale	% Apply scale factors
          dup /BBox knownoget {
            1 index /Matrix knownoget not { {1 0 0 1 0 0} } if
            .bbox_transform pop pop
            % Compensate for non-zero origin of BBox
            neg exch neg exch translate
          } if
          DoForm Q
        } {
          (   **** Error: Annotation's appearance is not a dictionary.\n)
          pdfformaterror
          (               Output may be incorrect.\n) pdfformaterror
        } ifelse
      } if
    } {
      dup /MK knownoget {    % mk
        dup /BG knownoget {  % mk bg
          dup length         % mk bg len
          //set_bc_color exch .knownget {
             gsave
             exec
             3 index 3 index scale
             1 index annotrect rectfill
             grestore
          } {
            pop
          } ifelse
        } if
        dup /BC knownoget {
          dup length
          //set_bc_color exch .knownget {
             gsave
             exec
             1 setlinewidth
             3 index 3 index scale
             1 index annotrect rectstroke
             grestore
          } {
            pop
          } ifelse
        } if
        pop
      } if

      dup can-regenerate-ap {
        make_tx_da
        dup /UpdatedAP //true put
        3 copy drawwidget
      } if
    } ifelse
  } if
  pop pop pop
} bind executeonly def


currentdict /set_bc_color undef

%  For annotation object we have to determine the size of the output rectangle
%  and the size of the BBox for the form XObject. From these we calculate
%  a scale factors for drawing it.
/calc_annot_scale {		% <annot> calc_annot_scale <x_scale> <y_scale>
  dup /Rect knownoget {
    pop dup annotrect 4 2 roll pop pop	 % get width height size in user space
    2 index /AP knownoget {
      /N knownogetdict {        % <<Annot>> x y <<N>>
        dup 4 index /AS knownoget {
          knownoget {
            exch pop
          } if
        } {
          pop
        } ifelse
        dup /Matrix knownoget not { {1 0 0 1 0 0} } if
        exch /BBox knownoget {  % <<>> x y  {matrix} [box]
          exch .bbox_transform  % <<>> x y  x0 y0 x1 y1
          3 -1 roll sub         % <<>> x y  x0 x1 y1-y0
          3 1 roll exch sub     % <<>> x y  y1-y0 x1-x0
          2 copy mul 0 eq {
            (   **** Error: /BBox has zero width or height, which is not allowed.\n)
            pdfformaterror
            (               Output may be incorrect.\n) pdfformaterror
            pop pop pop pop 1 1	% zero size -- revert to unity scaling
          } {
            3 1 roll div        % <<>> x x1-x0 y/(y1-y0)
            3 1 roll div        % <<>> y/(y1-y0) x/(x1-x0)
            exch                % <<>> x/(x1-x0) y/(y1-y0)
          } ifelse
        } {
          pop pop pop 1 1	% default to unity scaling
        } ifelse		% if we have /BBox
      } {
        pop pop 1 1
      } ifelse			% if we have /N
    } {
      pop pop 1 1
    } ifelse			% if we have /AP
    3 -1 roll pop
  } {
    (   **** Error: /Annot dict is missing required /Rect entry.\n)
    pdfformaterror
    (               Output may be incorrect.\n) pdfformaterror
    pop 1 1
  } ifelse
} bind executeonly def

/applyRD {
  % x y w h [l t r b]
  dup 0 get             % x y w h [] l
  6 -1 roll add
  5 1 roll              %x+l y w h []
  dup 1 get             %x+l y w h [] b
  5 -1 roll add         %x+l w h [] b+y
  4 1 roll              %x+l y+b w h []
  aload pop             %x+l y+b w h l t r b
  exch                  %x+l y+b w h l t b r
  4 -1 roll add         %x+l y+b w h t b r+l
  3 1 roll add          %x+l y+b w h r+l t+b
  3 -1 roll exch sub    %x+l y+b w r+l h-(t+b)
  3 1 roll sub          %x+l y+b h-(t+b) w-(r+l)
  exch
} bind executeonly def

% Draw an annotation.
/drawannottypes 20 dict begin

  /startannottransparency {
    PDFusingtransparency {
      dup /BM known {
        dup /BM get
        << exch /BM exch >>
      } {
        << >>
      }ifelse
      %% We should be able to use the Rect to create the group, but it seems
      %% Acrobat ignores this, or at least doesn't clip the annotation to it :-(
%      1 index /Rect known {
%        1 index annotrect exch % llx lly h w
%        3 index add exch   % x y urx h
%        2 index add
%      }{
        clippath pathbbox newpath
%      } ifelse
      .begintransparencygroup
    } if
  }bind executeonly def

  /endannottransparency {
    PDFusingtransparency {
      .endtransparencygroup
    } if
  }bind executeonly def

  /ValidateAP {
    dup /AP oknown {
        dup /AP oget
        /N oknown not {
          //false
        } {
          //true
        } ifelse
    } {
      //false
    }ifelse
  } bind executeonly def

  % x0 y0 x1 y1 x2 y2 x3 y3 -> x0 y0 x1-x0 y1-y0 x2-x0 y2-y0
  /quadpoints2basis {
    8 { oforce 8 1 roll } repeat

    % The text is oriented with respect to the vertex with the smallest
    % y value (or the leftmost of those, if there are two such vertices)
    % (x0, y0) and the next vertex in a counterclockwise direction
    % (x1, y1), regardless of whether these are the first two points in
    % the QuadPoints array.

    2 {
      2 index 1 index eq {
        3 index 2 index gt {
          4 2 roll
        } if
      } {
        2 index 1 index gt {
          4 2 roll
        } if
      } ifelse
      8 4 roll
    } repeat
    6 index 3 index gt {
      8 4 roll
    } if

    %  ^
    %  |
    %  * (x2,y2)    * (x3,y3)
    %  |
    %  |
    %  *------------*->
    %  (x0,y0)      (x1,y1)

    pop pop           % x0 y0 x1 y1 x2 y2
    4 index sub exch  % x0 y0 x1 y1 y2-y0 x2
    5 index sub exch  % x0 y0 x1 y1 x2-x0 y2-y0
    4 2 roll
    4 index sub exch  % x0 y0 x2-x0 y2-y0 y1-y0 x1
    5 index sub exch  % x0 y0 x2-x0 y2-y0 x1-x0 y1-y0
    4 2 roll          % x0 y0 x1-x0 y1-y0 x2-x0 y2-y0
  } bind executeonly def

  /Square {
    //ValidateAP exec
    {
      //true
    } {
      gsave
      //startannottransparency exec
      dup
      annotsetinteriorcolor
      {
        gsave
        dup /ca knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
        dup annotrect
        5 index /RD knownoget {
          applyRD
        } if
        rectfill
        grestore
        dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
        dup annotsetcolor {
          drawborder
        } if
        //false
      }{
        dup annotrect
        5 index /RD knownoget {
          applyRD
        } if
        drawopdict /re get exec
        dup annotsetcolor {
          strokeborderpath
        } if
      } ifelse
      //endannottransparency exec
      grestore
      //false
    }ifelse
  } bind executeonly def

%% Width Height drawellipse -
/drawellipse {
  %% Don Lancaster's code for drawing an ellipse
  0.55228475 0.00045 sub % improved magic value
  3 1 roll               % magic width height
  2 div exch 2 div       % magic y-radius x-radius
  dup 3 index mul        % magic y-radius x-radius x-magic
  2 index                % magic y-radius x-radius x-magic y-radius
  5 -1 roll mul          % magic y-radius x-radius x-magic y-magic

  2 index neg 0 moveto                                          % xrad neg 0 moveto
  2 index neg 1 index 3 index neg 6 index 0 8 index curveto     % xrad neg ymag xmag neg yrad 0 yrad curveto
  1 index 4 index 4 index 3 index 1 index 0 curveto             % xmag yrad xrad ymag xrad 0 curveto
  2 index 1 index neg 3 index 6 index neg 0 1 index curveto     % xrad ymag neg xmag yrad neg 0 yrad neg curveto
                                                                % Stack: yrad xrad xmag ymag
  exch neg 4 1 roll 3 -1 roll neg 3 1 roll exch neg exch
  neg 1 index 0 curveto                                         % xmag neg yrad neg xrad neg ymag neg 0 curveto
}bind executeonly def

  /Circle {
    //ValidateAP exec
    {
      //true
    } {
      gsave
      //startannottransparency exec
      dup annotrect
      5 index /RD knownoget {
        applyRD
      } if
      4 2 roll exch 3 index 2 div add exch 2 index 2 div add
      translate //drawellipse exec
      dup
      fillborderpath
      dup annotsetcolor {
        strokeborderpath
      } if
      //endannottransparency exec
      grestore
      //false
    } ifelse
  } bind executeonly def

  /Polygon {
    //ValidateAP exec
    {
      //true
    } {
      gsave
      //startannottransparency exec
      dup /Vertices knownoget {
        dup length 2 div 1 sub cvi 0 1 3 -1 roll
        {
          2 mul dup
          2 index exch 2 getinterval aload pop
          3 -1 roll 0 eq {
            moveto
          }{
            lineto
          } ifelse
        }
        for
        pop
        closepath
        //true
      } {
          (   **** Error: Invalid Vertices for Polygon, annotation has not been drawn.\n)
          pdfformaterror
          (               Output may be incorrect.\n) pdfformaterror
        //false
      } ifelse

      1 index annotsetinteriorcolor {
        //true
      }{
        //false
      }ifelse
      and

      {
        gsave
        dup /ca knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
        fill
        grestore
        dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
        dup annotsetcolor {
          strokeborderpath
        } if
      } {
        dup annotsetcolor {
          strokeborderpath
        } if
      } ifelse
      //endannottransparency exec
      //false
      grestore
    } ifelse
  } bind executeonly def

  /LineEnd_dict 10 dict begin
    %% Stack contains <annot>
    %% CTM rotated so line segment is vertical, translated so line endpoint at 0,0

    /Square {
      dup
      /BS knownoget {
        /W knownoget {
        }{
          1
        }ifelse
      }{
        1
      }ifelse
      dup 2.5 mul
      gsave
      dup neg 1 index neg exch moveto
      dup neg 1 index lineto
      dup 1 index exch lineto
      dup neg lineto
      closepath
      1 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
      1 index fillborderpath
      grestore
      3 mul
      dup neg 1 index neg exch moveto
      dup neg 1 index lineto
      dup 1 index exch lineto
      dup neg lineto
      closepath
      strokeborderpath
    } bind executeonly def
    /Circle {
      dup
      /BS knownoget {
        /W knownoget {
        }{
          1
        }ifelse
      }{
        1
      }ifelse
      dup
      gsave
      2.5 mul dup
      0 moveto
      0 0 3 -1 roll 0 360 arc
      1 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
      1 index fillborderpath
      grestore
      3 mul dup
      0 moveto
      0 0 3 -1 roll 0 360 arc
      strokeborderpath
    } bind executeonly def
    /Diamond {
      dup
      /BS knownoget {
        /W knownoget {
        }{
          1
        }ifelse
      }{
        1
      }ifelse
      dup 2.5 mul
      gsave
      dup neg 0 exch moveto
      dup neg 0 lineto
      dup 0 exch lineto
      0 lineto
      closepath
      1 index /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
      1 index fillborderpath
      grestore
      3 mul
      dup neg 0 exch moveto
      dup neg 0 lineto
      dup 0 exch lineto
      0 lineto
      closepath
      strokeborderpath
    } bind executeonly def
    /OpenArrow {
      dup
      gsave
      /BS knownoget {
        /W knownoget {
        }{
          1
        }ifelse
      }{
        1
      }ifelse
      0 setlinejoin
      dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto
      dup 6 mul neg exch 4 mul lineto
      strokeborderpath
      grestore
    } bind executeonly def
    /ClosedArrow {
      dup
      gsave
      /BS knownoget {
        /W knownoget {
        }{
          1
        }ifelse
      }{
        1
      }ifelse
      dup
      gsave
      0 setlinejoin
      dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto
      dup 6 mul neg exch 4 mul lineto closepath
      1 index strokeborderpath
      grestore
      dup 1.3 mul neg 0 translate
      dup 2 div sub
      dup 8.4 mul neg 1 index 5.9 mul neg moveto dup 1.2 div neg 0 lineto
      dup 8.4 mul neg exch 5.9 mul lineto closepath
      dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
      fillborderpath
      grestore
    } bind executeonly def
    /None {pop} bind executeonly def
    /Butt {
      dup
      /BS knownoget {
        /W knownoget {
        }{
          1
        }ifelse
      }{
        1
      }ifelse
      3 mul dup neg 0 exch moveto 0 exch lineto
      strokeborderpath
    } bind executeonly def
    /ROpenArrow {
      gsave
      dup
      /BS knownoget {
        /W knownoget {
        }{
          1
        }ifelse
      }{
        1
      }ifelse
      180 rotate
      0 setlinejoin
      dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto
      dup 6 mul neg exch 4 mul lineto
      strokeborderpath
      grestore
    } bind executeonly def
    /RClosedArrow {
      gsave
      dup
      /BS knownoget {
        /W knownoget {
        }{
          1
        }ifelse
      }{
        1
      }ifelse
      180 rotate
      dup
      gsave
      0 setlinejoin
      dup 6 mul neg 1 index 4 mul neg moveto dup 1.2 div neg 0 lineto
      dup 6 mul neg exch 4 mul lineto closepath
      1 index strokeborderpath
      grestore
      dup 1.3 mul neg 0 translate
      dup 2 div sub
      dup 8.4 mul neg 1 index 5.9 mul neg moveto dup 1.2 div neg 0 lineto
      dup 8.4 mul neg exch 5.9 mul lineto closepath
      dup /CA knownoget {dup .setstrokeconstantalpha .setfillconstantalpha} if
      fillborderpath
      grestore
    } bind executeonly def
    /Slash {
      gsave
      dup
      /BS knownoget {
        /W knownoget {
        }{
          1
        }ifelse
      }{
        1
      }ifelse
      330 rotate
      3 mul dup neg 0 exch moveto 0 exch lineto
      strokeborderpath
      grestore
    } bind executeonly def

  currentdict end readonly def

  /Line  {
    //ValidateAP exec
    {
      //true
    } {
      gsave
      //startannottransparency exec
      dup annotsetcolor {
        dup /L knownoget {
          1 index /LE knownoget { % <annot> [x1 y1 x2 y2] [LE1 LE2]
            gsave
            1 index aload pop     % <annot> [x1 y1 x2 y2] [LE1 LE2] x1 y1 x2 y2
            3 -1 roll sub         % <annot> [x1 y1 x2 y2] [LE1 LE2] x1 x2 dy
            3 1 roll exch sub     % <annot> [x1 y1 x2 y2] [LE1 LE2] dy dx
            3 index aload pop 4 2 roll pop pop
            translate
            0 0 moveto
            {atan} stopped {pop pop 0} if           % <annot> [x1 y1 x2 y2] [LE1 LE2]
            rotate
            dup 1 get             % <annot> [x1 y1 x2 y2] [LE1 LE2] LE1
            dup //LineEnd_dict exch known not
            {
              pop /None
            } if
            //LineEnd_dict exch   % <annot> [x1 y1 x2 y2] [LE1 LE2] <dict> LE1
            get                   % <annot> [x1 y1 x2 y2] [LE1 LE2] {}
            3 index exch          % <annot> [x1 y1 x2 y2] [LE1 LE2] <annot> {}
            exec
            grestore
            gsave
            1 index aload pop  % x1 y1 x2 y2
            3 -1 roll sub      % x1 x2 dy
            3 1 roll exch sub  % dy dx
            3 index aload pop pop pop
            translate
            0 0 moveto
            {atan} stopped {pop pop 0} if 180 add
            rotate
            0 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec
            grestore
          }if
          aload pop 4 2 roll
          moveto lineto
          strokeborderpath
        }{
          (   **** Error: Invalid L array for Line, annotation has not been drawn.\n)
          pdfformaterror
          (               Output may be incorrect.\n) pdfformaterror
          pop
        } ifelse
      } if
      //endannottransparency exec
      //false
      grestore
    } ifelse
  } bind executeonly def

  /PolyLine {
    //ValidateAP exec
    {
      //true
    } {
      gsave
      //startannottransparency exec
      dup annotsetcolor pop
      dup /Vertices knownoget {
        1 index /LE knownoget {
          gsave
          1 index 0 4 getinterval aload pop
          4 2 roll
          2 copy translate 4 2 roll
          3 -1 roll exch sub      % x1 x2 dy
          3 1 roll sub  % dy dx
          {atan} stopped {pop pop 0} if
          rotate
          dup 0 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec
          grestore

          gsave
          1 index dup length 4 sub 4 getinterval aload pop
          2 copy translate
          3 -1 roll sub      % x1 x2 dy
          3 1 roll exch sub  % dy dx
          {atan} stopped {pop pop 0} if
          rotate
          1 get dup //LineEnd_dict exch known not {pop /None} if //LineEnd_dict exch get 3 index exch exec
          grestore
        } if
        dup length 2 div 1 sub cvi 0 1 3 -1 roll
        {
          2 mul dup
          2 index exch 2 getinterval aload pop
          3 -1 roll 0 eq {
            moveto
          }{
            lineto
          } ifelse
        }
        for
        pop
        //true
      } {
          (   **** Error: Invalid Vertices for Polygon, annotation has not been drawn.\n)
          pdfformaterror
          (               Output may be incorrect.\n) pdfformaterror
        //false
      } ifelse

      {
        strokeborderpath
      } if
      //endannottransparency exec
      //false
      grestore
    } ifelse
  } bind executeonly def

  /Link { % <annot> -> <false>
    //startannottransparency exec
    dup annotsetcolor {
      dup drawborder dup calc_annot_scale
      2 copy mul 0 ne
      {3 -1 roll drawwidget}
      {
        pop pop
        (   **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
      }ifelse
    } if
    //endannottransparency exec
    //false
  } bind executeonly def

  /Ink { % <annot> -> <annot> <true>
         % <annot> -> <false>
    //ValidateAP exec
    {
      //true
    } {
      //startannottransparency exec
      1 setlinewidth
      1 setlinecap
      1 setlinejoin
      dup annotsetcolor
      {
        dup calc_annot_scale
        2 copy mul 0 ne
        {
            scale
            dup /InkList knownoget {
              { oforce
                mark exch { oforce } forall
                .pdfinkpath
                stroke
              } forall
              pop
            } {
              /Path knownoget {
                oforce
                dup length 1 sub 0 1 3 -1 roll {
                  dup 0 eq {
                    1 index exch get aload pop moveto
                  } {
                    1 index exch get dup length 2 eq {
                      aload pop lineto
                    }{
                      aload pop curveto
                    } ifelse
                  }ifelse
                } for
                pop dup
                strokeborderpath
              } if
            }ifelse
        }
        {
          pop pop
          (   **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
          (               Output may be incorrect.\n) pdfformaterror
        }
        ifelse
      } if
      //endannottransparency exec
      //false
    } ifelse
  } bind executeonly def

  /Underline {
    //ValidateAP exec
    {
      //true
    } {
      0 setlinecap
      dup annotsetcolor
      {
        dup calc_annot_scale
        2 copy mul 0 ne
        {
            scale
            /QuadPoints knownoget {
              aload length 8 idiv {
                //quadpoints2basis exec

                % Acrobat draws the line at 1/7 of the box width from the bottom
                % of the box and 1/16 thick of the box width. /Rect is ignored.

                2 copy dup mul exch dup mul add sqrt 16 div setlinewidth
                7 div 4 index add exch % x0 y0 x1-x0 y1-y0 (y2-y0)/7+y0 x2-x0
                7 div 5 index add exch % x0 y0 x1-x0 y1-y0 (x2-x0)/7+x0 (y2-y0)/7+y0
                2 copy moveto
                2 index add exch
                3 index add exch lineto % x0 y0 x1-x0 y1-y0
                pop pop pop pop
                stroke
              } repeat
            } if
        }
        {
          pop pop
          (   **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
          (               Output may be incorrect.\n) pdfformaterror
        }
        ifelse
      } if
      //false
    } ifelse
  } bind executeonly def

  /StrikeOut {
    //ValidateAP exec
    {
      //true
    } {
      0 setlinecap
      dup annotsetcolor
      {
        dup calc_annot_scale
        2 copy mul 0 ne
        {
            scale
            /QuadPoints knownoget {
              aload length 8 idiv {
                //quadpoints2basis exec

                % Acrobat draws the line at 3/7 of the box width from the bottom
                % of the box and 1/16 thick of the box width. /Rect is ignored.

                2 copy dup mul exch dup mul add sqrt 16 div setlinewidth
                0.4285714 mul 4 index add exch % x0 y0 x1-x0 y1-y0 (y2-y0)*3/7+y0 x2-x0
                0.4285714 mul 5 index add exch % x0 y0 x1-x0 y1-y0 (x2-x0)*3/7+x0 (y2-y0)*3/7+y0
                2 copy moveto
                2 index add exch
                3 index add exch lineto % x0 y0 x1-x0 y1-y0
                pop pop pop pop
                stroke
              } repeat
            } if
        }
        {
          pop pop
          (   **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
          (               Output may be incorrect.\n) pdfformaterror
        }
        ifelse
      } if
      //false
    } ifelse
  } bind executeonly def

  % Connect 2 points with an arc that has max distance from the line
  % segment to the ark equal 1/4 of the radius.
  /highlight-arc {                      % x1 y1 x0 y0 -> -
    4 2 roll                            % x0 y0 x1 y1
    dup 3 index add 2 div               % x0 y0 x1 y1 (y1+y0)/2
    2 index 5 index sub .9375 mul sub   % x0 y0 x1 y1 (y1+y0)/2-15/16*dx=yc
    4 index 3 index add 2 div           % x0 y0 x1 y1 yc (x0+x1)/2
    2 index 5 index sub .9375 mul add   % x0 y0 x1 y1 yc xc
    exch                                % x0 y0 x1 y1 xc yc
    dup 3 index exch sub                % x0 y0 x1 y1 xc yc y1-yc
    4 index 3 index sub                 % x0 y0 x1 y1 xc yc y1-yc x1-xc
    dup dup mul 2 index dup mul add sqrt %x0 y0 x1 y1 xc yc y1-yc x1-xc r
    3 1 roll atan                       % x0 y0 x1 y1 xc yc r a1
    6 index 3 index sub                 % x0 y0 x1 y1 xc yc r a1 y0-yc
    8 index 5 index sub                 % x0 y0 x1 y1 xc yc r a1 y0-yc x0-xc
    atan                                % x0 y0 x1 y1 xc yc r a1 a2
    exch arcn                           % x0 y0 x1 y1
    pop pop pop pop
  } bind executeonly def

  /emptydict 0 dict readonly def

  /Highlight {
    //ValidateAP exec
    {
      //true
    } {
    0 setlinecap
    dup annotsetcolor
    {
      /QuadPoints knownoget {
        aload length 8 idiv {
          6 -2 roll
          2 copy moveto
          //highlight-arc exec
          2 copy lineto
          //highlight-arc exec
          closepath
        } repeat
        PDFusingtransparency {
          //emptydict
          % If we get an error, just emit an empty box
          { pathbbox } stopped { 0 0 0 0 } if
          2 index add exch 3 index add exch .begintransparencygroup
          /Multiply .setblendmode
          fill
          .endtransparencygroup
        } { % for -dNOTRANSPARENCY
          stroke newpath
        } ifelse
      } if
    } if
    //false
    } ifelse
  } bind executeonly def
  currentdict /emptydict undef
  currentdict /highlight-arc undef

  /Squiggly {
    //ValidateAP exec
    {
      //true
    } {
      //startannottransparency exec
      dup annotsetcolor
      {
        dup calc_annot_scale
        2 copy mul 0 ne
        {
            scale
            /QuadPoints knownoget {
              aload length 8 idiv {
                gsave
                8 copy moveto lineto
                4 2 roll lineto lineto closepath clip newpath
                //quadpoints2basis exec
                6 -2 roll translate    % adjust for x0 y0      % x1-x0 y1-y0 x2-x0 y2-y0
                1 index 56 div 1 index 56 div translate        % zigzag box is 1/56 up
                1 index 72 div 1 index 72 div translate        % the line in the box is 1/72 up
                2 copy dup mul exch dup mul add sqrt           % x1-x0 y1-y0 x2-x0 y2-y0 |p2|
                4 index dup mul 4 index dup mul add sqrt       % x1-x0 y1-y0 x2-x0 y2-y0 |p2| |p1|
                dup 0 gt 2 index 0 gt and {
                  div                                          % x1-x0 y1-y0 x2-x0 y2-y0 |p2|/|p1|=p12
                  dup 1 exch div 4 mul 1 add cvi exch 6 2 roll % cnt p12 x1-x0 y1-y0 x2-x0 y2-y0
                  4 2 roll                                     % cnt p12 x2-x0 y2-y0 x1-x0 y1-y0
                  4 index mul exch 4 index mul exch            % cnt p12 x2-x0 y2-y0 (x1-x0)*p12 (y1-y0)*p12
                  4 2 roll 0 0 6 array astore concat           % cnt p12
                  1 40 div 1 72 div scale
                  pop                                          % cnt
                  0 0 moveto
                  1 setlinecap
                  1 setlinejoin
                  1 setlinewidth
                  {
                    5 10 lineto
                    10 0 lineto
                    10 0 translate
                  } repeat
                  stroke
                } {
                  6 { pop } repeat
                } ifelse
                grestore
              } repeat
            } if
        }
        {
          pop pop
          (   **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
          (               Output may be incorrect.\n) pdfformaterror
        }
        ifelse
      } if
      //endannottransparency exec
      //false
    } ifelse
  } bind executeonly def

  /Text {
    //ValidateAP exec
    {
      //true
    } {
      //startannottransparency exec
      dup calc_annot_scale
      2 copy mul 0 ne
      {
          scale
          annotrect 4 2 roll translate
          exch pop

          % Draw a page icon
          0.5 exch 18.5 sub translate
          1 setlinewidth
          0.75 setgray
          0.5 -1 moveto 10 -1 lineto 15 4 lineto 15 17.5 lineto stroke

          0 0 moveto
          9 0 lineto
          14 5 lineto
          14 18 lineto
          0 18 lineto closepath
          gsave .5 setgray fill grestore 0 setgray stroke

          3 8 moveto 7.5 8 lineto
          3 11 moveto 10 11 lineto
          3 14 moveto 10 14 lineto
          9 0 moveto 9 5 lineto 14 5 lineto
          stroke
      }
      {
        pop pop
        (   **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
      }
      ifelse
      //endannottransparency exec
      //false
    } ifelse
  } bind executeonly def

  /FreeText {
    //ValidateAP exec
    {
      //true
    }
    %% We either have no appearance, or its invalid, make one up.
    {
      gsave

      //startannottransparency exec
      dup annotrect rectclip

      dup /CA knownoget {
        dup .setstrokeconstantalpha .setfillconstantalpha
      } if

      dup /ca knownoget {
        dup .setstrokeconstantalpha .setfillconstantalpha
      } if

      dup /C knownoget {
        dup length 4 eq {
          aload pop setcmykcolor //true
        }{
          dup length 3 eq {
            aload pop setrgbcolor //true
          }{
            dup length 1 eq {
              aload pop setgray //true
            } {
              dup length 0 eq {
                pop
                //false
              }{
                (   **** Error: invalid color specified for FreeText annotation /C entry)
                pdfformaterror
                (               Output may be incorrect.\n) pdfformaterror
                //false
              } ifelse
            } ifelse
          } ifelse
        } ifelse
      }{
        //false
      } ifelse
      {
        dup annotrect
        5 index /RD knownoget {
          applyRD
        } if
        rectfill
      } if

      %% get and process the default appearance string, if we don't have one, use a default
      /DA_Action_Dict
      <<
        /Tf
        {
          exch dup /Helv eq
          {
            pop /Helvetica dup findfont
          }
          {dup findfont}ifelse

          % re-encode the font to PDFDocEncoding
          dup length dict begin
          {
            1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse
          } forall
          /Encoding /PDFDocEncoding /Encoding findresource def
          /FontName /Helvetica-PDFDocEncoding def
          currentdict
          end
          definefont
          exch scalefont setfont
        }
        /r  {aload pop setrgbcolor} % Can't find this actually defined anywhere, but Acrobat seems to honour it :-(
        /rg {setrgbcolor}
        /RG {setrgbcolor}
        /G  {setgray}
        /g  {setgray}
        /k  {setcmykcolor}
        /K  {setcmykcolor}
      >> def

      dup /DA knownoget {
        length string /tempstr exch def
        dup /DA get tempstr copy pop

        gstate
        mark
        {
          {
            %% This is kind of ugly, we use token to process the string
            %% and process each token separately.
            tempstr
            token {
              exch /tempstr exch def
              %% If the token is a name
              %%
              dup type /nametype eq {
                %% Is it a name we want to take actionon
                dup DA_Action_Dict exch known {
                  DA_Action_Dict exch get exec
                }{
                  %% Its not a name we know, is it executable
                  dup xcheck {exec} if
                } ifelse
              }{
                %% Not a name, just make it executable and execute it
                cvx exec
              }ifelse
            }{
              exit
            }ifelse
          } loop
        } stopped
        {cleartomark setgstate}
        {cleartomark pop} ifelse
      } {
        0 setgray
        /Helvetica findfont
        % re-encode the font to PDFDocEncoding
        dup length dict begin
        {
          1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse
        } forall
        /Encoding /PDFDocEncoding /Encoding findresource def
        /FontName /Helvetica-PDFDocEncoding def
        currentdict
        end
        /Helvetica-PDFDocEncoding exch definefont
        12 scalefont setfont
      }ifelse

      %% draw the border, if we don't have a border style dictionary, draw a default one.
      dup /BS knownoget
      {
        pop dup drawborder
      }{
        newpath
        0 setgray 1 setlinewidth
        dup annotrect
        5 index /RD knownoget {
          applyRD
          4 -1 roll 4 -1 roll 4 -1 roll 4 -1 roll
          4 2 roll
        } {
          4 -1 roll 1 add 4 -1 roll 1 add 4 -1 roll 2 sub 4 -1 roll 2 sub
          4 2 roll
        }ifelse
        moveto
        currentpoint exch 3 index add exch
        lineto
        currentpoint 2 index add
        lineto
        exch currentpoint 3 1 roll exch sub exch
        lineto
        currentpoint 3 -1 roll sub
        lineto stroke
      }ifelse

      gsave % in case we rotate the contents
      %% Start the current point at the top left of the annotation Rect
      %%
      dup /Rotate knownoget
      % x y w h - x' w' x' y'
      {
        dup 90 eq {
          pop
          dup annotrect
          5 index /RD knownoget {
            applyRD
          } if
          exch pop 3 -1 roll 2 index
          moveto 90 rotate
          1 index add
        } {
          dup 180 eq {
            pop
            dup annotrect
            5 index /RD knownoget {
              applyRD
            } if
            pop 3 -1 roll 1 index add -1 mul exch 1 index -1 mul 4 -1 roll
            moveto 180 rotate
            1 index add
          }{
            270 eq {
              dup annotrect
              5 index /RD knownoget {
                applyRD
              } if
              dup 4 -1 roll add 3 -1 roll 3 index add exch
              moveto 270 rotate
              exch pop currentpoint
              pop dup 3 -1 roll add
            }{
              dup annotrect
              5 index /RD knownoget {
                applyRD
                3 -1 roll add 2 index exch
                moveto 1 index add
              }{
                4 -1 roll 2 add 4 -1 roll 2 add 4 -1 roll 4 sub 4 -1 roll 4 sub
                3 -1 roll add 2 index exch
                moveto 1 index add
              } ifelse
            } ifelse
          } ifelse
        } ifelse
      }{
         dup annotrect
          5 index /RD knownoget {
            applyRD
            3 -1 roll add 2 index exch
            moveto 1 index add
          }{
           4 -1 roll 2 add 4 -1 roll 2 add 4 -1 roll 4 sub 4 -1 roll 4 sub
           3 -1 roll add 2 index exch
           moveto 1 index add
         } ifelse
      } ifelse

      %% Get the Contents string, if we don't have one, we're done
      %%
      2 index /Contents knownoget {
        dup length 0 gt {
          PDFusingtransparency {
            .begintransparencytextgroup
          } if
          %% Check for UTF16-BE, we probably don't work properly with this yet.
          %% (If the string is less than 4 bytes its either not UTF16-BE or it is
          %% but has no actual content)
          dup length 4 ge {
            dup 0 get 254 eq 1 index 1 get 255 eq and
          }{
            //false
          } ifelse

          {
            /FallBackFont /Identity-UTF16-H [/CIDFallBack] composefont 12 scalefont setfont
            dup length 2 div 1 sub 0 1 3 -1 roll {
                                      %% llx urx (string) index
             1 index exch 2 mul 2 getinterval        %% llx urx (string) (substring)
              dup stringwidth pop currentpoint pop add 3 index gt {
                currentpoint exch pop 4 index exch 12 sub moveto
              } if
              show
            } for
            pop
          }
          {
            %% Heuristic to determine the height (ascender to descender) of the text
            %% for when we move down a line.
            gsave
            /..TextHeight (Hy) //false charpath pathbbox exch pop exch sub exch pop def
            grestore
            %% and use it immediatley to start the text one line down
            %%
            currentpoint ..TextHeight sub moveto
            %% Now we process each character code in the string. If we find
            %% a /r/ or /n then we drop a line. If the character would end up
            %% outside the Annot Rect, then we drop a line before showing it.
            %%
            dup length 1 sub 0 1 3 -1 roll {
                                      %% llx urx (string) index
              1 index exch get        %% llx urx (string) int
              dup 10 eq 1 index 13 eq or {
                pop
                currentpoint exch pop 3 index exch ..TextHeight sub moveto
              } {
                1 string dup 0 4 -1 roll
                put dup                 %% llx urx (string) (int) (int)
                stringwidth pop currentpoint pop add 3 index
                gt {
                  currentpoint exch pop 4 index exch ..TextHeight sub moveto
                } if
                show
              } ifelse
            } for
            pop
          }ifelse
          PDFusingtransparency {
            .endtransparencytextgroup
          } if
        }
        {
          pop
        } ifelse
      } if
      pop pop

      grestore % in case the contents were rotated
      dup /CL knownoget {
        dup length 6 eq {
          dup aload pop pop pop
        } {
          dup length 4 eq {
            dup aload pop
          } {
            pop 0
          } ifelse
        } ifelse
        4 2 roll
        exch 4 -1 roll sub
        3 1 roll exch sub
        atan exch
        aload pop moveto lineto lineto
        currentpoint
%        stroke
%        0 1 0 setrgbcolor
        moveto currentpoint translate 0 0 moveto
        360 exch sub rotate
        currentpoint
        -5 -8 rlineto
        moveto
        5 -8 rlineto
        stroke
      } if
      //endannottransparency exec
      //false
      grestore
    } ifelse
  } bind executeonly def

  /frame {
    { 255 div } forall setrgbcolor
    -95 -25 translate
    2 190 atan rotate
    {
      6 0 moveto
      190 0 190 6 6 arct
      190 47 184 47 6 arct
      0 47 0 41 6 arct
      0 0 6 0 6 arct
      closepath

      10 4 moveto
      185 4 185 9 5 arct
      185 43 180 43 5 arct
      5 43 5 38 5 arct
      5 4 9 4 5 arct
      closepath
      eofill
   }
   gsave 1 -1 translate 0.75 setgray dup exec grestore
   exec
  } bind executeonly def

  % (text) y h -> -
  /text {
    PDFusingtransparency {
      .begintransparencytextgroup
    } if
    /Times-Bold findfont
    % re-encode the font to PDFDocEncoding
    dup length dict begin
    {
      1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse
    } forall
    /Encoding /PDFDocEncoding /Encoding findresource def
    /FontName /Times-Bold-PDFDocEncoding def
    currentdict
    end
    /Times-Bold-PDFDocEncoding exch definefont
    exch scalefont setfont  % (text) y
    gsave
    0 0 moveto
    1 index //false charpath flattenpath pathbbox
    pop exch pop sub 2 div
    grestore
    95 add exch moveto
    gsave 1 -1 rmoveto  0.75 setgray dup show grestore
    show
    PDFusingtransparency {
      .endtransparencytextgroup
    } if
  } bind executeonly def

  /red   <ef4023> readonly def
  /green <3fae49> readonly def
  /blue  <0072bc> readonly def

  /stamp_dict 14 dict begin
    /Approved {
      //green //frame exec
      (APPROVED) 13 30 //text exec
    } bind executeonly def
    /AsIs {
      //red //frame exec
      (AS IS) 13 30 //text exec
    } bind executeonly def
    /Confidential {
      //red //frame exec
      (CONFIDENTIAL) 17 20 //text exec
    } bind executeonly def
    /Departmental {
      //blue //frame exec
      (DEPARTMENTAL) 17 20 //text exec
    } bind executeonly def
    /Draft {
      //red //frame exec
      (DRAFT) 13 30 //text exec
    } bind executeonly def
    /Experimental {
      //blue //frame exec
      (EXPERIMENTAL) 17 20 //text exec
    } bind executeonly def
    /Expired {
      //red //frame exec
      (EXPIRED) 13 30 //text exec
    } bind executeonly def
    /Final {
      //red //frame exec
      (FINAL) 13 30 //text exec
    } bind executeonly def
    /ForComment {
      //green //frame exec
      (FOR COMMENT) 17 20 //text exec
    } bind executeonly def
    /ForPublicRelease {
      //green //frame exec
      (FOR PUBLIC) 26 18 //text exec
      (RELEASE)  8.5 18 //text exec
    } bind executeonly def
    /NotApproved {
      //red //frame exec
      (NOT APPROVED) 17 20 //text exec
    } bdef
    /NotForPublicRelease {
      //red //frame exec
      (NOT FOR) 26 18 //text exec
      (PUBLIC RELEASE) 8.5 18 //text exec
    } bind executeonly def
    /Sold {
      //blue //frame exec
      (SOLD) 13 30 //text exec
    } bind executeonly def
    /TopSecret {
      //red //frame exec
      (TOP SECRET) 14 26 //text exec
    } bind executeonly def
  currentdict end readonly def

  {/text/frame/red/green/blue} {currentdict exch undef} forall

  /Stamp  {
    //ValidateAP exec
    {
      //true
    } {
      //startannottransparency exec
      dup calc_annot_scale
      2 copy mul 0 ne
      {
          scale
          % translate to the center of Rect
          dup annotrect
          4 2 roll  % dx dy x0 y0
          2 index 2 div add exch
          3 index 2 div add exch translate  % dx dy

          50 div exch 190 div .min dup 0.0 eq {pop 1.0} if dup scale

          /Name knownoget not { /Draft } if
          //stamp_dict 1 index known not { exch pop /Draft exch } if
          //stamp_dict exch get exec
      }
      {
        pop pop
        (   **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
        (               Output may be incorrect.\n) pdfformaterror
      }
      ifelse
      //endannottransparency exec
      //false
    } ifelse
  } bind executeonly def

  /Popup {
    dup /Open oknown {
      dup /Open get {
        //ValidateAP exec
        {
          //true
        } {
          gsave
          //startannottransparency exec
          newpath
          0.05 setlinewidth
          dup /Parent .knownget {
            oforce
          } {
            dup /P .knownget {
              oforce
            } {
              dup
            } ifelse
          } ifelse
          /C .knownget {
            aload pop
          }{
            1 1 0
          }ifelse
          setrgbcolor
          dup /Rect get
          dup aload pop
          2 index sub
          exch 3 index sub exch
          4 copy
          gsave 1 setgray rectfill grestore
          gsave 0 setgray rectstroke grestore
          1 index /Parent .knownget {
            oforce
          }{
            1 index /P .knownget {
              oforce
            }{
              1 index
            } ifelse
          }ifelse
          dup
          /Contents .knownget {
            gsave
            PDFusingtransparency {
              .begintransparencytextgroup
            } if
            0 setgray
            /Helvetica findfont
            % re-encode the font to PDFDocEncoding
            dup length dict begin
            {
              1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse
            } forall
            /Encoding /PDFDocEncoding /Encoding findresource def
            /FontName /Helvetica-PDFDocEncoding def
            currentdict
            end
            /Helvetica-PDFDocEncoding exch definefont
            9 scalefont setfont
            2 index aload pop 3 1 roll pop pop 30 sub exch 5 add exch
            moveto show
            PDFusingtransparency {
              .endtransparencytextgroup
            } if
            grestore
          } if
          exch
          dup aload pop 3 -1 roll pop exch 2 index sub -15
          4 copy rectfill
          0 setgray rectstroke
          exch
          /T .knownget {
            gsave
            PDFusingtransparency {
              .begintransparencytextgroup
            } if
            0 setgray
            /Helvetica findfont
            % re-encode the font to PDFDocEncoding
            dup length dict begin
            {
              1 index /FID ne 2 index /UniqueID ne and { def } { pop pop } ifelse
            } forall
            /Encoding /PDFDocEncoding /Encoding findresource def
            /FontName /Helvetica-PDFDocEncoding def
            currentdict
            end
            /Helvetica-PDFDocEncoding exch definefont
            9 scalefont setfont
            dup stringwidth pop
            2 index aload pop pop exch pop exch sub
            exch sub 2 div 2 index aload pop 3 1 roll pop pop 11 sub 3 1 roll add exch moveto
            show
            PDFusingtransparency {
              .endtransparencytextgroup
            } if
            grestore
          } if
          grestore
          //endannottransparency exec
          //false
        } ifelse
      } {
        pop //false
      }ifelse
    } {
      pop //false
    }ifelse
  } bind executeonly def

  /Redact {
    %% Redact annotations are part of a process, a Redact annotation is only present
    %% until the content is removed, before that the content should be present and
    %% I beleive we should print it. So take no action for Redact annotations if they
    %% have no appearance.
    //ValidateAP exec
    {
      //true
    } {
      //false
    } ifelse
  } bind executeonly def

currentdict /startannottransparency undef
currentdict /endannottransparency undef
currentdict /ValidateAP undef
currentdict /quadpoints2basis undef
currentdict /drawellipse undef
currentdict end readonly def

/.PDFDrawAnnotType?
{
    //false exch
    /ShowAnnotTypes where
    {
      /ShowAnnotTypes get
      {
        dup /* eq exch 2 index eq or
        {
          pop //true exch
          exit
        } if
     } forall
     pop
   }
   {pop pop //true}
   ifelse
} bind executeonly def

/.PDFPreserveAnnotType?
{
    //false exch
    /PreserveAnnotTypes where
    {
      /PreserveAnnotTypes get
      {
        dup /* eq exch 2 index eq or
        {
          pop //true exch
          exit
        } if
     } forall
     pop
   }
   {pop pop //true}
   ifelse
} bind executeonly def

/drawannot {		% <annot> drawannot -
  dup annotvisible {
    gsave
    dup dup /Subtype knownoget {
      dup //.PDFDrawAnnotType? exec
      {
        //drawannottypes exch .knownget { exec } { //true } ifelse
        {
          dup calc_annot_scale 2 copy mul 0 ne
          {
            3 -1 roll drawwidget
          }
          {
            (   **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
            (               Output may be incorrect.\n) pdfformaterror
          }ifelse % Draw rejected annots as widgets
        } if			% type known
      }
      {
        pop
      }ifelse
    } {
      pop
      (   **** Error: Ignoring /Annot dict without required /Subtype entry.\n)
      pdfformaterror
      (               Output may be incorrect.\n) pdfformaterror
    } ifelse
    grestore
  } if pop			% annotvisible
} bind executeonly def
currentdict /drawannottypes undef

% Draw an annotation.

/loadannot {
  dup /AP .knownget {                                       % <<Annot dict>> <<Appearance dictionary>> true | false
    oforce

    dup {                                                       % <<Annot dict>> <<Appearance dict>> /Key <</Key dict>>
    oforce                                                  % <<Annot dict>> <<Appearance dict>> /Key <<resolved /Key dict>>

    %%
    %% Check to see if the apperance key has a simple stream or a dictionary of states
    %%
    dup /Subtype known                                      % <<Annot dict>> <<Appearance dict>> /Key <<resolved /Key dict>> bool
    {
      %% Simple appearance stream
      DoAppearance                                          % <<Annot dict>> <<Appearance dict>> /Key
      2 index                                               % <<Annot dict>> <<Appearance dict>> /Key <<Annot dict>>
      /AP <<                                                % <<Annot dict>> <<Appearance dict>> /Key <<Annot dict>> /AP <<
      4 -1 roll MakeAppearanceName cvx cvn >> put           % <<Annot dict>> <<Appearance dict>>
    } {
      %% dictionary of states   <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>>
      dup                                                   % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> <<appearance states dict>>
      {                                                     % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> /StateKey <<State dictionary>>
        oforce                                              % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> /StateKey <<resolved State dictionary>>
        DoAppearance                                        % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> /StateKey
        1 index exch                                        % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> <<appearance states dict>> /StateKey
        MakeAppearanceName cvx cvn                          % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>> <<appearance states dict>> /StateKey {}
        put                                                 % <<Annot dict>> <<Appearance dict>> /Key <<appearance states dict>>
      } forall
      put                                                   % <<Annot dict>> <<Appearance dict>> /Key
      dup
    }ifelse
    } forall
    pop                                                   % <<Annot dict>>
  } if

  %% Parent (or /P) references will be incorrect. Remove them
  %% for now as they are optional.
  dup /Popup known {dup /Popup undef} if
  dup /IRT known {dup /IRT undef} if
  dup /RT known {dup /RT undef} if
  dup /P known {dup /P undef} if
  dup /Parent known {dup /Parent undef} if

  %% Resolve any indirect references. May need further work :-(
  {
    %% We know /AP doesn't need processing, we handled that above...
    1 index /AP eq not {
      dup {oforce} stopped not {exch pop} if
      dup type /dicttype eq{
        dup
        {
          dup {oforce} stopped not {exch pop} if
          2 index 3 1 roll put
        } forall
        Removepdfobj#
      } if
      dup type /arraytype eq {
        0 1 2 index length 1 sub{
          dup 2 index exch get dup {oforce} stopped not {exch pop} if
          2 index 3 1 roll put
        } for
      } if
    } if
  } forall
} bind executeonly def


/ApplyCTMToQuadPoints {
  %% Nasty hackery here really. We need to undo the HWResolution scaling which
  %% is done by pdfwrite. Default is 720 dpi, so 0.1. We also need to make
  %% sure that any translation of the page (because its been rotated for example)
  %% is also modified by the requisite amount. SO we ned to calculate a matrix
  %% which does the scaling and concatenate it with the current matrix.
  %% Do this inside a gsave/grestore pair to avoid side effects!

  gsave
  currentpagedevice /HWResolution get
  aload pop exch 72 exch div exch 72 exch div
  matrix 3 1 roll 2 index 3 3 -1 roll put
  1 index 0 3 -1 roll put
  matrix currentmatrix exch matrix concatmatrix
  setmatrix

  oforce

  %% QuadPoints are given as 'n' sequences of 8 numbers.

  mark exch aload counttomark 1 roll
  counttomark 1 sub 2 div cvi {
    transform
    counttomark 1 sub 2 roll
  } repeat
  counttomark -1 roll astore

  exch pop % the mark

  grestore
} bind executeonly def

/preserveannottypes 20 dict begin

/Circle {mark exch loadannot /ANN pdfmark  //false} bind executeonly def
/FileAttachment {mark exch loadannot /ANN pdfmark  //false} bind executeonly def
/FreeText {mark exch loadannot /ANN pdfmark  //false} bind executeonly def

/Highlight {
  mark exch
  dup /QuadPoints .knownget {
    1 index /QuadPoints 3 -1 roll
    ApplyCTMToQuadPoints
    put
  } if
  loadannot /ANN pdfmark  //false
} bind executeonly def

/Ink {mark exch loadannot /ANN pdfmark  //false} bind executeonly def

/PolyLine {mark exch loadannot /ANN pdfmark  //false} bind executeonly def

/Line {mark exch loadannot /ANN pdfmark //false} bind executeonly def

/Link {
    /NO_PDFMARK_DESTS where {pop NO_PDFMARK_DESTS not}{//true}ifelse
    {
    mark exch
    dup /BS knownoget { << exch { oforce } forall >> /BS exch 3 -1 roll } if
    dup /F knownoget { /F exch 3 -1 roll } if
    dup /C knownoget { /Color exch 3 -1 roll } if
    dup /Rect knownoget { /Rect exch 3 -1 roll } if
    dup /Border knownoget {
      dup type /arraytype eq {
        dup length 3 lt
      } {
        //true
      } ifelse {
        pop [ 0 0 0 ] % Following AR5 use invisible border.
      } if
      /Border exch 3 -1 roll
    } if
    dup /A knownoget {
      dup /URI known {
        /A mark 3 2 roll    % <<>> /A [ <<action>>
        { oforce } forall
        .dicttomark
        3 2 roll
      } {
        dup /S knownoget  {
          %% Because we process GoTo Destinations into absolute references in the PDF file
          %% we need to resolve the /D or /Dest. However, we must *not* do this for
          %% GoToR Destinations because (obviously) those are in a different file and
          %% we cannot resolve them into absolute references. We don't need to anyway
          %% because that file must already have a named destination.
          dup /GoTo eq {
            pop
            dup /D knownoget {
              exch pop exch dup length dict copy dup /Dest 4 -1 roll put
            } if
          }{
            dup /GoToR eq {
              pop /A mark       % <<..action dict..>> /A [
              3 2 roll          % /A [ <<..action dict..>>
              { oforce } forall
              .dicttomark
              3 2 roll
            }{
              dup /Launch eq {
                pop /A mark       % <<..action dict..>> /A [
                3 2 roll          % /A [ <<..action dict..>>
                { oforce } forall
                .dicttomark
                3 2 roll
              }{
                /Named eq {
                  /N knownoget {
                    namedactions exch .knownget {
                      exec {
                        pop
                        (   **** Warning: Ignoring a named action pointing out of the document page range.\n)
                        pdfformatwarning
                      } {
                        /Page exch 3 -1 roll
                      } ifelse
                    } if
                  } if
                } if
              }ifelse
            } ifelse
          } ifelse
        } if
      } ifelse
    } if
    { linkdest } stopped {
      cleartomark
      (   **** Warning: Link annotation points out of the document page range.\n)
      pdfformatwarning
    } {
      pop
      {
        %% Need to remove any '/.gs.pdfobj# key/value pairs from any dictionaries
        counttomark array astore dup length 1 sub 0 1 3 -1 roll {
          dup 2 index exch get Removepdfobj# 2 index 3 1 roll put
        } for aload pop
        /LNK pdfmark
      } stopped {cleartomark} if
    } ifelse
    }{pop} ifelse
    //false
} bind executeonly def

%% We don't handle movies correctly, so don't try to preserve them
%/Movie {mark exch loadannot /ANN pdfmark  //false} bind executeonly def
/Popup {mark exch loadannot /ANN pdfmark  //false} bind executeonly def
/Sound {mark exch loadannot /ANN pdfmark  //false} bind executeonly def
/Square {mark exch loadannot /ANN pdfmark //false} bind executeonly def
/Stamp {mark exch loadannot /ANN pdfmark  //false} bind executeonly def

/StrikeOut {
  mark exch
  dup /QuadPoints .knownget {
    1 index /QuadPoints 3 -1 roll
    ApplyCTMToQuadPoints
    put
  } if
  loadannot /ANN pdfmark  //false
} bind executeonly def

/Squiggly {
  mark exch
  dup /QuadPoints .knownget {
    1 index /QuadPoints 3 -1 roll
    ApplyCTMToQuadPoints
    put
  } if
  loadannot /ANN pdfmark  //false
} bind executeonly def

/Text {mark exch loadannot /ANN pdfmark  //false} bind executeonly def
/TrapNet {mark exch loadannot /ANN pdfmark  //false} bind executeonly def

/Underline {
  mark exch
  dup /QuadPoints .knownget {
    1 index /QuadPoints 3 -1 roll
    ApplyCTMToQuadPoints
    put
  } if
  loadannot /ANN pdfmark  //false
} bind executeonly def

%% Widget annotations are only used with AcroForms, and since we don't preserve AcroForms
%% we don't want to preserve widget annotations either, because the consumer of the new
%% PDF won't know what values they should take. So we draw widget annotations instead. If we
%% ever preserve AcroForms then we should alter this to preserve Widgets as well.
%% simply chane "drawannot" to "mark exch loadannot /ANN pdfmark"
/Widget {mark exch {drawannot} PDFSTOPONERROR {exec}{stopped {(Error: Ignoring invalid annotation, output may be incorrect.\n) pdfformaterror} if} ifelse cleartomark //false} bind executeonly def

currentdict end readonly def

/preserveannot {		% <annot> preserveannot -
  dup /.gs.pdfobj# known {
    dup /.gs.pdfobj# undef
  } if

  gsave
  dup dup /Subtype knownoget {
    dup //.PDFPreserveAnnotType? exec
    {
      //preserveannottypes exch .knownget { exec } { //true } ifelse
      {
        dup annotvisible {
          dup calc_annot_scale 2 copy mul 0 ne
          {
            3 -1 roll drawwidget
          }
          {
            (   **** Error: ignoring annotation with scale factor of 0\n) pdfformaterror
            (               Output may be incorrect.\n) pdfformaterror
          }ifelse % Draw rejected annots as widgets
        } {
            pop
        }ifelse
      } if
    }
    {
      % Not preserving this type of annotation
      % discard teh Subtype
      pop
      % copy the Annot dictionary and try drawing it instead
      dup drawannot
    } ifelse
    % type known
  } {
    pop
    (   **** Error: Ignoring /Annot dict without required /Subtype entry.\n)
    pdfformaterror
    (               Output may be incorrect.\n) pdfformaterror
  } ifelse
  grestore
} bind executeonly def

currentdict /preserveannottypes undef
currentdict /.PDFDrawAnnotType? undef

% ============================ AcroForm fields ============================ %

% Get an attribure of the 0th annotation of a node
/annot_oget {  % <annot> /Name annot_oget <value>
  1 index /Kids knownoget {
    0 oget exch oget exch pop
  } {
    oget
  } ifelse
} bind executeonly def

% All procedures have the signature:
% <acroform> <field> <annot|field> foo <acroform> <field> <annot|field>
/draw_terminal_field_dict 4 dict begin

/Btn {
  1 index /Tf pget not { 0 } if
  dup 16#20000 and 0 ne {
    pop % Push button
    dup /AP known {
      1 1 2 index drawwidget
    } {
      (Push button without appearance stream is not yet implemented) =
    } ifelse
  } {
    16#10000 and 0 ne {
        % Radio button
        dup /AP known {
          1 index /Kids oget {
            1 1 3 -1 roll drawwidget
          } forall
        } {
          (Radio button without appearance stream is not yet implemented) =
        } ifelse
    } {
        % Checkbox
        dup /AP known {
          dup 1 1 3 -1 roll drawwidget
        } {
          (CkeckBox without appearance stream is not yet implemented) =
        } ifelse
    } ifelse
  } ifelse
} bind executeonly def

/Tx {
  dup /AP known {
    dup 1 1 3 -1 roll drawwidget
  } {
    %% If we don't have a NeedApperances, treat as true, because Acrobat
    %% always regenerates Appearances anyway.
    2 index /NeedAppearances knownoget not { //true } if {
      dup /AP << /N 10 dict dup cvx begin >> put
      /Subtype /Form def
      /BBox [ 0 0 4 index /Rect oget { oforce } forall  3 -1 roll sub abs 3 1 roll sub abs exch ] def
      /Resources 3 index /DR pget not { 0 dict } if def
      /File 1000 string dup 3 1 roll def
      /Length 1000 def
                            % <acroform> <field> <annot> (string)
      /NullEncode filter    % <acroform> <field> <annot> file

      dup (BT ) writestring
      2 index /DA pget not { () } if
      [ exch
        { token {
            dup /Tf eq {
              2 index 0 eq {
                /BBox load 3 get
                0.75 mul   % empirical constant
                4 -1 roll pop 3 1 roll
              } if
            } if
            exch
          } {
            exit
          } ifelse
        } loop
      ]
      { 1 index exch write== } forall
      dup 3 index /MaxLen pget not { 0 } if write=
      dup 3 index /V pget not {
        3 index /DV pget not { () } if
      } if write==
      dup 3 index /Ff pget not { 0 } if write=
      dup 3 index /Q pget not { 0 } if write=
      dup (Tform ET) write=
      end
      closefile             %  <acroform> <field> <annot>
      dup 1 1 3 -1 roll drawwidget
    } if
  } ifelse
} bind executeonly def

/Ch {
  dup /AP known 3 index /NeedAppearances knownoget not { //true } if not and {
    dup 1 1 3 -1 roll drawwidget
  } {
    %% If we don't have a NeedApperances, treat as true, because Acrobat
    %% always regenerates Appearances anyway.
    2 index /NeedAppearances knownoget not { //true } if {
      dup /AP << /N 10 dict dup cvx begin >> put
      /Subtype /Form def
      /BBox [ 0 0 4 index /Rect oget { oforce } forall  3 -1 roll sub abs 3 1 roll sub abs exch ] def
      /Resources 3 index /DR pget not { 0 dict } if def
      /File 1000 string dup 3 1 roll def
      /Length 1000 def
                            % <acroform> <field> <annot> (string)
      /NullEncode filter    % <acroform> <field> <annot> file

      dup (BT ) writestring
      2 index /DA pget not { () } if
      [ exch
        { token {
            dup /Tf eq {
              2 index 0 eq {
                /BBox load 3 get
                0.75 mul   % empirical constant
                4 -1 roll pop 3 1 roll
              } if
            } if
            exch
          } {
            exit
          } ifelse
        } loop
      ]
      { 1 index exch write== } forall
      dup 3 index /MaxLen pget not { 0 } if write=
      dup 3 index /V pget not {
        3 index /DV pget not { () } if
      } if write==
      dup 3 index /Ff pget not { 0 } if write=
      dup 3 index /Q pget not { 0 } if write=
      dup (Tform ET) write=
      end
      closefile             %  <acroform> <field> <annot>
      dup 1 1 3 -1 roll drawwidget
    } if
  } ifelse
} bind executeonly def

/Sig {
  (Sig is not yet implemened ) //== exec
} bind executeonly def

currentdict end def

/draw_terminal_field {   % <field> draw_terminal_field -
 dup /Kids knownoget { 0 oget } { dup } ifelse
 dup /P knownoget {
    /Page load eq {
      //draw_terminal_field_dict 2 index /FT pget not { 0 } if .knownget {
        exec
      } if
   } if
 } if
 pop pop
} bind executeonly def

% We distinguish 4 types of nodes on the form field tree:
%  - non-terminal field - has a kid that refers to the parent (or anywhere else)
%  - terminal field with separate widget annotations - has a kid that doesn't have a parent
%  - terminal field with a merged widget annotation - has no kids
%  - widget annotation - has /Subtype and /Rect
%
% The recursive enumeration of the form fields doesn't descend into widget annotations.

/draw_form_field { % <field> draw_form_field -
  dup type /dicttyype eq {	% File for Bug692447 has 'null' Fields entries
                                % This matches what pdf_main process_trailer_attrs
    dup /Kids knownoget {                       % field []
      dup length 0 gt {
        dup 0 oget /Parent knownoget {            % field [] kid
          pop % mon-terminal field                % field []
          exch pop                                % []
          { oforce draw_form_field } forall
        } {
          pop draw_terminal_field % separate annots % -
        } ifelse
      } {
          (  **** Error: Ignoring empty /Kids array in Form field.\n) pdfformaterror
          (              Output may be incorrect.\n) pdfformaterror
      } ifelse
    } {
      draw_terminal_field % merged annotation   % -
    } ifelse
  } if
} bind executeonly def

/draw_acro_form {		% <form> draw_acro_form -
  dup /Fields knownoget {
    { oforce draw_form_field } forall
  } if
  pop
} bind executeonly def

currentdict /draw_terminal_field_dict undef

end			% pdfdict
end			% GS_PDF_ProcSet
.setglobal

Zerion Mini Shell 1.0