/* | |
* Copyright (C) 2008 Apple Inc. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* | |
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | |
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
#include "config.h" | |
#include "GraphicsContext.h" | |
#include "AffineTransform.h" | |
#include "Path.h" | |
#include <cairo-win32.h> | |
#include "GraphicsContextPlatformPrivateCairo.h" | |
using namespace std; | |
namespace WebCore { | |
static cairo_t* createCairoContextWithHDC(HDC hdc, bool hasAlpha) | |
{ | |
// Put the HDC In advanced mode so it will honor affine transforms. | |
SetGraphicsMode(hdc, GM_ADVANCED); | |
cairo_surface_t* surface = 0; | |
HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP)); | |
BITMAP info; | |
if (!GetObject(bitmap, sizeof(info), &info)) | |
surface = cairo_win32_surface_create(hdc); | |
else { | |
ASSERT(info.bmBitsPixel == 32); | |
surface = cairo_image_surface_create_for_data((unsigned char*)info.bmBits, | |
CAIRO_FORMAT_ARGB32, | |
info.bmWidth, | |
info.bmHeight, | |
info.bmWidthBytes); | |
} | |
cairo_t* context = cairo_create(surface); | |
cairo_surface_destroy(surface); | |
return context; | |
} | |
GraphicsContext::GraphicsContext(HDC dc, bool hasAlpha) | |
: m_common(createGraphicsContextPrivate()) | |
, m_data(new GraphicsContextPlatformPrivate) | |
{ | |
if (dc) { | |
m_data->cr = createCairoContextWithHDC(dc, hasAlpha); | |
m_data->m_hdc = dc; | |
} else { | |
setPaintingDisabled(true); | |
m_data->cr = 0; | |
m_data->m_hdc = 0; | |
} | |
if (m_data->cr) { | |
// Make sure the context starts in sync with our state. | |
setPlatformFillColor(fillColor(), fillColorSpace()); | |
setPlatformStrokeColor(strokeColor(), strokeColorSpace()); | |
} | |
} | |
void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap) | |
{ | |
if (!mayCreateBitmap || !hdc || !inTransparencyLayer()) { | |
m_data->restore(); | |
return; | |
} | |
if (dstRect.isEmpty()) | |
return; | |
HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP)); | |
BITMAP info; | |
GetObject(bitmap, sizeof(info), &info); | |
ASSERT(info.bmBitsPixel == 32); | |
// Need to make a cairo_surface_t out of the bitmap's pixel buffer and then draw | |
// it into our context. | |
cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)info.bmBits, | |
CAIRO_FORMAT_ARGB32, | |
info.bmWidth, | |
info.bmHeight, | |
info.bmWidthBytes); | |
// Scale the target surface to the new image size, and flip it | |
// so that when we set the srcImage as the surface it will draw | |
// right-side-up. | |
cairo_translate(m_data->cr, 0, dstRect.height()); | |
cairo_scale(m_data->cr, dstRect.width(), -dstRect.height()); | |
cairo_set_source_surface (m_data->cr, image, dstRect.x(), dstRect.y()); | |
if (m_data->layers.size()) | |
cairo_paint_with_alpha(m_data->cr, m_data->layers.last()); | |
else | |
cairo_paint(m_data->cr); | |
// Delete all our junk. | |
cairo_surface_destroy(image); | |
::DeleteDC(hdc); | |
::DeleteObject(bitmap); | |
} | |
void GraphicsContextPlatformPrivate::syncContext(PlatformGraphicsContext* cr) | |
{ | |
if (!cr) | |
return; | |
cairo_surface_t* surface = cairo_get_target(cr); | |
m_hdc = cairo_win32_surface_get_dc(surface); | |
SetGraphicsMode(m_hdc, GM_ADVANCED); // We need this call for themes to honor world transforms. | |
} | |
void GraphicsContextPlatformPrivate::flush() | |
{ | |
cairo_surface_t* surface = cairo_win32_surface_create(m_hdc); | |
cairo_surface_flush(surface); | |
cairo_surface_destroy(surface); | |
} | |
} |