SVG path with transparent fill becomes grey with TCPDF - svg

I have a number of SVG images being inserted into a PDF file using TCPDF. For example:
<path d="M0 100 L 80 100 L 40 27 L 0 100" stroke="black" fill="transparent" stroke-width="5" />
The problem is that TCPDF seems to turn any transparency to grey. How can I make it transparent? I cannot simply turn it to white as it is being placed on top of other data as well.
Many of the shapes are complex, utilizing bezier curves and stroke arrays so I need to use a path rather than lines, polygons, or polylines.

I think this might not be possible, but I have found a workaround. Rather than setting
fill="transparent"
I just use:
fill="none"
or
fill-opacity="0"
This seems to work fine. Both can be found on this page:
How to make an SVG element transparent (using SVGweb)

Related

Minimal svg definition of a polygon with empty squares inside

I'm searching for the simplest definition in svg of a squared number '8', like in the figure below (black inside).
Ways that come to my mind are made of filling several polygons (minimal would be 1 black rectangle and 2 white squares). Is there a way to define it with a single command, specifying all the vertices?
Update: the purpose, BTW, is to create a font from svg files like this one.
You can overlap multiple paths in a single path element and using the fill-rule "evenodd" the intersecting areas will crop. like so:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
<path stroke-width="0" d="M20,20 h20 v35 h-20z M25,25 h10 v10 h-10z M25,40 h10 v10 h-10z" fill-rule="evenodd" />
</svg>
Here is a link that explains how it works.

Better way to position svg:polygon

The SVG elements <line>, <circle>, <rect>, <text> and , <image> allow for positioning by x and y based off of the view port. Furthermore they can also be relatively positioned. Is there any way to accomplish this for <polygon> than to wrap it in an <svg>? The closest substitute for <polygon>, <path>, also has this... issue.
Based on the excellent comment by #Michael Mullany I was able to find a solution to the issue. By putting the polygon or path in side a <defs> tag it can be used later on in a <use> tag. The <use> tag allows for setting of x and y attributes that function the same as the attributes of other simple shapes like <line>, <circle>, <rect>, <text>
http://jsbin.com/iqEkAsE/2
<svg width="100%" height="100%">
<defs >
<path id="Triangle"
d="M 1 1 L 200 1 L 100 200 z"
fill="orange"
stroke="black"
stroke-width="3" />
</defs>
<use x="33%" y="33%" xlink:href="#Triangle"/>
<use transform="scale(-1)" x="-66%" y="-66%" xlink:href="#Triangle"/>
</svg>
It would be nice to be able to scale the shape dynamically by setting the width and height property of the <use> to a percent but it can still be scaled with a transform.
Use transformations (translation, rotation, scale), that is the correct way to do it.
The other shapes allow you to use a point defined by x,y coordinates because that's just a part of the shape definition (i.e. how do you define a circle, you need the center point and the radius).
In theory you could position an element using its bounding box, however the bounding box is not "settable" (there is no setBBox method), there is only getBBox()

How do I draw an arc in SVG that starts out thick and gets thinner until reaching a single point?

I want an arc line that goes from thick to thin, kind of like figure 13 here:
Is this possible with SVG?
Not with just a stroke, no. You would have to use a fill, and offset the paths slightly to get the tapering effect.
I found a way to do it, just draw two lines with a little offset in beginning point. Just like this:
<svg viewBox="0 0 1000 400">
<path d="M 50,250 C 50,150 150,50 250,50" fill="none" stroke="green" stroke-width="11"></path>
<path d="M 60,250 C 60,150 150,50 250,50" fill="none" stroke="green" stroke-width="11"></path>
</svg>
In Inkscape, there are Triangle In and Triangle Out styles for drawing curves that look like that, and they just make a path, so I assume not.

SVG dilate/erode filter vs. Illustrator Offset Path

