initial import
[vuplus_webkit] / Source / WebCore / platform / graphics / mac / WebLayer.mm
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 "GraphicsLayerCA.h"
34 #import "PlatformCALayer.h"
35 #import <objc/objc-runtime.h>
36 #import <QuartzCore/QuartzCore.h>
37 #import <wtf/UnusedParam.h>
38
39 using namespace WebCore;
40
41 @implementation WebLayer
42
43 void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCALayer* platformLayer)
44 {
45     WebCore::PlatformCALayerClient* layerContents = platformLayer->owner();
46     if (!layerContents)
47         return;
48
49     CGContextSaveGState(context);
50
51     CGRect layerBounds = [layer bounds];
52     if (layerContents->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp) {
53         CGContextScaleCTM(context, 1, -1);
54         CGContextTranslateCTM(context, 0, -layerBounds.size.height);
55     }
56
57     [NSGraphicsContext saveGraphicsState];
58
59     // Set up an NSGraphicsContext for the context, so that parts of AppKit that rely on
60     // the current NSGraphicsContext (e.g. NSCell drawing) get the right one.
61     NSGraphicsContext* layerContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:YES];
62     [NSGraphicsContext setCurrentContext:layerContext];
63
64     GraphicsContext graphicsContext(context);
65     graphicsContext.setIsCALayerContext(true);
66     graphicsContext.setIsAcceleratedContext(platformLayer->acceleratesDrawing());
67
68     if (!layerContents->platformCALayerContentsOpaque()) {
69         // Turn off font smoothing to improve the appearance of text rendered onto a transparent background.
70         graphicsContext.setShouldSmoothFonts(false);
71     }
72     
73     // It's important to get the clip from the context, because it may be significantly
74     // smaller than the layer bounds (e.g. tiled layers)
75     CGRect clipBounds = CGContextGetClipBoundingBox(context);
76     IntRect clip(enclosingIntRect(clipBounds));
77     layerContents->platformCALayerPaintContents(graphicsContext, clip);
78
79     [NSGraphicsContext restoreGraphicsState];
80
81     // Re-fetch the layer owner, since <rdar://problem/9125151> indicates that it might have been destroyed during painting.
82     layerContents = platformLayer->owner();
83     ASSERT(layerContents);
84     if (layerContents && layerContents->platformCALayerShowRepaintCounter()) {
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->platformCALayerIncrementRepaintCount());
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
111     CGContextRestoreGState(context);
112 }
113
114 void setLayerNeedsDisplayInRect(CALayer *layer, WebCore::PlatformCALayerClient* layerContents, CGRect rect)
115 {
116     if (layerContents && layerContents->platformCALayerDrawsContent()) {
117         struct objc_super layerSuper = { layer, class_getSuperclass(object_getClass(layer)) };
118 #if defined(BUILDING_ON_LEOPARD)
119         rect = CGRectApplyAffineTransform(rect, [layer contentsTransform]);
120 #else
121         if (layerContents->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp)
122             rect.origin.y = [layer bounds].size.height - rect.origin.y - rect.size.height;
123 #endif
124         objc_msgSendSuper(&layerSuper, @selector(setNeedsDisplayInRect:), rect);
125
126 #ifndef NDEBUG
127         if (layerContents->platformCALayerShowRepaintCounter()) {
128             CGRect bounds = [layer bounds];
129             CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 46, 25);
130 #if defined(BUILDING_ON_LEOPARD)
131             indicatorRect = CGRectApplyAffineTransform(indicatorRect, [layer contentsTransform]);
132 #else
133             if (layerContents->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp)
134                 indicatorRect.origin.y = [layer bounds].size.height - indicatorRect.origin.y - indicatorRect.size.height;
135 #endif
136             objc_msgSendSuper(&layerSuper, @selector(setNeedsDisplayInRect:), indicatorRect);
137         }
138 #endif
139     }
140 }
141
142 // Disable default animations
143 - (id<CAAction>)actionForKey:(NSString *)key
144 {
145     UNUSED_PARAM(key);
146     return nil;
147 }
148
149 - (void)setNeedsDisplay
150 {
151     PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
152     if (layer && layer->owner() && layer->owner()->platformCALayerDrawsContent())
153         [super setNeedsDisplay];
154 }
155
156 - (void)setNeedsDisplayInRect:(CGRect)dirtyRect
157 {
158     PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
159     if (layer)
160         setLayerNeedsDisplayInRect(self, layer->owner(), dirtyRect);
161 }
162
163 - (void)display
164 {
165     [super display];
166     PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
167     if (layer && layer->owner())
168         layer->owner()->platformCALayerLayerDidDisplay(self);
169 }
170
171 - (void)drawInContext:(CGContextRef)context
172 {
173     PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
174     if (layer)
175         drawLayerContents(context, self, layer);
176 }
177
178 @end // implementation WebLayer
179
180 // MARK: -
181
182 #ifndef NDEBUG
183
184 @implementation CALayer(ExtendedDescription)
185
186 - (NSString*)_descriptionWithPrefix:(NSString*)inPrefix
187 {
188     CGRect aBounds = [self bounds];
189     CGPoint aPos = [self position];
190
191     NSString* selfString = [NSString stringWithFormat:@"%@<%@ 0x%08x> \"%@\" bounds(%.1f, %.1f, %.1f, %.1f) pos(%.1f, %.1f), sublayers=%d masking=%d",
192             inPrefix,
193             [self class],
194             self,
195             [self name],
196             aBounds.origin.x, aBounds.origin.y, aBounds.size.width, aBounds.size.height, 
197             aPos.x, aPos.y,
198             [[self sublayers] count],
199             [self masksToBounds]];
200     
201     NSMutableString* curDesc = [NSMutableString stringWithString:selfString];
202     
203     if ([[self sublayers] count] > 0)
204         [curDesc appendString:@"\n"];
205
206     NSString* sublayerPrefix = [inPrefix stringByAppendingString:@"\t"];
207
208     NSEnumerator* sublayersEnum = [[self sublayers] objectEnumerator];
209     CALayer* curLayer;
210     while ((curLayer = [sublayersEnum nextObject]))
211         [curDesc appendString:[curLayer _descriptionWithPrefix:sublayerPrefix]];
212
213     if ([[self sublayers] count] == 0)
214         [curDesc appendString:@"\n"];
215
216     return curDesc;
217 }
218
219 - (NSString*)extendedDescription
220 {
221     return [self _descriptionWithPrefix:@""];
222 }
223
224 @end  // implementation WebLayer(ExtendedDescription)
225
226 #endif // NDEBUG
227
228 #endif // USE(ACCELERATED_COMPOSITING)