~jconti/ubuntu/oneiric/webkit/fix_doc_path

« back to all changes in this revision

Viewing changes to WebCore/platform/graphics/win/GraphicsContextCGWin.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mike Hommey
  • Date: 2008-09-27 08:57:48 UTC
  • mfrom: (3.1.6 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080927085748-yhzld00w0rekp961
Tags: 1.0.1-4
WebCore/dom/Document.*, WebCore/loader/DocLoader.*: Avoid DoS via
crafted CSS import statements. Fixes: CVE-2008-3632. Closes: #499771.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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 COMPUTER, 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
#include "GraphicsContext.h"
 
28
 
 
29
#include "AffineTransform.h"
 
30
#include "NotImplemented.h"
 
31
#include "Path.h"
 
32
 
 
33
#include <CoreGraphics/CGBitmapContext.h>
 
34
#include <WebKitSystemInterface/WebKitSystemInterface.h>
 
35
#include "GraphicsContextPlatformPrivateCG.h"
 
36
 
 
37
using namespace std;
 
38
 
 
39
namespace WebCore {
 
40
 
 
41
static CGContextRef CGContextWithHDC(HDC hdc)
 
42
{
 
43
    HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
 
44
    CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
 
45
    BITMAP info;
 
46
 
 
47
    GetObject(bitmap, sizeof(info), &info);
 
48
    ASSERT(info.bmBitsPixel == 32);
 
49
    CGContextRef context = CGBitmapContextCreate(info.bmBits, info.bmWidth, info.bmHeight, 8,
 
50
                                                 info.bmWidthBytes, deviceRGB, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
 
51
    CGColorSpaceRelease(deviceRGB);
 
52
 
 
53
    // Flip coords
 
54
    CGContextTranslateCTM(context, 0, info.bmHeight);
 
55
    CGContextScaleCTM(context, 1, -1);
 
56
    
 
57
    // Put the HDC In advanced mode so it will honor affine transforms.
 
58
    SetGraphicsMode(hdc, GM_ADVANCED);
 
59
    
 
60
    return context;
 
61
}
 
62
 
 
63
GraphicsContext::GraphicsContext(HDC hdc)
 
64
    : m_common(createGraphicsContextPrivate())
 
65
    , m_data(new GraphicsContextPlatformPrivate(CGContextWithHDC(hdc)))
 
66
{
 
67
    CGContextRelease(m_data->m_cgContext);
 
68
    m_data->m_hdc = hdc;
 
69
    setPaintingDisabled(!m_data->m_cgContext);
 
70
    if (m_data->m_cgContext) {
 
71
        // Make sure the context starts in sync with our state.
 
72
        setPlatformFillColor(fillColor());
 
73
        setPlatformStrokeColor(strokeColor());
 
74
    }
 
75
}
 
76
 
 
77
bool GraphicsContext::inTransparencyLayer() const { return m_data->m_transparencyCount; }
 
78
 
 
79
// FIXME: Is it possible to merge getWindowsContext and createWindowsBitmap into a single API
 
80
// suitable for all clients?
 
81
HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
 
82
{
 
83
    // FIXME: Should a bitmap be created also when a shadow is set?
 
84
    if (mayCreateBitmap && inTransparencyLayer()) {
 
85
        if (dstRect.isEmpty())
 
86
            return 0;
 
87
 
 
88
        // Create a bitmap DC in which to draw.
 
89
        BITMAPINFO bitmapInfo;
 
90
        bitmapInfo.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
 
91
        bitmapInfo.bmiHeader.biWidth         = dstRect.width(); 
 
92
        bitmapInfo.bmiHeader.biHeight        = dstRect.height();
 
93
        bitmapInfo.bmiHeader.biPlanes        = 1;
 
94
        bitmapInfo.bmiHeader.biBitCount      = 32;
 
95
        bitmapInfo.bmiHeader.biCompression   = BI_RGB;
 
96
        bitmapInfo.bmiHeader.biSizeImage     = 0;
 
97
        bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
 
98
        bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
 
99
        bitmapInfo.bmiHeader.biClrUsed       = 0;
 
100
        bitmapInfo.bmiHeader.biClrImportant  = 0;
 
101
 
 
102
        void* pixels = 0;
 
103
        HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
 
104
        if (!bitmap)
 
105
            return 0;
 
106
 
 
107
        HDC bitmapDC = ::CreateCompatibleDC(m_data->m_hdc);
 
108
        ::SelectObject(bitmapDC, bitmap);
 
109
 
 
110
        // Fill our buffer with clear if we're going to alpha blend.
 
111
        if (supportAlphaBlend) {
 
112
            BITMAP bmpInfo;
 
113
            GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
 
114
            int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
 
115
            memset(bmpInfo.bmBits, 0, bufferSize);
 
116
        }
 
117
 
 
118
        // Make sure we can do world transforms.
 
119
        SetGraphicsMode(bitmapDC, GM_ADVANCED);
 
120
 
 
121
        // Apply a translation to our context so that the drawing done will be at (0,0) of the bitmap.
 
122
        XFORM xform;
 
123
        xform.eM11 = 1.0f;
 
124
        xform.eM12 = 0.0f;
 
125
        xform.eM21 = 0.0f;
 
126
        xform.eM22 = 1.0f;
 
127
        xform.eDx = -dstRect.x();
 
128
        xform.eDy = -dstRect.y();
 
129
        ::SetWorldTransform(bitmapDC, &xform);
 
130
 
 
131
        return bitmapDC;
 
132
    }
 
133
 
 
134
    CGContextFlush(platformContext());
 
135
    m_data->save();
 
136
    return m_data->m_hdc;
 
137
}
 
138
 
 
139
void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
 
140
{
 
141
    if (mayCreateBitmap && hdc && inTransparencyLayer()) {
 
142
        if (dstRect.isEmpty())
 
143
            return;
 
144
 
 
145
        HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
 
146
 
 
147
        // Need to make a CGImage out of the bitmap's pixel buffer and then draw
 
148
        // it into our context.
 
149
        BITMAP info;
 
150
        GetObject(bitmap, sizeof(info), &info);
 
151
        ASSERT(info.bmBitsPixel == 32);
 
152
 
 
153
        CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
 
154
        CGContextRef bitmapContext = CGBitmapContextCreate(info.bmBits, info.bmWidth, info.bmHeight, 8,
 
155
                                                           info.bmWidthBytes, deviceRGB, kCGBitmapByteOrder32Little | 
 
156
                                                           (supportAlphaBlend ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst));
 
157
        CGColorSpaceRelease(deviceRGB);
 
158
 
 
159
        CGImageRef image = CGBitmapContextCreateImage(bitmapContext);
 
160
        CGContextDrawImage(m_data->m_cgContext, dstRect, image);
 
161
        
 
162
        // Delete all our junk.
 
163
        CGImageRelease(image);
 
164
        CGContextRelease(bitmapContext);
 
165
        ::DeleteDC(hdc);
 
166
        ::DeleteObject(bitmap);
 
167
 
 
168
        return;
 
169
    }
 
170
 
 
171
    m_data->restore();
 
172
}
 
173
 
 
174
GraphicsContext::WindowsBitmap::WindowsBitmap(HDC hdc, IntSize size)
 
175
    : m_hdc(0)
 
176
    , m_size(size)
 
177
{
 
178
    BITMAPINFO bitmapInfo;
 
179
    bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 
180
    bitmapInfo.bmiHeader.biWidth = m_size.width(); 
 
181
    bitmapInfo.bmiHeader.biHeight = m_size.height();
 
182
    bitmapInfo.bmiHeader.biPlanes = 1;
 
183
    bitmapInfo.bmiHeader.biBitCount = 32;
 
184
    bitmapInfo.bmiHeader.biCompression = BI_RGB;
 
185
    bitmapInfo.bmiHeader.biSizeImage = 0;
 
186
    bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
 
187
    bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
 
188
    bitmapInfo.bmiHeader.biClrUsed = 0;
 
189
    bitmapInfo.bmiHeader.biClrImportant = 0;
 
190
 
 
191
    m_bitmap = CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, reinterpret_cast<void**>(&m_bitmapBuffer), 0, 0);
 
192
    if (!m_bitmap)
 
193
        return;
 
194
 
 
195
    m_hdc = CreateCompatibleDC(hdc);
 
196
    SelectObject(m_hdc, m_bitmap);
 
197
 
 
198
    BITMAP bmpInfo;
 
199
    GetObject(m_bitmap, sizeof(bmpInfo), &bmpInfo);
 
200
    m_bytesPerRow = bmpInfo.bmWidthBytes;
 
201
    m_bitmapBufferLength = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
 
202
 
 
203
    SetGraphicsMode(m_hdc, GM_ADVANCED);
 
204
}
 
205
 
 
206
GraphicsContext::WindowsBitmap::~WindowsBitmap()
 
207
{
 
208
    if (!m_bitmap)
 
209
        return;
 
210
 
 
211
    DeleteDC(m_hdc);
 
212
    DeleteObject(m_bitmap);
 
213
}
 
214
 
 
215
GraphicsContext::WindowsBitmap* GraphicsContext::createWindowsBitmap(IntSize size)
 
216
{
 
217
    return new WindowsBitmap(m_data->m_hdc, size);
 
218
}
 
219
 
 
220
void GraphicsContext::drawWindowsBitmap(WindowsBitmap* image, const IntPoint& point)
 
221
{
 
222
    RetainPtr<CGColorSpaceRef> deviceRGB(AdoptCF, CGColorSpaceCreateDeviceRGB());
 
223
    RetainPtr<CFDataRef> imageData(AdoptCF, CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, image->buffer(), image->bufferLength(), kCFAllocatorNull));
 
224
    RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(imageData.get()));
 
225
    RetainPtr<CGImageRef> cgImage(AdoptCF, CGImageCreate(image->size().width(), image->size().height(), 8, 32, image->bytesPerRow(), deviceRGB.get(),
 
226
                                                         kCGBitmapByteOrder32Little | kCGImageAlphaFirst, dataProvider.get(), 0, true, kCGRenderingIntentDefault));
 
227
    CGContextDrawImage(m_data->m_cgContext, CGRectMake(point.x(), point.y(), image->size().width(), image->size().height()), cgImage.get());   
 
228
}
 
