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