Пример #1
0
    function get_float_offsets()
    {
        if (!DOMPDF_ENABLE_CSS_FLOAT) {
            return;
        }

        static $anti_infinite_loop = 500; // FIXME smelly hack

        $reflower = $this->_block_frame->get_reflower();

        if (!$reflower) return;

        $cb_w = null;

        $block = $this->_block_frame;
        $root = $block->get_root();
        $floating_frames = $this->get_floats_inside($root);

        foreach ($floating_frames as $child_key => $floating_frame) {
            $id = $floating_frame->get_id();

            if (isset($this->floating_blocks[$id])) {
                continue;
            }

            $floating_style = $floating_frame->get_style();

            $clear = $floating_style->clear;
            $float = $floating_style->float;

            $floating_width = $floating_frame->get_margin_width();

            if (!$cb_w) {
                $cb_w = $floating_frame->get_containing_block("w");
            }

            $line_w = $this->get_width();

            if (!$floating_frame->_float_next_line && ($cb_w <= $line_w + $floating_width) && ($cb_w > $line_w)) {
                $floating_frame->_float_next_line = true;
                continue;
            }

            // If the child is still shifted by the floating element
            if ($anti_infinite_loop-- > 0 &&
                $floating_frame->get_position("y") + $floating_frame->get_margin_height() > $this->y &&
                $block->get_position("x") + $block->get_margin_width() > $floating_frame->get_position("x")
            ) {
                if ($float === "left")
                    $this->left += $floating_width;
                else
                    $this->right += $floating_width;

                $this->floating_blocks[$id] = true;
            } // else, the floating element won't shift anymore
            else {
                $root->remove_floating_frame($child_key);
            }
        }
    }
 function reflow(Block_Frame_Decorator $block = null)
 {
     $this->_frame->position();
     //FLOAT
     //$frame = $this->_frame;
     //$page = $frame->get_root();
     //if (DOMPDF_ENABLE_CSS_FLOAT && $frame->get_style()->float !== "none" ) {
     //  $page->add_floating_frame($this);
     //}
     // Set the frame's width
     $this->get_min_max_width();
     if ($block) {
         $block->add_frame_to_line($this->_frame);
     }
 }
 function get_float_offsets()
 {
     $enable_css_float = $this->_block_frame->get_dompdf()->get_option("enable_css_float");
     if (!$enable_css_float) {
         return;
     }
     static $anti_infinite_loop = 500;
     // FIXME smelly hack
     $reflower = $this->_block_frame->get_reflower();
     if (!$reflower) {
         return;
     }
     $cb_w = null;
     $block = $this->_block_frame;
     $root = $block->get_root();
     if (!$root) {
         return;
     }
     $floating_frames = $this->get_floats_inside($root);
     foreach ($floating_frames as $child_key => $floating_frame) {
         $id = $floating_frame->get_id();
         if (isset($this->floating_blocks[$id])) {
             continue;
         }
         $floating_style = $floating_frame->get_style();
         $float = $floating_style->float;
         $floating_width = $floating_frame->get_margin_width();
         if (!$cb_w) {
             $cb_w = $floating_frame->get_containing_block("w");
         }
         $line_w = $this->get_width();
         if (!$floating_frame->_float_next_line && $cb_w <= $line_w + $floating_width && $cb_w > $line_w) {
             $floating_frame->_float_next_line = true;
             continue;
         }
         // If the child is still shifted by the floating element
         if ($anti_infinite_loop-- > 0 && $floating_frame->get_position("y") + $floating_frame->get_margin_height() > $this->y && $block->get_position("x") + $block->get_margin_width() > $floating_frame->get_position("x")) {
             if ($float === "left") {
                 $this->left += $floating_width;
             } else {
                 $this->right += $floating_width;
             }
             $this->floating_blocks[$id] = true;
         } else {
             $root->remove_floating_frame($child_key);
         }
     }
 }
 function reset()
 {
     parent::reset();
     $this->_resolved_borders = array();
     $this->_content_height = 0;
     $this->_frame->reset();
 }
 function reflow(Block_Frame_Decorator $block = null)
 {
     $this->_frame->position();
     //FLOAT
     //$frame = $this->_frame;
     //$page = $frame->get_root();
     //$enable_css_float = $this->get_dompdf()->get_option("enable_css_float");
     //if ($enable_css_float && $frame->get_style()->float !== "none" ) {
     //  $page->add_floating_frame($this);
     //}
     // Set the frame's width
     $this->get_min_max_width();
     if ($block) {
         $block->add_frame_to_line($this->_frame);
     }
 }
  function reflow(Block_Frame_Decorator $block = null) {
    $frame = $this->_frame;

    // Check if a page break is forced
    $page = $frame->get_root();
    $page->check_forced_page_break($frame);

    if ( $page->is_full() )
      return;

    $style = $frame->get_style();

    // Generated content
    $this->_set_content();

    $frame->position();

    $cb = $frame->get_containing_block();

    // Add our margin, padding & border to the first and last children
    if ( ($f = $frame->get_first_child()) && $f instanceof Text_Frame_Decorator ) {
      $f_style = $f->get_style();
      $f_style->margin_left  = $style->margin_left;
      $f_style->padding_left = $style->padding_left;
      $f_style->border_left  = $style->border_left;
    }

    if ( ($l = $frame->get_last_child()) && $l instanceof Text_Frame_Decorator ) {
      $l_style = $l->get_style();
      $l_style->margin_right  = $style->margin_right;
      $l_style->padding_right = $style->padding_right;
      $l_style->border_right  = $style->border_right;
    }

    if ( $block ) {
      $block->add_frame_to_line($this->_frame);
    }

    // Set the containing blocks and reflow each child.  The containing
    // block is not changed by line boxes.
    foreach ( $frame->get_children() as $child ) {
      $child->set_containing_block($cb);
      $child->reflow($block);
    }
  }
