[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / platform / graphics / GraphicsLayer.cpp
1 /*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #include "GraphicsLayer.h"
29
30 #include "FloatPoint.h"
31 #include "FloatRect.h"
32 #include "GraphicsContext.h"
33 #include "LayoutRect.h"
34 #include "RotateTransformOperation.h"
35 #include <wtf/HashMap.h>
36 #include <wtf/NeverDestroyed.h>
37 #include <wtf/text/CString.h>
38 #include <wtf/text/StringBuilder.h>
39 #include <wtf/text/TextStream.h>
40 #include <wtf/text/WTFString.h>
41
42 #ifndef NDEBUG
43 #include <stdio.h>
44 #endif
45
46 namespace WebCore {
47
48 typedef HashMap<const GraphicsLayer*, Vector<FloatRect>> RepaintMap;
49 static RepaintMap& repaintRectMap()
50 {
51     static NeverDestroyed<RepaintMap> map;
52     return map;
53 }
54
55 void KeyframeValueList::insert(std::unique_ptr<const AnimationValue> value)
56 {
57     for (size_t i = 0; i < m_values.size(); ++i) {
58         const AnimationValue* curValue = m_values[i].get();
59         if (curValue->keyTime() == value->keyTime()) {
60             ASSERT_NOT_REACHED();
61             // insert after
62             m_values.insert(i + 1, WTFMove(value));
63             return;
64         }
65         if (curValue->keyTime() > value->keyTime()) {
66             // insert before
67             m_values.insert(i, WTFMove(value));
68             return;
69         }
70     }
71     
72     m_values.append(WTFMove(value));
73 }
74
75 #if !USE(CA)
76 bool GraphicsLayer::supportsLayerType(Type type)
77 {
78     switch (type) {
79     case Type::Normal:
80     case Type::PageTiledBacking:
81     case Type::ScrollContainer:
82     case Type::ScrolledContents:
83         return true;
84     case Type::Shape:
85         return false;
86     }
87     ASSERT_NOT_REACHED();
88     return false;
89 }
90
91 bool GraphicsLayer::supportsBackgroundColorContent()
92 {
93 #if USE(TEXTURE_MAPPER)
94     return true;
95 #else
96     return false;
97 #endif
98 }
99
100 bool GraphicsLayer::supportsSubpixelAntialiasedLayerText()
101 {
102     return false;
103 }
104 #endif
105
106 #if !USE(COORDINATED_GRAPHICS)
107 bool GraphicsLayer::supportsContentsTiling()
108 {
109     // FIXME: Enable the feature on different ports.
110     return false;
111 }
112 #endif
113
114 // Singleton client used for layers on which clearClient has been called.
115 class EmptyGraphicsLayerClient final : public GraphicsLayerClient {
116     WTF_MAKE_FAST_ALLOCATED;
117 public:
118     static EmptyGraphicsLayerClient& singleton();
119 };
120
121 EmptyGraphicsLayerClient& EmptyGraphicsLayerClient::singleton()
122 {
123     static NeverDestroyed<EmptyGraphicsLayerClient> client;
124     return client;
125 }
126
127 GraphicsLayer::GraphicsLayer(Type type, GraphicsLayerClient& layerClient)
128     : m_client(&layerClient)
129     , m_type(type)
130     , m_beingDestroyed(false)
131     , m_contentsOpaque(false)
132     , m_supportsSubpixelAntialiasedText(false)
133     , m_preserves3D(false)
134     , m_backfaceVisibility(true)
135     , m_masksToBounds(false)
136     , m_drawsContent(false)
137     , m_contentsVisible(true)
138     , m_acceleratesDrawing(false)
139     , m_usesDisplayListDrawing(false)
140     , m_appliesPageScale(false)
141     , m_showDebugBorder(false)
142     , m_showRepaintCounter(false)
143     , m_isMaskLayer(false)
144     , m_isTrackingDisplayListReplay(false)
145     , m_userInteractionEnabled(true)
146     , m_canDetachBackingStore(true)
147 {
148 #ifndef NDEBUG
149     client().verifyNotPainting();
150 #endif
151 }
152
153 GraphicsLayer::~GraphicsLayer()
154 {
155     resetTrackedRepaints();
156     ASSERT(!m_parent); // willBeDestroyed should have been called already.
157 }
158
159 void GraphicsLayer::unparentAndClear(RefPtr<GraphicsLayer>& layer)
160 {
161     if (layer) {
162         layer->removeFromParent();
163         layer->clearClient();
164         layer = nullptr;
165     }
166 }
167
168 void GraphicsLayer::clear(RefPtr<GraphicsLayer>& layer)
169 {
170     if (layer) {
171         layer->clearClient();
172         layer = nullptr;
173     }
174 }
175
176 void GraphicsLayer::willBeDestroyed()
177 {
178     m_beingDestroyed = true;
179 #ifndef NDEBUG
180     client().verifyNotPainting();
181 #endif
182     if (m_replicaLayer)
183         m_replicaLayer->setReplicatedLayer(nullptr);
184
185     if (m_replicatedLayer)
186         m_replicatedLayer->setReplicatedByLayer(nullptr);
187
188     if (m_maskLayer) {
189         m_maskLayer->setParent(nullptr);
190         m_maskLayer->setIsMaskLayer(false);
191     }
192
193     removeAllChildren();
194     removeFromParent();
195 }
196
197 void GraphicsLayer::clearClient()
198 {
199     m_client = &EmptyGraphicsLayerClient::singleton();
200 }
201
202 void GraphicsLayer::setClient(GraphicsLayerClient& client)
203 {
204     m_client = &client;
205 }
206
207 void GraphicsLayer::setParent(GraphicsLayer* layer)
208 {
209     ASSERT(!layer || !layer->hasAncestor(this));
210     m_parent = layer;
211 }
212
213 bool GraphicsLayer::hasAncestor(GraphicsLayer* ancestor) const
214 {
215     for (GraphicsLayer* curr = parent(); curr; curr = curr->parent()) {
216         if (curr == ancestor)
217             return true;
218     }
219     
220     return false;
221 }
222
223 bool GraphicsLayer::setChildren(Vector<Ref<GraphicsLayer>>&& newChildren)
224 {
225     // If the contents of the arrays are the same, nothing to do.
226     if (newChildren == m_children)
227         return false;
228
229     removeAllChildren();
230
231     size_t listSize = newChildren.size();
232     for (size_t i = 0; i < listSize; ++i)
233         addChild(WTFMove(newChildren[i]));
234     
235     return true;
236 }
237
238 void GraphicsLayer::addChild(Ref<GraphicsLayer>&& childLayer)
239 {
240     ASSERT(childLayer.ptr() != this);
241     
242     childLayer->removeFromParent();
243     childLayer->setParent(this);
244     m_children.append(WTFMove(childLayer));
245 }
246
247 void GraphicsLayer::addChildAtIndex(Ref<GraphicsLayer>&& childLayer, int index)
248 {
249     ASSERT(childLayer.ptr() != this);
250
251     childLayer->removeFromParent();
252     childLayer->setParent(this);
253     m_children.insert(index, WTFMove(childLayer));
254 }
255
256 void GraphicsLayer::addChildBelow(Ref<GraphicsLayer>&& childLayer, GraphicsLayer* sibling)
257 {
258     ASSERT(childLayer.ptr() != this);
259     childLayer->removeFromParent();
260
261     childLayer->setParent(this);
262
263     for (unsigned i = 0; i < m_children.size(); i++) {
264         if (sibling == m_children[i].ptr()) {
265             m_children.insert(i, WTFMove(childLayer));
266             return;
267         }
268     }
269
270     m_children.append(WTFMove(childLayer));
271 }
272
273 void GraphicsLayer::addChildAbove(Ref<GraphicsLayer>&& childLayer, GraphicsLayer* sibling)
274 {
275     childLayer->removeFromParent();
276     ASSERT(childLayer.ptr() != this);
277
278     childLayer->setParent(this);
279
280     for (unsigned i = 0; i < m_children.size(); i++) {
281         if (sibling == m_children[i].ptr()) {
282             m_children.insert(i + 1, WTFMove(childLayer));
283             return;
284         }
285     }
286
287     m_children.append(WTFMove(childLayer));
288 }
289
290 bool GraphicsLayer::replaceChild(GraphicsLayer* oldChild, Ref<GraphicsLayer>&& newChild)
291 {
292     ASSERT(!newChild->parent());
293     
294     GraphicsLayer* rawNewChild = newChild.ptr();
295
296     bool found = false;
297     for (unsigned i = 0; i < m_children.size(); i++) {
298         if (oldChild == m_children[i].ptr()) {
299             m_children[i] = WTFMove(newChild);
300             found = true;
301             break;
302         }
303     }
304     if (found) {
305         oldChild->setParent(nullptr);
306
307         rawNewChild->removeFromParent();
308         rawNewChild->setParent(this);
309         return true;
310     }
311     return false;
312 }
313
314 void GraphicsLayer::removeAllChildren()
315 {
316     while (m_children.size()) {
317         GraphicsLayer* curLayer = m_children[0].ptr();
318         ASSERT(curLayer->parent());
319         curLayer->removeFromParent();
320         // curLayer may be destroyed here.
321     }
322 }
323
324 void GraphicsLayer::removeFromParent()
325 {
326     if (m_parent) {
327         GraphicsLayer* parent = m_parent;
328         setParent(nullptr);
329         parent->m_children.removeFirstMatching([this](auto& layer) {
330             return layer.ptr() == this;
331         });
332         // |this| may be destroyed here.
333     }
334 }
335
336 const TransformationMatrix& GraphicsLayer::transform() const
337 {
338     return m_transform ? *m_transform : TransformationMatrix::identity;
339 }
340
341 void GraphicsLayer::setTransform(const TransformationMatrix& matrix)
342 {
343     if (m_transform)
344         *m_transform = matrix;
345     else
346         m_transform = makeUnique<TransformationMatrix>(matrix);
347 }
348
349 const TransformationMatrix& GraphicsLayer::childrenTransform() const
350 {
351     return m_childrenTransform ? *m_childrenTransform : TransformationMatrix::identity;
352 }
353
354 void GraphicsLayer::setChildrenTransform(const TransformationMatrix& matrix)
355 {
356     if (m_childrenTransform)
357         *m_childrenTransform = matrix;
358     else
359         m_childrenTransform = makeUnique<TransformationMatrix>(matrix);
360 }
361
362 void GraphicsLayer::setMaskLayer(RefPtr<GraphicsLayer>&& layer)
363 {
364     if (layer == m_maskLayer)
365         return;
366
367     if (layer) {
368         layer->removeFromParent();
369         layer->setParent(this);
370         layer->setIsMaskLayer(true);
371     } else if (m_maskLayer) {
372         m_maskLayer->setParent(nullptr);
373         m_maskLayer->setIsMaskLayer(false);
374     }
375     
376     m_maskLayer = WTFMove(layer);
377 }
378
379 Path GraphicsLayer::shapeLayerPath() const
380 {
381 #if USE(CA)
382     return m_shapeLayerPath;
383 #else
384     return Path();
385 #endif
386 }
387
388 void GraphicsLayer::setShapeLayerPath(const Path& path)
389 {
390 #if USE(CA)
391     m_shapeLayerPath = path;
392 #else
393     UNUSED_PARAM(path);
394 #endif
395 }
396
397 WindRule GraphicsLayer::shapeLayerWindRule() const
398 {
399 #if USE(CA)
400     return m_shapeLayerWindRule;
401 #else
402     return WindRule::NonZero;
403 #endif
404 }
405
406 void GraphicsLayer::setShapeLayerWindRule(WindRule windRule)
407 {
408 #if USE(CA)
409     m_shapeLayerWindRule = windRule;
410 #else
411     UNUSED_PARAM(windRule);
412 #endif
413 }
414
415 void GraphicsLayer::setEventRegion(EventRegion&& eventRegion)
416 {
417     m_eventRegion = WTFMove(eventRegion);
418 }
419
420 void GraphicsLayer::noteDeviceOrPageScaleFactorChangedIncludingDescendants()
421 {
422     deviceOrPageScaleFactorChanged();
423
424     if (m_maskLayer)
425         m_maskLayer->deviceOrPageScaleFactorChanged();
426
427     if (m_replicaLayer)
428         m_replicaLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
429
430     for (auto& layer : children())
431         layer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
432 }
433
434 void GraphicsLayer::setIsInWindow(bool inWindow)
435 {
436     if (TiledBacking* tiledBacking = this->tiledBacking())
437         tiledBacking->setIsInWindow(inWindow);
438 }
439
440 void GraphicsLayer::setReplicatedByLayer(RefPtr<GraphicsLayer>&& layer)
441 {
442     if (m_replicaLayer == layer)
443         return;
444
445     if (m_replicaLayer)
446         m_replicaLayer->setReplicatedLayer(nullptr);
447
448     if (layer)
449         layer->setReplicatedLayer(this);
450
451     m_replicaLayer = WTFMove(layer);
452 }
453
454 void GraphicsLayer::setOffsetFromRenderer(const FloatSize& offset, ShouldSetNeedsDisplay shouldSetNeedsDisplay)
455 {
456     if (offset == m_offsetFromRenderer)
457         return;
458
459     m_offsetFromRenderer = offset;
460
461     // If the compositing layer offset changes, we need to repaint.
462     if (shouldSetNeedsDisplay == SetNeedsDisplay)
463         setNeedsDisplay();
464 }
465
466 void GraphicsLayer::setScrollOffset(const ScrollOffset& offset, ShouldSetNeedsDisplay shouldSetNeedsDisplay)
467 {
468     if (offset == m_scrollOffset)
469         return;
470
471     m_scrollOffset = offset;
472
473     // If the compositing layer offset changes, we need to repaint.
474     if (shouldSetNeedsDisplay == SetNeedsDisplay)
475         setNeedsDisplay();
476 }
477
478 void GraphicsLayer::setSize(const FloatSize& size)
479 {
480     if (size == m_size)
481         return;
482     
483     m_size = size;
484
485     if (shouldRepaintOnSizeChange())
486         setNeedsDisplay();
487 }
488
489 void GraphicsLayer::setBackgroundColor(const Color& color)
490 {
491     m_backgroundColor = color;
492 }
493
494 void GraphicsLayer::setPaintingPhase(OptionSet<GraphicsLayerPaintingPhase> phase)
495 {
496     if (phase == m_paintingPhase)
497         return;
498
499     setNeedsDisplay();
500     m_paintingPhase = phase;
501 }
502
503 void GraphicsLayer::paintGraphicsLayerContents(GraphicsContext& context, const FloatRect& clip, GraphicsLayerPaintBehavior layerPaintBehavior)
504 {
505     FloatSize offset = offsetFromRenderer() - toFloatSize(scrollOffset());
506     context.translate(-offset);
507
508     FloatRect clipRect(clip);
509     clipRect.move(offset);
510
511     client().paintContents(this, context, m_paintingPhase, clipRect, layerPaintBehavior);
512 }
513
514 FloatRect GraphicsLayer::adjustCoverageRectForMovement(const FloatRect& coverageRect, const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect)
515 {
516     // If the old visible rect is empty, we have no information about how the visible area is changing
517     // (maybe the layer was just created), so don't attempt to expand. Also don't attempt to expand if the rects don't overlap.
518     if (previousVisibleRect.isEmpty() || !currentVisibleRect.intersects(previousVisibleRect))
519         return unionRect(coverageRect, currentVisibleRect);
520
521     const float paddingMultiplier = 2;
522
523     float leftEdgeDelta = paddingMultiplier * (currentVisibleRect.x() - previousVisibleRect.x());
524     float rightEdgeDelta = paddingMultiplier * (currentVisibleRect.maxX() - previousVisibleRect.maxX());
525
526     float topEdgeDelta = paddingMultiplier * (currentVisibleRect.y() - previousVisibleRect.y());
527     float bottomEdgeDelta = paddingMultiplier * (currentVisibleRect.maxY() - previousVisibleRect.maxY());
528     
529     FloatRect expandedRect = currentVisibleRect;
530
531     // More exposed on left side.
532     if (leftEdgeDelta < 0) {
533         float newLeft = expandedRect.x() + leftEdgeDelta;
534         // Pad to the left, but don't reduce padding that's already in the backing store (since we're still exposing to the left).
535         if (newLeft < previousVisibleRect.x())
536             expandedRect.shiftXEdgeTo(newLeft);
537         else
538             expandedRect.shiftXEdgeTo(previousVisibleRect.x());
539     }
540
541     // More exposed on right.
542     if (rightEdgeDelta > 0) {
543         float newRight = expandedRect.maxX() + rightEdgeDelta;
544         // Pad to the right, but don't reduce padding that's already in the backing store (since we're still exposing to the right).
545         if (newRight > previousVisibleRect.maxX())
546             expandedRect.setWidth(newRight - expandedRect.x());
547         else
548             expandedRect.setWidth(previousVisibleRect.maxX() - expandedRect.x());
549     }
550
551     // More exposed at top.
552     if (topEdgeDelta < 0) {
553         float newTop = expandedRect.y() + topEdgeDelta;
554         if (newTop < previousVisibleRect.y())
555             expandedRect.shiftYEdgeTo(newTop);
556         else
557             expandedRect.shiftYEdgeTo(previousVisibleRect.y());
558     }
559
560     // More exposed on bottom.
561     if (bottomEdgeDelta > 0) {
562         float newBottom = expandedRect.maxY() + bottomEdgeDelta;
563         if (newBottom > previousVisibleRect.maxY())
564             expandedRect.setHeight(newBottom - expandedRect.y());
565         else
566             expandedRect.setHeight(previousVisibleRect.maxY() - expandedRect.y());
567     }
568     
569     return unionRect(coverageRect, expandedRect);
570 }
571
572 String GraphicsLayer::animationNameForTransition(AnimatedPropertyID property)
573 {
574     // | is not a valid identifier character in CSS, so this can never conflict with a keyframe identifier.
575     StringBuilder id;
576     id.appendLiteral("-|transition");
577     id.appendNumber(static_cast<int>(property));
578     id.append('-');
579     return id.toString();
580 }
581
582 void GraphicsLayer::suspendAnimations(MonotonicTime)
583 {
584 }
585
586 void GraphicsLayer::resumeAnimations()
587 {
588 }
589
590 void GraphicsLayer::getDebugBorderInfo(Color& color, float& width) const
591 {
592     width = 2;
593
594     if (needsBackdrop()) {
595         color = Color(255, 0, 255, 128); // has backdrop: magenta
596         width = 12;
597         return;
598     }
599     
600     if (drawsContent()) {
601         if (tiledBacking()) {
602             color = Color(255, 128, 0, 128); // tiled layer: orange
603             return;
604         }
605
606         color = Color(0, 128, 32, 128); // normal layer: green
607         return;
608     }
609
610     if (usesContentsLayer()) {
611         color = Color(0, 64, 128, 150); // non-painting layer with contents: blue
612         width = 8;
613         return;
614     }
615     
616     if (masksToBounds()) {
617         color = Color(128, 255, 255, 48); // masking layer: pale blue
618         width = 16;
619         return;
620     }
621
622     color = Color(255, 255, 0, 192); // container: yellow
623 }
624
625 void GraphicsLayer::updateDebugIndicators()
626 {
627     if (!isShowingDebugBorder())
628         return;
629
630     Color borderColor;
631     float width = 0;
632     getDebugBorderInfo(borderColor, width);
633     setDebugBorder(borderColor, width);
634 }
635
636 void GraphicsLayer::setZPosition(float position)
637 {
638     m_zPosition = position;
639 }
640
641 float GraphicsLayer::accumulatedOpacity() const
642 {
643     if (!preserves3D())
644         return 1;
645         
646     return m_opacity * (parent() ? parent()->accumulatedOpacity() : 1);
647 }
648
649 void GraphicsLayer::distributeOpacity(float accumulatedOpacity)
650 {
651     // If this is a transform layer we need to distribute our opacity to all our children
652     
653     // Incoming accumulatedOpacity is the contribution from our parent(s). We mutiply this by our own
654     // opacity to get the total contribution
655     accumulatedOpacity *= m_opacity;
656     
657     setOpacityInternal(accumulatedOpacity);
658     
659     if (preserves3D()) {
660         for (auto& layer : children())
661             layer->distributeOpacity(accumulatedOpacity);
662     }
663 }
664
665 static inline const FilterOperations& filterOperationsAt(const KeyframeValueList& valueList, size_t index)
666 {
667     return static_cast<const FilterAnimationValue&>(valueList.at(index)).value();
668 }
669
670 int GraphicsLayer::validateFilterOperations(const KeyframeValueList& valueList)
671 {
672 #if ENABLE(FILTERS_LEVEL_2)
673     ASSERT(valueList.property() == AnimatedPropertyFilter || valueList.property() == AnimatedPropertyWebkitBackdropFilter);
674 #else
675     ASSERT(valueList.property() == AnimatedPropertyFilter);
676 #endif
677
678     if (valueList.size() < 2)
679         return -1;
680
681     // Empty filters match anything, so find the first non-empty entry as the reference
682     size_t firstIndex = 0;
683     for ( ; firstIndex < valueList.size(); ++firstIndex) {
684         if (!filterOperationsAt(valueList, firstIndex).operations().isEmpty())
685             break;
686     }
687
688     if (firstIndex >= valueList.size())
689         return -1;
690
691     const FilterOperations& firstVal = filterOperationsAt(valueList, firstIndex);
692     
693     for (size_t i = firstIndex + 1; i < valueList.size(); ++i) {
694         const FilterOperations& val = filterOperationsAt(valueList, i);
695         
696         // An emtpy filter list matches anything.
697         if (val.operations().isEmpty())
698             continue;
699         
700         if (!firstVal.operationsMatch(val))
701             return -1;
702     }
703     
704     return firstIndex;
705 }
706
707 // An "invalid" list is one whose functions don't match, and therefore has to be animated as a Matrix
708 // The hasBigRotation flag will always return false if isValid is false. Otherwise hasBigRotation is 
709 // true if the rotation between any two keyframes is >= 180 degrees.
710
711 static inline const TransformOperations& operationsAt(const KeyframeValueList& valueList, size_t index)
712 {
713     return static_cast<const TransformAnimationValue&>(valueList.at(index)).value();
714 }
715
716 int GraphicsLayer::validateTransformOperations(const KeyframeValueList& valueList, bool& hasBigRotation)
717 {
718     ASSERT(valueList.property() == AnimatedPropertyTransform);
719
720     hasBigRotation = false;
721     
722     if (valueList.size() < 2)
723         return -1;
724     
725     // Empty transforms match anything, so find the first non-empty entry as the reference.
726     size_t firstIndex = 0;
727     for ( ; firstIndex < valueList.size(); ++firstIndex) {
728         if (!operationsAt(valueList, firstIndex).operations().isEmpty())
729             break;
730     }
731     
732     if (firstIndex >= valueList.size())
733         return -1;
734         
735     const TransformOperations& firstVal = operationsAt(valueList, firstIndex);
736     
737     // See if the keyframes are valid.
738     for (size_t i = firstIndex + 1; i < valueList.size(); ++i) {
739         const TransformOperations& val = operationsAt(valueList, i);
740         
741         // An empty transform list matches anything.
742         if (val.operations().isEmpty())
743             continue;
744             
745         if (!firstVal.operationsMatch(val))
746             return -1;
747     }
748
749     // Keyframes are valid, check for big rotations.    
750     double lastRotationAngle = 0.0;
751     double maxRotationAngle = -1.0;
752         
753     for (size_t j = 0; j < firstVal.operations().size(); ++j) {
754         TransformOperation::OperationType type = firstVal.operations().at(j)->type();
755         
756         // if this is a rotation entry, we need to see if any angle differences are >= 180 deg
757         if (type == TransformOperation::ROTATE_X ||
758             type == TransformOperation::ROTATE_Y ||
759             type == TransformOperation::ROTATE_Z ||
760             type == TransformOperation::ROTATE_3D) {
761             lastRotationAngle = downcast<RotateTransformOperation>(*firstVal.operations().at(j)).angle();
762             
763             if (maxRotationAngle < 0)
764                 maxRotationAngle = fabs(lastRotationAngle);
765             
766             for (size_t i = firstIndex + 1; i < valueList.size(); ++i) {
767                 const TransformOperations& val = operationsAt(valueList, i);
768                 double rotationAngle = val.operations().isEmpty() ? 0 : downcast<RotateTransformOperation>(*val.operations().at(j)).angle();
769                 double diffAngle = fabs(rotationAngle - lastRotationAngle);
770                 if (diffAngle > maxRotationAngle)
771                     maxRotationAngle = diffAngle;
772                 lastRotationAngle = rotationAngle;
773             }
774         }
775     }
776     
777     hasBigRotation = maxRotationAngle >= 180.0;
778     
779     return firstIndex;
780 }
781
782 double GraphicsLayer::backingStoreMemoryEstimate() const
783 {
784     if (!drawsContent())
785         return 0;
786     
787     // Effects of page and device scale are ignored; subclasses should override to take these into account.
788     return static_cast<double>(4 * size().width()) * size().height();
789 }
790
791 void GraphicsLayer::resetTrackedRepaints()
792 {
793     repaintRectMap().remove(this);
794 }
795
796 void GraphicsLayer::addRepaintRect(const FloatRect& repaintRect)
797 {
798     if (!client().isTrackingRepaints())
799         return;
800
801     FloatRect largestRepaintRect(FloatPoint(), m_size);
802     largestRepaintRect.intersect(repaintRect);
803     RepaintMap::iterator repaintIt = repaintRectMap().find(this);
804     if (repaintIt == repaintRectMap().end()) {
805         Vector<FloatRect> repaintRects;
806         repaintRects.append(largestRepaintRect);
807         repaintRectMap().set(this, repaintRects);
808     } else {
809         Vector<FloatRect>& repaintRects = repaintIt->value;
810         repaintRects.append(largestRepaintRect);
811     }
812 }
813
814 void GraphicsLayer::traverse(GraphicsLayer& layer, const WTF::Function<void (GraphicsLayer&)>& traversalFunc)
815 {
816     traversalFunc(layer);
817
818     for (auto& childLayer : layer.children())
819         traverse(childLayer.get(), traversalFunc);
820
821     if (auto* replicaLayer = layer.replicaLayer())
822         traverse(*replicaLayer, traversalFunc);
823
824     if (auto* maskLayer = layer.maskLayer())
825         traverse(*maskLayer, traversalFunc);
826 }
827
828 GraphicsLayer::EmbeddedViewID GraphicsLayer::nextEmbeddedViewID()
829 {
830     static GraphicsLayer::EmbeddedViewID nextEmbeddedViewID;
831     return ++nextEmbeddedViewID;
832 }
833
834 void GraphicsLayer::dumpLayer(TextStream& ts, LayerTreeAsTextBehavior behavior) const
835 {
836     ts << indent << "(" << "GraphicsLayer";
837
838     if (behavior & LayerTreeAsTextDebug) {
839         ts << " " << static_cast<void*>(const_cast<GraphicsLayer*>(this));
840         ts << " \"" << m_name << "\"";
841     }
842
843     ts << "\n";
844     dumpProperties(ts, behavior);
845     ts << indent << ")\n";
846 }
847
848 static void dumpChildren(TextStream& ts, const Vector<Ref<GraphicsLayer>>& children, unsigned& totalChildCount, LayerTreeAsTextBehavior behavior)
849 {
850     totalChildCount += children.size();
851     for (auto& child : children) {
852         if ((behavior & LayerTreeAsTextDebug) || !child->client().shouldSkipLayerInDump(child.ptr(), behavior)) {
853             TextStream::IndentScope indentScope(ts);
854             child->dumpLayer(ts, behavior);
855             continue;
856         }
857
858         totalChildCount--;
859         dumpChildren(ts, child->children(), totalChildCount, behavior);
860     }
861 }
862
863 void GraphicsLayer::dumpProperties(TextStream& ts, LayerTreeAsTextBehavior behavior) const
864 {
865     TextStream::IndentScope indentScope(ts);
866     if (!m_offsetFromRenderer.isZero())
867         ts << indent << "(offsetFromRenderer " << m_offsetFromRenderer << ")\n";
868
869     if (!m_scrollOffset.isZero())
870         ts << indent << "(scrollOffset " << m_scrollOffset << ")\n";
871
872     if (m_position != FloatPoint())
873         ts << indent << "(position " << m_position.x() << " " << m_position.y() << ")\n";
874
875     if (m_approximatePosition)
876         ts << indent << "(approximate position " << m_approximatePosition.value().x() << " " << m_approximatePosition.value().y() << ")\n";
877
878     if (m_boundsOrigin != FloatPoint())
879         ts << indent << "(bounds origin " << m_boundsOrigin.x() << " " << m_boundsOrigin.y() << ")\n";
880
881     if (m_anchorPoint != FloatPoint3D(0.5f, 0.5f, 0)) {
882         ts << indent << "(anchor " << m_anchorPoint.x() << " " << m_anchorPoint.y();
883         if (m_anchorPoint.z())
884             ts << " " << m_anchorPoint.z();
885         ts << ")\n";
886     }
887
888     if (m_size != IntSize())
889         ts << indent << "(bounds " << m_size.width() << " " << m_size.height() << ")\n";
890
891     if (m_opacity != 1)
892         ts << indent << "(opacity " << m_opacity << ")\n";
893
894 #if ENABLE(CSS_COMPOSITING)
895     if (m_blendMode != BlendMode::Normal)
896         ts << indent << "(blendMode " << compositeOperatorName(CompositeSourceOver, m_blendMode) << ")\n";
897 #endif
898
899     if (type() == Type::Normal && tiledBacking())
900         ts << indent << "(usingTiledLayer 1)\n";
901
902     bool needsIOSDumpRenderTreeMainFrameRenderViewLayerIsAlwaysOpaqueHack = client().needsIOSDumpRenderTreeMainFrameRenderViewLayerIsAlwaysOpaqueHack(*this);
903     if (m_contentsOpaque || needsIOSDumpRenderTreeMainFrameRenderViewLayerIsAlwaysOpaqueHack)
904         ts << indent << "(contentsOpaque " << (m_contentsOpaque || needsIOSDumpRenderTreeMainFrameRenderViewLayerIsAlwaysOpaqueHack) << ")\n";
905
906     if (m_supportsSubpixelAntialiasedText)
907         ts << indent << "(supports subpixel antialiased text " << m_supportsSubpixelAntialiasedText << ")\n";
908
909     if (m_masksToBounds && behavior & LayerTreeAsTextIncludeClipping)
910         ts << indent << "(clips " << m_masksToBounds << ")\n";
911
912     if (m_preserves3D)
913         ts << indent << "(preserves3D " << m_preserves3D << ")\n";
914
915     if (m_drawsContent && client().shouldDumpPropertyForLayer(this, "drawsContent", behavior))
916         ts << indent << "(drawsContent " << m_drawsContent << ")\n";
917
918     if (!m_contentsVisible)
919         ts << indent << "(contentsVisible " << m_contentsVisible << ")\n";
920
921     if (!m_backfaceVisibility)
922         ts << indent << "(backfaceVisibility " << (m_backfaceVisibility ? "visible" : "hidden") << ")\n";
923
924     if (behavior & LayerTreeAsTextDebug)
925         ts << indent << "(primary-layer-id " << primaryLayerID() << ")\n";
926
927     if (m_backgroundColor.isValid() && client().shouldDumpPropertyForLayer(this, "backgroundColor", behavior))
928         ts << indent << "(backgroundColor " << m_backgroundColor.nameForRenderTreeAsText() << ")\n";
929
930     if (behavior & LayerTreeAsTextIncludeAcceleratesDrawing && m_acceleratesDrawing)
931         ts << indent << "(acceleratesDrawing " << m_acceleratesDrawing << ")\n";
932
933     if (behavior & LayerTreeAsTextIncludeBackingStoreAttached)
934         ts << indent << "(backingStoreAttached " << backingStoreAttachedForTesting() << ")\n";
935
936     if (m_transform && !m_transform->isIdentity()) {
937         ts << indent << "(transform ";
938         ts << "[" << m_transform->m11() << " " << m_transform->m12() << " " << m_transform->m13() << " " << m_transform->m14() << "] ";
939         ts << "[" << m_transform->m21() << " " << m_transform->m22() << " " << m_transform->m23() << " " << m_transform->m24() << "] ";
940         ts << "[" << m_transform->m31() << " " << m_transform->m32() << " " << m_transform->m33() << " " << m_transform->m34() << "] ";
941         ts << "[" << m_transform->m41() << " " << m_transform->m42() << " " << m_transform->m43() << " " << m_transform->m44() << "])\n";
942     }
943
944     // Avoid dumping the sublayer transform on the root layer, because it's used for geometry flipping, whose behavior
945     // differs between platforms.
946     if (parent() && m_childrenTransform && !m_childrenTransform->isIdentity()) {
947         ts << indent << "(childrenTransform ";
948         ts << "[" << m_childrenTransform->m11() << " " << m_childrenTransform->m12() << " " << m_childrenTransform->m13() << " " << m_childrenTransform->m14() << "] ";
949         ts << "[" << m_childrenTransform->m21() << " " << m_childrenTransform->m22() << " " << m_childrenTransform->m23() << " " << m_childrenTransform->m24() << "] ";
950         ts << "[" << m_childrenTransform->m31() << " " << m_childrenTransform->m32() << " " << m_childrenTransform->m33() << " " << m_childrenTransform->m34() << "] ";
951         ts << "[" << m_childrenTransform->m41() << " " << m_childrenTransform->m42() << " " << m_childrenTransform->m43() << " " << m_childrenTransform->m44() << "])\n";
952     }
953
954     if (m_maskLayer) {
955         ts << indent << "(mask layer";
956         if (behavior & LayerTreeAsTextDebug)
957             ts << " " << m_maskLayer;
958         ts << ")\n";
959
960         TextStream::IndentScope indentScope(ts);
961         m_maskLayer->dumpLayer(ts, behavior);
962     }
963
964     if (m_replicaLayer) {
965         ts << indent << "(replica layer";
966         if (behavior & LayerTreeAsTextDebug)
967             ts << " " << m_replicaLayer;
968         ts << ")\n";
969
970         TextStream::IndentScope indentScope(ts);
971         m_replicaLayer->dumpLayer(ts, behavior);
972     }
973
974     if (m_replicatedLayer) {
975         ts << indent << "(replicated layer";
976         if (behavior & LayerTreeAsTextDebug)
977             ts << " " << m_replicatedLayer;
978         ts << ")\n";
979     }
980
981     if (behavior & LayerTreeAsTextIncludeRepaintRects && repaintRectMap().contains(this) && !repaintRectMap().get(this).isEmpty() && client().shouldDumpPropertyForLayer(this, "repaintRects", behavior)) {
982         ts << indent << "(repaint rects\n";
983         for (size_t i = 0; i < repaintRectMap().get(this).size(); ++i) {
984             if (repaintRectMap().get(this)[i].isEmpty())
985                 continue;
986
987             TextStream::IndentScope indentScope(ts);
988             ts << indent << "(rect ";
989             ts << repaintRectMap().get(this)[i].x() << " ";
990             ts << repaintRectMap().get(this)[i].y() << " ";
991             ts << repaintRectMap().get(this)[i].width() << " ";
992             ts << repaintRectMap().get(this)[i].height();
993             ts << ")\n";
994         }
995         ts << indent << ")\n";
996     }
997
998     if (behavior & LayerTreeAsTextIncludeEventRegion && !m_eventRegion.isEmpty()) {
999         ts << indent << "(event region" << m_eventRegion;
1000         ts << indent << ")\n";
1001     }
1002
1003     if (behavior & LayerTreeAsTextIncludePaintingPhases && paintingPhase())
1004         ts << indent << "(paintingPhases " << paintingPhase() << ")\n";
1005
1006     dumpAdditionalProperties(ts, behavior);
1007     
1008     if (m_children.size()) {
1009         TextStream childrenStream;
1010         
1011         childrenStream.increaseIndent(ts.indent());
1012         unsigned totalChildCount = 0;
1013         dumpChildren(childrenStream, m_children, totalChildCount, behavior);
1014
1015         if (totalChildCount) {
1016             ts << indent << "(children " << totalChildCount << "\n";
1017             ts << childrenStream.release();
1018             ts << indent << ")\n";
1019         }
1020     }
1021 }
1022
1023 TextStream& operator<<(TextStream& ts, const Vector<GraphicsLayer::PlatformLayerID>& layers)
1024 {
1025     for (size_t i = 0; i < layers.size(); ++i) {
1026         if (i)
1027             ts << " ";
1028         ts << layers[i];
1029     }
1030
1031     return ts;
1032 }
1033
1034 TextStream& operator<<(TextStream& ts, GraphicsLayerPaintingPhase phase)
1035 {
1036     switch (phase) {
1037     case GraphicsLayerPaintingPhase::Background: ts << "background"; break;
1038     case GraphicsLayerPaintingPhase::Foreground: ts << "foreground"; break;
1039     case GraphicsLayerPaintingPhase::Mask: ts << "mask"; break;
1040     case GraphicsLayerPaintingPhase::ClipPath: ts << "clip-path"; break;
1041     case GraphicsLayerPaintingPhase::OverflowContents: ts << "overflow-contents"; break;
1042     case GraphicsLayerPaintingPhase::CompositedScroll: ts << "composited-scroll"; break;
1043     case GraphicsLayerPaintingPhase::ChildClippingMask: ts << "child-clipping-mask"; break;
1044     }
1045
1046     return ts;
1047 }
1048
1049 TextStream& operator<<(TextStream& ts, const GraphicsLayer::CustomAppearance& customAppearance)
1050 {
1051     switch (customAppearance) {
1052     case GraphicsLayer::CustomAppearance::None: ts << "none"; break;
1053     case GraphicsLayer::CustomAppearance::ScrollingOverhang: ts << "scrolling-overhang"; break;
1054     case GraphicsLayer::CustomAppearance::ScrollingShadow: ts << "scrolling-shadow"; break;
1055     case GraphicsLayer::CustomAppearance::LightBackdrop: ts << "light-backdrop"; break;
1056     case GraphicsLayer::CustomAppearance::DarkBackdrop: ts << "dark-backdrop"; break;
1057     }
1058     return ts;
1059 }
1060
1061 String GraphicsLayer::layerTreeAsText(LayerTreeAsTextBehavior behavior) const
1062 {
1063     TextStream ts(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect);
1064
1065     dumpLayer(ts, behavior);
1066     return ts.release();
1067 }
1068
1069 } // namespace WebCore
1070
1071 #if ENABLE(TREE_DEBUGGING)
1072 void showGraphicsLayerTree(const WebCore::GraphicsLayer* layer)
1073 {
1074     if (!layer)
1075         return;
1076
1077     String output = layer->layerTreeAsText(WebCore::LayerTreeAsTextShowAll);
1078     WTFLogAlways("%s\n", output.utf8().data());
1079 }
1080 #endif