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 37 using 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