Ei kuvausta

block_renderer.cls.php 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. * Renders block frames
  10. *
  11. * @access private
  12. * @package dompdf
  13. */
  14. class Block_Renderer extends Abstract_Renderer {
  15. //........................................................................
  16. function render(Frame $frame) {
  17. $style = $frame->get_style();
  18. $node = $frame->get_node();
  19. list($x, $y, $w, $h) = $frame->get_border_box();
  20. $this->_set_opacity( $frame->get_opacity( $style->opacity ) );
  21. if ( $node->nodeName === "body" ) {
  22. $h = $frame->get_containing_block("h") - $style->length_in_pt(array(
  23. $style->margin_top,
  24. $style->border_top_width,
  25. $style->border_bottom_width,
  26. $style->margin_bottom),
  27. $style->width);
  28. }
  29. // Handle anchors & links
  30. if ( $node->nodeName === "a" && $href = $node->getAttribute("href") ) {
  31. $this->_canvas->add_link($href, $x, $y, $w, $h);
  32. }
  33. // Draw our background, border and content
  34. list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
  35. if ( $tl + $tr + $br + $bl > 0 ) {
  36. $this->_canvas->clipping_roundrectangle( $x, $y, $w, $h, $tl, $tr, $br, $bl );
  37. }
  38. if ( ($bg = $style->background_color) !== "transparent" ) {
  39. $this->_canvas->filled_rectangle( $x, $y, $w, $h, $bg );
  40. }
  41. if ( ($url = $style->background_image) && $url !== "none" ) {
  42. $this->_background_image($url, $x, $y, $w, $h, $style);
  43. }
  44. if ( $tl + $tr + $br + $bl > 0 ) {
  45. $this->_canvas->clipping_end();
  46. }
  47. $border_box = array($x, $y, $w, $h);
  48. $this->_render_border($frame, $border_box);
  49. $this->_render_outline($frame, $border_box);
  50. if (DEBUG_LAYOUT && DEBUG_LAYOUT_BLOCKS) {
  51. $this->_debug_layout($frame->get_border_box(), "red");
  52. if (DEBUG_LAYOUT_PADDINGBOX) {
  53. $this->_debug_layout($frame->get_padding_box(), "red", array(0.5, 0.5));
  54. }
  55. }
  56. if (DEBUG_LAYOUT && DEBUG_LAYOUT_LINES && $frame->get_decorator()) {
  57. foreach ($frame->get_decorator()->get_line_boxes() as $line) {
  58. $frame->_debug_layout(array($line->x, $line->y, $line->w, $line->h), "orange");
  59. }
  60. }
  61. }
  62. protected function _render_border(Frame_Decorator $frame, $border_box = null, $corner_style = "bevel") {
  63. $style = $frame->get_style();
  64. $bp = $style->get_border_properties();
  65. if ( empty($border_box) ) {
  66. $border_box = $frame->get_border_box();
  67. }
  68. // find the radius
  69. $radius = $style->get_computed_border_radius($border_box[2], $border_box[3]); // w, h
  70. // Short-cut: If all the borders are "solid" with the same color and style, and no radius, we'd better draw a rectangle
  71. if (
  72. in_array($bp["top"]["style"], array("solid", "dashed", "dotted")) &&
  73. $bp["top"] == $bp["right"] &&
  74. $bp["right"] == $bp["bottom"] &&
  75. $bp["bottom"] == $bp["left"] &&
  76. array_sum($radius) == 0
  77. ) {
  78. $props = $bp["top"];
  79. if ( $props["color"] === "transparent" || $props["width"] <= 0 ) return;
  80. list($x, $y, $w, $h) = $border_box;
  81. $width = $style->length_in_pt($props["width"]);
  82. $pattern = $this->_get_dash_pattern($props["style"], $width);
  83. $this->_canvas->rectangle($x + $width / 2, $y + $width / 2, $w - $width, $h - $width, $props["color"], $width, $pattern);
  84. return;
  85. }
  86. // Do it the long way
  87. $widths = array($style->length_in_pt($bp["top"]["width"]),
  88. $style->length_in_pt($bp["right"]["width"]),
  89. $style->length_in_pt($bp["bottom"]["width"]),
  90. $style->length_in_pt($bp["left"]["width"]));
  91. foreach ($bp as $side => $props) {
  92. list($x, $y, $w, $h) = $border_box;
  93. $length = 0;
  94. $r1 = 0;
  95. $r2 = 0;
  96. if ( !$props["style"] ||
  97. $props["style"] === "none" ||
  98. $props["width"] <= 0 ||
  99. $props["color"] == "transparent" )
  100. continue;
  101. switch($side) {
  102. case "top":
  103. $length = $w;
  104. $r1 = $radius["top-left"];
  105. $r2 = $radius["top-right"];
  106. break;
  107. case "bottom":
  108. $length = $w;
  109. $y += $h;
  110. $r1 = $radius["bottom-left"];
  111. $r2 = $radius["bottom-right"];
  112. break;
  113. case "left":
  114. $length = $h;
  115. $r1 = $radius["top-left"];
  116. $r2 = $radius["bottom-left"];
  117. break;
  118. case "right":
  119. $length = $h;
  120. $x += $w;
  121. $r1 = $radius["top-right"];
  122. $r2 = $radius["bottom-right"];
  123. break;
  124. default:
  125. break;
  126. }
  127. $method = "_border_" . $props["style"];
  128. // draw rounded corners
  129. $this->$method($x, $y, $length, $props["color"], $widths, $side, $corner_style, $r1, $r2);
  130. }
  131. }
  132. protected function _render_outline(Frame_Decorator $frame, $border_box = null, $corner_style = "bevel") {
  133. $style = $frame->get_style();
  134. $props = array(
  135. "width" => $style->outline_width,
  136. "style" => $style->outline_style,
  137. "color" => $style->outline_color,
  138. );
  139. if ( !$props["style"] || $props["style"] === "none" || $props["width"] <= 0 )
  140. return;
  141. if ( empty($border_box) ) {
  142. $border_box = $frame->get_border_box();
  143. }
  144. $offset = $style->length_in_pt($props["width"]);
  145. $pattern = $this->_get_dash_pattern($props["style"], $offset);
  146. // If the outline style is "solid" we'd better draw a rectangle
  147. if ( in_array($props["style"], array("solid", "dashed", "dotted")) ) {
  148. $border_box[0] -= $offset / 2;
  149. $border_box[1] -= $offset / 2;
  150. $border_box[2] += $offset;
  151. $border_box[3] += $offset;
  152. list($x, $y, $w, $h) = $border_box;
  153. $this->_canvas->rectangle($x, $y, $w, $h, $props["color"], $offset, $pattern);
  154. return;
  155. }
  156. $border_box[0] -= $offset;
  157. $border_box[1] -= $offset;
  158. $border_box[2] += $offset * 2;
  159. $border_box[3] += $offset * 2;
  160. $method = "_border_" . $props["style"];
  161. $widths = array_fill(0, 4, $props["width"]);
  162. $sides = array("top", "right", "left", "bottom");
  163. $length = 0;
  164. foreach ($sides as $side) {
  165. list($x, $y, $w, $h) = $border_box;
  166. switch($side) {
  167. case "top":
  168. $length = $w;
  169. break;
  170. case "bottom":
  171. $length = $w;
  172. $y += $h;
  173. break;
  174. case "left":
  175. $length = $h;
  176. break;
  177. case "right":
  178. $length = $h;
  179. $x += $w;
  180. break;
  181. default:
  182. break;
  183. }
  184. $this->$method($x, $y, $length, $props["color"], $widths, $side, $corner_style);
  185. }
  186. }
  187. }