diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/transforms/transform_operations.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/platform/transforms/transform_operations.cc | 133 |
1 files changed, 101 insertions, 32 deletions
diff --git a/chromium/third_party/blink/renderer/platform/transforms/transform_operations.cc b/chromium/third_party/blink/renderer/platform/transforms/transform_operations.cc index b511af3367f..8e5477f54b2 100644 --- a/chromium/third_party/blink/renderer/platform/transforms/transform_operations.cc +++ b/chromium/third_party/blink/renderer/platform/transforms/transform_operations.cc @@ -28,9 +28,51 @@ #include "third_party/blink/renderer/platform/transforms/interpolated_transform_operation.h" #include "third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h" #include "third_party/blink/renderer/platform/transforms/rotate_transform_operation.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { +namespace { +using ApplyCallback = base::RepeatingCallback<scoped_refptr<TransformOperation>( + const scoped_refptr<TransformOperation>& from, + const scoped_refptr<TransformOperation>& to)>; + +// Applies a given function (|ApplyCallback|) to matching pairs of operations. +TransformOperations ApplyFunctionToMatchingPrefix( + ApplyCallback apply_cb, + const TransformOperations& from, + const TransformOperations& to, + wtf_size_t matching_prefix_length, + bool* success) { + TransformOperations result; + wtf_size_t from_size = from.Operations().size(); + wtf_size_t to_size = to.Operations().size(); + + // If the lists matched entirely but one was shorter, |matching_prefix_length| + // will be the length of the longer list and we implicitly consider the + // missing functions to be matching identity operations. + DCHECK(matching_prefix_length <= std::max(from_size, to_size)); + + for (wtf_size_t i = 0; i < matching_prefix_length; i++) { + scoped_refptr<TransformOperation> from_operation = + (i < from_size) ? from.Operations()[i].get() : nullptr; + scoped_refptr<TransformOperation> to_operation = + (i < to_size) ? to.Operations()[i].get() : nullptr; + + scoped_refptr<TransformOperation> result_operation = + apply_cb.Run(from_operation, to_operation); + + if (result_operation) { + result.Operations().push_back(result_operation); + } else { + *success = false; + return result; + } + } + return result; +} +} // namespace + TransformOperations::TransformOperations(bool make_identity) { if (make_identity) operations_.push_back(IdentityTransformOperation::Create()); @@ -75,36 +117,6 @@ wtf_size_t TransformOperations::MatchingPrefixLength( return std::max(Operations().size(), other.Operations().size()); } -TransformOperations TransformOperations::BlendPrefixByMatchingOperations( - const TransformOperations& from, - wtf_size_t matching_prefix_length, - double progress, - bool* success) const { - TransformOperations result; - wtf_size_t from_size = from.Operations().size(); - wtf_size_t to_size = Operations().size(); - for (wtf_size_t i = 0; i < matching_prefix_length; i++) { - scoped_refptr<TransformOperation> from_operation = - (i < from_size) ? from.Operations()[i].get() : nullptr; - scoped_refptr<TransformOperation> to_operation = - (i < to_size) ? Operations()[i].get() : nullptr; - - scoped_refptr<TransformOperation> blended_operation = - to_operation - ? to_operation->Blend(from_operation.get(), progress) - : (from_operation ? from_operation->Blend(nullptr, progress, true) - : nullptr); - - if (blended_operation) - result.Operations().push_back(blended_operation); - else { - *success = false; - return result; - } - } - return result; -} - scoped_refptr<TransformOperation> TransformOperations::BlendRemainingByUsingMatrixInterpolation( const TransformOperations& from, @@ -146,8 +158,17 @@ TransformOperations TransformOperations::Blend(const TransformOperations& from, std::max(Operations().size(), from.Operations().size()); bool success = true; - TransformOperations result = BlendPrefixByMatchingOperations( - from, matching_prefix_length, progress, &success); + TransformOperations result = ApplyFunctionToMatchingPrefix( + WTF::BindRepeating( + [](double progress, const scoped_refptr<TransformOperation>& from, + const scoped_refptr<TransformOperation>& to) { + // Where the lists matched but one was longer, the shorter list is + // padded with nullptr that represent matching identity operations. + return to ? to->Blend(from.get(), progress) + : (from ? from->Blend(nullptr, progress, true) : nullptr); + }, + progress), + from, *this, matching_prefix_length, &success); if (success && matching_prefix_length < max_path_length) { scoped_refptr<TransformOperation> matrix_op = BlendRemainingByUsingMatrixInterpolation(from, matching_prefix_length, @@ -163,6 +184,54 @@ TransformOperations TransformOperations::Blend(const TransformOperations& from, return result; } +TransformOperations TransformOperations::Accumulate( + const TransformOperations& to) const { + if (!to.size() && !size()) + return *this; + + bool success = true; + wtf_size_t matching_prefix_length = MatchingPrefixLength(to); + wtf_size_t max_path_length = + std::max(Operations().size(), to.Operations().size()); + + // Accumulate matching pairs of transform functions. + TransformOperations result = ApplyFunctionToMatchingPrefix( + WTF::BindRepeating([](const scoped_refptr<TransformOperation>& from, + const scoped_refptr<TransformOperation>& to) { + if (to && from) + return from->Accumulate(*to); + // Where the lists matched but one was longer, the shorter list is + // padded with nullptr that represent matching identity operations. For + // any function, accumulate(f, identity) == f, so just return f. + return to ? to : from; + }), + *this, to, matching_prefix_length, &success); + + // Then, if there are leftover non-matching functions, accumulate the + // remaining matrices. + if (success && matching_prefix_length < max_path_length) { + TransformationMatrix from_transform; + TransformationMatrix to_transform; + ApplyRemaining(FloatSize(), matching_prefix_length, from_transform); + to.ApplyRemaining(FloatSize(), matching_prefix_length, to_transform); + + scoped_refptr<TransformOperation> from_matrix = + Matrix3DTransformOperation::Create(from_transform); + scoped_refptr<TransformOperation> to_matrix = + Matrix3DTransformOperation::Create(to_transform); + scoped_refptr<TransformOperation> matrix_op = + from_matrix->Accumulate(*to_matrix); + + if (matrix_op) + result.Operations().push_back(matrix_op); + else + success = false; + } + + // On failure, behavior is to replace. + return success ? result : to; +} + static void FindCandidatesInPlane(double px, double py, double nz, |