b362c7516dd5ca7bf1db1461bea0a43f8e203657
[WebKit-https.git] / Source / WebKit2 / Shared / mac / RemoteLayerTreePropertyApplier.mm
1 /*
2  * Copyright (C) 2013 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "RemoteLayerTreePropertyApplier.h"
28
29 #import "PlatformCALayerRemote.h"
30 #import <QuartzCore/CALayer.h>
31 #import <WebCore/BlockExceptions.h>
32 #import <WebCore/PlatformCAFilters.h>
33 #import <WebCore/ScrollbarThemeMac.h>
34 #if PLATFORM(IOS)
35 #import <UIKit/UIView.h>
36 #endif
37
38 using namespace WebCore;
39
40 #if PLATFORM(IOS)
41 @interface UIView (WKUIViewUtilities)
42 - (void)_web_setSubviews:(NSArray *)subviews;
43 @end
44
45 @implementation UIView (WKUIViewUtilities)
46
47 - (void)_web_setSubviews:(NSArray *)subviews
48 {
49     for (UIView* subview in self.subviews)
50         [subview removeFromSuperview];
51
52     for (UIView* view in subviews)
53         [self addSubview:view];
54 }
55
56 @end
57 #endif
58
59 namespace WebKit {
60
61 static RetainPtr<CGColorRef> cgColorFromColor(Color color)
62 {
63     CGFloat components[4];
64     color.getRGBA(components[0], components[1], components[2], components[3]);
65
66     RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
67     return adoptCF(CGColorCreate(colorSpace.get(), components));
68 }
69
70 static NSString *toCAFilterType(PlatformCALayer::FilterType type)
71 {
72     switch (type) {
73     case PlatformCALayer::Linear:
74         return kCAFilterLinear;
75     case PlatformCALayer::Nearest:
76         return kCAFilterNearest;
77     case PlatformCALayer::Trilinear:
78         return kCAFilterTrilinear;
79     };
80     
81     ASSERT_NOT_REACHED();
82     return 0;
83 }
84
85 static void updateCustomAppearance(CALayer *layer, GraphicsLayer::CustomAppearance customAppearance)
86 {
87 #if ENABLE(RUBBER_BANDING)
88     switch (customAppearance) {
89     case GraphicsLayer::NoCustomAppearance:
90         ScrollbarThemeMac::removeOverhangAreaBackground(layer);
91         ScrollbarThemeMac::removeOverhangAreaShadow(layer);
92         break;
93     case GraphicsLayer::ScrollingOverhang:
94         ScrollbarThemeMac::setUpOverhangAreaBackground(layer);
95         break;
96     case GraphicsLayer::ScrollingShadow:
97         ScrollbarThemeMac::setUpOverhangAreaShadow(layer);
98         break;
99     }
100 #else
101     UNUSED_PARAM(customAppearance);
102 #endif
103 }
104
105 static void applyPropertiesToLayer(CALayer *layer, const RemoteLayerTreeTransaction::LayerProperties& properties)
106 {
107     if (properties.changedProperties & RemoteLayerTreeTransaction::NameChanged)
108         layer.name = properties.name;
109
110     if (properties.changedProperties & RemoteLayerTreeTransaction::PositionChanged) {
111         layer.position = CGPointMake(properties.position.x(), properties.position.y());
112         layer.zPosition = properties.position.z();
113     }
114
115     if (properties.changedProperties & RemoteLayerTreeTransaction::AnchorPointChanged) {
116         layer.anchorPoint = CGPointMake(properties.anchorPoint.x(), properties.anchorPoint.y());
117         layer.anchorPointZ = properties.anchorPoint.z();
118     }
119
120     if (properties.changedProperties & RemoteLayerTreeTransaction::SizeChanged)
121         layer.bounds = FloatRect(FloatPoint(), properties.size);
122
123     if (properties.changedProperties & RemoteLayerTreeTransaction::BackgroundColorChanged)
124         layer.backgroundColor = cgColorFromColor(properties.backgroundColor).get();
125
126     if (properties.changedProperties & RemoteLayerTreeTransaction::BorderColorChanged)
127         layer.borderColor = cgColorFromColor(properties.borderColor).get();
128
129     if (properties.changedProperties & RemoteLayerTreeTransaction::BorderWidthChanged)
130         layer.borderWidth = properties.borderWidth;
131
132     if (properties.changedProperties & RemoteLayerTreeTransaction::OpacityChanged)
133         layer.opacity = properties.opacity;
134
135     if (properties.changedProperties & RemoteLayerTreeTransaction::TransformChanged)
136         layer.transform = properties.transform ? (CATransform3D)*properties.transform.get() : CATransform3DIdentity;
137
138     if (properties.changedProperties & RemoteLayerTreeTransaction::SublayerTransformChanged)
139         layer.sublayerTransform = properties.sublayerTransform ? (CATransform3D)*properties.sublayerTransform.get() : CATransform3DIdentity;
140
141     if (properties.changedProperties & RemoteLayerTreeTransaction::HiddenChanged)
142         layer.hidden = properties.hidden;
143
144     if (properties.changedProperties & RemoteLayerTreeTransaction::GeometryFlippedChanged)
145         layer.geometryFlipped = properties.geometryFlipped;
146
147     if (properties.changedProperties & RemoteLayerTreeTransaction::DoubleSidedChanged)
148         layer.doubleSided = properties.doubleSided;
149
150     if (properties.changedProperties & RemoteLayerTreeTransaction::MasksToBoundsChanged)
151         layer.masksToBounds = properties.masksToBounds;
152
153     if (properties.changedProperties & RemoteLayerTreeTransaction::OpaqueChanged)
154         layer.opaque = properties.opaque;
155
156     if (properties.changedProperties & RemoteLayerTreeTransaction::ContentsRectChanged)
157         layer.contentsRect = properties.contentsRect;
158
159     if (properties.changedProperties & RemoteLayerTreeTransaction::ContentsScaleChanged)
160         layer.contentsScale = properties.contentsScale;
161
162     if (properties.changedProperties & RemoteLayerTreeTransaction::MinificationFilterChanged)
163         layer.minificationFilter = toCAFilterType(properties.minificationFilter);
164
165     if (properties.changedProperties & RemoteLayerTreeTransaction::MagnificationFilterChanged)
166         layer.magnificationFilter = toCAFilterType(properties.magnificationFilter);
167
168     if (properties.changedProperties & RemoteLayerTreeTransaction::SpeedChanged)
169         layer.speed = properties.speed;
170
171     if (properties.changedProperties & RemoteLayerTreeTransaction::TimeOffsetChanged)
172         layer.timeOffset = properties.timeOffset;
173
174     if (properties.changedProperties & RemoteLayerTreeTransaction::BackingStoreChanged) {
175         if (RemoteLayerBackingStore* backingStore = properties.backingStore.get()) {
176 #if USE(IOSURFACE)
177             if (backingStore->acceleratesDrawing())
178                 layer.contents = (id)backingStore->surface().get();
179             else
180                 layer.contents = (id)backingStore->image().get();
181 #else
182             ASSERT(!backingStore->acceleratesDrawing());
183             layer.contents = (id)backingStore->image().get();
184 #endif
185         } else
186             layer.contents = nil;
187     }
188
189     if (properties.changedProperties & RemoteLayerTreeTransaction::FiltersChanged)
190         PlatformCAFilters::setFiltersOnLayer(layer, properties.filters ? *properties.filters : FilterOperations());
191
192     if (properties.changedProperties & RemoteLayerTreeTransaction::EdgeAntialiasingMaskChanged)
193         layer.edgeAntialiasingMask = properties.edgeAntialiasingMask;
194
195     if (properties.changedProperties & RemoteLayerTreeTransaction::CustomAppearanceChanged)
196         updateCustomAppearance(layer, properties.customAppearance);
197 }
198
199 void RemoteLayerTreePropertyApplier::applyProperties(CALayer *layer, const RemoteLayerTreeTransaction::LayerProperties& properties, const RelatedLayerMap& relatedLayers)
200 {
201     BEGIN_BLOCK_OBJC_EXCEPTIONS;
202     applyPropertiesToLayer(layer, properties);
203
204     if (properties.changedProperties & RemoteLayerTreeTransaction::ChildrenChanged) {
205         RetainPtr<NSMutableArray> children = adoptNS([[NSMutableArray alloc] initWithCapacity:properties.children.size()]);
206         for (auto& child : properties.children) {
207             ASSERT(relatedLayers.get(child));
208             [children addObject:relatedLayers.get(child)];
209         }
210
211         layer.sublayers = children.get();
212     }
213
214     if (properties.changedProperties & RemoteLayerTreeTransaction::MaskLayerChanged) {
215         if (!properties.maskLayerID)
216             layer.mask = nullptr;
217         else {
218 #if PLATFORM(IOS)
219             UIView *maskView = relatedLayers.get(properties.maskLayerID);
220             // FIXME: need to check that the mask view is kept alive.
221             ASSERT(!maskView.layer.superlayer);
222             if (!maskView.layer.superlayer)
223                 layer.mask = maskView.layer;
224 #else
225             CALayer *maskLayer = relatedLayers.get(properties.maskLayerID);
226             ASSERT(!maskLayer.superlayer);
227             if (!maskLayer.superlayer)
228                 layer.mask = maskLayer;
229 #endif
230         }
231     }
232     END_BLOCK_OBJC_EXCEPTIONS;
233 }
234
235 #if PLATFORM(IOS)
236 void RemoteLayerTreePropertyApplier::applyProperties(UIView *view, const RemoteLayerTreeTransaction::LayerProperties& properties, const RelatedLayerMap& relatedLayers)
237 {
238     BEGIN_BLOCK_OBJC_EXCEPTIONS;
239     applyPropertiesToLayer(view.layer, properties);
240
241     if (properties.changedProperties & RemoteLayerTreeTransaction::ChildrenChanged) {
242         RetainPtr<NSMutableArray> children = adoptNS([[NSMutableArray alloc] initWithCapacity:properties.children.size()]);
243         for (auto& child : properties.children) {
244             ASSERT(relatedLayers.get(child));
245             [children addObject:relatedLayers.get(child)];
246         }
247
248         [view _web_setSubviews:children.get()];
249     }
250
251     if (properties.changedProperties & RemoteLayerTreeTransaction::MaskLayerChanged) {
252         if (!properties.maskLayerID)
253             view.layer.mask = nullptr;
254         else {
255             UIView *maskView = relatedLayers.get(properties.maskLayerID);
256             // FIXME: need to check that the mask view is kept alive.
257             ASSERT(!maskView.layer.superlayer);
258             if (!maskView.layer.superlayer)
259                 view.layer.mask = maskView.layer;
260         }
261     }
262     END_BLOCK_OBJC_EXCEPTIONS;
263 }
264 #endif
265
266 } // namespace WebKit