- From: Anthony Grasso <anthony.grasso@cisra.canon.com.au>
- Date: Wed, 04 Mar 2009 10:22:01 +1100
- To: Chris Lilley <chris@w3.org>
- CC: W3C SVG Public Working Group <public-svg-wg@w3.org>
Hi Chris, Really good work on getting a draft of the Vector effects module done up! The examples look great! I've looked over the draft in some detail and have a few comments and questions. Sorry for such a long email, but I've tried to make suggestions where possible to make things a bit easier. Rendering a vectorEffect element -------------------------------- The vector effect section states: [[ Alternatively, vector effects can be used as a drawing element; in such case its input is considered to be empty (and the vePath element must be used to get input data). ]] Unlike all other declaration elements (filters, patterns, clipPaths, gradients etc), this sentence seems to be stating that a vectorEffect element can be used to produce rendered output directly; that is it can be used as a graphics element. This is unusual for an SVG element and this is the only reference to its use as a drawing element. I'm assuming in this case there would be no referencing element, so the input path could be invalid or empty, but empty has been specified. It may be worth adding wording to say an input object must be referenced when vectorEffects element is in the defs and say what the case is when it's a drawing element. There should also be special handling for attributes that require there to be a referencing element. Is it safe to assume that: 1. The currentFill, currentStroke, currentFillOpacity and currentStrokeOpacity properties will use the current fill, stroke, fill-opacity and stroke-opacity as resolved for the vectorEffect element when there is no referencing element? 2. The objectBoundingBox value for vectorEffectUnits will be ignored, and userSpaceOnUse will be used instead when there is no referencing element (or the bounds could be taken of the empty input path, but that would result in zero width/height coordinate space). Can the vectorEffects element be a valid target for the 'use' element? Though given the assumptions above it probably should be, but can it be when it's being used in the defs element? Coordinate system and vectorEffectsUnits ---------------------------------------- The vectorEffect element allows for userSpaceOnUse and objectBoundingBox as the coordinate systems and I think it needs to describe how these behave in a bit more detail. All other SVG references explicitly describe the behaviour. Assuming behaviour is similar to other elements, the spec could be worded to say: [[ userSpaceOnUse: Use the current user coordinate system. If the vectorEffect element is rendered directly, this is the user space in existence at the time the vectorEffect element is encountered. If the vectorEffect is referenced via a vector-effect attribute, this is the user space in existence on the referencing element. Similarly, percentages are resolved against the current viewport. objectBoundingBox: Establish a new coordinate system based on the bounds of the referencing object. If the vectorEffect element is rendered directly there is no referencing object; assume this case is invalid and use userSpaceOnUse instead (i.e. ignore the vectorEffectUnits when rendering directly, and always use userSpaceOnUse). ]] There are no units specified for the children of the vectorEffect, which is similar to the clipPath element (unlike filters, masks, and patterns etc which have units for the children) or should there be? I guess this is ok as it is. objectBoundingBox units and vePathRef ------------------------------------- The vector effect module states that the 'SourcePath' is transformed to be in the correct coordinate space based on the vectorEffectUnits. The vePathRef allows access to other path definitions to be used by the vectorEffect, but the specification does not mention the coordinate space to apply to these paths. I assume that no additional transforms are applied to the paths referenced by vePathRef, and they are interpreted in the user space established by the vectorEffectUnits (after any additional transformations applied by a transform attribute on the referenced path itself)? Common vector effect primitive attributes ----------------------------------------- The section I didn't quite understand because it contradicts almost every schema definition in the vector effects module when it states that the following attributes are common to all of the vector effect primitives: 'in', 'in2', 'result', 'transform' and 'transformPath'. For example, the 'in2' property doesn't apply to all vector effect primitives or does it? I guess later on the spec will need to define which attributes apply to which primitives. The empty vectorEffect ---------------------- An empty vectorEffect is defined as: <vectorEffect/> The spec states that no rendering is performed, but does not indicate if the final path is available. I guess it would be useful if an empty vector effect returns an initial input path 'in' as the final output path so it is available for textPath, clipPath, vePathRef and text flow, but the path itself is not be rendered. The default vectorEffect ------------------------ The default vector effect is declared as: <vectorEffect> <veFill/> <veStroke/> <veMarker/> </vectorEffect> According to the specification this will produce the default SVG rendering behaviour. I think this has several problems: 1. The veStroke uses fill and fill-opacity to do the stroking, but the spec doesn't actually say that fill and stroke are initialised to the source stroke and stroke-opacity. 2. There is no mention of how other stroke properties such as dash-array etc are set. 3. The veMarker doesn't have any mention of where or how the marker properties are set. Suggestions for each point: 1. The fill and fill-opacity properties have different behaviour on veStroke and are initialised to currentStroke and currentStrokeOpacity if no other values have been set. 2. The other veStroke stroking properties inherit from the referencing object if no other values have been set. Another solution would be to have currentDashArray etc. 3. The veMarker inherits marker properties from the referencing object if no other properties have been set. Another solution would be that currentMarkerStart, currentMarkerMid and currentMarkerEnd could be created to be in keeping with the stroke and fill properties. Inheritance ----------- The vector effects module doesn't state how inheritance is handled. There is a brief mention on the veStroke element that stroking is done "taking into account the stroke properties on the source element". If it is assumed that properties inherit via the referencing element this will allow most of the "default" vector effect properties to work (though it does allow the vectorEffect element to potentially override values). As a suggestion could we say that the properties inherit from the element referencing the vectorEffect element; or if being rendered directly so there is no referencing element, properties inherit from the ancestors of the vectorEffect element. It should also be noted that this is different to other similar elements such as filters, clips etc where inheritance would normally be stated as: Properties inherit into the vectorEffect element from its ancestors; properties do not inherit from the element referencing the vectorEffect element. This is not done for vector effects. Stroking and path outline construction -------------------------------------- At some point the vector effects module will need to describe how to implement stroking or how to construct the path segment outline of logical path operations. Currently this is an issue for some primitives that are dependent on the path segment construction of the final paths. For instance: 1. The path may or may not be flattened. If flattened, different error tolerances may have been used, resulting in a different number and position of path segments. If not flattened, different path segments may have been used when replacing intersections in path outlines or when stroking. Also Bezier envelope calculations may have been approximated with simpler curves. This affects any veSetback operations applied to the shape as they break the path into segments. 2. The direction of the path outline might be clockwise or anti-clockwise. This affects any textPath operations (direction and normal vector calculations), any dashing operations (direction), and any marker operations (normal vector calculations). 3. The stroked path may or may not be an outline. The stroke may consist only of the points in the outline, or it may consist of rectangles and other overlapping shapes for the joins and end caps to be painted with a non-zero winding rule. In other cases the stroke may almost be an outline, but it has not handled self-intersecting lines, so later parts of the line overlap earlier parts of the line (again relying on the fill rule to correctly handle filling the path). Given that path handling and construction may be dependant on capabilities of underlying rendering libraries should the sepcification state that the user should be warned about inconsistent results between user agents, or the methods should be properly specified? Sorry I don't have any quick fixes for the above issues :( Path outline of unclosed paths ------------------------------ At some point the specification will need to describe how to produce the outline of a line (an unclosed path) in the result of a logically combined path. The two most likely options I can think of are: a. The line remains a simple line. Not sure how of if this will work. b. The line is changed to a closed path; that is, the line will trace back over itself to form a complete path with zero width. This fits better with the description of an 'outline', which implies a closed path solution. This will affect various functions such as markers, textPath, stroking, dashing and veSetback as it will determine whether the routines will retrace the line backward using normals in the opposite direction. vePathRef --------- The vePathRef element is used to reference paths to be combined by vePath. I think the specification should describe how various properties on the referenced path are treated. Below are some suggestions about various properties. clip-path: If the referenced path has a clip-path, that this is applied to the path before it is returned to vePathRef. The clip-path will be interpreted in the user space established by the vectorEffect element. transform: If the referenced path has a transform, that this is applied to the path before returning the path to vePathRef. vector-effect: The vector-effect property is applied before any other compositing operators (clip, masking, etc), so assume that if the referenced paths has a vector-effect property that this is applied before returning the path to vePathRef. I assume that if the vector-effect on the path contains any veStroke, veFill or veMarker primitives that these are not evaluated again as only the resultant path is required? marker: Any marker-start/mid/end are not applied, so the paths from the markers are not included. I guess doing the opposite is also possible but probably more complicated. Not sure which is more useful though. vePathRef and text ------------------ If the vePathRef is used to reference text, this has the same issues as the clipPath element, namely that SVG glyphs can contain arbitrary SVG markup, but vePathRef can only deal with paths. Some suggestions to handle this case: 1. If the referenced text has text-decoration applied, the paths of the underline/overline/strike-through are not included. 2. If the glyphs are for bitmap text, the glyphs are ignored. 3. If the glyphs are SVG glyphs with complex children then any elements involving bitmap data are ignored: So, there will be no masking, filters, images or compositing applied. Note: Another possible solution would be for any or all of the above to simply result in an error if they were encountered. veSetback offset values ----------------------- The veSetback element I think will need to describe a number of situations with offset values. The veSetback element allows two types of offsets values to set: 1. Sub-path start/end offsets: These are applied to the start/end of each sub-path. 2. Internal start/end offsets: These are applied to segments internal to each sub-path. The operation of veSetback is described as: Breaks the path into individual segments and shortens both ends of every segment by the distance specified by setback-offset I assume when applying offset values: 1. Any offset value can extend until they reach an operation applied by another offset value. So, if no internal offsets have been specified, the sub-path start/end offsets may extend over more than a single segment. Another reasonable behaviour could be that all start/end offsets are limited to the smallest segment, though this seems an unnecessary limitation for the sub-path start/end offsets. 2. If reducing the segment length by the start/end offsets results in a segment having a negative length, then the length will be clamped to zero (making it the equivalent to replacing the segment with a moveto command). This point could be calculated based on: point_offset = segment_length * start_offset / (start_offset + end_offset) to give a weighted position to the point (as choosing the start/end/mid point seems a bit too arbitrary). Other reasonable behaviours for the negative length could be: generate an error; draw the segment backwards (change of path direction); or completely remove the segment. I don't really have an opinion about either solution. 3. Negative offset values are invalid and will result in an error (so offsets can't extend the path). 4. Zero offset values are effectively ignored. This means that specifying a zero offset for the internal offsets would not cause separate sub-paths to be formed. Another reasonable behaviour would be that a zero offset caused the internal segments to be broken into separate sub-paths, via replacing the initial lineto of each segment with a moveto command). clipout and fill operations --------------------------- The "individual fill operations" mentioned in the clipout property will need to be explained futher at some point. Do you think "individual fill operation" should refer to veStroke, veFill and veMarker in their entirety, and not refer to the individual fill operations that make up each of these elements? When clipout is set to 'clip', the veFill is executed, then the entire path for the veFill is selected as a clip before the next operation, and so on. vector-effect applicability --------------------------- The vector-effect property states that it can be applied to graphic objects, but elsewhere this is limited to paths and basic shapes. Is it reasonable to say that the vector-effect property applies only to paths and basic shapes; so it cannot be applied to graphics objects such as text, or used to modify the outlines of images or video, or applied to another vectorEffect element etc? Vector effects and basic shapes ------------------------------- All path based vector effects (veJoin, veSetback, veReverse) are described in terms of path operations on moveto, and lineto commands etc. Basic shapes of course are described using their control points, not SVG path commands. Do you think the specification should clarify if shapes become some reasonable path approximation as though they were path commands? Or do they remain as shapes - if so, how should this work? If shapes are broken up into path commends the direction of the paths around the basic shapes could be clockwise in the current user space. Any thoughts? in, in2 and result ------------------ Each vector effect primitive can specify a result name to store its resultant path in, and each primitive can also specify one or more names to use as input. The specification states that the name 'SourcePath' when used by 'in' or 'in2' will refer to the input path, and any other string refers to a primitive node. I have some suggestions for these inputs: 1. If 'SourcePath' is specified as the result string for a primitive, this mapping will be ignored. Other alternatives that are an error could be generated, or possibly that SourcePath could be replaced (any thoughts) 2. If in or in2 refer to primitives that do not exist then the vectorEffect will be in error. 3. If in or in2 refer to their own output or a primitive that occurs later then the vectorEffect will be in error(i.e. no forward referencing or recursive referencing). 4. A vectorEffect in error will be handled as other errors; halt and catch fire... :P I guess this is up to the host language? Path length ----------- Operations such as veSetback and dashing in veStrokePath or veStroke can specify lengths to use as distances along the current path. The interpretation of these lengths is dependent on the user agent's calculation of the path length; as a result I think there is potential to have inconsistent results. Do you think that these elements should be able to specify a pathLength which can be used to adjust the user agent's calculation of the path length (same as the pathLength property on the path element)? Anti-aliasing and clipout -------------------------- If clipout is set to ‘clip', the description of the algorithm states: [[ The value "clip" means that painting operations should be processed last to first and after every painting operation a clipping should be applied that excludes (clips out) the path just painted from the paintable region. ]] Should this take into account any anti-aliasing that is commonly done along the edges of the rendered path segments? I guess this is fine for render engines with no anti-aliasing, but I suspect will produce edge artefacts in render engines that do support anti-aliasing. General vector effect spec enhancements --------------------------------------- - The description for the clipout property will need more wording, as it tends to imply that the overall effect of ‘clip' is that regions just painted won't be painted over. Do you think this should be reworded to indicate that the effect of the last operation is that - regions won't be painted over when rendering in reverse, but the overall effect is that each painted region is completely replaced by later paint operations when rendering forward (i.e. it's describing a knock-out group operation). Note, this is also me assuming that I've read the specification correctly. - The vectorEffect mentions that it can be used as a drawing element. Given that it is completely different behaviour to all similar containers such as clipPath, filter, it may be worth stating what effect display/visibility has on any of the vector effect elements (with regards to returning a path and execution of veFill etc). - The vector effect description refers to ‘primitive shapes', but I don't think there is such things in SVG. Would it be possible to replace this with ‘basic shapes', which is a defined list of shapes and consistent with other SVG specs? - Some of the examples use 'color' for setting the colour - should it be 'fill-color'? - The vector-effect attribute has the value 'non-scaling-stroke'. This is being really picky but most other SVG defined values (e.g. for vectorEffectUnits attribute) are defined in camelCase. Should 'non-scaling-stroke' be changed to 'nonScalingStroke'? Although I guess this can't be changed given that SVG Tiny 1.2 defines the value 'non-scaling-stroke'. Perhaps this module could use "-" property names like CSS instead of camelCase? I don't really have an opinion either way. Hope you found the comments useful. If you need any clarifications or want a hand with spec changes please let me know. Regards, Anthony
Received on Tuesday, 3 March 2009 23:22:52 UTC