GetCSSProperty('height'); if ($row_height == 'auto') { $row_height = 0; } $baseline = 0; foreach ($this->Children as $elem) { if ($elem->GetCSSProperty('vertical-align') == 'baseline') { // $ascent = $elem->FindChild('_LINE_')->Ascent; $ascent = $elem->FirstChild->Ascent; if ($ascent > $baseline) { $baseline = $ascent; } } $dim = $elem->GetBoxDimensions(); $elem_height = $dim[1]; if ($elem_height > $row_height) { $row_height = $elem_height; } } foreach ($this->Children as $elem) { $vertical_align = $elem->GetCSSProperty('vertical-align'); $dim = $elem->GetBoxDimensions(); $elem_height = $dim[1]; $add_top = 0; $add_bottom = 0; if ($vertical_align == 'top') { $add_bottom = $row_height - $elem_height; } elseif ($vertical_align == 'middle') { $add_top = ($row_height - $elem_height)/2; $add_bottom = $add_top; } elseif ($vertical_align == 'bottom') { $add_top = $row_height - $elem_height; } else { // baseline and all other if ($elem->Ascent < $baseline) { $add_top = $baseline - $elem->Ascent; } $add_bottom = $row_height - $elem_height - $add_top; } $elem->SetCSSProperty('padding-top', $elem->GetCSSProperty('padding-top') + $add_top); $elem->SetCSSProperty('padding-bottom', $elem->GetCSSProperty('padding-bottom') + $add_bottom); } } } class kPDFTable extends kPDFElement { public $InitialMode = null; public $Table = array(); public $TableBuild = false; public $CurCol = 0; public $CurRow = 0; public $ColWidths = array(); function __construct($node, $helper) { parent::__construct($node, $helper); } function Init() { parent::Init(); $this->InitialMode = $this->Helper->DimensionsMode; $this->Helper->DimensionsMode = kPDFHelper::DM_SKIP; } function Closed() { $this->BuildTable($this); parent::Closed(); /*$this->Helper->DimensionsMode = kPDFHelper::DM_NORMAL ; // $this->LayoutChildren(); $this->Helper->DimensionsMode = $this->InitialMode;*/ } function ComputeWidthAndMargins() { if (!$this->TableBuild || !$this->GetContainingBlock()->WidthComputed || $this->WidthComputed) return ; $this->ComputeCSSProperty('WIDTH', $this->CSSSpecifiedProperties['WIDTH']); if ($this->GetCSSProperty('table-layout') == 'fixed') { $this->CalculateWidthsFixed(); } if ($this->GetCSSProperty('table-layout') == 'auto') { $this->CalculateWidthsAuto(); //CalculateWidthsAuto(); } $this->WidthComputed = true; } function CalculateWidthsFixed() { if (count($this->Table) == 0) return ; $specified_width = 0; $specified_count = 0; $i = 0; foreach ($this->Table[1] as $cell) { $i++; $cur_w = $cell->GetCSSProperty('width'); $colspan = isset($cell->Node->Attributes['COLSPAN']) ? $cell->Node->Attributes['COLSPAN'] : 1; if ($cur_w != 'auto') { $specified_width += $cur_w; $specified_count += $colspan; $cur_w = $cur_w/$colspan; } for ($col=$i; $col < $i+$colspan; $col++) { $this->ColWidths[$col] = $cur_w; } $i += $colspan-1; } $max_cols = $i; $remaining_w = $this->GetCSSProperty('width') - $specified_width; $auto_width = $remaining_w/($max_cols-$specified_count); foreach ($this->ColWidths as $i => $width) { if ($width == 'auto') { $this->ColWidths[$i] = $auto_width; } } $this->SetColWidths($max_cols); } function SetColWidths($max_cols) { foreach ($this->Table as $row) { $i = 0; foreach ($row as $cell) { $i++; if ($i > $max_cols) { break; } $cell_extra_width = $cell->GetCSSProperty('border-left-width') + $cell->GetCSSProperty('padding-left') + $cell->GetCSSProperty('padding-right') + $cell->GetCSSProperty('border-right-width'); if (isset($cell->Node->Attributes['COLSPAN'])) { $colspan = $cell->Node->Attributes['COLSPAN']; $z = $i; $width = 0; do { $width += $this->ColWidths[$z]; } while ($z++ < $i+$colspan-1); // $width = array_sum( array_slice($this->ColWidths, $i-1, $colspan) ); $i += $colspan-1; } else { $width = $this->ColWidths[$i]; } $cell->SetCSSProperty('width', $width - $cell_extra_width); $cell->WidthComputed = true; } } $this->SetCSSProperty('width', array_sum($this->ColWidths)); } function BuildTable($node) { $this->ColWidths = array(); foreach ($node->Children as $child) { if ($child->GetCSSProperty('display') == 'table-row') { $this->CurRow++; $this->CurCol = 0; } if ($child->GetCSSProperty('display') == 'table-cell') { $this->CurCol++; $this->Table[$this->CurRow][$this->CurCol] = $child; if (isset($child->Node->Attributes['COLSPAN'])) { $this->CurCol += $child->Node->Attributes['COLSPAN']-1; } } else { // otherwise it will find all nested table cells $this->BuildTable($child); } } $this->TableBuild = true; } function CalculateWidthsAuto() { if (count($this->Table) == 0) return ; $min_col_widths = array(); $max_col_widths = array(); $specified_widths = array(); $percent_widths = array(); $row = 0; $max_cols = 0; foreach ($this->Table as $row) { $row++; $col = 0; foreach ($row as $cell) { $col++; $cell_w = $cell->GetCSSProperty('width'); $percent_w = false; if (preg_match('/([.0-9]+)%/', $cell_w, $regs)) { $percent_w = $regs[1]; } $min_cw = $cell_w == 'auto' && !$percent_w ? $cell->MinContentWidth : max($cell_w, $cell->MinContentWidth); $max_cw = $cell->MaxContentWidth; if ($cell_w != 'auto' && is_numeric($cell_w)) { if ($cell_w < $min_cw) { $cell_w = $min_cw; } if (!isset($specified_widths[$col]) || $cell_w > $specified_widths[$col]) { $specified_widths[$col] = $cell_w; } } $colspan = isset($cell->Node->Attributes['COLSPAN']) ? $cell->Node->Attributes['COLSPAN'] : 1; if ($colspan == 1) { if (!isset($min_col_widths[$col]) || $min_cw > $min_col_widths[$col]) { $min_col_widths[$col] = $min_cw; } if (!isset($max_col_widths[$col]) || $max_cw > $max_col_widths[$col]) { $max_col_widths[$col] = $max_cw; } if ($percent_w && (!isset($percent_widths[$col]) || $percent_w > $percent_widths[$col])) { $percent_widths[$col] = $percent_w; } } else { $spans_min = array_slice($min_col_widths, $col-1, $colspan); $spans_max = array_slice($max_col_widths, $col-1, $colspan); $spans_percent = array_slice($percent_widths, $col-1, $colspan); $min_diff = ($min_cw - array_sum($spans_min)); if ($min_diff > 0) { for($i=$col; $i < $col+$colspan; $i++) { if (!isset($min_col_widths[$i])) $min_col_widths[$i] = 0; $min_col_widths[$i] += $min_diff/$colspan; } } $max_diff = ($max_cw - array_sum($spans_max)); if ($max_diff > 0) { for($i=$col; $i < $col+$colspan; $i++) { if (!isset($max_col_widths[$i])) $max_col_widths[$i] = 0; $max_col_widths[$i] += $max_diff/$colspan; } } $percent_diff = ($percent_w - array_sum($spans_percent)); if ($percent_diff > 0) { for($i=$col; $i < $col+$colspan; $i++) { $percent_widths[$i] += $percent_diff/$colspan; } } $col += $colspan-1; } } if ($col > $max_cols) { $max_cols = $col; } } $table_min_width = array_sum($min_col_widths); $table_max_width = array_sum($max_col_widths) - $this->GetCSSProperty('border-left-width') - $this->GetCSSProperty('border-right-width'); $table_specifid_width = array_sum($specified_widths); $cb_width = $this->GetContainingBlock()->GetCSSProperty('width'); $computed_width = $this->ComputeCSSProperty('WIDTH', $this->GetCSSProperty('width')); if ($computed_width == 'auto') { $computed_width = $cb_width; } else { $computed_width -= $this->GetCSSProperty('border-left-width') + $this->GetCSSProperty('border-right-width'); } if ($this->CSSSpecifiedProperties['WIDTH'] == 'auto' && $table_max_width < $computed_width) { $width = $table_max_width; $this->ColWidths = $max_col_widths; } else { $width = max($table_min_width, $computed_width); // try to satisfy percent widths $reset_to_min = false; $percent_sum = 0; for ($i=1; $i<=$max_cols; $i++) { if (isset($percent_widths[$i])) { $adjusted_percent = $reset_to_min ? 0 : min($percent_widths[$i], 100-$percent_sum); $percent_sum += $adjusted_percent; if ($adjusted_percent > 0) { $min_col_widths[$i] = $width*$adjusted_percent/100; } } if ($percent_sum >= 100) { $reset_to_min = true; } } $distribute = $width - array_sum($min_col_widths); // recalc min width here, because of % changes $total_max = 0; for ($i=1; $i<=$max_cols; $i++) { if (isset($specified_widths[$i])) { $this->ColWidths[$i] = $specified_widths[$i]; // $distribute -= $specified_widths[$i]; continue; } else { $total_max += $max_col_widths[$i]; } } for ($i=1; $i<=$max_cols; $i++) { if (isset($this->ColWidths[$i])) { continue; } $coeff = isset($percent_widths[$i]) ? $percent_widths[$i] / $percent_sum : $max_col_widths[$i]/$total_max; $add = $coeff * $distribute; $this->ColWidths[$i] = $min_col_widths[$i] + $add; } } $this->SetColWidths($max_cols); } }