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

[svg-native] Decide whether reusable graphical elements are needed #689

Open
jarek-foksa opened this issue May 9, 2019 · 18 comments
Open

Comments

@jarek-foksa
Copy link

SVG 2 defines following primitives for creating reusable graphics:

  • <pattern>
  • <marker>
  • <symbol>
  • <use>
  • <linearGradient href="...">
  • <radialGradient href="...">.

Some of those elements are already discussed in #671 and #670, but I think the broader question that needs to be answered first is: are they adding any value when it comes to rendering performance, file read/write performance, security or interoperability?. If not, then I would get rid of them altogether just like it has been done with all the text elements.

@jarek-foksa
Copy link
Author

One concern raised in #670 by @dirkschulze is that the file size could increase greatly if no means for graphics reuse are provided. Perhaps this could be mitigated by allowing SVG Native files to be optionally gzipiped like SVGZ?

Another concern pointed out in #671 is that supporting some of those primitives would greatly complicate the task of writing a compliant SVG Native renderer, therefore holding back the adoption of the new standard.

@jarek-foksa
Copy link
Author

One more concern is that if those elements are supported, SVG Native would have to also support either "xlink:href" attribute (verbose and ugly) or "href" attribute (breaks backward compatibility with SVG 1.1).

@BigBadaboom
Copy link
Contributor

BigBadaboom commented May 9, 2019

  • <pattern>
    Usage of pattern is quite high I think. Apart from its obvious use for repeating fills, there is a common use case where <pattern> is used to place images inside shape elements. I think this would be missed if it was removed.

  • <marker>
    Not sure about this one. It is commonly used, but maybe not in the situations that SVG Native is intended for.

  • <symbol>
    Has a very similar purpose and function as child <svg> elements, which have been removed. I'm not sure what the purpose of removing child <svg> elements was. But any argument for removing one, could equally apply to the other.

  • <use>
    I think these should stay. They are commonly used and very useful for reducing file sizes.

  • <linearGradient href="..."> / <radialGradient href="..."> / <pattern href="...">
    In my experience, the href attribute for these is hardly ever used. It is an obvious candidate for removal.

@jarek-foksa
Copy link
Author

All those elements could be replaced with other more basic (and verbose) constructs. For example a <pattern> based bitmap texture fill effect could be achieved with an <image> which is clipped by a <clipPath> or has an alpha channel which imitates a clipping mask.

It looks like the main advantage of those elements is better semantics and decreased markup repetition. I'm not really sure whether this is enough to justify their inclusion in the SVG Native format, especially considering the fact that <text> is not included.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented May 9, 2019

One thing to consider is what features are available in the native graphics libraries. If most of these libraries have a simple pattern tiling function that the renderer can call, it is a bit of a waste of bandwidth to insist that every pattern tile be encoding as separate graphic instructions.

@dirkschulze
Copy link
Contributor

IMO the common difficulty of <pattern>, <mask>, inner <svg>, <symbol> and objectBoundingBox is keeping track of the different viewports for resources like gradients but even for percentage units. This increases the complexity and the temporarily used memory.

Each of the listed features may have other difficulties as well.

IIRC some authoring tools use xlink:href on gradients. Adobe Illustrator extensively uses it to share color stops. It would not be an implementation issue to skip the optimization but, as said by @jarek-foksa, it could increase file size. Especially for OT fonts, file size does matter.

@litherum
Copy link
Contributor

It’s probably worth making a distinction between the general principal vs any individual example.

In principle, we shouldn’t diverge too much from SVG proper, and the mechanism that SVG uses to represent patterns and gradients is to have an extra element (<pattern>, <linearGradient>) that is referenced by potentially many nodes. Inlining the contents of these nodes into every user of them would probably be too much of a departure from SVG. If we want to have these features, they should match SVG’s design for them, which is to say, be reusable.

