PageRenderTime 36ms CodeModel.GetById 8ms RepoModel.GetById 1ms app.codeStats 0ms

/include/PHPExcel/Writer/PDF/include/frame_decorator.cls.php

https://bitbucket.org/ite/on-track-code-base
PHP | 562 lines | 299 code | 106 blank | 157 comment | 53 complexity | ba6bdc5199cd925bf540afa9180d4b40 MD5 | raw file
  1. <?php
  2. /**
  3. * @package dompdf
  4. * @link http://www.dompdf.com/
  5. * @author Benj Carson <benjcarson@digitaljunkies.ca>
  6. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  7. * @version $Id: frame_decorator.cls.php 464 2012-01-30 20:44:53Z fabien.menager $
  8. */
  9. /**
  10. * Base Frame_Decorator class
  11. *
  12. * @access private
  13. * @package dompdf
  14. */
  15. abstract class Frame_Decorator extends Frame {
  16. const DEFAULT_COUNTER = "-dompdf-default-counter";
  17. public $_counters = array(); // array([id] => counter_value) (for generated content)
  18. /**
  19. * The root node of the DOM tree
  20. *
  21. * @var Frame
  22. */
  23. protected $_root;
  24. /**
  25. * The decorated frame
  26. *
  27. * @var Frame
  28. */
  29. protected $_frame;
  30. /**
  31. * Positioner object used to position this frame (Strategy pattern)
  32. *
  33. * @var Positioner
  34. */
  35. protected $_positioner;
  36. /**
  37. * Reflower object used to calculate frame dimensions (Strategy pattern)
  38. *
  39. * @var Frame_Reflower
  40. */
  41. protected $_reflower;
  42. /**
  43. * Reference to the current dompdf instance
  44. *
  45. * @var DOMPDF
  46. */
  47. protected $_dompdf;
  48. /**
  49. * First block parent
  50. *
  51. * @var Block_Frame_Decorator
  52. */
  53. private $_block_parent;
  54. /**
  55. * First positionned parent (position: relative | absolute | fixed)
  56. *
  57. * @var Frame_Decorator
  58. */
  59. private $_positionned_parent;
  60. /**
  61. * Class constructor
  62. *
  63. * @param Frame $frame the decoration target
  64. */
  65. function __construct(Frame $frame, DOMPDF $dompdf) {
  66. $this->_frame = $frame;
  67. $this->_root = null;
  68. $this->_dompdf = $dompdf;
  69. $frame->set_decorator($this);
  70. }
  71. /**
  72. * "Destructor": foribly free all references held by this object
  73. *
  74. * @param bool $recursive if true, call dispose on all children
  75. */
  76. function dispose($recursive = false) {
  77. if ( $recursive ) {
  78. while ( $child = $this->get_first_child() )
  79. $child->dispose(true);
  80. }
  81. $this->_root = null;
  82. unset($this->_root);
  83. $this->_frame->dispose(true);
  84. $this->_frame = null;
  85. unset($this->_frame);
  86. $this->_positioner = null;
  87. unset($this->_positioner);
  88. $this->_reflower = null;
  89. unset($this->_reflower);
  90. }
  91. /**
  92. * Return a copy of this frame with $node as its node
  93. *
  94. * @param DomNode $node
  95. * @return Frame
  96. */
  97. function copy(DomNode $node) {
  98. $frame = new Frame($node);
  99. $frame->set_style(clone $this->_frame->get_original_style());
  100. $deco = Frame_Factory::decorate_frame($frame, $this->_dompdf);
  101. $deco->set_root($this->_root);
  102. return $deco;
  103. }
  104. /**
  105. * Create a deep copy: copy this node and all children
  106. *
  107. * @return Frame
  108. */
  109. function deep_copy() {
  110. $frame = new Frame($this->get_node()->cloneNode());
  111. $frame->set_style(clone $this->_frame->get_original_style());
  112. $deco = Frame_Factory::decorate_frame($frame, $this->_dompdf);
  113. $deco->set_root($this->_root);
  114. foreach ($this->get_children() as $child)
  115. $deco->append_child($child->deep_copy());
  116. return $deco;
  117. }
  118. //........................................................................
  119. /**
  120. * Delegate calls to decorated frame object
  121. */
  122. function reset() {
  123. $this->_frame->reset();
  124. $this->_counters = array();
  125. // Reset all children
  126. foreach ($this->get_children() as $child)
  127. $child->reset();
  128. }
  129. // Getters -----------
  130. function get_id() { return $this->_frame->get_id(); }
  131. /**
  132. * @return Frame
  133. */
  134. function get_frame() { return $this->_frame; }
  135. /**
  136. * @return DomNode
  137. */
  138. function get_node() { return $this->_frame->get_node(); }
  139. /**
  140. * @return Style
  141. */
  142. function get_style() { return $this->_frame->get_style(); }
  143. /**
  144. * @return Style
  145. */
  146. function get_original_style() { return $this->_frame->get_original_style(); }
  147. function get_containing_block($i = null) { return $this->_frame->get_containing_block($i); }
  148. function get_position($i = null) { return $this->_frame->get_position($i); }
  149. /**
  150. * @return DOMPDF
  151. */
  152. function get_dompdf() { return $this->_dompdf; }
  153. function get_margin_height() { return $this->_frame->get_margin_height(); }
  154. function get_margin_width() { return $this->_frame->get_margin_width(); }
  155. function get_padding_box() { return $this->_frame->get_padding_box(); }
  156. function get_border_box() { return $this->_frame->get_border_box(); }
  157. // Setters -----------
  158. function set_id($id) { $this->_frame->set_id($id); }
  159. function set_style(Style $style) { $this->_frame->set_style($style); }
  160. function set_containing_block($x = null, $y = null, $w = null, $h = null) {
  161. $this->_frame->set_containing_block($x, $y, $w, $h);
  162. }
  163. function set_position($x = null, $y = null) {
  164. $this->_frame->set_position($x, $y);
  165. }
  166. function __toString() { return $this->_frame->__toString(); }
  167. function prepend_child(Frame $child, $update_node = true) {
  168. while ( $child instanceof Frame_Decorator )
  169. $child = $child->_frame;
  170. $this->_frame->prepend_child($child, $update_node);
  171. }
  172. function append_child(Frame $child, $update_node = true) {
  173. while ( $child instanceof Frame_Decorator )
  174. $child = $child->_frame;
  175. $this->_frame->append_child($child, $update_node);
  176. }
  177. function insert_child_before(Frame $new_child, Frame $ref, $update_node = true) {
  178. while ( $new_child instanceof Frame_Decorator )
  179. $new_child = $new_child->_frame;
  180. if ( $ref instanceof Frame_Decorator )
  181. $ref = $ref->_frame;
  182. $this->_frame->insert_child_before($new_child, $ref, $update_node);
  183. }
  184. function insert_child_after(Frame $new_child, Frame $ref, $update_node = true) {
  185. while ( $new_child instanceof Frame_Decorator )
  186. $new_child = $new_child->_frame;
  187. while ( $ref instanceof Frame_Decorator )
  188. $ref = $ref->_frame;
  189. $this->_frame->insert_child_after($new_child, $ref, $update_node);
  190. }
  191. function remove_child(Frame $child, $update_node = true) {
  192. while ( $child instanceof Frame_Decorator )
  193. $child = $new_child->_frame;
  194. $this->_frame->remove_child($child, $update_node);
  195. }
  196. //........................................................................
  197. /**
  198. * @return Frame_Decorator
  199. */
  200. function get_parent() {
  201. $p = $this->_frame->get_parent();
  202. if ( $p && $deco = $p->get_decorator() ) {
  203. while ( $tmp = $deco->get_decorator() )
  204. $deco = $tmp;
  205. return $deco;
  206. } else if ( $p )
  207. return $p;
  208. else
  209. return null;
  210. }
  211. /**
  212. * @return Frame_Decorator
  213. */
  214. function get_first_child() {
  215. $c = $this->_frame->get_first_child();
  216. if ( $c && $deco = $c->get_decorator() ) {
  217. while ( $tmp = $deco->get_decorator() )
  218. $deco = $tmp;
  219. return $deco;
  220. } else if ( $c )
  221. return $c;
  222. else
  223. return null;
  224. }
  225. /**
  226. * @return Frame_Decorator
  227. */
  228. function get_last_child() {
  229. $c = $this->_frame->get_last_child();
  230. if ( $c && $deco = $c->get_decorator() ) {
  231. while ( $tmp = $deco->get_decorator() )
  232. $deco = $tmp;
  233. return $deco;
  234. } else if ( $c )
  235. return $c;
  236. else
  237. return null;
  238. }
  239. /**
  240. * @return Frame_Decorator
  241. */
  242. function get_prev_sibling() {
  243. $s = $this->_frame->get_prev_sibling();
  244. if ( $s && $deco = $s->get_decorator() ) {
  245. while ( $tmp = $deco->get_decorator() )
  246. $deco = $tmp;
  247. return $deco;
  248. } else if ( $s )
  249. return $s;
  250. else
  251. return null;
  252. }
  253. /**
  254. * @return Frame_Decorator
  255. */
  256. function get_next_sibling() {
  257. $s = $this->_frame->get_next_sibling();
  258. if ( $s && $deco = $s->get_decorator() ) {
  259. while ( $tmp = $deco->get_decorator() )
  260. $deco = $tmp;
  261. return $deco;
  262. } else if ( $s )
  263. return $s;
  264. else
  265. return null;
  266. }
  267. /**
  268. * @return FrameTreeList
  269. */
  270. function get_subtree() {
  271. return new FrameTreeList($this);
  272. }
  273. //........................................................................
  274. function set_positioner(Positioner $posn) {
  275. $this->_positioner = $posn;
  276. if ( $this->_frame instanceof Frame_Decorator )
  277. $this->_frame->set_positioner($posn);
  278. }
  279. //........................................................................
  280. function set_reflower(Frame_Reflower $reflower) {
  281. $this->_reflower = $reflower;
  282. if ( $this->_frame instanceof Frame_Decorator )
  283. $this->_frame->set_reflower( $reflower );
  284. }
  285. /**
  286. * @return Frame_Reflower
  287. */
  288. function get_reflower() { return $this->_reflower; }
  289. //........................................................................
  290. function set_root(Frame $root) {
  291. $this->_root = $root;
  292. if ( $this->_frame instanceof Frame_Decorator )
  293. $this->_frame->set_root($root);
  294. }
  295. /**
  296. * @return Page_Frame_Decorator
  297. */
  298. function get_root() { return $this->_root; }
  299. //........................................................................
  300. /**
  301. * @return Block_Frame_Decorator
  302. */
  303. function find_block_parent() {
  304. /*if ( $this->_block_parent && !isset($this->_block_parent->_splitted) ) {
  305. return $this->_block_parent;
  306. }*/
  307. // Find our nearest block level parent
  308. $p = $this->get_parent();
  309. while ( $p ) {
  310. if ( $p->is_block() ) break;
  311. $p = $p->get_parent();
  312. }
  313. return $this->_block_parent = $p;
  314. }
  315. /**
  316. * @return Frame_Decorator
  317. */
  318. function find_positionned_parent() {
  319. /*if ( $this->_positionned_parent && !isset($this->_block_parent->_splitted) ) {
  320. return $this->_positionned_parent;
  321. }*/
  322. // Find our nearest relative positionned parent
  323. $p = $this->get_parent();
  324. while ( $p ) {
  325. if ( $p->is_positionned() ) break;
  326. $p = $p->get_parent();
  327. }
  328. if ( !$p ) {
  329. $p = $this->_root->get_first_child(); // <body>
  330. }
  331. return $this->_positionned_parent = $p;
  332. }
  333. //........................................................................
  334. /**
  335. * split this frame at $child.
  336. *
  337. * The current frame is cloned and $child and all children following
  338. * $child are added to the clone. The clone is then passed to the
  339. * current frame's parent->split() method.
  340. *
  341. * @param Frame $child
  342. * @param boolean $force_pagebreak
  343. */
  344. function split($child = null, $force_pagebreak = false) {
  345. if ( is_null( $child ) ) {
  346. $this->get_parent()->split($this, $force_pagebreak);
  347. return;
  348. }
  349. if ( $child->get_parent() !== $this )
  350. throw new DOMPDF_Exception("Unable to split: frame is not a child of this one.");
  351. $node = $this->_frame->get_node();
  352. // mark the frame as splitted (don't use the find_***_parent cache)
  353. //$this->_splitted = true;
  354. $split = $this->copy( $node->cloneNode() );
  355. $split->reset();
  356. $split->get_original_style()->text_indent = 0;
  357. // The body's properties must be kept
  358. if ( $node->nodeName !== "body" ) {
  359. // Style reset on the first and second parts
  360. $style = $this->_frame->get_style();
  361. $style->margin_bottom = 0;
  362. $style->padding_bottom = 0;
  363. $style->border_bottom = 0;
  364. // second
  365. $orig_style = $split->get_original_style();
  366. $orig_style->text_indent = 0;
  367. $orig_style->margin_top = 0;
  368. $orig_style->padding_top = 0;
  369. $orig_style->border_top = 0;
  370. }
  371. $this->get_parent()->insert_child_after($split, $this);
  372. // Add $frame and all following siblings to the new split node
  373. $iter = $child;
  374. while ($iter) {
  375. $frame = $iter;
  376. $iter = $iter->get_next_sibling();
  377. $frame->reset();
  378. $split->append_child($frame);
  379. }
  380. $this->get_parent()->split($split, $force_pagebreak);
  381. }
  382. function reset_counter($id = self::DEFAULT_COUNTER, $value = 0) {
  383. $this->get_parent()->_counters[$id] = $value;
  384. }
  385. function increment_counters($counters) {
  386. foreach($counters as $id => $increment) {
  387. $this->increment_counter($id, $increment);
  388. }
  389. }
  390. function increment_counter($id = self::DEFAULT_COUNTER, $increment = 1) {
  391. $counter_frame = $this->lookup_counter_frame($id);
  392. if ( $counter_frame ) {
  393. if ( !isset($counter_frame->_counters[$id]) ) {
  394. $counter_frame->_counters[$id] = 0;
  395. }
  396. $counter_frame->_counters[$id] += $increment;
  397. }
  398. }
  399. function lookup_counter_frame($id = self::DEFAULT_COUNTER) {
  400. $f = $this->get_parent();
  401. while( $f ) {
  402. if( isset($f->_counters[$id]) ) {
  403. return $f;
  404. }
  405. $fp = $f->get_parent();
  406. if ( !$fp ) {
  407. return $f;
  408. }
  409. $f = $fp;
  410. }
  411. }
  412. // TODO: What version is the best : this one or the one in List_Bullet_Renderer ?
  413. function counter_value($id = self::DEFAULT_COUNTER, $type = "decimal") {
  414. $type = mb_strtolower($type);
  415. if ( !isset($this->_counters[$id]) ) {
  416. $value = $this->_counters[$id] = 0;
  417. }
  418. else {
  419. $value = $this->_counters[$id];
  420. }
  421. switch ($type) {
  422. default:
  423. case "decimal":
  424. return $value;
  425. case "decimal-leading-zero":
  426. return str_pad($value, 2, "0");
  427. case "lower-roman":
  428. return dec2roman($value);
  429. case "upper-roman":
  430. return mb_strtoupper(dec2roman($value));
  431. case "lower-latin":
  432. case "lower-alpha":
  433. return chr( ($value % 26) + ord('a') - 1);
  434. case "upper-latin":
  435. case "upper-alpha":
  436. return chr( ($value % 26) + ord('A') - 1);
  437. case "lower-greek":
  438. return unichr($value + 944);
  439. case "upper-greek":
  440. return unichr($value + 912);
  441. }
  442. }
  443. //........................................................................
  444. final function position() { $this->_positioner->position(); }
  445. final function move($offset_x, $offset_y, $ignore_self = false) {
  446. $this->_positioner->move($offset_x, $offset_y, $ignore_self);
  447. }
  448. final function reflow(Frame_Decorator $block = null) {
  449. // Uncomment this to see the frames before they're laid out, instead of
  450. // during rendering.
  451. //echo $this->_frame; flush();
  452. $this->_reflower->reflow($block);
  453. }
  454. final function get_min_max_width() { return $this->_reflower->get_min_max_width(); }
  455. //........................................................................
  456. }