Minutes Sapporo F2F 2015-10-29 Part II: Properties and Values, Paint API [css-properties-values-api] [css-paint-api]

Properties & Values
-------------------

  - The group reviewed the changes to the spec since the Paris
      meeting.
  - Next was an in depth discussion of the apply hook.
      - There were concerns about apply being element specific as
          that means it would have to be recomputed every time.
          - This issue came mostly from pseudo elements so that was
              labeled as an issue.
          - There was also a desire to note that if the engine
              memoizes implementation is conformant.
      - For the ApplyDescriptor, there was a desire to access the
          properties on the parent.
          - This may be a Level 2 feature.
      - There was concern that, if two apply hooks are registered on
          the output same property, having the second apply hook
          fail would be confusing to authors.
  - RESOLVED: Apply all discussed edits and publish as FPWD.

Paint API
---------

  - iank reviewed the changes he had made to Paint API instead of
      publishing the FPWD.
  - There was some feedback on the spec:
      - Rossen had editorial notes on the registerPaint algorithm.
      - The lifetime of the paint constructor class was discussed.
          - There are benefits to having just one instance, but also
              benefits having it per fragment.
          - The authors will add a note stating that you can only
              start or stop outside of paint.
          - Having a defined point that always killed the paint
              constructor was discussed as a possible solution.
          - Experimenting to find interoperability was another
              possible solution.
          - This will be added as an issue to the spec.
      - The algorithm for how to produce an image should be kept
          simple for this iteration.
      - An issue will be added regarding how to get the device pixel
          ratio.
  - The resolution to publish FPWD now applies to this draft.

===== FULL MINUTES BELOW ======

Agenda: https://github.com/w3c/css-houdini-drafts/wiki/TPAC-F2F-October-2015
Scribe: iank

Properties & Values
===================

Review of Changes
-----------------

  <iank> https://drafts.css-houdini.org/css-properties-values-api/
  zcorpan: Can you quickly scroll through the document to see what
           has changed?
  shane: Apply hook is at risk, talks about the CSS-variables is
         required for this spec and that layout & paint are
         dependent on this spec. A more formal definition of
         registering custom properties.

  Rossen: Did registerProperty change since last time?
  shane: When we go down to the other functions, there isn't
         anything for the registerProperty function. Might need a
         more formal description for the process.
  zcorpan: An algorithm is generally better as it's more formal,
           doesn't say what happens when both happens.
  zcorpan: This should be an issue, shouldn't block.

  shane: Section on what syntax strings are support, can reference
         existing property name.
  TabAtkins: We will need to change the syntax, for matching
             <'background-color'>
  shane: Seems like a useful feature.
  Rossen: To be able to invoke the existing property parsers?
  zcorpan: It seems useful for being able to support shorthands.
  shane: I think that shorthands should be a different spec, but yes.
  shane: [explaining types of custom properties to be registered]
  astearns: Shorthand question; does this allow you to reference
            existing properties that you've defined yourself?
  dino: If you call registerProperty and inherits: true do you need
        to run style resolution?
  shane: Yes.
  dino: You need to re-parse everything.
  dino: Are they batched?
  dbaron: You can presumable just re-parse that token string as
          already a custom property.
  dbaron: You need to resubstitute variables.
  dbaron: Your identity of your CSSOM changes.
  dbaron: If you have an @rule object, this will change the identity.
  dbaron: Might change this in values.
  zcorpan: If you change the grammar of the property and there is
           another property which points to it, that could change
           its grammar.
  shane: File bug, calls to registerProperty, should not re-parse,
         as would change identity of CSSOM objects.

  TabAtkins: One thing to note - because idents aren't limited to
             ASCII here, we have to do full case-sensitivity, so
             "bigger | BIGGER" are two distinct, distinguishable
             values. This is like custom property names, but unlike
             keywords across most of CSS.
  <dbaron> bigger | BIGGER | bıgger | BİGGER :-)
  ojan: I didn't even know you could use capitals.

  shane: Previously we've just said you do things in the normal way.
  shane: 'inherit', 'unset', 'revert', 'x' then you get behavior to
         generate the computed values for these properties.
  shane: The length values computed value is absolute length
         expressed in pixels.
  shane: [reading from 2.4 of the properties and values spec]

  <dbaron> The <number>, <percentage> line should say that calc()s
           get computed out
  <dbaron> The current "For <number>, <percentage>, <custom-ident>,
           string or "*" values, the computed value is identical to
           the specified value." is wrong for calc()
  <dbaron> Also, "accepts lengths, or percentages, or length calc
           expressions, but not calc expressions containing a
           combination of length and percent values." should
           probably also say it accepts percentage calc expressions,
           but also explicitly say that it doesn't accept mixed
           length/percent calc expressions (based on what we just
           discussed)

  TabAtkins: Need to know for a given context if it is resolved
             against one of the other types. If so the calc can
             include a percentage added to one of the other types,
             and still be a length.
  TabAtkins: For here, because we don't have implicit knowledge, we
             would need to add new grammar terms.
  dbaron: Though even in that case there is still the distinction,
          between lengths calculated before and after CSS
          computation time.
  dbaron: This would allow you do percentages in calc where
          percentages are part of the computed value.
  shane: That makes everything a lot better.

  TabAtkins: <length> | <length-percentage>
  TabAtkins: This is specifying something that is distinct to the
             <length> value (<length> | <percentage>)
  rniwa: Could the input properties by other custom properties.
  TabAtkins: No, we'll get to that later.
  rniwa: This happens after all the computed values are computed.
  rniwa: If two apply hooks try and set the border property then you
         get into trouble.
  TabAtkins: We'll get to that.
  shane: There is a big issue relating to that, which we'll get to.

  shane: Do we need to add <length-percent>?
  zcorpan: What is the relation between this and the CSS grammar?
  zcorpan: Strict subset?
  shane: The CSS grammar doesn't have an explicit ordering. When we
         add features we'll need to add specific ordering.
  TabAtkins: Yes strict subset, plus whatever we need remove
             ambiguities.
  rniwa: If we introduce this new syntax, does it change the syntax
         for CSS potentially?
  shane: Syntaxes will be the same, strings will be the same,
         difference will have a mechanisms to resolve ambiguity.
  zcorpan: In theory we could change all the CSS specs to use this,
           and remove the prose which specifies this.

  TabAtkins: We screwed up word-spacing.
  TabAtkins: <length> | <percent> have different behaviors for that
             property.

