Your IP : 216.73.217.79


Current Path : /var/www/cesa.co.za/fpdf/postscript/
Upload File :
Current File : /var/www/cesa.co.za/fpdf/postscript/box.table.ps

/box-table-apply-colspans {        % => MaxWC MinWC WidthFun Context Widths This
  dup box-table-get-colspans {     % => MaxWC MinWC WidthFun Context Widths This Colspan
    dup cellspan-get-row
    1 index cellspan-get-column
    3 index box-table-get-cell     % => MaxWC MinWC WidthFun Context Widths This Colspan Cell

% apply colspans to the corresponsing colspanned-cell dimension
    4 index 1 index
    7 index call-method           % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth

% Apply cell constraint width, if any AND if table width is constrained
% if table width is not constrained, we should not do this, as current value 
% of $table->get_width is maximal width (parent width), not the actual 
% width of the table
    1 index get-width-constraint
    dup /type get /none ne {       % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth WC
      4 index /get-width call-method
      2 index
      2 index
      dup /apply get exec          % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth WC CellWidth'
      exch pop
      exch pop
    } { pop } ifelse               % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
    
% now select the pre-calculated widths of columns covered by this cell
% select the list of resizable columns covered by this cell
    [] []                          % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth' SpannedWidth SpannedRezisable

    4 index cellspan-get-column
    1
    6 index cellspan-get-column
    7 index cellspan-get-size add
    1 sub {                        % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth SpannedRezisable I
       7 index 1 index get         % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth SpannedRezisable I Widths[i]
       4 3 roll array-prepend
       3 1 roll                    % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable I
       11 index 1 index get        % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable I MaxWC[i]
       11 index 2 index get        % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable I MaxWC[i] MinWC[i]
       ne                          % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable I MaxWC[i]<>MinWC[i]
       exch pop
       exch array-prepend          % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable'
    } for                          % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable'  

% Sometimes we may encounter the colspan over the empty columns (I mean ALL columns are empty); in this case
% we need to make these columns reizable in order to fit colspanned cell contents

    1 index sum 0 eq {             % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable'  
      0 1 2 index length 1 sub {   % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable' I
        2 index 1 index rounding-epsilon put
        1 index 1 index true put
        pop
      } for
    } if                           % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable'  

% The same problem may arise when all colspanned columns are not resizable; in this case we'll force all
% of them to be resized
    { or } false 2 index reduce    % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable' AnyResizable
    not {
      0 1 2 index length 1 sub {   % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable' I
        1 index 1 index true put
        pop
      } for     
    } if                           % => MaxWC MinWC WidthFun Context Widths This Colspan Cell CellWidth'
                                   %    SpannedWidth' SpannedRezisable'
    
% Expand resizable columns
    expand-to-with-flags           % => MaxWC MinWC WidthFun Context Widths This Colspan Cell SpannedWidths'

% Store modified widths
    4 index
    3 index cellspan-get-column
    2 index
    putinterval                    % => MaxWC MinWC WidthFun Context Widths This Colspan Cell SpannedWidths'

    pop pop pop
  } forall                         % => MaxWC MinWC WidthFun Context Widths' This
  
  pop
  exch pop
  exch pop
  exch pop
  exch pop
} def                              % => Widths

