Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
% $Header: /cvsroot/html2ps/postscript/table.ps,v 1.1 2005/12/18 07:21:38 Konstantin Exp $
2
 
3
/table-get-row-height-constraints {% => Box
4
  get-table-content-rows           % => Rows
5
  {
6
    row-get-height-constraint
7
    exch
8
    array-append
9
  }
10
  []
11
  2 index
12
  reduce                           % => Rows RHCs
13
 
14
  exch pop                         % => RHCs
15
} def
16
 
17
/put-table-column-width-constraint % => WC Box
18
{
19
  dup is-table {
20
    dup table-get-cwc-raw          % => WC Box CWC
21
    1 index get-current-column
22
    1 add                          % => WC Box CWC CC(1-based)
23
    2 index get-table-content-rows % => WC Box CWC CC Rows
24
    length                         % => WC Box CWC CC CR
25
    4 index                        % => WC Box CWC CC CR WC
26
    3 array astore                 % => WC Box CWC [CC CR WC]
27
    exch array-prepend             % => WC Box CWC'
28
    1 index table-put-cwc-raw      % => WC Box
29
  } if
30
  pop pop
31
 
32
} def
33
/table-get-cwc {                   % => Table
34
  []                              % => Table [](CWC)
35
 
36
  1 index get-current-column
37
  dup 0 ge {
38
    1 add
39
 
40
    {wc-none}
41
    array-extend
42
 
43
    1 index table-get-cwc-raw       % => Table CWC RawCWCS
44
    {                               % => Table CWC RawCWC[CC CR WC]
45
      aload pop                     % => Table CWC CC CR WC
46
 
47
% Ignore column-width constraints for colspanned columns
48
      1 index
49
      3 index
50
      6 index
51
      table-have-colspan 1 eq {
52
        exch pop                      % => Table CWC CC WC
53
        exch 1 sub exch               % => Table CWC CC(0-based) WC
54
        2 index length 2 index 1 add lt {
55
          3 1 roll {wc-none}
56
          array-extend                % => Table WC CWC'
57
          array-prepend               % => Table CWC''
58
        } {
59
          2 index
60
          3 1 roll
61
          put
62
        } ifelse
63
      } {
64
        pop pop pop
65
      } ifelse
66
    } forall
67
    exch pop
68
  } {
69
    pop pop pop []
70
  } ifelse
71
} def
72
 
73
% Get the cell-width constraint
74
% @param R row number (zero based)
75
% @param C column number (zero based)
76
% @param Table table being processed
77
% returns false if no constraint; WC function if constraint have been found
78
/table-get-cwc-raw-at {            % => R C Table
79
  []                               % => R C Table []
80
  1 index table-get-cwc-raw {      % => R C Table [] CurrentWC
81
    aload pop                      % => R C Table [] C' R' WC
82
 
83
    6 index 2 index eq
84
    6 index 4 index eq and {       % => R C Table [] C' R' WC
85
      exch pop
86
      exch pop
87
      exch array-append            % => R C Table [WC]
88
 
89
    } {
90
      pop pop pop
91
    } ifelse                       % => R C Table [WC]
92
  } forall
93
 
94
  4 1 roll
95
  pop pop pop
96
 
97
  dup length 0 gt {
98
 
99
  } {
100
    pop false
101
  } ifelse
102
} def
103
 
104
/table-get-cwc-raw {               % => Table
105
  get-content                      % => Content
106
  5 get                            % => CWC
107
} def
108
/table-put-cwc-raw {               % => CWC Table
109
  get-content                     % => CWC Content
110
  5                               % => CWC Content 5
111
  3 2 roll                        % => Content 5 CWC
112
  put                             % =>
113
} def
114
/make-table-box {                  % => W Cols Rows
115
 
116
  2 copy make-table
117
  [] []           % => W 0(H) Cols Rows [] [](ColSpans) [](RowSpans)
118
  []              % => W 0(H) Cols Rows [] [](ColSpans) [](RowSpans) [](ColumnWidthConstraints)
119
  6 array astore  % => W 0(H) [Cols Rows [] [](ColSpans) [](RowSpans)](Content)
120
 
121
  5 4 roll        % => W H 0 0 0 0 Content
122
 
123
  /show-table-box % => W H 0 0 0 0 Content 0(Baseline) DisplayFun
124
 
125
  [0 0 0 0]
126
  make-box
127
  {flow-table} 1 index put-flow-fun
128
% Mark box as table
129
  dup get-box-dict
130
  /Display /table put
131
} def
132
/make-default-table-box {          % => W
133
 
134
  dup get-box-dict
135
  /Width get
136
  /Auto false put
137
} def
138
 
139
% PREDICATES
140
/is-constrained-column {           % => WC
141
 
142
} def                              % => Flag
143
 
