Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

convertPathData removs h0 in pathdata leading to not rending marker-start="url(#a)" in chromium #1493

Closed
JoKalliauer opened this issue Jun 15, 2021 · 1 comment · Fixed by #1967
Labels

Comments

@JoKalliauer
Copy link

Identical issue in scour-project/scour#282

Input

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-316.8 -1343 45 238.2">
 <marker id="a" stroke="#000" markerHeight="5.3" markerUnits="userSpaceOnUse" markerWidth="5.3" refX="2.7" refY="2.7" viewBox="0 0 5.3 5.3">
  <path stroke-linejoin="round" stroke-width=".7" d="M1.3 1.3H4V4H1.3z"/>
 </marker>
 <marker id="b" fill="red" stroke="red" markerHeight="5.3" markerUnits="userSpaceOnUse" markerWidth="5.3" refX="2.7" refY="2.7" viewBox="0 0 5.3 5.3">
  <circle cx="2.7" cy="2.7" r="1.6" stroke-linejoin="round" stroke-width=".7"/>
 </marker>
 <marker id="c" fill="#92d050" stroke="#92d050" markerHeight="5.3" markerUnits="userSpaceOnUse" markerWidth="5.3" refX="2.7" refY="2.7" viewBox="0 0 5.3 5.3">
  <path stroke-linejoin="round" stroke-width=".7" d="M1 1h3.3L2.7 4.4z"/>
 </marker>
 <marker id="d" fill="#ffc000" stroke="#ffc000" markerHeight="5.3" markerUnits="userSpaceOnUse" markerWidth="5.3" refX="2.7" refY="2.7" viewBox="0 0 5.3 5.3">
  <path stroke-linejoin="round" stroke-width=".7" d="m2.7.8 1.8 1.9-1.8 1.8-2-1.8z"/>
 </marker>
 <g fill="none" stroke="#000">
  <path marker-start="url(#a)" d="M15.8-101h0" transform="matrix(10 0 0 10 -452.2 -323.8)"/>
  <path marker-start="url(#b)" d="M15.8-94.2h0" transform="matrix(10 0 0 10 -452.2 -323.8)"/>
  <path marker-start="url(#c)" d="M15.8-87.5h0" transform="matrix(-10 0 0 -10 -136.2 -2074.6)"/>
  <path marker-start="url(#d)" d="M15.8-80.8h0" transform="matrix(10 0 0 10 -452.2 -323.8)"/>
 </g>
</svg>

Output

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-316.8 -1343 45 238.2">
 <marker id="a" stroke="#000" markerHeight="5.3" markerUnits="userSpaceOnUse" markerWidth="5.3" refX="2.7" refY="2.7" viewBox="0 0 5.3 5.3">
  <path stroke-linejoin="round" stroke-width=".7" d="M1.3 1.3H4V4H1.3z"/>
 </marker>
 <marker id="b" fill="red" stroke="red" markerHeight="5.3" markerUnits="userSpaceOnUse" markerWidth="5.3" refX="2.7" refY="2.7" viewBox="0 0 5.3 5.3">
  <circle cx="2.7" cy="2.7" r="1.6" stroke-linejoin="round" stroke-width=".7"/>
 </marker>
 <marker id="c" fill="#92d050" stroke="#92d050" markerHeight="5.3" markerUnits="userSpaceOnUse" markerWidth="5.3" refX="2.7" refY="2.7" viewBox="0 0 5.3 5.3">
  <path stroke-linejoin="round" stroke-width=".7" d="M1 1h3.3L2.7 4.4z"/>
 </marker>
 <marker id="d" fill="#ffc000" stroke="#ffc000" markerHeight="5.3" markerUnits="userSpaceOnUse" markerWidth="5.3" refX="2.7" refY="2.7" viewBox="0 0 5.3 5.3">
  <path stroke-linejoin="round" stroke-width=".7" d="m2.7.8 1.8 1.9-1.8 1.8-2-1.8z"/>
 </marker>
 <g fill="none" stroke="#000">
  <path marker-start="url(#a)" d="M15.8-101" transform="matrix(10 0 0 10 -452.2 -323.8)"/>
  <path marker-start="url(#b)" d="M15.8-94.2" transform="matrix(10 0 0 10 -452.2 -323.8)"/>
  <path marker-start="url(#c)" d="M15.8-87.5" transform="matrix(-10 0 0 -10 -136.2 -2074.6)"/>
  <path marker-start="url(#d)" d="M15.8-80.8" transform="matrix(10 0 0 10 -452.2 -323.8)"/>
 </g>
</svg>

Difference

Screenshot from 2021-06-15 18-25-05

compare in Chromium

input output
Input.svg Output.svg

settings

'use strict'

// const { extendDefaultPlugins } = require('svgo')