/box-table-columns-fit {           % => Context Width Table
  2 index 
  1 index
  box-table-get-table-columns-min-widths % => Context Width Table MinW

  3 index
  2 index
  box-table-get-table-columns-max-widths % => Context Width Table MinW MaxW

% Store number of columns

  dup length                       % => Context Width Table MinW MaxW Columns

% Apply column width constraints

  [] []                            % => Context Width Table MinW MaxW Columns MinWC MaxWC
  0 1 4 index 1 sub {              % => Context Width Table MinW MaxW Columns MinWC MaxWC I
    dup 7 index
    box-table-get-cwc              % => Context Width Table MinW MaxW Columns MinWC MaxWC I CWC

% Do not allow constrained max width be less than min width
% Do not allow constrained min width be less than min width

    7 index /get-width call-method % => Context Width Table MinW MaxW Columns MinWC MaxWC I CWC ThisWidth
    8 index /cellpadding get-css-value 2 mul
    9 index /cellspacing get-css-value add
                                   % => Context Width Table MinW MaxW Columns MinWC MaxWC I CWC ThisWidth Extra
    
    
    8 index 4 index get            % => Context Width Table MinW MaxW Columns MinWC MaxWC I CWC ThisWidth Extra MinW[i]
    1 index sub
    2 index 1 index 5 index
    dup /apply get exec            % => Context Width Table MinW MaxW Columns MinWC MaxWC I CWC ThisWidth Extra MinW[i] MinW[i]'
    2 index add
    max                            % => Context Width Table MinW MaxW Columns MinWC MaxWC I CWC ThisWidth Extra MinW[i]''
    7 6 roll array-prepend
    6 1 roll                       % => Context Width Table MinW MaxW Columns MinWC' MaxWC I CWC ThisWidth Extra

    8 index 4 index get            % => Context Width Table MinW MaxW Columns MinWC MaxWC I CWC ThisWidth Extra MinW[i]
    1 index sub
    2 index 1 index 5 index
    dup /apply get exec            % => Context Width Table MinW MaxW Columns MinWC MaxWC I CWC ThisWidth Extra MinW[i] MaxW[i]'
    2 index add
    max                            % => Context Width Table MinW MaxW Columns MinWC MaxWC I CWC ThisWidth Extra MaxW[i]''
    6 5 roll array-prepend
    5 1 roll                       % => Context Width Table MinW MaxW Columns MinWC MaxWC' I CWC ThisWidth Extra

    pop pop pop pop                % => Context Width Table MinW MaxW Columns MinWC MaxWC
  } for 

  1 index 5 index 8 index 8 index
  box-table-normalize-min-widths   % => Context Width Table MinW MaxW Columns MinWC MaxWC MinWC'
  3 2 roll pop exch                % => Context Width Table MinW MaxW Columns MinWC' MaxWC 

  dup 
  2 index
  /get-min-width
  10 index
  5 index
  10 index
  box-table-apply-colspans         % => Context Width Table MinW MaxW Columns MinWC MaxWC MinWC'
  3 2 roll pop exch                % => Context Width Table MinW MaxW Columns MinWC' MaxWC 

% We need to normalize widths for the case of colspans width is too much; for example:
% <table><tr><td width="100">
% <table><tr><td width="150">TEXT<td>TEXT<tr><td colspan="2" width="200">
% in this case table SHOULD NOT be expanded over the 100px!

  1 index
  5 index
  8 index
  8 index
  box-table-normalize-min-widths  % => Context Width Table MinW MaxW Columns MinWC' MaxWC MinWC'
  3 2 roll pop exch
  
  dup
  2 index
  /get-max-width
  10 index
  4 index
  10 index
  box-table-apply-colspans         % => Context Width Table MinW MaxW Columns MinWC  MaxWC MaxWC'
  exch pop                         % => Context Width Table MinW MaxW Columns MinWC' MaxWC 

% Calculate actual widths
% Calculate widths for all constrained columns

  []
  0 1 5 index 1 sub {              % => Context Width Table MinW MaxW Columns MinWC' MaxWC Widths I
    dup 8 index
    box-table-is-constrained-column {
      3 index exch get
      exch array-prepend           % => Context Width Table MinW MaxW Columns MinWC' MaxWC Widths'
    } {                            % => Context Width Table MinW MaxW Columns MinWC' MaxWC Widths I
      pop 0 exch array-prepend     % => Context Width Table MinW MaxW Columns MinWC' MaxWC Widths'
    } ifelse
  } for                            % => Context Width Table MinW MaxW Columns MinWC' MaxWC Widths'
  
% Quick fix for overconstrained tables: if table have width attribute AND its value is less than sum
% of constrained columns widths plus minimal widths of uncostrained columns, then we'll expand the width of table
% to fit all columns
% 1. calculate sum of constrained column widths
% 2. calculate sum of unconstrained column minimal widths

  0 0                             % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths SumCW SumUCW
  0 1 7 index 1 sub {             % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths SumCW SumUCW I
    dup 10 index box-table-is-constrained-column {
      3 index 1 index get         % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths SumCW SumUCW I W
      4 3 roll add 3 1 roll       % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths SumCW' SumUCW I
    } {
      5 index 1 index get         % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths SumCW SumUCW I CW
      3 2 roll add exch           % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths SumCW SumUCW' I
    } ifelse
    pop
  } for                           % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths SumCW SumUCW
  
% 3. compare these widths with the table width and choose the maximal value

  add
  8 index max                     % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths Width'
  9 8 roll pop 8 1 roll           % => Context Width' Table MinW MaxW Columns MinWC MaxWC Widths

% Second pass - disctribute the rest of the width

% Explanation of the stuff below (I've really had problems with this small piece of code, especially
% when I was trying to fix "bugs" inside it)
% 
% First of all, no column can be narrower than it minimal width (determined by its content)
% Note that constrained columns have their widths distributed above, so we can exclude them for now 
% (just throw them out and imagine that table does not contain any width-constrained cols)
%
% Second, the relative widths of columns will have _appoximately_ the same ratio as
% their maximal content widths. (In exception of cases where the first rule will take place - 
% say for the table containing two columns with the VERY long text in the first and one or two words
% in the second)
%
% In general, this approach can be inoptimal in case of _very_ different font sizes
% inside the cells, of, say big images; nevertheless, it will give a good approximate
% AND still fast enough (unlike fully correct methods involving evaluation of the content height of the cell)
% 
% Thus, we do the following:
% - calculate the ratio of current column MAXIMAL ($current_max) width to the sum of MAXIMAL widths of all columns left
%   (inluding current) second rule applied. Note that we need remember about column spans and select 
%   maxw or maxwc in order.
% - then check if the rest of width will be too small for other columns to fit and decrease current columns
%   width (see MIN function call)
% - then check again if our width will be too small for current column to fit (and expand if nesessary) - 
%   MAX function call
                                   % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths

  0 1 5 index 1 sub {              % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I
    dup 8 index
    box-table-is-constrained-column not {
        
% Get undistributed width (total table width - width of constrained columns)

      8 index 2 index sum sub      % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest
        
% get max width of column being processed
% If width is equal to zero, use max constrained width, as this column could be covered by colspan;
% If not, we lose nothing, because all constrained columns are already processed earlier, and no more
% columns except these two types can have different constrained and raw widths

      6 index 2 index get
      4 index 3 index get max      % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax

% Get sum of maximal constrained widths of unplaced columns
      0 0                          % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW SumMinCW

      0 1 10 index 1 sub {         % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW SumMinCW J
        6 index 1 index get 0 eq {
          10 index 1 index get
          8 index  2 index get
          max                      % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW SumMinCW J DSumMaxCW
          4 3 roll add 3 1 roll    % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW' SumMinCW J

          11 index 1 index get
          9  index 2 index get
          max                      % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW SumMinCW J DSumMinCW
          3 2 roll add exch        % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW SumMinCW' J
        } if                       % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW SumMinCW J
        pop
      } for                        % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW SumMinCW

% If some unplaced columns have maximal (constrained width) greater zero
      1 index 0 gt {               % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW SumMinCW
        10 index 5 index get
        8 index 6 index get max    % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW SumMinCW max($minwc[$i],$minw[$i]))
        1 index sub
        4 index add                % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW SumMinCW ($rest-$sum_min_cw+max($minwc[$i],$minw[$i]))
        3 index
        5 index mul
        3 index div

        min                        % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I Rest CurrentMax
                                   %    SumMaxCW SumMinCW CurrentMax'
        exch pop
        exch pop
        exch pop
        exch pop                   % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I CurrentMax'
      } {
        pop pop exch pop
      } ifelse                     % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I CurrentMax

% Check for minimal width (either unconstrained or constrained) of current column

      7 index 2 index get 0 eq {     % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I CurrentMax
        4 index 2 index get
      } {
        7 index 2 index get
      } ifelse
      max                            % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I CurrentMax'
      
% Store calculated width

      2 index exch
      2 index exch
      put                            % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths' I 
      
    } if                           % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I CurrentMax
             
    pop
  } for                            % => Context Width' Table MinW MaxW Columns MinWC MaxWC Widths