144
% ROW-RELATED
145
/table-fit-row {                   % => R Row Box ColsWidth
146
% Get total height of current row
147
  3 2 roll                        % => R Box ColsWidth Row
148
 
149
  2 index
150
% table-row-height accepts 1-based row indices
151
  4 index 1 add
152
  2 index
153
  table-row-height                % => R Box ColsWidth Row RH
154
 
155
% Get current Y coordinate (indicated the bottom edge of current row)
156
  dup 2 div
157
  4 index get-current-y
158
% Calculate middle Y coordinate of this row
159
  exch sub                        % => R Box ColsWidth Row RH Middle
160
 
161
% Row baseline information
162
  2 index get-row-baseline        % => R Box ColsWidth Row RH Middle RBaseline
163
  exch
164
  4 3 roll                        % => R Box ColsWidth RH RBaseline Middle Row
165
 
166
  {                               % => R Box ColsWidth RH RBaseline Middle Cell
167
    4 copy
168
    apply-valign                  % => R Box ColsWidth RH RBaseline Middle Cell
169
 
170
% extend cell height to fit the row vertically
171
    1 index                       % => R Box ColsWidth RH RBaseline Middle Cell Middle
172
    6 index get-current-y         % => R Box ColsWidth RH RBaseline Middle Cell Middle CY
173
 
174
    exch sub                      % => R Box ColsWidth RH RBaseline Middle Cell H/2
175
    2 mul                         % => R Box ColsWidth RH RBaseline Middle Cell H
176
    dup 2 index
177
    get-full-height               % => R Box ColsWidth RH RBaseline Middle Cell H H CellH
178
    gt {                          % => R Box ColsWidth RH RBaseline Middle Cell H
179
      2 copy exch
180
      put-full-height             % => R Box ColsWidth RH RBaseline Middle Cell H
181
    } if
182
% align the top edge of extended cell with the row top edge
183
    2 div 2 index exch
184
    add                           % => R Box ColsWidth RH RBaseline Middle Cell TY
185
    1 index put-top
186
    pop
187
  } forall                        % => R Box ColsWidth RH RBaseline Middle
188
 
189
  pop pop pop pop pop pop         % =>
190
} def
191
/table-row-height {                % => Box R Row
192
  1 exch                           % => Box R 1(C) Row
193
 
194
  {                                % => Box R C H Cell
195
    3 index
196
    3 index                        % => Box R C H Cell R C
197
    6 index                        % => Box R C H Cell R C Box
198
    table-have-rowspan             % => Box R C H Cell Span
199
    1 le {
200
      get-full-height
201
      max                         % => Box R C H
202
    } {
203
      pop
204
    } ifelse                      % => Box R C H
205
    exch 1 add exch               % => Box R C+1 H
206
  } forall                        % => Box R C+1 H
207
  4 1 roll
208
  pop pop pop                     % => H
209
} def
210
/in-table-resize-rows {            % => Box R OY RHs Rows
211
  dup length 0 gt {            % => Box R OY RHs Rows
212
    1 index 0 get              % => Box R OY RHs Rows H
213
 
214
    1 index 0 get              % => Box R OY RHs Rows H Row
215
    5 index                    % => Box R OY RHs Rows H Row R
216
    7 index                    % => Box R OY RHs Rows H Row R Box
217
    exch                       % => Box R OY RHs Rows H Row Box R
218
    3 2 roll                   % => Box R OY RHs Rows H Box R Row
219
    table-row-height           % => Box R OY RHs Rows H OldH
220
    7 1 roll                   % => OldH Box R OY RHs Rows H
221
 
222
    1 index 0 get              % => OldH Box R OY RHs Rows H Row
223
 
224
    dup get-row-baseline
225
    exch                       % => OldH Box R OY RHs Rows H RowBaseLine Row
226
 
227
    {                          % => OldH Box R OY RHs Rows H RowBaseLine Cell
228
% align top edge of the expanded cell and the top edge of row
229
% note that table content already have vertical alignment, so it should not
230
% be affected by this action
231
      dup get-left             % => OldH Box R OY RHs Rows H RowBaseLine Cell X
232
      8 index get-top-internal
233
      7 index sub              % => OldH Box R OY RHs Rows H RowBaseLine Cell X Y
234
      2 index
235
      move-to-box              % => OldH Box R OY RHs Rows H RowBaseLine Cell
236
 
237
% re-try to vertical align the cell contents using new row height
238
      1 index                  % => OldH Box R OY RHs Rows H RowBaseLine Cell RowBaseline
239
      8 index get-top
240
      7 index sub
241
      4 index 2 div
242
      sub                      % => OldH Box R OY RHs Rows H RowBaseLine Cell Baseline Middle
243
      2 index                  % => OldH Box R OY RHs Rows H RowBaseLine Cell Baseline Middle Cell
244
      5 index 4 1 roll         % => OldH Box R OY RHs Rows H RowBaseLine Cell H Baseline Middle Cell
245
 
246
      apply-valign             % => OldH Box R OY RHs Rows H RowBaseLine Cell
247
 
248
% expand cell to the row height
249
      2 index
250
      1 index                  % => OldH Box R OY RHs Rows H RowBaseLine Cell H Cell
251
      put-full-height          % => OldH Box R OY RHs Rows H RowBaseLine Cell
252
 
253
      pop
254
    } forall                   % => OldH Box R OY RHs Rows H RowBaseLine
255
    pop                        % => OldH Box R OY RHs Rows H
256
 
257
% Calculate new offset from the table top (old offset+current row height)
258
    7 6 roll                   % => Box R OY RHs Rows H OldH
259
    pop                        % => Box R OY RHs Rows H
260
    4 3 roll                   % => Box R RHs Rows H OY
261
    add                        % => Box R RHs Rows OY'
262
% remove processed element for row array
263
    3 1 roll                   % => Box R OY' RHs Rows
264
    array-pop-first            % => Box R OY RHs Rows'
265
% remove processed element for row heights array
266
    4 1 roll
267
    array-pop-first            % => Box Rows' R OY RHs'
268
% increase row index
269
    4 2 roll
270
    1 add                      % => Box OY RHs' Rows' R+1
271
% process next row recusively
272
    4 1 roll                   % => Box R+1 OY RHs' Rows'
273
 
274
    in-table-resize-rows
275
  } if
276
} def
277
/table-resize-rows {               % => Box RHs
278
  dup sum                      % => Box RHs FH
279
  2 index put-height           % => Box RHs
280
  1 exch                       % => Box 1(R) RHs
281
 
282
  3 index
283
  get-table-content-rows       % => Box 1(R) 0(Ofs) RHs Rows
284
  in-table-resize-rows         % => Box 1(R) OY [] []
285
  pop pop pop pop pop
286
} def
287
/table-rows-heights {              % => Box
288
  dup get-table-content-rows   % => Box Rows
289
  [] exch                      % => Box [](Heights) Rows
290
  1 exch                       % => Box [](Heights) 1(R) Rows
291
  {                            % => Box Heights R Row
292
    1 index exch               % => Box Heights R R Row
293
    4 index 3 1 roll           % => Box Heights R Box R Row
294
    table-row-height           % => Box Heights R H
295
    2 index array-prepend      % => Box Heights R Heights'
296
    3 1 roll                   % => Box Heights' Heights R
297
    exch pop                   % => Box Heights R
298
    1 add                      % => Box Heights R+1
299
  } forall                     % => Box Heights R
300
  pop
301
  exch pop                     % => Heights
302
} def
303
 
304
% Modify minimal column width using column span information
305
/get-max-width-table-column {      % => Box C Column
306
  1 exch
307
 
308
    2 index                        % => Box C 1(R) 0(ColumnMinWidth) ColumnElement R
309
    4 index                        % => Box C 1(R) 0(ColumnMinWidth) ColumnElement R C
310
    6 index
311
    table-have-colspan 1 gt {      % => Box C R Width Element
312
      pop                          % => Box C R Width
313
    } {
314
      get-max-width                % => Box C R Width CWidth
315
      max                          % => Box C R Width'
316
    } ifelse
317
    exch 1 add exch                % => Box C R+1 Width'
318
  } forall                         % => Box C RL Width'
319
 
320
  exch pop                         % => Box C Width'
321
  2 index get-hor-extra
322
  sub
323
 
324
  3 1 roll pop pop                 % => Width
