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 "DragImage.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "BitmapInfo.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CachedImage.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Image.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RetainPtr.h" 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 35635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <cairo-win32.h> 36635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "GraphicsContextPlatformPrivateCairo.h" 37635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <windows.h> 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 40635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectextern "C" { 41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projecttypedef struct _cairo* CairoContextRef; 42635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 43635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 46635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid deallocContext(CairoContextRef target) 47635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 48635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_destroy(target); 49635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 51635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectHBITMAP allocImage(HDC dc, IntSize size, CairoContextRef* targetRef) 52635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch BitmapInfo bmpInfo = BitmapInfo::create(size); 54635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 55635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project LPVOID bits; 56635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HBITMAP hbmp = CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, &bits, 0, 0); 57635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 58635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // At this point, we have a Cairo surface that points to a Windows DIB. The DIB interprets 59635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // with the opposite meaning of positive Y axis, so everything we draw into this cairo 60635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // context is going to be upside down. 61635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!targetRef) 62635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return hbmp; 63635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 64635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_surface_t* bitmapContext = cairo_image_surface_create_for_data((unsigned char*)bits, 65635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CAIRO_FORMAT_ARGB32, 66635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bmpInfo.bmiHeader.biWidth, 67635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bmpInfo.bmiHeader.biHeight, 68635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project bmpInfo.bmiHeader.biWidth * 4); 69635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 70635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!bitmapContext) { 71635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DeleteObject(hbmp); 72635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 73635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 74635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 75635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *targetRef = cairo_create (bitmapContext); 76635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_surface_destroy (bitmapContext); 77635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 78635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // At this point, we have a Cairo surface that points to a Windows DIB. The DIB interprets 79635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // with the opposite meaning of positive Y axis, so everything we draw into this cairo 80635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // context is going to be upside down. 81635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // 82635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // So, we must invert the CTM for the context so that drawing commands will be flipped 83635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // before they get written to the internal buffer. 84635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_matrix_t matrix; 85635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_matrix_init(&matrix, 1.0, 0.0, 0.0, -1.0, 0.0, size.height()); 86635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_set_matrix(*targetRef, &matrix); 87635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 88635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return hbmp; 89635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 90635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 91635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic cairo_surface_t* createCairoContextFromBitmap(HBITMAP bitmap) 92635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 93635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project BITMAP info; 94635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project GetObject(bitmap, sizeof(info), &info); 95635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(info.bmBitsPixel == 32); 96635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 97635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // At this point, we have a Cairo surface that points to a Windows BITMAP. The BITMAP 98635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // has the opposite meaning of positive Y axis, so everything we draw into this cairo 99635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // context is going to be upside down. 100635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return cairo_image_surface_create_for_data((unsigned char*)info.bmBits, 101635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CAIRO_FORMAT_ARGB32, 102635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project info.bmWidth, 103635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project info.bmHeight, 104635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project info.bmWidthBytes); 105635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 106635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDragImageRef scaleDragImage(DragImageRef image, FloatSize scale) 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 109635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: due to the way drag images are done on windows we need 110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // to preprocess the alpha channel <rdar://problem/5015946> 111635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!image) 112635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project IntSize srcSize = dragImageSize(image); 115635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project IntSize dstSize(static_cast<int>(srcSize.width() * scale.width()), static_cast<int>(srcSize.height() * scale.height())); 116635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 117635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HBITMAP hbmp = 0; 118635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HDC dc = GetDC(0); 119635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HDC dstDC = CreateCompatibleDC(dc); 120635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 121635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!dstDC) 122635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project goto exit; 123635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 124635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CairoContextRef targetContext; 125635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project hbmp = allocImage(dstDC, dstSize, &targetContext); 126635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!hbmp) 127635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project goto exit; 128635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 129635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_surface_t* srcImage = createCairoContextFromBitmap(image); 130635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 131635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Scale the target surface to the new image size, and flip it 132635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // so that when we set the srcImage as the surface it will draw 133635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // right-side-up. 134635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_translate(targetContext, 0, dstSize.height()); 135635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_scale(targetContext, scale.width(), -scale.height()); 136635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_set_source_surface (targetContext, srcImage, 0.0, 0.0); 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 138635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Now we can paint and get the correct result 139635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_paint(targetContext); 140635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 141635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_surface_destroy (srcImage); 142635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_destroy(targetContext); 143635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ::DeleteObject(image); 144635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project image = 0; 145635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 146635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectexit: 147635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!hbmp) 148635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project hbmp = image; 149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (dstDC) 150635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DeleteDC(dstDC); 151635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ReleaseDC(0, dc); 152635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return hbmp; 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDragImageRef createDragImageFromImage(Image* img) 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 157635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HBITMAP hbmp = 0; 158635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HDC dc = GetDC(0); 159635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project HDC workingDC = CreateCompatibleDC(dc); 160635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!workingDC) 161635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project goto exit; 162635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 163635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project CairoContextRef drawContext = 0; 164635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project hbmp = allocImage(workingDC, img->size(), &drawContext); 165635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!hbmp) 166635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project goto exit; 167635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 168635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!drawContext) { 169635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ::DeleteObject(hbmp); 170635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project hbmp = 0; 171635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 172635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 173635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_set_source_rgb (drawContext, 1.0, 0.0, 1.0); 174635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_fill_preserve (drawContext); 175635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 176635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_surface_t* srcImage = img->nativeImageForCurrentFrame(); 177635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 178635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Draw the image. 179635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_set_source_surface(drawContext, srcImage, 0.0, 0.0); 180635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_paint(drawContext); 181635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 182635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project cairo_destroy (drawContext); 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 184635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectexit: 185635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (workingDC) 186635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project DeleteDC(workingDC); 187635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ReleaseDC(0, dc); 188635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return hbmp; 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 192