[strokes] CSS fill/stroke spec + questions

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[strokes] CSS fill/stroke spec + questions

Tab Atkins Jr.
Per an FXTF meeting some time ago
<https://lists.w3.org/Archives/Public/www-style/2013Jun/0678.html>,
fantasai and I have been drafting fill/stroke as applied to text in
CSS, and with the extensions needed to handle multiline text,
hierarchical elements, and multi-layer (background-like) paints.

Currently this lives in the Text Decoration 4 ED
<https://drafts.csswg.org/css-text-decor-4/>.  Is this appropriate, or
should it live somewhere else less directly text-centric?

We're also unsure exactly how much of fill/stroke to define in this
spec.  Should we take over the entire model, copying text from SVG, or
should we only define the syntax, and the rendering parts that are
relevant to CSS, letting SVG define the rendering parts important to
it?

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [strokes] CSS fill/stroke spec + questions

Brad Kemper





Brad Kemper
> On Jan 25, 2016, at 3:32 PM, Tab Atkins Jr. <[hidden email]> wrote:
>
> Per an FXTF meeting some time ago
> <https://lists.w3.org/Archives/Public/www-style/2013Jun/0678.html>,
> fantasai and I have been drafting fill/stroke as applied to text in
> CSS, and with the extensions needed to handle multiline text,
> hierarchical elements, and multi-layer (background-like) paints.

Thanks for the work you put into this. My initial reaction is that it isn't ambitious enough. See below.

> Currently this lives in the Text Decoration 4 ED
> <https://drafts.csswg.org/css-text-decor-4/>.  Is this appropriate, or
> should it live somewhere else less directly text-centric?