Beyond general principle, it’s worth discussing each idea individually.

  • <pattern>: All 2D graphics libraries I know of have some facility for patterns, which seems to indicate they are a convenient concept. They can, however, be flattened into individual geometry. However, as the visual size of the pattern shrinks, the file size of the flattened pattern grows proportionately. We implemented patterns in our OT-SVG rasterizer, and I believe it is impossible to implement on CoreGraphics without using SPI.
  • <marker>: These should just be additional geometry. There’s no reason for them to exist in the document, because we are not preserving document semantics within the file.
  • <symbol> & <use>: These should be considered together. They are tricky to implement correctly, but they are used in lots and lots of content. Presumably that’s a signal that they’re useful. It might be worth keeping the elements themselves, but not supporting all of their attributes (like x=).
  • Inner SVG: This is significantly more difficult to implement than <use>, but I don’t think it gives you anything beyond what you already get with <use>.
  • Gradients Sharing Color Stops: Not very difficult to implement, and it Illustrator uses it extensively, it’s probably worth supporting.
  • <mask>: At least in CoreGraphics, implementing this requires making an offscreen drawing context and drawing into it. Each offscreen drawing context can use a significant amount of memory, either in main memory or on the GPU. These things can be nested, so the memory use could be quite significant, causing us to place artificial limits on how much we’ll mask. In addition, when making these offscreen contexts, we have to determine what the pixel density of the context should be (which might be nonuniform, if the content is under a perspective skew, for example). The masks can theoretically be flattened, but masking n-element geometry with an m-element mask would yield a n*m-element result, potentially causing the file size to explode. Also, implementing flattening would require using algorithms to perform path manipulation which are costly in performance, fuzzy in that they have magic epsilon thresholds which need to be tuned, and still the topic of ongoing academic research. On the other hand, every authoring tool I know of has some facility for masking, so the functionality is probably important. Masks are pretty common in lots of artwork around the world, but I don’t know how that translates into their use in existing SVG content.

@dirkschulze
Copy link
Contributor

@litherum None of the features are essential. Just that Illustrator (or other authoring tools) support some or all features should not be the only criteria to support them.

From implementation point of view, I think (from my experience) that <mask>, <pattern>, inner <svg>, <symbol>, <marker> are not as trivial to implement as it might seem on a first glance.

@litherum What do you think? How should we proceed on this? As you said, there are common and individual things to discuss for each feature. Are there parts where we can get to a conclusion earlier than others?

@chris-little
Copy link

chris-little commented Jul 9, 2019

As a rather inactive member, I may not understand the scope or use cases for SVG-Native. If not out of scope, how would mapping use cases be addressed, with many repetitions of symbols and text in multiple orientations? And reuse saved what was considered significant storage. One of the powerful arguments for SVG (Tiny) was that text was searchable, unlike most underlying graphics packages.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Jul 9, 2019

@chris-little
The purpose of SVG Native is to define an SVG subset specifically for environments that want lightweight vector graphics but do not want to implement text rendering within their graphics libraries, and do not need interactivity and scripting. The primary use case is for icons and logos.

So, it would not be suitable to represent a full map. But, it would be suitable to represent an individual map marker icon, which could be used as an image by map rendering software that has basic vector graphics support but does not want to implement full SVG support.

@chris-little
Copy link

@AmeliaBR Thank you for the clear answer.

@sairuspatel
Copy link

sairuspatel commented Jul 15, 2019

For reference, <pattern>, <marker> and <symbol> are not in the OT-SVG minimum subset (they’re in the “avoid these elements” list).
<use>, however, is explicitly indicated as a way to share elements across glyphs in the same SVG doc, e.g. see example 4 at https://docs.microsoft.com/en-us/typography/opentype/spec/svg#examples.

@css-meeting-bot
Copy link
Member

The SVG Working Group just discussed [svg-native] Decide whether reusable graphical elements are needed, and agreed to the following:

  • RESOLUTION: Patterns are not part of SVG Native
  • RESOLUTION: Markers are not part of SVG Native
  • RESOLUTION: Symbol and nested SVG elements are not part of SVG Native
  • RESOLUTION: Allow use element in SVG Native
  • RESOLUTION: Support href on gradients referencing gradients
