Unreviewed, rolling out r244627.
[WebKit-https.git] / Source / WebCore / platform / graphics / ca / cocoa / PlatformCALayerCocoa.mm
1 /*
2  * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #import "PlatformCALayerCocoa.h"
28
29 #import "AnimationUtilities.h"
30 #import "GraphicsContext.h"
31 #import "GraphicsLayerCA.h"
32 #import "LengthFunctions.h"
33 #import "PlatformCAAnimationCocoa.h"
34 #import "PlatformCAFilters.h"
35 #import "ScrollbarThemeMac.h"
36 #import "TileController.h"
37 #import "TiledBacking.h"
38 #import "WebActionDisablingCALayerDelegate.h"
39 #import "WebCoreCALayerExtras.h"
40 #import "WebGLLayer.h"
41 #import <pal/spi/cocoa/QuartzCoreSPI.h>
42 #import <wtf/SoftLinking.h>
43 #import "WebLayer.h"
44 #import "WebSystemBackdropLayer.h"
45 #import "WebTiledBackingLayer.h"
46 #import <AVFoundation/AVPlayer.h>
47 #import <AVFoundation/AVPlayerLayer.h>
48 #import <QuartzCore/QuartzCore.h>
49 #import <objc/runtime.h>
50 #import <wtf/BlockObjCExceptions.h>
51 #import <wtf/RetainPtr.h>
52
53 #if ENABLE(WEBGPU)
54 #import "WebGPULayer.h"
55 #endif
56
57 #if PLATFORM(IOS_FAMILY)
58 #import "FontAntialiasingStateSaver.h"
59 #import "WAKWindow.h"
60 #import "WKGraphics.h"
61 #import "WebCoreThread.h"
62 #else
63 #import "ThemeMac.h"
64 #endif
65
66 SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
67
68 SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVPlayerLayer)
69
70 namespace WebCore {
71
72 Ref<PlatformCALayer> PlatformCALayerCocoa::create(LayerType layerType, PlatformCALayerClient* owner)
73 {
74     return adoptRef(*new PlatformCALayerCocoa(layerType, owner));
75 }
76
77 Ref<PlatformCALayer> PlatformCALayerCocoa::create(void* platformLayer, PlatformCALayerClient* owner)
78 {
79     return adoptRef(*new PlatformCALayerCocoa((__bridge CALayer *)platformLayer, owner));
80 }
81
82 static NSString * const platformCALayerPointer = @"WKPlatformCALayer";
83 PlatformCALayer* PlatformCALayer::platformCALayer(void* platformLayer)
84 {
85     if (!platformLayer)
86         return 0;
87
88     // Pointer to PlatformCALayer is kept in a key of the CALayer
89     PlatformCALayer* platformCALayer = nil;
90     BEGIN_BLOCK_OBJC_EXCEPTIONS
91     platformCALayer = static_cast<PlatformCALayer*>([[(__bridge CALayer *)platformLayer valueForKey:platformCALayerPointer] pointerValue]);
92     END_BLOCK_OBJC_EXCEPTIONS
93     return platformCALayer;
94 }
95
96 static MonotonicTime mediaTimeToCurrentTime(CFTimeInterval t)
97 {
98     return MonotonicTime::now() + Seconds(t - CACurrentMediaTime());
99 }
100
101 } // namespace WebCore
102
103 // Delegate for animationDidStart callback
104 @interface WebAnimationDelegate : NSObject {
105     WebCore::PlatformCALayer* m_owner;
106 }
107
108 - (void)animationDidStart:(CAAnimation *)anim;
109 - (void)setOwner:(WebCore::PlatformCALayer*)owner;
110
111 @end
112
113 @implementation WebAnimationDelegate
114
115 - (void)animationDidStart:(CAAnimation *)animation
116 {
117     using namespace WebCore;
118 #if PLATFORM(IOS_FAMILY)
119     WebThreadLock();
120 #endif
121     if (!m_owner)
122         return;
123
124     MonotonicTime startTime;
125     if (hasExplicitBeginTime(animation)) {
126         // We don't know what time CA used to commit the animation, so just use the current time
127         // (even though this will be slightly off).
128         startTime = mediaTimeToCurrentTime(CACurrentMediaTime());
129     } else
130         startTime = mediaTimeToCurrentTime([animation beginTime]);
131
132     CALayer *layer = m_owner->platformLayer();
133
134     String animationKey;
135     for (NSString *key in [layer animationKeys]) {
136         if ([layer animationForKey:key] == animation) {
137             animationKey = key;
138             break;
139         }
140     }
141
142     if (!animationKey.isEmpty())
143         m_owner->animationStarted(animationKey, startTime);
144 }
145
146 - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished
147 {
148     using namespace WebCore;
149 #if PLATFORM(IOS_FAMILY)
150     WebThreadLock();
151 #endif
152     UNUSED_PARAM(finished);
153
154     if (!m_owner)
155         return;
156     
157     CALayer *layer = m_owner->platformLayer();
158
159     String animationKey;
160     for (NSString *key in [layer animationKeys]) {
161         if ([layer animationForKey:key] == animation) {
162             animationKey = key;
163             break;
164         }
165     }
166
167     if (!animationKey.isEmpty())
168         m_owner->animationEnded(animationKey);
169 }
170
171 - (void)setOwner:(WebCore::PlatformCALayer*)owner
172 {
173     m_owner = owner;
174 }
175
176 @end
177
178 namespace WebCore {
179
180 void PlatformCALayerCocoa::setOwner(PlatformCALayerClient* owner)
181 {
182     PlatformCALayer::setOwner(owner);
183     
184     // Change the delegate's owner if needed
185     if (m_delegate)
186         [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:this];        
187 }
188
189 static NSString *toCAFilterType(PlatformCALayer::FilterType type)
190 {
191     switch (type) {
192     case PlatformCALayer::Linear: return kCAFilterLinear;
193     case PlatformCALayer::Nearest: return kCAFilterNearest;
194     case PlatformCALayer::Trilinear: return kCAFilterTrilinear;
195     default: return 0;
196     }
197 }
198
199 PlatformCALayer::LayerType PlatformCALayerCocoa::layerTypeForPlatformLayer(PlatformLayer* layer)
200 {
201     if ([layer isKindOfClass:getAVPlayerLayerClass()])
202         return LayerTypeAVPlayerLayer;
203
204     if ([layer isKindOfClass:objc_getClass("WebVideoContainerLayer")]
205         && layer.sublayers.count == 1
206         && [layer.sublayers[0] isKindOfClass:getAVPlayerLayerClass()])
207         return LayerTypeAVPlayerLayer;
208
209     if ([layer isKindOfClass:[WebGLLayer class]])
210         return LayerTypeContentsProvidedLayer;
211
212 #if ENABLE(WEBGPU)
213     if ([layer isKindOfClass:[WebGPULayer class]])
214         return LayerTypeContentsProvidedLayer;
215 #endif
216
217     return LayerTypeCustom;
218 }
219
220 PlatformCALayerCocoa::PlatformCALayerCocoa(LayerType layerType, PlatformCALayerClient* owner)
221     : PlatformCALayer(layerType, owner)
222 {
223     Class layerClass = Nil;
224     switch (layerType) {
225     case LayerTypeLayer:
226     case LayerTypeRootLayer:
227         layerClass = [CALayer class];
228         break;
229     case LayerTypeScrollContainerLayer:
230         // Scroll container layers only have special behavior with PlatformCALayerRemote.
231         // fallthrough
232     case LayerTypeEditableImageLayer:
233     case LayerTypeWebLayer:
234         layerClass = [WebLayer class];
235         break;
236     case LayerTypeSimpleLayer:
237     case LayerTypeTiledBackingTileLayer:
238         layerClass = [WebSimpleLayer class];
239         break;
240     case LayerTypeTransformLayer:
241         layerClass = [CATransformLayer class];
242         break;
243 #if ENABLE(FILTERS_LEVEL_2)
244     case LayerTypeBackdropLayer:
245         layerClass = [CABackdropLayer class];
246         break;
247     case LayerTypeLightSystemBackdropLayer:
248         layerClass = [WebLightSystemBackdropLayer class];
249         break;
250     case LayerTypeDarkSystemBackdropLayer:
251         layerClass = [WebDarkSystemBackdropLayer class];
252         break;
253 #else
254     case LayerTypeBackdropLayer:
255     case LayerTypeLightSystemBackdropLayer:
256     case LayerTypeDarkSystemBackdropLayer:
257         ASSERT_NOT_REACHED();
258         layerClass = [CALayer class];
259         break;
260 #endif
261     case LayerTypeTiledBackingLayer:
262     case LayerTypePageTiledBackingLayer:
263         layerClass = [WebTiledBackingLayer class];
264         break;
265     case LayerTypeAVPlayerLayer:
266         layerClass = getAVPlayerLayerClass();
267         break;
268     case LayerTypeContentsProvidedLayer:
269         // We don't create PlatformCALayerCocoas wrapped around WebGLLayers or WebGPULayers.
270         ASSERT_NOT_REACHED();
271         break;
272     case LayerTypeShapeLayer:
273         layerClass = [CAShapeLayer class];
274         // fillColor defaults to opaque black.
275         break;
276     case LayerTypeCustom:
277         break;
278     }
279
280     if (layerClass)
281         m_layer = adoptNS([(CALayer *)[layerClass alloc] init]);
282
283 #if ENABLE(FILTERS_LEVEL_2) && PLATFORM(MAC)
284     if (layerType == LayerTypeBackdropLayer)
285         [(CABackdropLayer*)m_layer.get() setWindowServerAware:NO];
286 #endif
287
288     commonInit();
289 }
290
291 PlatformCALayerCocoa::PlatformCALayerCocoa(PlatformLayer* layer, PlatformCALayerClient* owner)
292     : PlatformCALayer(layerTypeForPlatformLayer(layer), owner)
293 {
294     m_layer = layer;
295     commonInit();
296 }
297
298 void PlatformCALayerCocoa::commonInit()
299 {
300     BEGIN_BLOCK_OBJC_EXCEPTIONS
301     // Save a pointer to 'this' in the CALayer
302     [m_layer setValue:[NSValue valueWithPointer:this] forKey:platformCALayerPointer];
303     
304     // Clear all the implicit animations on the CALayer
305     if (m_layerType == LayerTypeAVPlayerLayer || m_layerType == LayerTypeContentsProvidedLayer || m_layerType == LayerTypeScrollContainerLayer || m_layerType == LayerTypeCustom)
306         [m_layer web_disableAllActions];
307     else
308         [m_layer setDelegate:[WebActionDisablingCALayerDelegate shared]];
309
310     // So that the scrolling thread's performance logging code can find all the tiles, mark this as being a tile.
311     if (m_layerType == LayerTypeTiledBackingTileLayer)
312         [m_layer setValue:@YES forKey:@"isTile"];
313
314     if (usesTiledBackingLayer()) {
315         WebTiledBackingLayer* tiledBackingLayer = static_cast<WebTiledBackingLayer*>(m_layer.get());
316         TileController* tileController = [tiledBackingLayer createTileController:this];
317
318         m_customSublayers = std::make_unique<PlatformCALayerList>(tileController->containerLayers());
319     }
320
321     END_BLOCK_OBJC_EXCEPTIONS
322 }
323
324 Ref<PlatformCALayer> PlatformCALayerCocoa::clone(PlatformCALayerClient* owner) const
325 {
326     LayerType type;
327     switch (layerType()) {
328     case LayerTypeTransformLayer:
329         type = LayerTypeTransformLayer;
330         break;
331     case LayerTypeAVPlayerLayer:
332         type = LayerTypeAVPlayerLayer;
333         break;
334     case LayerTypeShapeLayer:
335         type = LayerTypeShapeLayer;
336         break;
337     case LayerTypeBackdropLayer:
338         type = LayerTypeBackdropLayer;
339         break;
340     case LayerTypeLayer:
341     default:
342         type = LayerTypeLayer;
343         break;
344     };
345     auto newLayer = PlatformCALayerCocoa::create(type, owner);
346     
347     newLayer->setPosition(position());
348     newLayer->setBounds(bounds());
349     newLayer->setAnchorPoint(anchorPoint());
350     newLayer->setTransform(transform());
351     newLayer->setSublayerTransform(sublayerTransform());
352     newLayer->setContents(contents());
353     newLayer->setMasksToBounds(masksToBounds());
354     newLayer->setDoubleSided(isDoubleSided());
355     newLayer->setOpaque(isOpaque());
356     newLayer->setBackgroundColor(backgroundColor());
357     newLayer->setContentsScale(contentsScale());
358     newLayer->setCornerRadius(cornerRadius());
359     newLayer->copyFiltersFrom(*this);
360     newLayer->updateCustomAppearance(customAppearance());
361
362     if (type == LayerTypeAVPlayerLayer) {
363         ASSERT([newLayer->platformLayer() isKindOfClass:getAVPlayerLayerClass()]);
364
365         AVPlayerLayer *destinationPlayerLayer = static_cast<PlatformCALayerCocoa&>(newLayer.get()).avPlayerLayer();
366         AVPlayerLayer *sourcePlayerLayer = avPlayerLayer();
367         ASSERT(sourcePlayerLayer);
368
369         dispatch_async(dispatch_get_main_queue(), ^{
370             [destinationPlayerLayer setPlayer:[sourcePlayerLayer player]];
371         });
372     }
373     
374     if (type == LayerTypeShapeLayer)
375         newLayer->setShapeRoundedRect(shapeRoundedRect());
376
377     return newLayer;
378 }
379
380 PlatformCALayerCocoa::~PlatformCALayerCocoa()
381 {
382     [m_layer setValue:nil forKey:platformCALayerPointer];
383     
384     // Remove the owner pointer from the delegate in case there is a pending animationStarted event.
385     [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:nil];
386
387     if (usesTiledBackingLayer())
388         [static_cast<WebTiledBackingLayer *>(m_layer.get()) invalidate];
389 }
390
391 void PlatformCALayerCocoa::animationStarted(const String& animationKey, MonotonicTime beginTime)
392 {
393     if (m_owner)
394         m_owner->platformCALayerAnimationStarted(animationKey, beginTime);
395 }
396
397 void PlatformCALayerCocoa::animationEnded(const String& animationKey)
398 {
399     if (m_owner)
400         m_owner->platformCALayerAnimationEnded(animationKey);
401 }
402
403 void PlatformCALayerCocoa::setNeedsDisplay()
404 {
405     if (!m_backingStoreAttached)
406         return;
407
408     BEGIN_BLOCK_OBJC_EXCEPTIONS
409     [m_layer setNeedsDisplay];
410     END_BLOCK_OBJC_EXCEPTIONS
411 }
412
413 void PlatformCALayerCocoa::setNeedsDisplayInRect(const FloatRect& dirtyRect)
414 {
415     if (!m_backingStoreAttached)
416         return;
417
418     BEGIN_BLOCK_OBJC_EXCEPTIONS
419     [m_layer setNeedsDisplayInRect:dirtyRect];
420     END_BLOCK_OBJC_EXCEPTIONS
421 }
422
423 void PlatformCALayerCocoa::copyContentsFromLayer(PlatformCALayer* layer)
424 {
425     BEGIN_BLOCK_OBJC_EXCEPTIONS
426     CALayer* caLayer = layer->m_layer.get();
427     if ([m_layer contents] != [caLayer contents])
428         [m_layer setContents:[caLayer contents]];
429     else
430         [m_layer reloadValueForKeyPath:@"contents"];
431     END_BLOCK_OBJC_EXCEPTIONS
432 }
433
434 PlatformCALayer* PlatformCALayerCocoa::superlayer() const
435 {
436     return platformCALayer((__bridge void*)[m_layer superlayer]);
437 }
438
439 void PlatformCALayerCocoa::removeFromSuperlayer()
440 {
441     BEGIN_BLOCK_OBJC_EXCEPTIONS
442     [m_layer removeFromSuperlayer];
443     END_BLOCK_OBJC_EXCEPTIONS
444 }
445
446 void PlatformCALayerCocoa::setSublayers(const PlatformCALayerList& list)
447 {
448     // Short circuiting here avoids the allocation of the array below.
449     if (!list.size()) {
450         removeAllSublayers();
451         return;
452     }
453
454     BEGIN_BLOCK_OBJC_EXCEPTIONS
455     NSMutableArray* sublayers = [[NSMutableArray alloc] init];
456     for (size_t i = 0; i < list.size(); ++i)
457         [sublayers addObject:list[i]->m_layer.get()];
458
459     [m_layer setSublayers:sublayers];
460     [sublayers release];
461     END_BLOCK_OBJC_EXCEPTIONS
462 }
463
464 void PlatformCALayerCocoa::removeAllSublayers()
465 {
466     BEGIN_BLOCK_OBJC_EXCEPTIONS
467     [m_layer setSublayers:nil];
468     END_BLOCK_OBJC_EXCEPTIONS
469 }
470
471 void PlatformCALayerCocoa::appendSublayer(PlatformCALayer& layer)
472 {
473     BEGIN_BLOCK_OBJC_EXCEPTIONS
474     ASSERT(m_layer != layer.m_layer);
475     [m_layer addSublayer:layer.m_layer.get()];
476     END_BLOCK_OBJC_EXCEPTIONS
477 }
478
479 void PlatformCALayerCocoa::insertSublayer(PlatformCALayer& layer, size_t index)
480 {
481     BEGIN_BLOCK_OBJC_EXCEPTIONS
482     ASSERT(m_layer != layer.m_layer);
483     [m_layer insertSublayer:layer.m_layer.get() atIndex:index];
484     END_BLOCK_OBJC_EXCEPTIONS
485 }
486
487 void PlatformCALayerCocoa::replaceSublayer(PlatformCALayer& reference, PlatformCALayer& layer)
488 {
489     BEGIN_BLOCK_OBJC_EXCEPTIONS
490     ASSERT(m_layer != layer.m_layer);
491     [m_layer replaceSublayer:reference.m_layer.get() with:layer.m_layer.get()];
492     END_BLOCK_OBJC_EXCEPTIONS
493 }
494
495 void PlatformCALayerCocoa::adoptSublayers(PlatformCALayer& source)
496 {
497     BEGIN_BLOCK_OBJC_EXCEPTIONS
498     [m_layer setSublayers:[source.m_layer.get() sublayers]];
499     END_BLOCK_OBJC_EXCEPTIONS
500 }
501
502 void PlatformCALayerCocoa::addAnimationForKey(const String& key, PlatformCAAnimation& animation)
503 {
504     // Add the delegate
505     if (!m_delegate) {
506         WebAnimationDelegate* webAnimationDelegate = [[WebAnimationDelegate alloc] init];
507         m_delegate = adoptNS(webAnimationDelegate);
508         [webAnimationDelegate setOwner:this];
509     }
510     
511     CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>(downcast<PlatformCAAnimationCocoa>(animation).platformAnimation());
512     if (![propertyAnimation delegate])
513         [propertyAnimation setDelegate:static_cast<id>(m_delegate.get())];
514
515     BEGIN_BLOCK_OBJC_EXCEPTIONS
516     [m_layer addAnimation:propertyAnimation forKey:key];
517     END_BLOCK_OBJC_EXCEPTIONS
518 }
519
520 void PlatformCALayerCocoa::removeAnimationForKey(const String& key)
521 {
522     BEGIN_BLOCK_OBJC_EXCEPTIONS
523     [m_layer removeAnimationForKey:key];
524     END_BLOCK_OBJC_EXCEPTIONS
525 }
526
527 RefPtr<PlatformCAAnimation> PlatformCALayerCocoa::animationForKey(const String& key)
528 {
529     CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>([m_layer animationForKey:key]);
530     if (!propertyAnimation)
531         return nullptr;
532     return PlatformCAAnimationCocoa::create(propertyAnimation);
533 }
534
535 void PlatformCALayerCocoa::setMask(PlatformCALayer* layer)
536 {
537     BEGIN_BLOCK_OBJC_EXCEPTIONS
538     [m_layer setMask:layer ? layer->platformLayer() : nil];
539     END_BLOCK_OBJC_EXCEPTIONS
540 }
541
542 bool PlatformCALayerCocoa::isOpaque() const
543 {
544     return [m_layer isOpaque];
545 }
546
547 void PlatformCALayerCocoa::setOpaque(bool value)
548 {
549     BEGIN_BLOCK_OBJC_EXCEPTIONS
550     [m_layer setOpaque:value];
551     END_BLOCK_OBJC_EXCEPTIONS
552 }
553
554 FloatRect PlatformCALayerCocoa::bounds() const
555 {
556     return [m_layer bounds];
557 }
558
559 void PlatformCALayerCocoa::setBounds(const FloatRect& value)
560 {
561     BEGIN_BLOCK_OBJC_EXCEPTIONS
562     [m_layer setBounds:value];
563     
564     if (requiresCustomAppearanceUpdateOnBoundsChange())
565         updateCustomAppearance(m_customAppearance);
566
567     END_BLOCK_OBJC_EXCEPTIONS
568 }
569
570 FloatPoint3D PlatformCALayerCocoa::position() const
571 {
572     CGPoint point = [m_layer position];
573     return FloatPoint3D(point.x, point.y, [m_layer zPosition]);
574 }
575
576 void PlatformCALayerCocoa::setPosition(const FloatPoint3D& value)
577 {
578     BEGIN_BLOCK_OBJC_EXCEPTIONS
579     [m_layer setPosition:CGPointMake(value.x(), value.y())];
580     [m_layer setZPosition:value.z()];
581     END_BLOCK_OBJC_EXCEPTIONS
582 }
583
584 FloatPoint3D PlatformCALayerCocoa::anchorPoint() const
585 {
586     CGPoint point = [m_layer anchorPoint];
587     float z = 0;
588     z = [m_layer anchorPointZ];
589     return FloatPoint3D(point.x, point.y, z);
590 }
591
592 void PlatformCALayerCocoa::setAnchorPoint(const FloatPoint3D& value)
593 {
594     BEGIN_BLOCK_OBJC_EXCEPTIONS
595     [m_layer setAnchorPoint:CGPointMake(value.x(), value.y())];
596     [m_layer setAnchorPointZ:value.z()];
597     END_BLOCK_OBJC_EXCEPTIONS
598 }
599
600 TransformationMatrix PlatformCALayerCocoa::transform() const
601 {
602     return [m_layer transform];
603 }
604
605 void PlatformCALayerCocoa::setTransform(const TransformationMatrix& value)
606 {
607     BEGIN_BLOCK_OBJC_EXCEPTIONS
608     [m_layer setTransform:value];
609     END_BLOCK_OBJC_EXCEPTIONS
610 }
611
612 TransformationMatrix PlatformCALayerCocoa::sublayerTransform() const
613 {
614     return [m_layer sublayerTransform];
615 }
616
617 void PlatformCALayerCocoa::setSublayerTransform(const TransformationMatrix& value)
618 {
619     BEGIN_BLOCK_OBJC_EXCEPTIONS
620     [m_layer setSublayerTransform:value];
621     END_BLOCK_OBJC_EXCEPTIONS
622 }
623
624 bool PlatformCALayerCocoa::isHidden() const
625 {
626     return [m_layer isHidden];
627 }
628
629 void PlatformCALayerCocoa::setHidden(bool value)
630 {
631     BEGIN_BLOCK_OBJC_EXCEPTIONS
632     [m_layer setHidden:value];
633     END_BLOCK_OBJC_EXCEPTIONS
634 }
635
636 bool PlatformCALayerCocoa::contentsHidden() const
637 {
638     return false;
639 }
640
641 void PlatformCALayerCocoa::setContentsHidden(bool)
642 {
643 }
644
645 bool PlatformCALayerCocoa::userInteractionEnabled() const
646 {
647     return true;
648 }
649
650 void PlatformCALayerCocoa::setUserInteractionEnabled(bool)
651 {
652 }
653
654 void PlatformCALayerCocoa::setBackingStoreAttached(bool attached)
655 {
656     if (attached == m_backingStoreAttached)
657         return;
658
659     m_backingStoreAttached = attached;
660
661     if (attached)
662         setNeedsDisplay();
663     else
664         setContents(nullptr);
665 }
666
667 bool PlatformCALayerCocoa::backingStoreAttached() const
668 {
669     return m_backingStoreAttached;
670 }
671
672 bool PlatformCALayerCocoa::geometryFlipped() const
673 {
674     return [m_layer isGeometryFlipped];
675 }
676
677 void PlatformCALayerCocoa::setGeometryFlipped(bool value)
678 {
679     BEGIN_BLOCK_OBJC_EXCEPTIONS
680     [m_layer setGeometryFlipped:value];
681     END_BLOCK_OBJC_EXCEPTIONS
682 }
683
684 bool PlatformCALayerCocoa::isDoubleSided() const
685 {
686     return [m_layer isDoubleSided];
687 }
688
689 void PlatformCALayerCocoa::setDoubleSided(bool value)
690 {
691     BEGIN_BLOCK_OBJC_EXCEPTIONS
692     [m_layer setDoubleSided:value];
693     END_BLOCK_OBJC_EXCEPTIONS
694 }
695
696 bool PlatformCALayerCocoa::masksToBounds() const
697 {
698     return [m_layer masksToBounds];
699 }
700
701 void PlatformCALayerCocoa::setMasksToBounds(bool value)
702 {
703     BEGIN_BLOCK_OBJC_EXCEPTIONS
704     [m_layer setMasksToBounds:value];
705     END_BLOCK_OBJC_EXCEPTIONS
706 }
707
708 bool PlatformCALayerCocoa::acceleratesDrawing() const
709 {
710     return [m_layer drawsAsynchronously];
711 }
712
713 void PlatformCALayerCocoa::setAcceleratesDrawing(bool acceleratesDrawing)
714 {
715     BEGIN_BLOCK_OBJC_EXCEPTIONS
716     [m_layer setDrawsAsynchronously:acceleratesDrawing];
717     END_BLOCK_OBJC_EXCEPTIONS
718 }
719
720 bool PlatformCALayerCocoa::wantsDeepColorBackingStore() const
721 {
722     return m_wantsDeepColorBackingStore;
723 }
724
725 void PlatformCALayerCocoa::setWantsDeepColorBackingStore(bool wantsDeepColorBackingStore)
726 {
727     if (wantsDeepColorBackingStore == m_wantsDeepColorBackingStore)
728         return;
729
730     m_wantsDeepColorBackingStore = wantsDeepColorBackingStore;
731
732     if (usesTiledBackingLayer()) {
733         [static_cast<WebTiledBackingLayer *>(m_layer.get()) setWantsDeepColorBackingStore:m_wantsDeepColorBackingStore];
734         return;
735     }
736
737     updateContentsFormat();
738 }
739
740 bool PlatformCALayerCocoa::supportsSubpixelAntialiasedText() const
741 {
742     return m_supportsSubpixelAntialiasedText;
743 }
744
745 void PlatformCALayerCocoa::setSupportsSubpixelAntialiasedText(bool supportsSubpixelAntialiasedText)
746 {
747     if (supportsSubpixelAntialiasedText == m_supportsSubpixelAntialiasedText)
748         return;
749     
750     m_supportsSubpixelAntialiasedText = supportsSubpixelAntialiasedText;
751
752     if (usesTiledBackingLayer()) {
753         [static_cast<WebTiledBackingLayer *>(m_layer.get()) setSupportsSubpixelAntialiasedText:m_supportsSubpixelAntialiasedText];
754         return;
755     }
756
757     updateContentsFormat();
758 }
759
760 bool PlatformCALayerCocoa::hasContents() const
761 {
762     return [m_layer contents];
763 }
764
765 CFTypeRef PlatformCALayerCocoa::contents() const
766 {
767     return (__bridge CFTypeRef)[m_layer contents];
768 }
769
770 void PlatformCALayerCocoa::setContents(CFTypeRef value)
771 {
772     BEGIN_BLOCK_OBJC_EXCEPTIONS
773     [m_layer setContents:(__bridge id)value];
774     END_BLOCK_OBJC_EXCEPTIONS
775 }
776
777 void PlatformCALayerCocoa::setContentsRect(const FloatRect& value)
778 {
779     BEGIN_BLOCK_OBJC_EXCEPTIONS
780     [m_layer setContentsRect:value];
781     END_BLOCK_OBJC_EXCEPTIONS
782 }
783
784 void PlatformCALayerCocoa::setMinificationFilter(FilterType value)
785 {
786     BEGIN_BLOCK_OBJC_EXCEPTIONS
787     [m_layer setMinificationFilter:toCAFilterType(value)];
788     END_BLOCK_OBJC_EXCEPTIONS
789 }
790
791 void PlatformCALayerCocoa::setMagnificationFilter(FilterType value)
792 {
793     BEGIN_BLOCK_OBJC_EXCEPTIONS
794     [m_layer setMagnificationFilter:toCAFilterType(value)];
795     END_BLOCK_OBJC_EXCEPTIONS
796 }
797
798 Color PlatformCALayerCocoa::backgroundColor() const
799 {
800     return [m_layer backgroundColor];
801 }
802
803 void PlatformCALayerCocoa::setBackgroundColor(const Color& value)
804 {
805     BEGIN_BLOCK_OBJC_EXCEPTIONS
806     [m_layer setBackgroundColor:cachedCGColor(value)];
807     END_BLOCK_OBJC_EXCEPTIONS
808 }
809
810 void PlatformCALayerCocoa::setBorderWidth(float value)
811 {
812     BEGIN_BLOCK_OBJC_EXCEPTIONS
813     [m_layer setBorderWidth:value];
814     END_BLOCK_OBJC_EXCEPTIONS
815 }
816
817 void PlatformCALayerCocoa::setBorderColor(const Color& value)
818 {
819     if (value.isValid()) {
820         BEGIN_BLOCK_OBJC_EXCEPTIONS
821         [m_layer setBorderColor:cachedCGColor(value)];
822         END_BLOCK_OBJC_EXCEPTIONS
823     } else {
824         BEGIN_BLOCK_OBJC_EXCEPTIONS
825         [m_layer setBorderColor:nil];
826         END_BLOCK_OBJC_EXCEPTIONS
827     }
828 }
829
830 float PlatformCALayerCocoa::opacity() const
831 {
832     return [m_layer opacity];
833 }
834
835 void PlatformCALayerCocoa::setOpacity(float value)
836 {
837     BEGIN_BLOCK_OBJC_EXCEPTIONS
838     [m_layer setOpacity:value];
839     END_BLOCK_OBJC_EXCEPTIONS
840 }
841
842 void PlatformCALayerCocoa::setFilters(const FilterOperations& filters)
843 {
844     PlatformCAFilters::setFiltersOnLayer(platformLayer(), filters);
845 }
846
847 void PlatformCALayerCocoa::copyFiltersFrom(const PlatformCALayer& sourceLayer)
848 {
849     BEGIN_BLOCK_OBJC_EXCEPTIONS
850     [m_layer setFilters:[sourceLayer.platformLayer() filters]];
851     END_BLOCK_OBJC_EXCEPTIONS
852 }
853
854 bool PlatformCALayerCocoa::filtersCanBeComposited(const FilterOperations& filters)
855 {
856     // Return false if there are no filters to avoid needless work
857     if (!filters.size())
858         return false;
859     
860     for (unsigned i = 0; i < filters.size(); ++i) {
861         const FilterOperation* filterOperation = filters.at(i);
862         switch (filterOperation->type()) {
863         case FilterOperation::REFERENCE:
864             return false;
865         case FilterOperation::DROP_SHADOW:
866             // FIXME: For now we can only handle drop-shadow is if it's last in the list
867             if (i < (filters.size() - 1))
868                 return false;
869             break;
870         default:
871             break;
872         }
873     }
874
875     return true;
876 }
877
878 #if ENABLE(CSS_COMPOSITING)
879 void PlatformCALayerCocoa::setBlendMode(BlendMode blendMode)
880 {
881     PlatformCAFilters::setBlendingFiltersOnLayer(platformLayer(), blendMode);
882 }
883 #endif
884
885 void PlatformCALayerCocoa::setName(const String& value)
886 {
887     BEGIN_BLOCK_OBJC_EXCEPTIONS
888     [m_layer setName:value];
889     END_BLOCK_OBJC_EXCEPTIONS
890 }
891
892 void PlatformCALayerCocoa::setSpeed(float value)
893 {
894     BEGIN_BLOCK_OBJC_EXCEPTIONS
895     [m_layer setSpeed:value];
896     END_BLOCK_OBJC_EXCEPTIONS
897 }
898
899 void PlatformCALayerCocoa::setTimeOffset(CFTimeInterval value)
900 {
901     BEGIN_BLOCK_OBJC_EXCEPTIONS
902     [m_layer setTimeOffset:value];
903     END_BLOCK_OBJC_EXCEPTIONS
904 }
905
906 float PlatformCALayerCocoa::contentsScale() const
907 {
908     return [m_layer contentsScale];
909 }
910
911 void PlatformCALayerCocoa::setContentsScale(float value)
912 {
913     BEGIN_BLOCK_OBJC_EXCEPTIONS
914     [m_layer setContentsScale:value];
915 #if PLATFORM(IOS_FAMILY)
916     [m_layer setRasterizationScale:value];
917 #endif
918     END_BLOCK_OBJC_EXCEPTIONS
919 }
920
921 float PlatformCALayerCocoa::cornerRadius() const
922 {
923     return [m_layer cornerRadius];
924 }
925
926 void PlatformCALayerCocoa::setCornerRadius(float value)
927 {
928     BEGIN_BLOCK_OBJC_EXCEPTIONS
929     [m_layer setCornerRadius:value];
930     END_BLOCK_OBJC_EXCEPTIONS
931 }
932
933 void PlatformCALayerCocoa::setEdgeAntialiasingMask(unsigned mask)
934 {
935     BEGIN_BLOCK_OBJC_EXCEPTIONS
936     [m_layer setEdgeAntialiasingMask:mask];
937     END_BLOCK_OBJC_EXCEPTIONS
938 }
939
940 FloatRoundedRect PlatformCALayerCocoa::shapeRoundedRect() const
941 {
942     ASSERT(m_layerType == LayerTypeShapeLayer);
943     if (m_shapeRoundedRect)
944         return *m_shapeRoundedRect;
945
946     return FloatRoundedRect();
947 }
948
949 void PlatformCALayerCocoa::setShapeRoundedRect(const FloatRoundedRect& roundedRect)
950 {
951     ASSERT(m_layerType == LayerTypeShapeLayer);
952     m_shapeRoundedRect = std::make_unique<FloatRoundedRect>(roundedRect);
953
954     BEGIN_BLOCK_OBJC_EXCEPTIONS
955     Path shapePath;
956     shapePath.addRoundedRect(roundedRect);
957     [(CAShapeLayer *)m_layer setPath:shapePath.platformPath()];
958     END_BLOCK_OBJC_EXCEPTIONS
959 }
960
961 WindRule PlatformCALayerCocoa::shapeWindRule() const
962 {
963     ASSERT(m_layerType == LayerTypeShapeLayer);
964
965     NSString *fillRule = [(CAShapeLayer *)m_layer fillRule];
966     if ([fillRule isEqualToString:@"even-odd"])
967         return WindRule::EvenOdd;
968
969     return WindRule::NonZero;
970 }
971
972 void PlatformCALayerCocoa::setShapeWindRule(WindRule windRule)
973 {
974     ASSERT(m_layerType == LayerTypeShapeLayer);
975
976     switch (windRule) {
977     case WindRule::NonZero:
978         [(CAShapeLayer *)m_layer setFillRule:@"non-zero"];
979         break;
980     case WindRule::EvenOdd:
981         [(CAShapeLayer *)m_layer setFillRule:@"even-odd"];
982         break;
983     }
984 }
985
986 Path PlatformCALayerCocoa::shapePath() const
987 {
988     ASSERT(m_layerType == LayerTypeShapeLayer);
989
990     BEGIN_BLOCK_OBJC_EXCEPTIONS
991     return Path(CGPathCreateMutableCopy([(CAShapeLayer *)m_layer path]));
992     END_BLOCK_OBJC_EXCEPTIONS
993 }
994
995 void PlatformCALayerCocoa::setShapePath(const Path& path)
996 {
997     ASSERT(m_layerType == LayerTypeShapeLayer);
998
999     BEGIN_BLOCK_OBJC_EXCEPTIONS
1000     [(CAShapeLayer *)m_layer setPath:path.platformPath()];
1001     END_BLOCK_OBJC_EXCEPTIONS
1002 }
1003
1004 bool PlatformCALayerCocoa::requiresCustomAppearanceUpdateOnBoundsChange() const
1005 {
1006     return m_customAppearance == GraphicsLayer::CustomAppearance::ScrollingShadow;
1007 }
1008
1009 void PlatformCALayerCocoa::updateCustomAppearance(GraphicsLayer::CustomAppearance appearance)
1010 {
1011     if (m_customAppearance == appearance)
1012         return;
1013
1014     m_customAppearance = appearance;
1015
1016 #if ENABLE(RUBBER_BANDING)
1017     switch (appearance) {
1018     case GraphicsLayer::CustomAppearance::None:
1019     case GraphicsLayer::CustomAppearance::LightBackdrop:
1020     case GraphicsLayer::CustomAppearance::DarkBackdrop:
1021         ScrollbarThemeMac::removeOverhangAreaBackground(platformLayer());
1022         ScrollbarThemeMac::removeOverhangAreaShadow(platformLayer());
1023         break;
1024     case GraphicsLayer::CustomAppearance::ScrollingOverhang:
1025         ScrollbarThemeMac::setUpOverhangAreaBackground(platformLayer());
1026         break;
1027     case GraphicsLayer::CustomAppearance::ScrollingShadow:
1028         ScrollbarThemeMac::setUpOverhangAreaShadow(platformLayer());
1029         break;
1030     }
1031 #endif
1032 }
1033
1034 GraphicsLayer::EmbeddedViewID PlatformCALayerCocoa::embeddedViewID() const
1035 {
1036     ASSERT_NOT_REACHED();
1037     return 0;
1038 }
1039
1040 static NSString *layerContentsFormat(bool acceleratesDrawing, bool wantsDeepColor, bool supportsSubpixelAntialiasedFonts)
1041 {
1042 #if PLATFORM(IOS_FAMILY)
1043     if (wantsDeepColor)
1044         return kCAContentsFormatRGBA10XR;
1045 #else
1046     UNUSED_PARAM(wantsDeepColor);
1047 #endif
1048
1049 #if PLATFORM(MAC)
1050     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
1051     if (supportsSubpixelAntialiasedFonts && acceleratesDrawing)
1052         return kCAContentsFormatRGBA8ColorRGBA8LinearGlyphMask;
1053     ALLOW_DEPRECATED_DECLARATIONS_END
1054 #else
1055     UNUSED_PARAM(supportsSubpixelAntialiasedFonts);
1056     UNUSED_PARAM(acceleratesDrawing);
1057 #endif
1058
1059     return nil;
1060 }
1061
1062 void PlatformCALayerCocoa::updateContentsFormat()
1063 {
1064     if (m_layerType == LayerTypeWebLayer || m_layerType == LayerTypeTiledBackingTileLayer) {
1065         BEGIN_BLOCK_OBJC_EXCEPTIONS
1066         if (NSString *formatString = layerContentsFormat(acceleratesDrawing(), wantsDeepColorBackingStore(), supportsSubpixelAntialiasedText()))
1067             [m_layer setContentsFormat:formatString];
1068         END_BLOCK_OBJC_EXCEPTIONS
1069     }
1070 }
1071
1072 TiledBacking* PlatformCALayerCocoa::tiledBacking()
1073 {
1074     if (!usesTiledBackingLayer())
1075         return nullptr;
1076
1077     WebTiledBackingLayer *tiledBackingLayer = static_cast<WebTiledBackingLayer *>(m_layer.get());
1078     return [tiledBackingLayer tiledBacking];
1079 }
1080
1081 #if PLATFORM(IOS_FAMILY)
1082 bool PlatformCALayer::isWebLayer()
1083 {
1084     BOOL result = NO;
1085     BEGIN_BLOCK_OBJC_EXCEPTIONS
1086     result = [m_layer isKindOfClass:[WebLayer self]];
1087     END_BLOCK_OBJC_EXCEPTIONS
1088     return result;
1089 }
1090
1091 void PlatformCALayer::setBoundsOnMainThread(CGRect bounds)
1092 {
1093     CALayer *layer = m_layer.get();
1094     dispatch_async(dispatch_get_main_queue(), ^{
1095         BEGIN_BLOCK_OBJC_EXCEPTIONS
1096         [layer setBounds:bounds];
1097         END_BLOCK_OBJC_EXCEPTIONS
1098     });
1099 }
1100
1101 void PlatformCALayer::setPositionOnMainThread(CGPoint position)
1102 {
1103     CALayer *layer = m_layer.get();
1104     dispatch_async(dispatch_get_main_queue(), ^{
1105         BEGIN_BLOCK_OBJC_EXCEPTIONS
1106         [layer setPosition:position];
1107         END_BLOCK_OBJC_EXCEPTIONS
1108     });
1109 }
1110
1111 void PlatformCALayer::setAnchorPointOnMainThread(FloatPoint3D value)
1112 {
1113     CALayer *layer = m_layer.get();
1114     dispatch_async(dispatch_get_main_queue(), ^{
1115         BEGIN_BLOCK_OBJC_EXCEPTIONS
1116         [layer setAnchorPoint:CGPointMake(value.x(), value.y())];
1117         [layer setAnchorPointZ:value.z()];
1118         END_BLOCK_OBJC_EXCEPTIONS
1119     });
1120 }
1121 #endif // PLATFORM(IOS_FAMILY)
1122
1123 PlatformCALayer::RepaintRectList PlatformCALayer::collectRectsToPaint(CGContextRef context, PlatformCALayer* platformCALayer)
1124 {
1125     __block double totalRectArea = 0;
1126     __block unsigned rectCount = 0;
1127     __block RepaintRectList dirtyRects;
1128     
1129     platformCALayer->enumerateRectsBeingDrawn(context, ^(CGRect rect) {
1130         if (++rectCount > webLayerMaxRectsToPaint)
1131             return;
1132         
1133         totalRectArea += rect.size.width * rect.size.height;
1134         dirtyRects.append(rect);
1135     });
1136     
1137     FloatRect clipBounds = CGContextGetClipBoundingBox(context);
1138     double clipArea = clipBounds.width() * clipBounds.height();
1139     
1140     if (rectCount >= webLayerMaxRectsToPaint || totalRectArea >= clipArea * webLayerWastedSpaceThreshold) {
1141         dirtyRects.clear();
1142         dirtyRects.append(clipBounds);
1143     }
1144     
1145     return dirtyRects;
1146 }
1147
1148 void PlatformCALayer::drawLayerContents(CGContextRef context, WebCore::PlatformCALayer* platformCALayer, RepaintRectList& dirtyRects, GraphicsLayerPaintBehavior layerPaintBehavior)
1149 {
1150     WebCore::PlatformCALayerClient* layerContents = platformCALayer->owner();
1151     if (!layerContents)
1152         return;
1153
1154     if (!layerContents->platformCALayerRepaintCount(platformCALayer))
1155         layerPaintBehavior |= GraphicsLayerPaintFirstTilePaint;
1156
1157 #if PLATFORM(IOS_FAMILY)
1158     WKSetCurrentGraphicsContext(context);
1159 #endif
1160     
1161     CGContextSaveGState(context);
1162     
1163     // We never use CompositingCoordinatesOrientation::BottomUp on Mac.
1164     ASSERT(layerContents->platformCALayerContentsOrientation() == GraphicsLayer::CompositingCoordinatesOrientation::TopDown);
1165     
1166 #if PLATFORM(IOS_FAMILY)
1167     FontAntialiasingStateSaver fontAntialiasingState(context, [platformCALayer->platformLayer() isOpaque]);
1168     fontAntialiasingState.setup([WAKWindow hasLandscapeOrientation]);
1169 #else
1170     [NSGraphicsContext saveGraphicsState];
1171     
1172     // Set up an NSGraphicsContext for the context, so that parts of AppKit that rely on
1173     // the current NSGraphicsContext (e.g. NSCell drawing) get the right one.
1174     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
1175     NSGraphicsContext* layerContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:YES];
1176     ALLOW_DEPRECATED_DECLARATIONS_END
1177     [NSGraphicsContext setCurrentContext:layerContext];
1178 #endif
1179     
1180     {
1181         GraphicsContext graphicsContext(context);
1182         graphicsContext.setIsCALayerContext(true);
1183         graphicsContext.setIsAcceleratedContext(platformCALayer->acceleratesDrawing());
1184         
1185         if (!layerContents->platformCALayerContentsOpaque() && !platformCALayer->supportsSubpixelAntialiasedText() && FontCascade::isSubpixelAntialiasingAvailable()) {
1186             // Turn off font smoothing to improve the appearance of text rendered onto a transparent background.
1187             graphicsContext.setShouldSmoothFonts(false);
1188         }
1189         
1190 #if PLATFORM(MAC)
1191         // It's important to get the clip from the context, because it may be significantly
1192         // smaller than the layer bounds (e.g. tiled layers)
1193         ThemeMac::setFocusRingClipRect(CGContextGetClipBoundingBox(context));
1194 #endif
1195         
1196         for (const auto& rect : dirtyRects) {
1197             GraphicsContextStateSaver stateSaver(graphicsContext);
1198             graphicsContext.clip(rect);
1199             
1200             layerContents->platformCALayerPaintContents(platformCALayer, graphicsContext, rect, layerPaintBehavior);
1201         }
1202         
1203 #if PLATFORM(IOS_FAMILY)
1204         fontAntialiasingState.restore();
1205 #else
1206         ThemeMac::setFocusRingClipRect(FloatRect());
1207         
1208         [NSGraphicsContext restoreGraphicsState];
1209 #endif
1210     }
1211
1212     CGContextRestoreGState(context);
1213
1214     // Re-fetch the layer owner, since <rdar://problem/9125151> indicates that it might have been destroyed during painting.
1215     layerContents = platformCALayer->owner();
1216     ASSERT(layerContents);
1217     
1218     // Always update the repaint count so that it's accurate even if the count itself is not shown. This will be useful
1219     // for the Web Inspector feeding this information through the LayerTreeAgent.
1220     int repaintCount = layerContents->platformCALayerIncrementRepaintCount(platformCALayer);
1221
1222     if (!platformCALayer->usesTiledBackingLayer() && layerContents && layerContents->platformCALayerShowRepaintCounter(platformCALayer))
1223         drawRepaintIndicator(context, platformCALayer, repaintCount, nullptr);
1224 }
1225
1226 CGRect PlatformCALayer::frameForLayer(const PlatformLayer* tileLayer)
1227 {
1228     return [tileLayer frame];
1229 }
1230
1231 Ref<PlatformCALayer> PlatformCALayerCocoa::createCompatibleLayer(PlatformCALayer::LayerType layerType, PlatformCALayerClient* client) const
1232 {
1233     return PlatformCALayerCocoa::create(layerType, client);
1234 }
1235
1236 void PlatformCALayerCocoa::enumerateRectsBeingDrawn(CGContextRef context, void (^block)(CGRect))
1237 {
1238     CGSRegionObj region = (CGSRegionObj)[m_layer regionBeingDrawn];
1239     if (!region) {
1240         block(CGContextGetClipBoundingBox(context));
1241         return;
1242     }
1243
1244     CGAffineTransform inverseTransform = CGAffineTransformInvert(CGContextGetCTM(context));
1245     CGSRegionEnumeratorObj enumerator = CGSRegionEnumerator(region);
1246     const CGRect* nextRect;
1247     while ((nextRect = CGSNextRect(enumerator))) {
1248         CGRect rectToDraw = CGRectApplyAffineTransform(*nextRect, inverseTransform);
1249         block(rectToDraw);
1250     }
1251     
1252     CGSReleaseRegionEnumerator(enumerator);
1253 }
1254
1255 unsigned PlatformCALayerCocoa::backingStoreBytesPerPixel() const
1256 {
1257 #if PLATFORM(IOS_FAMILY)
1258     if (wantsDeepColorBackingStore())
1259         return isOpaque() ? 4 : 5;
1260 #endif
1261
1262 #if PLATFORM(MAC)
1263     if (!isOpaque() && supportsSubpixelAntialiasedText())
1264         return 8;
1265 #endif
1266     return 4;
1267 }
1268
1269 AVPlayerLayer *PlatformCALayerCocoa::avPlayerLayer() const
1270 {
1271     if (layerType() != LayerTypeAVPlayerLayer)
1272         return nil;
1273
1274     if ([platformLayer() isKindOfClass:getAVPlayerLayerClass()])
1275         return static_cast<AVPlayerLayer *>(platformLayer());
1276
1277     if ([platformLayer() isKindOfClass:objc_getClass("WebVideoContainerLayer")]) {
1278         ASSERT([platformLayer() sublayers].count == 1);
1279         ASSERT([[platformLayer() sublayers][0] isKindOfClass:getAVPlayerLayerClass()]);
1280         return static_cast<AVPlayerLayer *>([platformLayer() sublayers][0]);
1281     }
1282
1283     ASSERT_NOT_REACHED();
1284     return nil;
1285 }
1286
1287 } // namespace WebCore