1/*
2 * Copyright (C) 2011 Brent Fulgham <bfulgham@webkit.org>
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 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 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 "DIBPixelData.h"
28
29namespace WebCore {
30
31static const WORD bitmapType = 0x4d42; // BMP format
32static const WORD bitmapPixelsPerMeter = 2834; // 72 dpi
33
34DIBPixelData::DIBPixelData(HBITMAP bitmap)
35{
36    initialize(bitmap);
37}
38
39void DIBPixelData::initialize(HBITMAP bitmap)
40{
41    BITMAP bmpInfo;
42    GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
43
44    m_bitmapBuffer = reinterpret_cast<UInt8*>(bmpInfo.bmBits);
45    m_bitmapBufferLength = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
46    m_size = IntSize(bmpInfo.bmWidth, bmpInfo.bmHeight);
47    m_bytesPerRow = bmpInfo.bmWidthBytes;
48    m_bitsPerPixel = bmpInfo.bmBitsPixel;
49}
50
51#ifndef NDEBUG
52void DIBPixelData::writeToFile(LPCWSTR filePath)
53{
54    HANDLE hFile = ::CreateFile(filePath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
55    if (INVALID_HANDLE_VALUE == hFile)
56        return;
57
58    BITMAPFILEHEADER header;
59    header.bfType = bitmapType;
60    header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
61    header.bfReserved1 = 0;
62    header.bfReserved2 = 0;
63    header.bfSize = sizeof(BITMAPFILEHEADER);
64
65    BITMAPINFOHEADER info;
66    info.biSize = sizeof(BITMAPINFOHEADER);
67    info.biWidth = m_size.width();
68    info.biHeight = m_size.height();
69    info.biPlanes = 1;
70    info.biBitCount = m_bitsPerPixel;
71    info.biCompression = BI_RGB;
72    info.biSizeImage = bufferLength();
73    info.biXPelsPerMeter = bitmapPixelsPerMeter;
74    info.biYPelsPerMeter = bitmapPixelsPerMeter;
75    info.biClrUsed = 0;
76    info.biClrImportant = 0;
77
78    DWORD bytesWritten = 0;
79    ::WriteFile(hFile, &header, sizeof(header), &bytesWritten, 0);
80    ::WriteFile(hFile, &info, sizeof(info), &bytesWritten, 0);
81    ::WriteFile(hFile, buffer(), bufferLength(), &bytesWritten, 0);
82
83    ::CloseHandle(hFile);
84}
85#endif
86
87void DIBPixelData::setRGBABitmapAlpha(HDC hdc, const IntRect& dstRect, unsigned char level)
88{
89    HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
90    DIBPixelData pixelData(bitmap);
91    ASSERT(pixelData.bitsPerPixel() == 32);
92
93    IntRect drawRect(dstRect);
94#if !OS(WINCE)
95    XFORM trans;
96    GetWorldTransform(hdc, &trans);
97    IntSize transformedPosition(trans.eDx, trans.eDy);
98    drawRect.move(transformedPosition);
99#endif
100
101    int pixelDataWidth = pixelData.size().width();
102    int pixelDataHeight = pixelData.size().height();
103    IntRect bitmapRect(0, 0, pixelDataWidth, pixelDataHeight);
104    drawRect.intersect(bitmapRect);
105    if (drawRect.isEmpty())
106        return;
107
108    RGBQUAD* bytes = reinterpret_cast<RGBQUAD*>(pixelData.buffer());
109    bytes += drawRect.y() * pixelDataWidth;
110
111    size_t width = drawRect.width();
112    size_t height = drawRect.height();
113    int x = drawRect.x();
114    for (size_t i = 0; i < height; i++) {
115        RGBQUAD* p = bytes + x;
116        for (size_t j = 0; j < width; j++) {
117            p->rgbReserved = level;
118            p++;
119        }
120        bytes += pixelDataWidth;
121    }
122}
123
124} // namespace WebCore
125