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_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_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::animationStarted(CFTimeInterval beginTime)
240{
241    if (m_owner)
242        m_owner->platformCALayerAnimationStarted(beginTime);
243}
244
245void PlatformCALayer::setNeedsDisplay(const FloatRect* dirtyRect)
246{
247    BEGIN_BLOCK_OBJC_EXCEPTIONS
248    if (dirtyRect)
249        [m_layer.get() setNeedsDisplayInRect:*dirtyRect];
250    else
251        [m_layer.get() setNeedsDisplay];
252    END_BLOCK_OBJC_EXCEPTIONS
253}
254
255void PlatformCALayer::setContentsChanged()
256{
257    BEGIN_BLOCK_OBJC_EXCEPTIONS
258    [m_layer.get() setContentsChanged];
259    END_BLOCK_OBJC_EXCEPTIONS
260}
261
262PlatformCALayer* PlatformCALayer::superlayer() const
263{
264    return platformCALayer([m_layer.get() superlayer]);
265}
266
267void PlatformCALayer::removeFromSuperlayer()
268{
269    BEGIN_BLOCK_OBJC_EXCEPTIONS
270    [m_layer.get() removeFromSuperlayer];
271    END_BLOCK_OBJC_EXCEPTIONS
272}
273
274void PlatformCALayer::setSublayers(const PlatformCALayerList& list)
275{
276    // Short circuiting here not only avoids the allocation of sublayers, but avoids <rdar://problem/7390716> (see below)
277    if (list.size() == 0) {
278        removeAllSublayers();
279        return;
280    }
281
282    BEGIN_BLOCK_OBJC_EXCEPTIONS
283    NSMutableArray* sublayers = [[NSMutableArray alloc] init];
284    for (size_t i = 0; i < list.size(); ++i)
285        [sublayers addObject:list[i]->m_layer.get()];
286
287    [m_layer.get() setSublayers:sublayers];
288    [sublayers release];
289    END_BLOCK_OBJC_EXCEPTIONS
290}
291
292void PlatformCALayer::removeAllSublayers()
293{
294    // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
295    BEGIN_BLOCK_OBJC_EXCEPTIONS
296    if (objc_collectingEnabled())
297        while ([[m_layer.get() sublayers] count])
298            [[[m_layer.get() sublayers] objectAtIndex:0] removeFromSuperlayer];
299    else
300        [m_layer.get() setSublayers:nil];
301    END_BLOCK_OBJC_EXCEPTIONS
302}
303
304void PlatformCALayer::appendSublayer(PlatformCALayer* layer)
305{
306    BEGIN_BLOCK_OBJC_EXCEPTIONS
307    [m_layer.get() addSublayer:layer->m_layer.get()];
308    END_BLOCK_OBJC_EXCEPTIONS
309}
310
311void PlatformCALayer::insertSublayer(PlatformCALayer* layer, size_t index)
312{
313    BEGIN_BLOCK_OBJC_EXCEPTIONS
314    [m_layer.get() insertSublayer:layer->m_layer.get() atIndex:index];
315    END_BLOCK_OBJC_EXCEPTIONS
316}
317
318void PlatformCALayer::replaceSublayer(PlatformCALayer* reference, PlatformCALayer* layer)
319{
320    BEGIN_BLOCK_OBJC_EXCEPTIONS
321    [m_layer.get() replaceSublayer:reference->m_layer.get() with:layer->m_layer.get()];
322    END_BLOCK_OBJC_EXCEPTIONS
323}
324
325size_t PlatformCALayer::sublayerCount() const
326{
327    return [[m_layer.get() sublayers] count];
328}
329
330void PlatformCALayer::adoptSublayers(PlatformCALayer* source)
331{
332    // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
333    NSArray* sublayers = [source->m_layer.get() sublayers];
334
335    if (objc_collectingEnabled() && ![sublayers count]) {
336        BEGIN_BLOCK_OBJC_EXCEPTIONS
337        while ([[m_layer.get() sublayers] count])
338            [[[m_layer.get() sublayers] objectAtIndex:0] removeFromSuperlayer];
339        END_BLOCK_OBJC_EXCEPTIONS
340        return;
341    }
342
343    BEGIN_BLOCK_OBJC_EXCEPTIONS
344    [m_layer.get() setSublayers:sublayers];
345    END_BLOCK_OBJC_EXCEPTIONS
346}
347
348void PlatformCALayer::addAnimationForKey(const String& key, PlatformCAAnimation* animation)
349{
350    // Add the delegate
351    if (!m_delegate) {
352        WebAnimationDelegate* webAnimationDelegate = [[WebAnimationDelegate alloc] init];
353        m_delegate.adoptNS(webAnimationDelegate);
354        [webAnimationDelegate setOwner:this];
355    }
356
357    CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>(animation->platformAnimation());
358
359    if (![propertyAnimation delegate])
360        [propertyAnimation setDelegate:static_cast<id>(m_delegate.get())];
361
362    BEGIN_BLOCK_OBJC_EXCEPTIONS
363    [m_layer.get() addAnimation:animation->m_animation.get() forKey:key];
364    END_BLOCK_OBJC_EXCEPTIONS
365}
366
367void PlatformCALayer::removeAnimationForKey(const String& key)
368{
369    BEGIN_BLOCK_OBJC_EXCEPTIONS
370    [m_layer.get() removeAnimationForKey:key];
371    END_BLOCK_OBJC_EXCEPTIONS
372}
373
374PassRefPtr<PlatformCAAnimation> PlatformCALayer::animationForKey(const String& key)
375{
376    CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>([m_layer.get() animationForKey:key]);
377    if (!propertyAnimation)
378        return 0;
379    return PlatformCAAnimation::create(propertyAnimation);
380}
381
382PlatformCALayer* PlatformCALayer::mask() const
383{
384    return platformCALayer([m_layer.get() mask]);
385}
386
387void PlatformCALayer::setMask(PlatformCALayer* layer)
388{
389    BEGIN_BLOCK_OBJC_EXCEPTIONS
390    [m_layer.get() setMask:layer ? layer->platformLayer() : 0];
391    END_BLOCK_OBJC_EXCEPTIONS
392}
393
394bool PlatformCALayer::isOpaque() const
395{
396    return [m_layer.get() isOpaque];
397}
398
399void PlatformCALayer::setOpaque(bool value)
400{
401    BEGIN_BLOCK_OBJC_EXCEPTIONS
402    [m_layer.get() setOpaque:value];
403    END_BLOCK_OBJC_EXCEPTIONS
404}
405
406FloatRect PlatformCALayer::bounds() const
407{
408    return [m_layer.get() bounds];
409}
410
411void PlatformCALayer::setBounds(const FloatRect& value)
412{
413    BEGIN_BLOCK_OBJC_EXCEPTIONS
414    [m_layer.get() setBounds:value];
415    END_BLOCK_OBJC_EXCEPTIONS
416}
417
418FloatPoint3D PlatformCALayer::position() const
419{
420    CGPoint point = [m_layer.get() position];
421    return FloatPoint3D(point.x, point.y, [m_layer.get() zPosition]);
422}
423
424void PlatformCALayer::setPosition(const FloatPoint3D& value)
425{
426    BEGIN_BLOCK_OBJC_EXCEPTIONS
427    [m_layer.get() setPosition:CGPointMake(value.x(), value.y())];
428    [m_layer.get() setZPosition:value.z()];
429    END_BLOCK_OBJC_EXCEPTIONS
430}
431
432FloatPoint3D PlatformCALayer::anchorPoint() const
433{
434    CGPoint point = [m_layer.get() anchorPoint];
435    float z = 0;
436#if HAVE_MODERN_QUARTZCORE
437    z = [m_layer.get() anchorPointZ];
438#endif
439    return FloatPoint3D(point.x, point.y, z);
440}
441
442void PlatformCALayer::setAnchorPoint(const FloatPoint3D& value)
443{
444    BEGIN_BLOCK_OBJC_EXCEPTIONS
445    [m_layer.get() setAnchorPoint:CGPointMake(value.x(), value.y())];
446#if HAVE_MODERN_QUARTZCORE
447    [m_layer.get() setAnchorPointZ:value.z()];
448#endif
449    END_BLOCK_OBJC_EXCEPTIONS
450}
451
452TransformationMatrix PlatformCALayer::transform() const
453{
454    return [m_layer.get() transform];
455}
456
457void PlatformCALayer::setTransform(const TransformationMatrix& value)
458{
459    BEGIN_BLOCK_OBJC_EXCEPTIONS
460    [m_layer.get() setTransform:value];
461    END_BLOCK_OBJC_EXCEPTIONS
462}
463
464TransformationMatrix PlatformCALayer::sublayerTransform() const
465{
466    return [m_layer.get() sublayerTransform];
467}
468
469void PlatformCALayer::setSublayerTransform(const TransformationMatrix& value)
470{
471    BEGIN_BLOCK_OBJC_EXCEPTIONS
472    [m_layer.get() setSublayerTransform:value];
473    END_BLOCK_OBJC_EXCEPTIONS
474}
475
476TransformationMatrix PlatformCALayer::contentsTransform() const
477{
478#if !HAVE_MODERN_QUARTZCORE
479    if (m_layerType != LayerTypeWebLayer)
480        return TransformationMatrix();
481
482    return [static_cast<WebLayer*>(m_layer.get()) contentsTransform];
483#else
484    return TransformationMatrix();
485#endif
486}
487
488void PlatformCALayer::setContentsTransform(const TransformationMatrix& value)
489{
490#if !HAVE_MODERN_QUARTZCORE
491    if (m_layerType != LayerTypeWebLayer)
492        return;
493
494    BEGIN_BLOCK_OBJC_EXCEPTIONS
495    [m_layer.get() setContentsTransform:value];
496    END_BLOCK_OBJC_EXCEPTIONS
497#else
498    UNUSED_PARAM(value);
499#endif
500}
501
502bool PlatformCALayer::isHidden() const
503{
504    return [m_layer.get() isHidden];
505}
506
507void PlatformCALayer::setHidden(bool value)
508{
509    BEGIN_BLOCK_OBJC_EXCEPTIONS
510    [m_layer.get() setHidden:value];
511    END_BLOCK_OBJC_EXCEPTIONS
512}
513
514bool PlatformCALayer::isGeometryFlipped() const
515{
516#if HAVE_MODERN_QUARTZCORE
517    return [m_layer.get() isGeometryFlipped];
518#else
519    return false;
520#endif
521}
522
523void PlatformCALayer::setGeometryFlipped(bool value)
524{
525#if HAVE_MODERN_QUARTZCORE
526    BEGIN_BLOCK_OBJC_EXCEPTIONS
527    [m_layer.get() setGeometryFlipped:value];
528    END_BLOCK_OBJC_EXCEPTIONS
529#else
530    UNUSED_PARAM(value);
531#endif
532}
533
534bool PlatformCALayer::isDoubleSided() const
535{
536    return [m_layer.get() isDoubleSided];
537}
538
539void PlatformCALayer::setDoubleSided(bool value)
540{
541    BEGIN_BLOCK_OBJC_EXCEPTIONS
542    [m_layer.get() setDoubleSided:value];
543    END_BLOCK_OBJC_EXCEPTIONS
544}
545
546bool PlatformCALayer::masksToBounds() const
547{
548    return [m_layer.get() masksToBounds];
549}
550
551void PlatformCALayer::setMasksToBounds(bool value)
552{
553    BEGIN_BLOCK_OBJC_EXCEPTIONS
554    [m_layer.get() setMasksToBounds:value];
555    END_BLOCK_OBJC_EXCEPTIONS
556}
557
558bool PlatformCALayer::acceleratesDrawing() const
559{
560#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
561    return [m_layer.get() acceleratesDrawing];
562#else
563    return false;
564#endif
565}
566
567void PlatformCALayer::setAcceleratesDrawing(bool acceleratesDrawing)
568{
569#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
570    BEGIN_BLOCK_OBJC_EXCEPTIONS
571    [m_layer.get() setAcceleratesDrawing:acceleratesDrawing];
572    END_BLOCK_OBJC_EXCEPTIONS
573#else
574    UNUSED_PARAM(acceleratesDrawing);
575#endif
576}
577
578CFTypeRef PlatformCALayer::contents() const
579{
580    return [m_layer.get() contents];
581}
582
583void PlatformCALayer::setContents(CFTypeRef value)
584{
585    BEGIN_BLOCK_OBJC_EXCEPTIONS
586    [m_layer.get() setContents:static_cast<id>(const_cast<void*>(value))];
587    END_BLOCK_OBJC_EXCEPTIONS
588}
589
590FloatRect PlatformCALayer::contentsRect() const
591{
592    return [m_layer.get() contentsRect];
593}
594
595void PlatformCALayer::setContentsRect(const FloatRect& value)
596{
597    BEGIN_BLOCK_OBJC_EXCEPTIONS
598    [m_layer.get() setContentsRect:value];
599    END_BLOCK_OBJC_EXCEPTIONS
600}
601
602void PlatformCALayer::setMinificationFilter(FilterType value)
603{
604#if HAVE_MODERN_QUARTZCORE
605    BEGIN_BLOCK_OBJC_EXCEPTIONS
606    [m_layer.get() setMinificationFilter:toCAFilterType(value)];
607    END_BLOCK_OBJC_EXCEPTIONS
608#else
609    UNUSED_PARAM(value);
610#endif
611}
612
613void PlatformCALayer::setMagnificationFilter(FilterType value)
614{
615#if HAVE_MODERN_QUARTZCORE
616    BEGIN_BLOCK_OBJC_EXCEPTIONS
617    [m_layer.get() setMagnificationFilter:toCAFilterType(value)];
618    END_BLOCK_OBJC_EXCEPTIONS
619#else
620    UNUSED_PARAM(value);
621#endif
622}
623
624Color PlatformCALayer::backgroundColor() const
625{
626    return [m_layer.get() backgroundColor];
627}
628
629void PlatformCALayer::setBackgroundColor(const Color& value)
630{
631    CGFloat components[4];
632    value.getRGBA(components[0], components[1], components[2], components[3]);
633
634    RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
635    RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
636
637    BEGIN_BLOCK_OBJC_EXCEPTIONS
638    [m_layer.get() setBackgroundColor:color.get()];
639    END_BLOCK_OBJC_EXCEPTIONS
640}
641
642float PlatformCALayer::borderWidth() const
643{
644    return [m_layer.get() borderWidth];
645}
646
647void PlatformCALayer::setBorderWidth(float value)
648{
649    BEGIN_BLOCK_OBJC_EXCEPTIONS
650    [m_layer.get() setBorderWidth:value];
651    END_BLOCK_OBJC_EXCEPTIONS
652}
653
654Color PlatformCALayer::borderColor() const
655{
656    return [m_layer.get() borderColor];
657}
658
659void PlatformCALayer::setBorderColor(const Color& value)
660{
661    CGFloat components[4];
662    value.getRGBA(components[0], components[1], components[2], components[3]);
663
664    RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
665    RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
666
667    BEGIN_BLOCK_OBJC_EXCEPTIONS
668    [m_layer.get() setBorderColor:color.get()];
669    END_BLOCK_OBJC_EXCEPTIONS
670}
671
672float PlatformCALayer::opacity() const
673{
674    return [m_layer.get() opacity];
675}
676
677void PlatformCALayer::setOpacity(float value)
678{
679    BEGIN_BLOCK_OBJC_EXCEPTIONS
680    [m_layer.get() setOpacity:value];
681    END_BLOCK_OBJC_EXCEPTIONS
682}
683
684String PlatformCALayer::name() const
685{
686    return [m_layer.get() name];
687}
688
689void PlatformCALayer::setName(const String& value)
690{
691    BEGIN_BLOCK_OBJC_EXCEPTIONS
692    [m_layer.get() setName:value];
693    END_BLOCK_OBJC_EXCEPTIONS
694}
695
696FloatRect PlatformCALayer::frame() const
697{
698    return [m_layer.get() frame];
699}
700
701void PlatformCALayer::setFrame(const FloatRect& value)
702{
703    BEGIN_BLOCK_OBJC_EXCEPTIONS
704    [m_layer.get() setFrame:value];
705    END_BLOCK_OBJC_EXCEPTIONS
706}
707
708float PlatformCALayer::speed() const
709{
710    return [m_layer.get() speed];
711}
712
713void PlatformCALayer::setSpeed(float value)
714{
715    BEGIN_BLOCK_OBJC_EXCEPTIONS
716    [m_layer.get() setSpeed:value];
717    END_BLOCK_OBJC_EXCEPTIONS
718}
719
720CFTimeInterval PlatformCALayer::timeOffset() const
721{
722    return [m_layer.get() timeOffset];
723}
724
725void PlatformCALayer::setTimeOffset(CFTimeInterval value)
726{
727    BEGIN_BLOCK_OBJC_EXCEPTIONS
728    [m_layer.get() setTimeOffset:value];
729    END_BLOCK_OBJC_EXCEPTIONS
730}
731
732float PlatformCALayer::contentsScale() const
733{
734#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
735    return [m_layer.get() contentsScale];
736#else
737    return 1;
738#endif
739}
740
741void PlatformCALayer::setContentsScale(float value)
742{
743#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
744    BEGIN_BLOCK_OBJC_EXCEPTIONS
745    [m_layer.get() setContentsScale:value];
746    END_BLOCK_OBJC_EXCEPTIONS
747#else
748    UNUSED_PARAM(value);
749#endif
750}
751
752#endif // USE(ACCELERATED_COMPOSITING)
753