18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#include "AffineTransform.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Path.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <cairo-win32.h> 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContextPlatformPrivateCairo.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std; 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic cairo_t* createCairoContextWithHDC(HDC hdc, bool hasAlpha) 405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // Put the HDC In advanced mode so it will honor affine transforms. 425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian SetGraphicsMode(hdc, GM_ADVANCED); 43d0825bca7fe65beaee391d30da42e937db621564Steve Block 44d0825bca7fe65beaee391d30da42e937db621564Steve Block cairo_surface_t* surface = 0; 45d0825bca7fe65beaee391d30da42e937db621564Steve Block 465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP)); 475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian BITMAP info; 49d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!GetObject(bitmap, sizeof(info), &info)) 50d0825bca7fe65beaee391d30da42e937db621564Steve Block surface = cairo_win32_surface_create(hdc); 51d0825bca7fe65beaee391d30da42e937db621564Steve Block else { 52d0825bca7fe65beaee391d30da42e937db621564Steve Block ASSERT(info.bmBitsPixel == 32); 535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 54d0825bca7fe65beaee391d30da42e937db621564Steve Block surface = cairo_image_surface_create_for_data((unsigned char*)info.bmBits, 555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian CAIRO_FORMAT_ARGB32, 565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian info.bmWidth, 575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian info.bmHeight, 585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian info.bmWidthBytes); 59d0825bca7fe65beaee391d30da42e937db621564Steve Block } 605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 61d0825bca7fe65beaee391d30da42e937db621564Steve Block cairo_t* context = cairo_create(surface); 62d0825bca7fe65beaee391d30da42e937db621564Steve Block cairo_surface_destroy(surface); 635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return context; 655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectGraphicsContext::GraphicsContext(HDC dc, bool hasAlpha) 68f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch : m_updatingControlTints(false) 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 70f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch platformInit(dc, hasAlpha); 71f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 72f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 73f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid GraphicsContext::platformInit(HDC dc, bool hasAlpha) 74f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 752bde8e466a4451c7319e3a072d118917957d6554Steve Block cairo_t* cr = 0; 762bde8e466a4451c7319e3a072d118917957d6554Steve Block if (dc) 772bde8e466a4451c7319e3a072d118917957d6554Steve Block cr = createCairoContextWithHDC(dc, hasAlpha); 782bde8e466a4451c7319e3a072d118917957d6554Steve Block else 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project setPaintingDisabled(true); 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch m_data = new GraphicsContextPlatformPrivateToplevel(new PlatformContextCairo(cr)); 822bde8e466a4451c7319e3a072d118917957d6554Steve Block m_data->m_hdc = dc; 832bde8e466a4451c7319e3a072d118917957d6554Steve Block if (platformContext()->cr()) { 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Make sure the context starts in sync with our state. 85643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setPlatformFillColor(fillColor(), fillColorSpace()); 86643ca7872b450ea4efacab6188849e5aac2ba161Steve Block setPlatformStrokeColor(strokeColor(), strokeColorSpace()); 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 90ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Blockstatic void setRGBABitmapAlpha(unsigned char* bytes, size_t length, unsigned char level) 91ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block{ 92ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block for (size_t i = 0; i < length; i += 4) 93ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block bytes[i + 3] = level; 94ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block} 95ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block 962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void drawBitmapToContext(GraphicsContextPlatformPrivate* context, cairo_t* cr, const DIBPixelData& pixelData, const IntSize& translate) 972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // Need to make a cairo_surface_t out of the bitmap's pixel buffer and then draw 992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // it into our context. 1002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_surface_t* surface = cairo_image_surface_create_for_data(pixelData.buffer(), 1012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch CAIRO_FORMAT_ARGB32, 1022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch pixelData.size().width(), 1032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch pixelData.size().height(), 1042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch pixelData.bytesPerRow()); 1052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // Flip the target surface so that when we set the srcImage as 1072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // the surface it will draw right-side-up. 1082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_save(cr); 1092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_translate(cr, static_cast<double>(translate.width()), static_cast<double>(translate.height())); 1102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_scale(cr, 1, -1); 1112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_set_source_surface(cr, surface, 0, 0); 1122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (context->layers.size()) 1142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_paint_with_alpha(cr, context->layers.last()); 1152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch else 1162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_paint(cr); 1172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // Delete all our junk. 1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_surface_destroy(surface); 1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_restore(cr); 1212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 1222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap) 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1255abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick bool createdBitmap = mayCreateBitmap && (!m_data->m_hdc || inTransparencyLayer()); 1265abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick if (!hdc || !createdBitmap) { 1275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian m_data->restore(); 1285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return; 1295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (dstRect.isEmpty()) 1325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return; 1335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 1342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch OwnPtr<HBITMAP> bitmap = adoptPtr(static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP))); 1355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 1362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch DIBPixelData pixelData(bitmap.get()); 1372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch ASSERT(pixelData.bitsPerPixel() == 32); 1385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 139ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block // If this context does not support alpha blending, then it may have 140ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block // been drawn with GDI functions which always set the alpha channel 141ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block // to zero. We need to manually set the bitmap to be fully opaque. 1422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch unsigned char* bytes = reinterpret_cast<unsigned char*>(pixelData.buffer()); 143ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block if (!supportAlphaBlend) 1442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch setRGBABitmapAlpha(bytes, pixelData.size().height() * pixelData.bytesPerRow(), 255); 145ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block 1462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch drawBitmapToContext(m_data, platformContext()->cr(), pixelData, IntSize(dstRect.x(), dstRect.height() + dstRect.y())); 1475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 1485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ::DeleteDC(hdc); 1492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 1502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid GraphicsContext::drawWindowsBitmap(WindowsBitmap* bitmap, const IntPoint& point) 1522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 1532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch drawBitmapToContext(m_data, platformContext()->cr(), bitmap->windowsDIB(), IntSize(point.x(), bitmap->size().height() + point.y())); 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1562bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid GraphicsContextPlatformPrivate::syncContext(cairo_t* cr) 1575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 1580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!cr) 1590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return; 1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian cairo_surface_t* surface = cairo_get_target(cr); 1625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian m_hdc = cairo_win32_surface_get_dc(surface); 1635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 1645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian SetGraphicsMode(m_hdc, GM_ADVANCED); // We need this call for themes to honor world transforms. 1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid GraphicsContextPlatformPrivate::flush() 1680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cairo_surface_t* surface = cairo_win32_surface_create(m_hdc); 1700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cairo_surface_flush(surface); 1710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cairo_surface_destroy(surface); 1720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 1730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 175