The full IRC log of that discussion <myles> Topic: [svg-native] Decide whether reusable graphical elements are needed
<myles> GitHub: https://github.com//issues/689
<krit> ScribeNick: krit
<krit> sairus_: SVG OT spec does not support pattern, marker and symbol
<krit> sairus_: but not banned either
<krit> sairus_: The use element is specifically used as an example in the spec though
<krit> myles: We can probably support patterns
<krit> s/support/agree on/
<krit> myles: Apples implementation is the only implementation as far as I know that supports it and we didn't find any content that uses it. We can remove.
<krit> AmeliaBR: Depends on the use cases for SVG Native.
<krit> AmeliaBR: if the idea is that the files are individual icons or small things in general then Wouldn't expect anything of that to be in.
<krit> AmeliaBR: otherwise I would imagine that you want to reuse shapes to simulate shadows w/o rewriting the same shape.
<krit> AmeliaBR: for patterns there is even more
<krit> AmeliaBR: For patterns, every dot can add a lot of markup in comparison of using a pattern once.
<krit> AmeliaBR: making the SVG larger and less easy to work with it
<krit> myles: file size vs supported features is a trade of
<krit> myles: There is no content that does use patterns for fonts.
<krit> myles: and that makes sense since the files are so small
<krit> myles: there is a point for supporting it on the other hand: 1) there is no wide support for fonts and 2) there is a way to do visually the same w/o patterns
<krit> sairus_: There were discussions to add patterns to the OT table. IT would be a competitive advantage to support it in SVG Native.
<krit> myles: will all implementations update to do it?
<krit> sairus_: Patterns doesn't seem to be a minimal subset. Though SVG Native is not really "minimal".
<krit> AmeliaBR: Myles point is that it is easier to add features later.
<krit> myles: there is a CTPattern... an API to draw patterns in CT. The pattern space is different from the document coordinate space and it is tricky to match the 2 spaces and that part is not in the API
<myles> s/CTPattern/CGPattern/
<myles> s/CT./CG./
<krit> RESOLUTION: Patterns are not part of SVG Native
<krit> AmeliaBR: markers and symbols we were leaning to not support?
<krit> myles: A tool that generates SVG Native file would know the geometry for markers. So we can omit it. Not much markup anyway
<krit> myles: And as far as I know it does not have wide support in OT implementations
<krit> RESOLUTION: Markers are not part of SVG Native
<krit> myles: I think we have to support use. There is much content out it that uses it.
<krit> myles: Apple does not support symbol.
<krit> AmeliaBR: Symbol to me is very similar to nested SVG.
<krit> AmeliaBR: as it affects coordinate system and internal coordinate system. They should be treated the same. So I would say no symbol either. But there definitely are use cases for symbol.
<krit> myles: symbol doesn't let you do what you can't do otherwise.
<krit> AmeliaBR: It allows creating a new SVG viewport
<krit> AmeliaBR: that is why it is similar to nested SVG.
<krit> krit: I would be ok with removing.
<krit> AmeliaBR: use is still useful w/o symbol.
<krit> RESOLUTION: Symbol and nested SVG elements are not part of SVG Native
<krit> RESOLUTION: Allow use element in SVG Native
<krit> myles: gradients sharing color stops?
<krit> myles: we support it in our implementations.
<krit> AmeliaBR: used a lot in Adobes SVG export.
<krit> AmeliaBR: Ai ends up with using lot of gradients but all sharing the same color stops.
<krit> AmeliaBR: shouldn't be a large implementation addition.
<krit> krit: inheritance and currentColor might be the biggest issue but that applies to everything
<krit> myles: don't think anyone considered it
<krit> myles: IMO if SVG OT doesn't mention something it is supported since it is SVG 1.1 minus stuff
<krit> AmeliaBR: It would be useful for fonts to define stops once and use it at different glyphs
<krit> myles: does Adobe's OSS implementation support it?
<krit> krit: it does.
<AmeliaBR> s/at different/at different positions for different/
<krit> RESOLUTION: Support href on gradients referencing gradients
<krit> trackbot, end telcon

@behdad
Copy link

behdad commented Jul 15, 2019

I want to point out that "For reference, , and are not in the OT-SVG minimum subset" means nothing. OT-SVG documents what's supported by implementations and makes recommendations based on that. Using it to justify what should be supported is false logic.

@AmeliaBR
Copy link
Contributor

The goal with SVG Native is to define a minimum subset that will be widely supported. If the SVG-OT recommendations about which features are to be avoided are based on real implementation limitations, that is a valid consideration.

Applications, including font rendering applications, could still be defined to support full SVG. (Or some subset of full SVG that is a superset of SVG Native.)

@css-meeting-bot
Copy link
Member

The SVG Working Group just discussed [svg-native] Decide whether reusable graphical elements are needed.

