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 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#import "WebRenderLayer.h"
27
28#import "WebFrameInternal.h"
29#import <WebCore/Frame.h>
30#import <WebCore/FrameLoader.h>
31#import <WebCore/FrameLoaderClient.h>
32#import <WebCore/RenderLayer.h>
33#import <WebCore/RenderLayerBacking.h>
34#import <WebCore/RenderView.h>
35#import <WebCore/StyledElement.h>
36#import <wtf/text/StringBuilder.h>
37#import <wtf/text/WTFString.h>
38
39using namespace WebCore;
40
41@interface WebRenderLayer(Private)
42
43- (id)initWithRenderLayer:(RenderLayer *)layer;
44- (void)buildDescendantLayers:(RenderLayer*)rootLayer;
45
46@end
47
48@implementation WebRenderLayer
49
50+ (NSString *)nameForLayer:(RenderLayer*)layer
51{
52    const RenderObject& renderer = layer->renderer();
53    NSString *name = [NSString stringWithUTF8String:renderer.renderName()];
54
55    if (Element* element = renderer.node() && renderer.node()->isElementNode() ? toElement(renderer.node()) : 0) {
56        name = [name stringByAppendingFormat:@" %@", (NSString *)element->tagName()];
57        if (element->hasID())
58            name = [name stringByAppendingFormat:@" id=\"%@\"", (NSString *)element->getIdAttribute()];
59
60        if (element->hasClass()) {
61            StringBuilder classes;
62            for (size_t i = 0; i < element->classNames().size(); ++i) {
63                if (i > 0)
64                    classes.append(' ');
65                classes.append(element->classNames()[i]);
66            }
67            name = [name stringByAppendingFormat:@" class=\"%@\"", (NSString *)classes.toString()];
68        }
69    }
70
71    if (layer->isReflection())
72        name = [name stringByAppendingString:@" (reflection)"];
73
74    return name;
75}
76
77+ (NSString *)compositingInfoForLayer:(RenderLayer*)layer
78{
79    if (!layer->isComposited())
80        return @"";
81
82    NSString *layerType = @"";
83    RenderLayerBacking* backing = layer->backing();
84    switch (backing->compositingLayerType()) {
85        case NormalCompositingLayer:
86            layerType = @"composited";
87            break;
88        case TiledCompositingLayer:
89            layerType = @"composited: tiled layer";
90            break;
91        case MediaCompositingLayer:
92            layerType = @"composited for plug-in, video or WebGL";
93            break;
94        case ContainerCompositingLayer:
95            layerType = @"composited: container layer";
96            break;
97    }
98
99    if (backing->hasClippingLayer())
100        layerType = [layerType stringByAppendingString:@" (clipping)"];
101
102    if (backing->hasAncestorClippingLayer())
103        layerType = [layerType stringByAppendingString:@" (clipped)"];
104
105    return layerType;
106}
107
108- (id)initWithRenderLayer:(RenderLayer*)layer
109{
110    if ((self = [super init])) {
111        name = [[WebRenderLayer nameForLayer:layer] retain];
112        bounds = layer->absoluteBoundingBox();
113        composited = layer->isComposited();
114        compositingInfo = [[WebRenderLayer compositingInfoForLayer:layer] retain];
115    }
116
117    return self;
118}
119
120- (id)initWithName:(NSString*)layerName
121{
122    if ((self = [super init])) {
123        name = [layerName copy];
124        separator = YES;
125    }
126
127    return self;
128}
129
130// Only called on the root.
131- (id)initWithWebFrame:(WebFrame *)webFrame
132{
133    self = [super init];
134
135    Frame* frame = core(webFrame);
136    if (!frame->loader().client().hasHTMLView()) {
137        [self release];
138        return nil;
139    }
140
141    RenderObject* renderer = frame->contentRenderer();
142    if (!renderer) {
143        [self release];
144        return nil;
145    }
146
147    if (renderer->hasLayer()) {
148        RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
149
150        name = [[WebRenderLayer nameForLayer:layer] retain];
151        bounds = layer->absoluteBoundingBox();
152        composited = layer->isComposited();
153        compositingInfo = [[WebRenderLayer compositingInfoForLayer:layer] retain];
154
155        [self buildDescendantLayers:layer];
156    }
157
158    return self;
159}
160
161- (void)dealloc
162{
163    [children release];
164    [name release];
165    [compositingInfo release];
166    [super dealloc];
167}
168
169- (void)buildDescendantLayers:(RenderLayer*)layer
170{
171    NSMutableArray *childWebLayers = [[NSMutableArray alloc] init];
172
173    // Build children in back to front order.
174
175    if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
176        size_t listSize = negZOrderList->size();
177
178        if (listSize) {
179            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithName:@"-ve z-order list"];
180            [childWebLayers addObject:newLayer];
181            [newLayer release];
182        }
183
184        for (size_t i = 0; i < listSize; ++i) {
185            RenderLayer* curLayer = negZOrderList->at(i);
186
187            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithRenderLayer:curLayer];
188            [newLayer buildDescendantLayers:curLayer];
189
190            [childWebLayers addObject:newLayer];
191            [newLayer release];
192        }
193    }
194
195    if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
196        size_t listSize = normalFlowList->size();
197
198        if (listSize) {
199            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithName:@"normal flow list"];
200            [childWebLayers addObject:newLayer];
201            [newLayer release];
202        }
203
204        for (size_t i = 0; i < listSize; ++i) {
205            RenderLayer* curLayer = normalFlowList->at(i);
206
207            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithRenderLayer:curLayer];
208            [newLayer buildDescendantLayers:curLayer];
209
210            [childWebLayers addObject:newLayer];
211            [newLayer release];
212        }
213    }
214
215    if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
216        size_t listSize = posZOrderList->size();
217
218        if (listSize) {
219            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithName:@"+ve z-order list"];
220            [childWebLayers addObject:newLayer];
221            [newLayer release];
222        }
223
224        for (size_t i = 0; i < listSize; ++i) {
225            RenderLayer* curLayer = posZOrderList->at(i);
226
227            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithRenderLayer:curLayer];
228            [newLayer buildDescendantLayers:curLayer];
229
230            [childWebLayers addObject:newLayer];
231            [newLayer release];
232        }
233    }
234
235    children = childWebLayers;
236}
237
238- (NSArray *)children
239{
240    return children;
241}
242
243- (NSString *)name
244{
245    return name;
246}
247
248- (NSString *)positionString
249{
250    return [NSString stringWithFormat:@"(%.0f, %.0f)", bounds.origin.x, bounds.origin.y];
251}
252
253- (NSString *)widthString
254{
255    return [NSString stringWithFormat:@"%.0f", bounds.size.width];
256}
257
258- (NSString *)heightString
259{
260    return [NSString stringWithFormat:@"%.0f", bounds.size.height];
261}
262
263- (NSString *)compositingInfo
264{
265    return compositingInfo;
266}
267
268- (BOOL)isComposited
269{
270    return composited;
271}
272
273- (BOOL)isSeparator
274{
275    return separator;
276}
277
278@end
279