1 /* 2 * Copyright (C) 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 "DragImage.h" 28 29 #include "BitmapInfo.h" 30 #include "CachedImage.h" 31 #include "GraphicsContext.h" 32 #include "Image.h" 33 #include "RetainPtr.h" 34 35 #include <CoreGraphics/CoreGraphics.h> 36 37 #include <windows.h> 38 39 namespace WebCore { 40 41 void deallocContext(CGContextRef target) 42 { 43 CGContextRelease(target); 44 } 45 46 HBITMAP allocImage(HDC dc, IntSize size, CGContextRef *targetRef) 47 { 48 BitmapInfo bmpInfo = BitmapInfo::create(size); 49 50 LPVOID bits; 51 HBITMAP hbmp = CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, &bits, 0, 0); 52 53 if (!targetRef) 54 return hbmp; 55 56 CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB(); 57 CGContextRef bitmapContext = CGBitmapContextCreate(bits, bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight, 8, 58 bmpInfo.bmiHeader.biWidth * 4, deviceRGB, 59 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); 60 CGColorSpaceRelease(deviceRGB); 61 if (!bitmapContext) { 62 DeleteObject(hbmp); 63 return 0; 64 } 65 66 *targetRef = bitmapContext; 67 return hbmp; 68 } 69 70 static CGContextRef createCgContextFromBitmap(HBITMAP bitmap) 71 { 72 BITMAP info; 73 GetObject(bitmap, sizeof(info), &info); 74 ASSERT(info.bmBitsPixel == 32); 75 76 CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB(); 77 CGContextRef bitmapContext = CGBitmapContextCreate(info.bmBits, info.bmWidth, info.bmHeight, 8, 78 info.bmWidthBytes, deviceRGB, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); 79 CGColorSpaceRelease(deviceRGB); 80 return bitmapContext; 81 } 82 83 DragImageRef scaleDragImage(DragImageRef image, FloatSize scale) 84 { 85 // FIXME: due to the way drag images are done on windows we need 86 // to preprocess the alpha channel <rdar://problem/5015946> 87 88 if (!image) 89 return 0; 90 CGContextRef targetContext; 91 CGContextRef srcContext; 92 CGImageRef srcImage; 93 IntSize srcSize = dragImageSize(image); 94 IntSize dstSize(static_cast<int>(srcSize.width() * scale.width()), static_cast<int>(srcSize.height() * scale.height())); 95 HBITMAP hbmp = 0; 96 HDC dc = GetDC(0); 97 HDC dstDC = CreateCompatibleDC(dc); 98 if (!dstDC) 99 goto exit; 100 101 hbmp = allocImage(dstDC, dstSize, &targetContext); 102 if (!hbmp) 103 goto exit; 104 105 srcContext = createCgContextFromBitmap(image); 106 srcImage = CGBitmapContextCreateImage(srcContext); 107 CGRect rect; 108 rect.origin.x = 0; 109 rect.origin.y = 0; 110 rect.size = dstSize; 111 CGContextDrawImage(targetContext, rect, srcImage); 112 CGImageRelease(srcImage); 113 CGContextRelease(srcContext); 114 CGContextRelease(targetContext); 115 ::DeleteObject(image); 116 image = 0; 117 118 exit: 119 if (!hbmp) 120 hbmp = image; 121 if (dstDC) 122 DeleteDC(dstDC); 123 ReleaseDC(0, dc); 124 return hbmp; 125 } 126 127 DragImageRef createDragImageFromImage(Image* img) 128 { 129 HBITMAP hbmp = 0; 130 HDC dc = GetDC(0); 131 HDC workingDC = CreateCompatibleDC(dc); 132 CGContextRef drawContext = 0; 133 if (!workingDC) 134 goto exit; 135 136 hbmp = allocImage(workingDC, img->size(), &drawContext); 137 138 if (!hbmp) 139 goto exit; 140 141 if (!drawContext) { 142 ::DeleteObject(hbmp); 143 hbmp = 0; 144 } 145 146 CGImageRef srcImage = img->getCGImageRef(); 147 CGRect rect; 148 rect.size = img->size(); 149 rect.origin.x = 0; 150 rect.origin.y = -rect.size.height; 151 static const CGFloat white [] = {1.0, 1.0, 1.0, 1.0}; 152 CGContextScaleCTM(drawContext, 1, -1); 153 CGContextSetFillColor(drawContext, white); 154 CGContextFillRect(drawContext, rect); 155 CGContextSetBlendMode(drawContext, kCGBlendModeNormal); 156 CGContextDrawImage(drawContext, rect, srcImage); 157 CGContextRelease(drawContext); 158 159 exit: 160 if (workingDC) 161 DeleteDC(workingDC); 162 ReleaseDC(0, dc); 163 return hbmp; 164 } 165 166 } 167