Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make stroke width immune to the current transformation matrix

In SVG (and Canvas, Quartz, Postscript, ...), the transformation matrix affects both the path coordinates and the line width. Is there a way to make an adjustment so the line width is not affected? That is, in the following example, the scale is different for X and Y, which makes the square into a rectangle, which is OK, but it also makes the lines wider on two sides.

  <g transform="rotate(30) scale(5,1) ">
      <rect x="10" y="10" width="20" height="20" 
            stroke="blue" fill="none" stroke-width="2"/>
  </g>

rectangle width scaled pen

I can see that would be useful in many cases, but is there a way to opt out of it? I suppose I would like to have a separate pen TM or be able to set the pen to be an ellipse that the CTM converts into a circle, but I don't see anything like that.

Lacking that, I think I have to not tell SVG about my CTM and instead transform the coordinates myself, which means converting primitives like rect to their path equivalents.

like image 251
xan Avatar asked Apr 27 '12 20:04

xan


2 Answers

Edit:

There is an attribute you can add to your rect to get exactly this behavior:

vector-effect="non-scaling-stroke"

This was wrong:

This will work if you apply the transform directly to the shape, not the group it is in. Of course, if you wanted to group several items and scale them all together, that approach won't work.

<rect x="10" y="10" width="20" height="20" 
            stroke="blue" fill="none" stroke-width="2"
            transform="rotate(30) scale(5,1)"/>

This may also depend on your SVG viewer; Inkscape renders your file the way you want (stroke width not affected by scale) but Chrome renders it as you have shown.

like image 124
Russell Zahniser Avatar answered Oct 13 '22 20:10

Russell Zahniser


In postscript, describing the path and performing the stroke are separate events, so it's perfectly possible to have a separate "pen" TM.

%!PS
%A Funky Shape

matrix currentmatrix %save normal matrix for stroke pen
306 396 translate
72 72 scale
1 1 5 { pop
    360 5 div rotate
    1 0 translate
    0 0 moveto
    1 1 5 { pop
        360 5 div rotate
        1 0 translate
        1 0 lineto
        -1 0 translate
    } for
    -1 0 translate
    closepath
} for
setmatrix
[ 1 -3 4 2 0 0 ] concat %put some skew in the pen
10 rotate     %makes it look more "organic"
stroke
showpage
like image 7
luser droog Avatar answered Oct 13 '22 18:10

luser droog