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(); }