1/*
2 * Copyright (C) 2010 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#import "PlatformCALayer.h"
31
32#import "BlockExceptions.h"
33#import "FloatConversion.h"
34#import "GraphicsContext.h"
35#import "GraphicsLayerCA.h"
36#import "WebLayer.h"
37#import "WebTiledLayer.h"
38#import <objc/objc-auto.h>
39#import <objc/objc-runtime.h>
40#import <QuartzCore/QuartzCore.h>
41#import <wtf/CurrentTime.h>
42#import <wtf/UnusedParam.h>
43
44#define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
45
46using namespace WebCore;
47
48// This value must be the same as in PlatformCAAnimationMac.mm
49static NSString * const WKNonZeroBeginTimeFlag = @"WKPlatformCAAnimationNonZeroBeginTimeFlag";
50
51static double mediaTimeToCurrentTime(CFTimeInterval t)
52{
53    return WTF::currentTime() + t - CACurrentMediaTime();
54}
55
56// Delegate for animationDidStart callback
57@interface WebAnimationDelegate : NSObject {
58    PlatformCALayer* m_owner;
59}
60
61- (void)animationDidStart:(CAAnimation *)anim;
62- (void)setOwner:(PlatformCALayer*)owner;
63
64@end
65
66@implementation WebAnimationDelegate
67
68- (void)animationDidStart:(CAAnimation *)animation
69{
70    // hasNonZeroBeginTime is stored in a key in the animation
71    bool hasNonZeroBeginTime = [[animation valueForKey:WKNonZeroBeginTimeFlag] boolValue];
72    CFTimeInterval startTime;
73
74    if (hasNonZeroBeginTime) {
75        // We don't know what time CA used to commit the animation, so just use the current time
76        // (even though this will be slightly off).
77        startTime = mediaTimeToCurrentTime(CACurrentMediaTime());
78    } else
79        startTime = mediaTimeToCurrentTime([animation beginTime]);
80
81    if (m_owner)
82        m_owner->animationStarted(startTime);
83}
84
85- (void)setOwner:(PlatformCALayer*)owner
86{
87    m_owner = owner;
88}
89
90@end
91
92@interface CALayer(Private)
93- (void)setContentsChanged;
94#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
95- (void)setAcceleratesDrawing:(BOOL)flag;
96- (BOOL)acceleratesDrawing;
97#endif
98@end
99
100static NSString * const platformCALayerPointer = @"WKPlatformCALayer";
101
102bool PlatformCALayer::isValueFunctionSupported()
103{
104    static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
105    return sHaveValueFunction;
106}
107
108void PlatformCALayer::setOwner(PlatformCALayerClient* owner)
109{
110    m_owner = owner;
111
112    // Change the delegate's owner if needed
113    if (m_delegate)
114        [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:this];
115}
116
117static NSDictionary* nullActionsDictionary()
118{
119    NSNull* nullValue = [NSNull null];
120    NSDictionary* actions = [NSDictionary dictionaryWithObjectsAndKeys:
121                             nullValue, @"anchorPoint",
122                             nullValue, @"bounds",
123                             nullValue, @"contents",
124                             nullValue, @"contentsRect",
125                             nullValue, @"opacity",
126                             nullValue, @"position",
127                             nullValue, @"shadowColor",
128                             nullValue, @"sublayerTransform",
129                             nullValue, @"sublayers",
130                             nullValue, @"transform",
131                             nullValue, @"zPosition",
132                             nil];
133    return actions;
134}
135
136#if HAVE_MODERN_QUARTZCORE
137static NSString* toCAFilterType(PlatformCALayer::FilterType type)
138{
139    switch (type) {
140    case PlatformCALayer::Linear: return kCAFilterLinear;
141    case PlatformCALayer::Nearest: return kCAFilterNearest;
142    case PlatformCALayer::Trilinear: return kCAFilterTrilinear;
143    default: return 0;
144    }
145}
146#endif
147
148PassRefPtr<PlatformCALayer> PlatformCALayer::create(LayerType layerType, PlatformCALayerClient* owner)
149{
150    return adoptRef(new PlatformCALayer(layerType, 0, owner));
151}
152
153PassRefPtr<PlatformCALayer> PlatformCALayer::create(void* platformLayer, PlatformCALayerClient* owner)
154{
155    return adoptRef(new PlatformCALayer(LayerTypeCustom, static_cast<PlatformLayer*>(platformLayer), owner));
156}
157
158PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformLayer* layer, PlatformCALayerClient* owner)
159    : m_owner(owner)
160{
161    BEGIN_BLOCK_OBJC_EXCEPTIONS
162    if (layer) {
163        m_layerType = LayerTypeCustom;
164        m_layer = layer;
165    } else {
166        m_layerType = layerType;
167
168        Class layerClass = Nil;
169        switch(layerType) {
170            case LayerTypeLayer:
171            case LayerTypeRootLayer:
172                layerClass = [CALayer class];
173                break;
174            case LayerTypeWebLayer:
175                layerClass = [WebLayer class];
176                break;
177            case LayerTypeTransformLayer:
178                layerClass = NSClassFromString(@"CATransformLayer");
179                break;
180            case LayerTypeWebTiledLayer:
181                layerClass = [WebTiledLayer class];
182                break;
183            case LayerTypeCustom:
184                break;
185        }
186
187        if (layerClass)
188            m_layer.adoptNS([[layerClass alloc] init]);
189    }
190
191    // Save a pointer to 'this' in the CALayer
192    [m_layer.get() setValue:[NSValue valueWithPointer:this] forKey:platformCALayerPointer];
193
194    // Clear all the implicit animations on the CALayer
195    [m_layer.get() setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]];
196
197    // If this is a TiledLayer, set some initial values
198    if (m_layerType == LayerTypeWebTiledLayer) {
199        WebTiledLayer* tiledLayer = static_cast<WebTiledLayer*>(m_layer.get());
200        [tiledLayer setTileSize:CGSizeMake(GraphicsLayerCA::kTiledLayerTileSize, GraphicsLayerCA::kTiledLayerTileSize)];
201        [tiledLayer setLevelsOfDetail:1];
202        [tiledLayer setLevelsOfDetailBias:0];
203        [tiledLayer setContentsGravity:@"bottomLeft"];
204    }
205
206    END_BLOCK_OBJC_EXCEPTIONS
207}
208
209PlatformCALayer::~PlatformCALayer()
210{
211    [m_layer.get() setValue:nil forKey:platformCALayerPointer];
212
213    // Clear the owner, which also clears it in the delegate to prevent attempts
214    // to use the GraphicsLayerCA after it has been destroyed.
215    setOwner(0);
216
217    // Remove the owner pointer from the delegate in case there is a pending animationStarted event.
218    [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:nil];
219}
220
221PlatformCALayer* PlatformCALayer::platformCALayer(void* platformLayer)
222{
223    if (!platformLayer)
224        return 0;
225
226    // Pointer to PlatformCALayer is kept in a key of the CALayer
227    PlatformCALayer* platformCALayer = nil;
228    BEGIN_BLOCK_OBJC_EXCEPTIONS
229    platformCALayer = static_cast<PlatformCALayer*>([[static_cast<CALayer*>(platformLayer) valueForKey:platformCALayerPointer] pointerValue]);
230    END_BLOCK_OBJC_EXCEPTIONS
231    return platformCALayer;
232}
233
234PlatformLayer* PlatformCALayer::platformLayer() const
235{
236    return m_layer.get();
237}
238
239void PlatformCALayer::setNeedsDisplay(const FloatRect* dirtyRect)
240{
241    BEGIN_BLOCK_OBJC_EXCEPTIONS
242    if (dirtyRect)
243        [m_layer.get() setNeedsDisplayInRect:*dirtyRect];
244    else
245        [m_layer.get() setNeedsDisplay];
246    END_BLOCK_OBJC_EXCEPTIONS
247}
248
249void PlatformCALayer::setContentsChanged()
250{
251    BEGIN_BLOCK_OBJC_EXCEPTIONS
252    [m_layer.get() setContentsChanged];
253    END_BLOCK_OBJC_EXCEPTIONS
254}
255
256PlatformCALayer* PlatformCALayer::superlayer() const
257{
258    return platformCALayer([m_layer.get() superlayer]);
259}
260
261void PlatformCALayer::removeFromSuperlayer()
262{
263    BEGIN_BLOCK_OBJC_EXCEPTIONS
264    [m_layer.get() removeFromSuperlayer];
265    END_BLOCK_OBJC_EXCEPTIONS
266}
267
268void PlatformCALayer::setSublayers(const PlatformCALayerList& list)
269{
270    // Short circuiting here not only avoids the allocation of sublayers, but avoids <rdar://problem/7390716> (see below)
271    if (list.size() == 0) {
272        removeAllSublayers();
273        return;
274    }
275
276    BEGIN_BLOCK_OBJC_EXCEPTIONS
277    NSMutableArray* sublayers = [[NSMutableArray alloc] init];
278    for (size_t i = 0; i < list.size(); ++i)
279        [sublayers addObject:list[i]->m_layer.get()];
280
281    [m_layer.get() setSublayers:sublayers];
282    [sublayers release];
283    END_BLOCK_OBJC_EXCEPTIONS
284}
285
286void PlatformCALayer::removeAllSublayers()
287{
288    // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
289    BEGIN_BLOCK_OBJC_EXCEPTIONS
290    if (objc_collectingEnabled())
291        while ([[m_layer.get() sublayers] count])
292            [[[m_layer.get() sublayers] objectAtIndex:0] removeFromSuperlayer];
293    else
294        [m_layer.get() setSublayers:nil];
295    END_BLOCK_OBJC_EXCEPTIONS
296}
297
298void PlatformCALayer::appendSublayer(PlatformCALayer* layer)
299{
300    BEGIN_BLOCK_OBJC_EXCEPTIONS
301    [m_layer.get() addSublayer:layer->m_layer.get()];
302    END_BLOCK_OBJC_EXCEPTIONS
303}
304
305void PlatformCALayer::insertSublayer(PlatformCALayer* layer, size_t index)
306{
307    BEGIN_BLOCK_OBJC_EXCEPTIONS
308    [m_layer.get() insertSublayer:layer->m_layer.get() atIndex:index];
309    END_BLOCK_OBJC_EXCEPTIONS
310}
311
312void PlatformCALayer::replaceSublayer(PlatformCALayer* reference, PlatformCALayer* layer)
313{
314    BEGIN_BLOCK_OBJC_EXCEPTIONS
315    [m_layer.get() replaceSublayer:reference->m_layer.get() with:layer->m_layer.get()];
316    END_BLOCK_OBJC_EXCEPTIONS
317}
318
319size_t PlatformCALayer::sublayerCount() const
320{
321    return [[m_layer.get() sublayers] count];
322}
323
324void PlatformCALayer::adoptSublayers(PlatformCALayer* source)
325{
326    // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
327    NSArray* sublayers = [source->m_layer.get() sublayers];
328
329    if (objc_collectingEnabled() && ![sublayers count]) {
330        BEGIN_BLOCK_OBJC_EXCEPTIONS
331        while ([[m_layer.get() sublayers] count])
332            [[[m_layer.get() sublayers] objectAtIndex:0] removeFromSuperlayer];
333        END_BLOCK_OBJC_EXCEPTIONS
334        return;
335    }
336
337    BEGIN_BLOCK_OBJC_EXCEPTIONS
338    [m_layer.get() setSublayers:sublayers];
339    END_BLOCK_OBJC_EXCEPTIONS
340}
341
342void PlatformCALayer::addAnimationForKey(const String& key, PlatformCAAnimation* animation)
343{
344    // Add the delegate
345    if (!m_delegate) {
346        WebAnimationDelegate* webAnimationDelegate = [[WebAnimationDelegate alloc] init];
347        m_delegate.adoptNS(webAnimationDelegate);
348        [webAnimationDelegate setOwner:this];
349    }
350
351    CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>(animation->platformAnimation());
352
353    if (![propertyAnimation delegate])
354        [propertyAnimation setDelegate:static_cast<id>(m_delegate.get())];
355
356    BEGIN_BLOCK_OBJC_EXCEPTIONS
357    [m_layer.get() addAnimation:animation->m_animation.get() forKey:key];
358    END_BLOCK_OBJC_EXCEPTIONS
359}
360
361void PlatformCALayer::removeAnimationForKey(const String& key)
362{
363    BEGIN_BLOCK_OBJC_EXCEPTIONS
364    [m_layer.get() removeAnimationForKey:key];
365    END_BLOCK_OBJC_EXCEPTIONS
366}
367
368PassRefPtr<PlatformCAAnimation> PlatformCALayer::animationForKey(const String& key)
369{
370    CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>([m_layer.get() animationForKey:key]);
371    if (!propertyAnimation)
372        return 0;
373    return PlatformCAAnimation::create(propertyAnimation);
374}
375
376PlatformCALayer* PlatformCALayer::mask() const
377{
378    return platformCALayer([m_layer.get() mask]);
379}
380
381void PlatformCALayer::setMask(PlatformCALayer* layer)
382{
383    BEGIN_BLOCK_OBJC_EXCEPTIONS
384    [m_layer.get() setMask:layer ? layer->platformLayer() : 0];
385    END_BLOCK_OBJC_EXCEPTIONS
386}
387
388bool PlatformCALayer::isOpaque() const
389{
390    return [m_layer.get() isOpaque];
391}
392
393void PlatformCALayer::setOpaque(bool value)
394{
395    BEGIN_BLOCK_OBJC_EXCEPTIONS
396    [m_layer.get() setOpaque:value];
397    END_BLOCK_OBJC_EXCEPTIONS
398}
399
400FloatRect PlatformCALayer::bounds() const
401{
402    return [m_layer.get() bounds];
403}
404
405void PlatformCALayer::setBounds(const FloatRect& value)
406{
407    BEGIN_BLOCK_OBJC_EXCEPTIONS
408    [m_layer.get() setBounds:value];
409    END_BLOCK_OBJC_EXCEPTIONS
410}
411
412FloatPoint3D PlatformCALayer::position() const
413{
414    CGPoint point = [m_layer.get() position];
415    return FloatPoint3D(point.x, point.y, [m_layer.get() zPosition]);
416}
417
418void PlatformCALayer::setPosition(const FloatPoint3D& value)
419{
420    BEGIN_BLOCK_OBJC_EXCEPTIONS
421    [m_layer.get() setPosition:CGPointMake(value.x(), value.y())];
422    [m_layer.get() setZPosition:value.z()];
423    END_BLOCK_OBJC_EXCEPTIONS
424}
425
426FloatPoint3D PlatformCALayer::anchorPoint() const
427{
428    CGPoint point = [m_layer.get() anchorPoint];
429    float z = 0;
430#if HAVE_MODERN_QUARTZCORE
431    z = [m_layer.get() anchorPointZ];
432#endif
433    return FloatPoint3D(point.x, point.y, z);
434}
435
436void PlatformCALayer::setAnchorPoint(const FloatPoint3D& value)
437{
438    BEGIN_BLOCK_OBJC_EXCEPTIONS
439    [m_layer.get() setAnchorPoint:CGPointMake(value.x(), value.y())];
440#if HAVE_MODERN_QUARTZCORE
441    [m_layer.get() setAnchorPointZ:value.z()];
442#endif
443    END_BLOCK_OBJC_EXCEPTIONS
444}
445
446TransformationMatrix PlatformCALayer::transform() const
447{
448    return [m_layer.get() transform];
449}
450
451void PlatformCALayer::setTransform(const TransformationMatrix& value)
452{
453    BEGIN_BLOCK_OBJC_EXCEPTIONS
454    [m_layer.get() setTransform:value];
455    END_BLOCK_OBJC_EXCEPTIONS
456}
457
458TransformationMatrix PlatformCALayer::sublayerTransform() const
459{
460    return [m_layer.get() sublayerTransform];
461}
462
463void PlatformCALayer::setSublayerTransform(const TransformationMatrix& value)
464{
465    BEGIN_BLOCK_OBJC_EXCEPTIONS
466    [m_layer.get() setSublayerTransform:value];
467    END_BLOCK_OBJC_EXCEPTIONS
468}
469
470TransformationMatrix PlatformCALayer::contentsTransform() const
471{
472#if !HAVE_MODERN_QUARTZCORE
473    if (m_layerType != LayerTypeWebLayer)
474        return TransformationMatrix();
475
476    return [static_cast<WebLayer*>(m_layer.get()) contentsTransform];
477#else
478    return TransformationMatrix();
479#endif
480}
481
482void PlatformCALayer::setContentsTransform(const TransformationMatrix& value)
483{
484#if !HAVE_MODERN_QUARTZCORE
485    if (m_layerType != LayerTypeWebLayer)
486        return;
487
488    BEGIN_BLOCK_OBJC_EXCEPTIONS
489    [m_layer.get() setContentsTransform:value];
490    END_BLOCK_OBJC_EXCEPTIONS
491#else
492    UNUSED_PARAM(value);
493#endif
494}
495
496bool PlatformCALayer::isHidden() const
497{
498    return [m_layer.get() isHidden];
499}
500
501void PlatformCALayer::setHidden(bool value)
502{
503    BEGIN_BLOCK_OBJC_EXCEPTIONS
504    [m_layer.get() setHidden:value];
505    END_BLOCK_OBJC_EXCEPTIONS
506}
507
508bool PlatformCALayer::isGeometryFlipped() const
509{
510#if HAVE_MODERN_QUARTZCORE
511    return [m_layer.get() isGeometryFlipped];
512#else
513    return false;
514#endif
515}
516
517void PlatformCALayer::setGeometryFlipped(bool value)
518{
519#if HAVE_MODERN_QUARTZCORE
520    BEGIN_BLOCK_OBJC_EXCEPTIONS
521    [m_layer.get() setGeometryFlipped:value];
522    END_BLOCK_OBJC_EXCEPTIONS
523#else
524    UNUSED_PARAM(value);
525#endif
526}
527
528bool PlatformCALayer::isDoubleSided() const
529{
530    return [m_layer.get() isDoubleSided];
531}
532
533void PlatformCALayer::setDoubleSided(bool value)
534{
535    BEGIN_BLOCK_OBJC_EXCEPTIONS
536    [m_layer.get() setDoubleSided:value];
537    END_BLOCK_OBJC_EXCEPTIONS
538}
539
540bool PlatformCALayer::masksToBounds() const
541{
542    return [m_layer.get() masksToBounds];
543}
544
545void PlatformCALayer::setMasksToBounds(bool value)
546{
547    BEGIN_BLOCK_OBJC_EXCEPTIONS
548    [m_layer.get() setMasksToBounds:value];
549    END_BLOCK_OBJC_EXCEPTIONS
550}
551
552bool PlatformCALayer::acceleratesDrawing() const
553{
554#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
555    return [m_layer.get() acceleratesDrawing];
556#else
557    return false;
558#endif
559}
560
561void PlatformCALayer::setAcceleratesDrawing(bool acceleratesDrawing)
562{
563#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
564    BEGIN_BLOCK_OBJC_EXCEPTIONS
565    [m_layer.get() setAcceleratesDrawing:acceleratesDrawing];
566    END_BLOCK_OBJC_EXCEPTIONS
567#else
568    UNUSED_PARAM(acceleratesDrawing);
569#endif
570}
571
572CFTypeRef PlatformCALayer::contents() const
573{
574    return [m_layer.get() contents];
575}
576
577void PlatformCALayer::setContents(CFTypeRef value)
578{
579    BEGIN_BLOCK_OBJC_EXCEPTIONS
580    [m_layer.get() setContents:static_cast<id>(const_cast<void*>(value))];
581    END_BLOCK_OBJC_EXCEPTIONS
582}
583
584FloatRect PlatformCALayer::contentsRect() const
585{
586    return [m_layer.get() contentsRect];
587}
588
589void PlatformCALayer::setContentsRect(const FloatRect& value)
590{
591    BEGIN_BLOCK_OBJC_EXCEPTIONS
592    [m_layer.get() setContentsRect:value];
593    END_BLOCK_OBJC_EXCEPTIONS
594}
595
596void PlatformCALayer::setMinificationFilter(FilterType value)
597{
598#if HAVE_MODERN_QUARTZCORE
599    BEGIN_BLOCK_OBJC_EXCEPTIONS
600    [m_layer.get() setMinificationFilter:toCAFilterType(value)];
601    END_BLOCK_OBJC_EXCEPTIONS
602#else
603    UNUSED_PARAM(value);
604#endif
605}
606
607void PlatformCALayer::setMagnificationFilter(FilterType value)
608{
609#if HAVE_MODERN_QUARTZCORE
610    BEGIN_BLOCK_OBJC_EXCEPTIONS
611    [m_layer.get() setMagnificationFilter:toCAFilterType(value)];
612    END_BLOCK_OBJC_EXCEPTIONS
613#else
614    UNUSED_PARAM(value);
615#endif
616}
617
618Color PlatformCALayer::backgroundColor() const
619{
620    return [m_layer.get() backgroundColor];
621}
622
623void PlatformCALayer::setBackgroundColor(const Color& value)
624{
625    CGFloat components[4];
626    value.getRGBA(components[0], components[1], components[2], components[3]);
627
628    RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
629    RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
630
631    BEGIN_BLOCK_OBJC_EXCEPTIONS
632    [m_layer.get() setBackgroundColor:color.get()];
633    END_BLOCK_OBJC_EXCEPTIONS
634}
635
636float PlatformCALayer::borderWidth() const
637{
638    return [m_layer.get() borderWidth];
639}
640
641void PlatformCALayer::setBorderWidth(float value)
642{
643    BEGIN_BLOCK_OBJC_EXCEPTIONS
644    [m_layer.get() setBorderWidth:value];
645    END_BLOCK_OBJC_EXCEPTIONS
646}
647
648Color PlatformCALayer::borderColor() const
649{
650    return [m_layer.get() borderColor];
651}
652
653void PlatformCALayer::setBorderColor(const Color& value)
654{
655    CGFloat components[4];
656    value.getRGBA(components[0], components[1], components[2], components[3]);
657
658    RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
659    RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
660
661    BEGIN_BLOCK_OBJC_EXCEPTIONS
662    [m_layer.get() setBorderColor:color.get()];
663    END_BLOCK_OBJC_EXCEPTIONS
664}
665
666float PlatformCALayer::opacity() const
667{
668    return [m_layer.get() opacity];
669}
670
671void PlatformCALayer::setOpacity(float value)
672{
673    BEGIN_BLOCK_OBJC_EXCEPTIONS
674    [m_layer.get() setOpacity:value];
675    END_BLOCK_OBJC_EXCEPTIONS
676}
677
678String PlatformCALayer::name() const
679{
680    return [m_layer.get() name];
681}
682
683void PlatformCALayer::setName(const String& value)
684{
685    BEGIN_BLOCK_OBJC_EXCEPTIONS
686    [m_layer.get() setName:value];
687    END_BLOCK_OBJC_EXCEPTIONS
688}
689
690FloatRect PlatformCALayer::frame() const
691{
692    return [m_layer.get() frame];
693}
694
695void PlatformCALayer::setFrame(const FloatRect& value)
696{
697    BEGIN_BLOCK_OBJC_EXCEPTIONS
698    [m_layer.get() setFrame:value];
699    END_BLOCK_OBJC_EXCEPTIONS
700}
701
702float PlatformCALayer::speed() const
703{
704    return [m_layer.get() speed];
705}
706
707void PlatformCALayer::setSpeed(float value)
708{
709    BEGIN_BLOCK_OBJC_EXCEPTIONS
710    [m_layer.get() setSpeed:value];
711    END_BLOCK_OBJC_EXCEPTIONS
712}
713
714CFTimeInterval PlatformCALayer::timeOffset() const
715{
716    return [m_layer.get() timeOffset];
717}
718
719void PlatformCALayer::setTimeOffset(CFTimeInterval value)
720{
721    BEGIN_BLOCK_OBJC_EXCEPTIONS
722    [m_layer.get() setTimeOffset:value];
723    END_BLOCK_OBJC_EXCEPTIONS
724}
725
726float PlatformCALayer::contentsScale() const
727{
728#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
729    return [m_layer.get() contentsScale];
730#else
731    return 1;
732#endif
733}
734
735void PlatformCALayer::setContentsScale(float value)
736{
737#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
738    BEGIN_BLOCK_OBJC_EXCEPTIONS
739    [m_layer.get() setContentsScale:value];
740    END_BLOCK_OBJC_EXCEPTIONS
741#else
742    UNUSED_PARAM(value);
743#endif
744}
745
746#endif // USE(ACCELERATED_COMPOSITING)
747