325
} def
326
/get-min-width-table-column {      % => Box C Column
327
  1 exch
328
 
329
    2 index                        % => Box C 1(R) 0(ColumnMinWidth) ColumnElement R
330
    4 index                        % => Box C 1(R) 0(ColumnMinWidth) ColumnElement R C
331
    6 index                        % => Box C 1(R) 0(ColumnMinWidth) ColumnElement R C Box
332
 
333
    table-have-colspan 1 gt {      % => Box C R Width Element
334
      pop                          % => Box C R Width
335
    } {
336
%      dup get-td-dict
337
%      /NoWrap get {
338
%        dup get-max-width
339
%        1 index get-min-width
340
%        max exch pop
341
%      } {
342
        get-min-width              % => Box C R Width CWidth
343
%      } ifelse
344
      max                          % => Box C R Width'
345
    } ifelse
346
    exch 1 add exch                % => Box C R+1 Width'
347
  } forall                         % => Box C RL Width'
348
 
349
  exch pop                         % => Box C Width'
350
  2 index get-hor-extra
351
  sub
352
 
353
  3 1 roll pop pop                 % => Width
354
} def
355
/get-table-columns-min-widths {    % => Box
356
  dup get-table-content-columns    % => Box ColumnsList
357
  1 exch
358
  [] exch                          % => Box 1(C) [] ColumnsList
359
  {                                % => Box C [](Widths) Column
360
    3 index                        % => Box C Widths Column Box
361
    3 index                        % => Box C Widths Column Box C
362
    3 2 roll                       % => Box C Widths Box C Column
363
 
364
    get-min-width-table-column     % => Box C Widths ColW
365
    exch array-prepend             % => Box C Widths
366
 
367
    exch 1 add exch                % => Box C+1 TotalMinWidth
368
  } forall                         % => Box C MinWidth
369
  exch pop                         % => Box MinWidths
370
  exch pop                         % => MinWidths
371
} def
372
/get-table-columns-max-widths {    % => Box
373
  dup get-table-content-columns    % => Box ColumnsList
374
  1 exch
375
  [] exch                          % => Box 1(C) [] ColumnsList
376
  {                                % => Box C [](Widths) Column
377
    3 index                        % => Box C Widths Column Box
378
    3 index                        % => Box C Widths Column Box C
379
    3 2 roll                       % => Box C Widths Box C Column
380
 
381
    get-max-width-table-column     % => Box C Widths ColW
382
    exch array-prepend             % => Box C Widths
383
 
384
    exch 1 add exch                % => Box C+1 TotalMinWidth
385
  } forall                         % => Box C MaxWidth
386
  exch pop                         % => Box MaxWidths
387
 
388
  % Use column width constraints - column should not be wider its constrained width
389
  1 index get-width                % => Box MaxWidths BW
390
  2 index table-normalize-cwc      % => Box MaxWidths BW CWCs
391
  2 index                          % => Box MaxWidths BW CWCs MaxWidths
392
  { 1 index is-fraction
393
    {
394
      6 index false 3 index exec 3 1 roll pop pop
395
    }
396
    { exch false exch exec } ifelse }
397
  zip-with
398
  exch pop exch pop                % => Box MaxWidhts
399
 
400
  exch pop                         % => MinWidths
401
} def
402
 
403
/table-apply-colspans-minw {       % => Flags Widths Fun Box
404
  dup table-get-colspans           % => Flags Widths Fun Box Colspans
405
  {                                % => Flags Widths Fun Box Colspan[Size R C]
406
    dup 0 get                      % => Flags Widths Fun Box Colspan[Size R C] Size
407
    1 index 1 get                  % => Flags Widths Fun Box Colspan[Size R C] Size R
408
    2 index 2 get                  % => Flags Widths Fun Box Colspan[Size R C] Size R C
409
% Calculate colspanned cell width (using appropriate function passed in the stack when
410
% calling this function)
411
    4 index                        % => Flags Widths Fun Box Colspan[Size R C] Size R C Box
412
    table-get-cell-content         % => Flags Widths Fun Box Colspan[Size R C] Size Cell
413
    4 index exec                   % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth
414
% apply cell width constraint, if any
415
    2 index aload pop
416
    3 2 roll pop                   % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth R C
417
    5 index table-get-cwc-raw-at   % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth WC
418
    dup false ne {
419
      dup is-fraction {
420
        4 index no-width-constraint not {
421
          4 index get-width exch
422
          false exch exec
423
          max
424
        } {
425
          pop
426
        } ifelse
427
      } {
428
        false exch exec
429
      } ifelse
430
    } {
431
      pop
432
    } ifelse                       % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth'
433
% now select the pre-calculated widths of columns covered by this cell
434
    2 index 2 get                % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth C
435
    1 sub                        % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth C(ZeroBased)
436
    3 2 roll                     % => Flags Widths Fun Box Colspan[Size R C] CellWidth C(ZeroBased) Size
437
    1 index                      % => Flags Widths Fun Box Colspan[Size R C] CellWidth C Size C
438
    exch                         % => Flags Widths Fun Box Colspan[Size R C] CellWidth C C Size
439
    7 index                      % => Flags Widths Fun Box Colspan[Size R C] CellWidth C C Size Widths
440
    3 1 roll                     % => Flags Widths Fun Box Colspan[Size R C] CellWidth C Widths C Size
441
    getinterval                  % => Flags Widths Fun Box Colspan[Size R C] CellWidth C SWidths
442
% select the list of resizable columns covered by this cell
443
    3 2 roll exch                % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths
444
    7 index                      % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths Flags
445
    3 index                      % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths Flags C
446
    5 index 0 get                % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths Flags C Size
447
    getinterval                  % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths SFlags
448
% Subtract sum width of non-resizable columns this cell spans over from the cell width
449
% Non-resizable columns are marked as 'false' in SFlags
450
    2 copy {
451
      { pop 0 } if
452
    } zip-with sum               % => Flags Widths Fun Box Colspan[Size R C] C CellWidth SWidths SFlags Non-resizable-width
453
    4 3 roll
454
    exch sub
455
% do not allow target width drop below zero
456
 
457
    3 1 roll
458
% Expand resizable columns to
459
    expand-to-with-flags         % => Flags Widths Fun Box Colspan[Size R C] C SWidths'
460
% store modified widths
461
    5 index                      % => Flags Widths Fun Box Colspan[Size R C] C SWidths' Widths
462
    3 1 roll                     % => Flags Widths Fun Box Colspan[Size R C] Widths C SWidths'
463
    putinterval                  % => Flags Widths' Fun Box Colspan[Size R C]
464
    pop                          % => Flags Widths' Fun Box
465
  } forall                       % => Flags Widths' Fun Box
466
  pop pop                        % => Widths'
467
  exch pop
468
} def
469
 
