| [ PHPXref.com ] | [ Generated: Sun Jul 20 17:19:34 2008 ] | [ dompdf 0.5 ] |
| [ Index ] [ Variables ] [ Functions ] [ Classes ] [ Constants ] [ Statistics ] | ||
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * DOMPDF - PHP5 HTML to PDF renderer 4 * 5 * File: $RCSfile: block_frame_reflower.cls.php,v $ 6 * Created on: 2004-06-17 7 * 8 * Copyright (c) 2004 - Benj Carson <benjcarson@digitaljunkies.ca> 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public License 21 * along with this library in the file LICENSE.LGPL; if not, write to the 22 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 23 * 02111-1307 USA 24 * 25 * Alternatively, you may distribute this software under the terms of the 26 * PHP License, version 3.0 or later. A copy of this license should have 27 * been distributed with this file in the file LICENSE.PHP . If this is not 28 * the case, you can obtain a copy at http://www.php.net/license/3_0.txt. 29 * 30 * The latest version of DOMPDF might be available at: 31 * http://www.digitaljunkies.ca/dompdf 32 * 33 * @link http://www.digitaljunkies.ca/dompdf 34 * @copyright 2004 Benj Carson 35 * @author Benj Carson <benjcarson@digitaljunkies.ca> 36 * @package dompdf 37 * @version 0.3 38 */ 39 40 /* $Id: block_frame_reflower.cls.php,v 1.13 2006/04/06 19:30:46 benjcarson Exp $ */ 41 42 /** 43 * Reflows block frames 44 * 45 * @access private 46 * @package dompdf 47 */ 48 class Block_Frame_Reflower extends Frame_Reflower { 49 const MIN_JUSTIFY_WIDTH = 0.80; // (Minimum line width to justify, as 50 // fraction of available width) 51 52 function __construct(Block_Frame_Decorator $frame) { parent::__construct($frame); } 53 54 //........................................................................ 55 56 // Calculate the ideal used value for the width property as per: 57 // http://www.w3.org/TR/CSS21/visudet.html#Computing_widths_and_margins 58 59 protected function _calculate_width($width) { 60 $style = $this->_frame->get_style(); 61 $cb = $this->_frame->get_containing_block(); 62 63 $r = $style->length_in_pt($style->margin_right, $cb["w"]); 64 $l = $style->length_in_pt($style->margin_left, $cb["w"]); 65 66 // Handle 'auto' values 67 $dims = array($style->border_left_width, 68 $style->border_right_width, 69 $style->padding_left, 70 $style->padding_right, 71 $width !== "auto" ? $width : 0, 72 $l !== "auto" ? $l : 0, 73 $r !== "auto" ? $r : 0); 74 75 $sum = $style->length_in_pt($dims, $cb["w"]); 76 77 // Compare to the containing block 78 $diff = $cb["w"] - $sum; 79 80 if ( $diff > 0 ) { 81 82 // Find auto properties and get them to take up the slack 83 if ( $width === "auto" ) 84 $width = $diff; 85 86 else if ( $l === "auto" && $r === "auto" ) 87 $l = $r = round($diff / 2); 88 89 else if ( $l === "auto" ) 90 $l = $diff; 91 92 else if ( $r === "auto" ) 93 $r = $diff; 94 95 } else if ($diff < 0) { 96 97 // We are over constrained--set margin-right to the difference 98 $r = $diff; 99 100 } 101 102 return array("width"=> $width, "margin_left" => $l, "margin_right" => $r); 103 } 104 105 // Call the above function, but resolve max/min widths 106 protected function _calculate_restricted_width() { 107 $style = $this->_frame->get_style(); 108 $cb = $this->_frame->get_containing_block(); 109 110 if ( !isset($cb["w"]) ) 111 throw new DOMPDF_Exception("Box property calculation requires containing block width"); 112 113 $width = $style->length_in_pt($style->width, $cb["w"]); 114 115 extract($this->_calculate_width($width)); 116 117 // Handle min/max width 118 $min_width = $style->length_in_pt($style->min_width, $cb["w"]); 119 $max_width = $style->length_in_pt($style->max_width, $cb["w"]); 120 121 if ( $max_width !== "none" && $min_width > $max_width) 122 // Swap 'em 123 list($max_width, $min_width) = array($min_width, $max_width); 124 125 if ( $max_width !== "none" && $width > $max_width ) 126 extract($this->_calculate_width($max_width)); 127 128 if ( $width < $min_width ) 129 extract($this->_calculate_width($min_width)); 130 131 return array($width, $margin_left, $margin_right); 132 133 } 134 135 //........................................................................ 136 137 // Determine the unrestricted height of content within the block 138 protected function _calculate_content_height() { 139 $style = $this->_frame->get_style(); 140 $cb = $this->_frame->get_containing_block(); 141 142 $height = $style->height; 143 144 // Handle percentage heights 145 if ( isset($cb["h"]) ) 146 $height = $style->length_in_pt($height, $cb["h"]); 147 148 else if ( mb_strpos($height, "%") !== false ) 149 $height = "auto"; 150 151 else 152 $height = $style->length_in_pt($height, $cb["w"]); 153 154 // FIXME: not sure about this... What if height is specified precisely, 155 // but overflow is visible? 156 if ( $style->overflow === "visible" || 157 ($style->overflow === "hidden" && $height === "auto") ) { 158 159 // Calculate the actual height 160 $height = 0; 161 162 // Add the height of all lines 163 foreach ($this->_frame->get_lines() as $line) 164 $height += $line["h"]; 165 166 } 167 168 return $height; 169 } 170 171 // Determine the frame's restricted height 172 protected function _calculate_restricted_height() { 173 $style = $this->_frame->get_style(); 174 $height = $this->_calculate_content_height(); 175 176 $cb = $this->_frame->get_containing_block(); 177 178 if ( !($style->overflow === "visible" || 179 ($style->overflow === "hidden" && $height === "auto")) ) { 180 181 // Only handle min/max height if the height is independent of the frame's content 182 183 $min_height = $style->min_height; 184 $max_height = $style->max_height; 185 186 if ( isset($cb["h"]) ) { 187 $min_height = $style->length_in_pt($min_height, $cb["h"]); 188 $max_height = $style->length_in_pt($max_height, $cb["h"]); 189 190 } else if ( isset($cb["w"]) ) { 191 192 if ( mb_strpos($min_height, "%") !== false ) 193 $min_height = 0; 194 else 195 $min_height = $style->length_in_pt($min_height, $cb["w"]); 196 197 if ( mb_strpos($max_height, "%") !== false ) 198 $max_height = "none"; 199 else 200 $max_height = $style->length_in_pt($max_height, $cb["w"]); 201 } 202 203 if ( $max_height !== "none" && $min_height > $max_height ) 204 // Swap 'em 205 list($max_height, $min_height) = array($min_height, $max_height); 206 207 if ( $max_height !== "none" && $height > $max_height ) 208 $height = $max_height; 209 210 if ( $height < $min_height ) 211 $height = $min_height; 212 } 213 214 return $height; 215 216 } 217 218 //........................................................................ 219 220 protected function _text_align() { 221 $style = $this->_frame->get_style(); 222 223 // Adjust the justification of each of our lines. 224 // http://www.w3.org/TR/CSS21/text.html#propdef-text-align 225 switch ($style->text_align) { 226 227 default: 228 case "left": 229 return; 230 231 case "right": 232 foreach ($this->_frame->get_lines() as $line) { 233 234 // Move each child over by $dx 235 $dx = $style->width - $line["w"]; 236 foreach($line["frames"] as $frame) 237 $frame->set_position( $frame->get_position("x") + $dx ); 238 239 } 240 break; 241 242 243 case "justify": 244 foreach ($this->_frame->get_lines() as $i => $line) { 245 246 // Only set the spacing if the line is long enough. This is really 247 // just an aesthetic choice ;) 248 if ( $line["w"] > self::MIN_JUSTIFY_WIDTH * $style->width ) { 249 // Set the spacing for each child 250 if ( $line["wc"] > 1 ) 251 $spacing = ($style->width - $line["w"]) / ($line["wc"] - 1); 252 else 253 $spacing = 0; 254 255 $dx = 0; 256 foreach($line["frames"] as $frame) { 257 if ( !$frame instanceof Text_Frame_Decorator ) 258 continue; 259 260 $frame->set_position( $frame->get_position("x") + $dx ); 261 $frame->set_text_spacing($spacing); 262 $dx += mb_substr_count($frame->get_text(), " ") * $spacing; 263 } 264 265 // The line (should) now occupy the entire width 266 $this->_frame->set_line($i, null, $style->width); 267 268 } 269 } 270 break; 271 272 case "center": 273 case "centre": 274 foreach ($this->_frame->get_lines() as $i => $line) { 275 // Centre each line by moving each frame in the line by: 276 $dx = ($style->width - $line["w"]) / 2; 277 foreach ($line["frames"] as $frame) 278 $frame->set_position( $frame->get_position("x") + $dx ); 279 } 280 break; 281 } 282 283 } 284 /** 285 * Align inline children vertically 286 */ 287 function vertical_align() { 288 // Align each child vertically after each line is reflowed 289 foreach ( $this->_frame->get_lines() as $i => $line ) { 290 291 foreach ( $line["frames"] as $frame ) { 292 $style = $frame->get_style(); 293 294 if ( $style->display != "inline" && $style->display != "text" ) 295 continue; 296 297 $align = $style->vertical_align; 298 299 $frame_h = $style->length_in_pt($style->height); 300 301 switch ($align) { 302 303 case "baseline": 304 $y = $line["y"] + $line["h"] - $frame_h; 305 break; 306 307 case "middle": 308 $y = $line["y"] + ($line["h"] + $frame_h) / 2; 309 break; 310 311 case "sub": 312 $y = $line["y"] + 0.9 * $line["h"]; 313 break; 314 315 case "super": 316 $y = $line["y"] + 0.1 * $line["h"]; 317 break; 318 319 case "text-top": 320 case "top": // Not strictly accurate, but good enough for now 321 $y = $line["y"]; 322 break; 323 324 case "text-bottom": 325 case "bottom": 326 $y = $line["y"] + $line["h"] - $frame_h; 327 break; 328 } 329 330 $x = $frame->get_position("x"); 331 $frame->set_position($x, $y); 332 333 } 334 } 335 } 336 337 //........................................................................ 338 339 function reflow() { 340 341 // Check if a page break is forced 342 $page = $this->_frame->get_root(); 343 $page->check_forced_page_break($this->_frame); 344 345 // Bail if the page is full 346 if ( $page->is_full() ) 347 return; 348 349 // Collapse margins if required 350 $this->_collapse_margins(); 351 352 $this->_frame->position(); 353 354 $style = $this->_frame->get_style(); 355 $cb = $this->_frame->get_containing_block(); 356 list($x, $y) = $this->_frame->get_position(); 357 358 // Determine the constraints imposed by this frame: calculate the width 359 // of the content area: 360 list($w, $left, $right) = $this->_calculate_restricted_width(); 361 362 // Store the calculated properties 363 $style->width = $w; 364 $style->margin_left = $left."pt"; 365 $style->margin_right = $right."pt"; 366 367 368 // Adjust the first line based on the text-indent property 369 $indent = $style->length_in_pt($style->text_indent, $cb["w"]); 370 $this->_frame->increase_line_width($indent); 371 372 // Determine the content edge 373 $top = $style->length_in_pt(array($style->margin_top, 374 $style->padding_top, 375 $style->border_top_width), $cb["h"]); 376 377 $bottom = $style->length_in_pt(array($style->border_bottom_width, 378 $style->margin_bottom, 379 $style->padding_bottom), $cb["h"]); 380 381 $cb_x = $x + $left + 382 $style->length_in_pt($style->border_left_width, $cb["w"]) + 383 $style->length_in_pt($style->padding_left, $cb["w"]); 384 385 $cb_y = $line_y = $y + $top; 386 387 $cb_h = ($cb["h"] + $cb["y"]) - $bottom - $cb_y; 388 389 // Set the y position of the first line in this block 390 $this->_frame->set_current_line($line_y); 391 392 // Set the containing blocks and reflow each child 393 foreach ( $this->_frame->get_children() as $child ) { 394 395 // Bail out if the page is full 396 if ( $page->is_full() ) 397 break; 398 399 $child->set_containing_block($cb_x, $cb_y, $w, $cb_h); 400 $child->reflow(); 401 402 // Don't add the child to the line if a page break has occurred 403 if ( $page->check_page_break($child) ) 404 break; 405 406 // It's okay to add the frame to the line 407 $this->_frame->add_frame_to_line( $child ); 408 } 409 410 // Determine our height 411 $style->height = $this->_calculate_restricted_height(); 412 413 $this->_text_align(); 414 415 $this->vertical_align(); 416 } 417 418 //........................................................................ 419 420 } 421 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| [ Powered by PHPXref - Served by Debian GNU/Linux ] |