Below is a screen capture of SVG image which is rendered on Chrome 22.0.1229.79 Mac. The original svg is on jsfiddle:
http://jsfiddle.net/LGBk5/
The left image is made using SVG:s dilate and erode filters. The right one is made using Illustrator's Offset Path effect.
The left one has problems: the border at the bottom is distorted and curves are not as smooth. Meanwhile the thick black border is the same in both.
Has my SVG some parameter wrong or are the dilate and erode filters so seemingly buggy?
EDIT: The purpose is to make paths thinner or thicker in SVG, but according to this example, the erode/dilate is not stable enough to rely.
Filter effects are done on pixel data (the rasterized path), while the path offset operation in Illustrator (similar in Inkscape) is done using the original path data (or vector data if you wish).
The former is like using photoshop filters, the latter is creating new paths by using the existing path. They're both stable, but they're not the same operation.
Illustrator's path offset and SVG filters erode/dilate are different operations.
This erode filter is working as designed - there is no bug here. For every pixel in the input image, the filter looks at the maximum RGBA values in a rectangle around it (the radius). In a normal image this tends to generate "rectangular highlights" for want of a better term. And results in weird artifacts when applied to curved draw paths. From the spec:
The dilation (or erosion) kernel is a rectangle with a width of
2*x-radius and a height of 2*y-radius. In dilation, the output pixel
is the individual component-wise maximum of the corresponding R,G,B,A
values in the input image's kernel rectangle. In erosion, the output
pixel is the individual component-wise minimum of the corresponding
R,G,B,A values in the input image's kernel rectangle.
So, imagine that that single pixel at the pointy end of your shape. With a 10 pixel "radius" in your filter (and remember that radius is an incredibly misleading term because it's using a rectangle not a circle!). Let's say it's at 100,100, for arguments sake. When the filter processes values for pixels in the range 90,110 to 110,110, its dilation radius is going to detect that pixel at 100,100 and paint all pixels in that range black. And just like that, your nice pointy end has been dilated into a straight line.
Note that you can achieve most offset path effects using nested strokes (some of which have masks to trim the inside or outside of the path.
For example, here is the OP's path reimplemented this way:
<!-- Left drawing is made using erode and dilate -->
<!-- Right one is made by Illustrator's Offset Path -->
<svg width="612" height="792" viewBox="0 0 612 792" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="curve" d="M21.552,74.438c2.531-28.879,73.668-52.734,102.629-53.971
c32.164-1.373,74.764,23.746,61.766,53.197c-32,72.5-84.236-59.594-109.5-29.5c-23.367,27.833,55.4,142.969,55.4,142.969
S18.109,113.708,21.552,74.438z"/>
<mask id="inner">
<use xlink:href="#curve" fill="white"/>
</mask>
</defs>
<!-- this black outermost line -->
<use x="10" y="10" xlink:href="#curve" style="stroke:black;stroke-width:26;stroke-linejoin:miter;stroke-miterlimit:10"></use>
<!-- thick red outer line -->
<use x="10" y="10" xlink:href="#curve" style="stroke:#f00;stroke-width:24;stroke-linejoin:miter;stroke-miterlimit:10"></use>
<!-- innermost black thin line, with green fill -->
<use x="10" y="10" xlink:href="#curve" style="fill:#1CFF00;stroke:black;stroke-width:32;stroke-linejoin:miter;stroke-miterlimit:10" mask="url(#inner)"></use>
<!-- blue inner stroke -->
<use x="10" y="10" xlink:href="#curve" style="fill:none;stroke:#5555FF;stroke-width:30;stroke-linejoin:miter;stroke-miterlimit:10" mask="url(#inner)"></use>
<!-- lastly, the black line -->
<use x="10" y="10" xlink:href="#curve" style="fill:none;stroke:black;stroke-width:10;stroke-linejoin:miter;stroke-miterlimit:10"></use>
<g transform="translate(210,10)">
<path fill="#FF0000" stroke="#231F20" d="M126.273,201.917c-1.188-0.766-29.407-19.044-57.679-42.532c-41.739-34.676-60.31-60.754-58.441-82.068
c1.575-17.974,18.042-34.105,48.943-47.945c21.673-9.707,48.782-16.997,65.925-17.729c1.023-0.043,2.057-0.065,3.096-0.065
c26.722,0,55.103,13.789,67.484,32.787c7.866,12.07,9.101,25.736,3.476,38.482c-8.697,19.704-20.608,29.697-35.403,29.702
c-0.002,0-0.007,0-0.01,0C144.382,112.551,127.62,95,111.407,78.028c-7.054-7.385-18.575-19.446-23.912-21.338
c-1.086,2.002-6.186,15.821,20.666,67.477c16.226,31.214,35.475,59.438,35.668,59.72l35.977,52.589L126.273,201.917z"/>
<path fill="#5555FF" stroke="#231F20" stroke-width="10" stroke-miterlimit="10" d="M22.939,78.438
c2.531-28.879,73.668-52.734,102.629-53.971c32.164-1.373,74.764,23.746,61.766,53.197c-32,72.5-84.237-59.594-109.5-29.5
c-23.366,27.833,55.401,142.969,55.401,142.969S19.497,117.709,22.939,78.438z"/>
<path fill="#00FF00" stroke="#231F20" d="M79.986,131.678C38.498,95.796,38.41,81.397,38.549,79.807c0.289-3.29,5.843-10.151,19.371-17.933
C57.676,78.899,64.972,101.816,79.986,131.678L79.986,131.678z M163.665,84.044c-7.09,0-22.461-16.091-31.646-25.706
c-5.867-6.143-11.433-11.969-16.966-16.846c4.324-0.776,8.128-1.238,11.184-1.368c0.621-0.027,1.249-0.04,1.88-0.04
c16.911,0,36.471,8.903,43.603,19.846c3.317,5.089,2.508,8.623,1.278,11.408C168.884,80.659,165.163,84.043,163.665,84.044
L163.665,84.044z"/>
</g>
</svg>

How to get correct SVG dimensioning / aspect ratio?

I'm making some pointers by hand coding svgs. I have defined a polygon using points in a 100x100 square and gotten the aspect ratio that I want by setting the width and height attributes of the outer SVG element. Here is a jsfiddle of the graphic: http://jsfiddle.net/62WpR/.
Unfortunately, the text is being compressed by the width and height attributes. Is there any way to use these without compressing text, or doing something silly like applying a transform to it?
If this is not possible, I guess I will have to define paths in a coordinate space with the final aspect ratio that I want. Disappointing.
Solved it kind of.
By setting the viewbox to a 1:2 ratio and using transforms on both of the polygons in the svg, I was able to get the dimensions I wanted. As long as the dimensions in the CSS are set to a 2:1 ratio, the graphic will display right.
I have also made judicious use of the preserveAspectRatio property to keep the image at the same aspect ratio. I'm only setting the width in the CSS: http://jsfiddle.net/62WpR/3/
<svg baseProfile="full" contentScriptType="text/ecmascript" contentStyleType="text/css" id="svg" preserveAspectRatio="xMinYMin meet" version="1.2" viewBox="0 0 100 50" xmlns="http://www.w3.org/2000/svg">
<g transform="scale(1 .5)" stroke-linejoin="bevel" stroke="black">
<polygon vector-effect="non-scaling-stroke" fill="#666" id="tab" points="20.0,95.0 5.0,50.0 20.0,5.0 90.0,5.0 95.0,15.0 95.0,85.0 90.0,95.0"></polygon>
<polygon vector-effect="non-scaling-stroke" fill="#FFEA00" id="insert" points="25.0,95.0 10.0,50.0 25.0,5.0" visibility="visible"></polygon>
</g>
<text fill="white" font-size="30" text-anchor="middle" x="60" y="36">999</text>
</svg>​

Resources