470
/table-apply-colspans {            % => Widths Fun Box
471
  dup table-get-colspans           % => Widths Fun Box Colspans
472
% Scan all cell spanning several columns
473
  {                                % => Widths Fun Box Colspan[Size R C]
474
% Get current colspan contents
475
    dup 0 get                      % => Widths Fun Box Colspan[Size R C] Size
476
    1 index 1 get                  % => Widths Fun Box Colspan[Size R C] Size R
477
    2 index 2 get                  % => Widths Fun Box Colspan[Size R C] Size R C
478
    4 index                        % => Widths Fun Box Colspan[Size R C] Size R C Box
479
    table-get-cell-content         % => Widths Fun Box Colspan[Size R C] Size Cell
480
% Calculate its width (by calling the appropriate function passed; usually it will be
481
% get-min-width or get-max-width)
482
    4 index exec                   % => Widths Fun Box Colspan[Size R C] Size CellWidth
483
% apply cell width constraint, if any
484
    2 index aload pop
485
    3 2 roll pop                   % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth R C
486
    5 index table-get-cwc-raw-at   % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth WC
487
    dup false ne {
488
      dup is-fraction {
489
        4 index no-width-constraint not {
490
          4 index get-width exch
491
          false exch exec
492
          max
493
        } {
494
          pop
495
        } ifelse
496
      } {
497
        false exch exec
498
      } ifelse
499
    } {
500
      pop
501
    } ifelse                       % => Flags Widths Fun Box Colspan[Size R C] Size CellWidth'
502
% Get the width list of columns covered by current column span
503
    2 index 2 get                  % => Widths Fun Box Colspan[Size R C] Size CellWidth C
504
    1 sub                          % => Widths Fun Box Colspan[Size R C] Size CellWidth C(ZeroBased)
505
    3 2 roll                       % => Widths Fun Box Colspan[Size R C] CellWidth C(ZeroBased) Size
506
    1 index                        % => Widths Fun Box Colspan[Size R C] CellWidth C Size C
507
    exch                           % => Widths Fun Box Colspan[Size R C] CellWidth C C Size
508
    7 index                        % => Widths Fun Box Colspan[Size R C] CellWidth C C Size Widths
509
    3 1 roll                       % => Widths Fun Box Colspan[Size R C] CellWidth C Widths C Size
510
    getinterval                    % => Widths Fun Box Colspan[Size R C] CellWidth C SWidths
511
% expand these columns to fit spanned data
512
    3 2 roll exch                  % => Widths Fun Box Colspan[Size R C] C CellWidth SWidths
513
    expand-to                      % => Widths Fun Box Colspan[Size R C] C SWidths'
514
% Store changed widths
515
    5 index                        % => Widths Fun Box Colspan[Size R C] C SWidths' Widths
516
    3 1 roll                       % => Widths Fun Box Colspan[Size R C] Widths C SWidths'
517
    putinterval                    % => Widths' Fun Box Colspan[Size R C]
518
    pop                            % => Widths' Fun Box
519
  } forall                         % => Widths' Fun Box
520
  pop pop                          % => Widths'
521
} def
522
/table-column-widths {             % => Box
523
  dup get-width                    % => Box Width
524
  table-columns-fit
525
} def
526
/table-columns-fit {               % => Box Widht
527
% Check if there's any columns in table
528
  1 index get-table-content-columns
529
  length 0 gt {
530
    in-table-columns-fit
531
  } {
532
    pop pop []
533
  } ifelse
534
} def
535
 
