File: native_css_paint_definition.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (155 lines) | stat: -rw-r--r-- 6,584 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_NATIVE_CSS_PAINT_DEFINITION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_NATIVE_CSS_PAINT_DEFINITION_H_

#include "third_party/blink/renderer/core/css/cssom/paint_worklet_input.h"
#include "third_party/blink/renderer/modules/csspaint/nativepaint/native_paint_definition.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "ui/gfx/animation/keyframe/timing_function.h"

namespace blink {

class LocalFrame;
class CSSProperty;
class Element;

// See README.md for how this class fits in to the overall design
class MODULES_EXPORT NativeCssPaintDefinition : public NativePaintDefinition {
 public:
  ~NativeCssPaintDefinition() override = default;

  // Validation function for determining if a value / interpolable_value is
  // supported on the compositor.
  using ValueFilter = bool (*)(const Element* element,
                               const CSSValue* value,
                               const InterpolableValue* interpolable_value);

  // Returns an animation for the given property, if it is compositable
  // excepting additional checks in CheckCanStartAnimationOnCompositor. Used
  // as a base for NativePaintImageGenerator::GetAnimationIfCompositable methods
  // which are implemented in the different Native Paint Definitions
  static Animation* GetAnimationForProperty(
      const Element* element,
      const CSSProperty& property,
      ValueFilter filter = DefaultValueFilter);

  // Used by GetAnimationForProperty and others to verify that the given
  // animation meets compositable paint-worklet animation criteria, excluding
  // additional checks in CheckCanStartAnimationOnCompositor which are the
  // caller's responsibility to verify.
  static bool AnimationIsValidForPaintWorklets(
      Animation* compositable_animation,
      const Element* element,
      const CSSProperty& property,
      NativeCssPaintDefinition::ValueFilter filter);

  // Used by GetAnimationForProperty to check the individual keyframe values.
  static bool CanGetValueFromKeyframe(const Element* element,
                                      const PropertySpecificKeyframe* frame,
                                      const KeyframeEffectModelBase* model,
                                      ValueFilter filter);

  // Default validator for a keyframe value, which accepts any non-null value
  // as being supported. Replace with a property specific validator as needed.
  static bool DefaultValueFilter(const Element* element,
                                 const CSSValue* value,
                                 const InterpolableValue* interpolable_value);

  struct BaseKeyframe {
    BaseKeyframe(double offset, std::unique_ptr<gfx::TimingFunction>& tf)
        : offset(offset), timing_function(tf.release()) {}
    double offset;
    std::unique_ptr<gfx::TimingFunction> timing_function;
  };

  template <typename T>
  struct TypedKeyframe : public BaseKeyframe {
    TypedKeyframe(double offset, std::unique_ptr<gfx::TimingFunction>& tf, T v)
        : BaseKeyframe(offset, tf), value(v) {}
    T value;
  };

  struct KeyframeIndexAndProgress {
    unsigned index;
    double progress;
  };

 protected:
  NativeCssPaintDefinition(LocalFrame*,
                           PaintWorkletInput::PaintWorkletInputType);
  NativeCssPaintDefinition() = default;

  // TODO(crbug.com/381126162): Unify this with the implementation in composited
  // clip path animations.
  // Computes the correct keyframe index and intra-keyframe progress given the
  // global progress. Used to ensure that custom timing functions are handled
  // correctly.
  template <typename T>
  KeyframeIndexAndProgress ComputeKeyframeIndexAndProgress(
      const std::optional<double>& main_thread_progress,
      const CompositorPaintWorkletJob::AnimatedPropertyValues&
          animated_property_values,
      const Vector<TypedKeyframe<T>>& keyframes) {
    DCHECK_GT(keyframes.size(), 1u);

    // TODO(crbug.com/40173432): We should handle the case when the animation is
    // inactive due to being in the before or after phase. When inactive,
    // progress is null. For now, clamping to the start of the animation, which
    // is incorrect. The worklet input will need the underlying property value.
    // Currently, animations with a positive input delay are run on the main
    // thread. This issue will need to be addressed in order to run the
    // animation on the compositor thread.
    double progress =
        Progress(main_thread_progress, animated_property_values).value_or(0);

    // Get the bounding keyframes based on the progress and offsets.
    // TODO(kevers): avoid a linear walk when the number of keyframes is large.
    unsigned result_index = keyframes.size() - 1;
    if (progress <= 0) {
      result_index = 0;
    } else if (progress > 0 && progress < 1) {
      for (unsigned i = 0; i < keyframes.size() - 1; i++) {
        if (progress <= keyframes[i + 1].offset) {
          result_index = i;
          break;
        }
      }
    }
    if (result_index == keyframes.size() - 1) {
      result_index = keyframes.size() - 2;
    }
    // Because the progress is a global one, we need to adjust it with offsets.
    double local_progress =
        (progress - keyframes[result_index].offset) /
        (keyframes[result_index + 1].offset - keyframes[result_index].offset);

    // TODO(crbug.com/347958668): Fix limit direction to account for phase and
    // direction. Important for making the correct decision at the boundary when
    // using a step timing function. Currently blocked on lack of support for a
    // start delay.
    double transformed_progress =
        keyframes[result_index].timing_function
            ? keyframes[result_index].timing_function->GetValue(
                  local_progress, TimingFunction::LimitDirection::RIGHT)
            : local_progress;

    return {result_index, transformed_progress};
  }

  static double Interpolate(double from, double to, double progress) {
    return from * (1 - progress) + to * progress;
  }

 private:
  std::optional<double> Progress(
      const std::optional<double>& main_thread_progress,
      const CompositorPaintWorkletJob::AnimatedPropertyValues&
          animated_property_values);
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_CSSPAINT_NATIVEPAINT_NATIVE_CSS_PAINT_DEFINITION_H_