\!/ KyuuKazami \!/

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

%    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
% 
% This software is provided AS-IS with no warranty, either express or
% implied.
% 
% This software is distributed under license and may not be copied,
% modified or distributed except as expressly authorized under the terms
% of the license contained in the file LICENSE in this distribution.
% 
% For more information about licensing, please refer to
% http://www.ghostscript.com/licensing/. For information on
% commercial licensing, go to http://www.artifex.com/licensing/ or
% contact Artifex Software, Inc., 101 Lucas Valley Road #110,
% San Rafael, CA  94903, U.S.A., +1(415)492-9861.

% $Id: pdf_draw.ps 9850 2009-07-09 00:28:02Z alexcher $
% pdf_draw.ps
% PDF drawing operations (graphics, text, and images).

/.setlanguagelevel where { pop 2 .setlanguagelevel } if
.currentglobal true .setglobal
/pdfdict where { pop } { /pdfdict 100 dict def } ifelse
GS_PDF_ProcSet 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
} bdef

/.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
} bdef

/.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
} bdef

/.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
} bdef

/.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
} bdef

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

/resolvefnproc {	% <fndict> resolvefnproc <proc>
  resolvefunction .buildfunction
} bdef

/resolveidfnproc {	% <fndict> resolveidfnproc <proc>
  dup /Identity eq { pop { } } { resolvefnproc } ifelse
} bdef

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

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

/shrdict mark
  /BBox {
    dup dup dup aload pop normrect_elems
    5 -1 roll astore
  } bind
  /ColorSpace {
    resolvecolorspace
  } bind
  /Function {
    dup type /dicttype eq {
      resolvefunction
    } {
      [ exch { oforce resolvefunction } forall ]
    } ifelse
  } bind
.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
} bdef
/resolvesh {		% <shname> resolvesh <shading>
			% <shname> resolvesh <null>
  Page /Shading rget {
    resolveshading
  } {
    null
  }ifelse
} bdef

% ---------------- 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
  }
  /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
  }
  /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
  }
  /EllipseA { dup mul .9 mul exch dup mul add 1 exch sub }
  /InvertedEllipseA { dup mul .9 mul exch dup mul add 1 sub }
  /EllipseB { dup 5 mul 8 div mul exch dup mul exch add sqrt 1 exch sub }
  /EllipseC { dup mul .9 mul exch dup mul add 1 exch sub }
  /InvertedEllipseC { dup mul .9 mul exch dup mul add 1 sub }
  /Line { exch pop abs neg }
  /LineX { pop }
  /LineY { exch pop }
  /Square { abs exch abs 2 copy lt { exch } if pop neg }
  /Cross { abs exch abs 2 copy gt { exch } if pop neg }
  /Rhomboid { abs exch abs 0.9 mul add 2 div }
  /DoubleDot { 2 {360 mul sin 2 div exch } repeat add }
  /InvertedDoubleDot { 2 {360 mul sin 2 div exch } repeat add neg }
  /SimpleDot { dup mul exch dup mul add 1 exch sub }
  /InvertedSimpleDot { dup mul exch dup mul add 1 sub }
  /CosineDot { 180 mul cos exch 180 mul cos add 2 div }
  /Double { exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add }
  /InvertedDouble {
    exch 2 div exch 2 { 360 mul sin 2 div exch } repeat add neg
  }
.dicttomark readonly def

/htrdict mark
  1 { .resolveht1 }
  5 { .resolveht5 }
	% We don't support types 6, 10, or 16 yet.
.dicttomark readonly def

/.resolveht1 {
  mark exch {
    oforce
    1 index /SpotFunction eq {
      dup type /nametype eq
	{ //spotfunctions exch get } { resolvefnproc }
      ifelse
    } {
      1 index /TransferFunction eq {
	resolveidfnproc
      } if
    } ifelse
  } forall .dicttomark
} bdef

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

/resolvehalftone {	% <dict> resolvehalftone <halftone>
  dup /HalftoneType get
  dup //htrdict exch .knownget {
    exch pop exec
  } {
    (\n\n   **** Unsupported HalftoneType ) pdfformaterror
    =string cvs pdfformaterror (. ***\n\n) pdfformaterror
    /resolvehalftone cvx /unregistered signalerror
  } ifelse
} bdef

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

