Is there an SVG path d convention for using z instead of coordinate with other segments? - svg

I've tried to explore a python library for SVG parsing named svgelements. And there is an unusual concept I can't find in any SVG docs, also nor dolphin file browser nor firefox nor gimp can't render svg files using this. There is a z in pathd parsed as a coordinate and passed to Path to create the curve or line with z_point (the end of last move operation). So z used with LQTCS operations to replace a coordinate.
Is it something standard for SVG? And why many other apps can't process this?
I've explored this code for path d parsing
https://github.com/meerk40t/svgelements/blob/master/svgelements/svgelements.py#L408
There's a part with z as number processing

The library is implementing something that is actually part of the SVG 2 specification: Segment-completing close path operation. There is a (apparently failing) test in the Chromium test suite that exemplifies what is meant. It gives the test path element:
<path d="M 10 10 z m 20 70 h 10 v 10 h -10 l z M 70 30 q 20 0 20 20 t -20 20 t -20 -20 T z" />
To make it clear: since SVG 1.0 the z command closes any path in a straight line. This variant makes it possible to define the closing segment as a curved line.
Unfortunately, that part of the specification looks a bit like a dead end. This issue of the W3C SVG working group from August says:
The spec for the Segment-completing close path operation command was added 4 years ago and hasn't been implemented by any browser yet.
(https://svgwg.org/svg2-draft/paths.html#PathDataClosePathCommand). Currently it only exists in the spec, and as a failing wpt test.
consider removing it from the spec?
So far, there has been no further discussion as it seems.

Related

SVG path in javafx 3d viewer

I am trying to load SVGPath (simple line) in JavaFx 3D viewer. I tried adding the SVGPath class object to Group and added it on scene, but it shows only in 2D. Is there a way I can change this to 3D representation. I also tried using JavaFx 3D Shapes like Box and Cylinder but not sure whether it is a correct way to do that. Following is my code.
Group relationGrp = new Group();
SVGPath path = new SVGPath();
path.setStroke(Color.WHITE);
path.setStrokeWidth(10);
path.setContent("M -15 -60 L -15 15 L 60 15z");
svg3dModelGrp.getChildren().add(path);
I think the SVGPath only allows 2D drawing, why ? Because you just have to introduce (positionX, positionY, and some curve details...) in each action and Logically a line has no depth:
//MoveTo (from positionX and positionY) / LineTo (to positionX and positionY)
Mx y , Lx y ...
You can play with the path to create depth effects by creating many shapes one behind the other with a decremented size but I do not believe that the SVGPath is made for this purpose !
Wikipedia :
Scalable Vector Graphics (SVG) is an XML-based vector image format for two-dimensional graphics

Is this a valid SVG path?

I've run into a problem rendering the following SVG path with various svg libraries:
<path d="M19.35 10.04c-.68-3.45-3.71-6.04-7.35-6.04-2.89 0-5.4 1.64-6.65 4.04-3.01.32-5.35 2.87-5.35 5.96 0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zm-2.35 2.96l-5 5-5-5h3v-4h4v4h3z"/>
specifically, you can see something odd about this block:
4.04-3.01.32-5.35
this fixes it:
4.04-3.01+0.32-5.35
... as does this:
4.04-3.01 0.32-5.35
My reading of the SVG spec suggests the original path is invalid, but since the icon comes right out of Google's material design icons (https://github.com/google/material-design-icons) - and there's many similar "errors", I'm a little suspect of my reading of the BNF.
Can anyone offer a second opinion?
4.04-3.01.32-5.35 is valid. The SVG path specification grammar says that we're processing this
curveto-argument comma-wsp? curveto-argument-sequence
The ? after comma-wsp means 0 or 1 of those. In this case we've 0.
Tracing through the BNF we end up in the part that's about parsing numbers prior to any exponentiation character i.e.
digit-sequence? "." digit-sequence.
Once we've seen one full stop we can't see any more unless we see an exponent and so the second full stop must be part of something else i.e. the next number.
So the above character sequence corresponds to the values: 4.04 -3.01 .32 -5.35

How to properly scale a glyph of an SVG font using an SVG symbol viewBox

I'm utilizing the Bravura music font.
Here's its font-face definition:
<font-face
font-family="Bravura"
font-weight="400"
font-stretch="normal"
units-per-em="2048"
panose-1="5 6 0 0 0 0 0 0 0 0"
ascent="1638"
descent="-410"
bbox="-889 -4080 4749 4120"
underline-thickness="102"
underline-position="-102"
unicode-range="U+0020-1D1DD"
/>
I'm trying to wrap my head around font metrics. I've studied the explanation on this site: But I'm still unclear.
My goal is to translate the glyphs into a properly scaled SVG path using an SVG symbol viewBox attribute.
So the EM square (which is an imaginary square enclosing each glyph) is 2048x2048 units (defined by units-per-em). A unit is 1/72 of an inch. My monitor DPI is 96x96
Converting this to pixels = 2048 * 96/72 = 2730 1/3 x 2730 1/3
(Let me know if I'm off here)
So each font should natively fit into a 2730 1/3 x 2730 1/3 square?
How does the bounding box #s fit into this process? Are the bbox units in glyph-units as well? (1/72 in)
Should the bbox value below be directly inputted into the viewBox attribute of a symbol?
Do I need to consider ascent and descent values?
Here is a jsfiddle somewhat demonstrating my issue: http://jsfiddle.net/1wqa384u/5/
Any resources or help appreciated.
The em box encompasses the ascent and decent. Notice that ascent-descent=2048.
As for your main question, I think you are confusing yourself a bit. The viewBox tells the browser how to scale the symbol to fit the size specified by the <use> that references it.
So if I understand what you want correctly, your symbol viewBox should just be "0 0 2048 2048".
You should then be able to draw it at, say 12pt, by referencing it like so:
<use xlink:href="#mysymbol" x="100" y="100" width="12pt" height="12pt"/>
You shouldn't have to worry about doing your own DPI conversion.

Merging multiple SVG files into one

first of all I know that there are many similar questions like this, but none of them seem to do the trick for me. I'd like to know if there is any way to combine multiple svg files within one single file. Somewhat like this:
<svg id="background" ...>
<svg id="first" ...>
...
</svg>
<svg id="second" ...>
...
</svg>
...
</svg>
Is there some sort of template or tutorial that helps me do this? In the end I want to do this programmatically using java und javafx 2.2.
To change the SVG in exactly that way, you should check out my SVG Stacking Tool. As SVGs are XML one can use XSLT to transform the data:
SVG Stacking GitHub Repository
Update: As pointed out in the comments, there seems to be a bug so that the SVG file is requested multiple times. More details and a possible solution can be found here:
The Problem with using SVG Sprites
You may try svg-join for combine multiple SVG in one symbol collection.
This tool create two files for you.
The first is "svg-bundle.svg":
<svg ...>
<symbol id="svg1" ...>
<symbol id="svg2" ...>
</svg>
Every symbol is your separate SVG file.
The last one is "svg-bundle.css":
.svg_svg1,
.svg_svg2 {
width: 20px; // for example
height: 20px;
}
Now you may use it in your html:
<link rel="stylesheet" type="text/css" href="svg-bundle.css" />
...
<svg class="svg_svg1"><use xlink:href="svg-bundle.svg#svg1"></svg>
<svg class="svg_svg2"><use xlink:href="svg-bundle.svg#svg2"></svg>
After searching a lot of resource, I fount there is a python solution which is really handy: https://github.com/astraw/svg_stack
Say you have two svg file in hand, 11.svg 12.svg, what you can do is:
python svg_stack.py --direction=h --margin=100 11.svg 12.svg > 1.svg
You may think to have 6 svg files to lay out in this way:
11 12
21 22
31 32
which you can do following step:
# merge 11 12
python svg_stack.py --direction=h --margin=100 11.svg 12.svg > 1.svg
# merge 21 22
python svg_stack.py --direction=h --margin=100 21.svg 22.svg > 2.svg
# merge 31 32
python svg_stack.py --direction=h --margin=100 31.svg 32.svg > 3.svg
# merge all
python svg_stack.py --direction=v --margin=100 1.svg 2.svg 3.svg > final.svg
note that you can change merge direction using v and h
I think the best and easiest way is to do this, assuming you only need to support the latest two major versions of major browsers, Android 9 Chrome, iOS 13 Safari, Desktop: Chrome, Firefox, Safari, Edge 87.
1 EDIT: First compress all the SVGs as they might break inside CSS otherwise using for example https://jakearchibald.github.io/svgomg/
2 Create a separate stylesheet and embed the svgs:
.icon-1 {
background-image: url('data:image/svg+xml;utf8,<svg>...</svg>');
}
.icon-2 {
background-image: url('data:image/svg+xml;utf8,<svg>...</svg>');
}
3 Lazy load this stylesheet with js - since these sorts of stylesheets tends to become very big and usually aren't needed to block rendering of the page.
I escaped # with %23(do not know if it's really necessary) it seems like you do not need to escape regular svgs in other ways - haven't tested if they contain inline style tags though (these styles can be moved to your stylesheet anyway)
I used Victor gem https://github.com/DannyBen/victor
first_svg = File.open("first.svg").read
second_svg = File.open("second.svg").read
first_content = first_svg.split("\n")[1..-2].join(", ")
second_content = second_svg.split("\n")[1..-2].join(", ")
svg = Victor::SVG.new width: "100%", height: "100%"
svg << first_content
svg << second_content
svg.save 'final.svg'
maybe you can use svg-sprite, it's a nodejs tool
svg-sprite is a low-level Node.js module that takes a bunch of SVG files, optimizes them and bakes them into SVG sprites
Are you saying you have entirely distinct SVG documents? In that case, what is the point of trying to cram them into one document? I'm confused.
If what you mean is you want to enclose one svg element in another, that's entirely possible, and in that sense your sample is syntactically correct.
If for some reason you really want to hold what are intrinsically distinct documents in a single SVG document, then I suppose you could use CSS to turn the display of each on and off.
#first, #second { display: none; }
.display-first #first { display: block; }
.display-second #second { display: block; }
function toggle_first () { document.body.classList.toggle("first"); }
or something along those lines.

How to convert latitude/longitude in degrees to BBOX where SRS=EPSG:27700

Anyone know how to convert latitude, longitude in degrees to define a BBOX where SRS=EPSG:27700?
I am trying to call a WMS service with a URL like following (not a real link):
http://mysecretmappingserver.com/wms?user=myuser&pwd=mypassword&VERSION=1.1.1&REQUEST=GetMap&LAYERS=ap25cm&STYLES=&SRS=EPSG:27700&BBOX=229096,231675,229296,231875&width=400&height=400
Any language would be fine; C# preferable.
Spacedman has been trying to help me, but I can't seem to get Proj4Net to work for me - all me, I'm sure - but if someone knows either Proj4Net or the math involved, that might be better...
You need an interface to the PROJ.4 projections library in your language of choice. In R, for example, its in the rgdal package:
Here's some points (1,1 to 2,2 degrees) in epsg:4326:
> pts
SpatialPoints:
coords.x1 coords.x2
[1,] 1 1
[2,] 2 2
Coordinate Reference System (CRS) arguments: +init=epsg:4326
and voila:
> spTransform(pts,CRS("+init=epsg:27700"))
SpatialPoints:
coords.x1 coords.x2
[1,] 734005.9 -5416918
[2,] 845270.7 -5305999
Coordinate Reference System (CRS) arguments: +init=epsg:27700
Proj.4 docs here:
http://trac.osgeo.org/proj/
Since this is OSGB, probably a better example would be in the UK: here's a point in central london:
> pts = SpatialPoints(cbind(-0.109863,51.460852),proj4string=CRS("+init=epsg:4326"))
> spTransform(pts,CRS("+init=epsg:27700"))SpatialPoints:
coords.x1 coords.x2
[1,] 531407.1 175235.8
Coordinate Reference System (CRS) arguments: +init=epsg:27700
+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000
+y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs
+towgs84=446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894
I recommend ogr2ogr, which among other things can convert between projections. I have it installed on my Mac, and there are binding e.g. to Python and many other languages. You can also use it on the commandline. Homepage is http://www.gdal.org/ogr2ogr.html

Resources