229
 
 
230
void GraphicsContextPlatformPrivate::concatCTM(const AffineTransform& transform)
 
231
{
 
232
    if (!m_hdc)
 
233
        return;
 
234
 
 
235
    CGAffineTransform mat = transform;
 
236
    XFORM xform;
 
237
    xform.eM11 = mat.a;
 
238
    xform.eM12 = mat.b;
 
239
    xform.eM21 = mat.c;
 
240
    xform.eM22 = mat.d;
 
241
    xform.eDx = mat.tx;
 
242
    xform.eDy = mat.ty;
 
243
 
 
244
    ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
 
245
}
 
246
 
 
247
void GraphicsContext::drawFocusRing(const Color& color)
 
248
{
 
249
    if (paintingDisabled())
 
250
        return;
 
251
 
 
252
    float radius = (focusRingWidth() - 1) / 2.0f;
 
253
    int offset = radius + focusRingOffset();
 
254
    CGColorRef colorRef = color.isValid() ? cgColor(color) : 0;
 
255
 
 
256
    CGMutablePathRef focusRingPath = CGPathCreateMutable();
 
257
    const Vector<IntRect>& rects = focusRingRects();
 
258
    unsigned rectCount = rects.size();
 
259
    for (unsigned i = 0; i < rectCount; i++)
 
260
        CGPathAddRect(focusRingPath, 0, CGRectInset(rects[i], -offset, -offset));
 
261
 
 
262
    CGContextRef context = platformContext();
 
263
    CGContextSaveGState(context);
 
264
 
 
265
    CGContextBeginPath(context);
 
266
    CGContextAddPath(context, focusRingPath);
 
267
 
 
268
    wkDrawFocusRing(context, colorRef, radius);
 
269
 
 
270
    CGColorRelease(colorRef);
 
271
 
 
272
    CGPathRelease(focusRingPath);
 
273
 
 
274
    CGContextRestoreGState(context);
 
275
}
 
