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