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