1<?php 2// $Header: /cvsroot/html2ps/box.img.php,v 1.50 2007/05/06 18:49:29 Konstantin Exp $ 3 4define('SCALE_NONE',0); 5define('SCALE_WIDTH',1); 6define('SCALE_HEIGHT',2); 7 8class 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 164class 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 224class 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?>