Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
% Definition of float context "class"
2
 
3
/context-add-absolute-positioned { % => Box Context
4
  dup /AbsolutePositioned get      % => Box Context AB
5
  2 index exch
6
  array-prepend                    % => Box Context AB'
7
  /AbsolutePositioned exch put     % => Box
8
  pop
9
} def
10
 
11
/context-add-fixed-positioned { % => Box Context
12
  dup /FixedPositioned get      % => Box Context AB
13
  2 index exch
14
  array-prepend                    % => Box Context AB'
15
  /FixedPositioned exch put     % => Box
16
  pop
17
} def
18
 
19
/context-add-float {               % => Float Context
20
  dup /Floats get                  % => Float Context Floats
21
  dup 0 get                        % => Float Context Floats Floats[0]
22
  3 index exch array-prepend       % => Float Context Floats Floats[0]'
23
 
24
  pop pop
25
} def
26
 
27
/context-container-uid {           % => Context
28
  /ContainerUID get 0 get
29
} def
30
 
31
/context-create {                  % =>
32
  <<
33
    /ContainerUID [1]
34
    /AbsolutePositioned []
35
    /FixedPositioned []
36
    /Floats [[]]
37
    /Margin [0 0]
38
    /Viewport []
39
  >>
40
} def
41
 
42
% Find the minimal X at the given Y coordinate suitable for float placement
43
%
44
/context-float-left-x {            % => Y X Context
45
  3 copy dup
46
  context-floats                   % => Y X Context Y X Context Floats
47
  context-float-left-x-rec         % => Y X Context X
48
 
49
% Clear the stack
50
  exch pop
51
  exch pop
52
  exch pop
53
} def
54
 
55
/context-float-left-x-rec {        % => Y X Context Floats
56
  dup length 0 gt {
57
    dup 0 get                      % => Y X Context Floats Float
58
 
59
    dup /float get-css-value
60
    /left eq {
61
 
62
% Check if this float contains given Y-coordinate
63
%
64
% Note that top margin coordinate is inclusive but
65
% bottom margin coordinate is exclusive! The cause is following:
66
% - if we have several floats in one line, their top margin edge Y coordinates will be equal,
67
%   so we must use agreater or equal sign to avod placing all floats at one X coordinate
68
% - on the other side, if we place one float under the other, the top margin Y coordinate
69
%   of bottom float will be equal to bottom margin Y coordinate of the top float and
70
%   we should NOT offset tho bottom float in this case
71
 
72
      dup get-top-margin             % => Y X Context Floats Float FTM
73
      rounding-epsilon add
74
      5 index                        % => Y X Context Floats Float FTM Y
75
      ge                             % => Y X Context Floats Float FTM>=Y
76
 
77
      1 index get-bottom-margin      % => Y X Context Floats Float FTM>=Y FBM
78
      6 index                        % => Y X Context Floats Float FTM>=Y FBM Y
79
      lt                             % => Y X Context Floats Float FTM>=Y FBM<Y
80
 
81
      and {                          % => Y X Context Floats Float
82
        dup get-right-margin         % => Y X Context Floats Float FRM
83
        4 index max                  % => Y X Context Floats Float X'=MAX(FRM,X)
84
        exch pop                     % => Y X Context Floats X'
85
        4 3 roll pop                 % => Y Context Floats X'
86
        3 1 roll                     % => Y X' Context Floats
87
        array-pop-first
88
        context-float-left-x-rec     % => X
89
      } {
90
        pop
91
        array-pop-first
92
        context-float-left-x-rec
93
      } ifelse
94
    } {
95
      pop
96
      array-pop-first
97
      context-float-left-x-rec
98
    } ifelse
99
  } {
100
% no more floats
101
    pop pop exch pop
102
  } ifelse
103
} def                              % => X
104
 
