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

Subset SVG table with pyftsubset #534

Closed
RoelN opened this issue Feb 29, 2016 · 12 comments · Fixed by #2452
Closed

Subset SVG table with pyftsubset #534

RoelN opened this issue Feb 29, 2016 · 12 comments · Fixed by #2452
Assignees

Comments

@RoelN
Copy link

RoelN commented Feb 29, 2016

It's noted in this issue that the subetter doesn't know how to subset the SVG table. It would be nice if it did as SVG fonts can use all the optimization they can get :)

Currently, I have to explicitly tell pyftsusbet to leave the SVG table alone, as per instructions in the mentioned issue, so that should change too:

pyftsubset --verbose --no-subset-tables+='SVG ' --drop-tables-='SVG '  my-test-font.otf  --text='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ao123%‰€$¢£¥áâàäåãæçéêèëíîìïıñóôòöõøœšßúûùüýÿžÁÂÀÄÅÃÆÇÉÊÈËÍÎÌÏÑÓÔÒÖÕØŒŠÚÛÙÜÝŸ.,:;-–—•·...“‘’‘‚“”„‹›«»/\?!¿¡()[]{}†*&©®@#§+×=_°|'
@RoelN RoelN changed the title Subset SVG tabel with pyftsubset Subset SVG table with pyftsubset Feb 29, 2016
@behdad
Copy link
Member

behdad commented Mar 1, 2016

You can't just do that since SVG docs have references to glyph ids in them. If glyphIDs change (which does in subsetting unless you choose all glyphs), then the SVGs need to be rewritten. That's not impossible. Removing unused parts of the SVGs is harder.

@RoelN
Copy link
Author

RoelN commented Mar 4, 2016

Ah, I see. I was working with a font that had one SVG doc per glyph, so it seemed simple. I suppose any subsetting should be done in the original font design software, or by hand.

@anthrotype
Copy link
Member

The way I would go about this is:

  1. Remove any svg document whose startGlyphID..endGlyphID range doesn't intersect the requested subset
  2. For each remaining SVG document, start with the set of all "glyph{gid}" identifiers in the range covered by that svg document that also intersect our requested font subset. Parse the SVG document with etree, skip the sub-trees of the glyphs whose id is not in the set of ids to keep; expand this set by all the other element ids that are referenced (via xlink:href attribute) from anywhere inside the subtree we're traversing; keep a set of visited node ids, and continue traversing until no more elements in the set of ids to keep is unvisited;
  3. make a new tree only containing elements whose id is in the set to keep; remove id-less elements unless contained within elements whose id should be kept; before removing an element, if any of its children needs to be kept, move these up as siblings; maybe also group top-level elements that are not <g> glyphs under a global <defs> at the top of the document.
  4. renumber glyph indices, both the startGlyphID and endGlyphID of the svgDoc container, and the id="glyphXX" attributes inside it

@behdad
Copy link
Member

behdad commented Apr 15, 2021

That should work, yes. Now find someone to do it please. :))

@anthrotype
Copy link
Member

anthrotype commented Oct 5, 2021

In the OT-SVG spec, I read

Note: Two or more records can point to the same SVG document. In this way, a single SVG document can provide glyph descriptions for discontinuous glyph ID ranges.

That's nice, as it could make subsetting a little easier since we wouldn't need to split SVG docs when subsetting leaves gaps in the GID ranges: we can simply make several records with continuous ranges whose offset points to the same SVG document containing discontinuous GID ranges.

However the current implementation in fontTools.ttLib.tables.S_V_G_ duplicates these shared SVG documents while decompiling the SVG table, but without also trying to share the offsets upon compiling, so in the re-compiled table all records get unique offsets even when the pointed-to bytes may be identical.

I could fix that by building a cache or map of SVG docs to offsets as these are first seen and reuse the offsets for any following records that share the same SVG content.
Or I could rewrite the OT-SVG table as an otData-driven class (like the layout tables) and get the offset sharing for free...

@anthrotype
Copy link
Member

Can somebody point me to existing OT-SVG vector color fonts that I could use to test my in-the-works subsetting implementation? /cc @RoelN @miguelsousa @cjchapman

@anthrotype
Copy link
Member

Can somebody point me to existing OT-SVG vector color fonts...

/cc @twardoch

@khaledhosny
Copy link
Collaborator

https://github.com/aliftype/anti

@cjchapman
Copy link
Member

https://github.com/adobe-fonts/noto-emoji-svg

@anthrotype
Copy link
Member

thank you guys! However, both those OT-SVG fonts are quite simple as far as subsetting is concerned, as each color glyph is defined in its own distinct SVG document. I'd like to see real-world example of fonts that take advantage of all the reuse facilities provided by OT-SVG, e.g. multiuple (ranges of) color glyphs defined within the same SVG document, sharing shapes via <use xlink:href="..."> elements as well as reusing gradients and clipPaths from a shared <defs>.

@RoelN
Copy link
Author

RoelN commented Oct 21, 2021

Unfortunately I only know of OT SVG fonts that use individual SVG documents per glyph, like bixacolor.com.

@anthrotype
Copy link
Member

We can finally subset OT-SVG fonts! 🥳
It should work with simple fonts (with single color glyph per SVG document, like most of the OT-SVG fonts out there) as well as more complex ones with lots of cross-references.
Please test your fonts and send us bug reports. I'll make a release soon.

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

Successfully merging a pull request may close this issue.

5 participants