Creates SVG for svgEnvelope and svgGeometry

@param type $geometry
@param \stdClass $viewbox viewbox from $this->getViewBox($envelope)
@return string svg as string
551337
public function getSVG($width, $height)
    {
        if($this->svgEnvelope === null)
        {
            return null;
        }
        $min_max = explode(" ",
                           preg_replace('/M\s?|\sL|\sZ/', "", $this->svgEnvelope));
        $min_x = floatval($min_max[0]);
        $min_y = floatval($min_max[1]);
        $max_x = floatval($min_max[0]);
        $max_y = floatval($min_max[1]);
        for($i = 1; $i < count($min_max); $i = $i + 2)
        {
            $min_x = min($min_x, floatval($min_max[$i - 1]));
            $max_x = max($max_x, floatval($min_max[$i - 1]));
            $min_y = min($min_y, floatval($min_max[$i]));
            $max_y = max($max_y, floatval($min_max[$i]));
        }
        $vb = $min_x . " " . $min_y . " " . ($max_x - $min_x) . " " . ($max_y - $min_y);

        return '<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="' . $width . 'px" height="' . $height . 'px" viewBox="' . $vb . '" version="1.1" xmlns="http://www.w3.org/2000/svg">
	<path d="' . ($this->svgGeometry === null
                            ? '' : $this->svgGeometry) . '" fill="black" />
</svg>';
    }
362692
private void render(SVG.Svg obj, Box viewPort)
   {
      render(obj, viewPort, obj.viewBox, obj.preserveAspectRatio);
   }
1311336
function(svg) {
		"use strict";

		var parent = this;
		var options = parent.options;

		if (arguments.length === 0) {
			svg = parent.root.selectAll(".graph-domain");
		}

		var rect = svg
			.selectAll("svg").selectAll("g")
			.data(function(d) { return parent._domains.get(d); })
		;

		/**
		 * Colorize the cell via a style attribute if enabled
		 */
		function addStyle(element) {
			if (parent.legendScale === null) {
				return false;
			}

			element.attr("fill", function(d) {
				if (d.v === null && (options.hasOwnProperty("considerMissingDataAsZero") && !options.considerMissingDataAsZero)) {
					if (options.legendColors.hasOwnProperty("base")) {
						return options.legendColors.base;
					}
				}

				if (options.legendColors !== null && options.legendColors.hasOwnProperty("empty") &&
					(d.v === 0 || (d.v === null && options.hasOwnProperty("considerMissingDataAsZero") && options.considerMissingDataAsZero))
				) {
					return options.legendColors.empty;
				}

				if (d.v < 0 && options.legend[0] > 0 && options.legendColors !== null && options.legendColors.hasOwnProperty("overflow")) {
					return options.legendColors.overflow;
				}

				return parent.legendScale(Math.min(d.v, options.legend[options.legend.length-1]));
			});
		}

		rect.transition().duration(options.animationDuration).select("rect")
			.attr("class", function(d) {

				var htmlClass = parent.getHighlightClassName(d.t).trim().split(" ");
				var pastDate = parent.dateIsLessThan(d.t, new Date());
        var sameDate = parent.dateIsEqual(d.t, new Date());

				if (parent.legendScale === null ||
					(d.v === null && (options.hasOwnProperty("considerMissingDataAsZero") && !options.considerMissingDataAsZero) &&!options.legendColors.hasOwnProperty("base"))
				) {
					htmlClass.push("graph-rect");
				}

        if (sameDate) {
          htmlClass.push("now");
        } else if (!pastDate) {
          htmlClass.push("future");
        }

				if (d.v !== null) {
					htmlClass.push(parent.Legend.getClass(d.v, (parent.legendScale === null)));
				} else if (options.considerMissingDataAsZero && pastDate) {
					htmlClass.push(parent.Legend.getClass(0, (parent.legendScale === null)));
				}

				if (options.onClick !== null) {
					htmlClass.push("hover_cursor");
				}

				return htmlClass.join(" ");
			})
			.call(addStyle)
		;

		rect.transition().duration(options.animationDuration).select("title")
			.text(function(d) { return parent.getSubDomainTitle(d); })
		;

		function formatSubDomainText(element) {
			if (typeof options.subDomainTextFormat === "function") {
				element.text(function(d) { return options.subDomainTextFormat(d.t, d.v); });
			}
		}

		/**
		 * Change the subDomainText class if necessary
		 * Also change the text, e.g when text is representing the value
		 * instead of the date
		 */
		rect.transition().duration(options.animationDuration).select("text")
			.attr("class", function(d) { return "subdomain-text" + parent.getHighlightClassName(d.t); })
			.call(formatSubDomainText)
		;
	}
