Changeset 44539 in webkit


Ignore:
Timestamp:
Jun 9, 2009 11:27:47 AM (15 years ago)
Author:
bfulgham@webkit.org
Message:

2009-06-09 Brent Fulgham <bfulgham@webkit.org>

Reviewed by Eric Seidel.

Fixes https://bugs.webkit.org/show_bug.cgi?id=22891
Scrolling in Windows Cairo Broken if no background color set.

  • platform/graphics/cairo/GradientCairo.cpp: (WebCore::Gradient::fill): Use the GraphicsContext save and restore methods (rather than the Cairo-only functions) so that the Windows device context is kept in sync.
  • platform/graphics/cairo/GraphicsContextCairo.cpp: (WebCore::GraphicsContext::GraphicsContext): Add new constructor call to sync Windows HDC with Cairo surface.
  • platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h: (WebCore::GraphicsContextPlatformPrivate::syncContext): Provide declaration for Windows HDC sync method (and stub for non-Windows Cairo implementations).
  • platform/graphics/cairo/ImageCairo.cpp: (WebCore::BitmapImage::draw): Use GraphicsContext save and restore methods (rather than the Cairo-only functions) so that the Windows device context is kept in sync.
  • platform/graphics/win/GraphicsContextCairoWin.cpp: (WebCore::CairoContextWithHDC): New method to create a valid Cairo context for a given HDC. (WebCore::GraphicsContext::GraphicsContext): Modify constructor to use new CairoContextWithHDC call. (WebCore::GraphicsContext::getWindowsContext): Revise to match behavior of CG implementation. (WebCore::GraphicsContext::releaseWindowsContext): Revise to match behavior of CG implementation. (WebCore::GraphicsContextPlatformPrivate::concatCTM): Get rid of incorrect new HDC, and use object's HDC member for dealing with concatCTM operations. (WebCore::GraphicsContextPlatformPrivate::syncContext): New method to sync Windows HDC with Cairo context.
  • platform/graphics/win/ImageCairoWin.cpp: (WebCore::BitmapImage::getHBITMAPOfSize): Revise implementation to match CG behavior.
