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 35using namespace WebCore; 36 37namespace WebKit { 38 39void 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 56CGContextRef 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 96void 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 116void 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