/cmmatrix matrix def
drawopdict begin
			% Graphics state stack
  /q { q } def
  /Q { Q } 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
      } bdef

  /i { 1 .min setflat } bdef
  /J /setlinecap load def
  /d /setdash load def
  /j /setlinejoin load def
  /w /setlinewidth load def
  /M { 1 .max setmiterlimit } bdef
  /gs { gs } def
end

% Each entry in this dictionary is
%	<gsres> <value> -proc- <gsres>
/gsbg {
  /BGDefault load resolvedefaultfnproc setblackgeneration
} bdef
/gsucr {
  /UCRDefault load resolvedefaultfnproc setundercolorremoval
} bdef
/gstr {
  dup type /arraytype eq {
    { oforce /TRDefault load resolvedefaultfnproc } forall
    setcolortransfer
  } {
    /TRDefault load resolvedefaultfnproc settransfer
  } ifelse
} bdef
/gsparamdict mark
  /SA { setstrokeadjust }
  /OP { 1 index /op known not { dup op } if OP }
	% 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 }
  /UCR { 1 index /UCR2 known { pop } { gsucr } ifelse }
  /TR { 1 index /TR2 known { pop } { gstr } ifelse }
  /HT {
    dup /Default eq {
      pop .setdefaulthalftone
    } {
	%****** DOESN'T IMPLEMENT THE STREAM CASE YET ******
      resolvehalftone sethalftone
    } ifelse
    % 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
  }
  /HTP {
	% HTP may be present even if this isn't a DPS interpreter.
    /sethalftonephase where { pop aload pop sethalftonephase } { pop } ifelse
  }
	% PDF 1.3
  /Font { aload pop Tf }
  /LW { setlinewidth }
  /LC { setlinecap }
  /LJ { setlinejoin }
  /ML { 1 .max setmiterlimit }
  /D { aload pop setdash }
  /RI { ri }
  /op { op }
  /OPM { OPM }
  /BG2 { gsbg }
  /UCR2 { gsucr }
  /TR2 { gstr }
  /FL { 1 .min setflat }
  /SM {
	% SM may be present even if this is only a Level 2 interpreter.
    /setsmoothness where { pop setsmoothness } { pop } ifelse
  }
	% PDF 1.4
	% All of these require the "transparency" feature in the interpreter.
  /ca { ca }
  /CA { CA }
  /SMask { gssmask }
  /AIS { AIS }
  /BM { BM }
  /TK { TK }
.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
  } if
} bdef

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

/gssmask {
  dup /None eq 1 index //null eq or PDFusingtransparency not or {
    pop null
  } {
	% 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
      gsave //nodict begin
        1 index /G oget /Group oget /CS knownoget {
	  resolvecolorspace dup setgcolorspace csput
	} if
        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 /BBox exch 4 2 roll
    /.execmaskgroup cvx 2 packedarray cvx /Draw exch 3 2 roll
    pop .dicttomark
  } ifelse SMask
} bdef

% 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
  /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
  mark currentcolor counttomark dup 4 add exch roll pop
  currentcolorspace 4 1 roll .getuseciecolor 4 1 roll //nodict begin
  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
  } {
    % inheriting the colorspace -- make sure Device* spaces are not CIEBased
    forceDefaultCS currentcolorspace 0 get .knownget { exec } if
    //false		% no defined colorspace
  } ifelse
  3 -1 roll dup /BBox get aload pop .begintransparencymaskgroup {
    dup /Resources knownoget { oforce } { 0 dict } ifelse
    exch false resolvestream
    .execgroup .endtransparencymask
  } stopped {
    .discardtransparencymask stop
  } if
  PDFfile exch setfileposition 
  .setuseciecolor setcolorspace setcolor end	% restore colorspace, color and ExtGState (end)
} bdef
% Paint a Form+Group XObject, either for a transparency mask or for a Do.
/.execgroup {		% <resdict> <stream> .execgroup -
  gsave //nodict begin
  newpath null SMask
  1 .setopacityalpha 1 .setshapealpha
  /Compatible .setblendmode
	% Execute the body of the Form, similar to DoForm.
  pdfopdict .pdfruncontext
  end grestore
} bdef