The full IRC log of that discussion <krit> topic: [svg-native] Decide whether reusable graphical elements are needed
<krit> GitHub: https://github.com//issues/689
<krit> kris: we had this on the previous agenda but didn't cover all
<krit> myles: I think we had symbols, masks, gradients sharing stops and use.
<krit> AmeliaBR: we grouped inner SVG with symbols
<krit> AmeliaBR: mask is still up for debate
<krit> myles: I think all implementations implementing masks use an offscreen buffwer
<krit> myles: so there are limitations like pixel density before drawing on a offscreen buffer and you need a big enough buffer which might be problematic on certain devices
<krit> myles: those are the pros.
<krit> s/pros/cons/
<krit> myles: The pros are that it is very common
<krit> AmeliaBR: I can not comment in general but on Blink they are similar
<krit> AmeliaBR: both are handled with compositing
<krit> some discussion about AA on clip path and masks
<AmeliaBR> > The raw geometry of each child element exclusive of rendering properties such as fill, stroke, stroke-width within a clipPath conceptually defines a 1-bit mask (with the possible exception of anti-aliasing along the edge of the geometry)
<AmeliaBR> from https://drafts.fxtf.org/css-masking-1/#ClipPathElement
<krit> krit: Masking draws a shape on an offscreen buffer which causes AA. Then this buffer is used with compositing which adds another level of AA. This is not allowed for clipping masks where only the clipped result (drawing the clipped content on the backdrop) is allowed to be anti-aliased
<krit> AmeliaBR: not normative in the spec though. We could agree that a clipping path is a vector operation.
<krit> myles: so the difference would be very suttle. Can it be tested?
<myles_> s/suttle/subtle/
<krit> krit: it is and we can not test it since AA depends on HW and SW implementation.
<krit> myles: I don't think that, if there are differences, they would matter for masking.
<krit> myles: As far as I know, there is no implementation that can use masking w/o an offscreen buffer.
<krit> AmeliaBR: reason I mentioned it is that the discussion should also be about clipping.
<krit> myles: most implementations implement clipping and masking differently. So implementation burden might differ. I would claim they do differ.
<krit> krit: just to add to the comment from myles: there might be implementations that implement masking and clipping the same way, there are implementations that don't.
<krit> krit: Do we know implementations that do not support masking?
<krit> myles: the MS one doesn't... let me verify
<krit> krit: I meant on the rendering level... D2D does support it, right?
<krit> krit: beside the argument of the offscreen buffer, all rendering implementations probably are able to support masking.
<myles_> https://docs.microsoft.com/en-us/windows/win32/direct2d/svg-support doesn't support masking
<krit> krit: the other question would be about the implementation complexity of <mask> itself.
<krit> AmeliaBR: you mean the creation of a local coordinate system?
<krit> AmeliaBR: clipping path and patterns are similar to mask and have some kind of a local coordinate space though not all create a viewport with viewBox or similar
<krit> AmeliaBR: One option might be to support masks and clip path but only userSpaceOnUse or objectBoundingBox depending which one is easier to implement.
<krit> krit: I'd like us to get into this direction.
<krit> myles: So if we did accept masking then we would be asking MS to add masking to their implementation because they don't support it today.
<krit> myles: how would you implement masking with the streaming interface SVG Native Viewer has?
<krit> krit: Thinking about it it would be very difficult but should be possible
<krit> AmeliaBR: we all agree that clip path is necessary? So clip path will be part of SVG Native?
<krit> myles: I think this is right
<krit> AmeliaBR: so the question is about mask
<krit> myles: from an illustration point of view: how often do authors use masking?
<krit> krit: most content uses clipping path but there are cases where ppl use actual masking. For SVG Tiny export we rasterise it.
<krit> myles: we should get more feedback from implementers.
<krit> AmeliaBR: especially to discuss what is difficult about masking. myles could you open a new issue please?
<krit> myles: I'll do
<krit> myles: I think this is all for this bug

@litherum
Copy link
Contributor

Masking discussion migrated to #659

@monfera
Copy link

monfera commented Apr 14, 2020

@jarek-foksa

are

<marker>
<symbol>
<use>
<linearGradient href="...">
<radialGradient href="...">

adding any value when it comes to rendering performance, file read/write performance, security or interoperability?

Absolutely, unless I misunderstand something. They buy you these:

  • performance: much more compact representation leading to eg. one DOM element instead of ten, or hundreds, so there's less data to move and parse, and the user agent can optimize fast rendering better
  • performance, again (rendering and read/write): there are much fewer DOM elements, so CSS calculations eg. transforms are way faster, experimental results show this clearly - also, even without this, many DOM elements even when they're inert, make things slower to render or update
  • security: might not be relevant to native (I'm not super clear on it) but the lessened need for DOM work may mean, less pressure to use JavaScript or any other imperative scripting to populate the scenegraph with tons of repeating elements

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

No branches or pull requests

10 participants