diff --git a/source b/source index 17797a86de0..888e5ab9a3a 100644 --- a/source +++ b/source @@ -4070,6 +4070,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
  • SVG title element
  • SVG use element
  • SVG text-rendering property
  • +
  • core attribute
  • +
  • presentation attribute
  • @@ -4082,6 +4084,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute @@ -60960,7 +60964,14 @@ interface mixin CanvasShadowStyles { interface mixin CanvasFilters { // filters - attribute DOMString filter; // (default "none") + attribute (DOMString or CanvasFilter) filter; // (default "none") +}; + +typedef record<DOMString, any> CanvasFilterInput; + +[Exposed=(Window,Worker,PaintWorklet)] +interface CanvasFilter { + constructor(optional (CanvasFilterInput or sequence<CanvasFilterInput>) filters); }; interface mixin CanvasRect { @@ -65992,62 +66003,333 @@ console.log(pixels.data[2]);
    Filters
    -

    All drawing operations on an object which implements the CanvasFilters - interface are affected by the global All drawing operations on an object which implements the CanvasFilters interface + are affected by the global filter attribute.

    context.filter [ = value ]
    -

    Returns the current filter.

    -

    Can be set, to change the filter. Values that cannot be parsed as a - <filter-value-list> value are ignored.

    +

    Can be set, to change the filter. Values can either be the string "none", a string parseable as a <filter-value-list>, or a + CanvasFilter object.

    + +
    filter = new CanvasFilter(input)
    +

    Constructs a new CanvasFilter from the properties + of the input object. These properties include a filter + property, whose value is one of the supported filter names, and additionally can + include properties corresponding to the settings for the filter. These latter properties are the + same as the XML attribute names when using the corresponding SVG filters.

    + +
    filter = new CanvasFilter(inputs)
    +

    Constructs a new CanvasFilter from the + inputs array. Each element in the array is an input as described for the previous + overload. They are composed in sequence to create the final filter.

    -

    The filter attribute, on getting, must - return the last value it was successfully set to. The value must not be re-serialized. On setting, - if the new value is 'none' (not the empty string, null, or undefined), filters must be disabled - for the context. Otherwise, the value must be parsed as a - <filter-value-list> value. If the value cannot be parsed as a - <filter-value-list> value, where using property-independent style sheet - syntax like 'inherit' or 'initial' is considered an invalid value, then it must be ignored, and - the attribute must retain its previous value. When creating the object implementing the - CanvasFilters interface, the attribute must be set to 'none'.

    +

    Such objects have an associated current + filter, which is either a string or a CanvasFilter. Initially the current filter is set to the string "none". Whenever the value of the current filter is the string "none" filters will be disabled for the context.

    -

    A <filter-value-list> value consists of a sequence of one or more - filter functions or references to SVG filters. The input to the filter is used as the input - to the first item in the list. Subsequent items take the output of the previous item as - their input.

    +

    A CanvasFilter is an interface for creating SVG filters using JavaScript. A + CanvasFilter has an associated XML filter list. An XML filter list is a + list of XML element data for filters that fully describes an SVG filter + network. It is set during construction of the CanvasFilter.

    -

    Coordinates used in the value of the filter attribute are interpreted such that one pixel is - equivalent to one SVG user space unit and to one canvas coordinate space unit. Filter coordinates - are not affected by the current transformation - matrix. The current transformation matrix affects only the input to the filter. Filters - are applied in the output bitmap's coordinate space.

    +

    The filter getter steps are to return + this's current filter.

    -

    When the value of the filter attribute defines - lengths using percentages or using 'em' or 'ex' units, these must be - interpreted relative to the computed value of the 'font-size' property - of the font style source object at the time that the attribute is set, if it is an - element. If the computed values are undefined for a - particular case (e.g. because the font style source object is not an element or is - not being rendered), then the relative keywords must be interpreted relative to the - default value of the font attribute. The 'larger' and - 'smaller' keywords are not supported.

    +

    The filter setter steps are:

    -

    If the value of the filter attribute refers to an - SVG filter in the same document, and this SVG filter changes, then the changed filter is used for - the next draw operation.

    +
      +
    1. +

      If the given value is a string, then:

      -

      If the value of the filter attribute refers to an - SVG filter in an external resource document and that document is not loaded when a drawing - operation is invoked, then the drawing operation must proceed with no filtering.

      +
        +
      1. If the given value is "none", then set this's current filter to "none" + and return.

      2. + +
      3. Let parsedValue be the result of parsing the given values as a <filter-value-list>. If + any property-independent style sheet syntax like 'inherit' or 'initial' is present, then this + parsing must return failure.

      4. + +
      5. If parsedValue is failure, then return.

      6. + +
      7. Set this's current + filter to the given value.

      8. +
      +
    2. + +
    3. Otherwise, set this's current + filter to the given value.

    4. +
    + +
    + +

    Though context.filter = "none" will disable + filters for the context, context.filter = "", context.filter = null, + and context.filter = + undefined are all treated as unparseable inputs and the value of the current filter is left unchanged.

    + +
    + +

    For the construction of CanvasFilter objects, the following definitions are + needed:

    + +
    + +

    The supported filter names are "gaussianBlur", "colorMatrix", "convolveMatrix", and "componentTransfer". + +

    + +

    The XML element data for filters is a struct, with the following items:

    + + + +

    To get the IDL type for a canvas filter attribute attrName:

    + +
      +
    1. Let type be the type listed for attrName in Filter + Effects.

    2. + +
    3. If type is "false | true", then return boolean.

    4. + +
    5. If type is "list of <number>s", then return sequence<long long>.

    6. + +
    7. If type is "<number-optional-number>", "<number>", or "<integer>", then return long long.

    8. + +
    9. Return DOMString.

    10. +
    + +

    To generate an XML value from a key, + value pair: + +

      +
    1. Let type be the result of getting the IDL type for a canvas filter + attribute for key.

    2. + +
    3. Let idlValue be the result of converting value to type.

    4. + +
    5. Let xmlValue be the result of converting idlValue to an ECMAScript value, and + then converting that result to a DOMString.

    6. + +
    7. Return xmlValue.

    8. +
    + +

    The new + CanvasFilter(filters) constructor steps are:

    + +
      +
    1. Let xmlFilters be an empty list.

    2. + +
    3. If filters is a CanvasFilterInput, then set filters to + « filters ».

    4. + +
    5. +

      For each filterDict of filters:

      + +
        +
      1. If filterDict["filter"] does not exist, then throw a TypeError.

      2. + +
      3. Let filterName be the value of filterDict["filter"].

      4. + +
      5. If filterName is not one of supported filter names, then + continue.

      6. + +
      7. Let xmlName be the concatenation of "fe", the first + code unit of filterName converted to ASCII uppercase, and all code + units of filterName after the first one.

      8. + +
      9. Let xmlFilter be a new XML element data for filters whose name is xmlName, whose attributes is an empty ordered map, and whose children is an empty list.

      10. + +
      11. Append xmlFilter to + xmlFilters.

      12. + +
      13. +

        For each keyvalue of + filterDict:

        + +
          +
        1. +

          If any of the following are true:

          + +
            +
          • key is not the local name of an attribute listed for the filter + primitive given by xmlName

          • + +
          • key is the local name of a core attribute

          • + +
          • key is the local name of a presentation attribute

          • + +
          • key is the local name of a filter primitive + attribute

          • + +
          • key is "in" or "filter"

          • + +
          • key contains U+003A (:)

          • +
          + +

          then continue.

          +
        2. + +
        3. +

          If key is one of "funcR", "funcG", "funcB", "funcA":

          + +
            +
          1. Set value to the result of converting value to record<DOMString, any>.

          2. + +
          3. Let xmlTransferName be the concatenation of "fe", + the first code unit of key converted to ASCII uppercase, and all + code units of name after the first one.

          4. + +
          5. Let transferFunction be a new XML element data for filters + whose name is xmlTransferName, whose + attributes is an empty ordered map, and whose + children is an empty list.

          6. + +
          7. +

            For each transferNametransferValue of value:

            + +
              +
            1. Let transferFunctionValue be the result of generating an XML value from transferName + and transferValue.

            2. + +
            3. Set transferFunction's attributes[key] to + transferFunctionValue.

            4. +
            +
          8. + +
          9. Append transferFunction to xmlFilter's children.

          10. +
          +
        4. + +
        5. +

          Otherwise:

          + +
            +
          1. Let attrXMLValue be the result of generating an XML value from key and + value.

          2. + +
          3. Set xmlFilter's attributes[key] to + attrXMLValue.

          4. +
          +
        6. +
        +
      14. +
      +
    6. + +
    7. Set this's XML + filter list to xmlFilters.

    8. +
    + +
    + +
    +

    The following example will set the canvas's filter to a colorMatrix + filter that swaps the green and red channels, then blurs the result by 5 pixels:

    + +
    // canvas is a reference to a <canvas> element
    +const context = canvas.getContext('2d');
    +context.filter = new CanvasFilter([
    +  {
    +    filter: "colorMatrix",
    +    type: "matrix",
    +    values: [
    +      0, 1, 0, 0, 0,
    +      1, 0, 0, 0, 0,
    +      0, 0, 1, 0, 0,
    +      0, 0, 0, 1, 0
    +    ],
    +  },
    +  {
    +    filter: "gaussianBlur",
    +    stdDeviation: 5,
    +  }
    +]);
    +
    + +

    Currently, CanvasFilters can only be linked lists. Full filter + graphs are a planned expansion of this feature.

    + +

    Coordinates used in the value of the current + filter are interpreted such that one pixel is equivalent to one SVG user space unit and to + one canvas coordinate space unit. Filter coordinates are not affected by the current transformation matrix. The current + transformation matrix affects only the input to the filter. Filters are applied in the + output bitmap's coordinate space.

    + +
    + +

    When the value of the current filter is a + string parsable as a <filter-value-list> which defines lengths using + percentages or using 'em' or 'ex' units, these must be interpreted + relative to the computed value of the 'font-size' property of the + font style source object at the time that the attribute is set. If the computed values are undefined for a particular case (e.g. because + the font style source object is not an element or is not being + rendered), then the relative keywords must be interpreted relative to the default value of + the font attribute. The 'larger' and 'smaller' keywords + are not supported.

    + +

    If the value of the current filter is a + string parseable as a <filter-value-list> with a reference to an SVG filter in + the same document, and this SVG filter changes, then the changed filter is used for the next draw + operation.

    + +

    If the value of the current filter is a + string parseable as a <filter-value-list> with a reference to an SVG filter in + an external resource document and that document is not loaded when a drawing operation is + invoked, then the drawing operation must proceed with no filtering.

    @@ -66055,13 +66337,12 @@ console.log(pixels.data[2]); -

    Since drawing is performed using filter value 'none' until an externally-defined - filter has finished loading, authors might wish to determine whether such a filter - has finished loading before proceeding with a drawing operation. One way to accomplish - this is to load the externally-defined filter elsewhere within the same page in some - element that sends a load event (for example, an SVG - use element), and wait for the load event to be - dispatched.

    +

    Since drawing is performed using filter value "none" until an + externally-defined filter has finished loading, authors might wish to determine whether such a + filter has finished loading before proceeding with a drawing operation. One way to accomplish + this is to load the externally-defined filter elsewhere within the same page in some element that + sends a load event (for example, an SVG use + element), and wait for the load event to be dispatched.

    @@ -66076,11 +66357,22 @@ console.log(pixels.data[2]); and line styles must be honored, and the stroke must itself also be subjected to the current transformation matrix.

    -
  • When the filter attribute is set to a value other than 'none' and all the - externally-defined filters it references, if any, are in documents that are currently loaded, - then use image A as the input to the filter, creating image B. Otherwise, let - B be an alias for A.

  • +
  • +

    When the current filter is set to a + value other than "none" and all the externally-defined filters it + references, if any, are in documents that are currently loaded, then use image A as + the input to the current filter, creating + image B. If the current filter + is a string parseable as a <filter-value-list>, then draw using the current filter in the same manner as SVG. If the + current filter is a + CanvasFilter, draw using the equivalent SVG for the XML structure stored in the + current filter's by mapping each + filter property of the XML filter list.

    + +

    Otherwise, let B be an alias for A.

    +
  • When shadows are drawn, render the shadow from image B, using the current shadow styles, creating image C.

  • @@ -126064,7 +126356,7 @@ INSERT INTERFACES HERE
    File API, A. Ranganathan. W3C.
    [FILTERS]
    -
    Filter Effects, D. Jackson, E. Dahlström, D. Schulze. W3C.
    +
    Filter Effects, D. Schulze, D. Jackson, C. Harrelson. W3C.
    [FULLSCREEN]
    Fullscreen, A. van Kesteren, T. Çelik. WHATWG.