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