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