536
% columns-fit helper function
537
/fit-cwidth {                      % => MW MCW TW-TCW TMCW-TMW
538
  2 index
539
  4 index
540
  sub                             % => MW MCW TW-TCW TMCW-TMW MCW-MW
541
  exch div                        % => MW MCW TW-TCW MCW-MW/TMCW-TMW
542
  mul
543
  add
544
% to avoid problems with negative cell widths
545
 
546
  exch pop
547
} def
548
/in-table-columns-fit {            % => Box Width
549
  1 index
550
  get-table-content-columns       % => Box Width Columns
551
 
552
  2 index                         % => Box Width Columns Box
553
  get-table-columns-min-widths    % => Box Width Columns MinWidths
554
 
555
  3 index
556
  get-table-columns-max-widths    % => Box Width Columns MinWidths MaxWidths
557
 
558
  1 index
559
  { max }
560
  zip-with
561
 
562
% Use data on the spanned cells
563
%  exch                            % => Box Width Columns MaxWidths MinWidths
564
%  2 copy { ne } zip-with          % => Box Width Columns MaxWidths MaxWidths [MaxWidthsCi<>MinWidthsCi]
565
%  exch                            % => Box Width Columns MaxWidths ResizableFlags MinWidths
566
 
567
%  { get-min-width } 6 index       % => Box Width Columns ManWidths ResizableFlags MinWidths Fun Box
568
%  table-apply-colspans-minw       % => Box Width Columns MaxWidths MinWidth
569
%  exch                            % => Box Width Columns MinWidth  MaxWidths
570
%  { get-max-width } 5 index       % => Box Width Columns MinWidth  MaxWidths Fun Box
571
%  table-apply-colspans            % => Box Width Columns MinWidth  MaxWidths
572
 
573
  3 2 roll
574
  pop                             % => Box Width MinWidths MaxWidths
575
 
576
% Apply column width constraints to minimum widths
577
  2 index                         % => Box Width MinWidths MaxWidths BW
578
  4 index table-normalize-cwc     % => Box Width MinWidths MaxWidths BW CWCs
579
  3 index                         % => Box Width MinWidths MaxWidths BW CWCs MinWidths
580
  { 1 index is-fraction
581
    {
582
      6 index false 3 index exec 3 1 roll pop pop
583
    }
584
    { exch false exch exec } ifelse }
585
  zip-with
586
  exch pop
587
 
588
% Apply column width constraints to maximum widths
589
  3 index                         % => Box Width MinWidths MaxWidths MinWidthsC BW
590
  5 index table-normalize-cwc     % => Box Width MinWidths MaxWidths MinWidthsC BW CWCs
591
  3 index                         % => Box Width MinWidths MaxWidths MinWidthsC BW CWCs maxWidth
592
  { 1 index is-fraction
593
    {
594
      % 6 index = BW
595
      6 index false 3 index exec 3 1 roll pop pop
596
    }
597
    { exch false exch exec } ifelse }
598
  zip-with
599
  exch pop                         % => ox Width MinWidths MaxWidths MinWidthsC MaxWidths
600
 
601
% Do not allow constrained max width be less than min width
602
  3 index
603
  { max }
604
  zip-with                        % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC
605
 
606
% Do not allow constrained min width be less than min width
607
  3 index
608
  2 index
609
  { max }
610
  zip-with                        % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC W'
611
 
612
  3 2 roll                        % => Box Width MinWidths MaxWidths MaxWidthsC W' MinWidthsC
613
  pop                             % => Box Width MinWidths MaxWidths MaxWidthsC W'
614
  exch                            % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC
615
 
616
% Check if sum of constrained widths is too big
617
% Note that we compare sum of constrained width with the MAXIMAL value of table width and
618
% sum of uncostrained minimal width; it will prevent from unneeded collapsing of table cells
619
% if table content will expand its width anyway
620
  1 index sum                      % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC SUM(MinWidthsC')
621
% find the "template" value
622
  5 index
623
  5 index sum
624
  max
625
% compare
626
  gt {
627
% now we should scale columns to fit table width
628
    1 index sum
629
% find template value
630
    5 index
631
    5 index sum
632
    max
633
 
634
% Calculate the amount if difference between minimal and constrained minimal width for each columns
635
    exch sub                      % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC
636
    4 index                       % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC MinWidth
637
    3 index                       % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC MinWidth MinWidthC
638
    {exch sub} zip-with sum       % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC CWDelta
639
    dup 0 gt {
640
      5 index                     % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC CWDelta MinW
641
      4 index                     % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC Width-MinWC CWDelta MinW MinWC
642
      4 2 roll                    % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC MinW MinWC Width-MinWC CWDelta
643
      /fit-cwidth cvx             % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC MinW MinWC Width-MinWC CWDelta cit-cwidth
644
      3 array astore cvx          % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC MinW MinWC {Width-MinWC CWDelta cit-cwidth}
645
      zip-with                    % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC MinWC'
646
      exch 3 2 roll pop           % => Box Width MinWidths MaxWidths MinWC'     MaxWidthsC
647
    } {
648
% if no difference is found, we can collapse no columns
649
      pop pop                     % => Box Width MinWidths MaxWidths MinWidthsC MaxWidthsC
650
    } ifelse
651
  } if
652
 
653
% Use data on the spanned cells (again)
654
  exch                            % => Box Width MinWidths MaxWidths MaxWidthsC MinWidthsC
655
  2 copy { ne } zip-with          % => Box Width MinWidths MaxWidths MaxWidthsC MinWidthsC [MaxWidthsCi<>MinWidthsCi]
656
  exch                            % => Box Width MinWidths MaxWidths MaxWidthsC ResizableFlags MinWidthsC
657
 
658
  { get-min-width } 7 index       % => Box Width MinWidths MaxWidths MaxWidthsC ResizableFlags MinWidthsC Fun Box
659
  table-apply-colspans-minw       % => Box Width MinWidths MaxWidths MaxWidthsC MinWidthC
660
  exch                            % => Box Width MinWidths MaxWidths MinWidthC  MaxWidthsC
661
  { get-max-width } 6 index       % => Box Width MinWidths MaxWidths MinWidthC  MaxWidthsC Fun Box
662
  table-apply-colspans            % => Box Width MinWidths MaxWidths MinWidthC  MaxWidthsC
663
 
664
% Calculate actual widths
665
% Prepare width array
666
  []
667
  1 index length 0
668
  array-extend                    % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths
669
 
670
% First pass - calculate widths for all constrained columns
671
  6 index table-normalize-cwc     % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs
672
 
673
 
674
    2 copy get
675
    is-constrained-column {
676
      2 index
677
      1 index
678
      6 index 3 index get
679
      put
680
    } if
681
 
682
    pop
683
  } for
684
 
685
% Quick fix for overconstrained tables: if table have width attribute AND its value is less than sum
686
% of constrained columns widths plus minimal widths of uncostrained columns, then we'll expand the width of table
687
% to fit all columns
688
% 1. calculate sum of constrained column widths
689
  1 index sum                     % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs SumConW
690
% 2. calculate sum of unconstrained column minimal widths
691
  2 index
692
  7 index
693
  { 1 index 0 gt { pop pop 0 } { exch pop } ifelse }
694
  zip-with sum                    % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs SumConW SumUnconW
695
% 3. compare these widths with the table width
696
  add
697
  dup 8 index gt {                % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs SumConW+SumUnconW
698
    8 7 roll pop
699
    7 1 roll
700
  } {
701
    pop
702
  } ifelse
703
 
704
% Second pass - distribute the rest of the width
705
 
706
% Explanation of the stuff below (I've really had problems with this small piece of code, especially
707
% when I was trying to fix "bugs" inside it)
708
%
709
% First of all, no column can be narrower than it minimal width (determined by its content)
710
% Note that constrained columns have their widths distributed above, so we can exclude them for now
711
% (just throw them out and imagine that table does not contain any width-constrained cols)
712
%
713
% Second, the relative widths of columns will have _appoximately_ the same ratio as
714
% their maximal content widths. (In exception of cases where the first rule will take place -
715
% say for the table containing two columns with the VERY long text in the first and one or two words
716
% in the second)
717
%
718
% In general, this approach can be inoptimal in case of _very_ different font sizes
719
% inside the cells, of, say big images; nevertheless, it will give a good approximate
720
% AND still fast enough (unlike fully correct methods involving evaluation of the content height of the cell)
721
%
722
% Thus, we do the following:
723
% - calculate the ratio of current column MAXIMAL ($current_max) width to the sum of MAXIMAL widths of all columns left
724
%   (inluding current) second rule applied. Note that we need remember about column spans and select
725
%   maxw or maxwc in order.
726
% - then check if the rest of width will be too small for other columns to fit and decrease current columns
727
%   width (see MIN function call)
728
% - then check again if our width will be too small for current column to fit (and expand if nesessary) -
729
%   MAX function call
730
 
731
 
732
    2 copy get
733
% Process only uncostrained columns
734
    is-constrained-column not {
735
      2 index
736
      1 index                      % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I
737
% Get undistibuted width (total table width - width of constrained columns)
738
      9 index                      % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I Width
739
      2 index sum sub              % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest
740
% Get max width of column being processed
741
      8 index 2 index get          % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW
742
      7 index 3 index get max      % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW
743
% If width is equal to zero, use max constrained width, as this column could be covered by colspan;
744
% If not, we lose nothing, because all constrained columns are already processed earlier, and no more
745
% columns except these two types can have different constrained and raw widths
746
      dup 0 eq {
747
        pop
748
        6 index 2 index get
749
      } if
750
% Get sum of maximal constrained widths of unplaced columns
751
      3 index                     % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW Widths
752
      8 index                     % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW Widths MaxWidthsC
753
      { 1 index 0 eq {exch pop} {pop pop 0} ifelse }
754
      zip-with
755
      sum                          % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MW MWR
756
% Get sum of minimal constrained widths of unplaced columns
757
      4 index                      % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW MaxWR Widths
758
      10 index                     % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW MaxWR Widths MaxWidthsC
759
      { 1 index 0 eq {exch pop} {pop pop 0} ifelse }
760
      zip-with
761
      sum                          % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW MaxWR MinWR
762
      3 index exch sub             % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest MaxW MaxWR WidthRest-MinWR
763
% add current columns min width
764
      12 index 5 index get
765
      11 index 6 index get max
766
      add
767
      4 1 roll                     % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest-MinWR WidthRest MaxW MaxWR
768
% If some unplaced columns have maximal (constrained width) greater zero
769
      dup 0 gt {
770
% Calculate the appropriate fraction of free table width for the current column
771
        div                        % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest-MinWR WidthRest MinWE MaxW MaxWR
772
        mul                        % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I WidthRest-MinWR W(WidthRest*MW/MWR)
773
        min
774
% Remove minimal width of current column;
775
%        9 index 2 index get
776
%        sub
777
% This will make calculated width not less than raw minimal column with. See also line marked with (*)
778
%        0 max
779
      } {
780
        pop pop pop pop 0
781
      } ifelse
782
% (*) Add the minimal width of current column
783
      9 index 2 index get
784
      dup 0 eq {
785
        pop
786
        7 index 2 index get
787
      } if
788
      max                          % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths CWCs I Widths I W
789
 
790
      put
791
    } if
792
 
793
    pop
794
  } for