1132453
static Geometry construct(MultiVertexGeometry mvg) {
		if (mvg.isEmpty())
			return new Polygon(mvg.getDescription());

		MultiVertexGeometryImpl mvg_impl = (MultiVertexGeometryImpl) mvg._getImpl();
		int N = mvg_impl.getPointCount();

		if (N <= 2) {
			if (N == 1 || mvg_impl.getXY(0).equals(mvg_impl.getXY(1))) {
				Point point = new Point(mvg_impl.getDescription());
				mvg_impl.getPointByVal(0, point);
				return point;
			} else {
				Point pt = new Point();
				Polyline polyline = new Polyline(mvg_impl.getDescription());
				mvg_impl.getPointByVal(0, pt);
				polyline.startPath(pt);
				mvg_impl.getPointByVal(1, pt);
				polyline.lineTo(pt);
				return polyline;
			}
		}

		AttributeStreamOfDbl stream = (AttributeStreamOfDbl) mvg_impl.getAttributeStreamRef(VertexDescription.Semantics.POSITION);
		ConvexHull convex_hull = new ConvexHull(stream, N);

		int t0 = 0, tm = 1;
		Point2D pt_0 = new Point2D();
		Point2D pt_m = new Point2D();
		Point2D pt_p = new Point2D();

		stream.read(t0 << 1, pt_0);

		while (true) {
			if (tm >= N)
				break;

			stream.read(tm << 1, pt_m);
			if (!pt_m.isEqual(pt_0, NumberUtils.doubleEps()))
				break;

			tm++; // We don't want to close the gap between t0 and tm.
		}

		convex_hull.m_tree_hull.addElement(t0, -1);

		if (tm < N) {
			convex_hull.m_tree_hull.addBiggestElement(tm, -1);

			for (int tp = tm + 1; tp < mvg_impl.getPointCount(); tp++) {// Dynamically insert into the current convex hull

				stream.read(tp << 1, pt_p);
				int p = convex_hull.treeHull_(pt_p);

				if (p != -1)
					convex_hull.m_tree_hull.setElement(p, tp); // reset the place holder to the point index.
			}
		}

		// Extracts the convex hull from the tree. Reading the tree in order from first to last is the resulting convex hull.

		VertexDescription description = mvg_impl.getDescription();
		boolean b_has_attributes = (description.getAttributeCount() > 1);
		int point_count = convex_hull.m_tree_hull.size(-1);

		Geometry hull;

		if (point_count >= 2) {
			if (point_count >= 3)
				hull = new Polygon(description);
			else
				hull = new Polyline(description);

			MultiPathImpl hull_impl = (MultiPathImpl) hull._getImpl();
			hull_impl.addPath((Point2D[]) null, 0, true);

			Point point = null;
			if (b_has_attributes)
				point = new Point();

			for (int i = convex_hull.m_tree_hull.getFirst(-1); i != -1; i = convex_hull.m_tree_hull.getNext(i)) {
				if (b_has_attributes) {
					mvg_impl.getPointByVal(convex_hull.m_tree_hull.getElement(i), point);
					hull_impl.insertPoint(0, -1, point);
				} else {
					stream.read(convex_hull.m_tree_hull.getElement(i) << 1, pt_p);
					hull_impl.insertPoint(0, -1, pt_p);
				}
			}
		} else {
			assert (point_count == 1);

			if (b_has_attributes) {
				Point point = new Point(description);
				mvg_impl.getPointByVal(convex_hull.m_tree_hull.getElement(convex_hull.m_tree_hull.getFirst(-1)), point);
				hull = point;
			} else {
				stream.read(convex_hull.m_tree_hull.getElement(convex_hull.m_tree_hull.getFirst(-1)) << 1, pt_p);
				hull = new Point(pt_p);
			}
		}

		return hull;
	}
