penpot / penpot

Penpot: The open-source design tool for design and code collaboration
https://penpot.app
Mozilla Public License 2.0
29.23k stars 1.43k forks source link

Penpot SVGs are very unefficient #3004

Open JulianBrasse opened 1 year ago

JulianBrasse commented 1 year ago

The SVG code in exported files from Penpot is quite inefficient and use some unnecessary/deprecated attributes (xmlns:xlink="...") and also at times empty attributes (transform="") or unused ones (id="..."). The fill attribute and similar attributes are found in style attributes, which isn't recommended. Circles are always ellipses and polygon or polyline shapes are always paths. SVGs exported with text will have embedded the font, instead of converting the text to paths, which could be implemented as shown in #1342 . Additionally many unnecessary elements are used as definitions (defs element) for shadows and gradients, and many unnecessary groups are made. These are only some of the things I have encountered, but they increase the size of the svg files and make them bloated, harder to use and incompatible with some programs. Some examples:

Circle

A simple circle has many more lines of code after export from Penpot. It is the exact same image and no information or content is lost. Often even displaying the SVG file from Penpot doesn't work, most likely due to the bloat and unsupported attributes.

Efficient SVG

circle_efficient

<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <circle cx="50" cy="50" r="50" fill="#60c"/>
</svg>

Current Penpot SVG

circle_unefficient

<!-- Shape: Ellipse -->
<svg xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" width="100" xmlns="http://www.w3.org/2000/svg" style="-webkit-print-color-adjust:exact" id="screenshot-ff2296a7-3f50-801f-8002-267d5fc50b1c" version="1.1" viewBox="0 0 100 100" height="100">
  <g id="shape-ff2296a7-3f50-801f-8002-267d5fc50b1c">
    <g class="fills" id="fills-ff2296a7-3f50-801f-8002-267d5fc50b1c">
      <ellipse rx="50" ry="50" style="fill:#B1B2B5;fill-opacity:1" cx="50" cy="50" transform="">
      </ellipse>
    </g>
  </g>
</svg>

Complex Objects

The difference is much more visible with even just slightly more complex objects that have groups, shadows, text and gradients. Even in this example, where I simply added a diamond-shaped path with dropshadow and grouped everything, the difference in the Penpot version is extreme.

Efficient SVG

icon_efficient

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <defs>
    <filter id="a">
      <feDropShadow dx="0" dy="0" stdDeviation="2.5" flood-opacity="0.5" />
    </filter>
  </defs>
  <circle r="50" cx="50" cy="50" fill="#60c"/>
  <polygon points="50,25 75,50 50,75 25,50" filter="url(#a)" fill="#fff"/>
</svg>

Current Penpot SVG

icon_unefficient