% Process the case of a lone empty table cell (used, for example, for its background color)
% as we're using floating point numbers, we cannot use equals sign

  dup sum rounding-epsilon lt {
    0 1 2 index length 1 sub {     % => Context Width' Table MinW MaxW Columns MinWC MaxWC Widths I
      1 index exch                 % => Context Width' Table MinW MaxW Columns MinWC MaxWC I Widths
      rounding-epsilon 
      put                          % => Context Width' Table MinW MaxW Columns MinWC MaxWC Widths
    } for
  } if                             % => Context Width' Table MinW MaxW Columns MinWC MaxWC Widths

% now - the last attempt; if total width is less than box width, then we have a situation when either 
% all columns AND table are width constrained or the HTML similer to the following:
% 
% <table cellpadding="0" width="100%" bgcolor="green"><tbody><tr>
% <td colspan="2" bgcolor="yellow"></td>
% <td style="width: 100px;" bgcolor="cyan">TEXT
%
% e.g. empty column (with zero width) and fixed-width column.

  dup sum 8 index lt {             % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths
% Let's make zero-width columns
% non-zero width (so that they columb expanded) and re-try expanding columns

    0 1 2 index length 1 sub {     % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths I
      1 index 1 index get 0 eq {
        1 index 1 index rounding-epsilon put
      } if
      pop
    } for                        % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths

    7 index
    1 index
    8 index box-table-get-non-constrained-width-flags
    expand-to-with-flags         % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths Widths'
    exch pop
  } if                           % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths

% in case of overconstrained table (e.g. two columns with 20% widths), expand them
  7 index
  1 index expand-to
  exch pop                       % => Context Width Table MinW MaxW Columns MinWC MaxWC Widths'

  exch pop
  exch pop
  exch pop
  exch pop
  exch pop
  exch pop
  exch pop
  exch pop
} def

/box-table-column-widths {         % => Context Table
  1 index
  1 index /get-width call-method
  2 index box-table-columns-fit    % => Context Table Widths
  exch pop
  exch pop
} def

/box-table-count-cols {
  get-content 0 get
  get-content length
} def

/box-table-count-rows {
  get-content length
} def

/box-table-create {                % => 
  box-container-create             % => Box
  dup box-table-setup-methods
  dup /box-table add-type

% List of column width constraints
  dup [] box-table-put-cwc-list
  dup [] box-table-put-rhc-list

} def

/box-table-fit-rowspans {          % => Heights Table
% Scan all cells spanning several rows
  dup box-table-get-rowspans       % => Heights Table Rowspans
  {                                % => Heights Table Rowspan
    dup cellspan-get-row
    1 index cellspan-get-column     % => Heights Table Rowspan RsRow RsCol
    3 index box-table-get-cell     % => Heights Table Rowspan Cell

% now check if cell height is less than sum of spanned rows heights
    3 index
    2 index cellspan-get-row
    3 index cellspan-get-size
    getinterval                    % => Heights Table Rowspan Cell RowHeights
    sum                            % => Heights Table Rowspan Cell RowHeightsSum

    dup 2 index get-full-height gt {
% Vertical-align current cell 
% calculate (approximate) row baseline
      3 index get-content          % => Heights Table Rowspan Cell RowHeightsSum Rows
      3 index cellspan-get-row get % => Heights Table Rowspan Cell RowHeightsSum Row
      box-table-row-get-baseline   % => Heights Table Rowspan Cell RowHeightsSum RowBaseline
      

% apply vertical-align
      1 index 3 index              % => Heights Tablw Rowspan Cell RowHeightsSum Baseline RowHeightsSum Cell
      box-table-cell-apply-vertical-align
                                   % => Heights Tablw Rowspan Cell RowHeightsSum

% Make cell fill all available vertical space
      dup 2 index put-full-height  % => Heights Tablw Rowspan Cell RowHeightsSum
    } if                           % => Heights Table Rowspan Cell RowHeightsSum
    pop pop pop
  } forall                         % => Heights Table

  pop pop
} def

/box-table-get-cell {              % => Y X Table
  dup get-content
  3 index get                      % => Y X Table Row
  get-content
  2 index get                      % => Y X Table Cell
  exch pop
  exch pop
  exch pop
} def

/box-table-get-colspans {          % => Table
  []
  0
  2 index get-content              % => Table RS I Rows
  {                                % => Table RS I Row
    1 index exch
    box-table-row-get-colspans     % => Table RS I RowColSpans
    3 2 roll exch                  % => Table I RS RowColSpans 
    array-merge                    % => Table I RS'
    exch                           % => Table RS' I 

    1 add
  } forall
  pop

  exch pop
} def

