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