PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/include/block_frame_decorator.cls.php

https://bitbucket.org/netglue/dompdf
PHP | 234 lines | 111 code | 44 blank | 79 comment | 16 complexity | 6e54b34c6bf44ac895a9de6e6dd7dccd MD5 | raw file
Possible License(s): LGPL-2.1
  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. */
  8. /**
  9. * Decorates frames for block layout
  10. *
  11. * @access private
  12. * @package dompdf
  13. */
  14. class Block_Frame_Decorator extends Frame_Decorator {
  15. /**
  16. * Current line index
  17. *
  18. * @var int
  19. */
  20. protected $_cl;
  21. /**
  22. * The block's line boxes
  23. *
  24. * @var Line_Box[]
  25. */
  26. protected $_line_boxes;
  27. function __construct(Frame $frame, DOMPDF $dompdf) {
  28. parent::__construct($frame, $dompdf);
  29. $this->_line_boxes = array(new Line_Box($this));
  30. $this->_cl = 0;
  31. }
  32. function reset() {
  33. parent::reset();
  34. $this->_line_boxes = array(new Line_Box($this));
  35. $this->_cl = 0;
  36. }
  37. /**
  38. * @return Line_Box
  39. */
  40. function get_current_line_box() {
  41. return $this->_line_boxes[$this->_cl];
  42. }
  43. /**
  44. * @return integer
  45. */
  46. function get_current_line_number() {
  47. return $this->_cl;
  48. }
  49. /**
  50. * @return Line_Box[]
  51. */
  52. function get_line_boxes() {
  53. return $this->_line_boxes;
  54. }
  55. /**
  56. * @param integer $i
  57. */
  58. function clear_line($i) {
  59. if ( isset($this->_line_boxes[$i]) ) {
  60. unset($this->_line_boxes[$i]);
  61. }
  62. }
  63. /**
  64. * @param Frame $frame
  65. */
  66. function add_frame_to_line(Frame $frame) {
  67. if ( !$frame->is_in_flow() ) {
  68. return;
  69. }
  70. $style = $frame->get_style();
  71. $frame->set_containing_line($this->_line_boxes[$this->_cl]);
  72. /*
  73. // Adds a new line after a block, only if certain conditions are met
  74. if ((($frame instanceof Inline_Frame_Decorator && $frame->get_node()->nodeName !== "br") ||
  75. $frame instanceof Text_Frame_Decorator && trim($frame->get_text())) &&
  76. ($frame->get_prev_sibling() && $frame->get_prev_sibling()->get_style()->display === "block" &&
  77. $this->_line_boxes[$this->_cl]->w > 0 )) {
  78. $this->maximize_line_height( $style->length_in_pt($style->line_height), $frame );
  79. $this->add_line();
  80. // Add each child of the inline frame to the line individually
  81. foreach ($frame->get_children() as $child)
  82. $this->add_frame_to_line( $child );
  83. }
  84. else*/
  85. // Handle inline frames (which are effectively wrappers)
  86. if ( $frame instanceof Inline_Frame_Decorator ) {
  87. // Handle line breaks
  88. if ( $frame->get_node()->nodeName === "br" ) {
  89. $this->maximize_line_height( $style->length_in_pt($style->line_height), $frame );
  90. $this->add_line(true);
  91. }
  92. return;
  93. }
  94. // Trim leading text if this is an empty line. Kinda a hack to put it here,
  95. // but what can you do...
  96. if ( $this->get_current_line_box()->w == 0 &&
  97. $frame->is_text_node() &&
  98. !$frame->is_pre() ) {
  99. $frame->set_text( ltrim($frame->get_text()) );
  100. $frame->recalculate_width();
  101. }
  102. $w = $frame->get_margin_width();
  103. if ( $w == 0 ) {
  104. return;
  105. }
  106. // Debugging code:
  107. /*
  108. pre_r("\n<h3>Adding frame to line:</h3>");
  109. // pre_r("Me: " . $this->get_node()->nodeName . " (" . spl_object_hash($this->get_node()) . ")");
  110. // pre_r("Node: " . $frame->get_node()->nodeName . " (" . spl_object_hash($frame->get_node()) . ")");
  111. if ( $frame->is_text_node() )
  112. pre_r('"'.$frame->get_node()->nodeValue.'"');
  113. pre_r("Line width: " . $this->_line_boxes[$this->_cl]->w);
  114. pre_r("Frame: " . get_class($frame));
  115. pre_r("Frame width: " . $w);
  116. pre_r("Frame height: " . $frame->get_margin_height());
  117. pre_r("Containing block width: " . $this->get_containing_block("w"));
  118. */
  119. // End debugging
  120. $line = $this->_line_boxes[$this->_cl];
  121. if ( $line->left + $line->w + $line->right + $w > $this->get_containing_block("w")) {
  122. $this->add_line();
  123. }
  124. $frame->position();
  125. $current_line = $this->_line_boxes[$this->_cl];
  126. $current_line->add_frame($frame);
  127. if ( $frame->is_text_node() ) {
  128. $current_line->wc += count(preg_split("/\s+/", trim($frame->get_text())));
  129. }
  130. $this->increase_line_width($w);
  131. $this->maximize_line_height($frame->get_margin_height(), $frame);
  132. }
  133. function remove_frames_from_line(Frame $frame) {
  134. // Search backwards through the lines for $frame
  135. $i = $this->_cl;
  136. $j = null;
  137. while ($i >= 0) {
  138. if ( ($j = in_array($frame, $this->_line_boxes[$i]->get_frames(), true)) !== false ) {
  139. break;
  140. }
  141. $i--;
  142. }
  143. if ( $j === false ) {
  144. return;
  145. }
  146. // Remove $frame and all frames that follow
  147. while ($j < count($this->_line_boxes[$i]->get_frames())) {
  148. $frames = $this->_line_boxes[$i]->get_frames();
  149. $f = $frames[$j];
  150. $frames[$j] = null;
  151. unset($frames[$j]);
  152. $j++;
  153. $this->_line_boxes[$i]->w -= $f->get_margin_width();
  154. }
  155. // Recalculate the height of the line
  156. $h = 0;
  157. foreach ($this->_line_boxes[$i]->get_frames() as $f) {
  158. $h = max( $h, $f->get_margin_height() );
  159. }
  160. $this->_line_boxes[$i]->h = $h;
  161. // Remove all lines that follow
  162. while ($this->_cl > $i) {
  163. $this->_line_boxes[ $this->_cl ] = null;
  164. unset($this->_line_boxes[ $this->_cl ]);
  165. $this->_cl--;
  166. }
  167. }
  168. function increase_line_width($w) {
  169. $this->_line_boxes[ $this->_cl ]->w += $w;
  170. }
  171. function maximize_line_height($val, Frame $frame) {
  172. if ( $val > $this->_line_boxes[ $this->_cl ]->h ) {
  173. $this->_line_boxes[ $this->_cl ]->tallest_frame = $frame;
  174. $this->_line_boxes[ $this->_cl ]->h = $val;
  175. }
  176. }
  177. function add_line($br = false) {
  178. // if ( $this->_line_boxes[$this->_cl]["h"] == 0 ) //count($this->_line_boxes[$i]["frames"]) == 0 ||
  179. // return;
  180. $this->_line_boxes[$this->_cl]->br = $br;
  181. $y = $this->_line_boxes[$this->_cl]->y + $this->_line_boxes[$this->_cl]->h;
  182. $new_line = new Line_Box($this, $y);
  183. $this->_line_boxes[ ++$this->_cl ] = $new_line;
  184. }
  185. //........................................................................
  186. }