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 43 bool PlatformCALayer::isValueFunctionSupported() 44 { 45 return true; 46 } 47 48 void PlatformCALayer::setOwner(PlatformCALayerClient* owner) 49 { 50 m_owner = owner; 51 } 52 53 static CFStringRef toCACFLayerType(PlatformCALayer::LayerType type) 54 { 55 return (type == PlatformCALayer::LayerTypeTransformLayer) ? kCACFTransformLayer : kCACFLayer; 56 } 57 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 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 78 static PlatformCALayerWinInternal* intern(const PlatformCALayer* layer) 79 { 80 return static_cast<PlatformCALayerWinInternal*>(CACFLayerGetUserData(layer->platformLayer())); 81 } 82 83 static PlatformCALayerWinInternal* intern(void* layer) 84 { 85 return static_cast<PlatformCALayerWinInternal*>(CACFLayerGetUserData(static_cast<CACFLayerRef>(layer))); 86 } 87 88 PassRefPtr<PlatformCALayer> PlatformCALayer::create(LayerType layerType, PlatformCALayerClient* owner) 89 { 90 return adoptRef(new PlatformCALayer(layerType, 0, owner)); 91 } 92 93 PassRefPtr<PlatformCALayer> PlatformCALayer::create(void* platformLayer, PlatformCALayerClient* owner) 94 { 95 return adoptRef(new PlatformCALayer(LayerTypeCustom, static_cast<PlatformLayer*>(platformLayer), owner)); 96 } 97 98 static void displayCallback(CACFLayerRef caLayer, CGContextRef context) 99 { 100 ASSERT_ARG(caLayer, CACFLayerGetUserData(caLayer)); 101 intern(caLayer)->displayCallback(caLayer, context); 102 } 103 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 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 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 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 152 PlatformLayer* PlatformCALayer::platformLayer() const 153 { 154 return m_layer.get(); 155 } 156 157 PlatformCALayer* PlatformCALayer::rootLayer() const 158 { 159 AbstractCACFLayerTreeHost* host = layerTreeHostForLayer(this); 160 return host ? host->rootLayer() : 0; 161 } 162 163 void PlatformCALayer::setNeedsDisplay(const FloatRect* dirtyRect) 164 { 165 intern(this)->setNeedsDisplay(dirtyRect); 166 } 167 168 void PlatformCALayer::setNeedsCommit() 169 { 170 AbstractCACFLayerTreeHost* host = layerTreeHostForLayer(this); 171 if (host) 172 host->layerTreeDidChange(); 173 } 174 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 186 void PlatformCALayer::setNeedsLayout() 187 { 188 if (!m_owner || !m_owner->platformCALayerRespondsToLayoutChanges()) 189 return; 190 191 CACFLayerSetNeedsLayout(m_layer.get()); 192 setNeedsCommit(); 193 } 194 195 PlatformCALayer* PlatformCALayer::superlayer() const 196 { 197 return platformCALayer(CACFLayerGetSuperlayer(m_layer.get())); 198 } 199 200 void PlatformCALayer::removeFromSuperlayer() 201 { 202 CACFLayerRemoveFromSuperlayer(m_layer.get()); 203 setNeedsCommit(); 204 } 205 206 void PlatformCALayer::setSublayers(const PlatformCALayerList& list) 207 { 208 intern(this)->setSublayers(list); 209 } 210 211 void PlatformCALayer::removeAllSublayers() 212 { 213 intern(this)->removeAllSublayers(); 214 } 215 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 222 void PlatformCALayer::insertSublayer(PlatformCALayer* layer, size_t index) 223 { 224 intern(this)->insertSublayer(layer, index); 225 } 226 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 249 size_t PlatformCALayer::sublayerCount() const 250 { 251 return intern(this)->sublayerCount(); 252 } 253 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 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 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 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 302 PlatformCALayer* PlatformCALayer::mask() const 303 { 304 return platformCALayer(CACFLayerGetMask(m_layer.get())); 305 } 306 307 void PlatformCALayer::setMask(PlatformCALayer* layer) 308 { 309 CACFLayerSetMask(m_layer.get(), layer ? layer->platformLayer() : 0); 310 setNeedsCommit(); 311 } 312 313 bool PlatformCALayer::isOpaque() const 314 { 315 return CACFLayerIsOpaque(m_layer.get()); 316 } 317 318 void PlatformCALayer::setOpaque(bool value) 319 { 320 CACFLayerSetOpaque(m_layer.get(), value); 321 setNeedsCommit(); 322 } 323 324 FloatRect PlatformCALayer::bounds() const 325 { 326 return CACFLayerGetBounds(m_layer.get()); 327 } 328 329 void PlatformCALayer::setBounds(const FloatRect& value) 330 { 331 intern(this)->setBounds(value); 332 setNeedsLayout(); 333 } 334 335 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 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 348 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 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 362 TransformationMatrix PlatformCALayer::transform() const 363 { 364 return CACFLayerGetTransform(m_layer.get()); 365 } 366 367 void PlatformCALayer::setTransform(const TransformationMatrix& value) 368 { 369 CACFLayerSetTransform(m_layer.get(), value); 370 setNeedsCommit(); 371 } 372 373 TransformationMatrix PlatformCALayer::sublayerTransform() const 374 { 375 return CACFLayerGetSublayerTransform(m_layer.get()); 376 } 377 378 void PlatformCALayer::setSublayerTransform(const TransformationMatrix& value) 379 { 380 CACFLayerSetSublayerTransform(m_layer.get(), value); 381 setNeedsCommit(); 382 } 383 384 TransformationMatrix PlatformCALayer::contentsTransform() const 385 { 386 // ContentsTransform is not used 387 return TransformationMatrix(); 388 } 389 390 void PlatformCALayer::setContentsTransform(const TransformationMatrix&) 391 { 392 // ContentsTransform is not used 393 } 394 395 bool PlatformCALayer::isHidden() const 396 { 397 return CACFLayerIsHidden(m_layer.get()); 398 } 399 400 void PlatformCALayer::setHidden(bool value) 401 { 402 CACFLayerSetHidden(m_layer.get(), value); 403 setNeedsCommit(); 404 } 405 406 bool PlatformCALayer::isGeometryFlipped() const 407 { 408 return CACFLayerIsGeometryFlipped(m_layer.get()); 409 } 410 411 void PlatformCALayer::setGeometryFlipped(bool value) 412 { 413 CACFLayerSetGeometryFlipped(m_layer.get(), value); 414 setNeedsCommit(); 415 } 416 417 bool PlatformCALayer::isDoubleSided() const 418 { 419 return CACFLayerIsDoubleSided(m_layer.get()); 420 } 421 422 void PlatformCALayer::setDoubleSided(bool value) 423 { 424 CACFLayerSetDoubleSided(m_layer.get(), value); 425 setNeedsCommit(); 426 } 427 428 bool PlatformCALayer::masksToBounds() const 429 { 430 return CACFLayerGetMasksToBounds(m_layer.get()); 431 } 432 433 void PlatformCALayer::setMasksToBounds(bool value) 434 { 435 CACFLayerSetMasksToBounds(m_layer.get(), value); 436 setNeedsCommit(); 437 } 438 439 bool PlatformCALayer::acceleratesDrawing() const 440 { 441 return false; 442 } 443 444 void PlatformCALayer::setAcceleratesDrawing(bool) 445 { 446 } 447 448 CFTypeRef PlatformCALayer::contents() const 449 { 450 return CACFLayerGetContents(m_layer.get()); 451 } 452 453 void PlatformCALayer::setContents(CFTypeRef value) 454 { 455 CACFLayerSetContents(m_layer.get(), value); 456 setNeedsCommit(); 457 } 458 459 FloatRect PlatformCALayer::contentsRect() const 460 { 461 return CACFLayerGetContentsRect(m_layer.get()); 462 } 463 464 void PlatformCALayer::setContentsRect(const FloatRect& value) 465 { 466 CACFLayerSetContentsRect(m_layer.get(), value); 467 setNeedsCommit(); 468 } 469 470 void PlatformCALayer::setMinificationFilter(FilterType value) 471 { 472 CACFLayerSetMinificationFilter(m_layer.get(), toCACFFilterType(value)); 473 } 474 475 void PlatformCALayer::setMagnificationFilter(FilterType value) 476 { 477 CACFLayerSetMagnificationFilter(m_layer.get(), toCACFFilterType(value)); 478 setNeedsCommit(); 479 } 480 481 Color PlatformCALayer::backgroundColor() const 482 { 483 return CACFLayerGetBackgroundColor(m_layer.get()); 484 } 485 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 498 float PlatformCALayer::borderWidth() const 499 { 500 return CACFLayerGetBorderWidth(m_layer.get()); 501 } 502 503 void PlatformCALayer::setBorderWidth(float value) 504 { 505 CACFLayerSetBorderWidth(m_layer.get(), value); 506 setNeedsCommit(); 507 } 508 509 Color PlatformCALayer::borderColor() const 510 { 511 return CACFLayerGetBorderColor(m_layer.get()); 512 } 513 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 526 float PlatformCALayer::opacity() const 527 { 528 return CACFLayerGetOpacity(m_layer.get()); 529 } 530 531 void PlatformCALayer::setOpacity(float value) 532 { 533 CACFLayerSetOpacity(m_layer.get(), value); 534 setNeedsCommit(); 535 } 536 537 String PlatformCALayer::name() const 538 { 539 return CACFLayerGetName(m_layer.get()); 540 } 541 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 549 FloatRect PlatformCALayer::frame() const 550 { 551 return CACFLayerGetFrame(m_layer.get()); 552 } 553 554 void PlatformCALayer::setFrame(const FloatRect& value) 555 { 556 intern(this)->setFrame(value); 557 setNeedsLayout(); 558 } 559 560 float PlatformCALayer::speed() const 561 { 562 return CACFLayerGetSpeed(m_layer.get()); 563 } 564 565 void PlatformCALayer::setSpeed(float value) 566 { 567 CACFLayerSetSpeed(m_layer.get(), value); 568 setNeedsCommit(); 569 } 570 571 CFTimeInterval PlatformCALayer::timeOffset() const 572 { 573 return CACFLayerGetTimeOffset(m_layer.get()); 574 } 575 576 void PlatformCALayer::setTimeOffset(CFTimeInterval value) 577 { 578 CACFLayerSetTimeOffset(m_layer.get(), value); 579 setNeedsCommit(); 580 } 581 582 float PlatformCALayer::contentsScale() const 583 { 584 return 1; 585 } 586 587 void PlatformCALayer::setContentsScale(float) 588 { 589 } 590 591 #ifndef NDEBUG 592 static void printIndent(int indent) 593 { 594 for ( ; indent > 0; --indent) 595 fprintf(stderr, " "); 596 } 597 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 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 700 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