module.exports = {
  multipass: true,
  js2svg: {
    pretty: true,
    indent: 1
  },
  plugins: ([
    {
      name: 'cleanupAttrs',
      active: true
    },
    {
      name: 'cleanupEnableBackground',
      active: true
    },
    {
      name: 'cleanupIDs',
      active: true
    },
/*    {
      name: 'cleanupListOfValues',//https://github.com/svg/svgo/issues/1402
    },*/
    {
      name: 'cleanupNumericValues',
      active: true
    },
    {
      name: 'collapseGroups',
      active: true
    },
    {
      name: 'convertColors',
      active: true
    },
    {
      name: 'convertPathData',
      active: true,
      params: {
        noSpaceAfterFlags: false
      }
    },
    {
      name: 'convertShapeToPath', //https://github.com/svg/svgo/issues/1466
      active: true
    },
    {
      name: 'convertStyleToAttrs',
      active: true
    },
    {
      name: 'convertTransform',
      active: true
    },
    {
      name: 'inlineStyles',
      active: true
    },
    {
      name: 'mergePaths',
      active: true,
      params: {
        noSpaceAfterFlags: false
      }
    },
    {
      name: 'minifyStyles',
      active: true
    },
    {
      name: 'moveElemsAttrsToGroup',
      active: true
    },
    {
      name: 'moveGroupAttrsToElems',
      active: true
    },
    {
      name: 'removeAttrs',
      active: true,
    },
    {
      name: 'removeComments',
      active: true
    },
    {
      name: 'removeDesc',
      active: true
    },
    {
      name: 'removeDoctype',
      active: false
    },
    {
      name: 'removeEditorsNSData',
      active: true
    },
    {
      name: 'removeEmptyAttrs',
      active: true
    },
    {
      name: 'removeEmptyContainers',
      active: true
    },
    {
      name: 'removeEmptyText',
      active: true
    },
    {
      name: 'removeHiddenElems',
      active: true
    },
    {
      name: 'removeMetadata',
      active: true
    },
    {
      name: 'removeNonInheritableGroupAttrs',
      active: true
    },
    {
      name: 'removeTitle',
      active: true
    },
    {
      name: 'removeUnknownsAndDefaults',
      active: true,
      params: {
        keepRoleAttr: true
      }
    },
    {
      name: 'removeUnusedNS',
      active: true
    },
    {
      name: 'removeUselessDefs',
      active: true
    },
    {
      name: 'removeUselessStrokeAndFill',
      active: true
    },
    {
      name: 'removeViewBox',
      active: true
    },
    {
      name: 'removeXMLNS',
      active: false
    },
    {
      name: 'removeXMLProcInst',
      active: false
    },
    {
      name: 'sortAttrs',
      active: true
    }
  ])
}

Copyright

source https://commons.wikimedia.org/wiki/File:2014_West_Africa_Ebola_Epidemic_-_New_Cases_per_Week.svg

author https://commons.wikimedia.org/wiki/User:Delphi234

license https://creativecommons.org/publicdomain/zero/1.0

Desktop (please complete the following information):

  • SVGO Version 2.3.0
  • node --version v15.4.0
  • OS: Fedora32
@JoKalliauer JoKalliauer changed the title removing h0 in pathdata leads to not rending marker-start="url(#a)" in chromium convertPathData removs h0 in pathdata leading to not rending marker-start="url(#a)" in chromium Jan 6, 2023
@SethFalco
Copy link
Member

SethFalco commented Mar 2, 2024

Thanks for reporting the issue!

MRE:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 9 9">
  <marker id="a" fill="red" stroke="red" markerHeight="5" markerUnits="userSpaceOnUse" markerWidth="5" refX="2" refY="2" viewBox="0 0 5 5">
    <circle cx="2" cy="2" r="1" stroke-linejoin="round" stroke-width="1"/>
  </marker>
  <marker id="b" fill="green" stroke="green" markerHeight="5" markerUnits="userSpaceOnUse" markerWidth="5" refX="2" refY="2" viewBox="0 0 5 5">
    <circle cx="2" cy="2" r="0.5" stroke-linejoin="round" stroke-width="1"/>
  </marker>
  <path marker-start="url(#a)" marker-end="url(#b)" d="M5 5h0"/>
</svg>

I checked the spec, but I don't see an explicit answer on how to handle marker-start and marker-end for zero sized paths.

Here are my observations across clients, ✅ means it rendered something, otherwise the marker didn't render at all:

Firefox marker-start marker-end
M5 5
M5 5h0
M5 5m0
M5 5z
Chromium marker-start marker-end
M5 5
M5 5h0
M5 5m0
M5 5z
Eye of GNOME marker-start marker-end
M5 5
M5 5h0
M5 5m0
M5 5z

I'm thinking we optimize it as usual. However, post-optimization, we'll check was it a marker only path with a none M/m command. If so, we'll tack a z on the end to preserve the behavior with markers that can be seen consistently across clients.

The reason for z is that it's the shortest way to arbitrarily add a vertex for path markers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants