Page MenuHomeIn-Portal Phabricator

pdf_table.php
No OneTemporary

File Metadata

Created
Sat, Sep 20, 4:00 PM

pdf_table.php

<?php
/**
* @version $Id: pdf_table.php 14244 2011-03-16 20:53:41Z alex $
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kPDFTableRow extends kPDFElement {
function LayoutChildren()
{
parent::LayoutChildren();
// http://manual.prod.intechnic.lv/css21/tables.html#height-layout
// vertical-alignment
$row_height = $this->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);
}
}

Event Timeline