composer package updates
[openemr.git] / vendor / dompdf / dompdf / src / Renderer.php
blobaa3bf2f88db28a421ea18a92339b4e776935df96
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 namespace Dompdf;
10 use Dompdf\Renderer\AbstractRenderer;
11 use Dompdf\Renderer\Block;
12 use Dompdf\Renderer\Image;
13 use Dompdf\Renderer\ListBullet;
14 use Dompdf\Renderer\TableCell;
15 use Dompdf\Renderer\TableRowGroup;
16 use Dompdf\Renderer\Text;
18 /**
19 * Concrete renderer
21 * Instantiates several specific renderers in order to render any given frame.
23 * @package dompdf
25 class Renderer extends AbstractRenderer
28 /**
29 * Array of renderers for specific frame types
31 * @var AbstractRenderer[]
33 protected $_renderers;
35 /**
36 * Cache of the callbacks array
38 * @var array
40 private $_callbacks;
42 /**
43 * Advance the canvas to the next page
45 function new_page()
47 $this->_canvas->new_page();
50 /**
51 * Render frames recursively
53 * @param Frame $frame the frame to render
55 public function render(Frame $frame)
57 global $_dompdf_debug;
59 $this->_check_callbacks("begin_frame", $frame);
61 if ($_dompdf_debug) {
62 echo $frame;
63 flush();
66 $style = $frame->get_style();
68 if (in_array($style->visibility, array("hidden", "collapse"))) {
69 return;
72 $display = $style->display;
74 // Starts the CSS transformation
75 if ($style->transform && is_array($style->transform)) {
76 $this->_canvas->save();
77 list($x, $y) = $frame->get_padding_box();
78 $origin = $style->transform_origin;
80 foreach ($style->transform as $transform) {
81 list($function, $values) = $transform;
82 if ($function === "matrix") {
83 $function = "transform";
86 $values = array_map("floatval", $values);
87 $values[] = $x + (float)$style->length_in_pt($origin[0], (float)$style->length_in_pt($style->width));
88 $values[] = $y + (float)$style->length_in_pt($origin[1], (float)$style->length_in_pt($style->height));
90 call_user_func_array(array($this->_canvas, $function), $values);
94 switch ($display) {
96 case "block":
97 case "list-item":
98 case "inline-block":
99 case "table":
100 case "inline-table":
101 $this->_render_frame("block", $frame);
102 break;
104 case "inline":
105 if ($frame->is_text_node()) {
106 $this->_render_frame("text", $frame);
107 } else {
108 $this->_render_frame("inline", $frame);
110 break;
112 case "table-cell":
113 $this->_render_frame("table-cell", $frame);
114 break;
116 case "table-row-group":
117 case "table-header-group":
118 case "table-footer-group":
119 $this->_render_frame("table-row-group", $frame);
120 break;
122 case "-dompdf-list-bullet":
123 $this->_render_frame("list-bullet", $frame);
124 break;
126 case "-dompdf-image":
127 $this->_render_frame("image", $frame);
128 break;
130 case "none":
131 $node = $frame->get_node();
133 if ($node->nodeName === "script") {
134 if ($node->getAttribute("type") === "text/php" ||
135 $node->getAttribute("language") === "php"
137 // Evaluate embedded php scripts
138 $this->_render_frame("php", $frame);
139 } elseif ($node->getAttribute("type") === "text/javascript" ||
140 $node->getAttribute("language") === "javascript"
142 // Insert JavaScript
143 $this->_render_frame("javascript", $frame);
147 // Don't render children, so skip to next iter
148 return;
150 default:
151 break;
155 // Starts the overflow: hidden box
156 if ($style->overflow === "hidden") {
157 list($x, $y, $w, $h) = $frame->get_padding_box();
159 // get border radii
160 $style = $frame->get_style();
161 list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
163 if ($tl + $tr + $br + $bl > 0) {
164 $this->_canvas->clipping_roundrectangle($x, $y, (float)$w, (float)$h, $tl, $tr, $br, $bl);
165 } else {
166 $this->_canvas->clipping_rectangle($x, $y, (float)$w, (float)$h);
170 $stack = array();
172 foreach ($frame->get_children() as $child) {
173 // < 0 : nagative z-index
174 // = 0 : no z-index, no stacking context
175 // = 1 : stacking context without z-index
176 // > 1 : z-index
177 $child_style = $child->get_style();
178 $child_z_index = $child_style->z_index;
179 $z_index = 0;
181 if ($child_z_index !== "auto") {
182 $z_index = intval($child_z_index) + 1;
183 } elseif ($child_style->float !== "none" || $child->is_positionned()) {
184 $z_index = 1;
187 $stack[$z_index][] = $child;
190 ksort($stack);
192 foreach ($stack as $by_index) {
193 foreach ($by_index as $child) {
194 $this->render($child);
198 // Ends the overflow: hidden box
199 if ($style->overflow === "hidden") {
200 $this->_canvas->clipping_end();
203 if ($style->transform && is_array($style->transform)) {
204 $this->_canvas->restore();
207 // Check for end frame callback
208 $this->_check_callbacks("end_frame", $frame);
212 * Check for callbacks that need to be performed when a given event
213 * gets triggered on a frame
215 * @param string $event the type of event
216 * @param Frame $frame the frame that event is triggered on
218 protected function _check_callbacks($event, $frame)
220 if (!isset($this->_callbacks)) {
221 $this->_callbacks = $this->_dompdf->getCallbacks();
224 if (is_array($this->_callbacks) && isset($this->_callbacks[$event])) {
225 $info = array(0 => $this->_canvas, "canvas" => $this->_canvas,
226 1 => $frame, "frame" => $frame);
227 $fs = $this->_callbacks[$event];
228 foreach ($fs as $f) {
229 if (is_callable($f)) {
230 if (is_array($f)) {
231 $f[0]->{$f[1]}($info);
232 } else {
233 $f($info);
241 * Render a single frame
243 * Creates Renderer objects on demand
245 * @param string $type type of renderer to use
246 * @param Frame $frame the frame to render
248 protected function _render_frame($type, $frame)
251 if (!isset($this->_renderers[$type])) {
253 switch ($type) {
254 case "block":
255 $this->_renderers[$type] = new Block($this->_dompdf);
256 break;
258 case "inline":
259 $this->_renderers[$type] = new Renderer\Inline($this->_dompdf);
260 break;
262 case "text":
263 $this->_renderers[$type] = new Text($this->_dompdf);
264 break;
266 case "image":
267 $this->_renderers[$type] = new Image($this->_dompdf);
268 break;
270 case "table-cell":
271 $this->_renderers[$type] = new TableCell($this->_dompdf);
272 break;
274 case "table-row-group":
275 $this->_renderers[$type] = new TableRowGroup($this->_dompdf);
276 break;
278 case "list-bullet":
279 $this->_renderers[$type] = new ListBullet($this->_dompdf);
280 break;
282 case "php":
283 $this->_renderers[$type] = new PhpEvaluator($this->_canvas);
284 break;
286 case "javascript":
287 $this->_renderers[$type] = new JavascriptEmbedder($this->_dompdf);
288 break;
293 $this->_renderers[$type]->render($frame);