SVG subtraction of objects and paths

2.3k views Asked by At

I am trying to create an SVG font, so I need to create some paths. One of the letters is defined by the following path:

Path

Which I created with svgwrite, by creating two circles and a rect, and then using inkscape to take the difference of the two circles and the intersection with the straight line, like so: Combination

My question is if I can do this directly with SVG or svgwrite? Either doing the boolean operations, or creating a path that behaves as the one above.

I've tried to create a black and white circle with a path like:

 d="M0,128 A128,128,1,1,0 0 127.9 Z\
  M 32 128 A 96 96 1 1 0 32 127.9 Z"

with fill="#000000", stroke = "none", fill-rule="evenodd" However this ring is not recognized by the SVG font editor (it just creates a black disc).

I also tried to create the combination of paths (outer circle, inner circle, horizontal line)

d="M0,128 A128,128,1,1,0 0 127.9 Z\
 M 32 128 A 96 96 1 1 0 32 127.9 Z \
M 38 128 l 0 15 l 180 0 l 0 -30 l -180 0 z"

but although I can see the right-looking result when I open the SVG, the font editor will not recognize the path created which looks like this:

path generated

Is there some way to generate programmatically the path of the first picture above?

3

There are 3 answers

0
Massagran On

following @martineau's suggestion and this SO question, I came to this solution:

  • Create a circle made of two halfs
  • Creates two smaller half circles (not quite circular)
  • then use fill-rule: evenodd to combine all of them.

    d="
    M 128, 128                 
    m -128, 0                    
    a 128,128 0 1,0 256,0\    
    a 128,128 0 1,0 -256,0\
    M 32,112 a 1.15 1 0 1 1 194, 0z\
    M 32,142 a 1.15 1 0 1 0 194, 0z\
    "
    

which returns something like this: e letter path from script. Unfortunately, the Inkscape SVG font editor only renders this: Imgur

So I'll have to continue investigating where the problem may come from. Further suggestions are welcome.

0
Ghost On

The first arc has a negative (0) draw angle, the second must have a positive (1) draw angle and drawn from the opposite side to achieve the desired effect.

#--------------------------N-----------↓↓↓-↓↓↓-------------P-↓↓↓-↓↓↓↓↓----------------------------------------------
d="M 0 128 A 128 128 1 1 0 0 127.9 Z M 224 128 A 96 96 1 1 1 224 127.9 Z M 38 128 L 0 15 L 180 0 L 0 -30 L -180 0 Z"
0
Michael Mullany On

Filters don't produce paths, they just produce bitmaps (so if you need a path - this is the wrong answer). But Here's a version using an SVG Filter - since you tagged the question with it (won't work in Firefox - can't use objects as feImage inputs yet - you'd have to inline them as data URI).

<svg width="200px" height="200px">
  <defs>
    <circle id="inner" cx="80" cy="80" r="60" fill="white" />
    <line id="crossbar" x1="20" x2="140" y1="80" y2="80" stroke-width="22" stroke="black"/>
    
    <filter id="combine" x="0%" y="0%">
      <feImage xlink:href="#inner" result="innerwhite"/>
      <feImage xlink:href="#crossbar" result="crossbarthing"/>
      <feComposite operator="xor" in="SourceGraphic" in2="innerwhite"/>
      <feComposite operator="over" in2="crossbarthing"/>
    </filter>
  </defs>
  <circle filter="url(#combine)" cx="100" cy="100" fill=
"black" r="80"/>"
</svg>