1 /* 2 * Copyright (C) 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 "Image.h" 28 #include "BitmapImage.h" 29 #include "GraphicsContext.h" 30 #include <cairo.h> 31 #include <cairo-win32.h> 32 33 #include <windows.h> 34 #include "PlatformString.h" 35 36 namespace WebCore { 37 38 PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap) 39 { 40 DIBSECTION dibSection; 41 if (!GetObject(hBitmap, sizeof(DIBSECTION), &dibSection)) 42 return 0; 43 44 ASSERT(dibSection.dsBm.bmBitsPixel == 32); 45 if (dibSection.dsBm.bmBitsPixel != 32) 46 return 0; 47 48 ASSERT(dibSection.dsBm.bmBits); 49 if (!dibSection.dsBm.bmBits) 50 return 0; 51 52 cairo_surface_t* image = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, dibSection.dsBm.bmWidth, dibSection.dsBm.bmHeight); 53 54 // The BitmapImage object takes over ownership of the cairo_surface_t*, so no need to destroy here. 55 return adoptRef(new BitmapImage(image)); 56 } 57 58 bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size) 59 { 60 ASSERT(bmp); 61 62 BITMAP bmpInfo; 63 GetObject(bmp, sizeof(BITMAP), &bmpInfo); 64 65 // If this is a 32bpp bitmap, which it always should be, we'll clear it so alpha-wise it will be visible 66 if (bmpInfo.bmBitsPixel == 32) { 67 int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight; 68 memset(bmpInfo.bmBits, 255, bufferSize); 69 } 70 71 cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)bmpInfo.bmBits, 72 CAIRO_FORMAT_ARGB32, 73 bmpInfo.bmWidth, 74 bmpInfo.bmHeight, 75 bmpInfo.bmWidthBytes); 76 77 78 cairo_t* targetRef = cairo_create(image); 79 cairo_surface_destroy(image); 80 81 GraphicsContext gc(targetRef); 82 83 IntSize imageSize = BitmapImage::size(); 84 if (size) 85 drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), DeviceColorSpace, CompositeCopy); 86 else 87 draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), DeviceColorSpace, CompositeCopy); 88 89 // Do cleanup 90 cairo_destroy(targetRef); 91 92 return true; 93 } 94 95 void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator compositeOp) 96 { 97 size_t frames = frameCount(); 98 for (size_t i = 0; i < frames; ++i) { 99 cairo_surface_t* image = frameAtIndex(i); 100 if (cairo_image_surface_get_height(image) == static_cast<size_t>(srcSize.height()) && cairo_image_surface_get_width(image) == static_cast<size_t>(srcSize.width())) { 101 size_t currentFrame = m_currentFrame; 102 m_currentFrame = i; 103 draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), DeviceColorSpace, compositeOp); 104 m_currentFrame = currentFrame; 105 return; 106 } 107 } 108 109 // No image of the correct size was found, fallback to drawing the current frame 110 IntSize imageSize = BitmapImage::size(); 111 draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), DeviceColorSpace, compositeOp); 112 } 113 114 } // namespace WebCore 115