Jump to content

Donuts in svg exports render as solid circle's in Xcode or iOS


Recommended Posts

Summary

Affinity Designer, as of 1.9, produces SVG exports where at least one simple, hollow shape (donut) is unusable in Xcode or subsequently on iOS

Impact

The problem effectively prevents the use of Affinity Designer by many developers working on the creation of svg assets for the Apple platforms.

Similar issues perhaps for Glowforge users, see https://community.glowforge.com/t/bug-svg-fill-rule-fix/20413

Setup

  • macOS 11.2.1 (20D74) Intel
  • Affinity Designer 1.9.0 on
  • Xcode 12.4 with iOS target 14.0

To reproduce

  1. New document, Presets -> Devices -> iPad Mini
  2. Use Donut tool to create Donut (screenshot "ad donut.png")
  3. Export entire document as SVG  (going via Export Persona and slices doesn't make any difference), (e.g. "xcodeProblem.svg")
  4. Open an Xcode project and navigate to an Assets.xcassets
  5. Drag SVG file exported in 3 into the project's Assets.xcassets
  6. Observe that Xcode renders the Donut incorrectly as a solid circle (screenshot "xcode ad broken.png")

Workaround 1

Manually edit the exported SVG file in coding editor such as Vim, Emacs, VSCode

  1. Find the Donut's path element.
  2. Add a "style="fill-rule:evenodd" attribute to the Donut's path (or if there's an existing one amend it to include the "fill-rule:evenodd" value.
  3. Save the file (e.g. "xcodeProblem tweaked style.svg")
  4. File works okay in Xcode, i.e. has empty middle (screenshot "xcode showing broken and both workarounds.png")

Workaround 2

Manually construct the Donut from two Ellipses, the inner of which is drawn with the opposit rotation.

  1. Draw outer ellipse
  2. Draw an inner ellipse
  3. NB: manually mirror the inner ellipse so that its drawing direction is in the opposite direction to the outer.
  4. Align inner with outer
  5. Select both and XOR differentially union together to create singe curves, donut.
  6. Export as SVG and file works okay in Xcode (e.g. "xcodeProblem xor'd different rotations.png")
  7. File works okay in Xcode, i.e. has empty middle (screenshot "xcode showing broken and both workarounds.png")

Tips on how to workaround, were picked up from the Glowforge forum here https://community.glowforge.com/t/bug-svg-fill-rule-fix/20413 where they are encountering a similar issue.

Misc

  1. Likely to have similar issues with other hollow shapes.
  2. Omnigraffle screws this up as well.
  3. Inkscape and Sketch gets it right.
  4. The SVG renders just fine in Firefox, Safari, preview etc, just within Xcode and on iOS

 

ad donut.png

xcode ad broken.png

xcode showing broken and both workarounds.png

xcodeProblem.svg xcodeProblem tweaked style.svg xcodeProblem xor'd different rotations.svg

Edited by jonH
Typo fix
Link to post
Share on other sites

Hi jonH,

Unfortunately I believe the issue here is actually with Xcode not fully interpreting the SVG correctly.

Looking at the SVG code provided from your xcodeProblem.svg file:

 

<svg width="100%" height="100%" viewBox="0 0 1024 768" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
    <rect id="Artboard1" x="0" y="0" width="1024" height="768" style="fill:none;"/>
    <g id="Artboard11" serif:id="Artboard1">
        <path d="M484.508,222.471C552.453,222.471 607.615,274.665 607.615,338.952C607.615,403.24 552.453,455.434 484.508,455.434C416.563,455.434 361.401,403.24 361.401,338.952C361.401,274.665 416.563,222.471 484.508,222.471ZM484.508,280.712C518.48,280.712 546.062,306.809 546.062,338.952C546.062,371.096 518.48,397.193 484.508,397.193C450.536,397.193 422.955,371.096 422.955,338.952C422.955,306.809 450.536,280.712 484.508,280.712Z"/>
    </g>
</svg>

Observe that in the <svg tag we're setting that the the fill-rule is evenodd. Please see this link for more information on the fill-rule and how evenodd and nonzero work, and how they relate to curve direction). What evenodd does is determine how certain sections of a shape get filled in. In the donut's case it will ensure the hole is not filled. As this is set out in the SVG tag's style it will dictate that any object inside that SVG will use this value for the fill-rule attribute unless it has been explicitly specified/overwritten in an object's own style (which is what your Workaround 1 is doing).

The default value for this attribute is nonzero and this can be seen by removing the 'fill-rule:evenodd;' section from the SVG above.

Now it sounds like Xcode is completely ignoring the SVG's style and reading just that object's style, which unfortunately because it hasn't been explicitly set is causing it to use the default nonzero fill type, causing you to have a hole-less donut. Unfortunately this is an issue you should discuss with Apple regarding Xcode, because we're exporting valid and correct SVG in this instance.

Your workaround 2 is also going to work because the the direction of the inner curve is travelling in a different direction to the outer one. You can reproduce this without using XOR by simply converting your Donut to curves, select a node on the inner circle and then click 'Reverse Curve' on the context toolbar. This will change the direction of the curve (from Clockwise to Anti-Clockwise or vice-versa) which will force the whole because even though it is a nonzero filled object it has curves travelling in a different direction and so forces the hole.

 

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...

Important Information

Please note there is currently a delay in replying to some post. See pinned thread in the Questions forum. These are the Terms of Use you will be asked to agree to if you join the forum. | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.