/box-table-get-cwc {               % => Index Table
  /CWC get exch get
} def

% Note that if table have no width constraint AND some columns are percentage constrained,
% then the width of the table can be determined based on the minimal column width; 
% e.g. if some column have minimal width of 10px and 10% width constraint,
% then table will have minimal width of 100px. If there's several percentage-constrained columns,
% then we choose from the generated values the maximal one
%
% Of course, all of the above can be applied ONLY to table without width constraint;
% of theres any w.c. applied to the table, it will have greater than column constraints
% 
% We must take constrained table width into account; if there's a width constraint,
% then we must choose the maximal value between the constrained width and sum of minimal
% columns widths - so, expanding the constrained width in case it is not enough to fit
% the table contents
%
% @param $context referene to a flow context object
% @return minimal box width (including the padding/margin/border width! NOT content width)
%
/box-table-get-min-width {         % => Context Table
  1 index 1 index
  box-table-get-table-columns-min-widths
                                   % => Context Table Widths
  dup sum                          % => Context Table Widths Width
  dup                              % => Context Table Widths Width BaseWidth

  3 index get-width-constraint
  /type get /none ne {             % => Context Table Widths Width BaseWidth
% Check if constrained table width should be expanded to fit the table contents

    1 index                        % => Context Table Widths Width BaseWidth Width
    5 index 
    5 index get-parent
    box-container-get-available-width
                                   % => Context Table Widths Width BaseWidth Width AvailWidth
    0
    6 index get-width-constraint
    dup /apply get exec            % => Context Table Widths Width BaseWidth Width CWidth
    max                            % => Context Table Widths Width BaseWidth Width'

    3 2 roll pop exch              % => Context Table Widths Width' BaseWidth
  } {                              % => Context Table Widths Width BaseWidth
% Now check if there's any percentage column width constraints (note that 
% if we've get here, than the table width is not constrained). Calculate 
% the table width basing on these values and select the maximal value

    0                              % => Context Table Widths Width BaseWidth I
    3 index {                      % => Context Table Widths Width BaseWidth I Widths[i]
      1 index
      6 index box-table-get-cwc    % => Context Table Widths Width BaseWidth I Widths[i] CWC

      3 index exch                 % => Context Table Widths Width BaseWidth I Widths[i] BaseWidth CWC
      2 index exch                 % => Context Table Widths Width BaseWidth I Widths[i] BaseWidth Width[i] CWC
      dup /apply-inverse get exec  % => Context Table Widths Width BaseWidth I Widths[i] ICW

      7 index
      7 index get-parent
      box-container-get-available-width
                                   % => Context Table Widths Width BaseWidth I Widths[i] ICW AW
      7 index get-hor-extra sub    % => Context Table Widths Width BaseWidth I Widths[i] ICW AW-HE
      min                          % => Context Table Widths Width BaseWidth I Widths[i] min(ICW,AW-HE)

      4 index max                  % => Context Table Widths Width BaseWidth I Widths[i] W
      5 4 roll pop 4 1 roll        % => Context Table Widths Width' BaseWidth I Widths[i]
      
      pop 1 add
    } forall                       % => Context Table Widths Width BaseWidth I
    pop    
  } ifelse

  pop                              % => Context Table Widths Width
  2 index get-hor-extra add        % => Context Table Widths Width'
  exch pop
  exch pop
  exch pop
} def

/box-table-get-max-width {         % => Context Table
  dup get-width-constraint
  /type get /none ne {             % => Context Table 
% Check if constrained table width should be expanded to fit the table contents
    1 index
    1 index
    box-container-get-available-width
                                   % => COntext Table AvailableWidth
    0                              % => Context Table AvailableWidth 0
    2 index get-width-constraint   % => Context Table AvailableWidth 0 WC
    dup /apply get exec            % => Context Table WC
  } {                              % => Context Table
    2 copy
    box-table-get-table-columns-max-widths
                                   % => Context Table CMaxW
    2 index
    2 index
    box-table-get-table-columns-min-widths
                                   % => Context Table CMaxWs CMinWs
    1 index
    1 index
    /get-max-width                 % => Context Table CMaxWs CMinWs CMaxWs CMinWs /get-max-width
    6 index                        % => Context Table CMaxWs CMinWs CMaxWs CMinWs /get-max-width Context
    3 index                        % => Context Table CMaxWs CMinWs CMaxWs CMinWs /get-max-width Context CMaxWs
    7 index
    box-table-apply-colspans       % => Context Table CMaxWs CMinWs CMaxWs'
    exch pop exch pop              % => Context Table Widths

    dup sum dup                    % => COntext Table Widths W BaseW
      
% Now check if there's any percentage column width constraints (note that 
% if we've get here, than the table width is not constrained). Calculate 
% the table width basing on these values and select the maximal value

    0                              % => Context Table Widths Width BaseWidth I
    3 index {                      % => Context Table Widths Width BaseWidth I Widths[i]
      1 index
      6 index box-table-get-cwc    % => Context Table Widths Width BaseWidth I Widths[i] CWC

      3 index exch                 % => Context Table Widths Width BaseWidth I Widths[i] BaseWidth CWC
      2 index exch                 % => Context Table Widths Width BaseWidth I Widths[i] BaseWidth Width[i] CWC
      dup /apply-inverse get exec  % => Context Table Widths Width BaseWidth I Widths[i] ICW

      7 index
      7 index get-parent
      box-container-get-available-width
                                   % => Context Table Widths Width BaseWidth I Widths[i] ICW AW
      7 index get-hor-extra sub    % => Context Table Widths Width BaseWidth I Widths[i] ICW AW-HE
      min                          % => Context Table Widths Width BaseWidth I Widths[i] min(ICW,AW-HE)

      4 index max                  % => Context Table Widths Width BaseWidth I Widths[i] W
      5 4 roll pop 4 1 roll        % => Context Table Widths Width' BaseWidth I Widths[i]
      
      pop 1 add
    } forall                       % => Context Table Widths Width BaseWidth I
    pop pop exch pop               % => Context Table Width
  } ifelse

  1 index get-hor-extra add        % => Context Table Width'
  exch pop
  exch pop
} def

