1<?php
2
3/**
4 * @abstract
5 */
6class BoxPageMargin extends GenericContainerBox {
7  /**
8   * @param $at_rule CSSAtRuleMarginBox At-rule object describing margin box to be created
9   * @return Object Object of concrete BoxPageMargin descendant type
10   */
11  function &create(&$pipeline, $at_rule) {
12    switch ($at_rule->getSelector()) {
13    case CSS_MARGIN_BOX_SELECTOR_TOP:
14      $box =& new BoxPageMarginTop($pipeline, $at_rule);
15      break;
16    case CSS_MARGIN_BOX_SELECTOR_TOP_LEFT_CORNER:
17      $box =& new BoxPageMarginTopLeftCorner($pipeline, $at_rule);
18      break;
19    case CSS_MARGIN_BOX_SELECTOR_TOP_LEFT:
20      $box =& new BoxPageMarginTopLeft($pipeline, $at_rule);
21      break;
22    case CSS_MARGIN_BOX_SELECTOR_TOP_CENTER:
23      $box =& new BoxPageMarginTopCenter($pipeline, $at_rule);
24      break;
25    case CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT:
26      $box =& new BoxPageMarginTopRight($pipeline, $at_rule);
27      break;
28    case CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT_CORNER:
29      $box =& new BoxPageMarginTopRightCorner($pipeline, $at_rule);
30      break;
31    case CSS_MARGIN_BOX_SELECTOR_BOTTOM:
32      $box =& new BoxPageMarginBottom($pipeline, $at_rule);
33      break;
34    case CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT_CORNER:
35      $box =& new BoxPageMarginBottomLeftCorner($pipeline, $at_rule);
36      break;
37    case CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT:
38      $box =& new BoxPageMarginBottomLeft($pipeline, $at_rule);
39      break;
40    case CSS_MARGIN_BOX_SELECTOR_BOTTOM_CENTER:
41      $box =& new BoxPageMarginBottomCenter($pipeline, $at_rule);
42      break;
43    case CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT:
44      $box =& new BoxPageMarginBottomRight($pipeline, $at_rule);
45      break;
46    case CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT_CORNER:
47      $box =& new BoxPageMarginBottomRightCorner($pipeline, $at_rule);
48      break;
49    case CSS_MARGIN_BOX_SELECTOR_LEFT_TOP:
50      $box =& new BoxPageMarginLeftTop($pipeline, $at_rule);
51      break;
52    case CSS_MARGIN_BOX_SELECTOR_LEFT_MIDDLE:
53      $box =& new BoxPageMarginLeftMiddle($pipeline, $at_rule);
54      break;
55    case CSS_MARGIN_BOX_SELECTOR_LEFT_BOTTOM:
56      $box =& new BoxPageMarginLeftBottom($pipeline, $at_rule);
57      break;
58    case CSS_MARGIN_BOX_SELECTOR_RIGHT_TOP:
59      $box =& new BoxPageMarginRightTop($pipeline, $at_rule);
60      break;
61    case CSS_MARGIN_BOX_SELECTOR_RIGHT_MIDDLE:
62      $box =& new BoxPageMarginRightMiddle($pipeline, $at_rule);
63      break;
64    case CSS_MARGIN_BOX_SELECTOR_RIGHT_BOTTOM:
65      $box =& new BoxPageMarginRightBottom($pipeline, $at_rule);
66      break;
67    default:
68      trigger_error("Unknown selector type", E_USER_ERROR);
69    };
70
71    return $box;
72  }
73
74  function BoxPageMargin(&$pipeline, $at_rule) {
75    $state =& $pipeline->get_current_css_state();
76    $state->pushDefaultState();
77
78    $root = null;
79    $at_rule->css->apply($root, $state, $pipeline);
80
81    $this->GenericContainerBox();
82    $this->readCSS($state);
83
84    $state->pushDefaultstate();
85
86    /**
87     * Check whether 'content' or '-html2ps-html-content' properties had been defined
88     * (if both properties are defined, -html2ps-html-content takes precedence)
89     */
90    $raw_html_content =& $at_rule->get_css_property(CSS_HTML2PS_HTML_CONTENT);
91    $html_content = $raw_html_content->render($pipeline->get_counters());
92
93    if ($html_content !== '') {
94      // We should wrap html_content in DIV tag,
95      // as we treat only the very first box of the resulting DOM tree as margin box content
96
97      $html_content = html2xhtml("<div>".$html_content."</div>");
98      $tree = TreeBuilder::build($html_content);
99      $tree_root = traverse_dom_tree_pdf($tree);
100      $body_box =& create_pdf_box($tree_root, $pipeline);
101      $box =& $body_box->content[0];
102    } else {
103      $raw_content =& $at_rule->get_css_property(CSS_CONTENT);
104      $content = $raw_content->render($pipeline->get_counters());
105
106      $box =& InlineBox::create_from_text($content,
107                                          WHITESPACE_PRE_LINE,
108                                          $pipeline);
109    }
110    $this->add_child($box);
111
112    $state->popState();
113    $state->popState();
114  }
115
116  function get_cell_baseline() {
117    return 0;
118  }
119
120  function reflow(&$driver, &$media, $boxes) {
121    $context = new FlowContext;
122    $this->_position($media, $boxes, $context);
123
124    $this->setCSSProperty(CSS_WIDTH, new WCConstant($this->get_width()));
125    $this->put_height_constraint(new HCConstraint(array($this->height, false),
126                                                  null,
127                                                  null));
128
129    $this->reflow_content($context);
130
131    /**
132     * Apply vertical-align (behave like table cell)
133     */
134    $va = CSSVerticalAlign::value2pdf($this->get_css_property(CSS_VERTICAL_ALIGN));
135
136    $va->apply_cell($this,$this->get_full_height(),0);
137  }
138
139  function show(&$driver) {
140    $this->offset(0, $driver->offset);
141    $this->show_fixed($driver);
142  }
143
144  function _calc_sizes($full_width, $left, $center, $right) {
145    $context = new FlowContext;
146
147    $left_width   = $left->get_max_width($context);
148    $center_width = $center->get_max_width($context);
149    $right_width  = $right->get_max_width($context);
150
151    $calculated_left_width   = 0;
152    $calculated_center_width = 0;
153    $calculated_right_width  = 0;
154
155    if ($center_width > 0) {
156      $calculated_center_width = $full_width * $center_width / ($center_width + 2*max($left_width, $right_width));
157      $calculated_left_width   = ($full_width - $calculated_center_width) / 2;
158      $calculated_right_width  = $calculated_left_width;
159    } elseif ($left_width == 0 && $right_width == 0) {
160      $calculated_center_width = 0;
161      $calculated_left_width   = 0;
162      $calculated_right_width  = 0;
163    } elseif ($left_width == 0) {
164      $calculated_center_width = 0;
165      $calculated_left_width   = 0;
166      $calculated_right_width  = $full_width;
167    } elseif ($right_width == 0) {
168      $calculated_center_width = 0;
169      $calculated_left_width   = $full_width;
170      $calculated_right_width  = 0;
171    } else {
172      $calculated_center_width = 0;
173      $calculated_left_width   = $full_width * $left_width / ($left_width + $right_width);
174      $calculated_right_width  = $full_width - $calculated_left_width;
175    };
176
177    return array($calculated_left_width,
178                 $calculated_center_width,
179                 $calculated_right_width);
180  }
181}
182
183class BoxPageMarginTop extends BoxPageMargin {
184  function _position($media, $boxes, $context) {
185    $this->put_left($this->get_extra_left() + 0);
186    $this->put_top(-$this->get_extra_top() +mm2pt($media->height()));
187
188    $this->put_full_width(mm2pt($media->width()));
189    $this->put_full_height(mm2pt($media->margins['top']));
190
191    $this->_current_x = $this->get_left();
192    $this->_current_y = $this->get_top();
193  }
194}
195
196class BoxPageMarginTopLeftCorner extends BoxPageMargin {
197  function _position($media, $boxes, $context) {
198    $this->put_left($this->get_extra_left() + 0);
199    $this->put_top(-$this->get_extra_top() +mm2pt($media->height()));
200
201    $this->put_full_width(mm2pt($media->margins['left']));
202    $this->put_full_height(mm2pt($media->margins['top']));
203
204    $this->_current_x = $this->get_left();
205    $this->_current_y = $this->get_top();
206  }
207}
208
209class BoxPageMarginTopLeft extends BoxPageMargin {
210  function _position($media, $boxes, $context) {
211    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_width()),
212                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_LEFT],
213                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_CENTER],
214                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT]);
215
216    $this->put_left($this->get_extra_left() + mm2pt($media->margins['left']));
217    $this->put_top(-$this->get_extra_top() +mm2pt($media->height()));
218
219    $this->put_full_width($left);
220    $this->put_full_height(mm2pt($media->margins['top']));
221
222    $this->_current_x = $this->get_left();
223    $this->_current_y = $this->get_top();
224  }
225}
226
227class BoxPageMarginTopCenter extends BoxPageMargin {
228  function _position($media, $boxes, $context) {
229    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_width()),
230                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_LEFT],
231                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_CENTER],
232                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT]);
233
234    $this->put_left($this->get_extra_left() + mm2pt($media->margins['left']) + $left);
235    $this->put_top(-$this->get_extra_top() +mm2pt($media->height()));
236
237    $this->put_full_width($center);
238    $this->put_full_height(mm2pt($media->margins['top']));
239
240    $this->_current_x = $this->get_left();
241    $this->_current_y = $this->get_top();
242  }
243}
244
245class BoxPageMarginTopRight extends BoxPageMargin {
246  function _position($media, $boxes, $context) {
247    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_width()),
248                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_LEFT],
249                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_CENTER],
250                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT]);
251
252    $this->put_left($this->get_extra_left() + mm2pt($media->margins['left']) + $left + $center);
253    $this->put_top(-$this->get_extra_top() +mm2pt($media->height()));
254
255    $this->put_full_width($right);
256    $this->put_full_height(mm2pt($media->margins['top']));
257
258    $this->_current_x = $this->get_left();
259    $this->_current_y = $this->get_top();
260  }
261}
262
263class BoxPageMarginTopRightCorner extends BoxPageMargin {
264  function _position($media, $boxes, $context) {
265    $this->put_left($this->get_extra_left() + mm2pt($media->width() - $media->margins['right']));
266    $this->put_top(-$this->get_extra_top() +mm2pt($media->height()));
267
268    $this->put_full_width(mm2pt($media->margins['right']));
269    $this->put_full_height(mm2pt($media->margins['top']));
270
271    $this->_current_x = $this->get_left();
272    $this->_current_y = $this->get_top();
273  }
274}
275
276class BoxPageMarginBottomLeftCorner extends BoxPageMargin {
277  function _position($media, $boxes, $context) {
278    $this->put_left($this->get_extra_left() + 0);
279    $this->put_top(-$this->get_extra_top() +mm2pt($media->margins['bottom']));
280
281    $this->put_full_width(mm2pt($media->margins['left']));
282    $this->put_full_height(mm2pt($media->margins['bottom']));
283
284    $this->_current_x = $this->get_left();
285    $this->_current_y = $this->get_top();
286  }
287}
288
289class BoxPageMarginBottomLeft extends BoxPageMargin {
290  function _position($media, $boxes, $context) {
291    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_width()),
292                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT],
293                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_CENTER],
294                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT]);
295
296    $this->put_left($this->get_extra_left() + mm2pt($media->margins['left']));
297    $this->put_top(-$this->get_extra_top() +mm2pt($media->margins['bottom']));
298
299    $this->put_full_width($left);
300    $this->put_full_height(mm2pt($media->margins['bottom']));
301
302    $this->_current_x = $this->get_left();
303    $this->_current_y = $this->get_top();
304  }
305}
306
307class BoxPageMarginBottomCenter extends BoxPageMargin {
308  function _position($media, $boxes, $context) {
309    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_width()),
310                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT],
311                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_CENTER],
312                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT]);
313
314    $this->put_left($this->get_extra_left() + mm2pt($media->margins['left']) + $left);
315    $this->put_top(-$this->get_extra_top() +mm2pt($media->margins['bottom']));
316
317    $this->put_full_width($center);
318    $this->put_full_height(mm2pt($media->margins['bottom']));
319
320    $this->_current_x = $this->get_left();
321    $this->_current_y = $this->get_top();
322  }
323}
324
325class BoxPageMarginBottomRight extends BoxPageMargin {
326  function _position($media, $boxes, $context) {
327    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_width()),
328                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT],
329                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_CENTER],
330                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT]);
331
332    $this->put_left($this->get_extra_left() + mm2pt($media->margins['left']) + $left + $center);
333    $this->put_top(-$this->get_extra_top() +mm2pt($media->margins['bottom']));
334
335    $this->put_full_width($right);
336    $this->put_full_height(mm2pt($media->margins['bottom']));
337
338    $this->_current_x = $this->get_left();
339    $this->_current_y = $this->get_top();
340  }
341}
342
343class BoxPageMarginBottomRightCorner extends BoxPageMargin {
344  function _position($media, $boxes, $context) {
345    $this->put_left($this->get_extra_left() + mm2pt($media->width() - $media->margins['right']));
346    $this->put_top(-$this->get_extra_top() +mm2pt($media->margins['bottom']));
347
348    $this->put_full_width(mm2pt($media->margins['right']));
349    $this->put_full_height(mm2pt($media->margins['top']));
350
351    $this->_current_x = $this->get_left();
352    $this->_current_y = $this->get_top();
353  }
354}
355
356class BoxPageMarginBottom extends BoxPageMargin {
357  function _position($media, $boxes, $context) {
358    $this->put_left($this->get_extra_left() + 0);
359    $this->put_top(-$this->get_extra_top() +mm2pt($media->margins['bottom']));
360
361    $this->put_full_width(mm2pt($media->width()));
362    $this->put_full_height(mm2pt($media->margins['bottom']));
363
364    $this->_current_x = $this->get_left();
365    $this->_current_y = $this->get_top();
366  }
367}
368
369class BoxPageMarginLeftTop extends BoxPageMargin {
370  function _position($media, $boxes, $context) {
371    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_height()),
372                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_TOP],
373                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_MIDDLE],
374                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_BOTTOM]);
375
376    $this->put_left($this->get_extra_left() + 0);
377    $this->put_top(-$this->get_extra_top() +mm2pt($media->height() - $media->margins['top']));
378
379    $this->put_full_height($left);
380    $this->put_full_width(mm2pt($media->margins['left']));
381
382    $this->_current_x = $this->get_left();
383    $this->_current_y = $this->get_top();
384  }
385}
386
387class BoxPageMarginLeftMiddle extends BoxPageMargin {
388  function _position($media, $boxes, $context) {
389    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_height()),
390                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_TOP],
391                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_MIDDLE],
392                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_BOTTOM]);
393    $this->put_left($this->get_extra_left() + 0);
394    $this->put_top(-$this->get_extra_top() +mm2pt($media->height() - $media->margins['top']) - $left);
395
396    $this->put_full_height($center);
397    $this->put_full_width(mm2pt($media->margins['left']));
398
399    $this->_current_x = $this->get_left();
400    $this->_current_y = $this->get_top();
401  }
402}
403
404class BoxPageMarginLeftBottom extends BoxPageMargin {
405  function _position($media, $boxes, $context) {
406    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_height()),
407                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_TOP],
408                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_MIDDLE],
409                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_BOTTOM]);
410
411    $this->put_left($this->get_extra_left() + 0);
412    $this->put_top(-$this->get_extra_top() +mm2pt($media->height() - $media->margins['top']) - $left - $center);
413
414    $this->put_full_height($right);
415    $this->put_full_width(mm2pt($media->margins['left']));
416
417    $this->_current_x = $this->get_left();
418    $this->_current_y = $this->get_top();
419  }
420}
421
422class BoxPageMarginRightTop extends BoxPageMargin {
423  function _position($media, $boxes, $context) {
424    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_height()),
425                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_RIGHT_TOP],
426                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_RIGHT_MIDDLE],
427                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_RIGHT_BOTTOM]);
428
429    $this->put_left($this->get_extra_left() + mm2pt($media->width() - $media->margins['right']));
430    $this->put_top(-$this->get_extra_top() +mm2pt($media->height() - $media->margins['top']));
431
432    $this->put_full_height($left);
433    $this->put_full_width(mm2pt($media->margins['right']));
434
435    $this->_current_x = $this->get_left();
436    $this->_current_y = $this->get_top();
437  }
438}
439
440class BoxPageMarginRightMiddle extends BoxPageMargin {
441  function _position($media, $boxes, $context) {
442    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_height()),
443                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_TOP],
444                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_MIDDLE],
445                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_BOTTOM]);
446
447    $this->put_left($this->get_extra_left() + mm2pt($media->width() - $media->margins['right']));
448    $this->put_top(-$this->get_extra_top() +mm2pt($media->height() - $media->margins['top']) - $left);
449
450    $this->put_full_height($center);
451    $this->put_full_width(mm2pt($media->margins['right']));
452
453    $this->_current_x = $this->get_left();
454    $this->_current_y = $this->get_top();
455  }
456}
457
458class BoxPageMarginRightBottom extends BoxPageMargin {
459  function _position($media, $boxes, $context) {
460    list($left, $center, $right) = $this->_calc_sizes(mm2pt($media->real_height()),
461                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_TOP],
462                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_MIDDLE],
463                                                      $boxes[CSS_MARGIN_BOX_SELECTOR_LEFT_BOTTOM]);
464
465    $this->put_left($this->get_extra_left() + mm2pt($media->width() - $media->margins['right']));
466    $this->put_top(-$this->get_extra_top() + mm2pt($media->height() - $media->margins['top']) - $left - $center);
467
468    $this->put_full_height($right);
469    $this->put_full_width(mm2pt($media->margins['right']));
470
471    $this->_current_x = $this->get_left();
472    $this->_current_y = $this->get_top();
473  }
474}
475
476?>