I'd like to see the dashed strokes capabilities applicable to regular borders. I've had this in my head a long time, and I think a 'dash()' function as a value of 'border-style' would be better all around than having a 'stroke-dasharray' property (btw, this hyphenation is too weird, and I don't care how they have it in SVG). Then 'dashed' and 'dotted' could just be shorthands. For instance: 'border-style: dash(0 1 round)' would mean "a zero-length dash with round endcaps, and one border-width length of space between endcaps", which could be a nice definition for what 'border-style: dotted' is.

I feel this is more important than having the same thing for text, but I'd use the same values for a new 'text-border-style' property, and also have the other main border properties (not including border-image) replicated with a 'text-' prefix. That would make it simpler to use and easier to learn and understand.

> We're also unsure exactly how much of fill/stroke to define in this
> spec.  Should we take over the entire model, copying text from SVG, or
> should we only define the syntax, and the rendering parts that are
> relevant to CSS, letting SVG define the rendering parts important to
> it?

Please design for people familiar with CSS and HTML, then back-port to SVG. That's why I'd prefer integration into existing or new border and background properties, and prefixing those with 'text-' when something similar should apply to glyph shapes (kind of like box-shadow/text-shadow, but without needing the 'box-' prefix).

Some other thoughts on the draft:

Issue 9, percentages: I would like percentages to mean percentages of the side it is on, for rectangles, and percentage of the whole stroke for other shapes. So, 'border-style: dash(25% 50%)' would have a dash that started in the top left corner and continued for 1/4 the width, have a centered gap that was half the width, and then (because the pattern repeats), another quarter-width dash from there to the top right corner.

This would be a nice way of having borders that were only on the corners, or centered borders that didn't go all the way to the corners. The author could set it up so that the dashes and gaps were always symmetrical, using the same general syntax as for other custom dashed lines.

Issue 10, commas. It would be much easier to read if dash/gap pair was separated by commas (a comma after each gap, unless it was the last item of the array). Thus, 'dash(6px 6px, 4 4, 4 1fr, 4 4, 4 6px, 6px)', which makes it clear that it starts and stops on a dash,  instead of 'dash(6px 6px 4 4 4 1fr 4 4 4 6px 6px)'.

PS. The '1fr' there is supposed to be a flexible measure, once the other dashed and dots are fit to one side of the rectangle. Maybe a level 2 feature?

Also, this comma syntax would allow you to start out with a gap, by just having a single measurement before the first comma ('border-style: dash(8px, 5px 8px);'). Then you don't need stroke-dashoffset as much. For when you do need stroke-dashoffset, I'd have it as the first measurement of the function, followed by a slash. So, 'border-style: dash(1in / 5px 8px)' would be repeating 5px dashes with 8px between them, starting 1in from the corner.

Stroke-align: I'd have a 'border-align' property to describe where the border goes. The initial value would need to be 'outset', to describe where borders are currently drawn, at least for how it would apply to 'border'. It could be different for 'text-border', I guess.

This also seems to be missing something that would allow the stroke/border to be outset from the shape by a specified distance. I thought SVG had that.
Reply | Threaded
Open this post in threaded view
|

Re: [strokes] CSS fill/stroke spec + questions

Tavmjong Bah-2
In reply to this post by Tab Atkins Jr.
On Mon, 2016-01-25 at 15:32 -0800, Tab Atkins Jr. wrote:
> Per an FXTF meeting some time ago
> <https://lists.w3.org/Archives/Public/www-style/2013Jun/0678.html>,
> fantasai and I have been drafting fill/stroke as applied to text in
> CSS, and with the extensions needed to handle multiline text,
> hierarchical elements, and multi-layer (background-like) paints.


I've added CSS Strokes as a topic for the joint CSS/SVG meeting. Here
are some quick comments:


stroke-align:

  This property, although highly desired and simple in principle, turns
out to be quite difficult to define and implement. It has been moved
out of the SVG 2 specification into a "strokes" module (along with
'stroke-dashcorner' and 'stroke-dashadjust'). For some of the problems,
see:

  https://svgwg.org/specs/strokes/#SpecifyingStrokeAlignment
  http://tavmjong.free.fr/blog/?p=1257

  It would also be nice to be able to give a numerical value to
partially offset a stroke.

  You might consider adding the 'paint-order' property as this solves
the common problem of distorted looking glyphs when stroke is above
fill.


stroke-linejoin:

  There are two additional values added in SVG 2:

    'miter-clip' (with a much nicer fallback behavior than 'miter').
    'arcs' (much more appealing join for curved paths).


stroke-miterlimit:

  With the 'miter-clip' and 'arcs' line joins, a '<number>' value makes
more sense than an '<angle>' value. Computed value should be a number.


stroke-dasharray:

  Yes, percentages are stupid when referenced to the diagonal of the
containing block. Values in SVG can be lengths, percentages, or
numbers. Numbers are in user-units. Relative to stroke-width may seem
at first be an obvious choice but if stacking stroked path above each
other (with different widths to build complicated paths) then having it
in user-units makes sense.

  Interesting, the SVG spec does say "The ‘pathLength’ attribute on a
‘path’ element affects ‘stroke-dasharray’: each dash and gap length is
interpreted relative to the author's path length as specified by
‘pathLength’." What this actually means, I don't know... but it would
be quite handy to have percentages defined relative to path length (but
probably not very useful for stroking text).


stroke-dashoffset:

  Same comments as for 'stroke-dasharray'.


Tav



> Currently this lives in the Text Decoration 4 ED
> <https://drafts.csswg.org/css-text-decor-4/>.  Is this appropriate,
> or
> should it live somewhere else less directly text-centric?
>
> We're also unsure exactly how much of fill/stroke to define in this
> spec.  Should we take over the entire model, copying text from SVG,
> or
> should we only define the syntax, and the rendering parts that are
> relevant to CSS, letting SVG define the rendering parts important to
> it?
>
> ~TJ
>

Reply | Threaded
Open this post in threaded view
|

Re: [strokes] CSS fill/stroke spec + questions

Tab Atkins Jr.
On Fri, Jan 29, 2016 at 6:07 AM, Tavmjong Bah <[hidden email]> wrote:

> On Mon, 2016-01-25 at 15:32 -0800, Tab Atkins Jr. wrote:
>> Per an FXTF meeting some time ago
>> <https://lists.w3.org/Archives/Public/www-style/2013Jun/0678.html>,
>> fantasai and I have been drafting fill/stroke as applied to text in
>> CSS, and with the extensions needed to handle multiline text,
>> hierarchical elements, and multi-layer (background-like) paints.
>
>
> I've added CSS Strokes as a topic for the joint CSS/SVG meeting. Here
> are some quick comments:
>
>
> stroke-align:
>
>   This property, although highly desired and simple in principle, turns
> out to be quite difficult to define and implement. It has been moved
> out of the SVG 2 specification into a "strokes" module (along with
> 'stroke-dashcorner' and 'stroke-dashadjust'). For some of the problems,
> see:
>
>   https://svgwg.org/specs/strokes/#SpecifyingStrokeAlignment
>   http://tavmjong.free.fr/blog/?p=1257

Thanks for that!

>   It would also be nice to be able to give a numerical value to
> partially offset a stroke.

Yeah, we saw that in one of the proposals.  We weren't sure what the
value range should be - 100% to -100%, default 0?  Or 0% to 100%,
default 50%?

>   You might consider adding the 'paint-order' property as this solves
> the common problem of distorted looking glyphs when stroke is above
> fill.

And the fill is opaque (which is common, of course).  I'm fine with this.

> stroke-linejoin:
>
>   There are two additional values added in SVG 2:
>
>     'miter-clip' (with a much nicer fallback behavior than 'miter').
>     'arcs' (much more appealing join for curved paths).

We're aware of that, but only integrated it into the Perfect-World
Syntax section. Check it out, we think it's a bit better.

stroke-corner-shape: bevel | round | [ arc | miter ] [ bevel | round ]?

That is, arc and miter can have a "limit shape" specified.  If
omitted, it's the "clip" that it currently does.  Otherwise, it's
bevel or round.

So, "bevel", "round", or "miter" would have the current behavior
SVG1.1 behavior.  "miter bevel" would give the better behavior of
"miter-clip".  We can make "arc" either default to the better
behavior, or be consistent and default to the uglier clipping
behavior, and require "arc bevel" for the attractive one.

We added "round" as a limit shape because it just seems to make sense?
 Same behavior as bevel.

> stroke-miterlimit:
>
>   With the 'miter-clip' and 'arcs' line joins, a '<number>' value makes
> more sense than an '<angle>' value. Computed value should be a number.

Yeah, this was our conclusion too after some discussion.  The problem
is that the SVG spec goes straight into "hey here's a trig formula",
rather than opening with an informative example of what the value
means and tucking the formula into an out-of-the-way note at the end.
I literally didn't understand what the number actually meant until we
wrote our spec and dug into it. ^_^

>
> stroke-dasharray:
>
>   Yes, percentages are stupid when referenced to the diagonal of the
> containing block. Values in SVG can be lengths, percentages, or
> numbers. Numbers are in user-units.

I'm annoyed at SVG's legacy insistence on only having two "units"
(numbers and %s), and having globalish flags to determine how to
interpret those units in a given instance. >_<

In CSS we can just have lots of units.  Is there a way out here?  If
we absolutely can't, shrug, that's life.

> Relative to stroke-width may seem
> at first be an obvious choice but if stacking stroked path above each
> other (with different widths to build complicated paths) then having it
> in user-units makes sense.

I mean, you just wouldn't use %s there.  What's the issue?

>   Interesting, the SVG spec does say "The ‘pathLength’ attribute on a
> ‘path’ element affects ‘stroke-dasharray’: each dash and gap length is
> interpreted relative to the author's path length as specified by
> ‘pathLength’." What this actually means, I don't know... but it would
> be quite handy to have percentages defined relative to path length (but
> probably not very useful for stroking text).
>
> stroke-dashoffset:
>
>   Same comments as for 'stroke-dasharray'.

...oh jeez, I see the issue.  The spec is wrong/contradictory!  For
both dasharray and dashoffset, it claims that % is relative to the
scaled diagonal, but it's *actually* relative to the pathLength, which
is obviously completely different!  That's why the "self-drawing SVG"
thing works - you create a 100% dash and a 100% gap, then animate
dashoffset from -100% to 0%.

Having the % be relative to the path length is more reasonable.  I'll
fix our spec.  I'll let you fix SVG. ^_^

~TJ

Reply | Threaded
Open this post in threaded view
|

Re: [strokes] CSS fill/stroke spec + questions

Nikos Andronikos
<snip>

> On 10 Feb 2016, at 11:37 AM, Tab Atkins Jr. <[hidden email]> wrote:
>
> On Fri, Jan 29, 2016 at 6:07 AM, Tavmjong Bah <[hidden email]> wrote:
>>
>>  Interesting, the SVG spec does say "The ‘pathLength’ attribute on a
>> ‘path’ element affects ‘stroke-dasharray’: each dash and gap length is
>> interpreted relative to the author's path length as specified by
>> ‘pathLength’." What this actually means, I don't know... but it would
>> be quite handy to have percentages defined relative to path length (but
>> probably not very useful for stroking text).
>>
>> stroke-dashoffset:
>>
>>  Same comments as for 'stroke-dasharray'.
>
> ...oh jeez, I see the issue.  The spec is wrong/contradictory!  For
> both dasharray and dashoffset, it claims that % is relative to the
> scaled diagonal, but it's *actually* relative to the pathLength, which
> is obviously completely different!  That's why the "self-drawing SVG"
> thing works - you create a 100% dash and a 100% gap, then animate
> dashoffset from -100% to 0%.
>
> Having the % be relative to the path length is more reasonable.  I'll
> fix our spec.  I'll let you fix SVG. ^_^
>
> ~TJ

SVG 2 fixes this already I believe.

"Specifies a dashing pattern to use. A <dasharray> is a list of comma and/or white space separated lengths or percentages. Each value specifies a length along the path for which the stroke is to be painted (a dash) and not painted (a gap).

https://svgwg.org/svg2-draft/painting.html#StrokeDashing

Nikos.



The information contained in this email message and any attachments may be confidential and may also be the subject to legal professional privilege. If you are not the intended recipient, any use, interference with, disclosure or copying of this material is unauthorised and prohibited. If you have received this email in error, please immediately advise the sender by return email and delete the information from your system.
Reply | Threaded
Open this post in threaded view
|

Re: [strokes] CSS fill/stroke spec + questions

fantasai
On 02/11/2016 04:35 PM, Nikos Andronikos wrote:
>
> SVG 2 fixes this already I believe.
>
> "Specifies a dashing pattern to use. A <dasharray> is a list of comma
> and/or white space separated lengths or percentages. Each value
> specifies a length along the path for which the stroke is to be painted
> (a dash) and not painted (a gap).

Yes, the measurements are along the path.

However, that still doesn't specify what percentages are relative to.

~fantasai

Reply | Threaded
Open this post in threaded view
|

Re: [strokes] CSS fill/stroke spec + questions

Dr. Olaf Hoffmann
In reply to this post by Tab Atkins Jr.

...
>Yes, the measurements are along the path.
>However, that still doesn't specify what percentages are relative to.

>~fantasai

Percentage is relative to the viewport and not related to the length of the
path, therefore typically not very useful.

The intended purpose for pathLength is to give authors a chance to provide
their result for pathLength calculation to ensure predictable visual results
for presentation.
For example if they have a result of '10000' and provide a dash-pattern of
10,10.
Now a user-agent has a result of '11000' for the pathLength.
Instead of using the noted '10,10' this user agent uses the adjusted pattern
'11,11' to get the visual effect intended by the author.
If another user-agent gets the result '9000' it adjusts the pattern to '9,9'.

The only simple chance to get some notation of the pattern relative to the
pathLength is to 'abuse' this correction mechanism by setting pathLength
intentionally on a simple, but wrong value like '100'.

Could be pretty helpful for authors to be able to provide a specific unit for
this like 'plf' for 'pathLength fraction'.


Olaf


Reply | Threaded
Open this post in threaded view
|

Re: [strokes] CSS fill/stroke spec + questions

Amelia Bellamy-Royds
In reply to this post by Tab Atkins Jr.
To go back to Tab's original question: where should this content be spec'd?

For SVG, these aren't "text-decoration" properties.  These are some of the most fundamental style properties for all of SVG. Furthermore, as suggested by Brad Kemper, there may be future interest in extending these approaches (stroke-like dashing control) to borders in the CSS box model.

The SVG WG has already published (a draft of) a dedicated module on Stroke geometry, including dashing, linejoins and stroke alignment.  Although not all of the stroke geometry options would apply to text, I think it makes sense to continue with that spec, possibly moving it to the FX task force umbrella.

This Stroke Geometry module (or an advanced level version of it) might then integrate new border-dashing options that would use the same underlying rendering calculations.  It would also be a good place to implement a new syntax for stroke dashes as a percent of the path length or path segment length, which everyone agrees is a "nice to have" but is not a simple addition in a backwards-compatible manner.

A matching Paint module (under FX) could become the universal definition for the `fill` and `stroke` shorthand properties and their constituent longhand properties, as well as some closely related properties such as `paint-order`.

As I mentioned at the F2F, I very much prefer the shorthand/longhand breakdown of multilayer paint presented in this spec, compared to the longhand-only syntax currently in the SVG 2 spec for fill and stroke.  It would be wonderful if this can be properly spec'd in time for SVG 2 publication.

I assume, from an implementation perspective, it would be ideal if the spec for CSS painted text is ready to implement at the same time as SVG wrapping text, and multilayer paint for both.  That way the rendering code can be harmonized once and used everywhere.

But that's a very short time scale (2-3 months), so probably not feasible. However, we should at least have a clear strategy for how the different specs will interact and depend on each other.

A few final thoughts:

1) Both syntaxes (SVG 2 and the long-hands in the new draft spec) are missing a way to define the reference box for SVG paint servers. This is something that needs to be clarified in coordination with other FX specs (mask/clip-path and filter) to provide clear but flexible interpretation of how to adapt the SVG objectBoundingBox / userSpaceOnUse units in a manner consistent across all properties and content types.