225864
function(el) {
        // Return a bounding box rectangle that takes into account stroke.
        // Note that this is a naive and ad-hoc implementation that does not
        // works only in certain cases and should be replaced as soon as browsers will
        // start supporting the getStrokeBBox() SVG method.
        // @TODO any better solution is very welcome!

        var isMagnet = !!el;

        el = el || this.el;
        var bbox = V(el).getBBox({ target: this.paper.viewport });
        var strokeWidth;
        if (isMagnet) {

            strokeWidth = V(el).attr('stroke-width');

        } else {

            strokeWidth = this.model.attr('rect/stroke-width') || this.model.attr('circle/stroke-width') || this.model.attr('ellipse/stroke-width') || this.model.attr('path/stroke-width');
        }

        strokeWidth = parseFloat(strokeWidth) || 0;

        return g.rect(bbox).moveAndExpand({ x: -strokeWidth / 2, y: -strokeWidth / 2, width: strokeWidth, height: strokeWidth });
    }
611033
public static function load_svg($svg='') {
		ref\cast::string($svg, true);

		// First thing first, lowercase all tags.
		$svg = \preg_replace('/<svg/ui', '<svg', $svg);
		$svg = \preg_replace('/<\/svg>/ui', '</svg>', $svg);

		// Find the start and end tags so we can cut out miscellaneous garbage.
		if (
			(false === ($start = mb::strpos($svg, '<svg'))) ||
			(false === ($end = mb::strrpos($svg, '</svg>')))
		) {
			return false;
		}
		$svg = mb::substr($svg, $start, ($end - $start + 6));

		// Bugs from old versions of Illustrator.
		$svg = \str_replace(
			\array_keys(constants::SVG_ATTR_CORRECTIONS),
			\array_values(constants::SVG_ATTR_CORRECTIONS),
			$svg
		);

		// Remove XML, PHP, ASP, etc.
		$svg = \preg_replace('/<\?(.*)\?>/Us', '', $svg);
		$svg = \preg_replace('/<\%(.*)\%>/Us', '', $svg);

		if ((false !== \strpos($svg, '<?')) || (false !== \strpos($svg, '<%'))) {
			return false;
		}

		// Remove comments.
		$svg = \preg_replace('/<!--(.*)-->/Us', '', $svg);
		$svg = \preg_replace('/\/\*(.*)\*\//Us', '', $svg);

		if ((false !== \strpos($svg, '<!--')) || (false !== \strpos($svg, '/*'))) {
			return false;
		}

		// Open it.
		\libxml_use_internal_errors(true);
		\libxml_disable_entity_loader(true);
		$dom = new \DOMDocument('1.0', 'UTF-8');
		$dom->formatOutput = false;
		$dom->preserveWhiteSpace = false;
		$dom->loadXML(constants::SVG_HEADER . "\n{$svg}");

		// Make sure there are still SVG tags.
		$svgs = $dom->getElementsByTagName('svg');
		if (! $svgs->length) {
			return false;
		}

		return $dom;
	}
197542
private static Box  parseViewBox(String val) throws SVGParseException
   {
      TextScanner scan = new TextScanner(val);
      scan.skipWhitespace();

      float minX = scan.nextFloat();
      scan.skipCommaWhitespace();
      float minY = scan.nextFloat();
      scan.skipCommaWhitespace();
      float width = scan.nextFloat();
      scan.skipCommaWhitespace();
      float height = scan.nextFloat();

      if (Float.isNaN(minX) || Float.isNaN(minY) || Float.isNaN(width) || Float.isNaN(height))
         throw new SVGParseException("Invalid viewBox definition - should have four numbers");
      if (width < 0)
         throw new SVGParseException("Invalid viewBox. width cannot be negative");
      if (height < 0)
         throw new SVGParseException("Invalid viewBox. height cannot be negative");

      return new SVG.Box(minX, minY, width, height);
   }
1153705
public function getData($fragment = false)
    {
        $svg = '';
        $widthAsString = number_format($this->width, 0, '.', '');
        $heightAsString = number_format($this->height, 0, '.', '');
        
        if (!$fragment) {
            $svg .= '<svg xmlns="http://www.w3.org/2000/svg" width="' .
                $widthAsString .'" height="'. $heightAsString .'" viewBox="0 0 '.
                $widthAsString .' '. $heightAsString .
                '" preserveAspectRatio="xMidYMid meet">';
        }

        if ($this->backgroundColor->a > 0) {
            $opacity = (float)$this->backgroundColor->a / 255;
            $svg .= '<rect fill="'. $this->backgroundColor->toHexString(6) .
                '" fill-opacity="'. number_format($opacity, 2, '.', '').
                '" x="0" y="0" width="'. $widthAsString .'" height="'. 
                $heightAsString .'"/>';
        }
        
        foreach ($this->pathsByColor as $color => $path) {
            $svg .= "<path fill=\"$color\" d=\"$path\"/>";
        }

        if (!$fragment) {
            $svg .= '</svg>';
        }
        
        return $svg;
    }
