• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2009 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 "WebLayer.h"
31
32#import "GraphicsContext.h"
33#import "GraphicsLayer.h"
34#import <QuartzCore/QuartzCore.h>
35#import <wtf/UnusedParam.h>
36
37using namespace WebCore;
38
39@implementation WebLayer
40
41+ (void)drawContents:(WebCore::GraphicsLayer*)layerContents ofLayer:(CALayer*)layer intoContext:(CGContextRef)context
42{
43    if (!layerContents)
44        return;
45
46    CGContextSaveGState(context);
47
48    CGRect layerBounds = [layer bounds];
49    if (layerContents->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp) {
50        CGContextScaleCTM(context, 1, -1);
51        CGContextTranslateCTM(context, 0, -layerBounds.size.height);
52    }
53
54    if (layerContents->client()) {
55        [NSGraphicsContext saveGraphicsState];
56
57        // Set up an NSGraphicsContext for the context, so that parts of AppKit that rely on
58        // the current NSGraphicsContext (e.g. NSCell drawing) get the right one.
59        NSGraphicsContext* layerContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:YES];
60        [NSGraphicsContext setCurrentContext:layerContext];
61
62        GraphicsContext graphicsContext(context);
63
64        // It's important to get the clip from the context, because it may be significantly
65        // smaller than the layer bounds (e.g. tiled layers)
66        CGRect clipBounds = CGContextGetClipBoundingBox(context);
67        IntRect clip(enclosingIntRect(clipBounds));
68        layerContents->paintGraphicsLayerContents(graphicsContext, clip);
69
70        [NSGraphicsContext restoreGraphicsState];
71    }
72#ifndef NDEBUG
73    else {
74        ASSERT_NOT_REACHED();
75
76        // FIXME: ideally we'd avoid calling -setNeedsDisplay on a layer that is a plain color,
77        // so CA never makes backing store for it (which is what -setNeedsDisplay will do above).
78        CGContextSetRGBFillColor(context, 0.0f, 1.0f, 0.0f, 1.0f);
79        CGContextFillRect(context, layerBounds);
80    }
81#endif
82
83    if (layerContents->showRepaintCounter()) {
84        bool isTiledLayer = [layer isKindOfClass:[CATiledLayer class]];
85
86        char text[16]; // that's a lot of repaints
87        snprintf(text, sizeof(text), "%d", layerContents->incrementRepaintCount());
88
89        CGContextSaveGState(context);
90        if (isTiledLayer)
91            CGContextSetRGBFillColor(context, 0.0f, 1.0f, 0.0f, 0.8f);
92        else
93            CGContextSetRGBFillColor(context, 1.0f, 0.0f, 0.0f, 0.8f);
94
95        CGRect aBounds = layerBounds;
96
97        aBounds.size.width = 10 + 12 * strlen(text);
98        aBounds.size.height = 25;
99        CGContextFillRect(context, aBounds);
100
101        CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 1.0f);
102
103        CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1.0f, -1.0f));
104        CGContextSelectFont(context, "Helvetica", 25, kCGEncodingMacRoman);
105        CGContextShowTextAtPoint(context, aBounds.origin.x + 3.0f, aBounds.origin.y + 20.0f, text, strlen(text));
106
107        CGContextRestoreGState(context);
108    }
109
110    CGContextRestoreGState(context);
111}
112
113// Disable default animations
114- (id<CAAction>)actionForKey:(NSString *)key
115{
116    UNUSED_PARAM(key);
117    return nil;
118}
119
120// Implement this so presentationLayer can get our custom attributes
121- (id)initWithLayer:(id)layer
122{
123    if ((self = [super initWithLayer:layer]))
124        m_layerOwner = [(WebLayer*)layer layerOwner];
125
126    return self;
127}
128
129- (void)setNeedsDisplay
130{
131    if (m_layerOwner && m_layerOwner->client() && m_layerOwner->drawsContent())
132        [super setNeedsDisplay];
133}
134
135- (void)setNeedsDisplayInRect:(CGRect)dirtyRect
136{
137    if (m_layerOwner && m_layerOwner->client() && m_layerOwner->drawsContent()) {
138#if defined(BUILDING_ON_LEOPARD)
139        dirtyRect = CGRectApplyAffineTransform(dirtyRect, [self contentsTransform]);
140#endif
141        [super setNeedsDisplayInRect:dirtyRect];
142
143#ifndef NDEBUG
144        if (m_layerOwner->showRepaintCounter()) {
145            CGRect bounds = [self bounds];
146            CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 46, 25);
147#if defined(BUILDING_ON_LEOPARD)
148            indicatorRect = CGRectApplyAffineTransform(indicatorRect, [self contentsTransform]);
149#endif
150            [super setNeedsDisplayInRect:indicatorRect];
151        }
152#endif
153    }
154}
155
156- (void)display
157{
158    [super display];
159    if (m_layerOwner)
160        m_layerOwner->didDisplay(self);
161}
162
163- (void)drawInContext:(CGContextRef)context
164{
165    [WebLayer drawContents:m_layerOwner ofLayer:self intoContext:context];
166}
167
168@end // implementation WebLayer
169
170#pragma mark -
171
172@implementation WebLayer(WebLayerAdditions)
173
174- (void)setLayerOwner:(GraphicsLayer*)aLayer
175{
176    m_layerOwner = aLayer;
177}
178
179- (GraphicsLayer*)layerOwner
180{
181    return m_layerOwner;
182}
183
184@end
185
186#pragma mark -
187
188#ifndef NDEBUG
189
190@implementation CALayer(ExtendedDescription)
191
192- (NSString*)_descriptionWithPrefix:(NSString*)inPrefix
193{
194    CGRect aBounds = [self bounds];
195    CGPoint aPos = [self position];
196    CATransform3D t = [self transform];
197
198    NSString* selfString = [NSString stringWithFormat:@"%@<%@ 0x%08x> \"%@\" bounds(%.1f, %.1f, %.1f, %.1f) pos(%.1f, %.1f), sublayers=%d masking=%d",
199            inPrefix,
200            [self class],
201            self,
202            [self name],
203            aBounds.origin.x, aBounds.origin.y, aBounds.size.width, aBounds.size.height,
204            aPos.x, aPos.y,
205            [[self sublayers] count],
206            [self masksToBounds]];
207
208    NSMutableString* curDesc = [NSMutableString stringWithString:selfString];
209
210    if ([[self sublayers] count] > 0)
211        [curDesc appendString:@"\n"];
212
213    NSString* sublayerPrefix = [inPrefix stringByAppendingString:@"\t"];
214
215    NSEnumerator* sublayersEnum = [[self sublayers] objectEnumerator];
216    CALayer* curLayer;
217    while ((curLayer = [sublayersEnum nextObject]))
218        [curDesc appendString:[curLayer _descriptionWithPrefix:sublayerPrefix]];
219
220    if ([[self sublayers] count] == 0)
221        [curDesc appendString:@"\n"];
222
223    return curDesc;
224}
225
226- (NSString*)extendedDescription
227{
228    return [self _descriptionWithPrefix:@""];
229}
230
231@end  // implementation WebLayer(ExtendedDescription)
232
233#endif // NDEBUG
234
235#endif // USE(ACCELERATED_COMPOSITING)
236