public function output($save_as = null, &$format = null) { $output_format = 'SVG'; if (isset($_SERVER['HTTP_USER_AGENT']) || isset($_REQUEST['force_format'])) { static $browser_renderer = null; if (isset($_REQUEST['force_format'])) { // Don't nest the force_format within the browser_renderer null check in case its overriden by OpenBenchmarking.org dynamically $output_format = $_REQUEST['force_format']; } else { if ($browser_renderer == null) { $output_format = pts_render::renderer_compatibility_check($_SERVER['HTTP_USER_AGENT']); } else { $output_format = $browser_renderer; } } } $format = $output_format; switch ($output_format) { case 'JPG': case 'JPEG': $output = pts_svg_dom_gd::svg_dom_to_gd($this->dom, 'JPEG'); $output_format = 'jpg'; break; case 'PNG': $output = pts_svg_dom_gd::svg_dom_to_gd($this->dom, 'PNG'); $output_format = 'png'; break; case 'SVG': default: $output = $this->save_xml(); $output_format = 'svg'; break; } if ($output == null) { return false; } else { if ($save_as) { return file_put_contents(str_replace('BILDE_EXTENSION', $output_format, $save_as), $output); } else { return $output; } } }
public static function svg_dom_to_gd($dom, $format) { if (extension_loaded('gd') && function_exists('imagettftext') && $dom->childNodes->item(2)->nodeName == 'svg') { $width = $dom->childNodes->item(2)->attributes->getNamedItem('width')->nodeValue; $height = $dom->childNodes->item(2)->attributes->getNamedItem('height')->nodeValue; if ($width > 1 && $height > 1) { $gd = imagecreatetruecolor($width, $height); if (!isset($_REQUEST['svg_dom_gd_no_interlacing'])) { // PHP FPDF fails on image interlacing imageinterlace($gd, true); } if (function_exists('imageantialias')) { imageantialias($gd, true); } } else { return false; } //foreach($dom->childNodes->item(2)->attributes as $atrr) // { echo $atrr->name . ' ' . $atrr->value . PHP_EOL; } } else { // If the first tag isn't an svg tag, chances are something is broke... return false; } self::$color_table = array(); foreach ($dom->childNodes->item(2)->childNodes as $node) { self::evaluate_node($node, $gd); // imagejpeg($this->image, $output_file, $quality); //var_dump($node->attributes); } $tmp_output = tempnam('/tmp', 'pts-gd'); switch ($format) { case 'JPEG': imagejpeg($gd, $tmp_output, 100); $output = file_get_contents($tmp_output); unlink($tmp_output); break; case 'PNG': imagepng($gd, $tmp_output, 1); $output = file_get_contents($tmp_output); unlink($tmp_output); break; } return $output; }
public static function svg_dom_to_gd($dom, $format) { if (extension_loaded('gd') && function_exists('imagettftext') && $dom->childNodes->item(2)->nodeName == 'svg') { $width = $dom->childNodes->item(2)->attributes->getNamedItem('width')->nodeValue; $height = $dom->childNodes->item(2)->attributes->getNamedItem('height')->nodeValue; if ($width > 1 && $height > 1) { $gd = imagecreatetruecolor($width, $height); if (!isset($_REQUEST['svg_dom_gd_no_interlacing'])) { // PHP FPDF fails on image interlacing imageinterlace($gd, true); } if (function_exists('imageantialias')) { imageantialias($gd, true); } } else { return false; } //foreach($dom->childNodes->item(2)->attributes as $atrr) // { echo $atrr->name . ' ' . $atrr->value . PHP_EOL; } } else { // If the first tag isn't an svg tag, chances are something is broke... return false; } self::$color_table = array(); foreach ($dom->childNodes->item(2)->childNodes as $node) { if ($node->nodeName == 'a') { // This is just a link so get whatever is the child of the embedded link to display $node = $node->childNodes->item(0); } switch ($node->nodeName) { case 'svg': // Not relevant at this point to GD rendering break; case 'line': $a = self::attributes_to_array($node, array('x1', 'y1', 'x2', 'y2', 'stroke', 'stroke-width', 'stroke-dasharray')); $line_color = self::gd_color_allocate($gd, $a['stroke']); if ($a['stroke-dasharray'] != null) { list($dash_length, $blank_length) = explode(',', $a['stroke-dasharray']); if ($a['y1'] == $a['y2']) { for ($i = $a['x1']; $i < $a['x2']; $i += $blank_length + $dash_length) { imagefilledrectangle($gd, $i, $a['y1'] - floor($a['stroke-width'] / 2), $i + $dash_length, $a['y1'] + floor($a['stroke-width'] / 2), $line_color); //imageline($gd, $i, $pos, ($i + $dash_length), $pos, $line_color); } } else { for ($i = $a['y1']; $i < $a['y2']; $i += $blank_length + $dash_length) { imagefilledrectangle($gd, $a['x1'] - floor($a['stroke-width'] / 2), $i, $a['x1'] + floor($a['stroke-width'] / 2), $i + $dash_length, $line_color); //imageline($gd, $i, $pos, ($i + $dash_length), $pos, $line_color); } } } else { imagesetthickness($gd, $a['stroke-width']); imageline($gd, $a['x1'], $a['y1'], $a['x2'], $a['y2'], $line_color); } break; case 'polyline': $a = self::attributes_to_array($node, array('points', 'stroke', 'stroke-width', 'fill')); imagesetthickness($gd, $a['stroke-width']); $line_color = self::gd_color_allocate($gd, $a['stroke']); $a['points'] = explode(' ', $a['points']); for ($i = 1; $i < count($a['points']); $i++) { $s_point = explode(',', $a['points'][$i - 1]); $e_point = explode(',', $a['points'][$i]); imageline($gd, $s_point[0], $s_point[1], $e_point[0], $e_point[1], $line_color); } break; case 'text': $a = self::attributes_to_array($node, array('x', 'y', 'font-size', 'text-anchor', 'fill', 'dominant-baseline', 'transform')); $text = $node->nodeValue; $a['font-size'] -= 1.6; $box_array = imagettfbbox($a['font-size'], 0, self::$default_font, $text); $box_width = $box_array[4] - $box_array[6]; $box_height = $box_array[1] - $box_array[7]; $rotate = 0; if ($a['transform']) { $rotate = substr($a['transform'], 7); $rotate = substr($rotate, 0, strpos($rotate, ' ')); // $rotate this should be the rotation degree in SVG if ($rotate != 0) { $rotate += 180; } switch ($a['text-anchor']) { case 'middle': $a['y'] -= round($box_width / 2); break; } } else { switch ($a['text-anchor']) { case 'start': break; case 'middle': $a['x'] -= round($box_width / 2); break; case 'end': $a['x'] -= $box_width - 4; break; } switch ($a['dominant-baseline']) { case 'text-before-edge': $a['y'] += $box_height; break; case 'middle': $a['y'] += round($box_height / 2); break; } } imagettftext($gd, $a['font-size'], $rotate, $a['x'], $a['y'], self::gd_color_allocate($gd, $a['fill']), self::$default_font, $text); break; case 'polygon': $a = self::attributes_to_array($node, array('points', 'fill', 'stroke', 'stroke-width')); $a['points'] = explode(' ', $a['points']); $points = array(); foreach ($a['points'] as &$point) { $point = explode(',', $point); array_push($points, $point[0]); array_push($points, $point[1]); } if ($a['stroke-width']) { imagesetthickness($gd, $a['stroke-width']); imagefilledpolygon($gd, $points, count($a['points']), self::gd_color_allocate($gd, $a['stroke'])); } imagefilledpolygon($gd, $points, count($a['points']), self::gd_color_allocate($gd, $a['fill'])); break; case 'rect': // Draw a rectangle $a = self::attributes_to_array($node, array('x', 'y', 'width', 'height', 'fill', 'stroke', 'stroke-width')); if ($a['fill'] != 'none') { imagefilledrectangle($gd, $a['x'], $a['y'], $a['x'] + $a['width'], $a['y'] + $a['height'], self::gd_color_allocate($gd, $a['fill'])); } if ($a['stroke'] != null) { // TODO: implement $a['stroke-width'] imagerectangle($gd, $a['x'], $a['y'], $a['x'] + $a['width'], $a['y'] + $a['height'], self::gd_color_allocate($gd, $a['stroke'])); } break; case 'circle': // Draw a circle $a = self::attributes_to_array($node, array('cx', 'cy', 'r', 'fill')); imagefilledellipse($gd, $a['cx'], $a['cy'], $a['r'] * 2, $a['r'] * 2, self::gd_color_allocate($gd, $a['fill'])); break; case 'ellipse': // Draw a ellipse/circle $a = self::attributes_to_array($node, array('cx', 'cy', 'rx', 'ry', 'fill', 'stroke', 'stroke-width')); imagefilledellipse($gd, $a['cx'], $a['cy'], $a['rx'] * 2, $a['ry'] * 2, self::gd_color_allocate($gd, $a['fill'])); if ($a['stroke'] != null) { // TODO: implement $a['stroke-width'] imagefilledellipse($gd, $a['cx'], $a['cy'], $a['rx'] * 2, $a['ry'] * 2, self::gd_color_allocate($gd, $a['stroke'])); } break; case 'image': $a = self::attributes_to_array($node, array('xlink:href', 'x', 'y', 'width', 'height')); if (substr($a['xlink:href'], 0, 22) == 'data:image/png;base64,') { $img = imagecreatefromstring(base64_decode(substr($a['xlink:href'], 22))); } else { $img = imagecreatefromstring(file_get_contents($a['xlink:href'])); } imagecopyresampled($gd, $img, $a['x'], $a['y'], 0, 0, $a['width'], $a['height'], imagesx($img), imagesy($img)); break; default: if (PTS_IS_CLIENT) { echo $node->nodeName . ' not implemented.' . PHP_EOL; } break; } // imagejpeg($this->image, $output_file, $quality); //var_dump($node->attributes); } $tmp_output = tempnam('/tmp', 'pts-gd'); switch ($format) { case 'JPEG': imagejpeg($gd, $tmp_output, 100); $output = file_get_contents($tmp_output); unlink($tmp_output); break; case 'PNG': imagepng($gd, $tmp_output, 1); $output = file_get_contents($tmp_output); unlink($tmp_output); break; } return $output; }