/.beginformgroup {	% groupdict bbox .beginformgroup -
  exch mark exch			% bbox mark groupdict
  dup /CS knownoget { resolvecolorspace setgcolorspace } 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
} bdef

% .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 -
  dup /Group oget exch /BBox oget
		% Stack: resdict stream groupdict bbox
  .beginformgroup {
    .execgroup
  } stopped {
    .discardtransparencygroup stop
  } if .endtransparencygroup
} bdef

% 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 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
  AlphaIsShape { /ShapeMaskDict } { /OpacityMaskDict } ifelse exch def
  /ColorSpace DataDict /ColorSpace get def
} bdef

% ---------------- 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 8 dict begin
  /DeviceGray { pop 1 } bdef
  /DeviceRGB { pop 3 } bdef
  /DeviceCMYK { pop 4 } bdef
  /CIEBasedA { pop 1 } bdef
  /CIEBasedABC { pop 3 } bdef
  /ICCBased { 1 oget /N oget } bdef
  /Separation { pop 1 } bdef
  /DeviceN { 1 oget length } bdef
currentdict end readonly def

/csrdict 13 dict begin 
  /DeviceGray { } bdef
  /DeviceRGB { } bdef
  /DeviceCMYK { } bdef

  /CalGray {
    1 oget 6 dict begin
    dup /Gamma knownoget {
      /exp load 2 packedarray cvx /DecodeA exch def
    } if
    dup /BlackPoint knownoget { /BlackPoint exch def } if
    dup /WhitePoint knownoget {
      dup /WhitePoint exch def
      dup /MatrixA exch def
      /RangeLMN [ 3 2 roll { 0 exch } forall ] def
    } if
    /PDFColorSpace exch def [ /CIEBasedA currentdict end ]
  } bdef

  /CalRGB {
    1 oget 6 dict begin
    dup /Gamma knownoget {
      [ exch { /exp load 2 packedarray cvx } forall
      ] /DecodeABC exch def
    } if
    dup /Matrix knownoget { /MatrixABC exch def } if
    dup /BlackPoint knownoget { /BlackPoint exch def } if
    dup /WhitePoint knownoget { /WhitePoint exch def } if
    /PDFColorSpace exch def [ /CIEBasedABC currentdict end ]
  } bdef

  /CalCMYK {
    pop /DeviceCMYK		% not defined by Adobe
  } bdef

  /Lab {
    1 oget 6 dict begin
    dup /Range knownoget not { [-100 100 -100 100] } if
    [0 100 null null null null] dup 2 4 -1 roll putinterval
    /RangeABC exch def
    /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind] def
    /MatrixABC [1 1 1 1 0 0 0 0 -1] def
    dup /BlackPoint knownoget { /BlackPoint exch def } if
    dup /WhitePoint knownoget { /WhitePoint exch def } {
      (   **** Warning: Lab colorspace is missing WhitePoint.\n)
      pdfformaterror
      /WhitePoint [0.9505 1 1.089] def
    } ifelse
    % scaling function g() for DecodeLMN construction
    { dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse }
    /DecodeLMN [
      % Store white point implicitly inside procedures.
      [ 3 index aload pop WhitePoint 0 get /mul .systemvar ] cvx bind
      [ 4 index aload pop WhitePoint 1 get /mul .systemvar ] cvx bind
      [ 5 index aload pop WhitePoint 2 get /mul .systemvar ] cvx bind
    ] def pop
    /PDFColorSpace exch def [ /CIEBasedABC currentdict end ]
  } bdef

  /ICCBased {
    dup 1 get type /dicttype ne {	% don't resolve more than once
    PDFfile fileposition exch
    dup dup 1 oget
    mark exch { oforce } forall .dicttomark
    dup dup true resolvestream
    /ReusableStreamDecode filter /DataSource exch put
    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
    } if
  } bdef

  /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
    4 array astore
  } bdef

  /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
      4 exch put			% Put resolved or new attributes dict
    } if
  } bdef

  /Indexed {
    aload pop 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
    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 true resolvestream
		% Stack: filepos /Indexed basespace hival lookupstream
	1 index 1 add
		% Stack: filepos /Indexed basespace hival lookupstream len
	3 index
	  dup dup type /arraytype eq { 0 get } if
	  //csncompdict exch get exec mul
	string dup 3 1 roll readstring pop  % the string is padded with 0s
        length 1 index length lt {
          (   **** Warning: Short look-up table in the Indexed color space was padded with 0's.\n)
          pdfformaterror
        } if
		% Stack: filepos /Indexed basespace hival table table'
	5 -1 roll PDFfile exch setfileposition
    }
    if 4 array astore
		% 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
  } bdef

  /I { % Bug 689815
    (   **** Warning: The name /Indexed cannot be abbreviated to /I in the color space\n)
    pdfformaterror
    dup 0 /Indexed put
    //Indexed exec 
  } bdef

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

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
} bdef

