get_width(); return $this->table_columns_fit($table, $width, $context); } function use_colspans(&$table, $widths, &$context, $width_fun, $minwc, $maxwc) { $colspans = $table->get_colspans(); foreach ($colspans as $colspan) { $cell = $table->content[$colspan->row]->content[$colspan->column]; // apply colspans to the corresponsing colspanned-cell dimension // $cell_width = $cell->$width_fun($context); // now select the pre-calculated widths of columns covered by this cell // select the list of resizable columns covered by this cell $spanned_widths = array(); $spanned_resizable = array(); for ($i=$colspan->column; $i < $colspan->column+$colspan->size; $i++) { $spanned_widths[] = $widths[$i]; $spanned_resizable[] = ($minwc[$i] != $maxwc[$i]); } // Sometimes we may encounter the colspan over the empty columns (I mean ALL columns are empty); in this case // we need to make these columns reizable in order to fit colspanned cell contents // if (array_sum($spanned_widths) == 0) { for ($i=0; $icolumn, $colspan->size, $spanned_widths); }; return $widths; } /** * Fit table columns to the given width */ function table_columns_fit(&$table, $width, &$context) { $minw = $table->get_table_columns_min_widths($context); $maxw = $table->get_table_columns_max_widths($context); $minw = $this->use_colspans($table, $minw, $context, 'get_min_width', $minw, $maxw); $maxw = $this->use_colspans($table, $maxw, $context, 'get_max_width', $minw, $maxw); // Store number of columns $columns = count($minw); // Apply column width constraints $minwc = array(); $maxwc = array(); $cellpadding = $table->get_css_property(CSS_HTML2PS_CELLPADDING); $cellspacing = $table->get_css_property(CSS_HTML2PS_CELLSPACING); for ($i=0; $iget_cwc($i); // Do not allow constrained max width be less than min width // Do not allow constrained min width be less than min width // $table_width = $table->get_width(); $extra = 2*$cellpadding->getPoints() + $cellspacing->getPoints(); $minwc[$i] = max($minw[$i], $cwc->apply($minw[$i]-$extra, $table_width) + $extra); $maxwc[$i] = max($minw[$i], $cwc->apply($maxw[$i]-$extra, $table_width) + $extra); }; $minwc = $table->normalize_min_widths($width, $minw, $minwc); $minwc = $table->_table_apply_colspans($minwc, $context, 'get_min_width', $minwc, $maxwc); // We need to normalize widths for the case of colspans width is too big; for example: //
// // //
TEXTTEXT
// in this case table SHOULD NOT be expanded over the 100px! // // $minwc = $table->normalize_min_widths($width, $minw, $minwc); $maxwc = $table->_table_apply_colspans($maxwc, $context, 'get_max_width', $minwc, $maxwc); // Calculate actual widths $widths = array(); // Calculate widths for all constrained columns for ($i=0; $i < $columns; $i++) { if ($table->is_constrained_column($i)) { $widths[$i] = $minwc[$i]; } } // Quick fix for overconstrained tables: if table have width attribute AND its value is less than sum // of constrained columns widths plus minimal widths of uncostrained columns, then we'll expand the width of table // to fit all columns // 1. calculate sum of constrained column widths // 2. calculate sum of unconstrained column minimal widths $sum_cw = 0; $sum_ucw = 0; for ($i=0; $i < $columns; $i++) { if ($table->is_constrained_column($i)) { $sum_cw += $widths[$i]; } else { $sum_ucw += $minwc[$i]; } } // 3. compare these widths with the table width and choose the maximal value $width = max($width, $sum_cw + $sum_ucw); // Second pass - disctribute the rest of the width // Explanation of the stuff below (I've really had problems with this small piece of code, especially // when I was trying to fix "bugs" inside it) // // First of all, no column can be narrower than it minimal width (determined by its content) // Note that constrained columns have their widths distributed above, so we can exclude them for now // (just throw them out and imagine that table does not contain any width-constrained cols) // // Second, the relative widths of columns will have _appoximately_ the same ratio as // their maximal content widths. (In exception of cases where the first rule will take place - // say for the table containing two columns with the VERY long text in the first and one or two words // in the second) // // In general, this approach can be inoptimal in case of _very_ different font sizes // inside the cells, of, say big images; nevertheless, it will give a good approximate // AND still fast enough (unlike fully correct methods involving evaluation of the content height of the cell) // // Thus, we do the following: // - calculate the ratio of current column MAXIMAL ($current_max) width to the sum of MAXIMAL widths of all columns left // (inluding current) second rule applied. Note that we need remember about column spans and select // maxw or maxwc in order. // - then check if the rest of width will be too small for other columns to fit and decrease current columns // width (see MIN function call) // - then check again if our width will be too small for current column to fit (and expand if nesessary) - // MAX function call for ($i=0; $i < $columns; $i++) { if (!$table->is_constrained_column($i)) { // Get undistributed width (total table width - width of constrained columns) $rest = $width - array_sum($widths); // get max width of column being processed // If width is equal to zero, use max constrained width, as this column could be covered by colspan; // If not, we lose nothing, because all constrained columns are already processed earlier, and no more // columns except these two types can have different constrained and raw widths $current_max = max($maxw[$i], $maxwc[$i]); // Get sum of maximal constrained widths of unplaced columns $sum_max_cw = 0; $sum_min_cw = 0; for ($j=0; $j<$columns; $j++) { if (!isset($widths[$j])) { $sum_max_cw += max($maxw[$j], $maxwc[$j]); $sum_min_cw += max($minw[$j], $minwc[$j]); }; }; // If some unplaced columns have maximal (constrained width) greater zero if ($sum_max_cw > 0) { $current_max = min($current_max * $rest / $sum_max_cw, $rest - $sum_min_cw + max($minwc[$i], $minw[$i])); }; // Check for minimal width (either unconstrained or constrained) of current column $current_max = max($current_max, $minw[$i] == 0 ? $minwc[$i] : $minw[$i]); // Store calculated width $widths[$i] = $current_max; } } // Process the case of a lone empty table cell (used, for example, for its background color) // as we're using floating point numbers, we cannot use equals sign if (array_sum($widths) < EPSILON) { for ($i=0; $i
TEXT // // e.g. empty column (with zero width) and fixed-width column. // $wc = $table->get_css_property(CSS_WIDTH); if (!$wc->isNull()) { if (array_sum($widths) < $width) { // Let's make zero-width columns // non-zero width (so that they columd be expanded) and re-try expanding columns // for ($i=0; $iget_non_constrained_width_flags(); if (!any_flag_set($flags)) { $flags = $table->get_non_constant_constrained_width_flags(); if (!any_flag_set($flags)) { $flags = $table->get_non_image_constrained_width_flags(); if (!any_flag_set($flags)) { for ($i=0; $iput_full_width(array_sum($widths)); // Now we need to sort array by key keeping key-value associations in order for array_slice to work correctly ksort($widths, SORT_NUMERIC); return $widths; } } ?>