Home | History | Annotate | Download | only in mac
      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