jonH Posted February 19, 2021 Share Posted February 19, 2021 (edited) 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 New document, Presets -> Devices -> iPad Mini Use Donut tool to create Donut (screenshot "ad donut.png") Export entire document as SVG (going via Export Persona and slices doesn't make any difference), (e.g. "xcodeProblem.svg") Open an Xcode project and navigate to an Assets.xcassets Drag SVG file exported in 3 into the project's Assets.xcassets 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 Find the Donut's path element. 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. Save the file (e.g. "xcodeProblem tweaked style.svg") 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. Draw outer ellipse Draw an inner ellipse NB: manually mirror the inner ellipse so that its drawing direction is in the opposite direction to the outer. Align inner with outer Select both and XOR differentially union together to create singe curves, donut. Export as SVG and file works okay in Xcode (e.g. "xcodeProblem xor'd different rotations.png") 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 Likely to have similar issues with other hollow shapes. Omnigraffle screws this up as well. Inkscape and Sketch gets it right. The SVG renders just fine in Firefox, Safari, preview etc, just within Xcode and on iOS xcodeProblem.svg xcodeProblem tweaked style.svg xcodeProblem xor'd different rotations.svg Edited February 19, 2021 by jonH Typo fix Quote Link to comment Share on other sites More sharing options...
Staff Sean P Posted February 19, 2021 Staff Share Posted February 19, 2021 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.