function reflow(Frame_Decorator $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->counter_increment && ($increment = $style->counter_increment) !== "none") {
         $this->_frame->increment_counter($increment);
     }
     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 . "pt";
     $style->margin_left = $left_margin . "pt";
     $style->margin_right = $right_margin . "pt";
     $style->left = $left . "pt";
     $style->right = $right . "pt";
     // 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
     $this->_frame->set_current_line($cb_y);
     $floating_children = array();
     // 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;
         }
         // Floating siblings
         if (DOMPDF_ENABLE_CSS_FLOAT && count($floating_children)) {
             $offset_left = 0;
             $offset_right = 0;
             // We need to reflow the child to know its initial x position
             $child->set_containing_block($cb_x, $cb_y, $w, $cb_h);
             $child->reflow($this->_frame);
             $current_line = $this->_frame->get_current_line();
             foreach ($floating_children as $child_key => $floating_child) {
                 $float = $floating_child->get_style()->float;
                 $floating_width = $floating_child->get_margin_width();
                 $floating_x = $floating_child->get_position("x");
                 if ($float === "left") {
                     if ($current_line["left"] + $child->get_position("x") > $floating_x + $floating_width) {
                         continue;
                     }
                 } else {
                     if ($current_line["left"] + $child->get_position("x") + $child->get_margin_width() < $w - $floating_width - $current_line["right"]) {
                         continue;
                     }
                 }
                 // If the child is still shifted by the floating element
                 if ($floating_child->get_position("y") + $floating_child->get_margin_height() > $current_line["y"]) {
                     if ($float === "left") {
                         $offset_left += $floating_width;
                     } else {
                         $offset_right += $floating_width;
                     }
                 } else {
                     unset($floating_children[$child_key]);
                 }
             }
             if ($offset_left) {
                 $this->_frame->set_current_line(array("left" => $offset_left));
             }
             if ($offset_right) {
                 $this->_frame->set_current_line(array("right" => $offset_right));
             }
         }
         $child->set_containing_block($cb_x, $cb_y, $w, $cb_h);
         $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;
         }
         $child_style = $child->get_style();
         if (DOMPDF_ENABLE_CSS_FLOAT && $child_style->float !== "none") {
             $floating_children[] = $child;
             // Remove next frame's beginning whitespace
             $next = $child->get_next_sibling();
             if ($next && $next instanceof Text_Frame_Decorator) {
                 $next->set_text(ltrim($next->get_text()));
             }
             $float_x = $cb_x;
             $float_y = $this->_frame->get_current_line("y");
             $child_style = $child->get_style();
             switch ($child_style->float) {
                 case "left":
                     break;
                 case "right":
                     $width = $w;
                     $float_x += $width - $child->get_margin_width();
                     break;
             }
             $child->set_position($float_x, $float_y);
         }
     }
     // 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;
     $this->_text_align();
     $this->vertical_align();
     if ($block) {
         $block->add_frame_to_line($this->_frame);
     }
 }
 function reflow(Frame_Decorator $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 . "pt";
     $style->margin_left = $left_margin . "pt";
     $style->margin_right = $right_margin . "pt";
     $style->left = $left . "pt";
     $style->right = $right . "pt";
     // 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
     $this->_frame->set_current_line($cb_y);
     $this->_frame->get_current_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;
     $needs_reposition = $style->position === "absolute" && ($style->right !== "auto" || $style->bottom !== "auto");
     // Absolute positioning measurement
     if ($needs_reposition) {
         $orig_style = $this->_frame->get_original_style();
         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;
     }
     $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();
         }
     }
 }
 /**
  * Adjust the justification of each of our lines.
  * http://www.w3.org/TR/CSS21/text.html#propdef-text-align
  */
 protected function _text_align()
 {
     $style = $this->_frame->get_style();
     $w = $this->_frame->get_containing_block("w");
     $width = $style->length_in_pt($style->width, $w);
     switch ($style->text_align) {
         default:
         case "left":
             foreach ($this->_frame->get_line_boxes() as $line) {
                 if (!$line->left) {
                     continue;
                 }
                 foreach ($line->get_frames() as $frame) {
                     if ($frame instanceof Block_Frame_Decorator) {
                         continue;
                     }
                     $frame->set_position($frame->get_position("x") + $line->left);
                 }
             }
             return;
         case "right":
             foreach ($this->_frame->get_line_boxes() as $line) {
                 // Move each child over by $dx
                 $dx = $width - $line->w - $line->right;
                 foreach ($line->get_frames() as $frame) {
                     // Block frames are not aligned by text-align
                     if ($frame instanceof Block_Frame_Decorator) {
                         continue;
                     }
                     $frame->set_position($frame->get_position("x") + $dx);
                 }
             }
             break;
         case "justify":
             // We justify all lines except the last one
             $lines = $this->_frame->get_line_boxes();
             // needs to be a variable (strict standards)
             array_pop($lines);
             foreach ($lines as $i => $line) {
                 if ($line->br) {
                     unset($lines[$i]);
                 }
             }
             // One space character's width. Will be used to get a more accurate spacing
             $space_width = Font_Metrics::get_text_width(" ", $style->font_family, $style->font_size);
             foreach ($lines as $line) {
                 if ($line->left) {
                     foreach ($line->get_frames() as $frame) {
                         if (!$frame instanceof Text_Frame_Decorator) {
                             continue;
                         }
                         $frame->set_position($frame->get_position("x") + $line->left);
                     }
                 }
                 // Only set the spacing if the line is long enough.  This is really
                 // just an aesthetic choice ;)
                 //if ( $line["left"] + $line["w"] + $line["right"] > self::MIN_JUSTIFY_WIDTH * $width ) {
                 // Set the spacing for each child
                 if ($line->wc > 1) {
                     $spacing = ($width - ($line->left + $line->w + $line->right) + $space_width) / ($line->wc - 1);
                 } else {
                     $spacing = 0;
                 }
                 $dx = 0;
                 foreach ($line->get_frames() as $frame) {
                     if (!$frame instanceof Text_Frame_Decorator) {
                         continue;
                     }
                     $text = $frame->get_text();
                     $spaces = mb_substr_count($text, " ");
                     $char_spacing = $style->length_in_pt($style->letter_spacing);
                     $_spacing = $spacing + $char_spacing;
                     $frame->set_position($frame->get_position("x") + $dx);
                     $frame->set_text_spacing($_spacing);
                     $dx += $spaces * $_spacing;
                 }
                 // The line (should) now occupy the entire width
                 $line->w = $width;
                 //}
             }
             break;
         case "center":
         case "centre":
             foreach ($this->_frame->get_line_boxes() as $line) {
                 // Centre each line by moving each frame in the line by:
                 $dx = ($width + $line->left - $line->w - $line->right) / 2;
                 foreach ($line->get_frames() as $frame) {
                     // Block frames are not aligned by text-align
                     if ($frame instanceof Block_Frame_Decorator) {
                         continue;
                     }
                     $frame->set_position($frame->get_position("x") + $dx);
                 }
             }
             break;
     }
 }