/include/PHPExcel/Writer/PDF/include/frame_decorator.cls.php
PHP | 562 lines | 299 code | 106 blank | 157 comment | 53 complexity | ba6bdc5199cd925bf540afa9180d4b40 MD5 | raw file
- <?php
- /**
- * @package dompdf
- * @link http://www.dompdf.com/
- * @author Benj Carson <benjcarson@digitaljunkies.ca>
- * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
- * @version $Id: frame_decorator.cls.php 464 2012-01-30 20:44:53Z fabien.menager $
- */
- /**
- * Base Frame_Decorator class
- *
- * @access private
- * @package dompdf
- */
- abstract class Frame_Decorator extends Frame {
- const DEFAULT_COUNTER = "-dompdf-default-counter";
-
- public $_counters = array(); // array([id] => counter_value) (for generated content)
-
- /**
- * The root node of the DOM tree
- *
- * @var Frame
- */
- protected $_root;
- /**
- * The decorated frame
- *
- * @var Frame
- */
- protected $_frame;
- /**
- * Positioner object used to position this frame (Strategy pattern)
- *
- * @var Positioner
- */
- protected $_positioner;
- /**
- * Reflower object used to calculate frame dimensions (Strategy pattern)
- *
- * @var Frame_Reflower
- */
- protected $_reflower;
-
- /**
- * Reference to the current dompdf instance
- *
- * @var DOMPDF
- */
- protected $_dompdf;
-
- /**
- * First block parent
- *
- * @var Block_Frame_Decorator
- */
- private $_block_parent;
-
- /**
- * First positionned parent (position: relative | absolute | fixed)
- *
- * @var Frame_Decorator
- */
- private $_positionned_parent;
- /**
- * Class constructor
- *
- * @param Frame $frame the decoration target
- */
- function __construct(Frame $frame, DOMPDF $dompdf) {
- $this->_frame = $frame;
- $this->_root = null;
- $this->_dompdf = $dompdf;
- $frame->set_decorator($this);
- }
- /**
- * "Destructor": foribly free all references held by this object
- *
- * @param bool $recursive if true, call dispose on all children
- */
- function dispose($recursive = false) {
-
- if ( $recursive ) {
- while ( $child = $this->get_first_child() )
- $child->dispose(true);
- }
-
- $this->_root = null;
- unset($this->_root);
-
- $this->_frame->dispose(true);
- $this->_frame = null;
- unset($this->_frame);
-
- $this->_positioner = null;
- unset($this->_positioner);
-
- $this->_reflower = null;
- unset($this->_reflower);
- }
- /**
- * Return a copy of this frame with $node as its node
- *
- * @param DomNode $node
- * @return Frame
- */
- function copy(DomNode $node) {
- $frame = new Frame($node);
- $frame->set_style(clone $this->_frame->get_original_style());
- $deco = Frame_Factory::decorate_frame($frame, $this->_dompdf);
- $deco->set_root($this->_root);
- return $deco;
- }
- /**
- * Create a deep copy: copy this node and all children
- *
- * @return Frame
- */
- function deep_copy() {
- $frame = new Frame($this->get_node()->cloneNode());
- $frame->set_style(clone $this->_frame->get_original_style());
- $deco = Frame_Factory::decorate_frame($frame, $this->_dompdf);
- $deco->set_root($this->_root);
- foreach ($this->get_children() as $child)
- $deco->append_child($child->deep_copy());
- return $deco;
- }
- //........................................................................
-
- /**
- * Delegate calls to decorated frame object
- */
- function reset() {
- $this->_frame->reset();
-
- $this->_counters = array();
- // Reset all children
- foreach ($this->get_children() as $child)
- $child->reset();
- }
-
- // Getters -----------
- function get_id() { return $this->_frame->get_id(); }
-
- /**
- * @return Frame
- */
- function get_frame() { return $this->_frame; }
-
- /**
- * @return DomNode
- */
- function get_node() { return $this->_frame->get_node(); }
-
- /**
- * @return Style
- */
- function get_style() { return $this->_frame->get_style(); }
-
- /**
- * @return Style
- */
- function get_original_style() { return $this->_frame->get_original_style(); }
- function get_containing_block($i = null) { return $this->_frame->get_containing_block($i); }
- function get_position($i = null) { return $this->_frame->get_position($i); }
-
- /**
- * @return DOMPDF
- */
- function get_dompdf() { return $this->_dompdf; }
-
- function get_margin_height() { return $this->_frame->get_margin_height(); }
- function get_margin_width() { return $this->_frame->get_margin_width(); }
- function get_padding_box() { return $this->_frame->get_padding_box(); }
- function get_border_box() { return $this->_frame->get_border_box(); }
- // Setters -----------
- function set_id($id) { $this->_frame->set_id($id); }
- function set_style(Style $style) { $this->_frame->set_style($style); }
- function set_containing_block($x = null, $y = null, $w = null, $h = null) {
- $this->_frame->set_containing_block($x, $y, $w, $h);
- }
- function set_position($x = null, $y = null) {
- $this->_frame->set_position($x, $y);
- }
- function __toString() { return $this->_frame->__toString(); }
-
- function prepend_child(Frame $child, $update_node = true) {
- while ( $child instanceof Frame_Decorator )
- $child = $child->_frame;
-
- $this->_frame->prepend_child($child, $update_node);
- }
- function append_child(Frame $child, $update_node = true) {
- while ( $child instanceof Frame_Decorator )
- $child = $child->_frame;
- $this->_frame->append_child($child, $update_node);
- }
- function insert_child_before(Frame $new_child, Frame $ref, $update_node = true) {
- while ( $new_child instanceof Frame_Decorator )
- $new_child = $new_child->_frame;
- if ( $ref instanceof Frame_Decorator )
- $ref = $ref->_frame;
- $this->_frame->insert_child_before($new_child, $ref, $update_node);
- }
- function insert_child_after(Frame $new_child, Frame $ref, $update_node = true) {
- while ( $new_child instanceof Frame_Decorator )
- $new_child = $new_child->_frame;
- while ( $ref instanceof Frame_Decorator )
- $ref = $ref->_frame;
-
- $this->_frame->insert_child_after($new_child, $ref, $update_node);
- }
- function remove_child(Frame $child, $update_node = true) {
- while ( $child instanceof Frame_Decorator )
- $child = $new_child->_frame;
- $this->_frame->remove_child($child, $update_node);
- }
-
- //........................................................................
- /**
- * @return Frame_Decorator
- */
- function get_parent() {
- $p = $this->_frame->get_parent();
- if ( $p && $deco = $p->get_decorator() ) {
- while ( $tmp = $deco->get_decorator() )
- $deco = $tmp;
- return $deco;
- } else if ( $p )
- return $p;
- else
- return null;
- }
- /**
- * @return Frame_Decorator
- */
- function get_first_child() {
- $c = $this->_frame->get_first_child();
- if ( $c && $deco = $c->get_decorator() ) {
- while ( $tmp = $deco->get_decorator() )
- $deco = $tmp;
- return $deco;
- } else if ( $c )
- return $c;
- else
- return null;
- }
- /**
- * @return Frame_Decorator
- */
- function get_last_child() {
- $c = $this->_frame->get_last_child();
- if ( $c && $deco = $c->get_decorator() ) {
- while ( $tmp = $deco->get_decorator() )
- $deco = $tmp;
- return $deco;
- } else if ( $c )
- return $c;
- else
- return null;
- }
- /**
- * @return Frame_Decorator
- */
- function get_prev_sibling() {
- $s = $this->_frame->get_prev_sibling();
- if ( $s && $deco = $s->get_decorator() ) {
- while ( $tmp = $deco->get_decorator() )
- $deco = $tmp;
- return $deco;
- } else if ( $s )
- return $s;
- else
- return null;
- }
-
- /**
- * @return Frame_Decorator
- */
- function get_next_sibling() {
- $s = $this->_frame->get_next_sibling();
- if ( $s && $deco = $s->get_decorator() ) {
- while ( $tmp = $deco->get_decorator() )
- $deco = $tmp;
- return $deco;
- } else if ( $s )
- return $s;
- else
- return null;
- }
- /**
- * @return FrameTreeList
- */
- function get_subtree() {
- return new FrameTreeList($this);
- }
-
- //........................................................................
- function set_positioner(Positioner $posn) {
- $this->_positioner = $posn;
- if ( $this->_frame instanceof Frame_Decorator )
- $this->_frame->set_positioner($posn);
- }
-
- //........................................................................
- function set_reflower(Frame_Reflower $reflower) {
- $this->_reflower = $reflower;
- if ( $this->_frame instanceof Frame_Decorator )
- $this->_frame->set_reflower( $reflower );
- }
-
- /**
- * @return Frame_Reflower
- */
- function get_reflower() { return $this->_reflower; }
-
- //........................................................................
-
- function set_root(Frame $root) {
- $this->_root = $root;
- if ( $this->_frame instanceof Frame_Decorator )
- $this->_frame->set_root($root);
- }
-
- /**
- * @return Page_Frame_Decorator
- */
- function get_root() { return $this->_root; }
-
- //........................................................................
- /**
- * @return Block_Frame_Decorator
- */
- function find_block_parent() {
- /*if ( $this->_block_parent && !isset($this->_block_parent->_splitted) ) {
- return $this->_block_parent;
- }*/
-
- // Find our nearest block level parent
- $p = $this->get_parent();
-
- while ( $p ) {
- if ( $p->is_block() ) break;
- $p = $p->get_parent();
- }
- return $this->_block_parent = $p;
- }
-
- /**
- * @return Frame_Decorator
- */
- function find_positionned_parent() {
- /*if ( $this->_positionned_parent && !isset($this->_block_parent->_splitted) ) {
- return $this->_positionned_parent;
- }*/
- // Find our nearest relative positionned parent
- $p = $this->get_parent();
- while ( $p ) {
- if ( $p->is_positionned() ) break;
- $p = $p->get_parent();
- }
-
- if ( !$p ) {
- $p = $this->_root->get_first_child(); // <body>
- }
- return $this->_positionned_parent = $p;
- }
- //........................................................................
- /**
- * split this frame at $child.
- *
- * The current frame is cloned and $child and all children following
- * $child are added to the clone. The clone is then passed to the
- * current frame's parent->split() method.
- *
- * @param Frame $child
- * @param boolean $force_pagebreak
- */
- function split($child = null, $force_pagebreak = false) {
- if ( is_null( $child ) ) {
- $this->get_parent()->split($this, $force_pagebreak);
- return;
- }
- if ( $child->get_parent() !== $this )
- throw new DOMPDF_Exception("Unable to split: frame is not a child of this one.");
- $node = $this->_frame->get_node();
-
- // mark the frame as splitted (don't use the find_***_parent cache)
- //$this->_splitted = true;
-
- $split = $this->copy( $node->cloneNode() );
- $split->reset();
- $split->get_original_style()->text_indent = 0;
-
- // The body's properties must be kept
- if ( $node->nodeName !== "body" ) {
- // Style reset on the first and second parts
- $style = $this->_frame->get_style();
- $style->margin_bottom = 0;
- $style->padding_bottom = 0;
- $style->border_bottom = 0;
-
- // second
- $orig_style = $split->get_original_style();
- $orig_style->text_indent = 0;
- $orig_style->margin_top = 0;
- $orig_style->padding_top = 0;
- $orig_style->border_top = 0;
- }
-
- $this->get_parent()->insert_child_after($split, $this);
- // Add $frame and all following siblings to the new split node
- $iter = $child;
- while ($iter) {
- $frame = $iter;
- $iter = $iter->get_next_sibling();
- $frame->reset();
- $split->append_child($frame);
- }
- $this->get_parent()->split($split, $force_pagebreak);
- }
- function reset_counter($id = self::DEFAULT_COUNTER, $value = 0) {
- $this->get_parent()->_counters[$id] = $value;
- }
-
- function increment_counters($counters) {
- foreach($counters as $id => $increment) {
- $this->increment_counter($id, $increment);
- }
- }
- function increment_counter($id = self::DEFAULT_COUNTER, $increment = 1) {
- $counter_frame = $this->lookup_counter_frame($id);
- if ( $counter_frame ) {
- if ( !isset($counter_frame->_counters[$id]) ) {
- $counter_frame->_counters[$id] = 0;
- }
-
- $counter_frame->_counters[$id] += $increment;
- }
- }
-
- function lookup_counter_frame($id = self::DEFAULT_COUNTER) {
- $f = $this->get_parent();
-
- while( $f ) {
- if( isset($f->_counters[$id]) ) {
- return $f;
- }
- $fp = $f->get_parent();
-
- if ( !$fp ) {
- return $f;
- }
-
- $f = $fp;
- }
- }
- // TODO: What version is the best : this one or the one in List_Bullet_Renderer ?
- function counter_value($id = self::DEFAULT_COUNTER, $type = "decimal") {
- $type = mb_strtolower($type);
-
- if ( !isset($this->_counters[$id]) ) {
- $value = $this->_counters[$id] = 0;
- }
- else {
- $value = $this->_counters[$id];
- }
-
- switch ($type) {
- default:
- case "decimal":
- return $value;
- case "decimal-leading-zero":
- return str_pad($value, 2, "0");
- case "lower-roman":
- return dec2roman($value);
- case "upper-roman":
- return mb_strtoupper(dec2roman($value));
- case "lower-latin":
- case "lower-alpha":
- return chr( ($value % 26) + ord('a') - 1);
- case "upper-latin":
- case "upper-alpha":
- return chr( ($value % 26) + ord('A') - 1);
- case "lower-greek":
- return unichr($value + 944);
- case "upper-greek":
- return unichr($value + 912);
- }
- }
- //........................................................................
- final function position() { $this->_positioner->position(); }
-
- final function move($offset_x, $offset_y, $ignore_self = false) {
- $this->_positioner->move($offset_x, $offset_y, $ignore_self);
- }
-
- final function reflow(Frame_Decorator $block = null) {
- // Uncomment this to see the frames before they're laid out, instead of
- // during rendering.
- //echo $this->_frame; flush();
- $this->_reflower->reflow($block);
- }
- final function get_min_max_width() { return $this->_reflower->get_min_max_width(); }
-
- //........................................................................
- }