Apply Hook
----------

  shane: I'll move onto apply hook
  zcorpan: Discussed with annevk, is actually a Task.
  shane: Let's defer talking about the name.
  shane: It should be inheriting from WorkletGlobalScope not Worklet.
  shane: Have two methods, registerApplyHook and unregisterApplyHook.
  shane: We think that ES6 classes provide a better user experience;
         you instance the class per element which has custom, you
         can use the classes 'this' to cache things.
  shane: I added example on the shape of the class.
  <astearns> https://drafts.css-houdini.org/processors/
  [shane draws on whiteboard]

  <dbaron> I wonder if inputProperties/inputStyle should have the
           same name rather than different names?

  rniwa: Why does apply need to be element specific?
  TabAtkins: Often relies on element specific information.
  ojan: For example flex.
  dbaron: Shouldn't that information be in inputProperties.
  ojan: Element here is not a DOM element.
  dbaron: You sill might want pseudo, but not others.
  rniwa: The reason why I ask this, is that I don't want to
         re-compute this 500 times. If this is stable between
         invocations should be able to re-use.
  dbaron: Content & display may have different behavior for pseudo.
  ojan: This could easily be v2.
  dbaron: I think that passing in the pseudo is easy enough.
  TabAtkins: Letting people safeguard their code a little bit is a
             nice thing.
  TabAtkins: None of the CSS properties in CSS works for first-line.
  ojan: I think that we need to think through this example a bit more.

  shane: Remove tagName, classList and id, add an issue about pseudo.
  dbaron: Spec should say that calls may reuse output of applyHook.
  dbaron: Memoize.
  dbaron: It should be clear that an implementation is conformant,
          if the engine memoizes.
  rniwa: If we did that, for example can just compute once for an
         infinite list.
  TabAtkins: List of inputProperties, why don't we have an optional
             request to have for pseudo element. Any additional
             information you need to request, so you can re-use as
             aggressively as possible.

  zcorpan: Thought about pseudo, this seems like a third you need to
           represent pseudo-elements.
  rniwa: Not an element proxy, ApplyPropertyInputClass, or
         StyleManipulationInput class.
  Rossen: Just a compute context.
  shane: Issue to bikeshed on the name of ElementProxy.
  <astearns> ComputedStylelet

  shane: [reading from section 3.2 - ApplyDescriptor]
  shane: Should be possible to access properties on the parent. I
         think this is a level 2 feature.
  shane: After transitions.

  shane: [3.5 registerApplyHook()]
  zcorpan: Can extend WebIDL syntax in this spec using extended
           attributes?
  rniwa: I'm thinking about this, and how you would use this, seems
         like you would just be piping from one place to another.
  rniwa: I'm thinking this will be very expensive, when authors
         don't care about the property that they are animating.
  shane: If you are just doing that, then you should just use
         var(--prop) instead of the apply hook.
  shane: This would be an apply hook based way to polyfill the
         --scale, --rotate, etc.
  rniwa: If I could declaratively do this...
  shane: You can var(--prop).

  rniwa: What is the use-case for this, to perform this fix-up?
  xidorn: Position property requires performing fix-up.
  xidorn: I think you should just avoid this this a lot.
  shane: All of these pipeline APIs are going to provide large
         footguns.
  shane: I'd love to minimize the cases where this occurs.
  rniwa: I'd love to come up with API where common case doesn't
         provide footgun.
  shane: This is only for those use-cases which don't work with var().
  zcorpan: Should place this in introduction of spec.
  shane: Yes.

  <TabAtkins> Doing the "transform" example is pure declarative:
  <TabAtkins> * { transform: translate(var(--translate-x,0px),
              var(--translate-y, 0px)) rotate(var(--rotate, 0deg))
              scale(var(--scale-x, 1), var(--scale-y, var(
              --scale-x, 1))) var(--transform, id()); }
  <TabAtkins> Then authors can use --translate-x, etc. But they also
              have to use --transform, not transform, to avoid
              clobbering the declaration.
  <TabAtkins> (This assumes an id() transform. Fill in any no-op
              transform if you wish.)

  shane: Big question: At the moment the apply hook says that if
         you've registered one which writes to the same output
         properties then the second registration will fail.
  shane: You can register as many properties as possible then you
         only fail when you try and write to the same element for
         that property.
  Rossen: Can I use the multiple apply hook to output to one final
          custom property, then run apply hook to write into width.
  Rossen: That would be a source of confusion, to not have them
          linked.
  TabAtkins: One thing that you could do to make this better, may
             want to expose an API to combine a way to combine two
             apply hooks.
  TabAtkins: Letting them sequence the apply hooks through another
             API.
  Rossen: Thats a work around.
  shane: There is a few different use-cases.
  shane: First two custom properties both write to width, but used
         in different portions of the page.
  TabAtkins: Runtime exception vs. ahead of time failing.
  rniwa: CSS doesn't have errors like this.
  TabAtkins: CSS is one giant apply hook, doesn't need this ability.

  RESOLVED: Apply above edits and publish as FPWD.

  Scribe: shane

