function testPagebreakBorderTestNoBorder() { $media = new Media(array('width' => 100, 'height' => 200 / mm2pt(1)), array('top' => 0, 'bottom' => 0, 'left' => 0, 'right' => 0)); $tree = $this->runPipeline(' <html> <head> <style type="text/css"> body { font-size: 10pt; line-height: 1; orphans:0; widows: 0; padding: 0; margin: 0; } #first { line-height: 1; height: 180pt; } #second { width: 3em; } </style> </head> <body> <div id="first"> </div> <div id="second"> LINE1<!--Page break should be here--> LINE2 LINE3 LINE4 LINE5 </div> </body> </html> ', $media); /** * Calculate page heights */ $page_heights = PageBreakLocator::getPages($tree, mm2pt($media->real_height()), mm2pt($media->height() - $media->margins['top'])); $first_div = $tree->get_element_by_id('first'); $second_div = $tree->get_element_by_id('second'); $this->assertEqual(count($page_heights), 2, sprintf("Two pages expected, got %s", count($page_heights))); $this->assertEqual($page_heights[0], $first_div->get_full_height() + pt2pt(20)); }
function testPagebreakTable2() { $media = new Media(array('width' => 100, 'height' => 200 / mm2pt(1)), array('top' => 0, 'bottom' => 0, 'left' => 0, 'right' => 0)); $tree = $this->runPipeline(' <html> <head> body { font-size: 10pt; line-height: 1; padding: 0; margin: 0; } table { line-height: 1; } </style> </head> <body> <table cellpadding="0" cellspacing="0" id="table"> <tr><td id="cell">TEXT1_1<br/>TEXT1_2</td></tr> </table> </body> </html> ', $media); $locations = PageBreakLocator::_getBreakLocations($tree); $table = $tree->get_element_by_id('table'); $cell = $tree->get_element_by_id('cell'); $line1 = $cell->content[0]->getLineBox(0); $this->assertEqual(count($locations), 3, "Testing number of page breaks inside a table with one cell & several text lines inside [%s]"); $this->assertEqual($locations[0]->location, $table->get_top_margin(), "First page break should be at the table top [%s]"); $this->assertEqual($locations[1]->location, $line1->bottom, "Second page break should be at the bottom of the first line box in the table cell [%s]"); $this->assertEqual($locations[2]->location, $table->get_bottom_margin(), "Last page break should be at the table bottom [%s]"); }
function init() { // Include the class file and create Html2ps instance App::import('vendor', 'Html2PsConfig', array('file' => 'html2ps' . DS . 'config.inc.php')); App::import('vendor', 'Html2Ps', array('file' => 'html2ps' . DS . 'pipeline.factory.class.php')); parse_config_file(APP . 'vendors' . DS . 'html2ps' . DS . 'html2ps.config'); global $g_config; $g_config = array('cssmedia' => 'screen', 'renderimages' => true, 'renderforms' => false, 'renderlinks' => true, 'mode' => 'html', 'debugbox' => false, 'draw_page_border' => false); $this->media = Media::predefined('A4'); $this->media->set_landscape(false); $this->media->set_margins(array('left' => 0, 'right' => 0, 'top' => 0, 'bottom' => 0)); $this->media->set_pixels(1024); global $g_px_scale; $g_px_scale = mm2pt($this->media->width() - $this->media->margins['left'] - $this->media->margins['right']) / $this->media->pixels; global $g_pt_scale; $g_pt_scale = $g_pt_scale * 1.43; $this->p = PipelineFactory::create_default_pipeline("", ""); switch ($this->output) { case 'download': $this->p->destination = new DestinationDownload($this->filename); break; case 'file': $this->p->destination = new DestinationFile($this->filename); break; default: $this->p->destination = new DestinationBrowser($this->filename); break; } }
function reflow(&$media) { $this->put_left(mm2pt($media->margins['left'])); $this->put_top(mm2pt($media->height() - $media->margins['top'])); $this->put_width(mm2pt($media->real_width())); $this->put_height(mm2pt($media->real_height())); }
function testWidthAbsolutePositioned1() { $media = null; $pipeline = null; $tree = $this->runPipeline(file_get_contents('test.width.absolute.positioned.1.html'), $media, $pipeline); $font_size = $tree->getCSSProperty(CSS_FONT_SIZE); $base = $font_size->getPoints(); $element =& $tree->get_element_by_id('div1'); $this->assertWithinMargin($element->get_width(), $pipeline->output_driver->stringwidth('No positioning data at all', 'Times-Roman', 'iso-8859-1', $base), 0); $element =& $tree->get_element_by_id('div2'); $this->assertWithinMargin($element->get_width(), $pipeline->output_driver->stringwidth('Left', 'Times-Roman', 'iso-8859-1', $base), 0); $element =& $tree->get_element_by_id('div3'); $this->assertEqual($element->get_width(), mm2pt($media->real_width()) - px2pt(200)); $element =& $tree->get_element_by_id('div4'); $this->assertEqual($element->get_width(), px2pt(100)); $element =& $tree->get_element_by_id('div5'); $this->assertEqual($element->get_width(), px2pt(100)); $element =& $tree->get_element_by_id('div6'); $this->assertEqual($element->get_width(), px2pt(100)); $element =& $tree->get_element_by_id('div7'); $this->assertEqual($element->get_width(), px2pt(100)); $element =& $tree->get_element_by_id('div8'); $this->assertWithinMargin($element->get_width(), $pipeline->output_driver->stringwidth('Right', 'Times-Roman', 'iso-8859-1', $base), 0); $element =& $tree->get_element_by_id('div9'); $this->assertEqual($element->get_width(), mm2pt($media->real_width()) - px2pt(100), 'DIV with long text and "left" property has incorrect width [%s]'); $element =& $tree->get_element_by_id('div10'); $this->assertEqual($element->get_width(), mm2pt($media->real_width()) - px2pt(100), 'DIV with long text and "right" property has incorrect width [%s]'); $element =& $tree->get_element_by_id('div11'); $this->assertEqual($element->get_width(), mm2pt($media->real_width()), 'DIV with long text and no positioning properties has incorrect width [%s]'); $element =& $tree->get_element_by_id('div12'); $this->assertEqual($element->get_width(), mm2pt($media->real_width()) - px2pt(200), 'DIV with long text and both "left" and "right" properties has incorrect width [%s]'); }
function parse($value) { if ($value == '') { return null; } // First attempt to create media with predefined name if (preg_match('/^(\\w+)(?:\\s+(portrait|landscape))?$/', $value, $matches)) { $name = $matches[1]; $landscape = isset($matches[2]) && $matches[2] == 'landscape'; $media =& Media::predefined($name); if (is_null($media)) { return null; } return array('size' => array('width' => $media->get_width(), 'height' => $media->get_height()), 'landscape' => $landscape); } // Second, attempt to create media with predefined size $parts = preg_split('/\\s+/', $value); $width_str = $parts[0]; $height_str = isset($parts[1]) ? $parts[1] : $parts[0]; $width = units2pt($width_str); $height = units2pt($height_str); if ($width == 0 || $height == 0) { return null; } return array('size' => array('width' => $width / mm2pt(1) / pt2pt(1), 'height' => $height / mm2pt(1) / pt2pt(1)), 'landscape' => false); }
function units2pt($value, $font_size = null) { $unit = Value::unit_from_string($value); switch ($unit) { case UNIT_PT: return pt2pt((double) $value); case UNIT_PX: return px2pt((double) $value); case UNIT_MM: return pt2pt(mm2pt((double) $value)); case UNIT_CM: return pt2pt(mm2pt((double) $value * 10)); case UNIT_EM: return em2pt((double) $value, $font_size); case UNIT_EX: return ex2pt((double) $value, $font_size); case UNIT_IN: return pt2pt((double) $value * 72); // points used by CSS 2.1 are equal to 1/72nd of an inch. // points used by CSS 2.1 are equal to 1/72nd of an inch. case UNIT_PC: return pt2pt((double) $value * 12); // 1 pica equals to 12 points. // 1 pica equals to 12 points. default: global $g_config; if ($g_config['mode'] === 'quirks') { return px2pt((double) $value); } else { return 0; } } }
function TestContainingBlockAbsolute1() { $tree = $this->runPipeline(' <style type="text/css"> #container { padding: 10mm; margin: 50mm; position: relative; top: 0; left: 0; } #block { position: absolute; top: 3mm; left: 2mm; margin: 7mm; } </style> <div id="container"> <div id="block"> </div><!--#block--> </div><!--#container--> '); $block =& $tree->get_element_by_id('block'); $container =& $tree->get_element_by_id('container'); $this->assertEqual($block->get_top_margin(), $container->get_top_padding() - mm2pt(3)); $this->assertEqual($block->get_left_margin(), $container->get_left_padding() + mm2pt(2)); }
function TestTextareaHeight1() { $tree = $this->runPipeline(' <textarea id="textarea" style="height: 8cm;">TEXT</textarea> '); $element =& $tree->get_element_by_id('textarea'); $this->assertEqual($element->get_full_height(), mm2pt(80)); }
function testCSSPageBreakAfter2() { $tree = $this->runPipeline(file_get_contents('test.css.page.break.after.2.html'), $media); $page_heights = PageBreakLocator::getPages($tree, mm2pt($media->real_height()), mm2pt($media->height() - $media->margins['top'])); $this->assertEqual(count($page_heights), 2); $div = $tree->get_element_by_id('div'); $h1 = $tree->get_element_by_id('h1'); $this->assertEqual($page_heights[0], $div->get_full_height()); }
function run(&$pipeline, &$media, &$box) { $num_pages = ceil($box->get_height() / mm2pt($media->real_height())); $page_heights = array(); for ($i = 0; $i < $num_pages; $i++) { $page_heights[] = mm2pt($media->real_height()); } return $page_heights; }
function testPagebreakFixedHeight1() { $media = new Media(array('width' => 100, 'height' => 200 / mm2pt(1)), array('top' => 0, 'bottom' => 0, 'left' => 0, 'right' => 0)); $tree = $this->runPipeline(file_get_contents('test.pagebreak.fixed.height.1.html'), $media); $page_heights = PageBreakLocator::getPages($tree, mm2pt($media->real_height()), mm2pt($media->height() - $media->margins['top'])); $div = $tree->get_element_by_id('div'); $this->assertEqual(count($page_heights), 2, sprintf("Two pages expected, got %s", count($page_heights))); $this->assertEqual($page_heights[0], 200); }
function guess_page(&$element, $page_heights, &$media) { $page_index = 0; $bottom = mm2pt($media->height() - $media->margins['top']); do { $bottom -= $page_heights[$page_index]; $page_index++; } while ($element->get_top() < $bottom); return $page_index; }
function handle_before_page_heights($params) { $pipeline =& $params['pipeline']; $document =& $params['document']; $media =& $params['media']; $boxes = $pipeline->reflow_margin_boxes(0, $media); $this->_top_margin = max($boxes[CSS_MARGIN_BOX_SELECTOR_TOP]->get_real_full_height(), $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_LEFT_CORNER]->get_real_full_height(), $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_LEFT]->get_real_full_height(), $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_CENTER]->get_real_full_height(), $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT]->get_real_full_height(), $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_RIGHT_CORNER]->get_real_full_height()); $this->_bottom_margin = max($boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM]->get_real_full_height(), $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT_CORNER]->get_real_full_height(), $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_LEFT]->get_real_full_height(), $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_CENTER]->get_real_full_height(), $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT]->get_real_full_height(), $boxes[CSS_MARGIN_BOX_SELECTOR_BOTTOM_RIGHT_CORNER]->get_real_full_height()); $media->margins['top'] = $this->_top_margin / mm2pt(1); $media->margins['bottom'] = $this->_bottom_margin / mm2pt(1); $pipeline->output_driver->update_media($media); $pipeline->_setupScales($media); }
function testLineBoxTop1() { $media = new Media(array('width' => 100, 'height' => 200 / mm2pt(1)), array('top' => 0, 'bottom' => 0, 'left' => 0, 'right' => 0)); $tree = $this->runPipeline(' <html> <head> body { font-size: 10pt; line-height: 1; padding: 0; margin: 0; } </style> </head> <body>TEXT</body> </html> ', $media); $line_box = $tree->content[0]->getLineBox(0); $this->assertEqual($tree->content[0]->get_top(), $line_box->top, "Comparing line box top and inline box top [%s]"); }
function testCSSParseMarginBoxesTopLeftSize() { parse_config_file('../html2ps.config'); $media =& Media::predefined('A4'); $media->set_margins(array('left' => 10, 'top' => 10, 'right' => 10, 'bottom' => 10)); $pipeline =& PipelineFactory::create_default_pipeline('utf-8', 'test.pdf'); $pipeline->_prepare($media); $pipeline->_cssState = array(new CSSState(CSS::get())); parse_css_atpage_rules('@page { @top-left { content: "TEXT"; } }', $pipeline); $boxes = $pipeline->reflow_margin_boxes(1, $media); $box =& $boxes[CSS_MARGIN_BOX_SELECTOR_TOP_LEFT]; $this->assertNotEqual($box->get_width(), 0); $expected_width = $pipeline->output_driver->stringwidth('TEXT', 'Times-Roman', 'iso-8859-1', 12); $this->assertTrue($box->get_width() >= $expected_width); $this->assertEqual($box->get_height(), mm2pt(10)); }
function testTableColumnWidth4() { $media = null; $tree = $this->runPipeline(file_get_contents('test.table.column.width.4.html'), $media); $container_table =& $tree->get_element_by_id('table'); $cell1 =& $tree->get_element_by_id('cell1'); $cell2 =& $tree->get_element_by_id('cell2'); $cell =& $tree->get_element_by_id('container-cell'); $this->assertEqual($container_table->get_width(), mm2pt($media->real_width()) * 0.9); $container_cell_width = $cell->get_width(); $container_cell_min_width = $cell->content[0]->get_width(); $this->assertTrue($container_cell_min_width <= $container_cell_width, sprintf('Container cell width (%s) is less than content minimal width (%s)', $container_cell_width, $container_cell_min_width)); $cell_width = $cell1->get_width() + $cell2->get_width() + $cell->get_width(); $table_width = $container_table->get_width(); $this->assertTrue($cell_width <= $table_width, sprintf('Total cell width (%s) is greater than table width (%s)', $cell_width, $table_width)); }
function units2pt($value, $font_size = null) { $units = substr($value, strlen($value) - 2, 2); switch ($units) { case "pt": return pt2pt((double) $value); case "px": return px2pt((double) $value); case "mm": return mm2pt((double) $value); case "cm": return mm2pt((double) $value * 10); // FIXME: check if it will work correcty in all situations (order of css rule application may vary). // FIXME: check if it will work correcty in all situations (order of css rule application may vary). case "em": if (is_null($font_size)) { $fs = get_font_size(); // $fs_parts = explode(" ", $fs); // if (count($fs_parts) == 2) { // return units2pt(((double)$value) * $fs_parts[0]*EM_KOEFF . $fs_parts[1]); // } else { return pt2pt((double) $value * $fs * EM_KOEFF); // }; } else { return $font_size * (double) $value * EM_KOEFF; } case "ex": if (is_null($font_size)) { $fs = get_font_size(); // $fs_parts = explode(" ", $fs); // if (count($fs_parts) == 2) { // return units2pt(((double)$value) * $fs_parts[0]*EX_KOEFF . $fs_parts[1]); // } else { return pt2pt((double) $value * $fs * EX_KOEFF); // }; } else { return $font_size * (double) $value * EX_KOEFF; } default: global $g_config; if ($g_config['mode'] === 'quirks') { return px2pt((double) $value); } else { return 0; } } }
function testPositionHorizontalbsolutePositioned1() { $media = null; $pipeline = null; $tree = $this->runPipeline(file_get_contents('test.position.horizontal.absolute.positioned.1.html'), $media, $pipeline); $font_size = $tree->getCSSProperty(CSS_FONT_SIZE); $base = $font_size->getPoints(); $element =& $tree->get_element_by_id('div1'); $this->assertEqual($element->get_left(), mm2pt($media->margins['left']), 'DIV with no positioning is positioned incorrectly [%s]'); $element =& $tree->get_element_by_id('div2'); $this->assertEqual($element->get_left(), mm2pt($media->margins['left']) + px2pt(100), 'DIV with "left" property is positioned incorrectly [%s]'); $element =& $tree->get_element_by_id('div3'); $this->assertEqual($element->get_right(), mm2pt($media->width() - $media->margins['right']) - px2pt(100), 'DIV with "right" property is positioned incorrectly [%s]'); $element =& $tree->get_element_by_id('div4'); $this->assertEqual($element->get_left(), mm2pt($media->margins['left']), 'DIV with long text and "right" property is positioned incorrectly [%s]'); $element =& $tree->get_element_by_id('div5'); $this->assertEqual($element->get_left(), mm2pt($media->margins['left']) + px2pt(100), 'DIV with long text and "left" property is positioned incorrectly [%s]'); }
function TestTableAbsolute1() { $tree = $this->runPipeline(' <style type="text/css"> body { margin: 0; padding: 0; } </style> <table id="table" style="position: absolute; left: 11mm; top: 17mm;" cellpadding="0" cellspacing="0"> <tr><td> </td></tr> </table> '); $table = $tree->get_element_by_id('table'); $body = $tree->get_body(); $this->assertEqual($table->get_top_margin(), $body->get_top() - mm2pt(17)); $this->assertEqual($table->get_left_margin(), mm2pt(11)); }
function TestBlockAbsolute1() { $tree = $this->runPipeline(' <style type="text/css"> body { margin: 0; padding: 0; } </style> <div id="block" style="position: absolute; left: 10mm; top: 20mm;"> </div> '); $block = $tree->get_element_by_id('block'); $body = $tree->get_body(); $this->assertEqual($block->get_top_margin(), $body->get_top() - mm2pt(20)); $this->assertEqual($block->get_left_margin(), mm2pt(10)); }
function testFontSizeMM() { $tree = $this->runPipeline(' <html> <head> <style type="text/css"> body { font-size: 10mm; line-height: 1; } </style> </head> <body> TEXT </body> </html> '); $inline = $tree->get_first(); $text = $inline->get_first(); $this->assertEqual($text->words[0], "TEXT"); $this->assertWithinMargin($text->get_full_height(), mm2pt(10), 0.01); }
function process(&$box, &$media, &$driver) { // Calculate the size of text boxes $box->reflow_text($driver); // Explicitly remove any height declarations from the BODY-generated box; // BODY should always fill last page completely. Percentage height of the BODY is meaningless // on the paged media. $box->_height_constraint = new HCConstraint(null, null, null); // As BODY generated box have zero calculated width at the very moment, // and we need some box to use as a parameter to _calc_percentage_margins, // we'll create a fake box having with equal to the viewport width. $media_box = new BlockBox(); $media_box->width = mm2pt($media->width() - $media->margins['left'] - $media->margins['right']); // Calculate actual margin values $box->_calc_percentage_margins($media_box); $box->width = mm2pt($media->width() - $media->margins['left'] - $media->margins['right']) - $box->_get_hor_extra(); $box->height = mm2pt($media->height() - $media->margins['top'] - $media->margins['bottom']) - $box->_get_vert_extra(); $box->put_top(mm2pt($media->height() - $media->margins['top']) - $box->get_extra_top()); $box->put_left(mm2pt($media->margins['left']) + $box->get_extra_left()); $box->to_ps($driver); }
/** * Checks if it is possible to make an incorrect page break in a table with * different font size in different cells */ function testPagebreakTableBr1() { $media = new Media(array('width' => 100, 'height' => 200 / mm2pt(1)), array('top' => 0, 'bottom' => 0, 'left' => 0, 'right' => 0)); $tree = $this->runPipeline(' <html> <head> body { font-size: 10pt; line-height: 1; padding: 0; margin: 0; } td.small { font-size: 20pt; } </style> </head> <body> <table cellpadding="0" cellspacing="0"> <tr> <td> SMALL<br/> SMALL<br/> SMALL<br/> SMALL<br/> SMALL<br/> </td> </tr> </table> </body> </html> ', $media); /** * Calculate page heights */ $locations = PageBreakLocator::_getBreakLocations($tree); $this->assertEqual(count($locations), 6); }
function testTableTopBoundary2() { $media = new Media(array('width' => 100, 'height' => 200 / mm2pt(1)), array('top' => 0, 'bottom' => 0, 'left' => 0, 'right' => 0)); $tree = $this->runPipeline(' <html> <head> body { font-size: 10pt; line-height: 1; padding: 0; margin: 0; } </style> </head> <body> <table cellpadding="0" cellspacing="0" id="table"> <tr><td id="cell">TEXT1<br/>TEXT2</td></tr> </table> </body> </html> ', $media); $table = $tree->get_element_by_id('table'); $cell = $tree->get_element_by_id('cell'); $this->assertEqual($table->get_top_margin(), $cell->get_top_margin(), "Comparing table and cell top margins for the table containins one cell [%s]"); $text = $cell->content[0]->content[0]; $this->assertEqual($text->get_top_margin(), $cell->get_top_margin(), "Comparing cell and cell content top margins for the table containins one cell [%s]"); }
function testPagebreakWithBR() { $media = new Media(array('width' => 100, 'height' => 200 / mm2pt(1)), array('top' => 0, 'bottom' => 0, 'left' => 0, 'right' => 0)); $tree = $this->runPipeline(' <html> <head> body { font-size: 10pt; line-height: 1; padding: 0; margin: 0; } </style> </head> <body> <div> LINE1<br/> LINE2<br/> LINE3<br/> LINE4<br/> LINE5<br/> </div> </body> </html> ', $media); $locations = PageBreakLocator::_getBreakLocations($tree); $this->assertEqual(count($locations), 6); }
function testLineBoxNested1() { $media = new Media(array('width' => 100, 'height' => 200 / mm2pt(1)), array('top' => 0, 'bottom' => 0, 'left' => 0, 'right' => 0)); $tree = $this->runPipeline(' <html> <head> body { font-size: 10pt; line-height: 1; padding: 0; margin: 0; } </style> </head> <body> <span id="outer" style="border: solid black 1px;"> <span id="inner1" style="background-color: red;">TEXT</span> <span id="inner2" style="background-color: green; font-size: 2em;">TEXT</span> <span id="inner3" style="background-color: red;">TEXT</span> </span> </body> </html> ', $media); $outer = $tree->get_element_by_id('outer'); $outer_line = $outer->getLineBox(0); $inner1 = $tree->get_element_by_id('inner1'); $inner1_line = $inner1->getLineBox(0); $inner2 = $tree->get_element_by_id('inner2'); $inner2_line = $inner2->getLineBox(0); $inner3 = $tree->get_element_by_id('inner3'); $inner3_line = $inner3->getLineBox(0); // Note that it will emulate IE behavior (line box includes all // nested line boxes), which (in my opinion) // is more standard than Firefox (line box height is calculated // using the first child line box). $this->assertEqual($outer_line->top, $inner2_line->top); $this->assertEqual($outer_line->bottom, $inner2_line->bottom); $this->assertEqual($inner1_line->bottom, $inner3_line->bottom); $this->assertEqual($inner1_line->top, $inner3_line->top); $this->assertTrue($inner1_line->top < $inner2_line->top); $this->assertTrue($inner1_line->bottom > $inner2_line->bottom); }
function update_media(&$media) { $this->media =& $media; $this->width = mm2pt($media->width() - $media->margins['left'] - $media->margins['right']); $this->height = mm2pt($media->height() - $media->margins['top'] - $media->margins['bottom']); $this->left = mm2pt($media->margins['left']); $this->bottom = mm2pt($media->margins['bottom']); $this->setPageHeight(mm2pt($media->real_height())); }
function process(&$box, &$media, &$driver, &$context) { // Calculate the size of text boxes if (is_null($box->reflow_text($driver))) { error_log("LayoutEngineDefault::process: reflow_text call failed"); return null; } // Explicitly remove any height declarations from the BODY-generated box; // BODY should always fill last page completely. Percentage height of the BODY is meaningless // on the paged media. $box->_height_constraint = new HCConstraint(null, null, null); $margin = $box->getCSSProperty(CSS_MARGIN); $margin->calcPercentages(mm2pt($media->width() - $media->margins['left'] - $media->margins['right'])); $box->setCSSProperty(CSS_MARGIN, $margin); $box->width = mm2pt($media->width() - $media->margins['left'] - $media->margins['right']) - $box->_get_hor_extra(); $box->setCSSProperty(CSS_WIDTH, new WCConstant($box->width)); $box->height = mm2pt($media->real_height()) - $box->_get_vert_extra(); $box->put_top(mm2pt($media->height() - $media->margins['top']) - $box->get_extra_top()); $box->put_left(mm2pt($media->margins['left']) + $box->get_extra_left()); $flag = false; $whitespace_flag = false; $box->reflow_whitespace($flag, $whitespace_flag); $box->pre_reflow_images(); $viewport = new FlowViewport(); $viewport->left = mm2pt($media->margins['left']); $viewport->top = mm2pt($media->height() - $media->margins['top']); $viewport->width = mm2pt($media->width() - $media->margins['left'] - $media->margins['right']); $viewport->height = mm2pt($media->height() - $media->margins['top'] - $media->margins['bottom']); $fake_parent = null; $context->push_viewport($viewport); $box->reflow($fake_parent, $context); // Make the top-level box competely fill the last page $page_real_height = mm2pt($media->real_height()); // Note we cannot have less than 1 page in our doc; max() call // is required as we, in general, CAN have the content height strictly equal to 0. // In this case wi still render the very first page $pages = max(1, ceil($box->get_full_height() / $page_real_height)); /** * Set body box height so it will fit the page exactly */ $box->height = $pages * $page_real_height - $box->_get_vert_extra(); $driver->set_expected_pages($pages); $driver->anchors = array(); $box->reflow_anchors($driver, $driver->anchors); /** * Flow absolute-positioned boxes; * note that we should know the number of expected pages at this moment, unless * we will not be able to calculate positions for elements using 'bottom: ...' CSS property */ for ($i = 0, $num_positioned = count($context->absolute_positioned); $i < $num_positioned; $i++) { $context->push(); $context->absolute_positioned[$i]->reflow_absolute($context); $context->pop(); } // Flow fixed-positioned box for ($i = 0, $num_positioned = count($context->fixed_positioned); $i < $num_positioned; $i++) { $context->push(); $context->fixed_positioned[$i]->reflow_fixed($context); $context->pop(); } $box->reflow_inline(); return true; }
function to_bbox() { return '0 0 ' . ceil(mm2pt($this->size['width'])) . ' ' . ceil(mm2pt($this->size['height'])); }