527958
def compose_view(bg_svgs, fg_svgs, ref=0, out_file='report.svg'):
    
    import svgutils.transform as svgt

    if fg_svgs is None:
        fg_svgs = []

    # Merge SVGs and get roots
    svgs = bg_svgs + fg_svgs
    roots = [f.getroot() for f in svgs]

    # Query the size of each
    sizes = []
    for f in svgs:
        viewbox = [float(v) for v in f.root.get("viewBox").split(" ")]
        width = int(viewbox[2])
        height = int(viewbox[3])
        sizes.append((width, height))
    nsvgs = len(bg_svgs)

    sizes = np.array(sizes)

    # Calculate the scale to fit all widths
    width = sizes[ref, 0]
    scales = width / sizes[:, 0]
    heights = sizes[:, 1] * scales

    # Compose the views panel: total size is the width of
    # any element (used the first here) and the sum of heights
    fig = svgt.SVGFigure(width, heights[:nsvgs].sum())

    yoffset = 0
    for i, r in enumerate(roots):
        r.moveto(0, yoffset, scale=scales[i])
        if i == (nsvgs - 1):
            yoffset = 0
        else:
            yoffset += heights[i]

    # Group background and foreground panels in two groups
    if fg_svgs:
        newroots = [
            svgt.GroupElement(roots[:nsvgs], {'class': 'background-svg'}),
            svgt.GroupElement(roots[nsvgs:], {'class': 'foreground-svg'})
        ]
    else:
        newroots = roots
    fig.append(newroots)
    fig.root.attrib.pop("width")
    fig.root.attrib.pop("height")
    fig.root.set("preserveAspectRatio", "xMidYMid meet")
    out_file = op.abspath(out_file)
    fig.save(out_file)

    # Post processing
    with open(out_file, 'r' if PY3 else 'rb') as f:
        svg = f.read().split('\n')

    # Remove <?xml... line
    if svg[0].startswith("<?xml"):
        svg = svg[1:]

    # Add styles for the flicker animation
    if fg_svgs:
        svg.insert(2, """\
<style type="text/css">
@keyframes flickerAnimation%s { 0%% {opacity: 1;} 100%% { opacity: 0; }}
.foreground-svg { animation: 1s ease-in-out 0s alternate none infinite paused flickerAnimation%s;}
.foreground-svg:hover { animation-play-state: running;}
</style>""" % tuple([uuid4()] * 2))

    with open(out_file, 'w' if PY3 else 'wb') as f:
        f.write('\n'.join(svg))
    return out_file
313652
@SuppressWarnings("unchecked")
    public GoogleMapShape toShape(Geometry geometry) {

        GoogleMapShape shape = null;

        GeometryType geometryType = geometry.getGeometryType();
        switch (geometryType) {
            case POINT:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.LAT_LNG, toLatLng((Point) geometry));
                break;
            case LINESTRING:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.POLYLINE_OPTIONS,
                        toPolyline((LineString) geometry));
                break;
            case POLYGON:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.POLYGON_OPTIONS,
                        toPolygon((Polygon) geometry));
                break;
            case MULTIPOINT:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.MULTI_LAT_LNG,
                        toLatLngs((MultiPoint) geometry));
                break;
            case MULTILINESTRING:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.MULTI_POLYLINE_OPTIONS,
                        toPolylines((MultiLineString) geometry));
                break;
            case MULTIPOLYGON:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.MULTI_POLYGON_OPTIONS,
                        toPolygons((MultiPolygon) geometry));
                break;
            case CIRCULARSTRING:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.POLYLINE_OPTIONS,
                        toPolyline((CircularString) geometry));
                break;
            case COMPOUNDCURVE:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.MULTI_POLYLINE_OPTIONS,
                        toPolylines((CompoundCurve) geometry));
                break;
            case CURVEPOLYGON:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.POLYGON_OPTIONS,
                        toCurvePolygon((CurvePolygon) geometry));
                break;
            case POLYHEDRALSURFACE:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.MULTI_POLYGON_OPTIONS,
                        toPolygons((PolyhedralSurface) geometry));
                break;
            case TIN:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.MULTI_POLYGON_OPTIONS,
                        toPolygons((TIN) geometry));
                break;
            case TRIANGLE:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.POLYGON_OPTIONS,
                        toPolygon((Triangle) geometry));
                break;
            case GEOMETRYCOLLECTION:
                shape = new GoogleMapShape(geometryType,
                        GoogleMapShapeType.COLLECTION,
                        toShapes((GeometryCollection<Geometry>) geometry));
                break;
            default:
                throw new GeoPackageException("Unsupported Geometry Type: "
                        + geometryType.getName());
        }

        return shape;
    }
