Completed
Branch development (b1b115)
by Ashutosh
10:00
created

Renderer::render()   F

Complexity

Conditions 37
Paths 8082

Size

Total Lines 154

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 154
rs 0
cc 37
nc 8082
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @package dompdf
4
 * @link    http://dompdf.github.com/
5
 * @author  Benj Carson <[email protected]>
6
 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
7
 */
8
namespace Dompdf;
9
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;
17
18
/**
19
 * Concrete renderer
20
 *
21
 * Instantiates several specific renderers in order to render any given frame.
22
 *
23
 * @package dompdf
24
 */
25
class Renderer extends AbstractRenderer
26
{
27
28
    /**
29
     * Array of renderers for specific frame types
30
     *
31
     * @var AbstractRenderer[]
32
     */
33
    protected $_renderers;
34
35
    /**
36
     * Cache of the callbacks array
37
     *
38
     * @var array
39
     */
40
    private $_callbacks;
41
42
    /**
43
     * Advance the canvas to the next page
44
     */
45
    function new_page()
46
    {
47
        $this->_canvas->new_page();
48
    }
49
50
    /**
51
     * Render frames recursively
52
     *
53
     * @param Frame $frame the frame to render
54
     */
55
    public function render(Frame $frame)
56
    {
57
        global $_dompdf_debug;
58
59
        $this->_check_callbacks("begin_frame", $frame);
60
61
        if ($_dompdf_debug) {
62
            echo $frame;
63
            flush();
64
        }
65
66
        $style = $frame->get_style();
67
68
        if (in_array($style->visibility, array("hidden", "collapse"))) {
69
            return;
70
        }
71
72
        $display = $style->display;
73
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;
79
80
            foreach ($style->transform as $transform) {
81
                list($function, $values) = $transform;
82
                if ($function === "matrix") {
83
                    $function = "transform";
84
                }
85
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));
89
90
                call_user_func_array(array($this->_canvas, $function), $values);
91
            }
92
        }
93
94
        switch ($display) {
95
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;
103
104
            case "inline":
105
                if ($frame->is_text_node()) {
106
                    $this->_render_frame("text", $frame);
107
                } else {
108
                    $this->_render_frame("inline", $frame);
109
                }
110
                break;
111
112
            case "table-cell":
113
                $this->_render_frame("table-cell", $frame);
114
                break;
115
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;
121
122
            case "-dompdf-list-bullet":
123
                $this->_render_frame("list-bullet", $frame);
124
                break;
125
126
            case "-dompdf-image":
127
                $this->_render_frame("image", $frame);
128
                break;
129
130
            case "none":
131
                $node = $frame->get_node();
132
133
                if ($node->nodeName === "script") {
134
                    if ($node->getAttribute("type") === "text/php" ||
135
                        $node->getAttribute("language") === "php"
136
                    ) {
137
                        // Evaluate embedded php scripts
138
                        $this->_render_frame("php", $frame);
139
                    } elseif ($node->getAttribute("type") === "text/javascript" ||
140
                        $node->getAttribute("language") === "javascript"
141
                    ) {
142
                        // Insert JavaScript
143
                        $this->_render_frame("javascript", $frame);
144
                    }
145
                }
146
147
                // Don't render children, so skip to next iter
148
                return;
149
150
            default:
151
                break;
152
153
        }
154
155
        // Starts the overflow: hidden box
156
        if ($style->overflow === "hidden") {
157
            list($x, $y, $w, $h) = $frame->get_padding_box();
158
159
            // get border radii
160
            $style = $frame->get_style();
161
            list($tl, $tr, $br, $bl) = $style->get_computed_border_radius($w, $h);
162
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);
167
            }
168
        }
169
170
        $stack = array();
171
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;
180
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;
185
            }
186
187
            $stack[$z_index][] = $child;
188
        }
189
190
        ksort($stack);
191
192
        foreach ($stack as $by_index) {
193
            foreach ($by_index as $child) {
194
                $this->render($child);
195
            }
196
        }
197
198
        // Ends the overflow: hidden box
199
        if ($style->overflow === "hidden") {
200
            $this->_canvas->clipping_end();
201
        }
202
203
        if ($style->transform && is_array($style->transform)) {
204
            $this->_canvas->restore();
205
        }
206
207
        // Check for end frame callback
208
        $this->_check_callbacks("end_frame", $frame);
209
    }
210
211
    /**
212
     * Check for callbacks that need to be performed when a given event
213
     * gets triggered on a frame
214
     *
215
     * @param string $event the type of event
216
     * @param Frame $frame  the frame that event is triggered on
217
     */
218
    protected function _check_callbacks($event, $frame)
219
    {
220
        if (!isset($this->_callbacks)) {
221
            $this->_callbacks = $this->_dompdf->getCallbacks();
222
        }
223
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);
234
                    }
235
                }
236
            }
237
        }
238
    }
239
240
    /**
241
     * Render a single frame
242
     *
243
     * Creates Renderer objects on demand
244
     *
245
     * @param string $type type of renderer to use
246
     * @param Frame $frame the frame to render
247
     */
248
    protected function _render_frame($type, $frame)
249
    {
250
251
        if (!isset($this->_renderers[$type])) {
252
253
            switch ($type) {
254
                case "block":
255
                    $this->_renderers[$type] = new Block($this->_dompdf);
256
                    break;
257
258
                case "inline":
259
                    $this->_renderers[$type] = new Renderer\Inline($this->_dompdf);
260
                    break;
261
262
                case "text":
263
                    $this->_renderers[$type] = new Text($this->_dompdf);
264
                    break;
265
266
                case "image":
267
                    $this->_renderers[$type] = new Image($this->_dompdf);
268
                    break;
269
270
                case "table-cell":
271
                    $this->_renderers[$type] = new TableCell($this->_dompdf);
272
                    break;
273
274
                case "table-row-group":
275
                    $this->_renderers[$type] = new TableRowGroup($this->_dompdf);
276
                    break;
277
278
                case "list-bullet":
279
                    $this->_renderers[$type] = new ListBullet($this->_dompdf);
280
                    break;
281
282
                case "php":
283
                    $this->_renderers[$type] = new PhpEvaluator($this->_canvas);
284
                    break;
285
286
                case "javascript":
287
                    $this->_renderers[$type] = new JavascriptEmbedder($this->_dompdf);
288
                    break;
289
290
            }
291
        }
292
293
        $this->_renderers[$type]->render($frame);
294
    }
295
}
296