Paint API
=========

  iank: We agreed in Paris to do a FPWD but I rewrote it instead.
  iank: Here's the changes:
  iank: I added a note that we're going to punt on clip, global
        alpha, etc.
  iank: I rewrote paint invalidation section. Effectively same as
        before (you'll get invalidated if geometry changes or when
        computed style changes a dependency),
  iank: but I made it more specific.
  iank: I added a note about partial invalidation support maybe
        coming in a future version of the spec.
  iank: The biggest rewrite was making things class based.
  iank: Class has inputPropeties for deps, overflow for size. This
        needs to return a value rather than void.
  iank: What should it return?

  TabAtkins, shane: Geometry?
  iank: It has paint function. Has restricted PaintRenderingContext.
        Good to know if anyone else would be interested in splitting
        the current canvas context into a sane subset - perhaps in
        WICG?
  rniwa: huh?
  iank: Current context has a bunch of stuff that isn't useful here,
        e.g. being able to add hit regions. Not useful for custom
        paint.
  iank: It would also be nice if this had no readback.
  rniwa: So the idea is a superclass?
  iank: Rip out a partial interface.
  rniwa: Ah, so make a new interface that existing canvas will
         implement.

  iank: So who will join me? Need at least one other vendor.

  rniwa: Feedback: having a Processor interface just for CSS seems
         to vague.
  ojan: We will talk about that in processor section.
  iank: As mentioned before, there's lots of crap because no webIDL
        support for classes yet.

  iank: There is a note about inputProperties being checked only once.
  iank: Also a note about getting WebGL to happen at some point.
        It's complex because of the phase where you hook up all the
        array buffers etc: - where would that happen here?
  iank: It's not impossible but complex.
  iank: Paint notation was just added to the <image> type.
  iank: There is bug on that.
  TabAtkins: Just do it here instead.

  rossen: The registerPaint algorithm - editorial feedback. I have
          some ideas for improving - will talk about later.

  dino: The lifetime of paint constructor class. Currently just one
        instance.
  iank: Yes, probably want per fragment instead.
  iank: There's arguments both ways. Problem with per fragment is
        that there's no fragment listed in the input. Just Rendering
        context, geometry and stylemap. So not tied to a fragment
        which means you can memoize the output.
  iank: In that regard makes sense to have a single instance of the
        class per type.
  iank: Per-fragment could potentially have different behavior per
        fragment.
  iank: Probably you don't want that.
  iank: So it seems to make more sense per paint function.
  dino: It'd be nice if they never got destroyed. Do you want to
        explain why they might?
  iank: The main reason is that it's an easy win memory-wise if a
        tab gets backgrounded to destroy these. They don't impact
        the state of the page.
  iank: So you can nuke the processors and re-instantiate where
        necessary.
  dino: So it's not going to happen e.g. while scrolling.
  iank, ojan: implementation defined thing. Seems wrong to do that.
  rniwa: How much data will these things keep around?
  iank: There's an overhead (at least for Chrome) of 1-200k per V8
        context (at least today). Could go down, or share. But with
        lots of tabs or on a memory constrained device that's a fair
        bit.
  rniwa: I have a hard time believing that 200k per page is worse
         than a compat issue.
  shane: You need to be able to spin up/turn down for parallelism too.
  rniwa: Yeah, but if these things are stateful then that's already
         a problem.
  iank: Use cases for state are caches and things like that, not
        genuinely stateful behavior.
  dino: Say you've got a cartoon-like animation but you want to show
        the frames one at a time.
  rniwa: Maybe stuff like what's in service worker?
  ojan: Data caching probably not a v1 feature.
  rniwa: But we're already discussing that. Maybe we need it now.

  rniwa: The whole purpose of class seems to be that it's temporary.
         Why not make it a separate API?
  iank: Classes are more ergonomic.
  iank: It should be a V2 thing.
  rniwa: But then authors will need to deal with 2 ways of accessing
         data.
  rniwa: I'm a it worried that we are encouraging authors to compute
         and store stuff on a class.
  rniwa: If we're encouraging that, why don't we encourage them to
         store in a caching API from the start?
  ojan: I think it actually makes sense to have transient &
        persistent storage. Persistent storage implies overhead.
        Could be a lot of states if e.g. doing whole layout tree.
  rniwa: Should not be storing full layout tree.
  ojan: Depends. Say you're doing constraint based layout. Now need
        to store something for every box on your page.
  rniwa: How does that work with parallelism?
  shane: It doesn't.

  iank: Grid. Want to work out where all your children are at layout
        time. It's nice to be able to cache that but you don't need
        it.
  iank: But you don't want to structured clone it because that's
        expensive.
  iank: You need to SC to avoid being able to detect being restarted.
  rniwa: You don't need to SC, only verify you can.
  ojan: But cycles, etc. - it's complicated, doesn't have an obvious
        solution, not required for majority of use cases.
  iank: Switching to classes was also feedback from Paris F2F.
  rniwa: If we don't have any guarantees then it's going to be hard
         for authors to reason about it.
  rniwa: Maybe it's enough to say you can only start or stop outside
         of paint.
  ojan: Ooh! Yeah that's definitely something we need to spec. Can't
        get killed within a given frame.
  iank: I'll add an issue about that now.

  ojan: We've just been picturing this for very coarse-grained things.
  rniwa: Makes sense.
  rniwa: But having inconsistent behavior really hurts.
  ojan: Yes, definitely should do guarantees within frame.
  rniwa: I think it'd still be nice to either never kill or always
         kill.
  iank: Something like every 10s?
  rniwa: or every 10 frames or something?
  rniwa: We should try and reduce implementation dependency as much
         as possible.
  shane: Rather than forcing every implementation to do something
         like this could instead make it unknowable when going to be
         killed?
  ojan: Or just need to do experimentation.
  rniwa: I'm unconvinced.
  iank: I'll add a general issue about when to kill these things.

  iank: Moving on. Here's algorithm for how to produce image.
  dino: This first note implies that you need to call overflow for
        every paint function to determine if it's in the viewport or
        not.
  iank: Two things there: (1) only need to call if overflow exists.
        Probably most things won't have. (2) Only call when computed
        style changes.
  iank: Could potentially add subset of properties that overflow
        depends on to restrict further.
  dino: Can leave that for now.
  iank: My gut feeling is keep simple for now and add more if we
        need it later.

  dino: This also makes me realize - geometry is just width &
        height? That means overflow needs to be more than that.
  iank: There's also an issue about whether there needs to be more
        in geometry for L1, e.g. sibling info or child info.
  dino: We might want something that changes within its viewport too.
  dino: I think maybe leave it simple for L1.
  iank: Should be easy to add more stuff later.

  rniwa: Is this in CSS pixels?
  iank: Yes.
  rniwa: Is there a way to get the device pixel ratio?
  iank: Not in this context.
  iank: Assumption is that backing store would be at device pixel
        ratio. Can only write into it so this should just work.
  rniwa: You might want to do different things depending.
  dino: e.g. if you want to store a pattern.
  rniwa: Or a hairline.
  iank: hmm makes sense. Will add as an issue.
  rossen: I'm not sure about that. Transforms and stuff mean you
          can't know the device pixels.
  rniwa: So there's no general way to know that.
  iank: But could plumb in with custom property.
  dino: Why not just expose it?
  rossen: Say you have a pinch zoom. The value will be wrong.
  dino: Right, so you don't know whether you can draw a one pixel
        line. But our device pixel ratio doesn't change.
  rniwa: Can we agree we need something?
  shane: Yes but can also do this with custom properties.
  dino: But if value changes need to keep polling.
  dino: You probably want some extra stuff on the Canvas Context.
  shane: Let's add an issue that summarizes canvas context vs.
         custom property and can discuss on the issue.

  iank: I added the bit that says that the result will be an invalid
        image if the custom painter throws. Added a note indicating
        it'd be nice for debugging tools to show a partial image in
        that case. Based on feedback from Paris.
  iank: I added note that long-running paint functions should be
        similar to long-running scripts.
  iank: I also added note that these things aren't accessible and
        should use standard a11y APIs.

  iank: One big issue that I haven't made progress on is determining
        how to side-load images / data.
  iank: Any thoughts on that, let me know.
  rniwa: What do you mean by side-load?
  iank: At the moment you load images by referencing with custom
        properties. Through typed OM will be able to see if image is
        loaded and extract bitmap data.
  rniwa: It would be bad to have to specify all of e.g. a theme
         through CSS.
  dino: If using SVG, would you get a bitmap?

  Scribe: TabAtkins

  iank: Yeah.
  rossen: At the size of whatever it would display at there.
  dino: What if you don't want to use it at that size?
  dino: I don't think the typed property API can always give a bitmap.
  iank: Actually ImageBitmap is an opaque object. So it can have an
        SVG in there.
  rniwa: Say you have an SVG whose native size is 100x100. You want
         to display it in a 200x200 space. What size is your canvas?
  rossen: Yeah, getting the size of the image and the size of the
          canvas, you just do simple math.
  TabAtkins: The image has some native dimensions (or none), the
             canvas has some dimensions, both of those are
             communicated in the paint callback.
  shane: Is there any use-case for actually getting at the image
         data?
  TabAtkins: Yes, like the filter() or cross-fade() functions. But
             that can be a v2 feature. Most CSS image-using features
             just want to draw an image at a particular
             size/position, and don't care about what's in it.
  dino: Looks like ImageBitmap is actually very specific about it
        representing a bitmap image.
  iank: Well, we'll either need to fix that, or create something
        similar and new which doesn't have that restriction.

  rossen: Any more discussion needed?
  shane: Everyone's still happy with this being FPWD?
  [general assent]

Received on Saturday, 7 November 2015 14:51:41 UTC