795
  pop                             % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths
796
 
797
% in case of overconstrained table (e.g. two columns with 20% widths), expand them
798
  dup sum                         % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths SumWidth
799
  dup 0 gt {
800
    6 index
801
    exch div
802
    dup 1 gt {
803
      map-scale
804
    } { pop } ifelse
805
  } {
806
    pop
807
  } ifelse                        % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths
808
 
809
% now - the last attempt; if total width is less than box width, just expand the very first column to fit
810
  dup sum 6 index lt {
811
    dup sum                         % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths SumWidth
812
    6 index
813
    exch sub                        % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths Delta
814
    1 index 0 get                   % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths Delta W0
815
    add                             % => Box Width MinWidths MaxWidths MinWidthsC' MaxWidthsC Widths W0'
816
    1 index exch
817
 
818
  } if
819
 
820
  7 1 roll
821
  pop pop pop
822
  pop pop pop
823
} def
824
 
825
% Modify heights of table cells spanning several rows
826
/table-fit-rowspans {              % => Table
827
  dup table-rows-heights          % => Table RHs
828
  1 index table-get-rowspans      % => Table RHs RS
829
% scan all cells spanning several rows
830
  {                               % => Table RHs RowSpan
831
% calculate the bottom edge of current cell
832
    aload pop                     % => Box RHs Span R C
833
    2 copy                        % => Box RHs Span R C R C
834
    6 index                       % => Box RHs Span R C R C Box
835
    table-get-cell-content        % => Box RHs Span R C Cell
836
    {
837
      get-bottom
838
      min
839
    }
840
    1 index get-top
841
    2 index get-content
842
    reduce
843
% reset the height of the cell to its content height (as it have been probably fitted to the top row spanned-over)
844
    1 index get-top
845
    sub neg
846
    1 index put-height
847
 
848
% now check if cell height is less than sum spanned rows height
849
    dup get-full-height           % => Box RHs Span R C Cell CellFH
850
    5 index                       % => Box RHs Span R C Cell CellFH RHs
851
    4 index 1 sub                 % => Box RHs Span R C Cell CellFH RHs R
852
    6 index                       % => Box RHs Span R C Cell CellFH RHs R Span
853
    getinterval sum               % => Box RHs Span R C Cell CellFH RowH
854
 
855
    2 copy lt {
856
% vertical-align current cell
857
% calculate (approximate) row baseline
858
      6 index                     % => Box RHs Span R C Cell CellFH RowH RHs
859
 
860
      getinterval sum neg         % => Box RHs Span R C Cell CellFH RowH -SpannedRHs
861
      8 index get-top-internal
862
      add                         % => Box RHs Span R C Cell CellFH RowH RBaseline
863
% calculate row middle coordinate
864
      dup 2 index 2 div sub       % => Box RHs Span R C Cell CellFH RowH RBaseline Middle
865
 
866
      2 index
867
      2 index
868
      2 index
869
      7 index
870
 
871
      apply-valign
872
 
873
      pop pop
874
 
875
% Make cell fill all available vertical space
876
      dup                         % => Box RHs Span R C Cell CellFH RowH RowH
877
      3 index
878
      put-full-height             % => Box RHs Span R C Cell CellFH RowH
879
 
880
      pop pop pop
881
    } {
882
      pop pop pop
883
    } ifelse                      % => Box RHs Span R C
884
    pop pop pop
885
  } forall
886
  pop pop
887
} def
888
 
889
/table-have-colspan { % => Row Col Table
890
  table-get-colspans
891
  1                   % => Row Col Spans 1
892
  exch                % => Row Col 1 Spans
893
  {                   % => Row Col CS Span
894
    dup 1 get         % => Row Col CS Span Row
895
    1 index 2 get     % => Row Col CS Span Row Col
896
    4 index eq        % => Row Col CS Span Row CEq
897
    exch              % => Row Col CS Span CEq Row
898
    5 index eq        % => Row Col CS Span CEq REq
899
    and               % => Row Col CS Span Match
900
    {
901
 
902
    } {
903
      pop
904
    } ifelse
905
  } forall            % => Row Col CS
906
  3 1 roll            % => CS Row Col
907
  pop pop             % => CS
908
} def
909
 
910
/table-have-rowspan { % => Row Col Table
911
  table-get-rowspans
912
  1                   % => Row Col Spans 1
913
  exch                % => Row Col 1 Spans
914
  {                   % => Row Col CS Span
915
    dup 1 get         % => Row Col CS Span Row
916
    1 index 2 get     % => Row Col CS Span Row Col
917
    4 index eq        % => Row Col CS Span Row CEq
918
    exch              % => Row Col CS Span CEq Row
919
    5 index eq        % => Row Col CS Span CEq REq
920
    and               % => Row Col CS Span Match
921
    {
922
 
923
    } {
924
      pop
925
    } ifelse
926
  } forall            % => Row Col CS
927
  3 1 roll            % => CS Row Col
928
  pop pop             % => CS
929
} def
930
 
931
/table-mark-rowspan {    % => Table SpanSize
932
  1 index
933
  get-table-content-rows % => Table SpanSize Rows
934
  dup length             % => Table SpanSize Rows CurRow
935
  1 index array-last     % => Table SpanSize Rows CurRow LastRow
936
  length                 % => Table SpanSize Rows CurRow CurColumn
937
  3 2 roll pop           % => Table SpanSize CurRow CurColumn
938
  3 index                % => Table SpanSize CurRow CurColumn Table
939
  table-add-rowspan      % => Table
940
} def
941
 
