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