2) Simply activating the `fill` and `stroke` properties on non-SVG text may have unintended complications.  Because these properties inherit to child SVG content there may be a zombie code issue, breaking existing content that sets these values on HTML elements that contain SVG icons.  The @supports rule and most simple feature detection methods are useless when certain properties are recognized as valid but may or may not have an effect on a given element.

Furthermore, Many implementations use advanced rendering methods (such as sub-pixel aliasing) for solid color text that isn't available for complex painted text.  It would probably be useful for performance if there was a single property that switched on or off the new feature. Something like

text-paint-mode: color | paint ;

(or just `paint-mode`, to match `paint-order`, and it could apply to SVG shapes as well, with an effect similar to `fill: currentColor` when switched)

where `color` is normal CSS-styled text, use color property, and `paint` is SVG text, use fill and stroke properties. This would also circumvent the issue with a default fill-color: currentColor not working for SVG backwards compatibility. The default fill-color would be black (to match SVG), but the default (text-)paint-mode for non-SVG text would be `color`.  With this mode, the rendering implementation could safely ignore changes to the fill-* and stroke-* properties.  And of course, authors could test support for the paint-mode property in an @supports block.


~ABR

On 25 January 2016 at 16:32, Tab Atkins Jr. <[hidden email]> wrote:
Per an FXTF meeting some time ago
<https://lists.w3.org/Archives/Public/www-style/2013Jun/0678.html>,
fantasai and I have been drafting fill/stroke as applied to text in
CSS, and with the extensions needed to handle multiline text,
hierarchical elements, and multi-layer (background-like) paints.

Currently this lives in the Text Decoration 4 ED
<https://drafts.csswg.org/css-text-decor-4/>.  Is this appropriate, or
should it live somewhere else less directly text-centric?

We're also unsure exactly how much of fill/stroke to define in this
spec.  Should we take over the entire model, copying text from SVG, or
should we only define the syntax, and the rendering parts that are
relevant to CSS, letting SVG define the rendering parts important to
it?

~TJ