% Get a list of boolean values indicating if table rows are NOT constant constrained
% 
% @return array containing 'true' value at index I if I-th row is height-constrained
% and 'false' otherwise
%
/box-table-get-non-constant-constrained-height-flags {
  []                               % => Table Flags
  0 1 3 index
  box-table-count-rows
  1 sub {                          % => Table Flags I 
    2 index box-table-get-rhc      % => Table Flags RHC
    hc-is-constant not             % => Table Flags Flag
    exch array-prepend             % => Table Flags'
  } for                            % => Table Flags

  exch pop                         % => Flags
} def

% Get a list of boolean values indicating if table rows are height constrained
% 
% @return array containing 'true' value at index I if I-th row is not height-constrained
% and 'false' otherwise
%
/box-table-get-non-constrained-flags { % => Table
  []                               % => Table Flags
  0 1 3 index
  box-table-count-rows
  1 sub {                          % => Table Flags I 
    2 index box-table-get-rhc      % => Table Flags RHC
    hc-is-null                     % => Table Flags Flag
    exch array-prepend             % => Table Flags'
  } for                            % => Table Flags

  exch pop                         % => Flags
} def

% Get a list of boolean values indicating if table columns are height constrained
% 
% @return array containing 'true' value at index I if I-th columns is not width-constrained
% and 'false' otherwise
%
/box-table-get-non-constrained-width-flags {
  []                               % => Table Flags
  0 1 3 index
  box-table-count-cols
  1 sub {                          % => Table Flags I 
    2 index box-table-get-cwc      % => Table Flags CWC
    /type get /none eq
    exch array-prepend             % => Table Flags'
  } for                            % => Table Flags

  exch pop                         % => Flags  
} def

% Get a list of boolean values indicating if table rows are height constrained using percentage values
% 
% @return array containing 'true' value at index I if I-th row is not height-constrained
% and 'false' otherwise
%
/box-table-get-non-percentage-constrained-height-flags {
  []                               % => Table Flags
  0 1 3 index
  box-table-count-rows
  1 sub {                          % => Table Flags I 
    2 index box-table-get-rhc      % => Table Flags RHC
    hc-is-percentage not           % => Table Flags Flag
    exch array-prepend             % => Table Flags'
  } for                            % => Table Flags

  exch pop                         % => Flags
} def

/box-table-get-rhc {               % => Index Table
  /RHC get exch get
} def

/box-table-get-rowspans {          % => Table
  []
  0
  2 index get-content              % => Table RS I Rows
  {                                % => Table RS I Row
    1 index exch
    box-table-row-get-rowspans     % => Table RS I RowColSpans
    3 2 roll exch                  % => Table I RS RowColSpans 
    array-merge                    % => Table I RS'
    exch                           % => Table RS' I 

    1 add
  } forall                         % => Table RS I
  pop

  exch pop
} def

/box-table-get-table-columns-min-widths { % => Context Table
  []                               % => Context Table Widths
  1 index get-content 0 get get-content { % => Context Table Widths Cell
    pop 0 exch array-append
  } forall                         % => Context Table Widths

  1 index get-content {            % => Context Table Widths Row
    3 index exch
    box-table-row-get-table-columns-min-widths
    { max } zip-with               % => Context Table Widths'
  } forall                         % => Context Table Widths

  exch pop
  exch pop
} def

/box-table-get-table-columns-max-widths { % => Context Table
  []                               % => Context Table Widths
  1 index get-content 0 get get-content { % => Context Table Widths Cell
    pop 0 exch array-append
  } forall                         % => Context Table Widths

  1 index get-content {            % => Context Table Widths Row
    3 index exch
    box-table-row-get-table-columns-max-widths
    { max } zip-with               % => Context Table Widths'
  } forall                         % => Context Table Widths

% Use column width constraints - column should not be wider its constrained width
  0 1 2 index length 1 sub {       % => Context Table Widths I
    dup 3 index box-table-get-cwc  % => Context Table Widths I CWC

% Newertheless, percentage constraints should not be applied IF table 
% does not have constrained width

    dup /type get
    /fraction eq not {             % => Context Table Widths I CWC
      3 index /get-width call-method
      3 index 3 index get
      2 index dup /apply get exec  % => Context Table Widths I CWC W
      3 index exch
      3 index exch put             % => Context Table Widths I CWC
    } if
    pop
    pop
  } for
  
  exch pop
  exch pop
} def

/box-table-get-width {             % => Table
  dup get-parent
  /box-table-cell is-a not         % => Table C1
  1 index get-parent
  get-width-constraint /type get
  /none eq not                     % => Table C1 C2
  2 index get-width-constraint
  /type get /fraction eq not       % => Table C1 C2 C3
  or or {
    dup get-parent /Position get /width get
    1 index /Position get /width get
    2 index get-width-constraint
    wc-apply                       % => Table W
  } {
    dup /Position get /width get
  } ifelse

  exch pop
} def

