Proposals/Stroke dash adjustment

From SVG

This is a proposal for two properties to control the positioning of stroke dashes so that they are more visually pleasing.

Name:stroke-dashadjust
Value:none | [stretch | compress] [dashes | gaps]?
Initial:none

The stroke-dashadjust property controls the kind of adjustment to stroke dashes and gaps that is to be performed when stroking a shape.

/* The initial value, no adjustment of stroke dashes is performed. */
stroke-dashadjust: none;


/* Scales up all dash array values so that length of the stroke is an integer multiple of
   the sum of the dash array. */
stroke-dashadjust: stretch;

/* Scales up the dash lengths in the dash array so that the length of the stroke is an
   integer multiple of the sum of the dash array. */
stroke-dashadjust: stretch dashes;

/* Scales up the gap lengths in the dash array so that the length of the stroke is an
   integer multiple of the sum of the dash array. */
stroke-dashadjust: stretch gaps;


/* Scales down all dash array values so that length of the stroke is an integer multiple of
   the sum of the dash array. */
stroke-dashadjust: compress;

/* Scales down the dash lengths in the dash array so that the length of the stroke is an
   integer multiple of the sum of the dash array. */
stroke-dashadjust: compress dashes;

/* Scales down the gap lengths in the dash array so that the length of the stroke is an
   integer multiple of the sum of the dash array. */
stroke-dashadjust: compress gaps;
Name:stroke-dashcorner
Value:none | <length>
Initial:none

The stroke-dashcorner property is used to control whether a dash is painted at every vertex of a path and, if so, how big that dash is. When stroke-dashcorner is not "none" and stroke-dashadjust is not "none", then adjustment of stroke dashes and gaps is done per path segment rather than across the entire path.

/* The initial value, no specific dashes are painted at the vertices of a path. */
stroke-dashcorner: none;

/* Paints a 5px long dash at every vertex of the path.  For a closed shape, there is no
   stroke painted at the final point. */
stroke-dashcorner: 5px;

/* Does not draw a dash at every vertex of the path, but causes stroke adjustment to
   be done per path segment if stroke-dashcorner is not "none". */
stroke-dashcorner: 0;

Examples

TBD

Issues

  • I would have preferred to call the properties "stroke-dash-adjust" and "stroke-dash-corner" instead, but I've left out the second hyphen (dash?) for consistency with the existing stroke dash properties.
  • The definitions for "stretch" above assume that the sum of the dash array elements is shorter than the length of the stroke. What do we do when it is longer? Perform no adjustment? Should we give author control to this situation too?
  • Does the compression or expansion of the dashes and gaps happen after an odd-lengthed dash array is doubled so that it has an even number of entries or before? Probably after.
  • Do we want to allow control of whether the stroke ends with a dash or with a gap? For a closed path, you probably want a gap at the end, while for a non-closed path, a dash at the end is probably better. Omit control for this, but just do it automatically based on whether the path is closed?
  • Need to define what happens when corner dashes would overlap.
  • To support a common use case of drawing a rectangle with dashes of say 5px at the corners and 5px dashes spaced nicely on the edges, you would need to use style="stroke-dasharray: 5px; stroke-dashadjust: compress gaps; stroke-dashoffset: -2.5px". Is that too cumbersome?
  • Is supporting stretching or compressing either gaps or dashes too much control? Should we simplify by just choosing one of these and using "stroke-dashadjust: adjust" instead?
  • What happens if there are multiple sub-paths? Does that start a new dashing there, or does dashing continue from the new sub-path startpoint with the remainder of the current dash or gap?