| 1 |
lars |
1 |
<?php
|
|
|
2 |
// $Header: /cvsroot/html2ps/box.img.php,v 1.50 2007/05/06 18:49:29 Konstantin Exp $
|
|
|
3 |
|
|
|
4 |
define('SCALE_NONE',0);
|
|
|
5 |
define('SCALE_WIDTH',1);
|
|
|
6 |
define('SCALE_HEIGHT',2);
|
|
|
7 |
|
|
|
8 |
class GenericImgBox extends GenericInlineBox {
|
|
|
9 |
function GenericImgBox() {
|
|
|
10 |
$this->GenericInlineBox();
|
|
|
11 |
}
|
|
|
12 |
|
|
|
13 |
function get_max_width_natural(&$context) {
|
|
|
14 |
return $this->get_full_width($context);
|
|
|
15 |
}
|
|
|
16 |
|
|
|
17 |
function get_min_width(&$context) {
|
|
|
18 |
return $this->get_full_width();
|
|
|
19 |
}
|
|
|
20 |
|
|
|
21 |
function get_max_width(&$context) {
|
|
|
22 |
return $this->get_full_width();
|
|
|
23 |
}
|
|
|
24 |
|
|
|
25 |
function is_null() {
|
|
|
26 |
return false;
|
|
|
27 |
}
|
|
|
28 |
|
|
|
29 |
function pre_reflow_images() {
|
|
|
30 |
switch ($this->scale) {
|
|
|
31 |
case SCALE_WIDTH:
|
|
|
32 |
// Only 'width' attribute given
|
|
|
33 |
$size =
|
|
|
34 |
$this->src_width/$this->src_height*
|
|
|
35 |
$this->get_width();
|
|
|
36 |
|
|
|
37 |
$this->put_height($size);
|
|
|
38 |
|
|
|
39 |
// Update baseline according to constrained image height
|
|
|
40 |
$this->default_baseline = $this->get_full_height();
|
|
|
41 |
break;
|
|
|
42 |
case SCALE_HEIGHT:
|
|
|
43 |
// Only 'height' attribute given
|
|
|
44 |
$size =
|
|
|
45 |
$this->src_height/$this->src_width*
|
|
|
46 |
$this->get_height();
|
|
|
47 |
|
|
|
48 |
$this->put_width($size);
|
|
|
49 |
$this->setCSSProperty(CSS_WIDTH, new WCConstant($size));
|
|
|
50 |
|
|
|
51 |
$this->default_baseline = $this->get_full_height();
|
|
|
52 |
break;
|
|
|
53 |
};
|
|
|
54 |
}
|
|
|
55 |
|
|
|
56 |
function readCSS(&$state) {
|
|
|
57 |
parent::readCSS($state);
|
|
|
58 |
|
|
|
59 |
// '-html2ps-link-target'
|
|
|
60 |
global $g_config;
|
|
|
61 |
if ($g_config["renderlinks"]) {
|
|
|
62 |
$this->_readCSS($state,
|
|
|
63 |
array(CSS_HTML2PS_LINK_TARGET));
|
|
|
64 |
};
|
|
|
65 |
}
|
|
|
66 |
|
|
|
67 |
function reflow_static(&$parent, &$context) {
|
|
|
68 |
$this->pre_reflow_images();
|
|
|
69 |
|
|
|
70 |
GenericFormattedBox::reflow($parent, $context);
|
|
|
71 |
|
|
|
72 |
// Check if we need a line break here
|
|
|
73 |
$this->maybe_line_break($parent, $context);
|
|
|
74 |
|
|
|
75 |
// set default baseline
|
|
|
76 |
$this->baseline = $this->default_baseline;
|
|
|
77 |
|
|
|
78 |
// append to parent line box
|
|
|
79 |
$parent->append_line($this);
|
|
|
80 |
|
|
|
81 |
// Move box to the parent current point
|
|
|
82 |
$this->guess_corner($parent);
|
|
|
83 |
|
|
|
84 |
// Move parent's X coordinate
|
|
|
85 |
$parent->_current_x += $this->get_full_width();
|
|
|
86 |
|
|
|
87 |
// Extend parent height
|
|
|
88 |
$parent->extend_height($this->get_bottom_margin());
|
|
|
89 |
}
|
|
|
90 |
|
|
|
91 |
function _get_font_name(&$driver, $subword_index) {
|
|
|
92 |
if (isset($this->_cache[CACHE_TYPEFACE][$subword_index])) {
|
|
|
93 |
return $this->_cache[CACHE_TYPEFACE][$subword_index];
|
|
|
94 |
};
|
|
|
95 |
|
|
|
96 |
$font_resolver =& $driver->get_font_resolver();
|
|
|
97 |
|
|
|
98 |
$font = $this->get_css_property(CSS_FONT);
|
|
|
99 |
$typeface = $font_resolver->get_typeface_name($font->family,
|
|
|
100 |
$font->weight,
|
|
|
101 |
$font->style,
|
|
|
102 |
'iso-8859-1');
|
|
|
103 |
|
|
|
104 |
$this->_cache[CACHE_TYPEFACE][$subword_index] = $typeface;
|
|
|
105 |
|
|
|
106 |
return $typeface;
|
|
|
107 |
}
|
|
|
108 |
|
|
|
109 |
function reflow_text(&$driver) {
|
|
|
110 |
// In XHTML images are treated as a common inline elements; they are affected by line-height and font-size
|
|
|
111 |
global $g_config;
|
|
|
112 |
if ($g_config['mode'] == 'xhtml') {
|
|
|
113 |
/**
|
|
|
114 |
* A simple assumption is made: fonts used for different encodings
|
|
|
115 |
* have equal ascender/descender values (while they have the same
|
|
|
116 |
* typeface, style and weight).
|
|
|
117 |
*/
|
|
|
118 |
$font_name = $this->_get_font_name($driver, 0);
|
|
|
119 |
|
|
|
120 |
/**
|
|
|
121 |
* Get font vertical metrics
|
|
|
122 |
*/
|
|
|
123 |
$ascender = $driver->font_ascender($font_name, 'iso-8859-1');
|
|
|
124 |
if (is_null($ascender)) {
|
|
|
125 |
error_log("ImgBox::reflow_text: cannot get font ascender");
|
|
|
126 |
return null;
|
|
|
127 |
};
|
|
|
128 |
|
|
|
129 |
$descender = $driver->font_descender($font_name, 'iso-8859-1');
|
|
|
130 |
if (is_null($descender)) {
|
|
|
131 |
error_log("ImgBox::reflow_text: cannot get font descender");
|
|
|
132 |
return null;
|
|
|
133 |
};
|
|
|
134 |
|
|
|
135 |
/**
|
|
|
136 |
* Setup box size
|
|
|
137 |
*/
|
|
|
138 |
$font = $this->get_css_property(CSS_FONT_SIZE);
|
|
|
139 |
$font_size = $font->getPoints();
|
|
|
140 |
|
|
|
141 |
$this->ascender = $ascender * $font_size;
|
|
|
142 |
$this->descender = $descender * $font_size;
|
|
|
143 |
} else {
|
|
|
144 |
$this->ascender = $this->get_height();
|
|
|
145 |
$this->descender = 0;
|
|
|
146 |
};
|
|
|
147 |
|
|
|
148 |
return true;
|
|
|
149 |
}
|
|
|
150 |
|
|
|
151 |
// Image boxes are regular inline boxes; whitespaces after images should be rendered
|
|
|
152 |
//
|
|
|
153 |
function reflow_whitespace(&$linebox_started, &$previous_whitespace) {
|
|
|
154 |
$linebox_started = true;
|
|
|
155 |
$previous_whitespace = false;
|
|
|
156 |
return;
|
|
|
157 |
}
|
|
|
158 |
|
|
|
159 |
function show_fixed(&$driver) {
|
|
|
160 |
return $this->show($driver);
|
|
|
161 |
}
|
|
|
162 |
}
|
|
|
163 |
|
|
|
164 |
class BrokenImgBox extends GenericImgBox {
|
|
|
165 |
var $alt;
|
|
|
166 |
|
|
|
167 |
function BrokenImgBox($width, $height, $alt) {
|
|
|
168 |
$this->scale = SCALE_NONE;
|
|
|
169 |
$this->encoding = DEFAULT_ENCODING;
|
|
|
170 |
|
|
|
171 |
// Call parent constructor
|
|
|
172 |
$this->GenericImgBox();
|
|
|
173 |
|
|
|
174 |
$this->alt = $alt;
|
|
|
175 |
}
|
|
|
176 |
|
|
|
177 |
function show(&$driver) {
|
|
|
178 |
$driver->save();
|
|
|
179 |
|
|
|
180 |
// draw generic box
|
|
|
181 |
GenericFormattedBox::show($driver);
|
|
|
182 |
|
|
|
183 |
$driver->setlinewidth(0.1);
|
|
|
184 |
$driver->moveto($this->get_left(), $this->get_top());
|
|
|
185 |
$driver->lineto($this->get_right(), $this->get_top());
|
|
|
186 |
$driver->lineto($this->get_right(), $this->get_bottom());
|
|
|
187 |
$driver->lineto($this->get_left(), $this->get_bottom());
|
|
|
188 |
$driver->closepath();
|
|
|
189 |
$driver->stroke();
|
|
|
190 |
|
|
|
191 |
if (!$GLOBALS['g_config']['debugnoclip']) {
|
|
|
192 |
$driver->moveto($this->get_left(), $this->get_top());
|
|
|
193 |
$driver->lineto($this->get_right(), $this->get_top());
|
|
|
194 |
$driver->lineto($this->get_right(), $this->get_bottom());
|
|
|
195 |
$driver->lineto($this->get_left(), $this->get_bottom());
|
|
|
196 |
$driver->closepath();
|
|
|
197 |
$driver->clip();
|
|
|
198 |
};
|
|
|
199 |
|
|
|
200 |
// Output text with the selected font
|
|
|
201 |
$size = pt2pt(BROKEN_IMAGE_ALT_SIZE_PT);
|
|
|
202 |
|
|
|
203 |
$status = $driver->setfont("Times-Roman", "iso-8859-1", $size);
|
|
|
204 |
if (is_null($status)) {
|
|
|
205 |
return null;
|
|
|
206 |
};
|
|
|
207 |
|
|
|
208 |
$driver->show_xy($this->alt,
|
|
|
209 |
$this->get_left() + $this->width/2 - $driver->stringwidth($this->alt,
|
|
|
210 |
"Times-Roman",
|
|
|
211 |
"iso-8859-1",
|
|
|
212 |
$size)/2,
|
|
|
213 |
$this->get_top() - $this->height/2 - $size/2);
|
|
|
214 |
|
|
|
215 |
$driver->restore();
|
|
|
216 |
|
|
|
217 |
$strategy =& new StrategyLinkRenderingNormal();
|
|
|
218 |
$strategy->apply($this, $driver);
|
|
|
219 |
|
|
|
220 |
return true;
|
|
|
221 |
}
|
|
|
222 |
}
|
|
|
223 |
|
|
|
224 |
class ImgBox extends GenericImgBox {
|
|
|
225 |
var $image;
|
|
|
226 |
var $type; // unused; should store the preferred image format (JPG / PNG)
|
|
|
227 |
|
|
|
228 |
function ImgBox($img) {
|
|
|
229 |
$this->encoding = DEFAULT_ENCODING;
|
|
|
230 |
$this->scale = SCALE_NONE;
|
|
|
231 |
|
|
|
232 |
// Call parent constructor
|
|
|
233 |
$this->GenericImgBox();
|
|
|
234 |
|
|
|
235 |
// Store image for further processing
|
|
|
236 |
$this->image = $img;
|
|
|
237 |
}
|
|
|
238 |
|
|
|
239 |
function &create(&$root, &$pipeline) {
|
|
|
240 |
// Open image referenced by HTML tag
|
|
|
241 |
// Some crazy HTML writers add leading and trailing spaces to SRC attribute value - we need to remove them
|
|
|
242 |
//
|
|
|
243 |
$url_autofix = new AutofixUrl();
|
|
|
244 |
$src = $url_autofix->apply(trim($root->get_attribute("src")));
|
|
|
245 |
|
|
|
246 |
$image_url = $pipeline->guess_url($src);
|
|
|
247 |
$src_img = ImageFactory::get($image_url, $pipeline);
|
|
|
248 |
|
|
|
249 |
if (is_null($src_img)) {
|
|
|
250 |
// image could not be opened, use ALT attribute
|
|
|
251 |
|
|
|
252 |
if ($root->has_attribute('width')) {
|
|
|
253 |
$width = px2pt($root->get_attribute('width'));
|
|
|
254 |
} else {
|
|
|
255 |
$width = px2pt(BROKEN_IMAGE_DEFAULT_SIZE_PX);
|
|
|
256 |
};
|
|
|
257 |
|
|
|
258 |
if ($root->has_attribute('height')) {
|
|
|
259 |
$height = px2pt($root->get_attribute('height'));
|
|
|
260 |
} else {
|
|
|
261 |
$height = px2pt(BROKEN_IMAGE_DEFAULT_SIZE_PX);
|
|
|
262 |
};
|
|
|
263 |
|
|
|
264 |
$alt = $root->get_attribute('alt');
|
|
|
265 |
|
|
|
266 |
$box =& new BrokenImgBox($width, $height, $alt);
|
|
|
267 |
|
|
|
268 |
$box->readCSS($pipeline->get_current_css_state());
|
|
|
269 |
|
|
|
270 |
$box->put_width($width);
|
|
|
271 |
$box->put_height($height);
|
|
|
272 |
|
|
|
273 |
$box->default_baseline = $box->get_full_height();
|
|
|
274 |
|
|
|
275 |
$box->src_height = $box->get_height();
|
|
|
276 |
$box->src_width = $box->get_width();
|
|
|
277 |
|
|
|
278 |
return $box;
|
|
|
279 |
} else {
|
|
|
280 |
$box =& new ImgBox($src_img);
|
|
|
281 |
$box->readCSS($pipeline->get_current_css_state());
|
|
|
282 |
$box->_setupSize();
|
|
|
283 |
|
|
|
284 |
return $box;
|
|
|
285 |
}
|
|
|
286 |
}
|
|
|
287 |
|
|
|
288 |
function _setupSize() {
|
|
|
289 |
$this->put_width(px2pt($this->image->sx()));
|
|
|
290 |
$this->put_height(px2pt($this->image->sy()));
|
|
|
291 |
$this->default_baseline = $this->get_full_height();
|
|
|
292 |
|
|
|
293 |
$this->src_height = $this->image->sx();
|
|
|
294 |
$this->src_width = $this->image->sy();
|
|
|
295 |
|
|
|
296 |
$wc = $this->get_css_property(CSS_WIDTH);
|
|
|
297 |
$hc = $this->get_height_constraint();
|
|
|
298 |
|
|
|
299 |
// Proportional scaling
|
|
|
300 |
if ($hc->is_null() && !$wc->isNull()) {
|
|
|
301 |
$this->scale = SCALE_WIDTH;
|
|
|
302 |
|
|
|
303 |
// Only 'width' attribute given
|
|
|
304 |
$size =
|
|
|
305 |
$this->src_width/$this->src_height*
|
|
|
306 |
$this->get_width();
|
|
|
307 |
|
|
|
308 |
$this->put_height($size);
|
|
|
309 |
|
|
|
310 |
// Update baseline according to constrained image height
|
|
|
311 |
$this->default_baseline = $this->get_full_height();
|
|
|
312 |
|
|
|
313 |
} elseif (!$hc->is_null() && $wc->isNull()) {
|
|
|
314 |
$this->scale = SCALE_HEIGHT;
|
|
|
315 |
|
|
|
316 |
// Only 'height' attribute given
|
|
|
317 |
$size =
|
|
|
318 |
$this->src_height/$this->src_width*
|
|
|
319 |
$this->get_height();
|
|
|
320 |
|
|
|
321 |
$this->put_width($size);
|
|
|
322 |
$this->setCSSProperty(CSS_WIDTH, new WCConstant($size));
|
|
|
323 |
|
|
|
324 |
$this->default_baseline = $this->get_full_height();
|
|
|
325 |
};
|
|
|
326 |
}
|
|
|
327 |
|
|
|
328 |
function show(&$driver) {
|
|
|
329 |
// draw generic box
|
|
|
330 |
GenericFormattedBox::show($driver);
|
|
|
331 |
|
|
|
332 |
// Check if "designer" set the height or width of this image to zero; in this there will be no reason
|
|
|
333 |
// in drawing the image at all
|
|
|
334 |
//
|
|
|
335 |
if ($this->get_width() < EPSILON ||
|
|
|
336 |
$this->get_height() < EPSILON) {
|
|
|
337 |
return true;
|
|
|
338 |
};
|
|
|
339 |
|
|
|
340 |
$driver->image_scaled($this->image,
|
|
|
341 |
$this->get_left(), $this->get_bottom(),
|
|
|
342 |
$this->get_width() / $this->image->sx(),
|
|
|
343 |
$this->get_height() / $this->image->sy());
|
|
|
344 |
|
|
|
345 |
$strategy =& new StrategyLinkRenderingNormal();
|
|
|
346 |
$strategy->apply($this, $driver);
|
|
|
347 |
|
|
|
348 |
return true;
|
|
|
349 |
}
|
|
|
350 |
}
|
|
|
351 |
?>
|