137063
protected function buildViewportField($viewport)
    {
        if ($this->useTextInput) {
            
            $field = TextField::create(
                $this->getViewportName($viewport),
                $this->getViewportLabel($viewport)
            );
            
        } else {
            
            $field = DropdownField::create(
                $this->getViewportName($viewport),
                $this->getViewportLabel($viewport),
                $this->getSource()
            );
            
        }
        
        return $field;
    }
617454
function createGeo() {
    $cnt = count( $this->geo );
    if( 0 >= $cnt )
      return;
    $attributes = $this->_createParams( $this->geo['params'] );
    $content    = null;
    $content   .= number_format( (float) $this->geo['value']['latitude'], 6, '.', '');
    $content   .= ';';
    $content   .= number_format( (float) $this->geo['value']['longitude'], 6, '.', '');
    return $this->_createElement( 'GEO', $attributes, $content );
  }
687867
private static URI createSvg(
            final Dimension targetSize,
            final RasterReference rasterReference, final Double rotation,
            final Color backgroundColor, final File workingDir)
            throws IOException {
        // load SVG graphic
        final SVGElement svgRoot = parseSvg(rasterReference.inputStream);

        // create a new SVG graphic in which the existing graphic is embedded (scaled and rotated)
        DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
        Document newDocument = impl.createDocument(SVG_NS, "svg", null);
        SVGElement newSvgRoot = (SVGElement) newDocument.getDocumentElement();
        newSvgRoot.setAttributeNS(null, "width", Integer.toString(targetSize.width));
        newSvgRoot.setAttributeNS(null, "height", Integer.toString(targetSize.height));

        setSvgBackground(backgroundColor, targetSize, newDocument, newSvgRoot);
        embedSvgGraphic(svgRoot, newSvgRoot, newDocument, targetSize, rotation);
        File path = writeSvgToFile(newDocument, workingDir);

        return path.toURI();
    }
584960
public function read(string $ewkb) : Geometry
    {
        $buffer = new WKBBuffer($ewkb);
        $geometry = $this->readGeometry($buffer, 0);

        if (! $buffer->isEndOfStream()) {
            throw GeometryIOException::invalidWKB('unexpected data at end of stream');
        }

        return $geometry;
    }
596752
function createSVGElement(id, { viewBox, className }) {
    let code = ['<svg xmlns="http://www.w3.org/2000/svg"'];

    // 设置视口
    viewBox && code.push(` viewBox="${ viewBox }"`);

    // 设置样式
    code.push(` class="${ className ? [className, id].join(' ') : id }"`);

    // 添加内容
    code.push(`><use xlink:href="#${ id }"></use></svg>`);

    // 拼接代码
    return code.join('');
}
1004561
private function fromGEOS(\GEOSGeometry $geometry) : Geometry
    {
        if ($geometry->isEmpty()) {
            return Geometry::fromText($this->wktWriter->write($geometry), $geometry->getSRID());
        }

        if ($this->hasBinaryReadWrite) {
            return $this->ewkbReader->read($this->wkbWriter->write($geometry));
        }

        return $this->ewkbReader->read(hex2bin($this->wkbWriter->writeHEX($geometry)));
    }
