• 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#ifndef NDEBUG
84    if (layerContents->showRepaintCounter()) {
85        bool isTiledLayer = [layer isKindOfClass:[CATiledLayer class]];
86
87        char text[16]; // that's a lot of repaints
88        snprintf(text, sizeof(text), "%d", layerContents->incrementRepaintCount());
89
90        CGContextSaveGState(context);
91        if (isTiledLayer)
92            CGContextSetRGBFillColor(context, 0.0f, 1.0f, 0.0f, 0.8f);
93        else
94            CGContextSetRGBFillColor(context, 1.0f, 0.0f, 0.0f, 0.8f);
95
96        CGRect aBounds = layerBounds;
97
98        aBounds.size.width = 10 + 12 * strlen(text);
99        aBounds.size.height = 25;
100        CGContextFillRect(context, aBounds);
101
102        CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 1.0f);
103
104        CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1.0f, -1.0f));
105        CGContextSelectFont(context, "Helvetica", 25, kCGEncodingMacRoman);
106        CGContextShowTextAtPoint(context, aBounds.origin.x + 3.0f, aBounds.origin.y + 20.0f, text, strlen(text));
107
108        CGContextRestoreGState(context);
109    }
110#endif
111
112    CGContextRestoreGState(context);
113}
114
115// Disable default animations
116- (id<CAAction>)actionForKey:(NSString *)key
117{
118    UNUSED_PARAM(key);
119    return nil;
120}
121
122// Implement this so presentationLayer can get our custom attributes
123- (id)initWithLayer:(id)layer
124{
125    if ((self = [super initWithLayer:layer]))
126        m_layerOwner = [(WebLayer*)layer layerOwner];
127
128    return self;
129}
130
131- (void)setNeedsDisplay
132{
133    if (m_layerOwner && m_layerOwner->client() && m_layerOwner->drawsContent())
134        [super setNeedsDisplay];
135}
136
137- (void)setNeedsDisplayInRect:(CGRect)dirtyRect
138{
139    if (m_layerOwner && m_layerOwner->client() && m_layerOwner->drawsContent()) {
140#if defined(BUILDING_ON_LEOPARD)
141        dirtyRect = CGRectApplyAffineTransform(dirtyRect, [self contentsTransform]);
142#endif
143        [super setNeedsDisplayInRect:dirtyRect];
144
145#ifndef NDEBUG
146        if (m_layerOwner->showRepaintCounter()) {
147            CGRect bounds = [self bounds];
148            CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 46, 25);
149#if defined(BUILDING_ON_LEOPARD)
150            indicatorRect = CGRectApplyAffineTransform(indicatorRect, [self contentsTransform]);
151#endif
152            [super setNeedsDisplayInRect:indicatorRect];
153        }
154#endif
155    }
156}
157
158- (void)drawInContext:(CGContextRef)context
159{
160    [WebLayer drawContents:m_layerOwner ofLayer:self intoContext:context];
161}
162
163@end // implementation WebLayer
164
165#pragma mark -
166
167@implementation WebLayer(WebLayerAdditions)
168
169- (void)setLayerOwner:(GraphicsLayer*)aLayer
170{
171    m_layerOwner = aLayer;
172}
173
174- (GraphicsLayer*)layerOwner
175{
176    return m_layerOwner;
177}
178
179@end
180
181#pragma mark -
182
183#ifndef NDEBUG
184
185@implementation CALayer(ExtendedDescription)
186
187- (NSString*)_descriptionWithPrefix:(NSString*)inPrefix
188{
189    CGRect aBounds = [self bounds];
190    CGPoint aPos = [self position];
191    CATransform3D t = [self transform];
192
193    NSString* selfString = [NSString stringWithFormat:@"%@<%@ 0x%08x> \"%@\" bounds(%.1f, %.1f, %.1f, %.1f) pos(%.1f, %.1f), sublayers=%d masking=%d",
194            inPrefix,
195            [self class],
196            self,
197            [self name],
198            aBounds.origin.x, aBounds.origin.y, aBounds.size.width, aBounds.size.height,
199            aPos.x, aPos.y,
200            [[self sublayers] count],
201            [self masksToBounds]];
202
203    NSMutableString* curDesc = [NSMutableString stringWithString:selfString];
204
205    if ([[self sublayers] count] > 0)
206        [curDesc appendString:@"\n"];
207
208    NSString* sublayerPrefix = [inPrefix stringByAppendingString:@"\t"];
209
210    NSEnumerator* sublayersEnum = [[self sublayers] objectEnumerator];
211    CALayer* curLayer;
212    while ((curLayer = [sublayersEnum nextObject]))
213        [curDesc appendString:[curLayer _descriptionWithPrefix:sublayerPrefix]];
214
215    if ([[self sublayers] count] == 0)
216        [curDesc appendString:@"\n"];
217
218    return curDesc;
219}
220
221- (NSString*)extendedDescription
222{
223    return [self _descriptionWithPrefix:@""];
224}
225
226@end  // implementation WebLayer(ExtendedDescription)
227
228#endif // NDEBUG
229
230#endif // USE(ACCELERATED_COMPOSITING)
231