105
% Calculates position of left floating box (taking into account the possibility
106
% of "wrapping" float to next line in case we have not enough space at current level (Y coordinate)
107
%
108
% @param parent reference to a parent box
109
% @param width width of float being placed. Full width! so, extra horizontal space (padding, margins and borders) is added here too
110
% @param $y Starting Y-coordinate
111
% @return X X coordinate of float upper-left corner
112
% @return Y Y coordinate of float upper-left corner
113
%
114
/context-float-left-xy {           % => Parent Width Y Context
115
% Prepare information about the float bottom corrdinates
116
  dup context-floats               % => Parent Width Y Context Floats
117
  make-sorted-bottom-y-list        % => Parent Width Y Context FloatBottoms
118
 
119
  context-float-left-xy-rec        % => Y X
120
} def                              % => Y X
121
 
122
/context-float-left-xy-rec {       % => Parent Width Y Context FloatBottoms
123
  4 index get-left
124
  3 index                          % => Parent Width Y Context FloatBottoms X Y
125
  exch                             % => Parent Width Y Context FloatBottoms Y X
126
  3 index
127
  context-float-left-x             % => Parent Width Y Context FloatBottoms X
128
 
129
% Check if current float will fit into the parent box
130
  dup 5 index add                  % => Parent Width Y Context FloatBottoms X FloatRight
131
  6 index get-right
132
  rounding-epsilon add
133
  le {                             % => Parent Width Y Context FloatBottoms X
134
% will fit
135
    exch pop                       % => Parent Width Y Context X
136
    exch pop                       % => Parent Width Y X
137
    4 2 roll                       % => Y X Parent Width
138
    pop pop exch                   % => X Y
139
  } {
140
    pop                            % => Parent Width Y Context FloatBottoms
141
% Check if all floats have been already cleared
142
    dup length 0 eq {
143
% All floats are cleared; fall back to the leftmost X coordinate
144
      pop pop exch pop             % => Parent Y
145
      exch                         % => Y Parent
146
      get-left exch                % => X Y
147
    } {
148
% No, float does not fit at current level, let's try to 'clear' some previous floats
149
      dup 0 get                    % => Parent Width Y Context FloatBottoms Bottom0
150
      3 index min                  % => Parent Width Y Context FloatBottoms Y'
151
      4 3 roll pop                 % => Parent Width Context FloatBottoms Y'
152
      3 1 roll
153
      array-pop-first              % => Parent Width Y' Context FloatBottoms'
154
      context-float-left-xy-rec    % => X Y
155
    } ifelse
156
  } ifelse
157
} def                              % => X Y
158
 
159
% Find the minimal X at the given Y coordinate suitable for float placement
160
%
161
/context-float-right-x {           % => Y X Context
162
  3 copy dup
163
  context-floats                   % => Y X Context Y X Context Floats
164
  context-float-right-x-rec        % => Y X Context X
165
 
166
% Clear the stack
167
  exch pop
168
  exch pop
169
  exch pop
170
} def
171
 
172
/context-float-right-x-rec {       % => Y X Context Floats
173
  dup length 0 gt {
174
    dup 0 get                      % => Y X Context Floats Float
175
 
176
    dup /float get-css-value
177
    /right eq {
178
 
179
% Check if this float contains given Y-coordinate
180
%
181
% Note that top margin coordinate is inclusive but
182
% bottom margin coordinate is exclusive! The cause is following:
183
% - if we have several floats in one line, their top margin edge Y coordinates will be equal,
184
%   so we must use agreater or equal sign to avod placing all floats at one X coordinate
185
% - on the other side, if we place one float under the other, the top margin Y coordinate
186
%   of bottom float will be equal to bottom margin Y coordinate of the top float and
187
%   we should NOT offset tho bottom float in this case
188
 
189
      dup get-top-margin             % => Y X Context Floats Float FTM
190
      rounding-epsilon add
191
      5 index                        % => Y X Context Floats Float FTM Y
192
      ge                             % => Y X Context Floats Float FTM>=Y
193
 
194
      1 index get-bottom-margin      % => Y X Context Floats Float FTM>=Y FBM
195
      6 index                        % => Y X Context Floats Float FTM>=Y FBM Y
196
      lt                             % => Y X Context Floats Float FTM>=Y FBM<Y
197
 
198
      and {                          % => Y X Context Floats Float
199
        dup get-left-margin          % => Y X Context Floats Float FRM
200
        4 index min                  % => Y X Context Floats Float X'=MAX(FRM,X)
201
        exch pop                     % => Y X Context Floats X'
202
        4 3 roll pop                 % => Y Context Floats X'
203
        3 1 roll                     % => Y X' Context Floats
204
        array-pop-first
205
        context-float-right-x-rec    % => X
206
      } {                            % => Y X Context Floats Float
207
        pop                          % => Y X Context Floats
208
        array-pop-first
209
        context-float-right-x-rec    % => X
210
      } ifelse
211
    } {
212
      pop
213
      array-pop-first
214
      context-float-right-x-rec
215
    } ifelse
216
  } {
217
% no more floats
218
    pop pop exch pop
219
  } ifelse
220
} def                              % => X
221
 
222
% Calculates position of left floating box (taking into account the possibility
223
% of "wrapping" float to next line in case we have not enough space at current level (Y coordinate)
224
%
225
% @param parent reference to a parent box
226
% @param width width of float being placed. Full width! so, extra horizontal space (padding, margins and borders) is added here too
227
% @param $y Starting Y-coordinate
228
% @return X X coordinate of float upper-left corner
229
% @return Y Y coordinate of float upper-left corner
230
%
231
/context-float-right-xy {          % => Parent Width Y Context
232
% Prepare information about the float bottom corrdinates
233
  dup context-floats               % => Parent Width Y Context Floats
234
  make-sorted-bottom-y-list        % => Parent Width Y Context FloatBottoms
235
 
236
  context-float-right-xy-rec       % => X Y
237
} def                              % => X Y
238
 
239
/context-float-right-xy-rec {      % => Parent Width Y Context FloatBottoms
240
  4 index get-right
241
  3 index                          % => Parent Width Y Context FloatBottoms X Y
242
  exch
243
  3 index
244
  context-float-right-x            % => Parent Width Y Context FloatBottoms X
245
 
246
% Check if current float will fit into the parent box
247
  dup                              % => Parent Width Y Context FloatBottoms X X
248
  6 index get-right
249
  rounding-epsilon add             % => Parent Width Y Context FloatBottoms X X FRight
250
  le {                             % => Parent Width Y Context FloatBottoms X
251
% will fit
252
    exch pop exch pop              % => Parent Width Y X
253
    4 2 roll                       % => Y X Parent Width
254
    pop pop exch                   % => X Y
255
  } {
256
    pop                            % => Parent Width Y Context FloatBottoms
257
% Check if all floats have been already cleared
258
    dup length 0 eq {
259
% All floats are cleared; fall back to the leftmost X coordinate
260
      pop pop exch pop             % => Parent Y
261
      exch                         % => Y Parent
262
      get-left exch                % => X Y
263
    } {
264
% No, float does not fit at current level, let's try to 'clear' some previous floats
265
      dup 0 get                    % => Parent Width Y Context FloatBottoms Bottom0
266
      3 index min                  % => Parent Width Y Context FloatBottoms Y'
267
      4 3 roll pop                 % => Parent Width Context FloatBottoms Y'
268
      3 1 roll
269
      array-pop-first              % => Parent Width Y' Context FloatBottoms'
270
      context-float-left-xy-rec    % => X Y
271
    } ifelse
272
  } ifelse
273
} def                              % => X Y
274
 
275
/context-floats {                  % => Context
276
  /Floats get 0 get
277
} def
278
 
279
/context-get-absolute-positioned { % => Context
280
  /AbsolutePositioned get
281
} def
282
 
283
/context-get-collapsed-margin {    % => Context
284
  /Margin get 0 get
285
} def
286
 
287
/context-get-fixed-positioned { % => Context
288
  /FixedPositioned get
289
} def
290
 
291
/context-get-viewport {            % => Context
292
  /Viewport get 0 get
293
} def
294
 
295
/context-point-in-floats {         % => Y X Context
296
  /null                            % => Y X Context /null
297
  1 index context-floats           % => Y X Context /null Floats
298
  {                                % => Y X Context /null Float
299
    4 index
300
    4 index
301
    2 index
302
    box-generic-contains-point-margin {        % => Y X Context /null Float
303
      exch pop
304
      exit                         % => Y X Context Float
305
    } if
306
    pop
307
  } forall                         % => Y X Context Float
308
 
309
  exch pop
310
  exch pop
311
  exch pop
312
} def
313
 
314
/context-pop {                     % => Context
315
  dup context-pop-collapsed-margin
316
  dup context-pop-floats
317
  pop
318
} def
319
 
320
/context-pop-collapsed-margin {    % => Context
321
  dup /Margin get                  % => Context CMT
322
  array-pop-first                  % => Context CMT'
323
  /Margin exch put                 % =>
324
} def
325
 
326
/context-pop-container-uid {       % => Context
327
  dup /ContainerUID get
328
  array-pop-first
329
  /ContainerUID exch put
330
} def
331
 
332
/context-pop-floats {              % => Context
333
  dup /Floats get
334
  array-pop-first
335
  /Floats exch put
336
} def
337
 
338
/context-pop-viewport {            % => Context
339
  dup /Viewport get
340
  array-pop-first                  % => Context Viewports
341
  /Viewport exch put               % =>
342
} def
343
 
344
/context-push {                    % => Context
345
 
346
  dup context-push-floats
347
  pop
348
} def
349
 
350
/context-push-collapsed-margin {   % => Value Context
351
  dup /Margin get                  % => Value Context CMT
352
  2 index exch                     % => Value Content Value CMT
353
  array-append                     % => Value Context CMT'
354
  /Margin exch put                 % => Value
355
  pop
356
} def
357
 
358
/context-push-container-uid {      % => Uid Context
359
  dup /ContainerUID get            % => Uid Context UIDStack
360
  2 index exch array-append        % => Uid Context UIDStack'
361
  1 index exch
362
  /ContainerUID exch put
363
  pop pop
364
} def
365
 
366
/context-push-floats {             % => Context
367
  dup /Floats get
368
  [] exch array-append             % => Context Floats'
369
  /Floats exch                     % => Context /Floats Floats'
370
  put                              % =>
371
} def
372
 
373
/context-push-viewport {           % => Viewport Context
374
  dup /Viewport get                % => Viewport Context Viewports
375
  2 index exch array-append        % => Viewport Context Viewports'
376
  1 index exch /Viewport exch put  % => Viewport Context
377
  pop pop
378
} def
379
 
380
% helper utility
381
/make-sorted-bottom-y-list {       % => Boxes
382
  {
383
    get-bottom-margin
384
    exch array-prepend
385
  } exch
386
  [] exch
387
  reduce                           % => UnsortedBottomsYs
388
 
389
  { gt }                           % => UnsortedBottomsYs GtFun
390
  array-sort                       % => SortedBottomYs
391
} def
392
 
393
%%%%%%%%%%%%%%%%%%%%%
394
 
395
/empty-context {
396
  << /Floats [] /CollapsedMarginTop [0] >>
397
} def
398
 
399
/context-stack [ empty-context ] def
400
 
401
/push-context {
402
  empty-context
403
  context-stack
404
  array-append
405
 
406
  /context-stack exch def
407
} def
408
 
409
/pop-context {
410
  context-stack
411
  array-pop-first
412
 
413
  /context-stack exch def
414
} def
415
 
416
/context-current {
417
  context-stack 0 get
418
} def
419
 
420
/context-floats-bottom {           % => MaxValue
421
  { get-bottom-margin min } exch
422
  context-floats reduce
423
} def
424
 
425
/context-save-float {              % => Float
426
  context-current
427
  /Floats get
428
 
429
  array-append
430
 
431
  context-current exch
432
  /Floats exch
433
  put
434
} def
435
 
436
% Get the bottom edge coordinate of the bottommost float in
437
% current formatting context
438
%
439
% @return /null in case of no floats exists in current context
440
% numeric coordinate value otherwise
441
%
442
/context-float-bottom {            % =>
443
  context-floats
444
  dup length 0 gt {
445
    { get-bottom-margin min }
446
    exch
447
    dup 0 get get-bottom-margin
448
    exch
449
    reduce
450
  } {
451
    pop /null
452
  } ifelse
453
} def
454
 
455
% Get the right edge coordinate of the rightmost float in
456
% current formatting context
457
%
458
% @return null in case of no floats exists in current context
459
% numeric coordinate value otherwise
460
%
461
/context-float-right {             % =>
462
  context-floats
463
  dup length 0 gt {
464
    { get-right-margin min }
465
    exch
466
    dup 0 get get-right-margin
467
    exch
468
    reduce
469
  } {
470
    pop /null
471
  } ifelse
472
} def