~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebKit2/UIProcess/mac/BackingStoreMac.mm

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#import <WebCore/Region.h>
 
35
 
 
36
using namespace WebCore;
 
37
 
 
38
namespace WebKit {
 
39
 
 
40
void BackingStore::performWithScrolledRectTransform(const IntRect& rect, void (^block)(const IntRect&, const IntSize&))
 
41
{
 
42
    if (m_scrolledRect.isEmpty() || m_scrolledRectOffset.isZero() || !m_scrolledRect.intersects(rect)) {
 
43
        block(rect, IntSize());
 
44
        return;
 
45
    }
 
46
 
 
47
    // The part of rect that's outside the scrolled rect is not translated.
 
48
    Region untranslatedRegion = rect;
 
49
    untranslatedRegion.subtract(m_scrolledRect);
 
50
    Vector<IntRect> untranslatedRects = untranslatedRegion.rects();
 
51
    for (size_t i = 0; i < untranslatedRects.size(); ++i)
 
52
        block(untranslatedRects[i], IntSize());
 
53
 
 
54
    // The part of rect that intersects the scrolled rect comprises up to four parts, each subject
 
55
    // to a different translation (all translations are equivalent modulo the dimensions of the
 
56
    // scrolled rect to the scroll offset).
 
57
    IntRect intersection = rect;
 
58
    intersection.intersect(m_scrolledRect);
 
59
 
 
60
    IntRect scrolledRect = m_scrolledRect;
 
61
    IntSize offset = m_scrolledRectOffset;
 
62
    scrolledRect.move(-offset);
 
63
 
 
64
    IntRect part = intersection;
 
65
    part.intersect(scrolledRect);
 
66
    if (!part.isEmpty())
 
67
        block(part, offset);
 
68
 
 
69
    part = intersection;
 
70
    offset += IntSize(0, -m_scrolledRect.height());
 
71
    scrolledRect.move(IntSize(0, m_scrolledRect.height()));
 
72
    part.intersect(scrolledRect);
 
73
    if (!part.isEmpty())
 
74
        block(part, offset);
 
75
 
 
76
    part = intersection;
 
77
    offset += IntSize(-m_scrolledRect.width(), 0);
 
78
    scrolledRect.move(IntSize(m_scrolledRect.width(), 0));
 
79
    part.intersect(scrolledRect);
 
80
    if (!part.isEmpty())
 
81
        block(part, offset);
 
82
 
 
83
    part = intersection;
 
84
    offset += IntSize(0, m_scrolledRect.height());
 
85
    scrolledRect.move(IntSize(0, -m_scrolledRect.height()));
 
86
    part.intersect(scrolledRect);
 
87
    if (!part.isEmpty())
 
88
        block(part, offset);
 
89
}
 
90
 
 
91
void BackingStore::resetScrolledRect()
 
92
{
 
93
    ASSERT(!m_scrolledRect.isEmpty());
 
94
 
 
95
    if (m_scrolledRectOffset.isZero()) {
 
96
        m_scrolledRect = IntRect();
 
97
        return;
 
98
    }
 
99
 
 
100
    IntSize scaledSize = m_scrolledRect.size();
 
101
    scaledSize.scale(m_deviceScaleFactor);
 
102
 
 
103
    RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
 
104
    RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(0, scaledSize.width(), scaledSize.height(), 8, scaledSize.width() * 4, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
 
105
 
 
106
    CGContextScaleCTM(context.get(), m_deviceScaleFactor, m_deviceScaleFactor);
 
107
 
 
108
    CGContextScaleCTM(context.get(), 1, -1);
 
109
    CGContextTranslateCTM(context.get(), -m_scrolledRect.x(), -m_scrolledRect.maxY());
 
110
    paint(context.get(), m_scrolledRect);
 
111
 
 
112
    IntRect sourceRect(IntPoint(), m_scrolledRect.size());
 
113
    paintBitmapContext(backingStoreContext(), context.get(), m_deviceScaleFactor, m_scrolledRect.location(), sourceRect);
 
114
 
 
115
    m_scrolledRect = IntRect();
 
116
    m_scrolledRectOffset = IntSize();
 
117
}
 
118
 
 
119
void BackingStore::paint(PlatformGraphicsContext context, const IntRect& rect)
 
120
{
 
121
    // FIXME: This is defined outside the block to work around bugs in llvm-gcc 4.2.
 
122
    __block CGRect source;
 
123
    performWithScrolledRectTransform(rect, ^(const IntRect& part, const IntSize& offset) {
 
124
        if (m_cgLayer) {
 
125
            CGContextSaveGState(context);
 
126
            CGContextClipToRect(context, part);
 
127
 
 
128
            CGContextScaleCTM(context, 1, -1);
 
129
            CGContextDrawLayerAtPoint(context, CGPointMake(-offset.width(), offset.height() - m_size.height()), m_cgLayer.get());
 
130
 
 
131
            CGContextRestoreGState(context);
 
132
            return;
 
133
        }
 
134
 
 
135
        ASSERT(m_bitmapContext);
 
136
        source = part;
 
137
        source.origin.x += offset.width();
 
138
        source.origin.y += offset.height();
 
139
        paintBitmapContext(context, m_bitmapContext.get(), m_deviceScaleFactor, part.location(), source);
 
140
    });
 
141
}
 
142
 
 
143
CGContextRef BackingStore::backingStoreContext()
 
144
{
 
145
    if (m_cgLayer)
 
146
        return CGLayerGetContext(m_cgLayer.get());
 
147
 
 
148
    // Try to create a layer.
 
149
    if (CGContextRef containingWindowContext = m_webPageProxy->containingWindowGraphicsContext()) {
 
150
        m_cgLayer.adoptCF(CGLayerCreateWithContext(containingWindowContext, m_size, 0));
 
151
        CGContextRef layerContext = CGLayerGetContext(m_cgLayer.get());
 
152
        
 
153
        CGContextSetBlendMode(layerContext, kCGBlendModeCopy);
 
154
 
 
155
        // We want the origin to be in the top left corner so flip the backing store context.
 
156
        CGContextTranslateCTM(layerContext, 0, m_size.height());
 
157
        CGContextScaleCTM(layerContext, 1, -1);
 
158
 
 
159
        if (m_bitmapContext) {
 
160
            // Paint the contents of the bitmap into the layer context.
 
161
            paintBitmapContext(layerContext, m_bitmapContext.get(), m_deviceScaleFactor, CGPointZero, CGRectMake(0, 0, m_size.width(), m_size.height()));
 
162
            m_bitmapContext = nullptr;
 
163
        }
 
164
 
 
165
        return layerContext;
 
166
    }
 
167
 
 
168
    if (!m_bitmapContext) {
 
169
        RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
 
170
 
 
171
        IntSize scaledSize(m_size);
 
172
        scaledSize.scale(m_deviceScaleFactor);
 
173
        m_bitmapContext.adoptCF(CGBitmapContextCreate(0, scaledSize.width(), scaledSize.height(), 8, scaledSize.width() * 4, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
 
174
 
 
175
        CGContextSetBlendMode(m_bitmapContext.get(), kCGBlendModeCopy);
 
176
 
 
177
        CGContextScaleCTM(m_bitmapContext.get(), m_deviceScaleFactor, m_deviceScaleFactor);
 
178
 
 
179
        // We want the origin to be in the top left corner so flip the backing store context.
 
180
        CGContextTranslateCTM(m_bitmapContext.get(), 0, m_size.height());
 
181
        CGContextScaleCTM(m_bitmapContext.get(), 1, -1);
 
182
    }
 
183
 
 
184
    return m_bitmapContext.get();
 
185
}
 
186
 
 
187
void BackingStore::incorporateUpdate(ShareableBitmap* bitmap, const UpdateInfo& updateInfo)
 
188
{
 
189
    CGContextRef context = backingStoreContext();
 
190
 
 
191
    scroll(updateInfo.scrollRect, updateInfo.scrollOffset);
 
192
 
 
193
    IntPoint updateRectLocation = updateInfo.updateRectBounds.location();
 
194
 
 
195
    GraphicsContext ctx(context);
 
196
    __block GraphicsContext* graphicsContext = &ctx;
 
197
 
 
198
    // Paint all update rects.
 
199
    for (size_t i = 0; i < updateInfo.updateRects.size(); ++i) {
 
200
        IntRect updateRect = updateInfo.updateRects[i];
 
201
        IntRect srcRect = updateRect;
 
202
        // FIXME: This is defined outside the block to work around bugs in llvm-gcc 4.2.
 
203
        __block IntRect srcPart;
 
204
        performWithScrolledRectTransform(srcRect, ^(const IntRect& part, const IntSize& offset) {
 
205
            srcPart = part;
 
206
            srcPart.move(-updateRectLocation.x(), -updateRectLocation.y());
 
207
            bitmap->paint(*graphicsContext, updateInfo.deviceScaleFactor, part.location() + offset, srcPart);
 
208
        });
 
209
    }
 
210
}
 
211
 
 
212
void BackingStore::scroll(const IntRect& scrollRect, const IntSize& scrollOffset)
 
213
{
 
214
    if (scrollOffset.isZero())
 
215
        return;
 
216
 
 
217
    ASSERT(!scrollRect.isEmpty());
 
218
 
 
219
    if (!m_scrolledRect.isEmpty() && m_scrolledRect != scrollRect)
 
220
        resetScrolledRect();
 
221
 
 
222
    m_scrolledRect = scrollRect;
 
223
 
 
224
    int width = (m_scrolledRectOffset.width() - scrollOffset.width()) % m_scrolledRect.width();
 
225
    if (width < 0)
 
226
        width += m_scrolledRect.width();
 
227
    m_scrolledRectOffset.setWidth(width);
 
228
 
 
229
    int height = (m_scrolledRectOffset.height() - scrollOffset.height()) % m_scrolledRect.height();
 
230
    if (height < 0)
 
231
        height += m_scrolledRect.height();
 
232
    m_scrolledRectOffset.setHeight(height);
 
233
}
 
234
 
 
235
} // namespace WebKit