Example #1
0
 /**
  * @param BlockFrameDecorator $block
  */
 function reflow(BlockFrameDecorator $block = null)
 {
     // Check if a page break is forced
     $page = $this->_frame->get_root();
     $page->check_forced_page_break($this->_frame);
     // Bail if the page is full
     if ($page->is_full()) {
         return;
     }
     // Generated content
     $this->_set_content();
     // Collapse margins if required
     $this->_collapse_margins();
     $style = $this->_frame->get_style();
     $cb = $this->_frame->get_containing_block();
     if ($style->position === "fixed") {
         $cb = $this->_frame->get_root()->get_containing_block();
     }
     // Determine the constraints imposed by this frame: calculate the width
     // of the content area:
     list($w, $left_margin, $right_margin, $left, $right) = $this->_calculate_restricted_width();
     // Store the calculated properties
     $style->width = $w;
     $style->margin_left = $left_margin;
     $style->margin_right = $right_margin;
     $style->left = $left;
     $style->right = $right;
     // Update the position
     $this->_frame->position();
     list($x, $y) = $this->_frame->get_position();
     // Adjust the first line based on the text-indent property
     $indent = $style->length_in_pt($style->text_indent, $cb["w"]);
     $this->_frame->increase_line_width($indent);
     // Determine the content edge
     $top = $style->length_in_pt(array($style->margin_top, $style->padding_top, $style->border_top_width), $cb["h"]);
     $bottom = $style->length_in_pt(array($style->border_bottom_width, $style->margin_bottom, $style->padding_bottom), $cb["h"]);
     $cb_x = $x + $left_margin + $style->length_in_pt(array($style->border_left_width, $style->padding_left), $cb["w"]);
     $cb_y = $y + $top;
     $cb_h = $cb["h"] + $cb["y"] - $bottom - $cb_y;
     // Set the y position of the first line in this block
     $line_box = $this->_frame->get_current_line_box();
     $line_box->y = $cb_y;
     $line_box->get_float_offsets();
     // Set the containing blocks and reflow each child
     foreach ($this->_frame->get_children() as $child) {
         // Bail out if the page is full
         if ($page->is_full()) {
             break;
         }
         $child->set_containing_block($cb_x, $cb_y, $w, $cb_h);
         $this->process_clear($child);
         $child->reflow($this->_frame);
         // Don't add the child to the line if a page break has occurred
         if ($page->check_page_break($child)) {
             break;
         }
         $this->process_float($child, $cb_x, $w);
     }
     // Determine our height
     list($height, $margin_top, $margin_bottom, $top, $bottom) = $this->_calculate_restricted_height();
     $style->height = $height;
     $style->margin_top = $margin_top;
     $style->margin_bottom = $margin_bottom;
     $style->top = $top;
     $style->bottom = $bottom;
     $orig_style = $this->_frame->get_original_style();
     $needs_reposition = $style->position === "absolute" && ($style->right !== "auto" || $style->bottom !== "auto");
     // Absolute positioning measurement
     if ($needs_reposition) {
         if ($orig_style->width === "auto" && ($orig_style->left === "auto" || $orig_style->right === "auto")) {
             $width = 0;
             foreach ($this->_frame->get_line_boxes() as $line) {
                 $width = max($line->w, $width);
             }
             $style->width = $width;
         }
         $style->left = $orig_style->left;
         $style->right = $orig_style->right;
     }
     // Calculate inline-block / float auto-widths
     if (($style->display === "inline-block" || $style->float !== 'none') && $orig_style->width === 'auto') {
         $width = 0;
         foreach ($this->_frame->get_line_boxes() as $line) {
             $line->recalculate_width();
             $width = max($line->w, $width);
         }
         if ($width === 0) {
             foreach ($this->_frame->get_children() as $child) {
                 $width += $child->calculate_auto_width();
             }
         }
         $style->width = $width;
     }
     $this->_text_align();
     $this->vertical_align();
     // Absolute positioning
     if ($needs_reposition) {
         list($x, $y) = $this->_frame->get_position();
         $this->_frame->position();
         list($new_x, $new_y) = $this->_frame->get_position();
         $this->_frame->move($new_x - $x, $new_y - $y, true);
     }
     if ($block && $this->_frame->is_in_flow()) {
         $block->add_frame_to_line($this->_frame);
         // May be inline-block
         if ($style->display === "block") {
             $block->add_line();
         }
     }
 }
Example #2
0
 protected function _line_break($text)
 {
     $style = $this->_frame->get_style();
     $size = $style->font_size;
     $font = $style->font_family;
     $current_line = $this->_block_parent->get_current_line_box();
     // Determine the available width
     $line_width = $this->_frame->get_containing_block("w");
     $current_line_width = $current_line->left + $current_line->w + $current_line->right;
     $available_width = $line_width - $current_line_width;
     // Account for word-spacing
     $word_spacing = $style->length_in_pt($style->word_spacing);
     $char_spacing = $style->length_in_pt($style->letter_spacing);
     // Determine the frame width including margin, padding & border
     $text_width = $this->getFontMetrics()->getTextWidth($text, $font, $size, $word_spacing, $char_spacing);
     $mbp_width = $style->length_in_pt(array($style->margin_left, $style->border_left_width, $style->padding_left, $style->padding_right, $style->border_right_width, $style->margin_right), $line_width);
     $frame_width = $text_width + $mbp_width;
     // Debugging:
     //    Helpers::pre_r("Text: '" . htmlspecialchars($text). "'");
     //    Helpers::pre_r("width: " .$frame_width);
     //    Helpers::pre_r("textwidth + delta: $text_width + $mbp_width");
     //    Helpers::pre_r("font-size: $size");
     //    Helpers::pre_r("cb[w]: " .$line_width);
     //    Helpers::pre_r("available width: " . $available_width);
     //    Helpers::pre_r("current line width: " . $current_line_width);
     //     Helpers::pre_r($words);
     if ($frame_width <= $available_width) {
         return false;
     }
     // split the text into words
     $words = preg_split('/([\\s-]+)/u', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
     $wc = count($words);
     // Determine the split point
     $width = 0;
     $str = "";
     reset($words);
     // @todo support <shy>, <wbr>
     for ($i = 0; $i < $wc; $i += 2) {
         $word = $words[$i] . (isset($words[$i + 1]) ? $words[$i + 1] : "");
         $word_width = $this->getFontMetrics()->getTextWidth($word, $font, $size, $word_spacing, $char_spacing);
         if ($width + $word_width + $mbp_width > $available_width) {
             break;
         }
         $width += $word_width;
         $str .= $word;
     }
     $break_word = $style->word_wrap === "break-word";
     // The first word has overflowed.   Force it onto the line
     if ($current_line_width == 0 && $width == 0) {
         $s = "";
         $last_width = 0;
         if ($break_word) {
             for ($j = 0; $j < strlen($word); $j++) {
                 $s .= $word[$j];
                 $_width = $this->getFontMetrics()->getTextWidth($s, $font, $size, $word_spacing, $char_spacing);
                 if ($_width > $available_width) {
                     break;
                 }
                 $last_width = $_width;
             }
         }
         if ($break_word && $last_width > 0) {
             $width += $last_width;
             $str .= substr($s, 0, -1);
         } else {
             $width += $word_width;
             $str .= $word;
         }
     }
     $offset = mb_strlen($str);
     // More debugging:
     //     var_dump($str);
     //     print_r("Width: ". $width);
     //     print_r("Offset: " . $offset);
     return $offset;
 }