- From: Amelia Bellamy-Royds <amelia.bellamy.royds@gmail.com>
- Date: Wed, 12 Nov 2014 16:21:53 -0700
- To: public-fx@w3.org
- Message-ID: <CAFDDJ7ySPsdqd_7o1RGL51ZQjsKQu5R3w3d7eBsPSP0URoVtOA@mail.gmail.com>
I see from the SVG WG agenda for this week [1] that there is a push to get the Filter Effects spec to Last Call Working Draft. (Hooray!) One of the items on that agenda is how to handle errors from <feImage> when the specified image cannot be accessed; browsers currently differ in implementations. A wider issue is what to do with filters as a whole if there is an error. For example, the use of "BackgroundImage" or "BackgroundAlpha" in SVG filters in browsers which haven't implemented them. Or the use of a named input that doesn't match any of the result names from previous filter primitives. Currently, all implementations I've seen cause the filtered graphic to disappear in these cases. I'm not sure how it is implemented behind the scenes. Maybe some implementations treat the entire filter as in error, so it results in empty rendering output; the graphic that referenced the filter is only rendered to the temporary buffer. Or, maybe implementations treat the invalid input as a zero-sized graphic input that results in zero-sized graphic output, as Max Vujovic discovers happens with invalid <feImage> references on Firefox [2]. Regardless, the effect is difficult to debug and means that authors are hesitant to use filters to enhance a graphic unless they are confident of universal support for all its components. There are very few situations where the desired fallback behaviour would be to remove the filtered graphic. Within the discussion on <feImage>, Paul LeBeau [3] quoted the general SVG error handling directive, ""The document shall be rendered up to, but not including, the first element which has an error" [4]. Paul's interpretation of how this should be applied to filters is that the filter primitive with an error, and all subsequent primitives within the filter, is ignored, but the filter as a whole is still applied. I would add that if the filter as a whole is in error, it should simply be ignored and the graphic drawn without the filter. But since that isn't what is happening in implementations, some clearer error handling rules are needed. The error handling rules that currently exist (in the current draft spec [5] or from CSS error handling) are as follows: 1) For CSS shorthand filter functions, an unsupported parameter value would be a CSS syntax error, and the accepted CSS error handling rule would be to ignore the entire property declaration. E.g., if you used .graphic { filter: blur(5px); filter: saturate(0.7) drop-shadow(5px 5px 10px 20px navy) contrast(2); /* four lengths given to drop-shadow function that takes max three lengths in current spec */ } the drop-shadow declaration would be invalid, therefore that entire property value would be invalid, and the blur filter would be applied instead. 2) A CSS property declaration that references a URL, where that URL is inaccessible or not of the correct content type, is still a valid property declaration, so more explicit rules are required. The current draft specifically says that invalid URLs should be treated as `filter:none` (i.e., the entire filter declaration is ignored and no filter applied). E.g., if you used .graphic { filter: blur(5px); filter: saturate(0.7) url(#foo) contrast(2); /* where #foo either doesn't exist or isn't a filter */ } then the graphic wouldn't have a filter applied. In particular, it would not fall back to the blur. This is a run-time error, not a compile-time error, so the CSS cascade has already washed away the previous property declaration. When this issue was previously discussed on the list [6], the options that came up were - Don't apply any filter if a URL reference is invalid (current draft spec rule). - Treat an invalid URL reference as a "pass-through", essentially removing it from the list of filter components (so the above CSS would be the same as `filter: saturate(0.7) contrast(2);`). - Treat an invalid URL reference as a block, but apply filters earlier in the list (so the above CSS would be the same as `filter: saturate(0.7);`). I can see arguments for all of the above options. However, there are also arguments in favour of consistency between CSS filter functions and SVG composite filters, so you might want to keep that in mind while considering options for SVG filter error handling. That said, the situations are somewhat different: errors from inaccessible URLs are often outside an author's control, so you want a pretty fallback for the end user; in contrast, errors within SVG markup can be fixed during debugging and browser testing by the author, so error handling should support that. For SVG filters, I would propose the following error handling rules in the interest of reasonable fallbacks and easy debugging: - If a filter element is in error, treat all references to the filter as invalid URLs (and follow the error handling rule above, so that no filter is applied). - If a filter primitive (or primitive component) is in error, ignore that primitive and all subsequent primitives, so that the output of the filter as a whole is the result of the last non-error primitive. - If a valid filter element has no children, or if all its children are ignored because of errors, then return the source graphic that would be the default input to that filter, clipped to the filter effects region if appropriate. In other words, treat it as if it contained a single, no-effect filter primitive with default input, such as <feMerge><feMergeNode/></feMerge>. (Note: This last rule might cause backwards compatibility issues. The alternative would be to continue to treat empty but error-free filter elements as a "delete" filter.) On the specific question of invalid source images for <feImage>, or invalid values for `in` or `in2` attributes, there are a couple approaches that could be reasonable: - Treat the filter primitive with invalid input as being in error, and apply the rules above. - Create a transparent black flood the same size as the primitive region, and use that to replace the invalid input or image. - Use the transparent black input for <feImage> (or even the browser broken-image icon, if you want to give feedback about what went wrong), but revert to default values for `in` and `in2`. (P.S. The default value for `in2` really should be explicitly stated somewhere in the spec; I think most implementations use the same defaults as for `in`, but I haven't tested carefully.) This last behaviour seems to be what is currently recommended in the draft spec for at least one specific type of invalid `in` or `in2` attributes: If the value for result appears multiple times within a given filter > element, then a reference to that result will use the closest preceding > filter primitive with the given value for attribute result. Forward > references to results are not allowed, and will be treated as if no result > was specified. That's not super-clear, but treating a forward reference "as if no result was specified" for the input of a primitive, would mean to use the default input (i.e., the output from the previous primitive or the SourceGraphic). This is in contrast to the SVG1.1 spec, which says "forward references are in error" [7] and therefore currently causes the filter-in-error-graphic-disappears effect. I don't have strong opinions on which of the three approaches to invalid inputs should be used, although I would lean towards the transparent black flood or the revert to default options. I think that covers all the possibilities for error handling. I would be interested to hear from those of you involved in implementing these features whether any of the options above are preferred (or difficult) for practical reasons. Best, Amelia BR [1]: http://lists.w3.org/Archives/Public/www-svg/2014Nov/0027.html [2]: http://lists.w3.org/Archives/Public/public-fx/2014OctDec/0040.html [3]: http://lists.w3.org/Archives/Public/public-fx/2014OctDec/0038.html [4]: http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing [5]: http://dev.w3.org/fxtf/filters/ [6]: http://lists.w3.org/Archives/Public/public-fx/2013JulSep/0000.html [7]: http://www.w3.org/TR/SVG11/filters.html#FilterPrimitiveInAttribute
Received on Wednesday, 12 November 2014 23:22:21 UTC