1/*
2 * Copyright (C) 2011 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 COMPUTER, 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#if USE(ACCELERATED_COMPOSITING)
29
30#include "PlatformCALayer.h"
31
32#include "Font.h"
33#include "GraphicsContext.h"
34#include "PlatformCALayerWinInternal.h"
35#include "WKCACFLayerRenderer.h"
36#include <QuartzCore/CACFAnimation.h>
37#include <QuartzCore/CACFContext.h>
38#include <QuartzCore/CACFLayer.h>
39#include <wtf/CurrentTime.h>
40#include <wtf/text/CString.h>
41
42using namespace WebCore;
43
44bool PlatformCALayer::isValueFunctionSupported()
45{
46 return true;
47}
48
49void PlatformCALayer::setOwner(PlatformCALayerClient* owner)
50{
51 m_owner = owner;
52}
53
54static CFStringRef toCACFLayerType(PlatformCALayer::LayerType type)
55{
56 return (type == PlatformCALayer::LayerTypeTransformLayer) ? kCACFTransformLayer : kCACFLayer;
57}
58
59static CFStringRef toCACFFilterType(PlatformCALayer::FilterType type)
60{
61 switch (type) {
62 case PlatformCALayer::Linear: return kCACFFilterLinear;
63 case PlatformCALayer::Nearest: return kCACFFilterNearest;
64 case PlatformCALayer::Trilinear: return kCACFFilterTrilinear;
65 default: return 0;
66 }
67}
68
69static WKCACFLayerRenderer* rendererForLayer(const PlatformCALayer* layer)
70{
71 // We need the WKCACFLayerRenderer associated with this layer, which is stored in the UserData of the CACFContext
72 CACFContextRef context = CACFLayerGetContext(layer->platformLayer());
73 if (!context)
74 return 0;
75
76 WKCACFLayerRenderer* renderer = static_cast<WKCACFLayerRenderer*>(CACFContextGetUserData(context));
77 ASSERT(renderer);
78 return renderer;
79}
80
81static PlatformCALayerWinInternal* intern(const PlatformCALayer* layer)
82{
83 return static_cast<PlatformCALayerWinInternal*>(CACFLayerGetUserData(layer->platformLayer()));
84}
85
86static PlatformCALayerWinInternal* intern(void* layer)
87{
88 return static_cast<PlatformCALayerWinInternal*>(CACFLayerGetUserData(static_cast<CACFLayerRef>(layer)));
89}
90
91PassRefPtr<PlatformCALayer> PlatformCALayer::create(LayerType layerType, PlatformCALayerClient* owner)
92{
93 return adoptRef(new PlatformCALayer(layerType, 0, owner));
94}
95
96PassRefPtr<PlatformCALayer> PlatformCALayer::create(void* platformLayer, PlatformCALayerClient* owner)
97{
98 return adoptRef(new PlatformCALayer(LayerTypeCustom, static_cast<PlatformLayer*>(platformLayer), owner));
99}
100
101static void displayCallback(CACFLayerRef caLayer, CGContextRef context)
102{
103 ASSERT_ARG(caLayer, CACFLayerGetUserData(caLayer));
104 intern(caLayer)->displayCallback(caLayer, context);
105}
106
107static void layoutSublayersProc(CACFLayerRef caLayer)
108{
109 PlatformCALayer* layer = PlatformCALayer::platformCALayer(caLayer);
110 if (layer && layer->owner())
111 layer->owner()->platformCALayerLayoutSublayersOfLayer(layer);
112}
113
114PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformLayer* layer, PlatformCALayerClient* owner)
115 : m_owner(owner)
116{
117 if (layer) {
118 m_layerType = LayerTypeCustom;
119 m_layer = layer;
120 } else {
121 m_layerType = layerType;
122 m_layer.adoptCF(CACFLayerCreate(toCACFLayerType(layerType)));
123
124 // Create the PlatformCALayerWinInternal object and point to it in the userdata.
125 PlatformCALayerWinInternal* intern = new PlatformCALayerWinInternal(this);
126 CACFLayerSetUserData(m_layer.get(), intern);
127
128 // Set the display callback
129 CACFLayerSetDisplayCallback(m_layer.get(), displayCallback);
130 CACFLayerSetLayoutCallback(m_layer.get(), layoutSublayersProc);
131 }
132}
133
134PlatformCALayer::~PlatformCALayer()
135{
136 // Toss all the kids
137 removeAllSublayers();
138
139 // Get rid of the user data
140 PlatformCALayerWinInternal* layerIntern = intern(this);
141 CACFLayerSetUserData(m_layer.get(), 0);
142
143 delete layerIntern;
144}
145
146PlatformCALayer* PlatformCALayer::platformCALayer(void* platformLayer)
147{
148 if (!platformLayer)
149 return 0;
150
151 PlatformCALayerWinInternal* layerIntern = intern(platformLayer);
152 return layerIntern ? layerIntern->owner() : 0;
153}
154
155PlatformLayer* PlatformCALayer::platformLayer() const
156{
157 return m_layer.get();
158}
159
160PlatformCALayer* PlatformCALayer::rootLayer() const
161{
162 WKCACFLayerRenderer* renderer = rendererForLayer(this);
163 return renderer ? renderer->rootLayer() : 0;
164}
165
166void PlatformCALayer::setNeedsDisplay(const FloatRect* dirtyRect)
167{
168 intern(this)->setNeedsDisplay(dirtyRect);
169}
170
171void PlatformCALayer::setNeedsCommit()
172{
173 WKCACFLayerRenderer* renderer = rendererForLayer(this);
174 if (renderer)
175 renderer->layerTreeDidChange();
176}
177
178void PlatformCALayer::setContentsChanged()
179{
180 // FIXME: There is no equivalent of setContentsChanged in CACF. For now I will
181 // set contents to 0 and then back to its original value to see if that
182 // kicks CACF into redisplaying.
183 RetainPtr<CFTypeRef> contents = CACFLayerGetContents(m_layer.get());
184 CACFLayerSetContents(m_layer.get(), 0);
185 CACFLayerSetContents(m_layer.get(), contents.get());
186 setNeedsCommit();
187}
188
189void PlatformCALayer::setNeedsLayout()
190{
191 if (!m_owner || !m_owner->platformCALayerRespondsToLayoutChanges())
192 return;
193
194 CACFLayerSetNeedsLayout(m_layer.get());
195 setNeedsCommit();
196}
197
198PlatformCALayer* PlatformCALayer::superlayer() const
199{
200 return platformCALayer(CACFLayerGetSuperlayer(m_layer.get()));
201}
202
203void PlatformCALayer::removeFromSuperlayer()
204{
205 CACFLayerRemoveFromSuperlayer(m_layer.get());
206 setNeedsCommit();
207}
208
209void PlatformCALayer::setSublayers(const PlatformCALayerList& list)
210{
211 intern(this)->setSublayers(list);
212}
213
214void PlatformCALayer::removeAllSublayers()
215{
216 intern(this)->removeAllSublayers();
217}
218
219void PlatformCALayer::appendSublayer(PlatformCALayer* layer)
220{
221 // This must be in terms of insertSublayer instead of a direct call so PlatformCALayerInternal can override.
222 insertSublayer(layer, sublayerCount());
223}
224
225void PlatformCALayer::insertSublayer(PlatformCALayer* layer, size_t index)
226{
227 intern(this)->insertSublayer(layer, index);
228}
229
230void PlatformCALayer::replaceSublayer(PlatformCALayer* reference, PlatformCALayer* newLayer)
231{
232 // This must not use direct calls to allow PlatformCALayerInternal to override.
233 ASSERT_ARG(reference, reference);
234 ASSERT_ARG(reference, reference->superlayer() == this);
235
236 if (reference == newLayer)
237 return;
238
239 int referenceIndex = intern(this)->indexOfSublayer(reference);
240 ASSERT(referenceIndex != -1);
241 if (referenceIndex == -1)
242 return;
243
244 reference->removeFromSuperlayer();
245
246 if (newLayer) {
247 newLayer->removeFromSuperlayer();
248 insertSublayer(newLayer, referenceIndex);
249 }
250}
251
252size_t PlatformCALayer::sublayerCount() const
253{
254 return intern(this)->sublayerCount();
255}
256
257void PlatformCALayer::adoptSublayers(PlatformCALayer* source)
258{
259 // Make a list of the sublayers from source
260 PlatformCALayerList sublayers;
261 size_t n = source->sublayerCount();
262 CFArrayRef sourceSublayers = CACFLayerGetSublayers(source->platformLayer());
263
264 for (size_t i = 0; i < n; ++i) {
265 CACFLayerRef layer = static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(sourceSublayers, i)));
266 sublayers.append(platformCALayer(layer));
267 }
268
269 // Use setSublayers() because it properly nulls out the superlayer pointers.
270 setSublayers(sublayers);
271}
272
273void PlatformCALayer::addAnimationForKey(const String& key, PlatformCAAnimation* animation)
274{
275 // Add it to the animation list
276 m_animations.add(key, animation);
277
278 RetainPtr<CFStringRef> s(AdoptCF, key.createCFString());
279 CACFLayerAddAnimation(m_layer.get(), s.get(), animation->platformAnimation());
280 setNeedsCommit();
281
282 // Tell the renderer about it so we can fire the start animation event
283 WKCACFLayerRenderer* renderer = rendererForLayer(this);
284 if (renderer)
285 renderer->addPendingAnimatedLayer(this);
286}
287
288void PlatformCALayer::removeAnimationForKey(const String& key)
289{
290 // Remove it from the animation list
291 m_animations.remove(key);
292
293 RetainPtr<CFStringRef> s(AdoptCF, key.createCFString());
294 CACFLayerRemoveAnimation(m_layer.get(), s.get());
295
296 // We don't "remove" a layer from WKCACFLayerRenderer when it loses an animation.
297 // There may be other active animations on the layer and if an animation
298 // callback is fired on a layer without any animations no harm is done.
299
300 setNeedsCommit();
301}
302
303PassRefPtr<PlatformCAAnimation> PlatformCALayer::animationForKey(const String& key)
304{
305 HashMap<String, RefPtr<PlatformCAAnimation> >::iterator it = m_animations.find(key);
306 if (it == m_animations.end())
307 return 0;
308
309 return it->second;
310}
311
312PlatformCALayer* PlatformCALayer::mask() const
313{
314 return platformCALayer(CACFLayerGetMask(m_layer.get()));
315}
316
317void PlatformCALayer::setMask(PlatformCALayer* layer)
318{
319 CACFLayerSetMask(m_layer.get(), layer ? layer->platformLayer() : 0);
320 setNeedsCommit();
321}
322
323bool PlatformCALayer::isOpaque() const
324{
325 return CACFLayerIsOpaque(m_layer.get());
326}
327
328void PlatformCALayer::setOpaque(bool value)
329{
330 CACFLayerSetOpaque(m_layer.get(), value);
331 setNeedsCommit();
332}
333
334FloatRect PlatformCALayer::bounds() const
335{
336 return CACFLayerGetBounds(m_layer.get());
337}
338
339void PlatformCALayer::setBounds(const FloatRect& value)
340{
341 intern(this)->setBounds(value);
342 setNeedsLayout();
343}
344
345FloatPoint3D PlatformCALayer::position() const
346{
347 CGPoint point = CACFLayerGetPosition(m_layer.get());
348 return FloatPoint3D(point.x, point.y, CACFLayerGetZPosition(m_layer.get()));
349}
350
351void PlatformCALayer::setPosition(const FloatPoint3D& value)
352{
353 CACFLayerSetPosition(m_layer.get(), CGPointMake(value.x(), value.y()));
354 CACFLayerSetZPosition(m_layer.get(), value.z());
355 setNeedsCommit();
356}
357
358FloatPoint3D PlatformCALayer::anchorPoint() const
359{
360 CGPoint point = CACFLayerGetAnchorPoint(m_layer.get());
361 float z = CACFLayerGetAnchorPointZ(m_layer.get());
362 return FloatPoint3D(point.x, point.y, z);
363}
364
365void PlatformCALayer::setAnchorPoint(const FloatPoint3D& value)
366{
367 CACFLayerSetAnchorPoint(m_layer.get(), CGPointMake(value.x(), value.y()));
368 CACFLayerSetAnchorPointZ(m_layer.get(), value.z());
369 setNeedsCommit();
370}
371
372TransformationMatrix PlatformCALayer::transform() const
373{
374 return CACFLayerGetTransform(m_layer.get());
375}
376
377void PlatformCALayer::setTransform(const TransformationMatrix& value)
378{
379 CACFLayerSetTransform(m_layer.get(), value);
380 setNeedsCommit();
381}
382
383TransformationMatrix PlatformCALayer::sublayerTransform() const
384{
385 return CACFLayerGetSublayerTransform(m_layer.get());
386}
387
388void PlatformCALayer::setSublayerTransform(const TransformationMatrix& value)
389{
390 CACFLayerSetSublayerTransform(m_layer.get(), value);
391 setNeedsCommit();
392}
393
394TransformationMatrix PlatformCALayer::contentsTransform() const
395{
396 // ContentsTransform is not used
397 return TransformationMatrix();
398}
399
400void PlatformCALayer::setContentsTransform(const TransformationMatrix&)
401{
402 // ContentsTransform is not used
403}
404
405bool PlatformCALayer::isHidden() const
406{
407 return CACFLayerIsHidden(m_layer.get());
408}
409
410void PlatformCALayer::setHidden(bool value)
411{
412 CACFLayerSetHidden(m_layer.get(), value);
413 setNeedsCommit();
414}
415
416bool PlatformCALayer::isGeometryFlipped() const
417{
418 return CACFLayerIsGeometryFlipped(m_layer.get());
419}
420
421void PlatformCALayer::setGeometryFlipped(bool value)
422{
423 CACFLayerSetGeometryFlipped(m_layer.get(), value);
424 setNeedsCommit();
425}
426
427bool PlatformCALayer::isDoubleSided() const
428{
429 return CACFLayerIsDoubleSided(m_layer.get());
430}
431
432void PlatformCALayer::setDoubleSided(bool value)
433{
434 CACFLayerSetDoubleSided(m_layer.get(), value);
435 setNeedsCommit();
436}
437
438bool PlatformCALayer::masksToBounds() const
439{
440 return CACFLayerGetMasksToBounds(m_layer.get());
441}
442
443void PlatformCALayer::setMasksToBounds(bool value)
444{
445 CACFLayerSetMasksToBounds(m_layer.get(), value);
446 setNeedsCommit();
447}
448
449bool PlatformCALayer::acceleratesDrawing() const
450{
451 return false;
452}
453
454void PlatformCALayer::setAcceleratesDrawing(bool)
455{
456}
457
458CFTypeRef PlatformCALayer::contents() const
459{
460 return CACFLayerGetContents(m_layer.get());
461}
462
463void PlatformCALayer::setContents(CFTypeRef value)
464{
465 CACFLayerSetContents(m_layer.get(), value);
466 setNeedsCommit();
467}
468
469FloatRect PlatformCALayer::contentsRect() const
470{
471 return CACFLayerGetContentsRect(m_layer.get());
472}
473
474void PlatformCALayer::setContentsRect(const FloatRect& value)
475{
476 CACFLayerSetContentsRect(m_layer.get(), value);
477 setNeedsCommit();
478}
479
480void PlatformCALayer::setMinificationFilter(FilterType value)
481{
482 CACFLayerSetMinificationFilter(m_layer.get(), toCACFFilterType(value));
483}
484
485void PlatformCALayer::setMagnificationFilter(FilterType value)
486{
487 CACFLayerSetMagnificationFilter(m_layer.get(), toCACFFilterType(value));
488 setNeedsCommit();
489}
490
491Color PlatformCALayer::backgroundColor() const
492{
493 return CACFLayerGetBackgroundColor(m_layer.get());
494}
495
496void PlatformCALayer::setBackgroundColor(const Color& value)
497{
498 CGFloat components[4];
499 value.getRGBA(components[0], components[1], components[2], components[3]);
500
501 RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
502 RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
503
504 CACFLayerSetBackgroundColor(m_layer.get(), color.get());
505 setNeedsCommit();
506}
507
508float PlatformCALayer::borderWidth() const
509{
510 return CACFLayerGetBorderWidth(m_layer.get());
511}
512
513void PlatformCALayer::setBorderWidth(float value)
514{
515 CACFLayerSetBorderWidth(m_layer.get(), value);
516 setNeedsCommit();
517}
518
519Color PlatformCALayer::borderColor() const
520{
521 return CACFLayerGetBorderColor(m_layer.get());
522}
523
524void PlatformCALayer::setBorderColor(const Color& value)
525{
526 CGFloat components[4];
527 value.getRGBA(components[0], components[1], components[2], components[3]);
528
529 RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
530 RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
531
532 CACFLayerSetBorderColor(m_layer.get(), color.get());
533 setNeedsCommit();
534}
535
536float PlatformCALayer::opacity() const
537{
538 return CACFLayerGetOpacity(m_layer.get());
539}
540
541void PlatformCALayer::setOpacity(float value)
542{
543 CACFLayerSetOpacity(m_layer.get(), value);
544 setNeedsCommit();
545}
546
547String PlatformCALayer::name() const
548{
549 return CACFLayerGetName(m_layer.get());
550}
551
552void PlatformCALayer::setName(const String& value)
553{
554 RetainPtr<CFStringRef> s(AdoptCF, value.createCFString());
555 CACFLayerSetName(m_layer.get(), s.get());
556 setNeedsCommit();
557}
558
559FloatRect PlatformCALayer::frame() const
560{
561 return CACFLayerGetFrame(m_layer.get());
562}
563
564void PlatformCALayer::setFrame(const FloatRect& value)
565{
566 intern(this)->setFrame(value);
567 setNeedsLayout();
568}
569
570float PlatformCALayer::speed() const
571{
572 return CACFLayerGetSpeed(m_layer.get());
573}
574
575void PlatformCALayer::setSpeed(float value)
576{
577 CACFLayerSetSpeed(m_layer.get(), value);
578 setNeedsCommit();
579}
580
581CFTimeInterval PlatformCALayer::timeOffset() const
582{
583 return CACFLayerGetTimeOffset(m_layer.get());
584}
585
586void PlatformCALayer::setTimeOffset(CFTimeInterval value)
587{
588 CACFLayerSetTimeOffset(m_layer.get(), value);
589 setNeedsCommit();
590}
591
592#ifndef NDEBUG
593static void printIndent(int indent)
594{
595 for ( ; indent > 0; --indent)
596 fprintf(stderr, " ");
597}
598
599static void printTransform(const CATransform3D& transform)
600{
601 fprintf(stderr, "[%g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g]",
602 transform.m11, transform.m12, transform.m13, transform.m14,
603 transform.m21, transform.m22, transform.m23, transform.m24,
604 transform.m31, transform.m32, transform.m33, transform.m34,
605 transform.m41, transform.m42, transform.m43, transform.m44);
606}
607
608static void printLayer(const PlatformCALayer* layer, int indent)
609{
610 FloatPoint3D layerPosition = layer->position();
611 FloatPoint3D layerAnchorPoint = layer->anchorPoint();
612 FloatRect layerBounds = layer->bounds();
613 printIndent(indent);
614
615 char* layerTypeName = 0;
616 switch (layer->layerType()) {
617 case PlatformCALayer::LayerTypeLayer: layerTypeName = "layer"; break;
618 case PlatformCALayer::LayerTypeWebLayer: layerTypeName = "web-layer"; break;
619 case PlatformCALayer::LayerTypeTransformLayer: layerTypeName = "transform-layer"; break;
620 case PlatformCALayer::LayerTypeWebTiledLayer: layerTypeName = "web-tiled-layer"; break;
621 case PlatformCALayer::LayerTypeRootLayer: layerTypeName = "root-layer"; break;
622 case PlatformCALayer::LayerTypeCustom: layerTypeName = "custom-layer"; break;
623 }
624
625 fprintf(stderr, "(%s [%g %g %g] [%g %g %g %g] [%g %g %g] superlayer=%p\n",
626 layerTypeName,
627 layerPosition.x(), layerPosition.y(), layerPosition.z(),
628 layerBounds.x(), layerBounds.y(), layerBounds.width(), layerBounds.height(),
629 layerAnchorPoint.x(), layerAnchorPoint.y(), layerAnchorPoint.z(), layer->superlayer());
630
631 // Print name if needed
632 String layerName = layer->name();
633 if (!layerName.isEmpty()) {
634 printIndent(indent + 1);
635 fprintf(stderr, "(name %s)\n", layerName.utf8().data());
636 }
637
638 // Print masksToBounds if needed
639 bool layerMasksToBounds = layer->masksToBounds();
640 if (layerMasksToBounds) {
641 printIndent(indent + 1);
642 fprintf(stderr, "(masksToBounds true)\n");
643 }
644
645 // Print opacity if needed
646 float layerOpacity = layer->opacity();
647 if (layerOpacity != 1) {
648 printIndent(indent + 1);
649 fprintf(stderr, "(opacity %hf)\n", layerOpacity);
650 }
651
652 // Print sublayerTransform if needed
653 TransformationMatrix layerTransform = layer->sublayerTransform();
654 if (!layerTransform.isIdentity()) {
655 printIndent(indent + 1);
656 fprintf(stderr, "(sublayerTransform ");
657 printTransform(layerTransform);
658 fprintf(stderr, ")\n");
659 }
660
661 // Print transform if needed
662 layerTransform = layer->transform();
663 if (!layerTransform.isIdentity()) {
664 printIndent(indent + 1);
665 fprintf(stderr, "(transform ");
666 printTransform(layerTransform);
667 fprintf(stderr, ")\n");
668 }
669
670 // Print contents if needed
671 CFTypeRef layerContents = layer->contents();
672 if (layerContents) {
673 if (CFGetTypeID(layerContents) == CGImageGetTypeID()) {
674 CGImageRef imageContents = static_cast<CGImageRef>(const_cast<void*>(layerContents));
675 printIndent(indent + 1);
676 fprintf(stderr, "(contents (image [%d %d]))\n",
677 CGImageGetWidth(imageContents), CGImageGetHeight(imageContents));
678 }
679 }
680
681 // Print sublayers if needed
682 int n = layer->sublayerCount();
683 if (n > 0) {
684 printIndent(indent + 1);
685 fprintf(stderr, "(sublayers\n");
686
687 CFArrayRef sublayers = CACFLayerGetSublayers(layer->platformLayer());
688 for (int i = 0; i < n; ++i) {
689 PlatformCALayer* sublayer = PlatformCALayer::platformCALayer(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, i)));
690 printLayer(sublayer, indent + 2);
691 }
692
693 printIndent(indent + 1);
694 fprintf(stderr, ")\n");
695 }
696
697 printIndent(indent);
698 fprintf(stderr, ")\n");
699}
700
701void PlatformCALayer::printTree() const
702{
703 // Print heading info
704 CGRect rootBounds = bounds();
705 fprintf(stderr, "\n\n** Render tree at time %g (bounds %g, %g %gx%g) **\n\n",
706 currentTime(), rootBounds.origin.x, rootBounds.origin.y, rootBounds.size.width, rootBounds.size.height);
707
708 // Print layer tree from the root
709 printLayer(this, 0);
710}
711#endif // #ifndef NDEBUG
712
713#endif // USE(ACCELERATED_COMPOSITING)