Home | History | Annotate | Download | only in mac
      1 /*
      2  * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #import "config.h"
     27 #import "BackingStore.h"
     28 
     29 #import "CGUtilities.h"
     30 #import "ShareableBitmap.h"
     31 #import "UpdateInfo.h"
     32 #import "WebPageProxy.h"
     33 #import <WebCore/GraphicsContext.h>
     34 
     35 using namespace WebCore;
     36 
     37 namespace WebKit {
     38 
     39 void BackingStore::paint(PlatformGraphicsContext context, const IntRect& rect)
     40 {
     41     if (m_cgLayer) {
     42         CGContextSaveGState(context);
     43         CGContextClipToRect(context, rect);
     44 
     45         CGContextScaleCTM(context, 1, -1);
     46         CGContextDrawLayerAtPoint(context, CGPointMake(0, -m_size.height()), m_cgLayer.get());
     47 
     48         CGContextRestoreGState(context);
     49         return;
     50     }
     51 
     52     ASSERT(m_bitmapContext);
     53     paintBitmapContext(context, m_bitmapContext.get(), rect.location(), rect);
     54 }
     55 
     56 CGContextRef BackingStore::backingStoreContext()
     57 {
     58     if (m_cgLayer)
     59         return CGLayerGetContext(m_cgLayer.get());
     60 
     61     // Try to create a layer.
     62     if (CGContextRef containingWindowContext = m_webPageProxy->containingWindowGraphicsContext()) {
     63         m_cgLayer.adoptCF(CGLayerCreateWithContext(containingWindowContext, NSSizeToCGSize(m_size), 0));
     64         CGContextRef layerContext = CGLayerGetContext(m_cgLayer.get());
     65 
     66         CGContextSetBlendMode(layerContext, kCGBlendModeCopy);
     67 
     68         // We want the origin to be in the top left corner so flip the backing store context.
     69         CGContextTranslateCTM(layerContext, 0, m_size.height());
     70         CGContextScaleCTM(layerContext, 1, -1);
     71 
     72         if (m_bitmapContext) {
     73             // Paint the contents of the bitmap into the layer context.
     74             paintBitmapContext(layerContext, m_bitmapContext.get(), CGPointZero, CGRectMake(0, 0, m_size.width(), m_size.height()));
     75             m_bitmapContext = nullptr;
     76         }
     77 
     78         return layerContext;
     79     }
     80 
     81     if (!m_bitmapContext) {
     82         RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
     83 
     84         m_bitmapContext.adoptCF(CGBitmapContextCreate(0, m_size.width(), m_size.height(), 8, m_size.width() * 4, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
     85 
     86         CGContextSetBlendMode(m_bitmapContext.get(), kCGBlendModeCopy);
     87 
     88         // We want the origin to be in the top left corner so flip the backing store context.
     89         CGContextTranslateCTM(m_bitmapContext.get(), 0, m_size.height());
     90         CGContextScaleCTM(m_bitmapContext.get(), 1, -1);
     91     }
     92 
     93     return m_bitmapContext.get();
     94 }
     95 
     96 void BackingStore::incorporateUpdate(ShareableBitmap* bitmap, const UpdateInfo& updateInfo)
     97 {
     98     CGContextRef context = backingStoreContext();
     99 
    100     scroll(updateInfo.scrollRect, updateInfo.scrollOffset);
    101 
    102     IntPoint updateRectLocation = updateInfo.updateRectBounds.location();
    103 
    104     GraphicsContext graphicsContext(context);
    105 
    106     // Paint all update rects.
    107     for (size_t i = 0; i < updateInfo.updateRects.size(); ++i) {
    108         IntRect updateRect = updateInfo.updateRects[i];
    109         IntRect srcRect = updateRect;
    110         srcRect.move(-updateRectLocation.x(), -updateRectLocation.y());
    111 
    112         bitmap->paint(graphicsContext, updateRect.location(), srcRect);
    113     }
    114 }
    115 
    116 void BackingStore::scroll(const IntRect& scrollRect, const IntSize& scrollOffset)
    117 {
    118     if (scrollOffset.isZero())
    119         return;
    120 
    121     if (m_cgLayer) {
    122         CGContextRef layerContext = CGLayerGetContext(m_cgLayer.get());
    123 
    124         // Scroll the layer by painting it into itself with the given offset.
    125         CGContextSaveGState(layerContext);
    126         CGContextClipToRect(layerContext, scrollRect);
    127         CGContextScaleCTM(layerContext, 1, -1);
    128         CGContextDrawLayerAtPoint(layerContext, CGPointMake(scrollOffset.width(), -m_size.height() - scrollOffset.height()), m_cgLayer.get());
    129         CGContextRestoreGState(layerContext);
    130 
    131         return;
    132     }
    133 
    134     ASSERT(m_bitmapContext);
    135 
    136     CGContextSaveGState(m_bitmapContext.get());
    137     CGContextClipToRect(m_bitmapContext.get(), scrollRect);
    138     CGPoint destination = CGPointMake(scrollRect.x() + scrollOffset.width(), scrollRect.y() + scrollOffset.height());
    139     paintBitmapContext(m_bitmapContext.get(), m_bitmapContext.get(), destination, scrollRect);
    140     CGContextRestoreGState(m_bitmapContext.get());
    141 }
    142 
    143 } // namespace WebKit
    144