Closed kkaefer closed 4 years ago
Missing:
spritezero.generateLayout
should parse the SVGs and add the metadatacontent
, stretch-x
, and stretch-y
coordinates need to be stretched by the pixel ratio@kkaefer here's a fixture I just made in illustrator. I think I did it right:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="18px" height="18px" viewBox="0 0 18 18" style="enable-background:new 0 0 18 18;" xml:space="preserve">
<rect x="3" y="3" style="fill:#FFFFFF;stroke:#000000;stroke-width:2;stroke-miterlimit:10;" width="12" height="12"/>
<rect x="4" y="4" style="fill:#00FFEE;" width="10" height="4"/>
<rect id="mapbox-icon-content" x="4" y="8" style="fill:none;" width="10" height="6"/>
<rect id="mapbox-icon-stretch-y" x="13" y="8" style="fill:none;" width="1" height="6"/>
<rect id="mapbox-icon-stretch-x" x="4" y="13" style="fill:none;" width="10" height="1"/>
</svg>
add more thorough test coverage
What kind of test coverage are you referring to? There are already a lot of tests for validation; do you think we should add more SVGs? In that case, I think we'd need a larger variety of icons designed for being stretched that we can test this with. Where do you propose we'd get these from?
Questions from https://github.com/mapbox/mapbox-gl-js/issues/8917:
What do we do when one of the keyword ids like
mapbox-icon-content
is inside a group with a transform? Skew, rotate, or scale transforms could potentially change the bounding box.
The code resolves transforms prior to computing the bounding boxes. I tested translate
transforms, but I'll also check rotation and skewing.
What happens when a keyword id is on a path or some other element rather than a rect? Should that throw an error, or should our service try to derive a bounding box anyway?
The code converts all shapes to paths, and computes the bounding box of the path. We could change it to be restricted to just <rect>
elements, but one application is that you can currently draw lines for stretch-x
and stretch-y
, which more closely mirrors the fact that we only care about one axis.
The code resolves transforms prior to computing the bounding boxes. I tested
translate
transforms, but I'll also check rotation and skewing.
Turns out svgo skips transform folding if elements have an id
attribute. It does cleanup null transforms though.
do you think we should add more SVGs?
Yep that’s what I meant - in my experience SVGO doesn’t always work exactly the way I expect it to. I can make a few more fixtures for you!
Here are some weird SVGs, food for thought.
A shield where each element is individually rotated. Results in a shield that is rotated 45 degrees.
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="18px" height="18px" viewBox="0 0 18 18" style="enable-background:new 0 0 18 18;" xml:space="preserve">
<g>
<rect x="4.5" y="4.5" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -3.7279 9)" style="fill:#FFFFFF;stroke:#000000;stroke-width:2;stroke-miterlimit:10;" width="8.9" height="8.9"/>
<rect x="9.1" y="3.7" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -2.1473 9.6547)" style="fill:#00FFEE;" width="3" height="7.5"/>
<rect id="mapbox-icon-content" x="5.7" y="6.3" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -4.7817 8.5635)" style="fill:none;" width="4.5" height="7.5"/>
<rect id="mapbox-icon-stretch-y" x="8.1" y="12.1" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -5.7637 10.9344)" style="fill:none;" width="4.5" height="0.7"/>
<rect id="mapbox-icon-stretch-x" x="6.3" y="7.6" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -6.0988 8.0179)" style="fill:none;" width="0.7" height="7.5"/>
</g>
</svg>
A shield inside two groups, one with a rotation, one with a translate. Results in a shield that is rotated 45 degrees.
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="18px" height="18px" viewBox="0 0 18 18" style="enable-background:new 0 0 18 18;" xml:space="preserve">
<g transform="rotate(45)">
<g transform="translate(4 -8)">
<rect x="5" y="5" style="fill:#FFFFFF;stroke:#000000;stroke-width:2;stroke-miterlimit:10;" width="8" height="8"/>
<rect x="6" y="6" style="fill:#00FFEE;" width="6" height="2"/>
<rect id="mapbox-icon-content" x="6" y="8" style="fill:none;" width="6" height="4"/>
<rect id="mapbox-icon-stretch-y" x="11" y="8" style="fill:none;" width="1" height="4"/>
<rect id="mapbox-icon-stretch-x" x="6" y="11" style="fill:none;" width="6" height="1"/>
</g>
</g>
</svg>
A shield inside two groups, one with a rotation, one with the reverse rotation. Results in a normal-looking shield:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="18px" height="18px" viewBox="0 0 18 18" style="enable-background:new 0 0 18 18;" xml:space="preserve">
<g transform="rotate(45)">
<g transform="rotate(-45)">
<rect x="5" y="5" style="fill:#FFFFFF;stroke:#000000;stroke-width:2;stroke-miterlimit:10;" width="8" height="8"/>
<rect x="6" y="6" style="fill:#00FFEE;" width="6" height="2"/>
<rect id="mapbox-icon-content" x="6" y="8" style="fill:none;" width="6" height="4"/>
<rect id="mapbox-icon-stretch-y" x="11" y="8" style="fill:none;" width="1" height="4"/>
<rect id="mapbox-icon-stretch-x" x="6" y="11" style="fill:none;" width="6" height="1"/>
</g>
</g>
</svg>
@samanpwbb is that the verbatim output from Illustrator or did you modify them after the export?
did you modify them after the export?
The last two are modified, first is directly from illustrator. Do you think these are edge cases that we shouldn’t worry about?
Ok, I was wondering whether Illustrator will actually put transforms into exported SVGs, but it looks like it does in some circumstances. Affinity seems to resolve them prior to exporting.
@samanpwbb Thanks for the SVGs. I incorportated them into the test suite and changed our parsing so that transforms, including multiple nested transforms on groups, are resolved correctly. The SVGs' stretch zones don't really make a lot of sense given that the entire icon is rotated.
Is there a chance we could see a performance hit when we add this to the API?
Yeah, it can take a few millisecond to process an icon. If we're looking for optimizations, https://github.com/mapbox/spritezero/issues/7 has probably a higher impact. In any case, sprite generation should be an infrequent operation.
This is ready to be merged pending the discussion in https://github.com/mapbox/mapbox-gl-js/issues/8917#issuecomment-558992126
Implements metadata parsing from SVGs for stretchable icons.