line_box.cls.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. <?php
  2. /**
  3. * @package dompdf
  4. * @link http://dompdf.github.com/
  5. * @author Fabien Ménager <fabien.menager@gmail.com>
  6. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  7. */
  8. /**
  9. * The line box class
  10. *
  11. * This class represents a line box
  12. * http://www.w3.org/TR/CSS2/visuren.html#line-box
  13. *
  14. * @access protected
  15. * @package dompdf
  16. */
  17. class Line_Box {
  18. /**
  19. * @var Block_Frame_Decorator
  20. */
  21. protected $_block_frame;
  22. /**
  23. * @var Frame[]
  24. */
  25. protected $_frames = array();
  26. /**
  27. * @var integer
  28. */
  29. public $wc = 0;
  30. /**
  31. * @var float
  32. */
  33. public $y = null;
  34. /**
  35. * @var float
  36. */
  37. public $w = 0.0;
  38. /**
  39. * @var float
  40. */
  41. public $h = 0.0;
  42. /**
  43. * @var float
  44. */
  45. public $left = 0.0;
  46. /**
  47. * @var float
  48. */
  49. public $right = 0.0;
  50. /**
  51. * @var Frame
  52. */
  53. public $tallest_frame = null;
  54. /**
  55. * @var bool[]
  56. */
  57. public $floating_blocks = array();
  58. /**
  59. * @var bool
  60. */
  61. public $br = false;
  62. /**
  63. * Class constructor
  64. *
  65. * @param Block_Frame_Decorator $frame the Block_Frame_Decorator containing this line
  66. */
  67. function __construct(Block_Frame_Decorator $frame, $y = 0) {
  68. $this->_block_frame = $frame;
  69. $this->_frames = array();
  70. $this->y = $y;
  71. $this->get_float_offsets();
  72. }
  73. /**
  74. * Returns the floating elements inside the first floating parent
  75. *
  76. * @param Page_Frame_Decorator $root
  77. *
  78. * @return Frame[]
  79. */
  80. function get_floats_inside(Page_Frame_Decorator $root) {
  81. $floating_frames = $root->get_floating_frames();
  82. if ( count($floating_frames) == 0 ) {
  83. return $floating_frames;
  84. }
  85. // Find nearest floating element
  86. $p = $this->_block_frame;
  87. while( $p->get_style()->float === "none" ) {
  88. $parent = $p->get_parent();
  89. if ( !$parent ) {
  90. break;
  91. }
  92. $p = $parent;
  93. }
  94. if ( $p == $root ) {
  95. return $floating_frames;
  96. }
  97. $parent = $p;
  98. $childs = array();
  99. foreach ($floating_frames as $_floating) {
  100. $p = $_floating->get_parent();
  101. while (($p = $p->get_parent()) && $p !== $parent);
  102. if ( $p ) {
  103. $childs[] = $p;
  104. }
  105. }
  106. return $childs;
  107. }
  108. function get_float_offsets() {
  109. $enable_css_float = $this->_block_frame->get_dompdf()->get_option("enable_css_float");
  110. if ( !$enable_css_float ) {
  111. return;
  112. }
  113. static $anti_infinite_loop = 500; // FIXME smelly hack
  114. $reflower = $this->_block_frame->get_reflower();
  115. if ( !$reflower ) {
  116. return;
  117. }
  118. $cb_w = null;
  119. $block = $this->_block_frame;
  120. $root = $block->get_root();
  121. if ( !$root ) {
  122. return;
  123. }
  124. $floating_frames = $this->get_floats_inside($root);
  125. foreach ( $floating_frames as $child_key => $floating_frame ) {
  126. $id = $floating_frame->get_id();
  127. if ( isset($this->floating_blocks[$id]) ) {
  128. continue;
  129. }
  130. $floating_style = $floating_frame->get_style();
  131. $float = $floating_style->float;
  132. $floating_width = $floating_frame->get_margin_width();
  133. if (!$cb_w) {
  134. $cb_w = $floating_frame->get_containing_block("w");
  135. }
  136. $line_w = $this->get_width();
  137. if ( !$floating_frame->_float_next_line && ($cb_w <= $line_w + $floating_width) && ($cb_w > $line_w) ) {
  138. $floating_frame->_float_next_line = true;
  139. continue;
  140. }
  141. // If the child is still shifted by the floating element
  142. if ( $anti_infinite_loop-- > 0 &&
  143. $floating_frame->get_position("y") + $floating_frame->get_margin_height() > $this->y &&
  144. $block->get_position("x") + $block->get_margin_width() > $floating_frame->get_position("x")
  145. ) {
  146. if ( $float === "left" )
  147. $this->left += $floating_width;
  148. else
  149. $this->right += $floating_width;
  150. $this->floating_blocks[$id] = true;
  151. }
  152. // else, the floating element won't shift anymore
  153. else {
  154. $root->remove_floating_frame($child_key);
  155. }
  156. }
  157. }
  158. /**
  159. * @return float
  160. */
  161. function get_width(){
  162. return $this->left + $this->w + $this->right;
  163. }
  164. /**
  165. * @return Block_Frame_Decorator
  166. */
  167. function get_block_frame() {
  168. return $this->_block_frame;
  169. }
  170. /**
  171. * @return Frame[]
  172. */
  173. function &get_frames() {
  174. return $this->_frames;
  175. }
  176. /**
  177. * @param Frame $frame
  178. */
  179. function add_frame(Frame $frame) {
  180. $this->_frames[] = $frame;
  181. }
  182. function __toString(){
  183. $props = array("wc", "y", "w", "h", "left", "right", "br");
  184. $s = "";
  185. foreach($props as $prop) {
  186. $s .= "$prop: ".$this->$prop."\n";
  187. }
  188. $s .= count($this->_frames)." frames\n";
  189. return $s;
  190. }
  191. /*function __get($prop) {
  192. if (!isset($this->{"_$prop"})) return;
  193. return $this->{"_$prop"};
  194. }*/
  195. }
  196. /*
  197. class LineBoxList implements Iterator {
  198. private $_p = 0;
  199. private $_lines = array();
  200. }
  201. */