/box-table-have-colspan {          % => Y X Table
  3 copy box-table-get-cell        % => Y X Table Cell
  box-table-cell-get-colspan
  
  exch pop
  exch pop
  exch pop
} def

/box-table-have-rowspan {          % => Y X Table
  dup get-content                  % => Y X Table Rows
  3 index get                      % => Y X Table Row
  2 index get                      % => Y X Table Cell
  box-table-cell-get-rowspan
  
  exch pop
  exch pop
  exch pop
} def

/box-table-is-constrained-column { % => Index Table
  2 copy box-table-get-cwc
  /type get /none ne
  
  exch pop
  exch pop
} def

% Tries to change minimal constrained width so that columns will fit into the given
% table width
%
% Note that every width constraint have its own priority; first, the unconstrained columns are collapsed,
% then - percentage constrained and after all - columns having fixed width
% 
% @param $width table width
% @param $minw array of unconstrained minimal widths
% @param $minwc array of constrained minimal widths
% @return list of normalized minimal constrained widths
%
/box-table-normalize-min-widths {  % => MinWC MinW Width Table
% Check if sum of constrained widths is too big
% Note that we compare sum of constrained width with the MAXIMAL value of table width and
% sum of uncostrained minimal width; it will prevent from unneeded collapsing of table cells
% if table content will expand its width anyway

  2 index sum
  2 index max                      % => MinWC MinW Width Table TWidth

% compare with sum of minimal constrained widths
  
  4 index sum 1 index gt {
    4 index sum 1 index sub        % => MinWC MinW Width Table TWidth Delta

% Calculate the amount of difference between minimal and constrained minimal width for each columns
    5 index
    5 index
    { sub } zip-with               % => MinWC MinW Width Table TWidth Delta Diff

% If no difference is found, we can collapse no columns
% otherwise scale some columns...

    dup sum                        % => MinWC MinW Width Table TWidth Delta Diff CWDelta

    dup 0 gt {                     % => MinWC MinW Width Table TWidth Delta Diff CWDelta
      0 1 3 index length 1 sub {   % => MinWC MinW Width Table TWidth Delta Diff CWDelta I
        2 index 1 index get neg    % => MinWC MinW Width Table TWidth Delta Diff CWDelta I -diff[i]
        2 index div                % => MinWC MinW Width Table TWidth Delta Diff CWDelta I -diff[i]/cwdelta
        4 index mul                % => MinWC MinW Width Table TWidth Delta Diff CWDelta I -diff[i]/cwdelta*delta
        9 index 2 index get add    % => MinWC MinW Width Table TWidth Delta Diff CWDelta I MinWC[i]'
        9 index exch
        2 index exch put           % => MinWC MinW Width Table TWidth Delta Diff CWDelta I
        pop                        % => MinWC MinW Width Table TWidth Delta Diff CWDelta
      } for
    } if                           % => MinWC MinW Width Table TWidth Delta Diff CWDelta
    pop pop pop
  } if                             % => MinWC MinW Width Table TWidth
  pop pop pop pop                  % => MinWC
} def
     
/box-table-put-cwc-list {          % => Box List
  /CWC exch put
} def

/box-table-put-rhc-list {          % => Box List
  /RHC exch put

} def

/box-table-reflow {                % => Context Parent This
  dup /float get-css-value /none eq {
    3 copy
    box-table-reflow-static-normal
  } {
    3 copy
    box-container-reflow-static-float
  } ifelse

  pop pop pop
} def

