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#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    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#if USE(ACCELERATED_COMPOSITING)
84    RenderLayerBacking* backing = layer->backing();
85    switch (backing->compositingLayerType()) {
86        case NormalCompositingLayer:
87            layerType = @"composited";
88            break;
89        case TiledCompositingLayer:
90            layerType = @"composited: tiled layer";
91            break;
92        case MediaCompositingLayer:
93            layerType = @"composited for plug-in, video or WebGL";
94            break;
95        case ContainerCompositingLayer:
96            layerType = @"composited: container layer";
97            break;
98    }
99
100    if (backing->hasClippingLayer())
101        layerType = [layerType stringByAppendingString:@" (clipping)"];
102
103    if (backing->hasAncestorClippingLayer())
104        layerType = [layerType stringByAppendingString:@" (clipped)"];
105#endif
106
107    return layerType;
108}
109
110- (id)initWithRenderLayer:(RenderLayer*)layer
111{
112    if ((self = [super init])) {
113        name = [[WebRenderLayer nameForLayer:layer] retain];
114        bounds = layer->absoluteBoundingBox();
115        composited = layer->isComposited();
116        compositingInfo = [[WebRenderLayer compositingInfoForLayer:layer] retain];
117    }
118
119    return self;
120}
121
122- (id)initWithName:(NSString*)layerName
123{
124    if ((self = [super init])) {
125        name = [layerName copy];
126        separator = YES;
127    }
128
129    return self;
130}
131
132// Only called on the root.
133- (id)initWithWebFrame:(WebFrame *)webFrame
134{
135    self = [super init];
136
137    Frame* frame = core(webFrame);
138    if (!frame->loader()->client()->hasHTMLView()) {
139        [self release];
140        return nil;
141    }
142
143    RenderObject* renderer = frame->contentRenderer();
144    if (!renderer) {
145        [self release];
146        return nil;
147    }
148
149    if (renderer->hasLayer()) {
150        RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
151
152        name = [[WebRenderLayer nameForLayer:layer] retain];
153        bounds = layer->absoluteBoundingBox();
154        composited = layer->isComposited();
155        compositingInfo = [[WebRenderLayer compositingInfoForLayer:layer] retain];
156
157        [self buildDescendantLayers:layer];
158    }
159
160    return self;
161}
162
163- (void)dealloc
164{
165    [children release];
166    [name release];
167    [compositingInfo release];
168    [super dealloc];
169}
170
171- (void)buildDescendantLayers:(RenderLayer*)layer
172{
173    NSMutableArray *childWebLayers = [[NSMutableArray alloc] init];
174
175    // Build children in back to front order.
176
177    if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
178        size_t listSize = negZOrderList->size();
179
180        if (listSize) {
181            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithName:@"-ve z-order list"];
182            [childWebLayers addObject:newLayer];
183            [newLayer release];
184        }
185
186        for (size_t i = 0; i < listSize; ++i) {
187            RenderLayer* curLayer = negZOrderList->at(i);
188
189            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithRenderLayer:curLayer];
190            [newLayer buildDescendantLayers:curLayer];
191
192            [childWebLayers addObject:newLayer];
193            [newLayer release];
194        }
195    }
196
197    if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
198        size_t listSize = normalFlowList->size();
199
200        if (listSize) {
201            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithName:@"normal flow list"];
202            [childWebLayers addObject:newLayer];
203            [newLayer release];
204        }
205
206        for (size_t i = 0; i < listSize; ++i) {
207            RenderLayer* curLayer = normalFlowList->at(i);
208
209            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithRenderLayer:curLayer];
210            [newLayer buildDescendantLayers:curLayer];
211
212            [childWebLayers addObject:newLayer];
213            [newLayer release];
214        }
215    }
216
217    if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
218        size_t listSize = posZOrderList->size();
219
220        if (listSize) {
221            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithName:@"+ve z-order list"];
222            [childWebLayers addObject:newLayer];
223            [newLayer release];
224        }
225
226        for (size_t i = 0; i < listSize; ++i) {
227            RenderLayer* curLayer = posZOrderList->at(i);
228
229            WebRenderLayer* newLayer = [[WebRenderLayer alloc] initWithRenderLayer:curLayer];
230            [newLayer buildDescendantLayers:curLayer];
231
232            [childWebLayers addObject:newLayer];
233            [newLayer release];
234        }
235    }
236
237    children = childWebLayers;
238}
239
240- (NSArray *)children
241{
242    return children;
243}
244
245- (NSString *)name
246{
247    return name;
248}
249
250- (NSString *)positionString
251{
252    return [NSString stringWithFormat:@"(%.0f, %.0f)", bounds.origin.x, bounds.origin.y];
253}
254
255- (NSString *)widthString
256{
257    return [NSString stringWithFormat:@"%.0f", bounds.size.width];
258}
259
260- (NSString *)heightString
261{
262    return [NSString stringWithFormat:@"%.0f", bounds.size.height];
263}
264
265- (NSString *)compositingInfo
266{
267    return compositingInfo;
268}
269
270- (BOOL)isComposited
271{
272    return composited;
273}
274
275- (BOOL)isSeparator
276{
277    return separator;
278}
279
280@end
281