PluginProbe
MBE eShip / trunk
MBE eShip vtrunk
2.8.1 trunk 1.0.0 1.1.0 1.1.3 1.2.1 1.2.2 1.3.0 1.4.0 1.4.1 1.5.0 1.5.1 1.5.2 1.6.0 1.7.0 1.7.1 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1.0 2.1.1 2.1.2 2.2.1 All 37 releases
mail-boxes-etc / lib / dompdf / src / FrameReflower / Image.php

Image.php in MBE eShip trunk, at lib/dompdf/src/FrameReflower/Image.php

214 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package dompdf
4 * @link https://github.com/dompdf/dompdf
5 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
6 */
7 namespace Dompdf\FrameReflower;
8
9 use Dompdf\Helpers;
10 use Dompdf\FrameDecorator\Block as BlockFrameDecorator;
11 use Dompdf\FrameDecorator\Image as ImageFrameDecorator;
12
13 /**
14 * Image reflower class
15 *
16 * @package dompdf
17 */
18 class Image extends AbstractFrameReflower
19 {
20
21 /**
22 * Image constructor.
23 * @param ImageFrameDecorator $frame
24 */
25 function __construct(ImageFrameDecorator $frame)
26 {
27 parent::__construct($frame);
28 }
29
30 /**
31 * @param BlockFrameDecorator|null $block
32 */
33 function reflow(BlockFrameDecorator $block = null)
34 {
35 $this->determine_absolute_containing_block();
36
37 // Counters and generated content
38 $this->_set_content();
39
40 //FLOAT
41 //$frame = $this->_frame;
42 //$page = $frame->get_root();
43
44 //if ($frame->get_style()->float !== "none" ) {
45 // $page->add_floating_frame($this);
46 //}
47
48 $this->resolve_dimensions();
49 $this->resolve_margins();
50
51 $frame = $this->_frame;
52 $frame->position();
53
54 if ($block && $frame->is_in_flow()) {
55 $block->add_frame_to_line($frame);
56 }
57 }
58
59 public function get_min_max_content_width(): array
60 {
61 // TODO: While the containing block is not set yet on the frame, it can
62 // already be determined in some cases due to fixed dimensions on the
63 // ancestor forming the containing block. In such cases, percentage
64 // values could be resolved here
65 $style = $this->_frame->get_style();
66
67 [$width] = $this->calculate_size(null, null);
68 $min_width = $this->resolve_min_width(null);
69 $percent_width = Helpers::is_percent($style->width)
70 || Helpers::is_percent($style->max_width)
71 || ($style->width === "auto"
72 && (Helpers::is_percent($style->height) || Helpers::is_percent($style->max_height)));
73
74 // Use the specified min width as minimum when width or max width depend
75 // on the containing block and cannot be resolved yet. This mimics
76 // browser behavior
77 $min = $percent_width ? $min_width : $width;
78 $max = $width;
79
80 return [$min, $max];
81 }
82
83 /**
84 * Calculate width and height, accounting for min/max constraints.
85 *
86 * * https://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width
87 * * https://www.w3.org/TR/CSS21/visudet.html#inline-replaced-height
88 * * https://www.w3.org/TR/CSS21/visudet.html#min-max-widths
89 * * https://www.w3.org/TR/CSS21/visudet.html#min-max-heights
90 *
91 * @param float|null $cbw Width of the containing block.
92 * @param float|null $cbh Height of the containing block.
93 *
94 * @return float[]
95 */
96 protected function calculate_size(?float $cbw, ?float $cbh): array
97 {
98 /** @var ImageFrameDecorator */
99 $frame = $this->_frame;
100 $style = $frame->get_style();
101
102 $computed_width = $style->width;
103 $computed_height = $style->height;
104
105 $width = $cbw === null && Helpers::is_percent($computed_width)
106 ? "auto"
107 : $style->length_in_pt($computed_width, $cbw ?? 0);
108 $height = $cbh === null && Helpers::is_percent($computed_height)
109 ? "auto"
110 : $style->length_in_pt($computed_height, $cbh ?? 0);
111 $min_width = $this->resolve_min_width($cbw);
112 $max_width = $this->resolve_max_width($cbw);
113 $min_height = $this->resolve_min_height($cbh);
114 $max_height = $this->resolve_max_height($cbh);
115
116 if ($width === "auto" && $height === "auto") {
117 // Use intrinsic dimensions, resampled to pt
118 [$img_width, $img_height] = $frame->get_intrinsic_dimensions();
119 $w = $frame->resample($img_width);
120 $h = $frame->resample($img_height);
121
122 // Resolve min/max constraints according to the constraint-violation
123 // table in https://www.w3.org/TR/CSS21/visudet.html#min-max-widths
124 $max_width = max($min_width, $max_width);
125 $max_height = max($min_height, $max_height);
126
127 if (($w > $max_width && $h <= $max_height)
128 || ($w > $max_width && $h > $max_height && $max_width / $w <= $max_height / $h)
129 || ($w < $min_width && $h > $min_height)
130 || ($w < $min_width && $h < $min_height && $min_width / $w > $min_height / $h)
131 ) {
132 $width = Helpers::clamp($w, $min_width, $max_width);
133 $height = $width * ($img_height / $img_width);
134 $height = Helpers::clamp($height, $min_height, $max_height);
135 } else {
136 $height = Helpers::clamp($h, $min_height, $max_height);
137 $width = $height * ($img_width / $img_height);
138 $width = Helpers::clamp($width, $min_width, $max_width);
139 }
140 } elseif ($height === "auto") {
141 // Width is fixed, scale height according to aspect ratio
142 [$img_width, $img_height] = $frame->get_intrinsic_dimensions();
143 $width = Helpers::clamp((float) $width, $min_width, $max_width);
144 $height = $width * ($img_height / $img_width);
145 $height = Helpers::clamp($height, $min_height, $max_height);
146 } elseif ($width === "auto") {
147 // Height is fixed, scale width according to aspect ratio
148 [$img_width, $img_height] = $frame->get_intrinsic_dimensions();
149 $height = Helpers::clamp((float) $height, $min_height, $max_height);
150 $width = $height * ($img_width / $img_height);
151 $width = Helpers::clamp($width, $min_width, $max_width);
152 } else {
153 // Width and height are fixed
154 $width = Helpers::clamp((float) $width, $min_width, $max_width);
155 $height = Helpers::clamp((float) $height, $min_height, $max_height);
156 }
157
158 return [$width, $height];
159 }
160
161 protected function resolve_dimensions(): void
162 {
163 /** @var ImageFrameDecorator */
164 $frame = $this->_frame;
165 $style = $frame->get_style();
166
167 $debug_png = $this->get_dompdf()->getOptions()->getDebugPng();
168
169 if ($debug_png) {
170 [$img_width, $img_height] = $frame->get_intrinsic_dimensions();
171 print "resolve_dimensions() " .
172 $frame->get_style()->width . " " .
173 $frame->get_style()->height . ";" .
174 $frame->get_parent()->get_style()->width . " " .
175 $frame->get_parent()->get_style()->height . ";" .
176 $frame->get_parent()->get_parent()->get_style()->width . " " .
177 $frame->get_parent()->get_parent()->get_style()->height . ";" .
178 $img_width . " " .
179 $img_height . "|";
180 }
181
182 [, , $cbw, $cbh] = $frame->get_containing_block();
183 [$width, $height] = $this->calculate_size($cbw, $cbh);
184
185 if ($debug_png) {
186 print $width . " " . $height . ";";
187 }
188
189 $style->set_used("width", $width);
190 $style->set_used("height", $height);
191 }
192
193 protected function resolve_margins(): void
194 {
195 // Only handle the inline case for now
196 // https://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width
197 // https://www.w3.org/TR/CSS21/visudet.html#inline-replaced-height
198 $style = $this->_frame->get_style();
199
200 if ($style->margin_left === "auto") {
201 $style->set_used("margin_left", 0.0);
202 }
203 if ($style->margin_right === "auto") {
204 $style->set_used("margin_right", 0.0);
205 }
206 if ($style->margin_top === "auto") {
207 $style->set_used("margin_top", 0.0);
208 }
209 if ($style->margin_bottom === "auto") {
210 $style->set_used("margin_bottom", 0.0);
211 }
212 }
213 }
214