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