Stop using PassRefPtr in platform/graphics
[WebKit-https.git] / Source / WebCore / platform / graphics / texmap / TextureMapperLayer.cpp
1 /*
2  Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  Library General Public License for more details.
13
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB.  If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "TextureMapperLayer.h"
22
23 #include "FloatQuad.h"
24 #include "GraphicsLayerTextureMapper.h"
25 #include "Region.h"
26 #include <wtf/MathExtras.h>
27
28 namespace WebCore {
29
30 class TextureMapperPaintOptions {
31 public:
32     TextureMapperPaintOptions(TextureMapper& textureMapper)
33         : textureMapper(textureMapper)
34     { }
35
36     TextureMapper& textureMapper;
37     TransformationMatrix transform;
38     RefPtr<BitmapTexture> surface;
39     float opacity { 1 };
40     IntSize offset;
41 };
42
43 void TextureMapperLayer::computeTransformsRecursive()
44 {
45     if (m_state.size.isEmpty() && m_state.masksToBounds)
46         return;
47
48     // Compute transforms recursively on the way down to leafs.
49     TransformationMatrix parentTransform;
50     if (m_parent)
51         parentTransform = m_parent->m_currentTransform.combinedForChildren();
52     else if (m_effectTarget)
53         parentTransform = m_effectTarget->m_currentTransform.combined();
54     m_currentTransform.combineTransforms(parentTransform);
55
56     m_state.visible = m_state.backfaceVisibility || !m_currentTransform.combined().isBackFaceVisible();
57
58     if (m_parent && m_parent->m_state.preserves3D)
59         m_centerZ = m_currentTransform.combined().mapPoint(FloatPoint3D(m_state.size.width() / 2, m_state.size.height() / 2, 0)).z();
60
61     if (m_state.maskLayer)
62         m_state.maskLayer->computeTransformsRecursive();
63     if (m_state.replicaLayer)
64         m_state.replicaLayer->computeTransformsRecursive();
65     for (auto* child : m_children) {
66         ASSERT(child->m_parent == this);
67         child->computeTransformsRecursive();
68     }
69
70     // Reorder children if needed on the way back up.
71     if (m_state.preserves3D)
72         sortByZOrder(m_children);
73 }
74
75 void TextureMapperLayer::paint()
76 {
77     computeTransformsRecursive();
78
79     ASSERT(m_textureMapper);
80     TextureMapperPaintOptions options(*m_textureMapper);
81     options.textureMapper.bindSurface(0);
82
83     paintRecursive(options);
84 }
85
86 static Color blendWithOpacity(const Color& color, float opacity)
87 {
88     if (color.isOpaque() && opacity == 1.)
89         return color;
90
91     return color.colorWithAlphaMultipliedBy(opacity);
92 }
93
94 void TextureMapperLayer::computePatternTransformIfNeeded()
95 {
96     if (!m_patternTransformDirty)
97         return;
98
99     m_patternTransformDirty = false;
100     m_patternTransform =
101         TransformationMatrix::rectToRect(FloatRect(FloatPoint::zero(), m_state.contentsTileSize), FloatRect(FloatPoint::zero(), m_state.contentsRect.size()))
102         .multiply(TransformationMatrix().translate(m_state.contentsTilePhase.width() / m_state.contentsRect.width(), m_state.contentsTilePhase.height() / m_state.contentsRect.height()));
103 }
104
105 void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
106 {
107     if (!m_state.visible || !m_state.contentsVisible)
108         return;
109
110     // We apply the following transform to compensate for painting into a surface, and then apply the offset so that the painting fits in the target rect.
111     TransformationMatrix transform;
112     transform.translate(options.offset.width(), options.offset.height());
113     transform.multiply(options.transform);
114     transform.multiply(m_currentTransform.combined());
115
116     if (m_state.solidColor.isValid() && !m_state.contentsRect.isEmpty() && m_state.solidColor.isVisible()) {
117         options.textureMapper.drawSolidColor(m_state.contentsRect, transform, blendWithOpacity(m_state.solidColor, options.opacity));
118         if (m_state.showDebugBorders)
119             options.textureMapper.drawBorder(m_state.debugBorderColor, m_state.debugBorderWidth, layerRect(), transform);
120         return;
121     }
122
123     options.textureMapper.setWrapMode(TextureMapper::StretchWrap);
124     options.textureMapper.setPatternTransform(TransformationMatrix());
125
126     if (m_backingStore) {
127         FloatRect targetRect = layerRect();
128         ASSERT(!targetRect.isEmpty());
129         m_backingStore->paintToTextureMapper(options.textureMapper, targetRect, transform, options.opacity);
130         if (m_state.showDebugBorders)
131             m_backingStore->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, targetRect, transform);
132         // Only draw repaint count for the main backing store.
133         if (m_state.showRepaintCounter)
134             m_backingStore->drawRepaintCounter(options.textureMapper, m_state.repaintCount, m_state.debugBorderColor, targetRect, transform);
135     }
136
137     if (!m_contentsLayer)
138         return;
139
140     if (!m_state.contentsTileSize.isEmpty()) {
141         computePatternTransformIfNeeded();
142         options.textureMapper.setWrapMode(TextureMapper::RepeatWrap);
143         options.textureMapper.setPatternTransform(m_patternTransform);
144     }
145
146     ASSERT(!layerRect().isEmpty());
147     m_contentsLayer->paintToTextureMapper(options.textureMapper, m_state.contentsRect, transform, options.opacity);
148     if (m_state.showDebugBorders)
149         m_contentsLayer->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, m_state.contentsRect, transform);
150 }
151
152 void TextureMapperLayer::sortByZOrder(Vector<TextureMapperLayer* >& array)
153 {
154     std::sort(array.begin(), array.end(),
155         [](TextureMapperLayer* a, TextureMapperLayer* b) {
156             return a->m_centerZ < b->m_centerZ;
157         });
158 }
159
160 void TextureMapperLayer::paintSelfAndChildren(const TextureMapperPaintOptions& options)
161 {
162     paintSelf(options);
163
164     if (m_children.isEmpty())
165         return;
166
167     bool shouldClip = m_state.masksToBounds && !m_state.preserves3D;
168     if (shouldClip) {
169         TransformationMatrix clipTransform;
170         clipTransform.translate(options.offset.width(), options.offset.height());
171         clipTransform.multiply(options.transform);
172         clipTransform.multiply(m_currentTransform.combined());
173         options.textureMapper.beginClip(clipTransform, layerRect());
174     }
175
176     for (auto* child : m_children)
177         child->paintRecursive(options);
178
179     if (shouldClip)
180         options.textureMapper.endClip();
181 }
182
183 bool TextureMapperLayer::shouldBlend() const
184 {
185     if (m_state.preserves3D)
186         return false;
187
188     return m_currentOpacity < 1
189         || hasFilters()
190         || m_state.maskLayer
191         || (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer);
192 }
193
194 bool TextureMapperLayer::isVisible() const
195 {
196     if (m_state.size.isEmpty() && (m_state.masksToBounds || m_state.maskLayer || m_children.isEmpty()))
197         return false;
198     if (!m_state.visible && m_children.isEmpty())
199         return false;
200     if (!m_state.contentsVisible && m_children.isEmpty())
201         return false;
202     if (m_currentOpacity < 0.01)
203         return false;
204     return true;
205 }
206
207 void TextureMapperLayer::paintSelfAndChildrenWithReplica(const TextureMapperPaintOptions& options)
208 {
209     if (m_state.replicaLayer) {
210         TextureMapperPaintOptions replicaOptions(options);
211         replicaOptions.transform
212             .multiply(m_state.replicaLayer->m_currentTransform.combined())
213             .multiply(m_currentTransform.combined().inverse().value_or(TransformationMatrix()));
214         paintSelfAndChildren(replicaOptions);
215     }
216
217     paintSelfAndChildren(options);
218 }
219
220 void TextureMapperLayer::setAnimatedTransform(const TransformationMatrix& matrix)
221 {
222     m_currentTransform.setLocalTransform(matrix);
223 }
224
225 void TextureMapperLayer::setAnimatedOpacity(float opacity)
226 {
227     m_currentOpacity = opacity;
228 }
229
230 TransformationMatrix TextureMapperLayer::replicaTransform()
231 {
232     return TransformationMatrix(m_state.replicaLayer->m_currentTransform.combined()).multiply(m_currentTransform.combined().inverse().value_or(TransformationMatrix()));
233 }
234
235 void TextureMapperLayer::setAnimatedFilters(const FilterOperations& filters)
236 {
237     m_currentFilters = filters;
238 }
239
240 static void resolveOverlaps(Region& newRegion, Region& overlapRegion, Region& nonOverlapRegion)
241 {
242     Region newOverlapRegion(newRegion);
243     newOverlapRegion.intersect(nonOverlapRegion);
244     nonOverlapRegion.subtract(newOverlapRegion);
245     overlapRegion.unite(newOverlapRegion);
246     newRegion.subtract(overlapRegion);
247     nonOverlapRegion.unite(newRegion);
248 }
249
250 void TextureMapperLayer::computeOverlapRegions(Region& overlapRegion, Region& nonOverlapRegion, ResolveSelfOverlapMode mode)
251 {
252     if (!m_state.visible || !m_state.contentsVisible)
253         return;
254
255     FloatRect boundingRect;
256     if (m_backingStore || m_state.masksToBounds || m_state.maskLayer || hasFilters())
257         boundingRect = layerRect();
258     else if (m_contentsLayer || m_state.solidColor.isVisible())
259         boundingRect = m_state.contentsRect;
260
261     if (m_currentFilters.hasOutsets()) {
262         FilterOutsets outsets = m_currentFilters.outsets();
263         IntRect unfilteredTargetRect(boundingRect);
264         boundingRect.move(std::max(0, -outsets.left()), std::max(0, -outsets.top()));
265         boundingRect.expand(outsets.left() + outsets.right(), outsets.top() + outsets.bottom());
266         boundingRect.unite(unfilteredTargetRect);
267     }
268
269     TransformationMatrix replicaMatrix;
270     if (m_state.replicaLayer) {
271         replicaMatrix = replicaTransform();
272         boundingRect.unite(replicaMatrix.mapRect(boundingRect));
273     }
274
275     boundingRect = m_currentTransform.combined().mapRect(boundingRect);
276
277     // Count all masks and filters as overlap layers.
278     if (hasFilters() || m_state.maskLayer || (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer)) {
279         Region newOverlapRegion(enclosingIntRect(boundingRect));
280         nonOverlapRegion.subtract(newOverlapRegion);
281         overlapRegion.unite(newOverlapRegion);
282         return;
283     }
284
285     Region newOverlapRegion;
286     Region newNonOverlapRegion(enclosingIntRect(boundingRect));
287
288     if (!m_state.masksToBounds) {
289         for (auto* child : m_children)
290             child->computeOverlapRegions(newOverlapRegion, newNonOverlapRegion, ResolveSelfOverlapIfNeeded);
291     }
292
293     if (m_state.replicaLayer) {
294         newOverlapRegion.unite(replicaMatrix.mapRect(newOverlapRegion.bounds()));
295         Region replicaRegion(replicaMatrix.mapRect(newNonOverlapRegion.bounds()));
296         resolveOverlaps(replicaRegion, newOverlapRegion, newNonOverlapRegion);
297     }
298
299     if ((mode != ResolveSelfOverlapAlways) && shouldBlend()) {
300         newNonOverlapRegion.unite(newOverlapRegion);
301         newOverlapRegion = Region();
302     }
303
304     overlapRegion.unite(newOverlapRegion);
305     resolveOverlaps(newNonOverlapRegion, overlapRegion, nonOverlapRegion);
306 }
307
308 void TextureMapperLayer::paintUsingOverlapRegions(const TextureMapperPaintOptions& options)
309 {
310     Region overlapRegion;
311     Region nonOverlapRegion;
312     computeOverlapRegions(overlapRegion, nonOverlapRegion, ResolveSelfOverlapAlways);
313     if (overlapRegion.isEmpty()) {
314         paintSelfAndChildrenWithReplica(options);
315         return;
316     }
317
318     // Having both overlap and non-overlap regions carries some overhead. Avoid it if the overlap area
319     // is big anyway.
320     if (overlapRegion.bounds().size().area() > nonOverlapRegion.bounds().size().area()) {
321         overlapRegion.unite(nonOverlapRegion);
322         nonOverlapRegion = Region();
323     }
324
325     nonOverlapRegion.translate(options.offset);
326     Vector<IntRect> rects = nonOverlapRegion.rects();
327
328     for (auto& rect : rects) {
329         if (!rect.intersects(options.textureMapper.clipBounds()))
330             continue;
331
332         options.textureMapper.beginClip(TransformationMatrix(), rect);
333         paintSelfAndChildrenWithReplica(options);
334         options.textureMapper.endClip();
335     }
336
337     rects = overlapRegion.rects();
338     static const size_t OverlapRegionConsolidationThreshold = 4;
339     if (nonOverlapRegion.isEmpty() && rects.size() > OverlapRegionConsolidationThreshold) {
340         rects.clear();
341         rects.append(overlapRegion.bounds());
342     }
343
344     IntSize maxTextureSize = options.textureMapper.maxTextureSize();
345     IntRect adjustedClipBounds(options.textureMapper.clipBounds());
346     adjustedClipBounds.move(-options.offset);
347     for (auto& rect : rects) {
348         for (int x = rect.x(); x < rect.maxX(); x += maxTextureSize.width()) {
349             for (int y = rect.y(); y < rect.maxY(); y += maxTextureSize.height()) {
350                 IntRect tileRect(IntPoint(x, y), maxTextureSize);
351                 tileRect.intersect(rect);
352                 if (!tileRect.intersects(adjustedClipBounds))
353                     continue;
354
355                 paintWithIntermediateSurface(options, tileRect);
356             }
357         }
358     }
359 }
360
361 void TextureMapperLayer::applyMask(const TextureMapperPaintOptions& options)
362 {
363     options.textureMapper.setMaskMode(true);
364     paintSelf(options);
365     options.textureMapper.setMaskMode(false);
366 }
367
368 RefPtr<BitmapTexture> TextureMapperLayer::paintIntoSurface(const TextureMapperPaintOptions& options, const IntSize& size)
369 {
370     RefPtr<BitmapTexture> surface = options.textureMapper.acquireTextureFromPool(size, BitmapTexture::SupportsAlpha | BitmapTexture::FBOAttachment);
371     TextureMapperPaintOptions paintOptions(options);
372     paintOptions.surface = surface;
373     options.textureMapper.bindSurface(surface.get());
374     paintSelfAndChildren(paintOptions);
375     if (m_state.maskLayer)
376         m_state.maskLayer->applyMask(options);
377     surface = surface->applyFilters(options.textureMapper, m_currentFilters);
378     options.textureMapper.bindSurface(surface.get());
379     return surface;
380 }
381
382 static void commitSurface(const TextureMapperPaintOptions& options, BitmapTexture& surface, const IntRect& rect, float opacity)
383 {
384     options.textureMapper.bindSurface(options.surface.get());
385     TransformationMatrix targetTransform;
386     targetTransform.translate(options.offset.width(), options.offset.height());
387     targetTransform.multiply(options.transform);
388     options.textureMapper.drawTexture(surface, rect, targetTransform, opacity);
389 }
390
391 void TextureMapperLayer::paintWithIntermediateSurface(const TextureMapperPaintOptions& options, const IntRect& rect)
392 {
393     RefPtr<BitmapTexture> replicaSurface;
394     RefPtr<BitmapTexture> mainSurface;
395     TextureMapperPaintOptions paintOptions(options);
396     paintOptions.offset = -IntSize(rect.x(), rect.y());
397     paintOptions.opacity = 1;
398     paintOptions.transform = TransformationMatrix();
399     if (m_state.replicaLayer) {
400         paintOptions.transform = replicaTransform();
401         replicaSurface = paintIntoSurface(paintOptions, rect.size());
402         paintOptions.transform = TransformationMatrix();
403         if (m_state.replicaLayer->m_state.maskLayer)
404             m_state.replicaLayer->m_state.maskLayer->applyMask(paintOptions);
405     }
406
407     if (replicaSurface && options.opacity == 1) {
408         commitSurface(options, *replicaSurface, rect, 1);
409         replicaSurface = nullptr;
410     }
411
412     mainSurface = paintIntoSurface(paintOptions, rect.size());
413     if (replicaSurface) {
414         options.textureMapper.bindSurface(replicaSurface.get());
415         options.textureMapper.drawTexture(*mainSurface.get(), FloatRect(FloatPoint::zero(), rect.size()));
416         mainSurface = replicaSurface;
417     }
418
419     commitSurface(options, *mainSurface, rect, options.opacity);
420 }
421
422 void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options)
423 {
424     if (!isVisible())
425         return;
426
427     TextureMapperPaintOptions paintOptions(options);
428     paintOptions.opacity *= m_currentOpacity;
429
430     if (!shouldBlend()) {
431         paintSelfAndChildrenWithReplica(paintOptions);
432         return;
433     }
434
435     paintUsingOverlapRegions(paintOptions);
436 }
437
438 TextureMapperLayer::~TextureMapperLayer()
439 {
440     for (auto* child : m_children)
441         child->m_parent = nullptr;
442
443     removeFromParent();
444
445     if (m_effectTarget) {
446         if (m_effectTarget->m_state.maskLayer == this)
447             m_effectTarget->m_state.maskLayer = nullptr;
448         if (m_effectTarget->m_state.replicaLayer == this)
449             m_effectTarget->m_state.replicaLayer = nullptr;
450     }
451 }
452
453 #if !USE(COORDINATED_GRAPHICS)
454 void TextureMapperLayer::setChildren(const Vector<GraphicsLayer*>& newChildren)
455 {
456     removeAllChildren();
457     for (auto* child : newChildren)
458         addChild(&downcast<GraphicsLayerTextureMapper>(child)->layer());
459 }
460 #endif
461
462 void TextureMapperLayer::setChildren(const Vector<TextureMapperLayer*>& newChildren)
463 {
464     removeAllChildren();
465     for (auto* child : newChildren)
466         addChild(child);
467 }
468
469 void TextureMapperLayer::addChild(TextureMapperLayer* childLayer)
470 {
471     ASSERT(childLayer != this);
472
473     if (childLayer->m_parent)
474         childLayer->removeFromParent();
475
476     childLayer->m_parent = this;
477     m_children.append(childLayer);
478 }
479
480 void TextureMapperLayer::removeFromParent()
481 {
482     if (m_parent) {
483         size_t index = m_parent->m_children.find(this);
484         ASSERT(index != notFound);
485         m_parent->m_children.remove(index);
486     }
487
488     m_parent = nullptr;
489 }
490
491 void TextureMapperLayer::removeAllChildren()
492 {
493     auto oldChildren = WTFMove(m_children);
494     for (auto* child : oldChildren)
495         child->m_parent = nullptr;
496 }
497
498 void TextureMapperLayer::setMaskLayer(TextureMapperLayer* maskLayer)
499 {
500     if (maskLayer)
501         maskLayer->m_effectTarget = this;
502     m_state.maskLayer = maskLayer;
503 }
504
505 void TextureMapperLayer::setReplicaLayer(TextureMapperLayer* replicaLayer)
506 {
507     if (replicaLayer)
508         replicaLayer->m_effectTarget = this;
509     m_state.replicaLayer = replicaLayer;
510 }
511
512 void TextureMapperLayer::setPosition(const FloatPoint& position)
513 {
514     m_state.pos = position;
515     m_currentTransform.setPosition(adjustedPosition());
516 }
517
518 void TextureMapperLayer::setSize(const FloatSize& size)
519 {
520     m_state.size = size;
521     m_currentTransform.setSize(size);
522 }
523
524 void TextureMapperLayer::setAnchorPoint(const FloatPoint3D& anchorPoint)
525 {
526     m_state.anchorPoint = anchorPoint;
527     m_currentTransform.setAnchorPoint(anchorPoint);
528 }
529
530 void TextureMapperLayer::setPreserves3D(bool preserves3D)
531 {
532     m_state.preserves3D = preserves3D;
533     m_currentTransform.setFlattening(!preserves3D);
534 }
535
536 void TextureMapperLayer::setTransform(const TransformationMatrix& transform)
537 {
538     m_state.transform = transform;
539     m_currentTransform.setLocalTransform(transform);
540 }
541
542 void TextureMapperLayer::setChildrenTransform(const TransformationMatrix& childrenTransform)
543 {
544     m_state.childrenTransform = childrenTransform;
545     m_currentTransform.setChildrenTransform(childrenTransform);
546 }
547
548 void TextureMapperLayer::setContentsRect(const FloatRect& contentsRect)
549 {
550     if (contentsRect == m_state.contentsRect)
551         return;
552     m_state.contentsRect = contentsRect;
553     m_patternTransformDirty = true;
554 }
555
556 void TextureMapperLayer::setContentsTileSize(const FloatSize& size)
557 {
558     if (size == m_state.contentsTileSize)
559         return;
560     m_state.contentsTileSize = size;
561     m_patternTransformDirty = true;
562 }
563
564 void TextureMapperLayer::setContentsTilePhase(const FloatSize& phase)
565 {
566     if (phase == m_state.contentsTilePhase)
567         return;
568     m_state.contentsTilePhase = phase;
569     m_patternTransformDirty = true;
570 }
571
572 void TextureMapperLayer::setMasksToBounds(bool masksToBounds)
573 {
574     m_state.masksToBounds = masksToBounds;
575 }
576
577 void TextureMapperLayer::setDrawsContent(bool drawsContent)
578 {
579     m_state.drawsContent = drawsContent;
580 }
581
582 void TextureMapperLayer::setContentsVisible(bool contentsVisible)
583 {
584     m_state.contentsVisible = contentsVisible;
585 }
586
587 void TextureMapperLayer::setContentsOpaque(bool contentsOpaque)
588 {
589     m_state.contentsOpaque = contentsOpaque;
590 }
591
592 void TextureMapperLayer::setBackfaceVisibility(bool backfaceVisibility)
593 {
594     m_state.backfaceVisibility = backfaceVisibility;
595 }
596
597 void TextureMapperLayer::setOpacity(float opacity)
598 {
599     m_state.opacity = opacity;
600 }
601
602 void TextureMapperLayer::setSolidColor(const Color& color)
603 {
604     m_state.solidColor = color;
605 }
606
607 void TextureMapperLayer::setFilters(const FilterOperations& filters)
608 {
609     m_state.filters = filters;
610 }
611
612 void TextureMapperLayer::setDebugVisuals(bool showDebugBorders, const Color& debugBorderColor, float debugBorderWidth, bool showRepaintCounter)
613 {
614     m_state.showDebugBorders = showDebugBorders;
615     m_state.debugBorderColor = debugBorderColor;
616     m_state.debugBorderWidth = debugBorderWidth;
617     m_state.showRepaintCounter = showRepaintCounter;
618 }
619
620 void TextureMapperLayer::setRepaintCount(int repaintCount)
621 {
622     m_state.repaintCount = repaintCount;
623 }
624
625 void TextureMapperLayer::setContentsLayer(TextureMapperPlatformLayer* platformLayer)
626 {
627     m_contentsLayer = platformLayer;
628 }
629
630 void TextureMapperLayer::setAnimations(const TextureMapperAnimations& animations)
631 {
632     m_animations = animations;
633 }
634
635 void TextureMapperLayer::setFixedToViewport(bool fixedToViewport)
636 {
637     m_fixedToViewport = fixedToViewport;
638 }
639
640 void TextureMapperLayer::setBackingStore(RefPtr<TextureMapperBackingStore>&& backingStore)
641 {
642     m_backingStore = WTFMove(backingStore);
643 }
644
645 bool TextureMapperLayer::descendantsOrSelfHaveRunningAnimations() const
646 {
647     if (m_animations.hasRunningAnimations())
648         return true;
649
650     return std::any_of(m_children.begin(), m_children.end(),
651         [](TextureMapperLayer* child) {
652             return child->descendantsOrSelfHaveRunningAnimations();
653         });
654 }
655
656 void TextureMapperLayer::applyAnimationsRecursively()
657 {
658     syncAnimations();
659     for (auto* child : m_children)
660         child->applyAnimationsRecursively();
661 }
662
663 void TextureMapperLayer::syncAnimations()
664 {
665     m_animations.apply(*this);
666     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyTransform))
667         m_currentTransform.setLocalTransform(m_state.transform);
668     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity))
669         m_currentOpacity = m_state.opacity;
670
671     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyFilter))
672         m_currentFilters = m_state.filters;
673 }
674
675 bool TextureMapperLayer::isAncestorFixedToViewport() const
676 {
677     for (TextureMapperLayer* parent = m_parent; parent; parent = parent->m_parent) {
678         if (parent->m_fixedToViewport)
679             return true;
680     }
681
682     return false;
683 }
684
685 void TextureMapperLayer::setScrollPositionDeltaIfNeeded(const FloatSize& delta)
686 {
687     // delta is the difference between the scroll offset in the ui process and the scroll offset
688     // in the web process. We add this delta to the position of fixed layers, to make
689     // sure that they do not move while scrolling. We need to reset this delta to fixed layers
690     // that have an ancestor which is also a fixed layer, because the delta will be added to the ancestor.
691     if (isAncestorFixedToViewport())
692         m_scrollPositionDelta = FloatSize();
693     else
694         m_scrollPositionDelta = delta;
695     m_currentTransform.setPosition(adjustedPosition());
696 }
697
698 template<class HitTestCondition> TextureMapperLayer* TextureMapperLayer::hitTest(const FloatPoint& point, HitTestCondition condition)
699 {
700     if (!m_state.visible || !m_state.contentsVisible)
701         return 0;
702
703     TextureMapperLayer* result = 0;
704     for (int i = m_children.size() - 1; !result && i >= 0; --i)
705         result = m_children[i]->hitTest(point, condition);
706
707     if (result)
708         return result;
709
710     return condition(this, point) ? this : 0;
711 }
712
713 bool TextureMapperLayer::scrollableLayerHitTestCondition(TextureMapperLayer* layer, const FloatPoint& point)
714 {
715     // scrolling layer's m_parent->m_parent, the parent of the scrolling layes, is the one that defines the
716     // rectangle to be used for hit testing.
717     if (!layer->isScrollable() || !layer->m_parent || !layer->m_parent->m_parent)
718         return false;
719
720     TextureMapperLayer* parentLayer = layer->m_parent->m_parent;
721     FloatRect rect = parentLayer->layerRect();
722     return parentLayer->m_currentTransform.combined().mapQuad(rect).containsPoint(point);
723 }
724
725 TextureMapperLayer* TextureMapperLayer::findScrollableContentsLayerAt(const FloatPoint& point)
726 {
727     return hitTest(point, &TextureMapperLayer::scrollableLayerHitTestCondition);
728 }
729
730 FloatSize TextureMapperLayer::mapScrollOffset(const FloatSize& offset)
731 {
732     double zeroX, zeroY, offsetX, offsetY;
733     TransformationMatrix transform = m_currentTransform.combined().inverse().value_or(TransformationMatrix());
734     transform.map(0, 0, zeroX, zeroY);
735     transform.map(offset.width(), offset.height(), offsetX, offsetY);
736     return FloatSize(offsetX - zeroX, offsetY - zeroY);
737 }
738
739 void TextureMapperLayer::commitScrollOffset(const FloatSize& offset)
740 {
741     FloatSize fullOffset = m_accumulatedScrollOffsetFractionalPart + offset;
742
743     int intWidth = round(fullOffset.width());
744     int intHeight = round(fullOffset.height());
745
746     // m_accumulatedScrollOffsetFractionalPart holds the fractional part of the user scroll offset that
747     // has not yet been synced with the web process because the web process expects an IntSize.
748     m_accumulatedScrollOffsetFractionalPart = FloatSize(fullOffset.width() - intWidth, fullOffset.height() - intHeight);
749
750     m_scrollClient->commitScrollOffset(m_id, IntSize(intWidth, intHeight));
751 }
752
753 void TextureMapperLayer::scrollBy(const FloatSize& offset)
754 {
755     if (!isScrollable() || !m_scrollClient || offset.isZero())
756         return;
757
758     FloatSize scrollOffset = mapScrollOffset(offset);
759     m_userScrollOffset += scrollOffset;
760
761     m_currentTransform.setPosition(adjustedPosition());
762     commitScrollOffset(scrollOffset);
763 }
764
765 void TextureMapperLayer::didCommitScrollOffset(const IntSize& offset)
766 {
767     m_userScrollOffset = FloatSize(m_userScrollOffset.width() - offset.width(), m_userScrollOffset.height() - offset.height());
768     m_currentTransform.setPosition(adjustedPosition());
769 }
770
771 }