1257 lines
51 KiB
PostScript
1257 lines
51 KiB
PostScript
% $Header: /cvsroot/html2ps/postscript/table.ps,v 1.1 2005/12/18 07:21:38 Konstantin Exp $
|
|
|
|
/table-get-row-height-constraints {% => Box
|
|
get-table-content-rows % => Rows
|
|
{
|
|
row-get-height-constraint
|
|
exch
|
|
array-append
|
|
}
|
|
[]
|
|
2 index
|
|
reduce % => Rows RHCs
|
|
|
|
exch pop % => RHCs
|
|
} def
|
|
|
|
/put-table-column-width-constraint % => WC Box
|
|
{
|
|
dup is-table {
|
|
dup table-get-cwc-raw % => WC Box CWC
|
|
1 index get-current-column
|
|
1 add % => WC Box CWC CC(1-based)
|
|
2 index get-table-content-rows % => WC Box CWC CC Rows
|
|
length % => WC Box CWC CC CR
|
|
4 index % => WC Box CWC CC CR WC
|
|
3 array astore % => WC Box CWC [CC CR WC]
|
|
exch array-prepend % => WC Box CWC'
|
|
1 index table-put-cwc-raw % => WC Box
|
|
} if
|
|
pop pop
|
|
|
|
} def
|
|
/table-get-cwc { % => Table
|
|
[] % => Table [](CWC)
|
|
|
|
1 index get-current-column
|
|
dup 0 ge {
|
|
1 add
|
|
|
|
{wc-none}
|
|
array-extend
|
|
|
|
1 index table-get-cwc-raw % => Table CWC RawCWCS
|
|
{ % => Table CWC RawCWC[CC CR WC]
|
|
aload pop % => Table CWC CC CR WC
|
|
|
|
% Ignore column-width constraints for colspanned columns
|
|
1 index
|
|
3 index
|
|
6 index
|
|
table-have-colspan 1 eq {
|
|
exch pop % => Table CWC CC WC
|
|
exch 1 sub exch % => Table CWC CC(0-based) WC
|
|
2 index length 2 index 1 add lt {
|
|
3 1 roll {wc-none}
|
|
array-extend % => Table WC CWC'
|
|
array-prepend % => Table CWC''
|
|
} {
|
|
2 index
|
|
3 1 roll
|
|
put
|
|
} ifelse
|
|
} {
|
|
pop pop pop
|
|
} ifelse
|
|
} forall
|
|
exch pop
|
|
} {
|
|
pop pop pop []
|
|
} ifelse
|
|
} def
|
|
|
|
% Get the cell-width constraint
|
|
% @param R row number (zero based)
|
|
% @param C column number (zero based)
|
|
% @param Table table being processed
|
|
% returns false if no constraint; WC function if constraint have been found
|
|
/table-get-cwc-raw-at { % => R C Table
|
|
[] % => R C Table []
|
|
1 index table-get-cwc-raw { % => R C Table [] CurrentWC
|
|
aload pop % => R C Table [] C' R' WC
|
|
|
|
6 index 2 index eq
|
|
6 index 4 index eq and { % => R C Table [] C' R' WC
|
|
exch pop
|
|
exch pop
|
|
exch array-append % => R C Table [WC]
|
|
|
|
} {
|
|
pop pop pop
|
|
} ifelse % => R C Table [WC]
|
|
} forall
|
|
|
|
4 1 roll
|
|
pop pop pop
|
|
|
|
dup length 0 gt {
|
|
0 get
|
|
} {
|
|
pop false
|
|
} ifelse
|
|
} def
|
|
|
|
/table-get-cwc-raw { % => Table
|
|
get-content % => Content
|
|
5 get % => CWC
|
|
} def
|
|
/table-put-cwc-raw { % => CWC Table
|
|
get-content % => CWC Content
|
|
5 % => CWC Content 5
|
|
3 2 roll % => Content 5 CWC
|
|
put % =>
|
|
} def
|
|
/make-table-box { % => W Cols Rows
|
|
0 3 1 roll % => W 0(H) Cols Rows
|
|
2 copy make-table
|
|
[] [] % => W 0(H) Cols Rows [] [](ColSpans) [](RowSpans)
|
|
[] % => W 0(H) Cols Rows [] [](ColSpans) [](RowSpans) [](ColumnWidthConstraints)
|
|
6 array astore % => W 0(H) [Cols Rows [] [](ColSpans) [](RowSpans)](Content)
|
|
0 0 0 0
|
|
5 4 roll % => W H 0 0 0 0 Content
|
|
0 % => W H 0 0 0 0 Content 0(Baseline)
|
|
/show-table-box % => W H 0 0 0 0 Content 0(Baseline) DisplayFun
|
|
0 % => W H 0 0 0 0 Content 0(Baseline) DisplayFun 0(DefaultBaseline)
|
|
[0 0 0 0]
|
|
make-box
|
|
{flow-table} 1 index put-flow-fun
|
|
% Mark box as table
|
|
dup get-box-dict
|
|
/Display /table put
|
|
} def
|
|
/make-default-table-box { % => W
|
|
0 0 make-table-box
|
|
dup get-box-dict
|
|
/Width get
|
|
/Auto false put
|
|
} def
|
|
|
|
% PREDICATES
|
|
/is-constrained-column { % => WC
|
|
0 get /wc-none cvx ne
|
|
} def % => Flag
|
|
|
|
% ROW-RELATED
|
|
/table-fit-row { % => R Row Box ColsWidth
|
|
% Get total height of current row
|
|
3 2 roll % => R Box ColsWidth Row
|
|
|
|
2 index
|
|
% table-row-height accepts 1-based row indices
|
|
4 index 1 add
|
|
2 index
|
|
table-row-height % => R Box ColsWidth Row RH
|
|
|
|
% Get current Y coordinate (indicated the bottom edge of current row)
|
|
dup 2 div
|
|
4 index get-current-y
|
|
% Calculate middle Y coordinate of this row
|
|
exch sub % => R Box ColsWidth Row RH Middle
|
|
|
|
% Row baseline information
|
|
2 index get-row-baseline % => R Box ColsWidth Row RH Middle RBaseline
|
|
exch
|
|
4 3 roll % => R Box ColsWidth RH RBaseline Middle Row
|
|
|
|
{ % => R Box ColsWidth RH RBaseline Middle Cell
|
|
4 copy
|
|
apply-valign % => R Box ColsWidth RH RBaseline Middle Cell
|
|
|
|
% extend cell height to fit the row vertically
|
|
1 index % => R Box ColsWidth RH RBaseline Middle Cell Middle
|
|
6 index get-current-y % => R Box ColsWidth RH RBaseline Middle Cell Middle CY
|
|
|
|
exch sub % => R Box ColsWidth RH RBaseline Middle Cell H/2
|
|
2 mul % => R Box ColsWidth RH RBaseline Middle Cell H
|
|
dup 2 index
|
|
get-full-height % => R Box ColsWidth RH RBaseline Middle Cell H H CellH
|
|
gt { % => R Box ColsWidth RH RBaseline Middle Cell H
|
|
2 copy exch
|
|
put-full-height % => R Box ColsWidth RH RBaseline Middle Cell H
|
|
} if
|
|
% align the top edge of extended cell with the row top edge
|
|
2 div 2 index exch
|
|
add % => R Box ColsWidth RH RBaseline Middle Cell TY
|
|
1 index put-top
|
|
pop
|
|
} forall % => R Box ColsWidth RH RBaseline Middle
|
|
|
|
pop pop pop pop pop pop % =>
|
|
} def
|
|
/table-row-height { % => Box R Row
|
|
1 exch % => Box R 1(C) Row
|
|
0 exch % => Box R 1(C) 0(H) Row
|
|
{ % => Box R C H Cell
|
|
3 index
|
|
3 index % => Box R C H Cell R C
|
|
6 index % => Box R C H Cell R C Box
|
|
table-have-rowspan % => Box R C H Cell Span
|
|
1 le {
|
|
get-full-height
|
|
max % => Box R C H
|
|
} {
|
|
pop
|
|
} ifelse % => Box R C H
|
|
exch 1 add exch % => Box R C+1 H
|
|
} forall % => Box R C+1 H
|
|
4 1 roll
|
|
pop pop pop % => H
|
|
} def
|
|
/in-table-resize-rows { % => Box R OY RHs Rows
|
|
dup length 0 gt { % => Box R OY RHs Rows
|
|
1 index 0 get % => Box R OY RHs Rows H
|
|
|
|
1 index 0 get % => Box R OY RHs Rows H Row
|
|
5 index % => Box R OY RHs Rows H Row R
|
|
7 index % => Box R OY RHs Rows H Row R Box
|
|
exch % => Box R OY RHs Rows H Row Box R
|
|
3 2 roll % => Box R OY RHs Rows H Box R Row
|
|
table-row-height % => Box R OY RHs Rows H OldH
|
|
7 1 roll % => OldH Box R OY RHs Rows H
|
|
|
|
1 index 0 get % => OldH Box R OY RHs Rows H Row
|
|
|
|
dup get-row-baseline
|
|
exch % => OldH Box R OY RHs Rows H RowBaseLine Row
|
|
|
|
{ % => OldH Box R OY RHs Rows H RowBaseLine Cell
|
|
% align top edge of the expanded cell and the top edge of row
|
|
% note that table content already have vertical alignment, so it should not
|
|
% be affected by this action
|
|
dup get-left % => OldH Box R OY RHs Rows H RowBaseLine Cell X
|
|
8 index get-top-internal
|
|
7 index sub % => OldH Box R OY RHs Rows H RowBaseLine Cell X Y
|
|
2 index
|
|
move-to-box % => OldH Box R OY RHs Rows H RowBaseLine Cell
|
|
|
|
% re-try to vertical align the cell contents using new row height
|
|
1 index % => OldH Box R OY RHs Rows H RowBaseLine Cell RowBaseline
|
|
8 index get-top
|
|
7 index sub
|
|
4 index 2 div
|
|
sub % => OldH Box R OY RHs Rows H RowBaseLine Cell Baseline Middle
|
|
2 index % => OldH Box R OY RHs Rows H RowBaseLine Cell Baseline Middle Cell
|
|
5 index 4 1 roll % => OldH Box R OY RHs Rows H RowBaseLine Cell H Baseline Middle Cell
|
|
|
|
apply-valign % => OldH Box R OY RHs Rows H RowBaseLine Cell
|
|
|
|
% expand cell to the row height
|
|
2 index
|
|
1 index % => OldH Box R OY RHs Rows H RowBaseLine Cell H Cell
|
|
put-full-height % => OldH Box R OY RHs Rows H RowBaseLine Cell
|
|
|
|
pop
|
|
} forall % => OldH Box R OY RHs Rows H RowBaseLine
|
|
pop % => OldH Box R OY RHs Rows H
|
|
|
|
% Calculate new offset from the table top (old offset+current row height)
|
|
7 6 roll % => Box R OY RHs Rows H OldH
|
|
pop % => Box R OY RHs Rows H
|
|
4 3 roll % => Box R RHs Rows H OY
|
|
add % => Box R RHs Rows OY'
|
|
% remove processed element for row array
|
|
3 1 roll % => Box R OY' RHs Rows
|
|
array-pop-first % => Box R OY RHs Rows'
|
|
% remove processed element for row heights array
|
|
4 1 roll
|
|
array-pop-first % => Box Rows' R OY RHs'
|
|
% increase row index
|
|
4 2 roll
|
|
1 add % => Box OY RHs' Rows' R+1
|
|
% process next row recusively
|
|
4 1 roll % => Box R+1 OY RHs' Rows'
|
|
|
|
in-table-resize-rows
|
|
} if
|
|
} def
|
|
/table-resize-rows { % => Box RHs
|
|
dup sum % => Box RHs FH
|
|
2 index put-height % => Box RHs
|
|
1 exch % => Box 1(R) RHs
|
|
0 exch % => Box 1(R) 0(Ofs) RHs
|
|
3 index
|
|
get-table-content-rows % => Box 1(R) 0(Ofs) RHs Rows
|
|
in-table-resize-rows % => Box 1(R) OY [] []
|
|
pop pop pop pop pop
|
|
} def
|
|
/table-rows-heights { % => Box
|
|
dup get-table-content-rows % => Box Rows
|
|
[] exch % => Box [](Heights) Rows
|
|
1 exch % => Box [](Heights) 1(R) Rows
|
|
{ % => Box Heights R Row
|
|
1 index exch % => Box Heights R R Row
|
|
4 index 3 1 roll % => Box Heights R Box R Row
|
|
table-row-height % => Box Heights R H
|
|
2 index array-prepend % => Box Heights R Heights'
|
|
3 1 roll % => Box Heights' Heights R
|
|
exch pop % => Box Heights R
|
|
1 add % => Box Heights R+1
|
|
} forall % => Box Heights R
|
|
pop
|
|
exch pop % => Heights
|
|
} def
|
|
|
|
% Modify minimal column width using column span information
|
|
/get-max-width-table-column { % => Box C Column
|
|
1 exch
|
|
0 exch { % => Box C 1(R) 0(ColumnMinWidth) ColumnElement
|
|
2 index % => Box C 1(R) 0(ColumnMinWidth) ColumnElement R
|
|
4 index % => Box C 1(R) 0(ColumnMinWidth) ColumnElement R C
|
|
6 index
|
|
table-have-colspan 1 gt { % => Box C R Width Element
|
|
pop % => Box C R Width
|
|
} {
|
|
get-max-width % => Box C R Width CWidth
|
|
max % => Box C R Width'
|
|
} ifelse
|
|
exch 1 add exch % => Box C R+1 Width'
|
|
} forall % => Box C RL Width'
|
|
|
|
exch pop % => Box C Width'
|
|
2 index get-hor-extra
|
|
sub
|
|
|
|
3 1 roll pop pop % => Width
|
|
} def
|
|
/get-min-width-table-column { % => Box C Column
|
|
1 exch
|
|
0 exch { % => Box C 1(R) 0(ColumnMinWidth) ColumnElement
|
|
2 index % => Box C 1(R) 0(ColumnMinWidth) ColumnElement R
|
|
4 index % => Box C 1(R) 0(ColumnMinWidth) ColumnElement R C
|
|
6 index % => Box C 1(R) 0(ColumnMinWidth) ColumnElement R C Box
|
|
|
|
table-have-colspan 1 gt { % => Box C R Width Element
|
|
pop % => Box C R Width
|
|
} {
|
|
% dup get-td-dict
|
|
% /NoWrap get {
|
|
% dup get-max-width
|
|
% 1 index get-min-width
|
|
% max exch pop
|
|
% } {
|
|
get-min-width % => Box C R Width CWidth
|
|
% } ifelse
|
|
max % => Box C R Width'
|
|
} ifelse
|
|
exch 1 add exch % => Box C R+1 Width'
|
|
} forall % => Box C RL Width'
|
|
|
|
exch pop % => Box C Width'
|
|
2 index get-hor-extra
|
|
sub
|
|
|
|
3 1 roll pop pop % => Width
|
|
} def
|
|
/get-table-columns-min-widths { % => Box
|
|
dup get-table-content-columns % => Box ColumnsList
|
|
1 exch
|
|
[] exch % => Box 1(C) [] ColumnsList
|
|
{ % => Box C [](Widths) Column
|
|
3 index % => Box C Widths Column Box
|
|
3 index % => Box C Widths Column Box C
|
|
3 2 roll % => Box C Widths Box C Column
|
|
|
|
get-min-width-table-column % => Box C Widths ColW
|
|
exch array-prepend % => Box C Widths
|
|
|
|
exch 1 add exch % => Box C+1 TotalMinWidth
|
|
} forall % => Box C MinWidth
|
|
exch pop % => Box MinWidths
|
|
exch pop % => MinWidths
|
|
} def
|
|
/get-table-columns-max-widths { % => Box
|
|
dup get-table-content-columns % => Box ColumnsList
|
|
1 exch
|
|
[] exch % => Box 1(C) [] ColumnsList
|
|
{ % => Box C [](Widths) Column
|
|
3 index % => Box C Widths Column Box
|
|
3 index % => Box C Widths Column Box C
|
|
3 2 roll % => Box C Widths Box C Column
|
|
|
|
get-max-width-table-column % => Box C Widths ColW
|
|
exch array-prepend % => Box C Widths
|
|
|
|
exch 1 add exch % => Box C+1 TotalMinWidth
|
|
} forall % => Box C MaxWidth
|
|
exch pop % => Box MaxWidths
|
|
|
|
% Use column width constraints - column should not be wider its constrained width
|
|
1 index get-width % => Box MaxWidths BW
|
|
2 index table-normalize-cwc % => Box MaxWidths BW CWCs
|
|
2 index % => Box MaxWidths BW CWCs MaxWidths
|
|
{ 1 index is-fraction
|
|
{
|
|
6 index false 3 index exec 3 1 roll pop pop
|
|
}
|
|
{ exch false exch exec } ifelse }
|
|
zip-with
|
|
exch pop exch pop % => Box MaxWidhts
|
|
|
|
exch pop % => MinWidths
|
|
} def
|
|
|
|
/table-apply-colspans-minw { % => Flags Widths Fun Box
|
|
dup table-get-colspans % => Flags Widths Fun Box Colspans
|
|
{ % => Flags Widths Fun Box Colspan[Size R C]
|
|
dup 0 get % => Flags Widths Fun Box Colspan[Size R C] Size
|
|
1 index 1 get % => Flags Widths Fun Box Colspan[Size R C] Size R
|
|
2 index 2 get % => Flags Widths Fun Box Colspan[Size R C] Size R C
|
|
% Calculate colspanned cell width (using appropriate function passed in the stack when
|
|
% calling this function)
|
|
4 index % => Flags Widths Fun Box Colspan[Size R C] Size R C Box
|
|
table-get-cell-content % => Flags Widths Fun Box Colspan[Size R C] Size Cell
|
|
4 index exec % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth
|
|
% apply cell width constraint, if any
|
|
2 index aload pop
|
|
3 2 roll pop % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth R C
|
|
5 index table-get-cwc-raw-at % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth WC
|
|
dup false ne {
|
|
dup is-fraction {
|
|
4 index no-width-constraint not {
|
|
4 index get-width exch
|
|
false exch exec
|
|
max
|
|
} {
|
|
pop
|
|
} ifelse
|
|
} {
|
|
false exch exec
|
|
} ifelse
|
|
} {
|
|
pop
|
|
} ifelse % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth'
|
|
% now select the pre-calculated widths of columns covered by this cell
|
|
2 index 2 get % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth C
|
|
1 sub % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth C(ZeroBased)
|
|
3 2 roll % => Flags Widths Fun Box Colspan[Size R C] CellWidth C(ZeroBased) Size
|
|
1 index % => Flags Widths Fun Box Colspan[Size R C] CellWidth C Size C
|
|
exch % => Flags Widths Fun Box Colspan[Size R C] CellWidth C C Size
|
|
7 index % => Flags Widths Fun Box Colspan[Size R C] CellWidth C C Size Widths
|
|
3 1 roll % => Flags Widths Fun Box Colspan[Size R C] CellWidth C Widths C Size
|
|
getinterval % => Flags Widths Fun Box Colspan[Size R C] CellWidth C SWidths
|
|
% select the list of resizable columns covered by this cell
|
|
3 2 roll exch % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths
|
|
7 index % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths Flags
|
|
3 index % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths Flags C
|
|
5 index 0 get % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths Flags C Size
|
|
getinterval % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths SFlags
|
|
% Subtract sum width of non-resizable columns this cell spans over from the cell width
|
|
% Non-resizable columns are marked as 'false' in SFlags
|
|
2 copy {
|
|
{ pop 0 } if
|
|
} zip-with sum % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths SFlags Non-resizable-width
|
|
4 3 roll
|
|
exch sub
|
|
% do not allow target width drop below zero
|
|
0 max
|
|
3 1 roll
|
|
% Expand resizable columns to
|
|
expand-to-with-flags % => Flags Widths Fun Box Colspan[Size R C] C SWidths'
|
|
% store modified widths
|
|
5 index % => Flags Widths Fun Box Colspan[Size R C] C SWidths' Widths
|
|
3 1 roll % => Flags Widths Fun Box Colspan[Size R C] Widths C SWidths'
|
|
putinterval % => Flags Widths' Fun Box Colspan[Size R C]
|
|
pop % => Flags Widths' Fun Box
|
|
} forall % => Flags Widths' Fun Box
|
|
pop pop % => Widths'
|
|
exch pop
|
|
} def
|
|
|
|
/table-apply-colspans { % => Widths Fun Box
|
|
dup table-get-colspans % => Widths Fun Box Colspans
|
|
% Scan all cell spanning several columns
|
|
{ % => Widths Fun Box Colspan[Size R C]
|
|
% Get current colspan contents
|
|
dup 0 get % => Widths Fun Box Colspan[Size R C] Size
|
|
1 index 1 get % => Widths Fun Box Colspan[Size R C] Size R
|
|
2 index 2 get % => Widths Fun Box Colspan[Size R C] Size R C
|
|
4 index % => Widths Fun Box Colspan[Size R C] Size R C Box
|
|
table-get-cell-content % => Widths Fun Box Colspan[Size R C] Size Cell
|
|
% Calculate its width (by calling the appropriate function passed; usually it will be
|
|
% get-min-width or get-max-width)
|
|
4 index exec % => Widths Fun Box Colspan[Size R C] Size CellWidth
|
|
% apply cell width constraint, if any
|
|
2 index aload pop
|
|
3 2 roll pop % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth R C
|
|
5 index table-get-cwc-raw-at % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth WC
|
|
dup false ne {
|
|
dup is-fraction {
|
|
4 index no-width-constraint not {
|
|
4 index get-width exch
|
|
false exch exec
|
|
max
|
|
} {
|
|
pop
|
|
} ifelse
|
|
} {
|
|
false exch exec
|
|
} ifelse
|
|
} {
|
|
pop
|
|
} ifelse % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth'
|
|
% Get the width list of columns covered by current column span
|
|
2 index 2 get % => Widths Fun Box Colspan[Size R C] Size CellWidth C
|
|
1 sub % => Widths Fun Box Colspan[Size R C] Size CellWidth C(ZeroBased)
|
|
3 2 roll % => Widths Fun Box Colspan[Size R C] CellWidth C(ZeroBased) Size
|
|
1 index % => Widths Fun Box Colspan[Size R C] CellWidth C Size C
|
|
exch % => Widths Fun Box Colspan[Size R C] CellWidth C C Size
|
|
7 index % => Widths Fun Box Colspan[Size R C] CellWidth C C Size Widths
|
|
3 1 roll % => Widths Fun Box Colspan[Size R C] CellWidth C Widths C Size
|
|
getinterval % => Widths Fun Box Colspan[Size R C] CellWidth C SWidths
|
|
% expand these columns to fit spanned data
|
|
3 2 roll exch % => Widths Fun Box Colspan[Size R C] C CellWidth SWidths
|
|
expand-to % => Widths Fun Box Colspan[Size R C] C SWidths'
|
|
% Store changed widths
|
|
5 index % => Widths Fun Box Colspan[Size R C] C SWidths' Widths
|
|
3 1 roll % => Widths Fun Box Colspan[Size R C] Widths C SWidths'
|
|
putinterval % => Widths' Fun Box Colspan[Size R C]
|
|
pop % => Widths' Fun Box
|
|
} forall % => Widths' Fun Box
|
|
pop pop % => Widths'
|
|
} def
|
|
/table-column-widths { % => Box
|
|
dup get-width % => Box Width
|
|
table-columns-fit
|
|
} def
|
|
/table-columns-fit { % => Box Widht
|
|
% Check if there's any columns in table
|
|
1 index get-table-content-columns
|
|
length 0 gt {
|
|
in-table-columns-fit
|
|
} {
|
|
pop pop []
|
|
} ifelse
|
|
} def
|
|
|
|
% columns-fit helper function
|
|
/fit-cwidth { % => MW MCW TW-TCW TMCW-TMW
|
|
2 index
|
|
4 index
|
|
sub % => MW MCW TW-TCW TMCW-TMW MCW-MW
|
|
exch div % => MW MCW TW-TCW MCW-MW/TMCW-TMW
|
|
mul
|
|
add
|
|
% to avoid problems with negative cell widths
|
|
0 max
|
|
exch pop
|
|
} def
|
|
/in-table-columns-fit { % => Box Width
|
|
1 index
|
|
get-table-content-columns % => Box Width Columns
|
|
|
|
2 index % => Box Width Columns Box
|
|
get-table-columns-min-widths % => Box Width Columns MinWidths
|
|
|
|
3 index
|
|
get-table-columns-max-widths % => Box Width Columns MinWidths MaxWidths
|
|
|
|
1 index
|
|
{ max }
|
|
zip-with
|
|
|
|
% Use data on the spanned cells
|
|
% exch % => Box Width Columns MaxWidths MinWidths
|
|
% 2 copy { ne } zip-with % => Box Width Columns MaxWidths MaxWidths [MaxWidthsCi<>MinWidthsCi]
|
|
% exch % => Box Width Columns MaxWidths ResizableFlags MinWidths
|
|
|
|
% { get-min-width } 6 index % => Box Width Columns ManWidths ResizableFlags MinWidths Fun Box
|
|
% table-apply-colspans-minw % => Box Width Columns MaxWidths MinWidth
|
|
% exch % => Box Width Columns MinWidth MaxWidths
|
|
% { get-max-width } 5 index % => Box Width Columns MinWidth MaxWidths Fun Box
|
|
% table-apply-colspans % => Box Width Columns MinWidth MaxWidths
|
|
|
|
3 2 roll
|
|
pop % => Box Width MinWidths MaxWidths
|
|
|
|
% Apply column width constraints to minimum widths
|
|
2 index % => Box Width MinWidths MaxWidths BW
|
|
4 index table-normalize-cwc % => Box Width MinWidths MaxWidths BW CWCs
|
|
3 index % => Box Width MinWidths MaxWidths BW CWCs MinWidths
|
|
{ 1 index is-fraction
|
|
{
|
|
6 index false 3 index exec 3 1 roll pop pop
|
|
}
|
|
{ exch false exch exec } ifelse }
|
|
zip-with
|
|
exch pop
|
|
|
|
% Apply column width constraints to maximum widths
|
|
3 index % => Box Width MinWidths MaxWidths MinWidthsC BW
|
|
5 index table-normalize-cwc % => Box Width MinWidths MaxWidths MinWidthsC BW CWCs
|
|
3 index % => Box Width MinWidths MaxWidths MinWidthsC BW CWCs maxWidth
|
|
{ 1 index is-fraction
|
|
{
|
|
% 6 index = BW
|
|
6 index false 3 index exec 3 1 roll pop pop
|
|
}
|
|
{ exch false exch exec } ifelse }
|
|
zip-with
|
|
exch pop % => ox Width MinWidths MaxWidths MinWidthsC MaxWidths
|
|
|
|
% Do not allow constrained max width be less than min width
|
|
3 index
|
|
{ max }
|
|
zip-with % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC
|
|
|
|
% Do not allow constrained min width be less than min width
|
|
3 index
|
|
2 index
|
|
{ max }
|
|
zip-with % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC W'
|
|
|
|
3 2 roll % => Box Width MinWidths MaxWidths MaxWidthsC W' MinWidthsC
|
|
pop % => Box Width MinWidths MaxWidths MaxWidthsC W'
|
|
exch % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC
|
|
|
|
% 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
|
|
1 index sum % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC SUM(MinWidthsC')
|
|
% find the "template" value
|
|
5 index
|
|
5 index sum
|
|
max
|
|
% compare
|
|
gt {
|
|
% now we should scale columns to fit table width
|
|
1 index sum
|
|
% find template value
|
|
5 index
|
|
5 index sum
|
|
max
|
|
|
|
% Calculate the amount if difference between minimal and constrained minimal width for each columns
|
|
exch sub % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC
|
|
4 index % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC MinWidth
|
|
3 index % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC MinWidth MinWidthC
|
|
{exch sub} zip-with sum % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC CWDelta
|
|
dup 0 gt {
|
|
5 index % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC CWDelta MinW
|
|
4 index % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC CWDelta MinW MinWC
|
|
4 2 roll % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC MinW MinWC Width-MinWC CWDelta
|
|
/fit-cwidth cvx % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC MinW MinWC Width-MinWC CWDelta cit-cwidth
|
|
3 array astore cvx % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC MinW MinWC {Width-MinWC CWDelta cit-cwidth}
|
|
zip-with % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC MinWC'
|
|
exch 3 2 roll pop % => Box Width MinWidths MaxWidths MinWC' MaxWidthsC
|
|
} {
|
|
% if no difference is found, we can collapse no columns
|
|
pop pop % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC
|
|
} ifelse
|
|
} if
|
|
|
|
% Use data on the spanned cells (again)
|
|
exch % => Box Width MinWidths MaxWidths MaxWidthsC MinWidthsC
|
|
2 copy { ne } zip-with % => Box Width MinWidths MaxWidths MaxWidthsC MinWidthsC [MaxWidthsCi<>MinWidthsCi]
|
|
exch % => Box Width MinWidths MaxWidths MaxWidthsC ResizableFlags MinWidthsC
|
|
|
|
{ get-min-width } 7 index % => Box Width MinWidths MaxWidths MaxWidthsC ResizableFlags MinWidthsC Fun Box
|
|
table-apply-colspans-minw % => Box Width MinWidths MaxWidths MaxWidthsC MinWidthC
|
|
exch % => Box Width MinWidths MaxWidths MinWidthC MaxWidthsC
|
|
{ get-max-width } 6 index % => Box Width MinWidths MaxWidths MinWidthC MaxWidthsC Fun Box
|
|
table-apply-colspans % => Box Width MinWidths MaxWidths MinWidthC MaxWidthsC
|
|
|
|
% Calculate actual widths
|
|
% Prepare width array
|
|
[]
|
|
1 index length 0
|
|
array-extend % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths
|
|
|
|
% First pass - calculate widths for all constrained columns
|
|
6 index table-normalize-cwc % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs
|
|
|
|
0 1 2 index length 1 sub { % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I
|
|
2 copy get
|
|
is-constrained-column {
|
|
2 index
|
|
1 index
|
|
6 index 3 index get
|
|
put
|
|
} if
|
|
|
|
pop
|
|
} for
|
|
|
|
% 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
|
|
1 index sum % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs SumConW
|
|
% 2. calculate sum of unconstrained column minimal widths
|
|
2 index
|
|
7 index
|
|
{ 1 index 0 gt { pop pop 0 } { exch pop } ifelse }
|
|
zip-with sum % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs SumConW SumUnconW
|
|
% 3. compare these widths with the table width
|
|
add
|
|
dup 8 index gt { % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs SumConW+SumUnconW
|
|
8 7 roll pop
|
|
7 1 roll
|
|
} {
|
|
pop
|
|
} ifelse
|
|
|
|
% Second pass - distribute 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
|
|
|
|
0 1 2 index length 1 sub { % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I
|
|
2 copy get
|
|
% Process only uncostrained columns
|
|
is-constrained-column not {
|
|
2 index
|
|
1 index % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I
|
|
% Get undistibuted width (total table width - width of constrained columns)
|
|
9 index % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I Width
|
|
2 index sum sub % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest
|
|
% Get max width of column being processed
|
|
8 index 2 index get % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW
|
|
7 index 3 index get max % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW
|
|
% 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
|
|
dup 0 eq {
|
|
pop
|
|
6 index 2 index get
|
|
} if
|
|
% Get sum of maximal constrained widths of unplaced columns
|
|
3 index % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW Widths
|
|
8 index % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW Widths MaxWidthsC
|
|
{ 1 index 0 eq {exch pop} {pop pop 0} ifelse }
|
|
zip-with
|
|
sum % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MW MWR
|
|
% Get sum of minimal constrained widths of unplaced columns
|
|
4 index % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW MaxWR Widths
|
|
10 index % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW MaxWR Widths MaxWidthsC
|
|
{ 1 index 0 eq {exch pop} {pop pop 0} ifelse }
|
|
zip-with
|
|
sum % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW MaxWR MinWR
|
|
3 index exch sub % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW MaxWR WidthRest-MinWR
|
|
% add current columns min width
|
|
12 index 5 index get
|
|
11 index 6 index get max
|
|
add
|
|
4 1 roll % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest-MinWR WidthRest MaxW MaxWR
|
|
% If some unplaced columns have maximal (constrained width) greater zero
|
|
dup 0 gt {
|
|
% Calculate the appropriate fraction of free table width for the current column
|
|
div % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest-MinWR WidthRest MinWE MaxW MaxWR
|
|
mul % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest-MinWR W(WidthRest*MW/MWR)
|
|
min
|
|
% Remove minimal width of current column;
|
|
% 9 index 2 index get
|
|
% sub
|
|
% This will make calculated width not less than raw minimal column with. See also line marked with (*)
|
|
% 0 max
|
|
} {
|
|
pop pop pop pop 0
|
|
} ifelse
|
|
% (*) Add the minimal width of current column
|
|
9 index 2 index get
|
|
dup 0 eq {
|
|
pop
|
|
7 index 2 index get
|
|
} if
|
|
max % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I W
|
|
|
|
put
|
|
} if
|
|
|
|
pop
|
|
} for
|
|
pop % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths
|
|
|
|
% in case of overconstrained table (e.g. two columns with 20% widths), expand them
|
|
dup sum % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths SumWidth
|
|
dup 0 gt {
|
|
6 index
|
|
exch div
|
|
dup 1 gt {
|
|
map-scale
|
|
} { pop } ifelse
|
|
} {
|
|
pop
|
|
} ifelse % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths
|
|
|
|
% now - the last attempt; if total width is less than box width, just expand the very first column to fit
|
|
dup sum 6 index lt {
|
|
dup sum % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths SumWidth
|
|
6 index
|
|
exch sub % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths Delta
|
|
1 index 0 get % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths Delta W0
|
|
add % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths W0'
|
|
1 index exch
|
|
0 exch put % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths
|
|
} if
|
|
|
|
7 1 roll
|
|
pop pop pop
|
|
pop pop pop
|
|
} def
|
|
|
|
% Modify heights of table cells spanning several rows
|
|
/table-fit-rowspans { % => Table
|
|
dup table-rows-heights % => Table RHs
|
|
1 index table-get-rowspans % => Table RHs RS
|
|
% scan all cells spanning several rows
|
|
{ % => Table RHs RowSpan
|
|
% calculate the bottom edge of current cell
|
|
aload pop % => Box RHs Span R C
|
|
2 copy % => Box RHs Span R C R C
|
|
6 index % => Box RHs Span R C R C Box
|
|
table-get-cell-content % => Box RHs Span R C Cell
|
|
{
|
|
get-bottom
|
|
min
|
|
}
|
|
1 index get-top
|
|
2 index get-content
|
|
reduce
|
|
% reset the height of the cell to its content height (as it have been probably fitted to the top row spanned-over)
|
|
1 index get-top
|
|
sub neg
|
|
1 index put-height
|
|
|
|
% now check if cell height is less than sum spanned rows height
|
|
dup get-full-height % => Box RHs Span R C Cell CellFH
|
|
5 index % => Box RHs Span R C Cell CellFH RHs
|
|
4 index 1 sub % => Box RHs Span R C Cell CellFH RHs R
|
|
6 index % => Box RHs Span R C Cell CellFH RHs R Span
|
|
getinterval sum % => Box RHs Span R C Cell CellFH RowH
|
|
|
|
2 copy lt {
|
|
% vertical-align current cell
|
|
% calculate (approximate) row baseline
|
|
6 index % => Box RHs Span R C Cell CellFH RowH RHs
|
|
0 6 index 1 sub % => Box RHs Span R C Cell CellFH RowH RHs 0 R(ZeroBased)
|
|
getinterval sum neg % => Box RHs Span R C Cell CellFH RowH -SpannedRHs
|
|
8 index get-top-internal
|
|
add % => Box RHs Span R C Cell CellFH RowH RBaseline
|
|
% calculate row middle coordinate
|
|
dup 2 index 2 div sub % => Box RHs Span R C Cell CellFH RowH RBaseline Middle
|
|
|
|
2 index
|
|
2 index
|
|
2 index
|
|
7 index
|
|
|
|
apply-valign
|
|
|
|
pop pop
|
|
|
|
% Make cell fill all available vertical space
|
|
dup % => Box RHs Span R C Cell CellFH RowH RowH
|
|
3 index
|
|
put-full-height % => Box RHs Span R C Cell CellFH RowH
|
|
|
|
pop pop pop
|
|
} {
|
|
pop pop pop
|
|
} ifelse % => Box RHs Span R C
|
|
pop pop pop
|
|
} forall
|
|
pop pop
|
|
} def
|
|
|
|
/table-have-colspan { % => Row Col Table
|
|
table-get-colspans
|
|
1 % => Row Col Spans 1
|
|
exch % => Row Col 1 Spans
|
|
{ % => Row Col CS Span
|
|
dup 1 get % => Row Col CS Span Row
|
|
1 index 2 get % => Row Col CS Span Row Col
|
|
4 index eq % => Row Col CS Span Row CEq
|
|
exch % => Row Col CS Span CEq Row
|
|
5 index eq % => Row Col CS Span CEq REq
|
|
and % => Row Col CS Span Match
|
|
{
|
|
0 get exch pop
|
|
} {
|
|
pop
|
|
} ifelse
|
|
} forall % => Row Col CS
|
|
3 1 roll % => CS Row Col
|
|
pop pop % => CS
|
|
} def
|
|
|
|
/table-have-rowspan { % => Row Col Table
|
|
table-get-rowspans
|
|
1 % => Row Col Spans 1
|
|
exch % => Row Col 1 Spans
|
|
{ % => Row Col CS Span
|
|
dup 1 get % => Row Col CS Span Row
|
|
1 index 2 get % => Row Col CS Span Row Col
|
|
4 index eq % => Row Col CS Span Row CEq
|
|
exch % => Row Col CS Span CEq Row
|
|
5 index eq % => Row Col CS Span CEq REq
|
|
and % => Row Col CS Span Match
|
|
{
|
|
0 get exch pop
|
|
} {
|
|
pop
|
|
} ifelse
|
|
} forall % => Row Col CS
|
|
3 1 roll % => CS Row Col
|
|
pop pop % => CS
|
|
} def
|
|
|
|
/table-mark-rowspan { % => Table SpanSize
|
|
1 index
|
|
get-table-content-rows % => Table SpanSize Rows
|
|
dup length % => Table SpanSize Rows CurRow
|
|
1 index array-last % => Table SpanSize Rows CurRow LastRow
|
|
length % => Table SpanSize Rows CurRow CurColumn
|
|
3 2 roll pop % => Table SpanSize CurRow CurColumn
|
|
3 index % => Table SpanSize CurRow CurColumn Table
|
|
table-add-rowspan % => Table
|
|
} def
|
|
|
|
/table-mark-colspan { % => Table SpanSize
|
|
1 index
|
|
get-table-content-rows % => Table SpanSize Rows
|
|
dup length % => Table SpanSize Rows CurRow
|
|
1 index array-last % => Table SpanSize Rows CurRow LastRow
|
|
length % => Table SpanSize Rows CurRow CurColumn
|
|
3 2 roll pop % => Table SpanSize CurRow CurColumn
|
|
3 index % => Table SpanSize CurRow CurColumn Table
|
|
table-add-colspan % => Table
|
|
} def
|
|
|
|
/normalize-row { % => Length Row
|
|
aload length % => Length R1 .. RN N
|
|
dup % => Length R1 .. RN N N
|
|
dup 2 add % => Length R1 .. RN N N N+2
|
|
index % => Length R1 .. RN N N Length
|
|
exch sub dup % => Length R1 .. RN N Delta Delta
|
|
replicate-row % => Length R1 .. RN N []..[] Delta 0
|
|
pop % => Length R1 .. RN N []..[] Delta
|
|
dup 2 add % => Length R1 .. RN N []..[] Delta Delta+2
|
|
dup 1 sub % => Length R1 .. RN N []..[] Delta Delta+2 Delta+1
|
|
roll % => Length R1 .. RN []..[] Delta N
|
|
add % => Length R1 .. RN []..[] Delta+N
|
|
array astore % => Length Row'
|
|
exch pop % => Row'
|
|
} def
|
|
|
|
/table-slide-cw { % => R C Box
|
|
dup table-get-cwc-raw % => R C Box RawCWCS
|
|
{ % => R C Box RawCWC
|
|
aload % => R C Box !C !R WC [!C !R WC]
|
|
2 index 7 index eq {
|
|
3 index 6 index ge {
|
|
dup
|
|
0 5 index 1 add put % => R C Box !C !R WC [!C+1 !R WC]
|
|
} if
|
|
} if % => R C Box !C !R WC [!C !R WC]
|
|
pop pop pop pop
|
|
} forall
|
|
|
|
pop pop pop
|
|
} def
|
|
|
|
/do-slide-rs { % => ... RS' [SS SR SC] R C
|
|
2 index 1 get % => ... RS' [SS SR SC] R C SR
|
|
2 index eq { % => ... RS' [SS SR SC] R C
|
|
2 index 2 get % => ... RS' [SS SR SC] R C SC
|
|
1 index ge { % => ... RS' [SS SR SC] R C
|
|
2 index 2 get % => ... RS' [SS SR SC] R C SC
|
|
1 add % => ... RS' [SS SR SC] R C SC+1
|
|
3 index exch
|
|
2 exch % => ... RS' [SS SR SC] R C [..] 2 SC+1
|
|
put % => ... RS' [SS SR SC+1] R C
|
|
% FIXME: reorder rowspans after this operation?
|
|
} if
|
|
} if
|
|
|
|
pop pop
|
|
exch array-prepend
|
|
} def
|
|
|
|
/table-slide-rs { % => R C Box
|
|
2 index 2 index /do-slide-rs % => R C Box {fun}
|
|
cvx 3 array astore cvx
|
|
[]
|
|
2 index table-get-rowspans
|
|
reduce
|
|
|
|
1 index table-put-rowspans % => R C Box
|
|
|
|
pop pop pop % =>
|
|
} def
|
|
|
|
/do-slide-cs { % => ... RS' [SS SR SC] R C
|
|
2 index 1 get % => ... RS' [SS SR SC] R C SR
|
|
2 index eq { % => ... RS' [SS SR SC] R C
|
|
2 index 2 get % => ... RS' [SS SR SC] R C SC
|
|
1 index ge { % => ... RS' [SS SR SC] R C
|
|
2 index 2 get % => ... RS' [SS SR SC] R C SC
|
|
1 add % => ... RS' [SS SR SC] R C SC+1
|
|
3 index exch
|
|
2 exch % => ... RS' [SS SR SC] R C [..] 2 SC+1
|
|
put % => ... RS' [SS SR SC+1] R C
|
|
% FIXME: reorder rowspans after this operation?
|
|
} if
|
|
} if
|
|
|
|
pop pop
|
|
exch array-prepend
|
|
} def
|
|
|
|
/table-slide-cs { % => R C Box
|
|
2 index 2 index /do-slide-cs % => R C Box {fun}
|
|
cvx 3 array astore cvx
|
|
[]
|
|
2 index table-get-colspans
|
|
reduce
|
|
|
|
1 index table-put-colspans % => R C Box
|
|
|
|
pop pop pop % =>
|
|
} def
|
|
|
|
/table-fake-cell { % => R C Box
|
|
3 copy
|
|
table-slide-cw % => R C Box
|
|
3 copy
|
|
table-slide-rs % => R C Box
|
|
3 copy
|
|
table-slide-cs % => R C Box
|
|
|
|
dup
|
|
get-table-content-rows % => R C Box Rows
|
|
dup % => R C Box Rows Rows
|
|
4 index 1 sub % => R C Box Rows Rows R(0)
|
|
dup
|
|
2 index length 1 sub gt {
|
|
pop pop pop pop pop pop
|
|
} {
|
|
get % => R C Box Rows Row
|
|
3 index 1 sub exch % => R C Box Rows C(ZeroBased) Row
|
|
box-block-create % => R C Box Rows C Row FBox
|
|
{show-fake-block-box}
|
|
1 index put-display
|
|
exch % => R C Box Rows C FBox Row
|
|
|
|
dup length 3 index lt {
|
|
3 1 roll
|
|
array-extend
|
|
} {
|
|
array-insert % => R C Box Rows Row'
|
|
} ifelse
|
|
|
|
dup length % => R C Box Rows Row' RL'
|
|
3 index get-content % => R C Box Rows Row' RL' [C R Content]
|
|
exch 0 exch % => R C Box Rows Row' [C R Content] 1 RL'
|
|
2 index 0 get max
|
|
put
|
|
|
|
4 index 1 sub % => R C Box Rows Row' R(ZeroBased)
|
|
exch % => R C Box Rows R(ZeroBased) Row'
|
|
put % => R C Box
|
|
pop pop pop % =>
|
|
} ifelse
|
|
} def
|
|
|
|
/in-normalize-rowspans { % => Size Row Col Box
|
|
3 index 1 gt {
|
|
2 index 1 add % => Size Row Col Box Row+1
|
|
2 index % => Size Row Col Box Row+1 Col
|
|
2 index
|
|
table-fake-cell % => Size Row Col Box
|
|
4 2 roll % => Col Box Size Row
|
|
1 add % => Col Box Size Row+1
|
|
4 1 roll % => Row+1 Col Box Size
|
|
1 sub % => Row+1 Col Box Size-1
|
|
4 1 roll % => Size-1 Row+1 Col Box
|
|
in-normalize-rowspans % =>
|
|
} {
|
|
pop pop pop pop % =>
|
|
} ifelse
|
|
} def
|
|
|
|
/normalize-rowspans { % => Box
|
|
dup table-get-rowspans % => Box Rowspans
|
|
{ % => Box Rowspan
|
|
aload pop % => Box Size Row Col
|
|
3 index % => Box Size Row Col Box
|
|
in-normalize-rowspans % => Box
|
|
} forall % => Box
|
|
|
|
dup get-table-content-rows % => Box Rows
|
|
length % => Box RN
|
|
|
|
1 index table-get-rowspans % => Box RN Rowspans
|
|
{ % => Box RN Rowspan
|
|
dup 1 get % => Box RN Rowspan RSR
|
|
dup % => Box RN Rowspan RSR RSR
|
|
2 index 0 get % => Box RN Rowspan RSR RSR RSS
|
|
add 1 sub % => Box RN Rowspan RSR RSR+RSS-1
|
|
3 index min % => Box RN RowSpan RSR SpanEnd
|
|
exch sub 1 add % => Box RN RowSpan SpanSize
|
|
0 exch put % => Box RN
|
|
} forall % => Box RN
|
|
|
|
pop pop % =>
|
|
} def
|
|
|
|
/normalize-table { % => Box
|
|
dup normalize-rowspans
|
|
|
|
dup get-content % => Box Content
|
|
get-children-from-content % => Box Rows
|
|
dup dup % => Box Rows Rows Rows
|
|
0 exch % => Box Rows Rows 0 Rows
|
|
{ % => Box Rows Rows 0 Row
|
|
length
|
|
max
|
|
} forall % => Box Rows Rows MaxRowLength
|
|
|
|
0 exch % => Box Rows Rows 0 MaxRowLength
|
|
3 2 roll % => Box Rows 0 MaxRowLength Rows
|
|
{ % => Box Rows RowNo MaxRowLength Row
|
|
1 index exch % => Box Rows RowNo MaxRowLength MaxRowLength Row
|
|
normalize-row % => Box Rows RowNo MaxRowLength Row'
|
|
3 index 3 index % => Box Rows RowNo MaxRowLength Row' Rows RowNo
|
|
3 2 roll % => Box Rows RowNo MaxRowLength Rows RowNo Row'
|
|
put % => Box Rows RowNo MaxRowLength
|
|
exch 1 add exch % => Box Rows RowNo+1 MaxRowLength
|
|
} forall
|
|
|
|
pop pop pop
|
|
pop
|
|
} def
|
|
|
|
/in-make-table-row { % => RowData Size
|
|
dup 0 gt {
|
|
1 index % => RowData Size RowData
|
|
aload % => RowData Size Data1 ... DataN Arr
|
|
length % => RowData Size Data1 ... DataN N
|
|
1 add % => RowData Size Data1 ... DataN N+1
|
|
[] exch % => RowData Size Data1 ... DataN [] N+1
|
|
array astore % => RowData Size NewRowData
|
|
3 2 roll pop % => Size NewRowData
|
|
exch % => NewRowData Size
|
|
1 sub % => NewRowData Size-1
|
|
in-make-table-row
|
|
} {
|
|
pop
|
|
} ifelse
|
|
} def
|
|
|
|
/make-table-row { % => Size
|
|
[] exch % => [](EmptyRow) Size
|
|
in-make-table-row
|
|
} def
|
|
|
|
/in-make-table { % => TableData Cols Rows
|
|
dup 0 gt {
|
|
2 index % => TableData Cols Rows TableData
|
|
aload % => TableData Cols Rows Data1 ... DataN TableData
|
|
length % => TableData Cols Rows Data1 ... DataN N
|
|
1 add % => TableData Cols Rows Data1 ... DataN N+1
|
|
dup 1 add index
|
|
make-table-row
|
|
exch % => TableData Cols Rows Data1 ... DataN NewRow N+1
|
|
array astore % => TableData Cols Rows NewTableData
|
|
4 3 roll pop % => Cols Rows NewTableData
|
|
3 1 roll % => NewTableData Cols Rows
|
|
1 sub % => NewTableData Cols Rows-1
|
|
in-make-table
|
|
} {
|
|
pop pop
|
|
} ifelse
|
|
} def
|
|
|
|
/make-table { % => Cols Rows
|
|
[] 3 1 roll
|
|
in-make-table
|
|
} def
|
|
|
|
/in-add-table-cell { % => Box Cell
|
|
1 index get-content % => Box Cell [Cols Rows Content](RawContent)
|
|
2 get % => Box Cell Rows
|
|
dup length 1 sub % => Box Cell Rows LastIndex
|
|
dup
|
|
2 index exch get % => Box Cell Rows LastIndex LastRow
|
|
aload length % => Box Cell Rows LastIndex Cell1 .. CellN N
|
|
dup 3 add % => Box Cell Rows LastIndex Cell1 .. CellN N N+4
|
|
index exch % => Box Cell Rows LastIndex Cell1 .. CellN Cell N
|
|
1 add
|
|
array astore % => Box Cell Rows LastIndex NewRow
|
|
dup length % => Box Cell Rows LastIndex NewRow NewRowLength
|
|
5 1 roll % => Box NewRowLength Cell Rows LastIndex NewRow
|
|
put
|
|
pop % => Box NewRowLength
|
|
1 index get-content
|
|
dup 0 get % => Box NewRowLength Content Cols
|
|
3 2 roll % => Box Content Cols NewRowLength
|
|
max
|
|
0 exch put % => Box
|
|
} def
|
|
|
|
/add-table-cell { % => Table Child
|
|
1 index is-table {
|
|
% setup parent reference in the child box
|
|
dup get-box-dict
|
|
/Parent 3 index put
|
|
% set display property
|
|
dup get-box-dict
|
|
/Display /table-cell put
|
|
|
|
% Check if any rows have been added to the table
|
|
% Add one if no rows still exists
|
|
1 index get-table-content-rows % => Rows
|
|
length 0 eq {
|
|
1 index add-table-row pop
|
|
} if
|
|
|
|
2 copy
|
|
in-add-table-cell % => Table Child Table
|
|
pop % => Table Child
|
|
|
|
% If table-cell had width constaint, propagate it to the column
|
|
dup no-width-constraint not {
|
|
dup get-width-constraint
|
|
2 index put-table-column-width-constraint
|
|
{wc-none} 1 index put-width-constraint
|
|
} if
|
|
pop
|
|
} {
|
|
% if parent is not a table, just ignore this box
|
|
pop
|
|
} ifelse
|
|
} def
|