276
 
 
277
// Pulled from GraphicsContextCG
 
278
static void setCGStrokeColor(CGContextRef context, const Color& color)
 
279
{
 
280
    CGFloat red, green, blue, alpha;
 
281
    color.getRGBA(red, green, blue, alpha);
 
282
    CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
 
283
}
 
284
 
 
285
static const Color& spellingPatternColor() {
 
286
    static const Color spellingColor(255, 0, 0);
 
287
    return spellingColor;
 
288
}
 
289
 
 
290
static const Color& grammarPatternColor() {
 
291
    static const Color grammarColor(0, 128, 0);
 
292
    return grammarColor;
 
293
}
 
294
 
 
295
void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, int width, bool grammar)
 
296
{
 
297
    if (paintingDisabled())
 
298
        return;
 
299
 
 
300
    // These are the same for misspelling or bad grammar
 
301
    const int patternHeight = 3; // 3 rows
 
302
    ASSERT(cMisspellingLineThickness == patternHeight);
 
303
    const int patternWidth = 4; // 4 pixels
 
304
    ASSERT(patternWidth == cMisspellingLinePatternWidth);
 
305
 
 
306
    // Make sure to draw only complete dots.
 
307
    // NOTE: Code here used to shift the underline to the left and increase the width
 
308
    // to make sure everything gets underlined, but that results in drawing out of
 
309
    // bounds (e.g. when at the edge of a view) and could make it appear that the
 
310
    // space between adjacent misspelled words was underlined.
 
311
    // allow slightly more considering that the pattern ends with a transparent pixel
 
312
    int widthMod = width % patternWidth;
 
313
    if (patternWidth - widthMod > cMisspellingLinePatternGapWidth)
 
314
        width -= widthMod;
 
315
      
 
316
    // Draw the underline
 
317
    CGContextRef context = platformContext();
 
318
    CGContextSaveGState(context);
 
319
 
 
320
    const Color& patternColor = grammar ? grammarPatternColor() : spellingPatternColor();
 
321
    setCGStrokeColor(context, patternColor);
 
322
 
 
323
    wkSetPatternPhaseInUserSpace(context, point);
 
324
    CGContextSetBlendMode(context, kCGBlendModeNormal);
 
325
    
 
326
    // 3 rows, each offset by half a pixel for blending purposes
 
327
    const CGPoint upperPoints [] = {{point.x(), point.y() + patternHeight - 2.5 }, {point.x() + width, point.y() + patternHeight - 2.5}};
 
328
    const CGPoint middlePoints [] = {{point.x(), point.y() + patternHeight - 1.5 }, {point.x() + width, point.y() + patternHeight - 1.5}};
 
329
    const CGPoint lowerPoints [] = {{point.x(), point.y() + patternHeight - 0.5 }, {point.x() + width, point.y() + patternHeight - 0.5 }};
 
330
    
 
331
    // Dash lengths for the top and bottom of the error underline are the same.
 
332
    // These are magic.
 
333
    static const float edge_dash_lengths[] = {2.0f, 2.0f};
 
334
    static const float middle_dash_lengths[] = {2.76f, 1.24f};
 
335
    static const float edge_offset = -(edge_dash_lengths[1] - 1.0f) / 2.0f;
 
336
    static const float middle_offset = -(middle_dash_lengths[1] - 1.0f) / 2.0f;
 
337
 
 
338
    // Line opacities.  Once again, these are magic.
 
339
    const float upperOpacity = 0.33f;
 
340
    const float middleOpacity = 0.75f;
 
341
    const float lowerOpacity = 0.88f;
 
342
 
 
343
    //Top line
 
344
    CGContextSetLineDash(context, edge_offset, edge_dash_lengths, 
 
345
                         sizeof(edge_dash_lengths) / sizeof(edge_dash_lengths[0]));
 
346
    CGContextSetAlpha(context, upperOpacity);
 
347
    CGContextStrokeLineSegments(context, upperPoints, 2);
 
348
 
 
349
    // Middle line
 
350
    CGContextSetLineDash(context, middle_offset, middle_dash_lengths, 
 
351
                         sizeof(middle_dash_lengths) / sizeof(middle_dash_lengths[0]));
 
352
    CGContextSetAlpha(context, middleOpacity);
 
353
    CGContextStrokeLineSegments(context, middlePoints, 2);
 
354
    
 
355
    // Bottom line
 
356
    CGContextSetLineDash(context, edge_offset, edge_dash_lengths,
 
357
                         sizeof(edge_dash_lengths) / sizeof(edge_dash_lengths[0]));
 
358
    CGContextSetAlpha(context, lowerOpacity);
 
359
    CGContextStrokeLineSegments(context, lowerPoints, 2);
 
360
 
 
361
    CGContextRestoreGState(context);
 
362
}
 
363
 
 
364
}