frame_factory.cls.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. <?php
  2. /**
  3. * @package dompdf
  4. * @link http://dompdf.github.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. * Contains frame decorating logic
  10. *
  11. * This class is responsible for assigning the correct {@link Frame_Decorator},
  12. * {@link Positioner}, and {@link Frame_Reflower} objects to {@link Frame}
  13. * objects. This is determined primarily by the Frame's display type, but
  14. * also by the Frame's node's type (e.g. DomElement vs. #text)
  15. *
  16. * @access private
  17. * @package dompdf
  18. */
  19. class Frame_Factory {
  20. /**
  21. * Decorate the root Frame
  22. *
  23. * @param $root Frame The frame to decorate
  24. * @param $dompdf DOMPDF The dompdf instance
  25. * @return Page_Frame_Decorator
  26. */
  27. static function decorate_root(Frame $root, DOMPDF $dompdf) {
  28. $frame = new Page_Frame_Decorator($root, $dompdf);
  29. $frame->set_reflower( new Page_Frame_Reflower($frame) );
  30. $root->set_decorator($frame);
  31. return $frame;
  32. }
  33. /**
  34. * Decorate a Frame
  35. *
  36. * @param Frame $frame The frame to decorate
  37. * @param DOMPDF $dompdf The dompdf instance
  38. * @param Frame $root The frame to decorate
  39. *
  40. * @throws DOMPDF_Exception
  41. * @return Frame_Decorator
  42. * FIXME: this is admittedly a little smelly...
  43. */
  44. static function decorate_frame(Frame $frame, DOMPDF $dompdf, Frame $root = null) {
  45. if ( is_null($dompdf) ) {
  46. throw new DOMPDF_Exception("The DOMPDF argument is required");
  47. }
  48. $style = $frame->get_style();
  49. // Floating (and more generally out-of-flow) elements are blocks
  50. // http://coding.smashingmagazine.com/2007/05/01/css-float-theory-things-you-should-know/
  51. if ( !$frame->is_in_flow() && in_array($style->display, Style::$INLINE_TYPES)) {
  52. $style->display = "block";
  53. }
  54. $display = $style->display;
  55. switch ($display) {
  56. case "block":
  57. $positioner = "Block";
  58. $decorator = "Block";
  59. $reflower = "Block";
  60. break;
  61. case "inline-block":
  62. $positioner = "Inline";
  63. $decorator = "Block";
  64. $reflower = "Block";
  65. break;
  66. case "inline":
  67. $positioner = "Inline";
  68. if ( $frame->is_text_node() ) {
  69. $decorator = "Text";
  70. $reflower = "Text";
  71. }
  72. else {
  73. $enable_css_float = $dompdf->get_option("enable_css_float");
  74. if ( $enable_css_float && $style->float !== "none" ) {
  75. $decorator = "Block";
  76. $reflower = "Block";
  77. }
  78. else {
  79. $decorator = "Inline";
  80. $reflower = "Inline";
  81. }
  82. }
  83. break;
  84. case "table":
  85. $positioner = "Block";
  86. $decorator = "Table";
  87. $reflower = "Table";
  88. break;
  89. case "inline-table":
  90. $positioner = "Inline";
  91. $decorator = "Table";
  92. $reflower = "Table";
  93. break;
  94. case "table-row-group":
  95. case "table-header-group":
  96. case "table-footer-group":
  97. $positioner = "Null";
  98. $decorator = "Table_Row_Group";
  99. $reflower = "Table_Row_Group";
  100. break;
  101. case "table-row":
  102. $positioner = "Null";
  103. $decorator = "Table_Row";
  104. $reflower = "Table_Row";
  105. break;
  106. case "table-cell":
  107. $positioner = "Table_Cell";
  108. $decorator = "Table_Cell";
  109. $reflower = "Table_Cell";
  110. break;
  111. case "list-item":
  112. $positioner = "Block";
  113. $decorator = "Block";
  114. $reflower = "Block";
  115. break;
  116. case "-dompdf-list-bullet":
  117. if ( $style->list_style_position === "inside" ) {
  118. $positioner = "Inline";
  119. }
  120. else {
  121. $positioner = "List_Bullet";
  122. }
  123. if ( $style->list_style_image !== "none" ) {
  124. $decorator = "List_Bullet_Image";
  125. }
  126. else {
  127. $decorator = "List_Bullet";
  128. }
  129. $reflower = "List_Bullet";
  130. break;
  131. case "-dompdf-image":
  132. $positioner = "Inline";
  133. $decorator = "Image";
  134. $reflower = "Image";
  135. break;
  136. case "-dompdf-br":
  137. $positioner = "Inline";
  138. $decorator = "Inline";
  139. $reflower = "Inline";
  140. break;
  141. default:
  142. // FIXME: should throw some sort of warning or something?
  143. case "none":
  144. $positioner = "Null";
  145. $decorator = "Null";
  146. $reflower = "Null";
  147. break;
  148. }
  149. // Handle CSS position
  150. $position = $style->position;
  151. if ( $position === "absolute" ) {
  152. $positioner = "Absolute";
  153. }
  154. else if ( $position === "fixed" ) {
  155. $positioner = "Fixed";
  156. }
  157. $node = $frame->get_node();
  158. // Handle nodeName
  159. if ( $node->nodeName === "img" ) {
  160. $style->display = "-dompdf-image";
  161. $decorator = "Image";
  162. $reflower = "Image";
  163. }
  164. $positioner .= "_Positioner";
  165. $decorator .= "_Frame_Decorator";
  166. $reflower .= "_Frame_Reflower";
  167. $deco = new $decorator($frame, $dompdf);
  168. $deco->set_positioner( new $positioner($deco) );
  169. $deco->set_reflower( new $reflower($deco) );
  170. if ( $root ) {
  171. $deco->set_root($root);
  172. }
  173. if ( $display === "list-item" ) {
  174. // Insert a list-bullet frame
  175. $xml = $dompdf->get_dom();
  176. $bullet_node = $xml->createElement("bullet"); // arbitrary choice
  177. $b_f = new Frame($bullet_node);
  178. $node = $frame->get_node();
  179. $parent_node = $node->parentNode;
  180. if ( $parent_node ) {
  181. if ( !$parent_node->hasAttribute("dompdf-children-count") ) {
  182. $xpath = new DOMXPath($xml);
  183. $count = $xpath->query("li", $parent_node)->length;
  184. $parent_node->setAttribute("dompdf-children-count", $count);
  185. }
  186. if ( is_numeric($node->getAttribute("value")) ) {
  187. $index = intval($node->getAttribute("value"));
  188. }
  189. else {
  190. if ( !$parent_node->hasAttribute("dompdf-counter") ) {
  191. $index = ($parent_node->hasAttribute("start") ? $parent_node->getAttribute("start") : 1);
  192. }
  193. else {
  194. $index = $parent_node->getAttribute("dompdf-counter")+1;
  195. }
  196. }
  197. $parent_node->setAttribute("dompdf-counter", $index);
  198. $bullet_node->setAttribute("dompdf-counter", $index);
  199. }
  200. $new_style = $dompdf->get_css()->create_style();
  201. $new_style->display = "-dompdf-list-bullet";
  202. $new_style->inherit($style);
  203. $b_f->set_style($new_style);
  204. $deco->prepend_child( Frame_Factory::decorate_frame($b_f, $dompdf, $root) );
  205. }
  206. return $deco;
  207. }
  208. }