1<?php
2// $Header: /cvsroot/html2ps/box.table.row.php,v 1.29 2007/01/24 18:55:45 Konstantin Exp $
3
4class TableRowBox extends GenericContainerBox {
5  var $rows;
6  var $colspans;
7  var $rowspans;
8
9  function &create(&$root, &$pipeline) {
10    $box =& new TableRowBox();
11    $box->readCSS($pipeline->get_current_css_state());
12
13    $child = $root->first_child();
14    while ($child) {
15      $child_box =& create_pdf_box($child, $pipeline);
16      $box->add_child($child_box);
17
18      $child = $child->next_sibling();
19    };
20
21    return $box;
22  }
23
24  function add_child(&$item) {
25    if ($item->isCell()) {
26      GenericContainerBox::add_child($item);
27    };
28  }
29
30  function TableRowBox() {
31    // Call parent constructor
32    $this->GenericContainerBox();
33  }
34
35  // Normalize colspans by adding fake cells after the "colspanned" cell
36  // Say, if we've got the following row:
37  // <tr><td colspan="3">1</td><td>2</td></tr>
38  // we should get row containing four cells after normalization;
39  // first contains "1"
40  // second and third are completely empty
41  // fourth contains "2"
42  function normalize(&$pipeline) {
43    for ($i=0, $size = count($this->content); $i < $size; $i++) {
44      for ($j=1; $j<$this->content[$i]->colspan; $j++) {
45        $this->add_fake_cell_after($i, $pipeline);
46        // Note that add_fake_cell_after will increase the length of current row by one cell,
47        // so we must increase $size variable
48        $size++;
49      };
50    };
51  }
52
53  function add_fake_cell_after($index, &$pipeline) {
54    array_splice($this->content, $index+1, 0, array(FakeTableCellBox::create($pipeline)));
55  }
56
57  function add_fake_cell_before($index, &$pipeline) {
58    array_splice($this->content, $index, 0, array(FakeTableCellBox::create($pipeline)));
59  }
60
61  function append_fake_cell(&$pipeline) {
62    $this->content[] = FakeTableCellBox::create($pipeline);
63  }
64
65  // Table specific
66
67  function table_resize_row($height, $top) {
68    // Do cell vertical-align
69    // Calculate row baseline
70
71    $baseline = $this->get_row_baseline();
72
73    // Process cells contained in current row
74    for ($i=0, $size = count($this->content); $i<$size; $i++) {
75      $cell =& $this->content[$i];
76
77      // Offset cell if needed
78      $cell->offset(0,
79                    $top -
80                    $cell->get_top_margin());
81
82      // Vertical-align cell (do not apply to rowspans)
83      if ($cell->rowspan == 1) {
84        $va = $cell->get_css_property(CSS_VERTICAL_ALIGN);
85        $va_fun = CSSVerticalAlign::value2pdf($va);
86        $va_fun->apply_cell($cell, $height, $baseline);
87
88        // Expand cell to full row height
89        $cell->put_full_height($height);
90      }
91    }
92  }
93
94  function get_row_baseline() {
95    $baseline = 0;
96    for ($i=0, $size = count($this->content); $i<$size; $i++) {
97      $cell = $this->content[$i];
98      if ($cell->rowspan == 1) {
99        $baseline = max($baseline, $cell->get_cell_baseline());
100      };
101    }
102    return $baseline;
103  }
104
105  function get_colspans($row_index) {
106    $colspans = array();
107
108    for ($i=0, $size = count($this->content); $i<$size; $i++) {
109      // Check if current colspan will run off the right table edge
110      if ($this->content[$i]->colspan > 1) {
111        $colspan = new CellSpan;
112        $colspan->row = $row_index;
113        $colspan->column = $i;
114        $colspan->size = $this->content[$i]->colspan;
115
116        $colspans[] = $colspan;
117      }
118    }
119
120    return $colspans;
121  }
122
123  function get_rowspans($row_index) {
124    $spans = array();
125
126    for ($i=0; $i<count($this->content); $i++) {
127      if ($this->content[$i]->rowspan > 1) {
128        $rowspan = new CellSpan;
129        $rowspan->row = $row_index;
130        $rowspan->column = $i;
131        $rowspan->size = $this->content[$i]->rowspan;
132        $spans[] = $rowspan;
133      }
134    }
135
136    return $spans;
137  }
138
139  // Column widths
140  function get_table_columns_max_widths(&$context) {
141    $widths = array();
142    for ($i=0; $i<count($this->content); $i++) {
143      // For now, colspans are treated as zero-width; they affect
144      // column widths only in parent *_fit function
145      if ($this->content[$i]->colspan > 1) {
146        $widths[] = 0;
147      } else {
148        $widths[] = $this->content[$i]->get_max_width($context);
149      }
150    }
151
152    return $widths;
153  }
154
155  function get_table_columns_min_widths(&$context) {
156    $widths = array();
157    for ($i=0; $i<count($this->content); $i++) {
158      // For now, colspans are treated as zero-width; they affect
159      // column widths only in parent *_fit function
160      if ($this->content[$i]->colspan > 1) {
161        $widths[] = 0;
162      } else {
163        $widths[] = $this->content[$i]->get_min_width($context);
164      };
165    }
166
167    return $widths;
168  }
169
170  function row_height() {
171    // Calculate height of each cell contained in this row
172    $height = 0;
173    for ($i=0; $i<count($this->content); $i++) {
174      if ($this->content[$i]->rowspan <= 1) {
175        $height = max($height, $this->content[$i]->get_full_height());
176      }
177    }
178
179    return $height;
180  }
181
182  /**
183   * Note that we SHOULD owerride the show method inherited from GenericContainerBox,
184   * as it MAY draw row background in case it was set via CSS rules. As row box
185   * is a "fake" box and will never have reasonable size and/or position in the layout,
186   * we should prevent this
187   */
188  function show(&$viewport) {
189    // draw content
190    $size = count($this->content);
191
192    for ($i=0; $i < $size; $i++) {
193      /**
194       * We'll check the visibility property here
195       * Reason: all boxes (except the top-level one) are contained in some other box,
196       * so every box will pass this check. The alternative is to add this check into every
197       * box class show member.
198       *
199       * The only exception of absolute positioned block boxes which are drawn separately;
200       * their show method is called explicitly; the similar check should be performed there
201       */
202
203      $cell =& $this->content[$i];
204      $visibility = $cell->get_css_property(CSS_VISIBILITY);
205
206      if ($visibility === VISIBILITY_VISIBLE) {
207        if (is_null($cell->show($viewport))) {
208          return null;
209        };
210      };
211    }
212
213    return true;
214  }
215
216  function isTableRow() {
217    return true;
218  }
219}
220?>