Location:
trunk/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r44538 r44539  
     12009-06-09  Brent Fulgham  <bfulgham@webkit.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        Fixes https://bugs.webkit.org/show_bug.cgi?id=22891
     6        Scrolling in Windows Cairo Broken if no background color set.
     7
     8        * platform/graphics/cairo/GradientCairo.cpp:
     9        (WebCore::Gradient::fill):  Use the GraphicsContext save and restore
     10          methods (rather than the Cairo-only functions) so that the Windows
     11          device context is kept in sync.
     12        * platform/graphics/cairo/GraphicsContextCairo.cpp:
     13        (WebCore::GraphicsContext::GraphicsContext): Add new constructor call
     14          to sync Windows HDC with Cairo surface.
     15        * platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h:
     16        (WebCore::GraphicsContextPlatformPrivate::syncContext): Provide
     17          declaration for Windows HDC sync method (and stub for non-Windows
     18          Cairo implementations).
     19        * platform/graphics/cairo/ImageCairo.cpp:
     20        (WebCore::BitmapImage::draw): Use GraphicsContext save and restore
     21          methods (rather than the Cairo-only functions) so that the Windows
     22          device context is kept in sync.
     23        * platform/graphics/win/GraphicsContextCairoWin.cpp:
     24        (WebCore::CairoContextWithHDC): New method to create a valid Cairo
     25          context for a given HDC.
     26        (WebCore::GraphicsContext::GraphicsContext): Modify constructor to
     27          use new CairoContextWithHDC call.
     28        (WebCore::GraphicsContext::getWindowsContext): Revise to match
     29          behavior of CG implementation.
     30        (WebCore::GraphicsContext::releaseWindowsContext): Revise to match
     31          behavior of CG implementation.
     32        (WebCore::GraphicsContextPlatformPrivate::concatCTM): Get rid of
     33          incorrect new HDC, and use object's HDC member for dealing with
     34          concatCTM operations.
     35        (WebCore::GraphicsContextPlatformPrivate::syncContext): New method
     36          to sync Windows HDC with Cairo context.
     37        * platform/graphics/win/ImageCairoWin.cpp:
     38        (WebCore::BitmapImage::getHBITMAPOfSize): Revise implementation to
     39          match CG behavior.
     40
    1412009-06-09  Jian Li  <jianli@chromium.org>
    242
  • trunk/WebCore/platform/graphics/cairo/GradientCairo.cpp

    r40795 r44539  
    8181    cairo_t* cr = context->platformContext();
    8282
    83     cairo_save(cr);
     83    context->save();
    8484    cairo_set_source(cr, platformGradient());
    8585    cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
    8686    cairo_fill(cr);
    87     cairo_restore(cr);
     87    context->restore();
    8888}
    8989
  • trunk/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp

    r40774 r44539  
    9393{
    9494    m_data->cr = cairo_reference(cr);
     95    m_data->syncContext(cr);
    9596    setPaintingDisabled(!cr);
    9697}
  • trunk/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h

    r40490 r44539  
    7474    void beginTransparencyLayer() { m_transparencyCount++; }
    7575    void endTransparencyLayer() { m_transparencyCount--; }
     76    void syncContext(PlatformGraphicsContext* cr);
    7677#else
    7778    // On everything else, we do nothing.
     
    8687    void beginTransparencyLayer() {}
    8788    void endTransparencyLayer() {}
     89    void syncContext(PlatformGraphicsContext* cr) {}
    8890#endif
    8991
  • trunk/WebCore/platform/graphics/cairo/ImageCairo.cpp

    r44099 r44539  
    113113
    114114    cairo_t* cr = context->platformContext();
    115     cairo_save(cr);
     115    context->save();
    116116
    117117    // Set the compositing operation.
     
    145145    cairo_paint_with_alpha(cr, context->getAlpha());
    146146
    147     cairo_restore(cr);
     147    context->restore();
    148148
    149149    if (imageObserver())
  • trunk/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp

    r40722 r44539  
    191191    // Cairo does not like zero height images.
    192192    // If we have a zero height image, just pretend we don't have enough data yet.
    193     if (!buffer->height())
     193    if (!size().height())
    194194        return 0;
    195195
     
    197197                                               CAIRO_FORMAT_ARGB32,
    198198                                               size().width(),
    199                                                buffer->height(),
     199                                               size().height(),
    200200                                               size().width()*4);
    201201}
  • trunk/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp

    r42590 r44539  
    3737namespace WebCore {
    3838
     39static cairo_t* createCairoContextWithHDC(HDC hdc, bool hasAlpha)
     40{
     41    // Put the HDC In advanced mode so it will honor affine transforms.
     42    SetGraphicsMode(hdc, GM_ADVANCED);
     43   
     44    HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
     45
     46    BITMAP info;
     47    GetObject(bitmap, sizeof(info), &info);
     48    ASSERT(info.bmBitsPixel == 32);
     49
     50    cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)info.bmBits,
     51                                               CAIRO_FORMAT_ARGB32,
     52                                               info.bmWidth,
     53                                               info.bmHeight,
     54                                               info.bmWidthBytes);
     55
     56    cairo_t* context = cairo_create(image);
     57    cairo_surface_destroy(image);
     58
     59    return context;
     60}
     61
     62static BITMAPINFO bitmapInfoForSize(const IntSize& size)
     63{
     64    BITMAPINFO bitmapInfo;
     65    bitmapInfo.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
     66    bitmapInfo.bmiHeader.biWidth         = size.width();
     67    bitmapInfo.bmiHeader.biHeight        = size.height();
     68    bitmapInfo.bmiHeader.biPlanes        = 1;
     69    bitmapInfo.bmiHeader.biBitCount      = 32;
     70    bitmapInfo.bmiHeader.biCompression   = BI_RGB;
     71    bitmapInfo.bmiHeader.biSizeImage     = 0;
     72    bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
     73    bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
     74    bitmapInfo.bmiHeader.biClrUsed       = 0;
     75    bitmapInfo.bmiHeader.biClrImportant  = 0;
     76
     77    return bitmapInfo;
     78}
     79
     80static void fillWithClearColor(HBITMAP bitmap)
     81{
     82    BITMAP bmpInfo;
     83    GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
     84    int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
     85    memset(bmpInfo.bmBits, 0, bufferSize);
     86}
     87
    3988GraphicsContext::GraphicsContext(HDC dc, bool hasAlpha)
    4089    : m_common(createGraphicsContextPrivate())
     
    4291{
    4392    if (dc) {
    44         cairo_surface_t* surface = cairo_win32_surface_create(dc);
    45         m_data->cr = cairo_create(surface);
     93        m_data->cr = createCairoContextWithHDC(dc, hasAlpha);
    4694        m_data->m_hdc = dc;
    4795    } else {
     
    60108HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
    61109{
    62     // FIXME:  We aren't really doing anything with the 'mayCreateBitmap' flag.  This needs
    63     // to be addressed.
     110    // FIXME: Should a bitmap be created also when a shadow is set?
     111    if (mayCreateBitmap && inTransparencyLayer()) {
     112        if (dstRect.isEmpty())
     113            return 0;
     114
     115        // Create a bitmap DC in which to draw.
     116        BITMAPINFO bitmapInfo = bitmapInfoForSize(dstRect.size());
     117
     118        void* pixels = 0;
     119        HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
     120        if (!bitmap)
     121            return 0;
     122
     123        HDC bitmapDC = ::CreateCompatibleDC(m_data->m_hdc);
     124        ::SelectObject(bitmapDC, bitmap);
     125
     126        // Fill our buffer with clear if we're going to alpha blend.
     127        if (supportAlphaBlend)
     128           fillWithClearColor(bitmap);
     129
     130        // Make sure we can do world transforms.
     131        SetGraphicsMode(bitmapDC, GM_ADVANCED);
     132
     133        // Apply a translation to our context so that the drawing done will be at (0,0) of the bitmap.
     134        XFORM xform;
     135        xform.eM11 = 1.0f;
     136        xform.eM12 = 0.0f;
     137        xform.eM21 = 0.0f;
     138        xform.eM22 = 1.0f;
     139        xform.eDx = -dstRect.x();
     140        xform.eDy = -dstRect.y();
     141        ::SetWorldTransform(bitmapDC, &xform);
     142
     143        return bitmapDC;
     144    }
     145
     146    cairo_surface_t* surface = cairo_win32_surface_create(m_data->m_hdc);
     147    cairo_surface_flush(surface);
     148    cairo_surface_destroy(surface);
     149
     150    m_data->save();
     151
     152    return m_data->m_hdc;
     153}
     154
     155void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
     156{
     157    if (!mayCreateBitmap || !hdc || !inTransparencyLayer()) {
     158        m_data->restore();
     159        return;
     160    }
     161
    64162    if (dstRect.isEmpty())
    65        return 0;
    66 
    67     // This is probably wrong, and definitely out of date.  Pulled from old SVN
    68     cairo_surface_t* surface = cairo_get_target(platformContext());
    69     HDC hdc = cairo_win32_surface_get_dc(surface);   
    70     SaveDC(hdc);
    71 
    72     // FIXME: We need to make sure a clip is really set on the HDC.
    73     // Call SetWorldTransform to honor the current Cairo transform.
    74     SetGraphicsMode(hdc, GM_ADVANCED); // We need this call for themes to honor world transforms.
    75     cairo_matrix_t mat;
    76     cairo_get_matrix(platformContext(), &mat);
    77     XFORM xform;
    78     xform.eM11 = mat.xx;
    79     xform.eM12 = mat.xy;
    80     xform.eM21 = mat.yx;
    81     xform.eM22 = mat.yy;
    82     xform.eDx = mat.x0;
    83     xform.eDy = mat.y0;
    84     ::SetWorldTransform(hdc, &xform);
    85 
    86     return hdc;
    87 }
    88 
    89 void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
    90 {
    91     // FIXME:  We aren't really doing anything with the 'mayCreateBitmap' flag.  This needs
    92     // to be addressed.
    93     if (dstRect.isEmpty())
    94        return;
    95 
    96     cairo_surface_t* surface = cairo_get_target(platformContext());
    97     HDC hdc2 = cairo_win32_surface_get_dc(surface);
    98     RestoreDC(hdc2, -1);
    99     cairo_surface_mark_dirty(surface);
     163        return;
     164
     165    HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
     166
     167    BITMAP info;
     168    GetObject(bitmap, sizeof(info), &info);
     169    ASSERT(info.bmBitsPixel == 32);
     170
     171    // Need to make a cairo_surface_t out of the bitmap's pixel buffer and then draw
     172    // it into our context.
     173    cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)info.bmBits,
     174                                            CAIRO_FORMAT_ARGB32,
     175                                            info.bmWidth,
     176                                            info.bmHeight,
     177                                            info.bmWidthBytes);
     178
     179    // Scale the target surface to the new image size, and flip it
     180    // so that when we set the srcImage as the surface it will draw
     181    // right-side-up.
     182    cairo_translate(m_data->cr, 0, dstRect.height());
     183    cairo_scale(m_data->cr, dstRect.width(), -dstRect.height());
     184    cairo_set_source_surface (m_data->cr, image, dstRect.x(), dstRect.y());
     185
     186    if (m_data->layers.size())
     187        cairo_paint_with_alpha(m_data->cr, m_data->layers.last());
     188    else
     189        cairo_paint(m_data->cr);
     190     
     191    // Delete all our junk.
     192    cairo_surface_destroy(image);
     193    ::DeleteDC(hdc);
     194    ::DeleteObject(bitmap);
    100195}
    101196
    102197void GraphicsContextPlatformPrivate::concatCTM(const TransformationMatrix& transform)
    103198{
    104     cairo_surface_t* surface = cairo_get_target(cr);
    105     HDC hdc = cairo_win32_surface_get_dc(surface);   
    106     SaveDC(hdc);
    107 
    108199    const cairo_matrix_t* matrix = reinterpret_cast<const cairo_matrix_t*>(&transform);
    109200
     
    116207    xform.eDy = matrix->y0;
    117208
    118     ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
    119 }
    120 
    121 }
     209    ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
     210}
     211
     212void GraphicsContextPlatformPrivate::syncContext(PlatformGraphicsContext* cr)
     213{
     214    cairo_surface_t* surface = cairo_get_target(cr);
     215    m_hdc = cairo_win32_surface_get_dc(surface);   
     216
     217    SetGraphicsMode(m_hdc, GM_ADVANCED); // We need this call for themes to honor world transforms.
     218}
     219
     220}
  • trunk/WebCore/platform/graphics/win/ImageCairoWin.cpp

    r30056 r44539  
    4848    }
    4949
    50     HDC tempDC = CreateCompatibleDC(0);
    51     if (!tempDC) {
    52         LOG_ERROR("Failed to create in-memory DC for Image::blit()");
    53         return false;
    54     }
    55     SelectObject(tempDC, bmp);
    56     GraphicsContext gc(tempDC);
     50    cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)bmpInfo.bmBits,
     51                                               CAIRO_FORMAT_ARGB32,
     52                                               bmpInfo.bmWidth,
     53                                               bmpInfo.bmHeight,
     54                                               bmpInfo.bmWidthBytes);
     55
     56
     57    cairo_t* targetRef = cairo_create(image);
     58    cairo_surface_destroy(image);
     59
     60    GraphicsContext gc(targetRef);
    5761
    5862    IntSize imageSize = BitmapImage::size();
     
    6367
    6468    // Do cleanup
    65     DeleteDC(tempDC);
     69    cairo_destroy(targetRef);
    6670
    6771    return true;
Note: See TracChangeset for help on using the changeset viewer.