Files
luos/thirdparty/html2ps_pdf/postscript/context.ps
Paula Quispe 9eb7d6cac2 HOR-2689
2017-08-03 17:00:30 -04:00

472 lines
15 KiB
PostScript

% Definition of float context "class"
/context-add-absolute-positioned { % => Box Context
dup /AbsolutePositioned get % => Box Context AB
2 index exch
array-prepend % => Box Context AB'
/AbsolutePositioned exch put % => Box
pop
} def
/context-add-fixed-positioned { % => Box Context
dup /FixedPositioned get % => Box Context AB
2 index exch
array-prepend % => Box Context AB'
/FixedPositioned exch put % => Box
pop
} def
/context-add-float { % => Float Context
dup /Floats get % => Float Context Floats
dup 0 get % => Float Context Floats Floats[0]
3 index exch array-prepend % => Float Context Floats Floats[0]'
0 exch put % => Float Context
pop pop
} def
/context-container-uid { % => Context
/ContainerUID get 0 get
} def
/context-create { % =>
<<
/ContainerUID [1]
/AbsolutePositioned []
/FixedPositioned []
/Floats [[]]
/Margin [0 0]
/Viewport []
>>
} def
% Find the minimal X at the given Y coordinate suitable for float placement
%
/context-float-left-x { % => Y X Context
3 copy dup
context-floats % => Y X Context Y X Context Floats
context-float-left-x-rec % => Y X Context X
% Clear the stack
exch pop
exch pop
exch pop
} def
/context-float-left-x-rec { % => Y X Context Floats
dup length 0 gt {
dup 0 get % => Y X Context Floats Float
dup /float get-css-value
/left eq {
% Check if this float contains given Y-coordinate
%
% Note that top margin coordinate is inclusive but
% bottom margin coordinate is exclusive! The cause is following:
% - if we have several floats in one line, their top margin edge Y coordinates will be equal,
% so we must use agreater or equal sign to avod placing all floats at one X coordinate
% - on the other side, if we place one float under the other, the top margin Y coordinate
% of bottom float will be equal to bottom margin Y coordinate of the top float and
% we should NOT offset tho bottom float in this case
dup get-top-margin % => Y X Context Floats Float FTM
rounding-epsilon add
5 index % => Y X Context Floats Float FTM Y
ge % => Y X Context Floats Float FTM>=Y
1 index get-bottom-margin % => Y X Context Floats Float FTM>=Y FBM
6 index % => Y X Context Floats Float FTM>=Y FBM Y
lt % => Y X Context Floats Float FTM>=Y FBM<Y
and { % => Y X Context Floats Float
dup get-right-margin % => Y X Context Floats Float FRM
4 index max % => Y X Context Floats Float X'=MAX(FRM,X)
exch pop % => Y X Context Floats X'
4 3 roll pop % => Y Context Floats X'
3 1 roll % => Y X' Context Floats
array-pop-first
context-float-left-x-rec % => X
} {
pop
array-pop-first
context-float-left-x-rec
} ifelse
} {
pop
array-pop-first
context-float-left-x-rec
} ifelse
} {
% no more floats
pop pop exch pop
} ifelse
} def % => X
% Calculates position of left floating box (taking into account the possibility
% of "wrapping" float to next line in case we have not enough space at current level (Y coordinate)
%
% @param parent reference to a parent box
% @param width width of float being placed. Full width! so, extra horizontal space (padding, margins and borders) is added here too
% @param $y Starting Y-coordinate
% @return X X coordinate of float upper-left corner
% @return Y Y coordinate of float upper-left corner
%
/context-float-left-xy { % => Parent Width Y Context
% Prepare information about the float bottom corrdinates
dup context-floats % => Parent Width Y Context Floats
make-sorted-bottom-y-list % => Parent Width Y Context FloatBottoms
context-float-left-xy-rec % => Y X
} def % => Y X
/context-float-left-xy-rec { % => Parent Width Y Context FloatBottoms
4 index get-left
3 index % => Parent Width Y Context FloatBottoms X Y
exch % => Parent Width Y Context FloatBottoms Y X
3 index
context-float-left-x % => Parent Width Y Context FloatBottoms X
% Check if current float will fit into the parent box
dup 5 index add % => Parent Width Y Context FloatBottoms X FloatRight
6 index get-right
rounding-epsilon add
le { % => Parent Width Y Context FloatBottoms X
% will fit
exch pop % => Parent Width Y Context X
exch pop % => Parent Width Y X
4 2 roll % => Y X Parent Width
pop pop exch % => X Y
} {
pop % => Parent Width Y Context FloatBottoms
% Check if all floats have been already cleared
dup length 0 eq {
% All floats are cleared; fall back to the leftmost X coordinate
pop pop exch pop % => Parent Y
exch % => Y Parent
get-left exch % => X Y
} {
% No, float does not fit at current level, let's try to 'clear' some previous floats
dup 0 get % => Parent Width Y Context FloatBottoms Bottom0
3 index min % => Parent Width Y Context FloatBottoms Y'
4 3 roll pop % => Parent Width Context FloatBottoms Y'
3 1 roll
array-pop-first % => Parent Width Y' Context FloatBottoms'
context-float-left-xy-rec % => X Y
} ifelse
} ifelse
} def % => X Y
% Find the minimal X at the given Y coordinate suitable for float placement
%
/context-float-right-x { % => Y X Context
3 copy dup
context-floats % => Y X Context Y X Context Floats
context-float-right-x-rec % => Y X Context X
% Clear the stack
exch pop
exch pop
exch pop
} def
/context-float-right-x-rec { % => Y X Context Floats
dup length 0 gt {
dup 0 get % => Y X Context Floats Float
dup /float get-css-value
/right eq {
% Check if this float contains given Y-coordinate
%
% Note that top margin coordinate is inclusive but
% bottom margin coordinate is exclusive! The cause is following:
% - if we have several floats in one line, their top margin edge Y coordinates will be equal,
% so we must use agreater or equal sign to avod placing all floats at one X coordinate
% - on the other side, if we place one float under the other, the top margin Y coordinate
% of bottom float will be equal to bottom margin Y coordinate of the top float and
% we should NOT offset tho bottom float in this case
dup get-top-margin % => Y X Context Floats Float FTM
rounding-epsilon add
5 index % => Y X Context Floats Float FTM Y
ge % => Y X Context Floats Float FTM>=Y
1 index get-bottom-margin % => Y X Context Floats Float FTM>=Y FBM
6 index % => Y X Context Floats Float FTM>=Y FBM Y
lt % => Y X Context Floats Float FTM>=Y FBM<Y
and { % => Y X Context Floats Float
dup get-left-margin % => Y X Context Floats Float FRM
4 index min % => Y X Context Floats Float X'=MAX(FRM,X)
exch pop % => Y X Context Floats X'
4 3 roll pop % => Y Context Floats X'
3 1 roll % => Y X' Context Floats
array-pop-first
context-float-right-x-rec % => X
} { % => Y X Context Floats Float
pop % => Y X Context Floats
array-pop-first
context-float-right-x-rec % => X
} ifelse
} {
pop
array-pop-first
context-float-right-x-rec
} ifelse
} {
% no more floats
pop pop exch pop
} ifelse
} def % => X
% Calculates position of left floating box (taking into account the possibility
% of "wrapping" float to next line in case we have not enough space at current level (Y coordinate)
%
% @param parent reference to a parent box
% @param width width of float being placed. Full width! so, extra horizontal space (padding, margins and borders) is added here too
% @param $y Starting Y-coordinate
% @return X X coordinate of float upper-left corner
% @return Y Y coordinate of float upper-left corner
%
/context-float-right-xy { % => Parent Width Y Context
% Prepare information about the float bottom corrdinates
dup context-floats % => Parent Width Y Context Floats
make-sorted-bottom-y-list % => Parent Width Y Context FloatBottoms
context-float-right-xy-rec % => X Y
} def % => X Y
/context-float-right-xy-rec { % => Parent Width Y Context FloatBottoms
4 index get-right
3 index % => Parent Width Y Context FloatBottoms X Y
exch
3 index
context-float-right-x % => Parent Width Y Context FloatBottoms X
% Check if current float will fit into the parent box
dup % => Parent Width Y Context FloatBottoms X X
6 index get-right
rounding-epsilon add % => Parent Width Y Context FloatBottoms X X FRight
le { % => Parent Width Y Context FloatBottoms X
% will fit
exch pop exch pop % => Parent Width Y X
4 2 roll % => Y X Parent Width
pop pop exch % => X Y
} {
pop % => Parent Width Y Context FloatBottoms
% Check if all floats have been already cleared
dup length 0 eq {
% All floats are cleared; fall back to the leftmost X coordinate
pop pop exch pop % => Parent Y
exch % => Y Parent
get-left exch % => X Y
} {
% No, float does not fit at current level, let's try to 'clear' some previous floats
dup 0 get % => Parent Width Y Context FloatBottoms Bottom0
3 index min % => Parent Width Y Context FloatBottoms Y'
4 3 roll pop % => Parent Width Context FloatBottoms Y'
3 1 roll
array-pop-first % => Parent Width Y' Context FloatBottoms'
context-float-left-xy-rec % => X Y
} ifelse
} ifelse
} def % => X Y
/context-floats { % => Context
/Floats get 0 get
} def
/context-get-absolute-positioned { % => Context
/AbsolutePositioned get
} def
/context-get-collapsed-margin { % => Context
/Margin get 0 get
} def
/context-get-fixed-positioned { % => Context
/FixedPositioned get
} def
/context-get-viewport { % => Context
/Viewport get 0 get
} def
/context-point-in-floats { % => Y X Context
/null % => Y X Context /null
1 index context-floats % => Y X Context /null Floats
{ % => Y X Context /null Float
4 index
4 index
2 index
box-generic-contains-point-margin { % => Y X Context /null Float
exch pop
exit % => Y X Context Float
} if
pop
} forall % => Y X Context Float
exch pop
exch pop
exch pop
} def
/context-pop { % => Context
dup context-pop-collapsed-margin
dup context-pop-floats
pop
} def
/context-pop-collapsed-margin { % => Context
dup /Margin get % => Context CMT
array-pop-first % => Context CMT'
/Margin exch put % =>
} def
/context-pop-container-uid { % => Context
dup /ContainerUID get
array-pop-first
/ContainerUID exch put
} def
/context-pop-floats { % => Context
dup /Floats get
array-pop-first
/Floats exch put
} def
/context-pop-viewport { % => Context
dup /Viewport get
array-pop-first % => Context Viewports
/Viewport exch put % =>
} def
/context-push { % => Context
0 1 index context-push-collapsed-margin
dup context-push-floats
pop
} def
/context-push-collapsed-margin { % => Value Context
dup /Margin get % => Value Context CMT
2 index exch % => Value Content Value CMT
array-append % => Value Context CMT'
/Margin exch put % => Value
pop
} def
/context-push-container-uid { % => Uid Context
dup /ContainerUID get % => Uid Context UIDStack
2 index exch array-append % => Uid Context UIDStack'
1 index exch
/ContainerUID exch put
pop pop
} def
/context-push-floats { % => Context
dup /Floats get
[] exch array-append % => Context Floats'
/Floats exch % => Context /Floats Floats'
put % =>
} def
/context-push-viewport { % => Viewport Context
dup /Viewport get % => Viewport Context Viewports
2 index exch array-append % => Viewport Context Viewports'
1 index exch /Viewport exch put % => Viewport Context
pop pop
} def
% helper utility
/make-sorted-bottom-y-list { % => Boxes
{
get-bottom-margin
exch array-prepend
} exch
[] exch
reduce % => UnsortedBottomsYs
{ gt } % => UnsortedBottomsYs GtFun
array-sort % => SortedBottomYs
} def
%%%%%%%%%%%%%%%%%%%%%
/empty-context {
<< /Floats [] /CollapsedMarginTop [0] >>
} def
/context-stack [ empty-context ] def
/push-context {
empty-context
context-stack
array-append
/context-stack exch def
} def
/pop-context {
context-stack
array-pop-first
/context-stack exch def
} def
/context-current {
context-stack 0 get
} def
/context-floats-bottom { % => MaxValue
{ get-bottom-margin min } exch
context-floats reduce
} def
/context-save-float { % => Float
context-current
/Floats get
array-append
context-current exch
/Floats exch
put
} def
% Get the bottom edge coordinate of the bottommost float in
% current formatting context
%
% @return /null in case of no floats exists in current context
% numeric coordinate value otherwise
%
/context-float-bottom { % =>
context-floats
dup length 0 gt {
{ get-bottom-margin min }
exch
dup 0 get get-bottom-margin
exch
reduce
} {
pop /null
} ifelse
} def
% Get the right edge coordinate of the rightmost float in
% current formatting context
%
% @return null in case of no floats exists in current context
% numeric coordinate value otherwise
%
/context-float-right { % =>
context-floats
dup length 0 gt {
{ get-right-margin min }
exch
dup 0 get get-right-margin
exch
reduce
} {
pop /null
} ifelse
} def