942
/table-mark-colspan {    % => Table SpanSize
943
  1 index
944
  get-table-content-rows % => Table SpanSize Rows
945
  dup length             % => Table SpanSize Rows CurRow
946
  1 index array-last     % => Table SpanSize Rows CurRow LastRow
947
  length                 % => Table SpanSize Rows CurRow CurColumn
948
  3 2 roll pop           % => Table SpanSize CurRow CurColumn
949
  3 index                % => Table SpanSize CurRow CurColumn Table
950
  table-add-colspan      % => Table
951
} def
952
 
953
/normalize-row {                   % => Length Row
954
  aload length   % => Length R1 .. RN N
955
  dup            % => Length R1 .. RN N N
956
  dup 2 add      % => Length R1 .. RN N N N+2
957
  index          % => Length R1 .. RN N N Length
958
  exch sub dup   % => Length R1 .. RN N Delta Delta
959
  replicate-row  % => Length R1 .. RN N []..[] Delta 0
960
  pop            % => Length R1 .. RN N []..[] Delta
961
  dup 2 add      % => Length R1 .. RN N []..[] Delta Delta+2
962
  dup 1 sub      % => Length R1 .. RN N []..[] Delta Delta+2 Delta+1
963
  roll           % => Length R1 .. RN []..[] Delta N
964
  add            % => Length R1 .. RN []..[] Delta+N
965
  array astore   % => Length Row'
966
  exch pop       % => Row'
967
} def
968
 
969
/table-slide-cw {                  % => R C Box
970
  dup table-get-cwc-raw            % => R C Box RawCWCS
971
  {                                % => R C Box RawCWC
972
    aload                          % => R C Box !C !R WC [!C !R WC]
973
    2 index 7 index eq {
974
      3 index 6 index ge {
975
        dup
976
 
977
      } if
978
    } if                           % => R C Box !C !R WC [!C !R WC]
979
    pop pop pop pop
980
  } forall
981
 
982
  pop pop pop
983
} def
984
 
985
/do-slide-rs {                     % => ... RS' [SS SR SC] R C
986
  2 index 1 get                   % => ... RS' [SS SR SC] R C SR
987
  2 index eq {                    % => ... RS' [SS SR SC] R C
988
    2 index 2 get                 % => ... RS' [SS SR SC] R C SC
989
    1 index ge {                  % => ... RS' [SS SR SC] R C
990
      2 index 2 get               % => ... RS' [SS SR SC] R C SC
991
      1 add                       % => ... RS' [SS SR SC] R C SC+1
992
      3 index exch
993
      2 exch                      % => ... RS' [SS SR SC] R C [..] 2 SC+1
994
      put                         % => ... RS' [SS SR SC+1] R C
995
% FIXME: reorder rowspans after this operation?
996
    } if
997
  } if
998
 
999
  pop pop
1000
  exch array-prepend
1001
} def
1002
 
1003
/table-slide-rs {                  % => R C Box
1004
  2 index 2 index /do-slide-rs    % => R C Box {fun}
1005
  cvx 3 array astore cvx
1006
  []
1007
  2 index table-get-rowspans
1008
  reduce
1009
 
1010
  1 index table-put-rowspans      % => R C Box
1011
 
1012
  pop pop pop                     % =>
1013
} def
1014
 
1015
/do-slide-cs {                     % => ... RS' [SS SR SC] R C
1016
  2 index 1 get                   % => ... RS' [SS SR SC] R C SR
1017
  2 index eq {                    % => ... RS' [SS SR SC] R C
1018
    2 index 2 get                 % => ... RS' [SS SR SC] R C SC
1019
    1 index ge {                  % => ... RS' [SS SR SC] R C
1020
      2 index 2 get               % => ... RS' [SS SR SC] R C SC
1021
      1 add                       % => ... RS' [SS SR SC] R C SC+1
1022
      3 index exch
1023
      2 exch                      % => ... RS' [SS SR SC] R C [..] 2 SC+1
1024
      put                         % => ... RS' [SS SR SC+1] R C
1025
% FIXME: reorder rowspans after this operation?
1026
    } if
1027
  } if
1028
 
1029
  pop pop
1030
  exch array-prepend
1031
} def
1032
 
1033
/table-slide-cs {                  % => R C Box
1034
  2 index 2 index /do-slide-cs    % => R C Box {fun}
1035
  cvx 3 array astore cvx
1036
  []
1037
  2 index table-get-colspans
1038
  reduce
1039
 
1040
  1 index table-put-colspans      % => R C Box
1041
 
1042
  pop pop pop                     % =>
1043
} def
1044
 
1045
/table-fake-cell {                 % => R C Box
1046
  3 copy
1047
  table-slide-cw                   % => R C Box
1048
  3 copy
1049
  table-slide-rs                   % => R C Box
1050
  3 copy
1051
  table-slide-cs                   % => R C Box
1052
 
1053
  dup
1054
  get-table-content-rows           % => R C Box Rows
1055
  dup                              % => R C Box Rows Rows
1056
  4 index 1 sub                    % => R C Box Rows Rows R(0)
1057
  dup
1058
  2 index length 1 sub gt {
1059
    pop pop pop pop pop pop
1060
  } {
1061
    get                            % => R C Box Rows Row
1062
    3 index 1 sub exch             % => R C Box Rows C(ZeroBased) Row
1063
    box-block-create       % => R C Box Rows C Row FBox
1064
    {show-fake-block-box}
1065
    1 index put-display
1066
    exch                           % => R C Box Rows C FBox Row
1067
 
1068
    dup length 3 index lt {
1069
      3 1 roll
1070
      array-extend
1071
    } {
1072
      array-insert                   % => R C Box Rows Row'
1073
    } ifelse
1074
 
1075
    dup length                     % => R C Box Rows Row' RL'
1076
    3 index get-content            % => R C Box Rows Row' RL' [C R Content]
1077
    exch 0 exch                    % => R C Box Rows Row' [C R Content] 1 RL'
1078
    2 index 0 get max
1079
    put
1080
 
1081
    4 index 1 sub                  % => R C Box Rows Row' R(ZeroBased)
1082
    exch                           % => R C Box Rows R(ZeroBased) Row'
1083
    put                            % => R C Box
1084
    pop pop pop                    % =>
1085
  } ifelse
1086
} def
1087
 
1088
/in-normalize-rowspans {           % => Size Row Col Box
1089
  3 index 1 gt {
1090
    2 index 1 add           % => Size Row Col Box Row+1
1091
    2 index                 % => Size Row Col Box Row+1 Col
1092
    2 index
1093
    table-fake-cell         % => Size Row Col Box
1094
    4 2 roll                % => Col Box Size Row
1095
    1 add                   % => Col Box Size Row+1
1096
    4 1 roll                % => Row+1 Col Box Size
1097
    1 sub                   % => Row+1 Col Box Size-1
1098
    4 1 roll                % => Size-1 Row+1 Col Box
1099
    in-normalize-rowspans   % =>
1100
  } {
1101
    pop pop pop pop         % =>
1102
  } ifelse
1103
} def
1104
 