Пример #7
0
 function get_float_offsets()
 {
     static $anti_infinite_loop;
     $reflower = $this->_block_frame->get_reflower();
     if (!$reflower) {
         return;
     }
     $cb_w = null;
     if (DOMPDF_ENABLE_CSS_FLOAT) {
         $block = $this->_block_frame;
         $root = $block->get_root();
         $floating_frames = $root->get_floating_frames();
         foreach ($floating_frames as $child_key => $floating_frame) {
             $id = $floating_frame->get_id();
             if (isset($this->floating_blocks[$id])) {
                 continue;
             }
             $float = $floating_frame->get_style()->float;
             $floating_width = $floating_frame->get_margin_width();
             if (!$cb_w) {
                 $cb_w = $floating_frame->get_containing_block("w");
             }
             $line_w = $this->get_width();
             if (!$floating_frame->_float_next_line && $cb_w <= $line_w + $floating_width && $cb_w > $line_w) {
                 $floating_frame->_float_next_line = true;
                 continue;
             }
             // If the child is still shifted by the floating element
             if ($anti_infinite_loop++ < 1000 && $floating_frame->get_position("y") + $floating_frame->get_margin_height() > $this->y && $block->get_position("x") + $block->get_margin_width() > $floating_frame->get_position("x")) {
                 if ($float === "left") {
                     $this->left += $floating_width;
                 } else {
                     $this->right += $floating_width;
                 }
                 $this->floating_blocks[$id] = true;
             } else {
                 $root->remove_floating_frame($child_key);
             }
         }
     }
 }
