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