/csnames mark
  /DeviceGray dup  /DeviceRGB dup  /DeviceCMYK dup  /Pattern dup
.dicttomark readonly def
/csresolve {		% <csresourcename> csresolve <cspace>
  dup type /nametype ne {
    (\n   **** Warning: CS/cs (setcolorspace) operand not a name: ) pdfformaterror
    dup stderrfile dup 3 -1 roll write==only flushfile
    ( ****\n) pdfformaterror
    dup type /arraytype eq {	% Adobe InDesign + PDF Library has array
      resolvecolorspace
    } if
  } {
    dup Page /ColorSpace rget {
      exch pop resolvecolorspace
    } {
      //csnames 1 index known not { /undefined cvx signalerror } if
    } ifelse
  } ifelse
} bdef
/resolvecolorspace {	% <cspace> resolvecolorspace <cspace'>
  dup dup type /arraytype eq { 0 get } if
  //csrdict exch .knownget
  {
    exec dup type /nametype ne { dup length 1 eq { 0 get } if } if
  } {
    dup type /nametype eq { csresolve } { csset exch pop } ifelse
  } ifelse
} bdef

/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
} bdef

/.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.
    //null sc1 //null SC1
  } ifelse

  % Save old values on opstack, set pdfemptycount to new value.
  pdfemptycount countdictstack
  /pdfemptycount count 3 sub def 4 2 roll
  %
  % Stack: ... <old emptycount> <dictcount> <patdict> <resdict> 
  %                                            |
  %           New empty count points here -----+

  exch //false resolvestream pdfopdict .pdfruncontext

  countdictstack exch sub dup 0 gt { 
     (   **** Warning: Pattern stream has unbalanced q/Q operators \(too many q's\)\n)
     pdfformaterror
     { Q } repeat
   } {
     pop
   } ifelse

  % restore pdfemptycount
  /pdfemptycount exch def

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

/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 /.pattern_uses_transparency  1 index patternusestransparency put
  PDFDEBUG { pdfdict /PDFSTEPcount .knownget { 1 le } { true } ifelse { (%Pattern: ) print dup === flush } if } if
} bdef

/ignore_color_op  (   **** Warning: Ignoring a color operation in a cached context.\n) readonly def

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

  /rg { .incachedevice {
          pop pop pop //ignore_color_op pdfformaterror
        } {
          /DeviceRGB cssubst { cs sc* } { rg } ifelse
        } ifelse
      } bdef

  /k  { .incachedevice {
          pop pop pop pop //ignore_color_op pdfformaterror
        } {
          k
        } ifelse
      } bdef

  /cs { .incachedevice {
          pop //ignore_color_op pdfformaterror
        } {
          csresolve cs
        } ifelse
      } bdef

  /sc { .incachedevice {
          .pdfcount { pop } repeat //ignore_color_op pdfformaterror
        } {
          scresolve { sc* } { sc1 } ifelse
        } ifelse
      } bdef

  /scn /sc load def

  /G  { .incachedevice {
          pop //ignore_color_op pdfformaterror
        } {
          /DeviceGray cssubst { CS SC1 } { G } ifelse
        } ifelse
      } bdef

  /RG { .incachedevice {
          pop pop pop //ignore_color_op pdfformaterror
        } {
          /DeviceRGB cssubst { CS SC* } { RG } ifelse
        } ifelse
      } bdef

  /K  { .incachedevice {
          pop pop pop pop //ignore_color_op pdfformaterror
        } {
          K
        } ifelse
      } bdef

  /CS { .incachedevice {
          pop //ignore_color_op pdfformaterror
        } {
          csresolve CS
        } ifelse
      } bdef

  /ri { .incachedevice {
          pop //ignore_color_op pdfformaterror
        } {
          ri
        } ifelse
      } bdef

  /SC { .incachedevice {
          .pdfcount { pop } repeat //ignore_color_op pdfformaterror
        } {
          scresolve { SC* } { SC1 } ifelse
        } ifelse
      } bdef

  /SCN /SC load def
end

currentdict /ignore_color_op undef

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

drawopdict begin
			% Path construction
  /m /moveto load def
  /l /lineto load def
  /c /curveto load def
  /v { currentpoint 6 2 roll curveto } def
  /y { 2 copy curveto } def
  /re {
   4 2 roll moveto  exch dup 0 rlineto  0 3 -1 roll rlineto  neg 0 rlineto
   closepath
  } def
  /h /closepath load def
			% Path painting and clipping
  /n { n } def
  /S { S } def
  /s { s } def
  /f { f } def
  /f* { f* } def
  /B { B } def
  /b { b } def
  /B* { B* } def
  /b* { b* } def
  /W { W } def
  /W* { W* } def
  /sh { setfillstate resolvesh 
        gsave 0 .setoverprintmode 
        dup /.shading .knownget {
          exch 
          pop
        } {
          dup
          .buildshading
          dup 3 1 roll /.shading exch put
        } ifelse
        .shfill grestore 
      } def
end

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

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

% Note that the keys in defaultdecodedict are resolved (PostScript, not PDF)
% color space names.
/defaultdecodedict mark
  /DeviceGray { pop //01_1 } bind
  /DeviceRGB { pop //01_3 } bind
  /DeviceCMYK { pop //01_4 } bind
  /CIEBasedA { 1 get /RangeA knownoget not { //01_1 } if } bind
  /CIEBasedABC { 1 get /RangeABC knownoget not { //01_3 } if } bind
  /ICCBased {
     1 oget dup /Range knownoget {
       exch pop
     }{
       /N get [ exch {0 1} repeat ] readonly
     } ifelse
  } bind
  /Separation { pop //01_1 } bind
  /DeviceN {
    1 oget length [ exch {0 1} repeat ] readonly
  } bind
  /Indexed {
    pop [ 0 1 BitsPerComponent bitshift 1 sub ]
  } bind
.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
} bdef

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

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


% Process jp2 blocks (aka boxes). All procedures have the signature
% <file> <length> -> ... <file> <flush_length>
/jp2_tag_dict <<
  /jp2h { % descend into a sub-stream, never return.
    () /SubFileDecode filter 0
  } bind
  /ihdr {
    14 sub                               % file len-14
    1 index 14 string readstring pop     % file len-14 (14)
    /Components 1 index 8 getu16         % file len-14 (14) /Components NC
    def                                  % file len-14 (14)
    10 get 16#7F and 1 add
    /BitsPerComponent exch def           % file len-14 
  } bind
  /colr {
    3 sub
    1 index 3 string readstring pop      % file len-3 (3)
    0 get 1 eq {
      4 sub                              % file len-7
      1 index 4 string readstring pop    % file len-16 (4) 
      0 getu32                           % file len-16 enum
      dup 16 eq {
        % Don't set device-independent color space now
        % to avoid raster differences
        pop /ColorSpace /DeviceRGB % /sRGB
        def                              % file len-7
      } {
        17 eq {
          % See above.
          /ColorSpace /DeviceGray % /sGray
          def                            % file len-7
        } if
      } ifelse
    } {
      string 1 index exch readstring pop % file ()
      /ColorSpace exch                   % file /ColorSpace ()
      % ICC ColorSpace is not yet implemented
      pop pop
      %
      0                                  % file 0
    } ifelse
  } bind
>> 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 ==            % 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 def

currentdict /jp2_tag_dict .undef

/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 { def } { pop } ifelse
  /Interpolate 2 copy knownoget { def } { pop } ifelse
  makeimagekeys
} bdef
/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
  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).
    //false resolvestream /DataSource exch def
    //true
  } {
		% Opaque image
    dup /ColorSpace oknown 
    1 index /BitsPerComponent oknown and not {
      dup /Filter knownoget {
        dup type /arraytype eq {
          dup length
          dup 0 gt {
            1 sub get oforce
          } {
            pop
          } ifelse
        } if
        /JPXDecode eq {
          % JPXDecode filters can omit the /ColorSpace and /BitsPerComponent
          % keys, in which case the interpreter must retrieve this information
          % from inside the compressed stream. Here we substitute the most
          % likely values as a work-around.
          dup /IDFlag known {
            (   **** Warning: PDF spec bans inline JPX images.\n) pdfformaterror
            % 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 /Params knownoget {
                  dup type /arraytype eq {
                    dup length 1 gt {
                      dup length 1 sub 0 exch getinterval
                      1 index exch /Params exch put
                    } {
                      pop
                      dup /Params undef
                    } ifelse
                  } {
                    pop
                    dup /Params undef
                  } ifelse
                } if
              } {
                pop
                dup /Filter undef
                dup /Params undef
              } ifelse
            } {
              pop
              dup /Filter undef
              dup /Params undef
            } ifelse

            //false resolvestream get_jp2_csp
          } ifelse
        } if
      } if
      currentdict /BitsPerComponent oknown not {
        (   **** Warning: image has no /BitsPerComponent key; assuming 8 bit.\n)
        pdfformaterror
        /BitsPerComponent 8 def
      } if
    } if

    currentdict /ColorSpace knownoget not {
      dup /ColorSpace knownoget not {
        (   **** Warning: image has no /ColorSpace key; assuming /DeviceRGB.\n)
        pdfformaterror
        /DeviceRGB
      } if
    } if
    resolvecolorspace /ColorSpace exch def

		% Decode is required for the PostScript image operators.
    /Decode 2 copy knownoget not {
      ColorSpace //defaultdecodedict
      ColorSpace dup type /arraytype eq { 0 get } if get exec
    } if def
		% 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
} bdef

/DoImage {
  checkaltimage dup length 6 add dict
  1 index /SMask knownoget { 1 index exch /SMask exch put } if
  1 index /Mask knownoget { 1 index exch /Mask exch put } if
  makeimagedict doimagesmask
} bdef
/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 {
      (\n   **** Warning: Some elements of Mask array are not integers.\n)
      pdfformaterror
      [ exch { 0.5 add cvi } forall ]  % following AR4, 5, 6 implementation
    } if
	% Check elements of array are within 0::(2**BitsPerComponent)-1
	% This is a PostScript error, but AR ignores Mask in that case
    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 {
      (\n   **** Warning: Some elements of Mask array are out of range.\n)
      pdfformaterror
      [ exch { 0 .max 1 BitsPerComponent bitshift 1 sub .min } forall ]
    } if
    /MaskColor exch def
  } {
		% 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 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
} bdef

/doimagesmask { % <imagemask> doimagesmask -
  PDFusingtransparency {
    currentdict /SMask knownoget
  } {
    false
  } ifelse
  {	% We are doing transparency and SMask is present in the image
	% stack: <imagemask> <SMask>
    currentdevice .devicename /pdfwrite eq {
      pop	% pdfwrite will process SMask directly during 'doimage'
    } {
      .begintransparencymaskimage
      PDFfile fileposition exch
      gsave //nodict begin
      null /SoftMask gput
      1 .setopacityalpha 1 .setshapealpha
      /Compatible .setblendmode
      DoImage
      end grestore
      PDFfile exch setfileposition
      0 .endtransparencymask
    } ifelse
    << /Subtype /Group /Isolated true 
      /.image_with_SMask true % pdfwrite needs : see gs/src/ztrans.c, gs/src/gdevpdft.c 
    >> 0 0 1 1 .begintransparencygroup
    doimage
    .endtransparencygroup
  } {
    SoftMask //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
      doimage
      .endtransparencygroup
    }
    { doimage }
    ifelse
  } ifelse
} bdef

% 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
  } bdef
} if