Пример #8
0
 /**
  * Align inline children vertically.
  * Aligns each child vertically after each line is reflowed
  */
 function vertical_align()
 {
     $canvas = null;
     foreach ($this->_frame->get_line_boxes() as $line) {
         $height = $line->h;
         foreach ($line->get_frames() as $frame) {
             $style = $frame->get_style();
             if ($style->display !== "inline" && $style->display !== "text") {
                 continue;
             }
             // FIXME?
             if ($this instanceof Table_Cell_Frame_Reflower) {
                 $align = $frame->get_frame()->get_style()->vertical_align;
             } else {
                 $align = $frame->get_frame()->get_parent()->get_style()->vertical_align;
             }
             $frame_h = $frame->get_margin_height();
             if (!isset($canvas)) {
                 $canvas = $frame->get_root()->get_dompdf()->get_canvas();
             }
             $baseline = $canvas->get_font_baseline($style->font_family, $style->font_size);
             $y_offset = 0;
             switch ($align) {
                 case "baseline":
                     $y_offset = $height * 0.8 - $baseline;
                     // The 0.8 ratio is arbitrary until we find it's meaning
                     break;
                 case "middle":
                     $y_offset = ($height * 0.8 - $baseline) / 2;
                     break;
                 case "sub":
                     $y_offset = 0.3 * $height;
                     break;
                 case "super":
                     $y_offset = -0.2 * $height;
                     break;
                 case "text-top":
                 case "top":
                     // Not strictly accurate, but good enough for now
                     break;
                 case "text-bottom":
                 case "bottom":
                     $y_offset = $height * 0.8 - $baseline;
                     break;
             }
             if ($y_offset) {
                 $frame->move(0, $y_offset);
             }
         }
     }
 }
Пример #9
0
 function get_float_offsets()
 {
     $reflower = $this->_block_frame->get_reflower();
     if (!$reflower) {
         return;
     }
     $floating_children = $reflower->get_floating_children();
     $cb_w = null;
     if (DOMPDF_ENABLE_CSS_FLOAT && !empty($floating_children)) {
         foreach ($floating_children as $child_key => $floating_child) {
             $id = $floating_child->get_id();
             if (isset($this->floating_blocks[$id])) {
                 continue;
             }
             $float = $floating_child->get_style()->float;
             $floating_width = $floating_child->get_margin_width();
             if (!$cb_w) {
                 $cb_w = $floating_child->get_containing_block("w");
             }
             $line_w = $this->get_width();
             if (!$floating_child->_float_next_line && $cb_w <= $line_w + $floating_width && $cb_w > $line_w) {
                 $floating_child->_float_next_line = true;
                 continue;
             }
             // If the child is still shifted by the floating element
             if ($floating_child->get_position("y") + $floating_child->get_margin_height() > $this->y) {
                 if ($float === "left") {
                     $this->left += $floating_width;
                 } else {
                     $this->right += $floating_width;
                 }
                 $this->floating_blocks[$id] = true;
             } else {
                 $reflower->remove_floating_child($child_key);
             }
         }
     }
 }
 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();
         }
     }
 }
 protected function _layout_line()
 {
     $style = $this->_frame->get_style();
     $text = $this->_frame->get_text();
     $size = $style->font_size;
     $font = $style->font_family;
     $word_spacing = $style->length_in_pt($style->word_spacing);
     $char_spacing = $style->length_in_pt($style->letter_spacing);
     // Determine the text height
     $style->height = Font_Metrics::get_font_height($font, $size);
     $split = false;
     $add_line = false;
     // Handle text transform:
     // http://www.w3.org/TR/CSS21/text.html#propdef-text-transform
     switch (strtolower($style->text_transform)) {
         default:
             break;
         case "capitalize":
             $text = mb_convert_case($text, MB_CASE_TITLE);
             break;
         case "uppercase":
             $text = mb_convert_case($text, MB_CASE_UPPER);
             break;
         case "lowercase":
             $text = mb_convert_case($text, MB_CASE_LOWER);
             break;
     }
     // Handle white-space property:
     // http://www.w3.org/TR/CSS21/text.html#propdef-white-space
     switch ($style->white_space) {
         default:
         case "normal":
             $this->_frame->set_text($text = $this->_collapse_white_space($text));
             if ($text == "") {
                 break;
             }
             $split = $this->_line_break($text);
             break;
         case "pre":
             $split = $this->_newline_break($text);
             $add_line = $split !== false;
             break;
         case "nowrap":
             $this->_frame->set_text($text = $this->_collapse_white_space($text));
             break;
         case "pre-wrap":
             $split = $this->_newline_break($text);
             if (($tmp = $this->_line_break($text)) !== false) {
                 $add_line = $split < $tmp;
                 $split = min($tmp, $split);
             } else {
                 $add_line = true;
             }
             break;
         case "pre-line":
             // Collapse white-space except for \n
             $this->_frame->set_text($text = preg_replace("/[ \t]+/u", " ", $text));
             if ($text == "") {
                 break;
             }
             $split = $this->_newline_break($text);
             if (($tmp = $this->_line_break($text)) !== false) {
                 $add_line = $split < $tmp;
                 $split = min($tmp, $split);
             } else {
                 $add_line = true;
             }
             break;
     }
     // Handle degenerate case
     if ($text === "") {
         return;
     }
     if ($split !== false) {
         // Handle edge cases
         if ($split == 0 && $text === " ") {
             $this->_frame->set_text("");
             return;
         }
         if ($split == 0) {
             // Trim newlines from the beginning of the line
             //$this->_frame->set_text(ltrim($text, "\n\r"));
             $this->_block_parent->add_line();
             $this->_frame->position();
             // Layout the new line
             $this->_layout_line();
         } else {
             if ($split < mb_strlen($this->_frame->get_text())) {
                 // split the line if required
                 $this->_frame->split_text($split);
                 $t = $this->_frame->get_text();
                 // Remove any trailing newlines
                 if ($split > 1 && $t[$split - 1] === "\n") {
                     $this->_frame->set_text(mb_substr($t, 0, -1));
                 }
                 // Do we need to trim spaces on wrapped lines? This might be desired, however, we
                 // can't trim the lines here or the layout will be affected if trimming the line
                 // leaves enough space to fit the next word in the text stream (because pdf layout
                 // is performed elsewhere).
                 /*if (!$this->_frame->get_prev_sibling() && !$this->_frame->get_next_sibling()) {
                     $t = $this->_frame->get_text();
                     $this->_frame->set_text( trim($t) );
                   }*/
             }
         }
         if ($add_line) {
             $this->_block_parent->add_line();
             $this->_frame->position();
         }
     } else {
         // Remove empty space from start and end of line, but only where there isn't an inline sibling
         // and the parent node isn't an inline element with siblings
         // FIXME: Include non-breaking spaces?
         $t = $this->_frame->get_text();
         $parent = $this->_frame->get_parent();
         $is_inline_frame = get_class($parent) === 'Inline_Frame_Decorator';
         if (!$is_inline_frame && !$this->_frame->get_next_sibling() || $is_inline_frame && !$parent->get_next_sibling()) {
             $t = rtrim($t);
         }
         if (!$is_inline_frame && !$this->_frame->get_prev_sibling() || $is_inline_frame && !$parent->get_prev_sibling()) {
             $t = ltrim($t);
         }
         $this->_frame->set_text($t);
     }
     // Set our new width
     $width = $this->_frame->recalculate_width();
 }
