/** * tag : G * mode : OPEN * * @param array $param * @return boolean */ protected function _tag_open_G($param) { if (!$this->_isInDraw) { $e = new HtmlParsingException('The asked [G] tag is not in a [DRAW] tag'); $e->setInvalidTag('G'); throw $e; } $this->pdf->doTransform(isset($param['transform']) ? $this->_prepareTransform($param['transform']) : null); $this->parsingCss->save(); $styles = $this->parsingCss->getSvgStyle('path', $param); $style = $this->pdf->svgSetStyle($styles); }
/** * SVG - make a Advanced Polygone * * @param array $actions list of actions * @param string $style PDF Style * @access public */ public function svgPolygone($actions, $style) { // get the Closing operator from the PDF Style if ($style == 'F') { $op = 'f'; } elseif ($style == 'FD' || $style == 'DF') { $op = 'B'; } else { $op = 'S'; } // To save the First action and the last point $first = array('', 0, 0); $last = array(0, 0, 0, 0); foreach ($actions as $action) { switch ($action[0]) { // Start the Path case 'M': case 'm': $first = $action; $x = $action[1]; $y = $action[2]; $xc = $x; $yc = $y; $this->_Point($x, $y, true); break; // Close the Path // Close the Path case 'Z': case 'z': $x = $first[1]; $y = $first[2]; $xc = $x; $yc = $y; $this->_Line($x, $y, true); break; // Make a Line (new point) // Make a Line (new point) case 'L': $x = $action[1]; $y = $action[2]; $xc = $x; $yc = $y; $this->_Line($x, $y, true); break; // Make a Line (vector from last point) // Make a Line (vector from last point) case 'l': $x = $last[0] + $action[1]; $y = $last[1] + $action[2]; $xc = $x; $yc = $y; $this->_Line($x, $y, true); break; // Make a Horizontal Line (new point) // Make a Horizontal Line (new point) case 'H': $x = $action[1]; $y = $last[1]; $xc = $x; $yc = $y; $this->_Line($x, $y, true); break; // Make a Horisontal Line (vector from last point) // Make a Horisontal Line (vector from last point) case 'h': $x = $last[0] + $action[1]; $y = $last[1]; $xc = $x; $yc = $y; $this->_Line($x, $y, true); break; // Make a Vertical Line (new point) // Make a Vertical Line (new point) case 'V': $x = $last[0]; $y = $action[1]; $xc = $x; $yc = $y; $this->_Line($x, $y, true); break; // Make a Vertical Line (vector from last point) // Make a Vertical Line (vector from last point) case 'v': $x = $last[0]; $y = $last[1] + $action[1]; $xc = $x; $yc = $y; $this->_Line($x, $y, true); break; // Make a Arc (new point) // Make a Arc (new point) case 'A': $rx = $action[1]; // rx $ry = $action[2]; // ry $a = $action[3]; // deviation angle of the axis X $l = $action[4]; // large-arc-flag $s = $action[5]; // sweep-flag $x1 = $last[0]; // begin x $y1 = $last[1]; // begin y $x2 = $action[6]; // final x $y2 = $action[7]; // final y $this->_Arc2($x1, $y1, $x2, $y2, $rx, $ry, $a, $l, $s, true); $x = $x2; $y = $y2; $xc = $x; $yc = $y; break; // Make a Arc (vector from last point) // Make a Arc (vector from last point) case 'a': $rx = $action[1]; // rx $ry = $action[2]; // ry $a = $action[3]; // deviation angle of the axis X $l = $action[4]; // large-arc-flag $s = $action[5]; // sweep-flag $x1 = $last[0]; // begin x $y1 = $last[1]; // begin y $x2 = $last[0] + $action[6]; // final x $y2 = $last[1] + $action[7]; // final y $this->_Arc2($x1, $y1, $x2, $y2, $rx, $ry, $a, $l, $s, true); $x = $x2; $y = $y2; $xc = $x; $yc = $y; break; // Make a Bezier Curve (new point) // Make a Bezier Curve (new point) case 'C': $x1 = $action[1]; $y1 = $action[2]; $x2 = $action[3]; $y2 = $action[4]; $xf = $action[5]; $yf = $action[6]; $this->_Curve($x1, $y1, $x2, $y2, $xf, $yf, true); $x = $xf; $y = $yf; $xc = $x2; $yc = $y2; break; // Make a Bezier Curve (vector from last point) // Make a Bezier Curve (vector from last point) case 'c': $x1 = $last[0] + $action[1]; $y1 = $last[1] + $action[2]; $x2 = $last[0] + $action[3]; $y2 = $last[1] + $action[4]; $xf = $last[0] + $action[5]; $yf = $last[1] + $action[6]; $this->_Curve($x1, $y1, $x2, $y2, $xf, $yf, true); $x = $xf; $y = $yf; $xc = $x2; $yc = $y2; break; // Unknown Path // Unknown Path default: $e = new HtmlParsingException('SVG Path Error : [' . $action[0] . '] is unknown'); $e->setInvalidTag('POLYGON'); throw $e; } // save the last point $last = array($x, $y, $xc, $yc); } // finish the path $this->_out($op); }
/** * TODO remove the reference on the $parents variable * * @param Token $token * @param array $parents * * @return array * @throws HtmlParsingException */ protected function getTagAction(Token $token, &$parents) { // tag that can be not closed $tagsNotClosed = array('br', 'hr', 'img', 'col', 'input', 'link', 'option', 'circle', 'ellipse', 'path', 'rect', 'line', 'polygon', 'polyline'); // analyze the HTML code $node = $this->tagParser->analyzeTag($token->getData()); // save the current position in the HTML code $node->setLine($token->getLine()); $actions = array(); // if the tag must be closed if (!in_array($node->getName(), $tagsNotClosed)) { // if it is a closure tag if ($node->isClose()) { // HTML validation if (count($parents) < 1) { $e = new HtmlParsingException('Too many tag closures found for [' . $node->getName() . ']'); $e->setInvalidTag($node->getName()); $e->setHtmlLine($token->getLine()); throw $e; } elseif (end($parents) != $node->getName()) { $e = new HtmlParsingException('Tags are closed in a wrong order for [' . $node->getName() . ']'); $e->setInvalidTag($node->getName()); $e->setHtmlLine($token->getLine()); throw $e; } else { array_pop($parents); } } else { // if it is an auto-closed tag if ($node->isAutoClose()) { // save the opened tag $actions[] = $node; // prepare the closed tag $node = clone $node; $node->setParams(array()); $node->setClose(true); } else { // else: add a child for validation array_push($parents, $node->getName()); } } // if it is a <pre> tag (or <code> tag) not auto-closed => update the flag if (($node->getName() == 'pre' || $node->getName() == 'code') && !$node->isAutoClose()) { $this->tagPreIn = !$node->isClose(); } } // save the actions to convert $actions[] = $node; return $actions; }
/** * analyze a HTML tag * * @param string $code HTML code to analyze * * @return Node corresponding action * @throws HtmlParsingException */ public function analyzeTag($code) { // name of the tag, opening, closure, autoclosure $tag = '<([\\/]{0,1})([_a-z0-9]+)([\\/>\\s]+)'; if (!preg_match('/' . $tag . '/isU', $code, $match)) { $e = new HtmlParsingException('The HTML tag [' . $code . '] provided is invalid'); $e->setInvalidTag($code); throw $e; } $close = $match[1] == '/' ? true : false; $autoclose = preg_match('/\\/>$/isU', $code); $name = strtolower($match[2]); // required parameters (depends on the tag name) $defaultParams = array(); $defaultParams['style'] = ''; if ($name == 'img') { $defaultParams['alt'] = ''; $defaultParams['src'] = ''; } elseif ($name == 'a') { $defaultParams['href'] = ''; } $param = array_merge($defaultParams, $this->extractTagAttributes($code)); // compliance of each parameter $color = "#000000"; $border = null; foreach ($param as $key => $val) { switch ($key) { case 'width': unset($param[$key]); $param['style'] .= 'width: ' . $val . 'px; '; break; case 'align': if ($name === 'img') { unset($param[$key]); $param['style'] .= 'float: ' . $val . '; '; } elseif ($name !== 'table') { unset($param[$key]); $param['style'] .= 'text-align: ' . $val . '; '; } break; case 'valign': unset($param[$key]); $param['style'] .= 'vertical-align: ' . $val . '; '; break; case 'height': unset($param[$key]); $param['style'] .= 'height: ' . $val . 'px; '; break; case 'bgcolor': unset($param[$key]); $param['style'] .= 'background: ' . $val . '; '; break; case 'bordercolor': unset($param[$key]); $color = $val; break; case 'border': unset($param[$key]); if (preg_match('/^[0-9]+$/isU', $val)) { $val = $val . 'px'; } $border = $val; break; case 'cellpadding': case 'cellspacing': if (preg_match('/^([0-9]+)$/isU', $val)) { $param[$key] = $val . 'px'; } break; case 'colspan': case 'rowspan': $val = preg_replace('/[^0-9]/isU', '', $val); if (!$val) { $val = 1; } $param[$key] = $val; break; } } // compliance of the border if ($border !== null) { if ($border) { $border = 'border: solid ' . $border . ' ' . $color; } else { $border = 'border: none'; } $param['style'] .= $border . '; '; $param['border'] = $border; } // reading styles: decomposition and standardization $styles = explode(';', $param['style']); $param['style'] = array(); foreach ($styles as $style) { $tmp = explode(':', $style); if (count($tmp) > 1) { $cod = $tmp[0]; unset($tmp[0]); $tmp = implode(':', $tmp); $param['style'][trim(strtolower($cod))] = preg_replace('/[\\s]+/isU', ' ', trim($tmp)); } } // determining the level of table opening, with an added level if (in_array($name, array('ul', 'ol', 'table')) && !$close) { $this->num++; array_push($this->level, $this->num); } // get the level of the table containing the element if (!isset($param['num'])) { $param['num'] = end($this->level); } // for closures table: remove a level if (in_array($name, array('ul', 'ol', 'table')) && $close) { array_pop($this->level); } // prepare the parameters if (isset($param['value'])) { $param['value'] = $this->textParser->prepareTxt($param['value']); } if (isset($param['alt'])) { $param['alt'] = $this->textParser->prepareTxt($param['alt']); } if (isset($param['title'])) { $param['title'] = $this->textParser->prepareTxt($param['title']); } if (isset($param['class'])) { $param['class'] = $this->textParser->prepareTxt($param['class']); } // return the new action to do return new Node($name, $param, $close, $autoclose); }