/is_big_mask {  % - is_big_mask <bool>
  1 0 dtransform dup mul exch dup mul sqrt add
  0 1 dtransform dup mul exch dup mul sqrt add mul
  currentdevice getdeviceprops .dicttomark /BufferSpace .knownget not {
    4000000 % hack: Can't get the real default value from C source.
  } if
  2 % arbitrary
  div gt
} bind 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 {
  /is_big_mask {  % - is_big_mask <bool>
    //false
  } bdef
} if

/doimage {	% <imagemask> doimage -
		% imagedict is currentdict, gets popped from dstack
  DataSource exch
  PDFusingtransparency
  currentdevice .devicename /pdfwrite ne { 
    % This is a temporary workaround for the bug 689080,
    % which is done under a rush of 8.63 release.
    % The purpose is to disable a conversion of an image with soft mask
    % into a Type 103 image, which currently allocates a full mask buffer
    % before writing clist.
    % With this workaround the Matte color is not working (ignored).
    is_big_mask not 
  } {
    true % pdfwrite doesn't need the workaround explained above,
         % and cannot work with it. 
  } ifelse
  and {
    currentdict /SMask knownoget
  } {
    false
  } ifelse {
    makesoftmaskimage
  } {
    currentdict /Mask knownoget {
      makemaskimage
    } if
  } ifelse
		% Stack: datasource imagemask
   { currentdict end setfillstate { imagemask } }
   { ColorSpace setgcolorspace currentdict end setfillblend { image } }
  ifelse
  stopped {
    dup type /dicttype eq { pop } if % Sometimes image fails to restore the stack
    $error /errorname get dup /ioerror eq {
      pop (\n   **** Warning: File has insufficient data for an image.\n)
      pdfformaterror
    } {
      (\n   **** Warning: File encountered ')
      exch 40 string cvs concatstrings
      (' error while processing an image.\n) concatstrings
      pdfformaterror
    } ifelse
  } if
		% Close the input stream, unless it is PDFfile or
		% PDFsource.
  dup dup PDFfile eq exch PDFsource eq or { pop } { closefile } ifelse
} bdef

/.paintform {	% <formdict> <resdict> <stream> .paintform -
  3 -1 roll dup /Group known PDFusingtransparency and {
    .paintgroupform
  } {
    pop pdfopdict .pdfruncontext
  } ifelse
} bdef

/DoForm {
    % 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 } if
  currentdict end { oforce } forall
  >>
  dup [ 2 index /Resources knownoget { oforce } { 0 dict } ifelse
  3 index 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 1 sub store
  q execform  			% gsave / grestore around the Form
    % Restore pdfemptycount
  countdictstack exch sub
  dup 1 gt {
    (   **** Warning: Pattern stream has unbalanced q/Q operators \(too many q's\)\n)
    pdfformaterror
  } if
  { Q } repeat
  /pdfemptycount exch store
} bdef

/_dops_save 1 array def

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

currentdict /_dops_save undef

drawopdict begin
  /Do {
    setfillblend
    PDFfile fileposition exch
    dup Page /XObject rget { 
      exch pop dup /Subtype get xobjectprocs exch get
		% Don't leave extra objects on the stack while executing
		% the definition of the form.
      3 -1 roll 2 .execn
    } {
		% This should cause an error, but Acrobat Reader can
		% continue, so we do too.
      (   **** Undefined XObject resource: ) 
      exch =string cvs concatstrings (\n) concatstrings
      pdfformaterror
    } ifelse
    PDFfile exch setfileposition
  } bdef
end

% ---------------- 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
} bdef

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

drawopdict begin
  /BI { mark } bdef
  /ID {
    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 doimage	
	% 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
  } bdef
end

currentdict /is_space_dict undef

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

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

  /Tform { Tform } def  % Text formatting and painting for AcroForm
                        % without appearance streams.
  /QBT {
    Q BT
    (   **** Warning: invalid operator QBT processed as Q BT .\n)
    pdfformaterror  % Bug 690089
  } def

end

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



% Get and normalize an annotation's rectangle.
/annotrect {		% <annot> annotrect <x> <y> <w> <h>
  /Rect oget 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
} bdef

% Set an annotation color.
/annotsetcolor {	% <annot> annotsetcolor -
  /C knownoget { aload pop setrgbcolor } { 0 setgray } ifelse
} bdef

% 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 annotrect
    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
} bdef

% 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 { 
      (   **** Warning: Wrong annotation border object, no border is drawn.\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 {	% 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
} bdef

%
%   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
%
/annotvisible {			% <annot> annotvisible <visible>
  /F knownoget not { 0 } if 		% Get flag value
  dup 2 and 0 eq  			% Check hidden flag
  exch dup 4 and 0 ne Printed and	% Check print flag
  exch 32 and 0 eq Printed not and	% Check noview flag
  or					% Combine print and view
  and 					% Combine with 'hidden' flag test
} bdef

/drawwidget {			% <scalefactor_x> <scalefactor_y> <annot> drawwidget -
  dup /AP knownoget {
    dup /N known not {
      (   **** Appearance dictionary (AP) lacks the mandatory normal (N) appearance.\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 known 1 index /File known or {
      		% 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
    {
      		% 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
    } if
  } {
    dup /FT knownoget {
      /Tx eq {
	  % Stack: scalex scaley annot
	dup /DA known 1 index /V known and {
	  dup /DA oget
	  q graphicsbeginpage textbeginpage
	  1 index annotrect pop pop translate
	  3 index 3 index scale		% Apply scale factors
	  cvx exec
	  dup /V oget
	  0 0 moveto dup false charpath pathbbox newpath 3 -1 roll
	  sub abs 3 1 roll sub abs
	  3 index annotrect 4 2 roll pop pop
	  6 index mul exch 6 index mul
	    % stack: scale annot V vsize hsize vrect hrect
	  % Calculate horizontal justification first
	  % horizontal can be left (Q=0), center (Q=1), or right (Q=2) justification
	  3 -1 roll 
	    % stack: scalex scaley annot V vsize vrect hrect hsize 
	  5 index /Q knownoget not { 0 } if	% default 0 == left
	  dup 0 eq {
	      pop pop pop 0		% left justified
	    } {
	    1 eq {
	      2 div exch 2 div exch sub	% centered
	    } {
	      sub			% right justified (hrect - hsize)
	    } ifelse
	  } ifelse
	    % stack: scalex scaley annot V vsize vrect hoffset
	  % Center the text vertically in the rect (Acrobat Reader seems to do this)
	  3 1 roll 2 div exch 2 div sub abs
	    % stack: scalex scaley annot V hoffset voffset
	  moveto show
	  Q
	} if
      } if
    } if
  } ifelse
  pop pop pop
} bdef

%  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
    3 -1 roll /AP knownoget {
      /N knownogetdict {
	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 {
            (   **** Warning: /BBox has zero width or height, which is not allowed.\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
  } {
    (   **** Warning: /Annot dict is missing required /Rect entry.\n)
    pdfformaterror
    pop 1 1
  } ifelse
} bdef

/drawlink {			% <annot> drawlink -
  dup drawborder dup calc_annot_scale 3 -1 roll drawwidget
} bdef

% Draw an annotation.
/drawannottypes mark
  /Link { drawlink } bind
.dicttomark readonly def
/drawannot {		% <annot> drawannot -
  dup annotvisible {
    gsave
    dup dup /Subtype knownoget {
      //drawannottypes exch .knownget {
        exec
      } {
        dup calc_annot_scale 3 -1 roll drawwidget	% Use drawwidget for everything else
      } ifelse			% type known
    } {
      pop
      (   **** Warning: /Annot dict without required /Subtype entry is ignored.\n)
      pdfformaterror
    } ifelse
    grestore
  } if pop			% annotvisible
} bdef
currentdict /drawannottypes 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
} bdef

% 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
} bdef

/Tx {
  dup /AP known {
    dup 1 1 3 -1 roll drawwidget
  } {
    2 index /NeedAppearances knownoget not { //false } 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 0 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 { () } 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
} bdef

/Ch {
  (Ch is not yet implemened) ==
} bdef

/Sig {
  (Sig is not yet implemened ) ==
} bdef

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
} bdef

% 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 /Kids knownoget {                       % field []
    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
  } {
    draw_terminal_field % merged annotation   % -
  } ifelse
} bdef

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

currentdict /draw_terminal_field_dict undef

end			% pdfdict
end			% GS_PDF_ProcSet
.setglobal

@KyuuKazami