Пример #12
0
 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);
     }
 }
Пример #13
0
 function reflow(Block_Frame_Decorator $block = null)
 {
     $frame = $this->_frame;
     $page = $frame->get_root();
     $page->check_forced_page_break($this->_frame);
     if ($page->is_full()) {
         return;
     }
     $this->_block_parent = $frame->find_block_parent();
     // Left trim the text if this is the first text on the line and we're
     // collapsing white space
     //     if ( $this->_block_parent->get_current_line()->w == 0 &&
     //          ($frame->get_style()->white_space !== "pre" ||
     //           $frame->get_style()->white_space !== "pre-wrap") ) {
     //       $frame->set_text( ltrim( $frame->get_text() ) );
     //     }
     $frame->position();
     $this->_layout_line();
     if ($block) {
         $block->add_frame_to_line($frame);
     }
 }
 /**
  * @param Block_Frame_Decorator $block
  */
 function reflow(Block_Frame_Decorator $block = null)
 {
     /**
      * @var Table_Frame_Decorator
      */
     $frame = $this->_frame;
     // Check if a page break is forced
     $page = $frame->get_root();
     $page->check_forced_page_break($frame);
     // Bail if the page is full
     if ($page->is_full()) {
         return;
     }
     // Let the page know that we're reflowing a table so that splits
     // are suppressed (simply setting page-break-inside: avoid won't
     // work because we may have an arbitrary number of block elements
     // inside tds.)
     $page->table_reflow_start();
     // Collapse vertical margins, if required
     $this->_collapse_margins();
     $frame->position();
     // Table layout algorithm:
     // http://www.w3.org/TR/CSS21/tables.html#auto-table-layout
     if (is_null($this->_state)) {
         $this->get_min_max_width();
     }
     $cb = $frame->get_containing_block();
     $style = $frame->get_style();
     // This is slightly inexact, but should be okay.  Add half the
     // border-spacing to the table as padding.  The other half is added to
     // the cells themselves.
     if ($style->border_collapse === "separate") {
         list($h, $v) = $style->border_spacing;
         $v = $style->length_in_pt($v) / 2;
         $h = $style->length_in_pt($h) / 2;
         $style->padding_left = $style->length_in_pt($style->padding_left, $cb["w"]) + $h;
         $style->padding_right = $style->length_in_pt($style->padding_right, $cb["w"]) + $h;
         $style->padding_top = $style->length_in_pt($style->padding_top, $cb["h"]) + $v;
         $style->padding_bottom = $style->length_in_pt($style->padding_bottom, $cb["h"]) + $v;
     }
     $this->_assign_widths();
     // Adjust left & right margins, if they are auto
     $width = $style->width;
     $left = $style->margin_left;
     $right = $style->margin_right;
     $diff = $cb["w"] - $width;
     if ($left === "auto" && $right === "auto") {
         if ($diff < 0) {
             $left = 0;
             $right = $diff;
         } else {
             $left = $right = $diff / 2;
         }
         $style->margin_left = "{$left} pt";
         $style->margin_right = "{$right} pt";
     } else {
         if ($left === "auto") {
             $left = $style->length_in_pt($cb["w"] - $right - $width, $cb["w"]);
         }
         if ($right === "auto") {
             $left = $style->length_in_pt($left, $cb["w"]);
         }
     }
     list($x, $y) = $frame->get_position();
     // Determine the content edge
     $content_x = $x + $left + $style->length_in_pt(array($style->padding_left, $style->border_left_width), $cb["w"]);
     $content_y = $y + $style->length_in_pt(array($style->margin_top, $style->border_top_width, $style->padding_top), $cb["h"]);
     if (isset($cb["h"])) {
         $h = $cb["h"];
     } else {
         $h = null;
     }
     $cellmap = $frame->get_cellmap();
     $col =& $cellmap->get_column(0);
     $col["x"] = $content_x;
     $row =& $cellmap->get_row(0);
     $row["y"] = $content_y;
     $cellmap->assign_x_positions();
     // Set the containing block of each child & reflow
     foreach ($frame->get_children() as $child) {
         // Bail if the page is full
         if (!$page->in_nested_table() && $page->is_full()) {
             break;
         }
         $child->set_containing_block($content_x, $content_y, $width, $h);
         $child->reflow();
         if (!$page->in_nested_table()) {
             $page->check_page_break($child);
         }
     }
     // Assign heights to our cells:
     $style->height = $this->_calculate_height();
     if ($style->border_collapse === "collapse") {
         // Unset our borders because our cells are now using them
         $style->border_style = "none";
     }
     $page->table_reflow_end();
     // Debugging:
     //echo ($this->_frame->get_cellmap());
     if ($block && $style->float === "none" && $frame->is_in_flow()) {
         $block->add_frame_to_line($frame);
         $block->add_line();
     }
 }
Пример #15
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;

        // split the text into words
        $words = preg_split('/([\s-]+)/u', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
        $wc = count($words);

        // 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 = Font_Metrics::get_text_width($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:
//    pre_r("Text: '" . htmlspecialchars($text). "'");
//    pre_r("width: " .$frame_width);
//    pre_r("textwidth + delta: $text_width + $mbp_width");
//    pre_r("font-size: $size");
//    pre_r("cb[w]: " .$line_width);
//    pre_r("available width: " . $available_width);
//    pre_r("current line width: " . $current_line_width);

//     pre_r($words);

        if ($frame_width <= $available_width)
            return false;

        // 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 = Font_Metrics::get_text_width($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 = Font_Metrics::get_text_width($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:
//     pre_var_dump($str);
//     pre_r("Width: ". $width);
//     pre_r("Offset: " . $offset);

        return $offset;

    }