1105
/normalize-rowspans {              % => Box
1106
  dup table-get-rowspans           % => Box Rowspans
1107
  {                                % => Box Rowspan
1108
    aload pop                      % => Box Size Row Col
1109
    3 index                        % => Box Size Row Col Box
1110
    in-normalize-rowspans          % => Box
1111
  } forall                         % => Box
1112
 
1113
  dup get-table-content-rows       % => Box Rows
1114
  length                           % => Box RN
1115
 
1116
  1 index table-get-rowspans       % => Box RN Rowspans
1117
  {                                % => Box RN Rowspan
1118
    dup 1 get                      % => Box RN Rowspan RSR
1119
    dup                            % => Box RN Rowspan RSR RSR
1120
    2 index 0 get                  % => Box RN Rowspan RSR RSR RSS
1121
    add 1 sub                      % => Box RN Rowspan RSR RSR+RSS-1
1122
    3 index min                    % => Box RN RowSpan RSR SpanEnd
1123
    exch sub 1 add                 % => Box RN RowSpan SpanSize
1124
 
1125
  } forall                         % => Box RN
1126
 
1127
  pop pop                          % =>
1128
} def
1129
 
1130
/normalize-table {                 % => Box
1131
  dup normalize-rowspans
1132
 
1133
  dup get-content                  % => Box Content
1134
  get-children-from-content        % => Box Rows
1135
  dup dup                          % => Box  Rows Rows Rows
1136
 
1137
  {                         % => Box Rows Rows 0 Row
1138
    length
1139
    max
1140
  } forall                  % => Box Rows Rows MaxRowLength
1141
 
1142
 
1143
  3 2 roll                  % => Box Rows 0       MaxRowLength Rows
1144
  {                         % => Box Rows RowNo   MaxRowLength Row
1145
    1 index exch            % => Box Rows RowNo   MaxRowLength MaxRowLength Row
1146
    normalize-row           % => Box Rows RowNo   MaxRowLength Row'
1147
    3 index 3 index         % => Box Rows RowNo   MaxRowLength Row' Rows RowNo
1148
    3 2 roll                % => Box Rows RowNo   MaxRowLength Rows RowNo Row'
1149
    put                     % => Box Rows RowNo   MaxRowLength
1150
    exch 1 add exch         % => Box Rows RowNo+1 MaxRowLength
1151
  } forall
1152
 
1153
  pop pop pop
1154
  pop
1155
} def
1156
 
1157
/in-make-table-row {               % => RowData Size
1158
  dup 0 gt {
1159
    1 index          % => RowData Size RowData
1160
    aload            % => RowData Size Data1 ... DataN Arr
1161
    length           % => RowData Size Data1 ... DataN N
1162
    1 add            % => RowData Size Data1 ... DataN N+1
1163
    [] exch          % => RowData Size Data1 ... DataN [] N+1
1164
    array astore     % => RowData Size NewRowData
1165
    3 2 roll pop     % => Size NewRowData
1166
    exch             % => NewRowData Size
1167
    1 sub            % => NewRowData Size-1
1168
    in-make-table-row
1169
  } {
1170
    pop
1171
  } ifelse
1172
} def
1173
 
1174
/make-table-row {                  % => Size
1175
  [] exch         % => [](EmptyRow) Size
1176
  in-make-table-row
1177
} def
1178
 
1179
/in-make-table {                   % => TableData Cols Rows
1180
  dup 0 gt {
1181
    2 index          % => TableData Cols Rows TableData
1182
    aload            % => TableData Cols Rows Data1 ... DataN TableData
1183
    length           % => TableData Cols Rows Data1 ... DataN N
1184
    1 add            % => TableData Cols Rows Data1 ... DataN N+1
1185
    dup 1 add index
1186
    make-table-row
1187
    exch             % => TableData Cols Rows Data1 ... DataN NewRow N+1
1188
    array astore     % => TableData Cols Rows NewTableData
1189
    4 3 roll pop     % => Cols Rows NewTableData
1190
    3 1 roll         % => NewTableData Cols Rows
1191
    1 sub            % => NewTableData Cols Rows-1
1192
    in-make-table
1193
  } {
1194
    pop pop
1195
  } ifelse
1196
} def
1197
 
1198
/make-table {                      % => Cols Rows
1199
  [] 3 1 roll
1200
  in-make-table
1201
} def
1202
 
1203
/in-add-table-cell {               % => Box Cell
1204
  1 index get-content % => Box Cell [Cols Rows Content](RawContent)
1205
  2 get               % => Box Cell Rows
1206
  dup length 1 sub    % => Box Cell Rows LastIndex
1207
  dup
1208
  2 index exch get    % => Box Cell Rows LastIndex LastRow
1209
  aload length        % => Box Cell Rows LastIndex Cell1 .. CellN N
1210
  dup 3 add           % => Box Cell Rows LastIndex Cell1 .. CellN N N+4
1211
  index exch          % => Box Cell Rows LastIndex Cell1 .. CellN Cell N
1212
  1 add
1213
  array astore        % => Box Cell Rows LastIndex NewRow
1214
  dup length          % => Box Cell Rows LastIndex NewRow NewRowLength
1215
  5 1 roll            % => Box NewRowLength Cell Rows LastIndex NewRow
1216
  put
1217
  pop                 % => Box NewRowLength
1218
  1 index get-content
1219
  dup 0 get           % => Box NewRowLength Content Cols
1220
  3 2 roll            % => Box Content Cols NewRowLength
1221
  max
1222
 
1223
} def
1224
 
1225
/add-table-cell {                 % => Table Child
1226
  1 index is-table {
1227
% setup parent reference in the child box
1228
    dup get-box-dict
1229
    /Parent 3 index put
1230
% set display property
1231
    dup get-box-dict
1232
    /Display /table-cell put
1233
 
1234
% Check if any rows have been added to the table
1235
% Add one if no rows still exists
1236
    1 index get-table-content-rows          % => Rows
1237
    length 0 eq {
1238
      1 index add-table-row pop
1239
    } if
1240
 
1241
    2 copy
1242
    in-add-table-cell             % => Table Child Table
1243
    pop                           % => Table Child
1244
 
1245
% If table-cell had width constaint, propagate it to the column
1246
    dup no-width-constraint not {
1247
      dup get-width-constraint
1248
      2 index put-table-column-width-constraint
1249
      {wc-none} 1 index put-width-constraint
1250
    } if
1251
    pop
1252
  } {
1253
% if parent is not a table, just ignore this box
1254
    pop
1255
  } ifelse
1256
} def