/box-table-reflow-content {        % => Context This
% Reset current Y value

  dup get-top
  1 index put-current-y

% Determine the base table width 
% if width constraint exists, the actual table width will not be changed anyway

  dup /get-width call-method
  2 index 2 index /get-max-width call-method
  min
  1 index put-width

% calculate width of table columns

  2 copy box-table-column-widths   % => Context This ColWidths

% Collapse table to minimum width (if width is not constrained

  dup sum 2 index put-width        % => Context This ColWidths

% Flow cells horizontally in each table row

  0 1
  3 index box-table-count-rows
  1 sub {                          % => Context This ColWidths I

% Row flow started
% Reset current X coordinate to the far left of the table

    2 index get-left
    3 index put-current-x

% Flow each cell in the row

    0                              % => Context This ColWidths I Span
    0 1
    5 index box-table-count-cols
    1 sub {                        % => Context This ColWidths I Span J
% Skip cells covered by colspans (fake cells, anyway)
      1 index 0 eq {               % => Context This ColWidths I Span J
% Flow current cell
% Any colspans here?
        2 index 1 index 6 index
        box-table-have-colspan     % => COntext This ColWidths I Span J Span'
        3 2 roll pop exch          % => COntext This ColWidths I Span' J 

% Get sum of width for the current cell (or several cells in colspan)
% In most cases, $span == 1 here (just a single cell)

        3 index 1 index 3 index
        getinterval sum            % => COntext This ColWidths I Span' J CW

% store calculated width of the current cell

        3 index 2 index            % => Context This ColWidths I Span  J CW I(Row) J(Col)
        7 index
        box-table-get-cell         % => COntext This ColWidths I Span J CW Cell

        1 index 1 index
        put-full-width             % => COntext This ColWidths I Span J CW Cell

        1 index 1 index get-hor-extra sub
        wc-create-constant
        1 index put-width-constraint % => COntext This ColWidths I Span' J CW Cell

% Flow cell

        7 index 7 index 2 index
        /reflow call-method        % => COntext This ColWidths I Span' J CW Cell

        6 index get-current-x
        2 index add
        7 index put-current-x      % => COntext This ColWidths I Span' J CW Cell
        
        pop pop
      } if                         % => Context This ColWidths I SPan J
      pop                          % => Context This ColWidths I SPan
      
% Current cell have been processed or skipped
      1 sub 0 max
    } for                          % => Context This ColWidths I SPan
      
    pop                            % => Context This ColWidths I

% row height calculation offset current Y coordinate by the row height calculated    
    2 index get-content
    1 index get                    % => Context This ColWidth I Row
    box-table-row-height           % => Context This ColWidth I RH
    3 index get-current-y
    exch sub
    3 index put-current-y          % => Context This ColWidth I
    
    pop
  } for                            % => Context This ColWidths

  pop                              % => Context This
  
% Calculate (and possibly adjust height of table rows)
  0.1 1 index box-table-row-heights % => Context This RowHeights

% adjust row heights to fit cells spanning several rows
  1 index box-table-get-rowspans { % => Context This RowHeights Rowspan
    % Get height of the cell
    dup cellspan-get-row
    1 index cellspan-get-column
    4 index
    box-table-get-cell
    get-full-height                % => Context This RowHeights Rowspan CellHeight

% Get calculated height of the spanned-over rows
    2 index
    2 index cellspan-get-row
    3 index cellspan-get-size
    getinterval                    % => Context This RowHeights Rowspan CellHeight CellRowHeights

% Get list of non-constrained columns
    4 index box-table-get-non-constrained-flags
    3 index cellspan-get-row
    4 index cellspan-get-size
    getinterval                    % => Context This RowHeights Rowspan CellHeight CellRowHeights Flags

% Expand row heights (only for non-constrained columns)
    3 copy
    expand-to-with-flags           % => Context This RowHeights Rowspan CellHeight CellRowHeights Flags NewHeights
    exch pop                       % => Context This RowHeights Rowspan CellHeight CellRowHeights NewHeights

% Check if rows could not be expanded

    dup sum 3 index rounding-epsilon sub lt { % => Context This RowHeights Rowspan CellHeight CellRowHeights NewHeights
      pop
      
% Get list of non-constant-constrained columns

      4 index box-table-get-non-constant-constrained-flags
      3 index cellspan-get-row
      4 index cellspan-get-size
      getinterval                  % => Context This RowHeights Rowspan CellHeight CellRowHeights Flags
      
      3 copy
      expand-to-with-flags         % => Context This RowHeights Rowspan CellHeight CellRowHeights Flags NewHeights
      exch pop                     % => Context This RowHeights Rowspan CellHeight CellRowHeights NewHeights
    } if                           % => Context This RowHeights Rowspan CellHeight CellRowHeights NewHeights

% Update the rows heights
    4 index
    4 index cellspan-get-row
    2 index
    putinterval                    % => Context This RowHeights Rowspan CellHeight CellRowHeights NewHeights

    pop pop pop pop
  } forall                         % => Context This RowHeights

% Now expand rows to full table height
  dup sum
  2 index get-height
  max                              % => Context This RowHeights TableHeight

% Get list of non-constrained coluns
  2 index box-table-get-non-constrained-flags
  1 index exch
  3 index exch
  expand-to-with-flags             % => Context This RowHeights TableHeight RowHeights'
  3 2 roll pop exch                % => Context This RowHeights' TableHeight

% Check if rows could not be expanded
  1 index sum
  1 index rounding-epsilon sub     % => Context This RowHeights' TableHeight
  lt {
% Get list of non-constant-constrained columns
    2 index box-table-get-non-constant-constrained-flags
% use non-constant-constrained rows
    2 index exch
    expand-to-with-flags           % => Context This RowHeights' TableHeight
  } if                             % => Context This RowHeights' TableHeight
  pop
  
% Now we calculated row heights, time to actually resize them
  dup 2 index box-table-resize-rows % => Context This RowHeights

% Update size of cells spanning several rows
  dup 2 index
  box-table-fit-rowspans           % => Context This Rowheights

  pop pop pop
} def

/box-table-reflow-static-normal {  % => Context Parent This
% Calculate margin values if they have been set as a percentage
  1 index 1 index
  box-generic-calc-percentage-margins

% Calculate width value if it had been set as a percentage
  3 copy
  box-generic-calc-percentage-width

% As table width can be deterimined by its contents, we may calculate auto values
% only AFTER the contents have been reflown; thus, we'll offset the table 
% as a whole by a value of left margin AFTER the content reflow

% Do margin collapsing

  3 copy box-generic-collapse-margin % => Context Parent This Y
 
% At this moment we have top parent/child collapsed margin at the top of context object
% margin stack

  3 index exch 2 index box-generic-apply-clear

% Store calculated Y coordinate as current Y in the parent box

  2 index put-current-y            % => Context Parent This

% Terminate current parent line-box

  2 index 2 index
  box-container-close-line

% And add current box to the parent's line-box (alone)

  dup 2 index
  box-container-append-line        % => Context Parent This

% Determine upper-left _content_ corner position of current box 
% Also see note above regarding margins

  1 index get-current-x
  1 index get-border-left-width add
  1 index get-padding-left add
  1 index put-left                 % => Context Pareht This

% Note that top margin already used above during maring collapsing

  1 index get-current-y
  1 index get-border-top-width sub
  1 index get-padding-top sub
  1 index put-top                  % => Context Parent This

% By default, child block box will fill all available parent width;
% note that actual width will be smaller because of non-zero padding, border and margins

  2 index 
  2 index box-container-get-available-width
  1 index put-full-width           % => Context Parent This

% reflow contents
  
  2 index 1 index
  box-table-reflow-content         % => Context Parent This

% Update the collapsed margin value with current box bottom margin

  2 index context-pop-collapsed-margin
  2 index context-pop-collapsed-margin
  dup get-margin-bottom
  3 index context-push-collapsed-margin

% Calculate margins and/or width is 'auto' values have been specified

  2 copy box-generic-calc-auto-width-margins
  0 1 index get-margin-left 2 index
  /offset call-method

% Extend parent's height to fit current box
  dup get-bottom-margin
  2 index box-generic-extend-height

% terminate parent's line box

  2 index
  2 index box-container-close-line % => Context Parent This
  
  pop pop pop
} def

/box-table-resize-rows {           % => Heights Table
  dup get-top                      % => Heights Table RowTop
  0                                % => Heights Table RowTop I
  2 index get-content {            % => Heights Table RowTop I Row
    4 index 2 index get            % => Heights Table RowTop I Row H[I]
    3 index                        % => Heights Table RowTop I Row H[I] RowTop
    1 index                        % => Heights Table RowTop I Row H[I] RowTop H[I]
    3 index                        % => Heights Table RowTop I Row H[i] RowTop H[I] Row
    box-table-row-resize           % => Heights Table RowTop I Row H[i]

    exch pop                       % => Heights Table RowTop I H[i]
    3 2 roll exch sub exch         % => Heights Table RowTop' I
    
    1 add                          % => Heights Table RowTop I+1
  } forall                         % => Heights Table RowTop I
  pop pop

  1 index sum
  1 index put-height
  
  pop pop                          % => 
} def

% Calculate set of row heights 
%
% @param $minheight the minimal allowed height of the row; as we'll need to expand rows later
% and rows containing totally empty cells will have zero height
% @return array of row heights in media points
% 
/box-table-row-heights {           % => Minheight Box
  [] [] 0                          % => Minheight Box Heights CHeights I
  3 index get-content {            % => Minheight Box Heights CHeights I Row
    box-table-row-height           % => Minheight Box Heights CHeights I RowHeight
    5 index max                    % => Minheight Box Heights CHeights I RowHeight'

    dup                            % => Minheight Box Heights CHeights I RowHeight RowHeight
    5 4 roll                       % => Minheight Box CHeights I RowHeight RowHeight Heights
    array-prepend                  % => Minheight Box CHeights I RowHeight Heights'
    4 1 roll                       % => Minheight Box Heights' CHeights I RowHeight

    1 index 5 index
    box-table-get-rhc              % => Minheight Box Heights' CHeights I RowHeight RHC

    5 index get-content
    3 index get exch               % => Minheight Box Heights' CHeights I RowHeight RHC Cell
    2 index exch
    hc-apply                       % => Minheight Box Heights' CHeights I RowHeight RowHeightC

    4 3 roll                       % => Minheight Box Heights' I RowHeight RowHeightC CHeights
    array-prepend                  % => Minheight Box Heights' I RowHeight CHeights'
    3 1 roll                       % => Minheight Box Heights' CHeights' I RowHeight

    pop 1 add                      % => Minheight Box Heights' CHeights' I+1
  } forall pop                     % => Minheight Box Heights' CHeights'

% Now adjust percentage-constrained rows;
  2 index box-table-get-non-percentage-constrained-height-flags
                                   % => Minheight Box Heights CHeights Flags

  3 index get-height               % => Minheight Box Heights CHeights Flags H CH
  0
  0                                % => Minheight Box Heights CHeights Flags H CH I

  3 index {                        % => Minheight Box Heights CHeights Flags H CH I Flag
    {                              % => Minheight Box Heights CHeights Flags H CH I 
      4 index 1 index get          % => Minheight Box Heights CHeights Flags H CH I CH[i]
      4 3 roll exch sub            % => Minheight Box Heights CHeights Flags CH I H'
      3 1 roll                     % => Minheight Box Heights CHeights Flags H' CH I 
    } {                            % => Minheight Box Heights CHeights Flags H CH I
      4 index 1 index get          % => Minheight Box Heights CHeights Flags H CH I CH[i]
      3 2 roll add                 % => Minheight Box Heights CHeights Flags H I CH'
      exch                         % => Minheight Box Heights CHeights Flags H CH' I     
    } ifelse
    1 add
  } forall pop                     % => Minheight Box Heights CHeights Flags H CH'

  dup 0 gt {
    div                            % => Minheight Box Heights CHeights Flags Scale
    0                              % => Minheight Box Heights CHeights Flags Scale I
    2 index                        % => Minheight Box Heights CHeights Flags Scale I Flags
    {                              % => Minheight Box Heights CHeights Flags Scale I Flag
      {                            % => Minheight Box Heights CHeights Flags Scale I
        3 index 1 index get        % => Minheight Box Heights CHeights Flags Scale I CH[i]
        2 index mul                % => Minheight Box Heights CHeights Flags Scale I CH[i]'
        4 index exch               % => Minheight Box Heights CHeights Flags Scale I CH CH[i]'
        2 index exch               % => Minheight Box Heights CHeights Flags Scale I CH I CH[i]'
        put                        % => Minheight Box Heights CHeights Flags Scale I 
      } if
      1 add                        % => Minheight Box Heights CHeights Flags Scale I+1
    } forall

    pop pop pop
  } {
    pop pop pop
  } ifelse                         % => Minheight Box Heights CHeights

  { max } zip-with                 % => Minheight Box Heights'

  exch pop
  exch pop  
} def

/box-table-setup-methods {         % => Box
  dup get-box-dict /Methods get
  dup /reflow {box-table-reflow} put
  dup /get-min-width {box-table-get-min-width} put
  dup /get-max-width {box-table-get-max-width} put
  dup /get-width {box-table-get-width} put
  dup /reflow-content {box-table-reflow-content} put
  pop pop
} def                              % =>