<!-- Shape: Icon -->
<svg xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" width="130" xmlns="http://www.w3.org/2000/svg" style="-webkit-print-color-adjust:exact" id="screenshot-ff2296a7-3f50-801f-8002-26825274e7da" version="1.1" viewBox="-15 -15 130 130" height="130">
  <g id="shape-ff2296a7-3f50-801f-8002-26825274e7da" rx="0" ry="0">
    <g id="shape-ff2296a7-3f50-801f-8002-267d5fc50b1c">
      <g class="fills" id="fills-ff2296a7-3f50-801f-8002-267d5fc50b1c">
        <ellipse rx="50" ry="50" style="fill:#6600cc;fill-opacity:1" cx="50" cy="50" transform="">
        </ellipse>
      </g>
    </g>
    <g id="shape-ff2296a7-3f50-801f-8002-2681cce563fe">
      <defs>
        <filter id="filter_rumext-id-116" x="-0.6" y="-0.6" width="2.2" height="2.2" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB">
          <feFlood flood-opacity="0" result="BackgroundImageFix">
          </feFlood>
          <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0">
          </feColorMatrix>
          <feOffset dx="0" dy="0">
          </feOffset>
          <feGaussianBlur stdDeviation="2.5">
          </feGaussianBlur>
          <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0">
          </feColorMatrix>
          <feBlend mode="normal" in2="BackgroundImageFix" result="filter_ff2296a7-3f50-801f-8002-26821673fc0e">
          </feBlend>
          <feBlend mode="normal" in="SourceGraphic" in2="filter_ff2296a7-3f50-801f-8002-26821673fc0e" result="shape">
          </feBlend>
        </filter>
        <filter id="filter_shadow_rumext-id-116" x="-0.6" y="-0.6" width="2.2" height="2.2" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB">
          <feFlood flood-opacity="0" result="BackgroundImageFix">
          </feFlood>
          <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0">
          </feColorMatrix>
          <feOffset dx="0" dy="0">
          </feOffset>
          <feGaussianBlur stdDeviation="2.5">
          </feGaussianBlur>
          <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0">
          </feColorMatrix>
          <feBlend mode="normal" in2="BackgroundImageFix" result="filter_ff2296a7-3f50-801f-8002-26821673fc0e">
          </feBlend>
          <feBlend mode="normal" in="SourceGraphic" in2="filter_ff2296a7-3f50-801f-8002-26821673fc0e" result="shape">
          </feBlend>
        </filter>
      </defs>
      <g class="fills" id="fills-ff2296a7-3f50-801f-8002-2681cce563fe">
        <path rx="0" ry="0" style="fill:#ffffff;fill-opacity:1" d="M25.000,50.000L50.000,25.000L75.000,50.000L50.000,75.000L25.000,50.000Z" filter="url(#filter_rumext-id-116)">
        </path>
      </g>
    </g>
  </g>
</svg>
SatarisGIT commented 1 year ago

I noticed a similar problem. For example, in the screenshot is the same SVG - left before import, right after export from PenPot

image

superalex commented 1 year ago

Hey!, thank you very much for the feedback. The reason after all of these is that we have to support in svg thins that aren't supported directly (multiple fills, multiple strokes, different type of strokes...)

There is an enhancement in our Taiga to make our svg exports cleaner, I'm pointing this issue from there: https://tree.taiga.io/project/penpot/issue/4131

KazimirPodolski commented 10 months ago

Penpot unapologetically and unconditionally supports open standards for all your design work. Our SVG and web standards approach means zero vendor lock-in and extreme interoperability.

One could argue that this is misleading as bloated svg is barely usable outside of Penpot. Following the promise in words rather than in spirit.

PvUtrix commented 6 months ago

This is something to be fixed. I've just exported a 250kb svg from Figma, pasted it into Penpot, exported it back and it's 350kb now, full of garbage and the structure is broken & IDs are lost, which is critical for me, since we parse and manipulate the svg in our web app.

If I import and export using Sketch, the file size becomes 5kb smaller, keeping the structure and ids.

This is a show stopper for us...

JulianBrasse commented 5 months ago

@superalex It seems that nothing has happened on the taiga + I can't comment there, so I am wondering if this somehow got ignored as this really is the biggest issue I have been having with penpot, so much so that I have literally been coding the SVG files myself or using PowerPoint's slightly less messy SVG export (I am aware that inkscape exists but no), rather then Penpot's. This is why I am asking your team to rethink the importance of this and maybe consider fixing the problem.

PvUtrix commented 4 months ago

Any updates planed on this issue?

fabianmichael commented 4 months ago

I just evaluated Penpot (and I’m very impressed so far :-)) for the first time for an upcoming project and ran into the same issue, when creating icons for a website. A modern web design workflow often means to manage all vector assets within one application, at least that’s what I did when working with Sketch or Figma. A website often contains dozens of icons, which usually need to follow a certain structury to allow for dynamic colorization. This often requires to set fills to e.g. currentColor manually after exporting – not a big deal when the exported SVG is clean. Unfortunately, this is currently a show-stopper for my team for adopting Penpot, because even SVGO is not able to remove all of the extra code from Penpot-exported SVGs at the moment. I hope that this issue is given a certain priority, because as long as we cannot get clean SVGs out of Penpot, its use for web design is rather limited.

PvUtrix commented 4 months ago

Why isn't this given a top priority? Inefficient SVGs are a show stopper for use on the web!