1191169
function svgText()
	{
		// $tmp = count($this->txt_style)-1;
		$current_style = $this->txt_style[count($this->txt_style) - 1]; // mPDF 5.7.4
		$style = '';
		$op = '';
		$render = -1;
		if (isset($this->txt_data[2])) {
			// mPDF 6
			// If using SVG Font
			if (isset($this->svg_font[$current_style['font-family']])) {
				// select font
				$style = 'R';
				$style .= (isset($current_style['font-weight']) && $current_style['font-weight'] == 'bold') ? 'B' : '';
				$style .= (isset($current_style['font-style']) && $current_style['font-style'] == 'italic') ? 'I' : '';
				$style .= (isset($current_style['font-variant']) && $current_style['font-variant'] == 'small-caps') ? 'S' : '';

				$fontsize = $current_style['font-size'] * $this->mpdf->dpi / 72;
				if (isset($this->svg_font[$current_style['font-family']][$style])) {
					$svg_font = $this->svg_font[$current_style['font-family']][$style];
				} else if (isset($this->svg_font[$current_style['font-family']]['R'])) {
					$svg_font = $this->svg_font[$current_style['font-family']]['R'];
				}

				if (!isset($svg_font['units-per-em']) || $svg_font['units-per-em'] < 1) {
					$svg_font['units-per-em'] = 1000;
				}
				$units_per_em = $svg_font['units-per-em'];
				$scale = $fontsize / $units_per_em;
				$stroke_width = $current_style['stroke-width'];
				$stroke_width /= $scale;

				$opacitystr = '';
				$fopacity = 1;
				if (isset($current_style['fill-opacity'])) {
					if ($current_style['fill-opacity'] == 0) {
						$fopacity = 0;
					} else if ($current_style['fill-opacity'] > 1) {
						$fopacity = 1;
					} else if ($current_style['fill-opacity'] > 0) {
						$fopacity = $current_style['fill-opacity'];
					} else if ($current_style['fill-opacity'] < 0) {
						$fopacity = 0;
					}
				}
				$sopacity = 1;
				if (isset($current_style['stroke-opacity'])) {
					if ($current_style['stroke-opacity'] == 0) {
						$sopacity = 0;
					} else if ($current_style['stroke-opacity'] > 1) {
						$sopacity = 1;
					} else if ($current_style['stroke-opacity'] > 0) {
						$sopacity = $current_style['stroke-opacity'];
					} else if ($current_style['stroke-opacity'] < 0) {
						$sopacity = 0;
					}
				}
				$gs = $this->mpdf->AddExtGState(['ca' => $fopacity, 'CA' => $sopacity, 'BM' => '/Normal']);
				$this->mpdf->extgstates[$gs]['fo'] = true;
				$opacitystr = sprintf(' /GS%d gs ', $gs);

				$fillstr = '';
				if (isset($current_style['fill']) && $current_style['fill'] != 'none') {
					$col = $this->colorConverter->convert($current_style['fill'], $this->mpdf->PDFAXwarnings);
					$fillstr = $this->mpdf->SetFColor($col, true);
					$render = "0"; // Fill (only)
					$op = 'f';
				}
				$strokestr = '';
				if ($stroke_width > 0 && $current_style['stroke'] != 'none') {
					$scol = $this->colorConverter->convert($current_style['stroke'], $this->mpdf->PDFAXwarnings);
					if ($scol) {
						$strokestr .= $this->mpdf->SetDColor($scol, true) . ' ';
					}
					$linewidth = $this->ConvertSVGSizePixels($stroke_width);
					if ($linewidth > 0) {
						$strokestr .= sprintf('%.3F w 0 J 0 j ', $linewidth * $this->kp);
						if ($render == -1) {
							$render = "1";
						} // stroke only
						else {
							$render = "2";
						}  // fill and stroke
						$op .= 'S';
					}
				}
				if ($render == -1) {
					return '';
				}
				if ($op == 'fS') {
					$op = 'B';
				}

				$x = $this->txt_data[0]; // mPDF 5.7.4
				$y = $this->txt_data[1]; // mPDF 5.7.4
				$txt = $this->txt_data[2];

				$txt = preg_replace('/\f/', '', $txt);
				$txt = preg_replace('/\r/', '', $txt);
				$txt = preg_replace('/\n/', ' ', $txt);
				$txt = preg_replace('/\t/', ' ', $txt);
				$txt = preg_replace("/[ ]+/u", ' ', $txt);

				if ($this->textjuststarted) {
					$txt = ltrim($txt);
				}  // mPDF 5.7.4
				$this->textjuststarted = false;  // mPDF 5.7.4

				$txt = $this->mpdf->purify_utf8_text($txt);
				if ($this->mpdf->text_input_as_HTML) {
					$txt = $this->mpdf->all_entities_to_utf8($txt);
				}

				$nb = mb_strlen($txt, 'UTF-8');
				$i = 0;
				$sw = 0;
				$subpath_cmd = '';
				while ($i < $nb) {
					//Get next character
					$char = mb_substr($txt, $i, 1, 'UTF-8');


					if (isset($svg_font['glyphs'][$char])) {
						$d = $svg_font['glyphs'][$char]['d'];
						if (isset($svg_font['glyphs'][$char]['horiz-adv-x'])) {
							$horiz_adv_x = $svg_font['glyphs'][$char]['horiz-adv-x'];
						} else {
							$horiz_adv_x = $svg_font['horiz-adv-x'];
						} // missing glyph width
					} else {
						$d = $svg_font['d'];
						$horiz_adv_x = $svg_font['horiz-adv-x']; // missing glyph width
					}
					preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $d, $commands, PREG_SET_ORDER);
					$subpath_cmd .= sprintf('q %.4F 0 0 %.4F mPDF-AXS(%.4F) %.4F cm ', $scale, -$scale, ($x + $sw * $scale) * $this->kp, -$y * $this->kp);

					$this->subPathInit = true;
					$this->pathBBox = [999999, 999999, -999999, -999999];
					foreach ($commands as $cmd) {
						if (count($cmd) == 3 || (isset($cmd[2]) && $cmd[2] == '')) {
							list($tmp, $command, $arguments) = $cmd;
						} else {
							list($tmp, $command) = $cmd;
							$arguments = '';
						}

						$subpath_cmd .= $this->svgPath($command, $arguments);
					}
					$subpath_cmd .= $op . ' Q ';
					if ($this->pathBBox[2] == -1999998) {
						$this->pathBBox[2] = 100;
					}
					if ($this->pathBBox[3] == -1999998) {
						$this->pathBBox[3] = 100;
					}
					if ($this->pathBBox[0] == 999999) {
						$this->pathBBox[0] = 0;
					}
					if ($this->pathBBox[1] == 999999) {
						$this->pathBBox[1] = 0;
					}


					$sw += $horiz_adv_x;
					$i++;
				}

				$sw *= $scale; // convert stringwidth to units
				// mPDF 5.7.4
				$this->textlength = $sw;
				$this->texttotallength += $this->textlength;

				$path_cmd = sprintf('q %s %s Tr %s %s ', $opacitystr, $render, $fillstr, $strokestr);
				$path_cmd .= $subpath_cmd;
				$path_cmd .= 'Q ';

				unset($this->txt_data[0], $this->txt_data[1], $this->txt_data[2]);
				return $path_cmd;
			}

			// select font
			$style .= ($current_style['font-weight'] == 'bold') ? 'B' : '';
			$style .= ($current_style['font-style'] == 'italic') ? 'I' : '';
			$size = $current_style['font-size'] * $this->kf;

			$current_style['font-family'] = $this->mpdf->SetFont($current_style['font-family'], $style, $size, false);
			$this->mpdf->CurrentFont['fo'] = true;

			$opacitystr = '';
			// mPDF 6
			$fopacity = 1;
			if (isset($current_style['fill-opacity'])) {
				if ($current_style['fill-opacity'] == 0) {
					$fopacity = 0;
				} else if ($current_style['fill-opacity'] > 1) {
					$fopacity = 1;
				} else if ($current_style['fill-opacity'] > 0) {
					$fopacity = $current_style['fill-opacity'];
				} else if ($current_style['fill-opacity'] < 0) {
					$fopacity = 0;
				}
			}
			$sopacity = 1;
			if (isset($current_style['stroke-opacity'])) {
				if ($current_style['stroke-opacity'] == 0) {
					$sopacity = 0;
				} else if ($current_style['stroke-opacity'] > 1) {
					$sopacity = 1;
				} else if ($current_style['stroke-opacity'] > 0) {
					$sopacity = $current_style['stroke-opacity'];
				} else if ($current_style['stroke-opacity'] < 0) {
					$sopacity = 0;
				}
			}
			$gs = $this->mpdf->AddExtGState(['ca' => $fopacity, 'CA' => $sopacity, 'BM' => '/Normal']);
			$this->mpdf->extgstates[$gs]['fo'] = true;
			$opacitystr = sprintf(' /GS%d gs ', $gs);

			$fillstr = '';
			if (isset($current_style['fill']) && $current_style['fill'] != 'none') {
				$col = $this->colorConverter->convert($current_style['fill'], $this->mpdf->PDFAXwarnings);
				$fillstr = $this->mpdf->SetFColor($col, true);
				$render = "0"; // Fill (only)
			}
			$strokestr = '';
			if (isset($current_style['stroke-width']) && $current_style['stroke-width'] > 0 && $current_style['stroke'] != 'none') {
				$scol = $this->colorConverter->convert($current_style['stroke'], $this->mpdf->PDFAXwarnings);
				if ($scol) {
					$strokestr .= $this->mpdf->SetDColor($scol, true) . ' ';
				}
				$linewidth = $this->ConvertSVGSizePixels($current_style['stroke-width']);
				if ($linewidth > 0) {
					$strokestr .= sprintf('%.3F w 1 J 1 j ', $linewidth * $this->kp);
					if ($render == -1) {
						$render = "1";
					} // stroke only
					else {
						$render = "2";
					}  // fill and stroke
				}
			}
			if ($render == -1) {
				return '';
			}

			$x = $this->txt_data[0]; // mPDF 5.7.4
			$y = $this->txt_data[1]; // mPDF 5.7.4
			$txt = $this->txt_data[2];

			$txt = preg_replace('/\f/', '', $txt);
			$txt = preg_replace('/\r/', '', $txt);
			$txt = preg_replace('/\n/', ' ', $txt);
			$txt = preg_replace('/\t/', ' ', $txt);
			$txt = preg_replace("/[ ]+/u", ' ', $txt);

			if ($this->textjuststarted) {
				$txt = ltrim($txt);
			}  // mPDF 5.7.4
			$this->textjuststarted = false;  // mPDF 5.7.4

			$txt = $this->mpdf->purify_utf8_text($txt);
			if ($this->mpdf->text_input_as_HTML) {
				$txt = $this->mpdf->all_entities_to_utf8($txt);
			}

			if ($this->mpdf->usingCoreFont) {
				$txt = mb_convert_encoding($txt, $this->mpdf->mb_enc, 'UTF-8');
			}
			if (preg_match("/([" . $this->mpdf->pregRTLchars . "])/u", $txt)) {
				$this->mpdf->biDirectional = true;
			}

			$textvar = 0;
			$save_OTLtags = $this->mpdf->OTLtags;
			$this->mpdf->OTLtags = [];
			if ($this->mpdf->useKerning) {
				if ($this->mpdf->CurrentFont['haskernGPOS']) {
					if (isset($this->mpdf->OTLtags['Plus'])) {
						$this->mpdf->OTLtags['Plus'] .= ' kern';
					} else {
						$this->mpdf->OTLtags['Plus'] = ' kern';
					}
				} else {
					$textvar = ($textvar | TextVars::FC_KERNING);
				}
			}

			// Use OTL OpenType Table Layout - GSUB & GPOS
			if (isset($this->mpdf->CurrentFont['useOTL']) && $this->mpdf->CurrentFont['useOTL']) {
				$txt = $this->otl->applyOTL($txt, $this->mpdf->CurrentFont['useOTL']);
				$OTLdata = $this->otl->OTLdata;
			}
			$this->mpdf->OTLtags = $save_OTLtags;

			$this->mpdf->magic_reverse_dir($txt, $this->mpdf->directionality, $OTLdata);

			$this->mpdf->CurrentFont['used'] = true;

			$sw = $this->mpdf->GetStringWidth($txt, true, $OTLdata, $textvar); // also adds characters to subset
			// mPDF 5.7.4
			$this->textlength = $sw * 1 / (25.4 / $this->mpdf->dpi);
			$this->texttotallength += $this->textlength;

			$pdfx = $x * $this->kp;
			$pdfy = -$y * $this->kp;

			$aixextra = sprintf(' /F%d %.3F Tf %s %s Tr %s %s ', $this->mpdf->CurrentFont['i'], $this->mpdf->FontSizePt, $opacitystr, $render, $fillstr, $strokestr);

			$path_cmd = 'q 1 0 0 1 mPDF-AXS(0.00) 0 cm '; // Align X-shift
			$path_cmd .= $this->mpdf->Text($pdfx, $pdfy, $txt, $OTLdata, $textvar, $aixextra, 'SVG', true);
			$path_cmd .= " Q\n";

			unset($this->txt_data[0], $this->txt_data[1], $this->txt_data[2]);

			if (isset($current_style['font-size-parent'])) {
				$this->mpdf->SetFontSize($current_style['font-size-parent']);
			}
		} else {
			return ' ';
		}
		// Reset font	// mPDF 5.7.4
		$prev_style = $this->txt_style[count($this->txt_style) - 1];
		$style = '';
		$style .= ($prev_style['font-weight'] == 'bold') ? 'B' : '';
		$style .= ($prev_style['font-style'] == 'italic') ? 'I' : '';
		$size = $prev_style['font-size'] * $this->kf;
		$this->mpdf->SetFont($prev_style['font-family'], $style, $size, false);

		return $path_cmd;
	}