Host GraphicsContext's CTM inside GraphicsContextState
[WebKit-https.git] / Source / WebCore / platform / graphics / win / GraphicsContextWin.cpp
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2013 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 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 "GraphicsContext.h"
28
29 #if USE(CG)
30 #include "GraphicsContextPlatformPrivateCG.h"
31 #elif USE(CAIRO)
32 #include "GraphicsContextPlatformPrivateCairo.h"
33 #endif
34
35 #include "AffineTransform.h"
36 #include "BitmapInfo.h"
37 #include "TransformationMatrix.h"
38 #include "NotImplemented.h"
39 #include "Path.h"
40 #include <wtf/MathExtras.h>
41 #include <wtf/win/GDIObject.h>
42
43 using namespace std;
44
45 namespace WebCore {
46
47 static void fillWithClearColor(HBITMAP bitmap)
48 {
49     BITMAP bmpInfo;
50     GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
51     int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
52     memset(bmpInfo.bmBits, 0, bufferSize);
53 }
54
55 #if PLATFORM(WIN)
56 void GraphicsContext::setShouldIncludeChildWindows(bool include)
57 {
58     m_data->m_shouldIncludeChildWindows = include;
59 }
60
61 bool GraphicsContext::shouldIncludeChildWindows() const
62 {
63     return m_data->m_shouldIncludeChildWindows;
64 }
65
66 GraphicsContext::WindowsBitmap::WindowsBitmap(HDC hdc, const IntSize& size)
67     : m_hdc(0)
68 {
69     BitmapInfo bitmapInfo = BitmapInfo::create(size);
70
71     void* storage = 0;
72     m_bitmap = CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &storage, 0, 0);
73     if (!m_bitmap)
74         return;
75
76     m_hdc = CreateCompatibleDC(hdc);
77     SelectObject(m_hdc, m_bitmap);
78
79     m_pixelData.initialize(m_bitmap);
80
81     ASSERT(storage == m_pixelData.buffer());
82
83     SetGraphicsMode(m_hdc, GM_ADVANCED);
84 }
85
86 GraphicsContext::WindowsBitmap::~WindowsBitmap()
87 {
88     if (!m_bitmap)
89         return;
90
91     DeleteDC(m_hdc);
92     DeleteObject(m_bitmap);
93 }
94
95 std::unique_ptr<GraphicsContext::WindowsBitmap> GraphicsContext::createWindowsBitmap(const IntSize& size)
96 {
97     return std::make_unique<WindowsBitmap>(m_data->m_hdc, size);
98 }
99 #endif
100
101 HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
102 {
103     // FIXME: Should a bitmap be created also when a shadow is set?
104     if (mayCreateBitmap && (!m_data->m_hdc || isInTransparencyLayer())) {
105         if (dstRect.isEmpty())
106             return 0;
107
108         // Create a bitmap DC in which to draw.
109         BitmapInfo bitmapInfo = BitmapInfo::create(dstRect.size());
110
111         void* pixels = 0;
112         HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
113         if (!bitmap)
114             return 0;
115
116         auto bitmapDC = adoptGDIObject(::CreateCompatibleDC(m_data->m_hdc));
117         ::SelectObject(bitmapDC.get(), bitmap);
118
119         // Fill our buffer with clear if we're going to alpha blend.
120         if (supportAlphaBlend)
121            fillWithClearColor(bitmap);
122
123         // Make sure we can do world transforms.
124         ::SetGraphicsMode(bitmapDC.get(), GM_ADVANCED);
125
126         // Apply a translation to our context so that the drawing done will be at (0,0) of the bitmap.
127         XFORM xform = TransformationMatrix().translate(-dstRect.x(), -dstRect.y());
128
129         ::SetWorldTransform(bitmapDC.get(), &xform);
130
131         return bitmapDC.leak();
132     }
133
134     m_data->flush();
135     m_data->save();
136     return m_data->m_hdc;
137 }
138
139 HDC GraphicsContext::hdc() const
140 {
141     if (!m_data)
142         return nullptr;
143
144     return m_data->m_hdc;
145 }
146
147 #if PLATFORM(WIN)
148 void GraphicsContextPlatformPrivate::save()
149 {
150     if (!m_hdc)
151         return;
152     SaveDC(m_hdc);
153 }
154
155 void GraphicsContextPlatformPrivate::restore()
156 {
157     if (!m_hdc)
158         return;
159     RestoreDC(m_hdc, -1);
160 }
161
162 void GraphicsContextPlatformPrivate::clip(const FloatRect& clipRect)
163 {
164     if (!m_hdc)
165         return;
166     IntersectClipRect(m_hdc, clipRect.x(), clipRect.y(), clipRect.maxX(), clipRect.maxY());
167 }
168
169 void GraphicsContextPlatformPrivate::clip(const Path&)
170 {
171     notImplemented();
172 }
173
174 void GraphicsContextPlatformPrivate::scalePlatformCTM(float x, float y)
175 {
176     if (!m_hdc)
177         return;
178
179     XFORM xform = TransformationMatrix().scaleNonUniform(x, y);
180     ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
181 }
182
183 static const double deg2rad = 0.017453292519943295769; // pi/180
184
185 void GraphicsContextPlatformPrivate::rotatePlatformCTM(float degreesAngle)
186 {
187     XFORM xform = TransformationMatrix().rotate(degreesAngle);
188     ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
189 }
190
191 void GraphicsContextPlatformPrivate::translatePlatformCTM(float x , float y)
192 {
193     if (!m_hdc)
194         return;
195
196     XFORM xform = TransformationMatrix().translate(x, y);
197     ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
198 }
199
200 void GraphicsContextPlatformPrivate::concatPlatformCTM(const AffineTransform& transform)
201 {
202     if (!m_hdc)
203         return;
204
205     XFORM xform = transform.toTransformationMatrix();
206     ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
207 }
208
209 void GraphicsContextPlatformPrivate::setPlatformCTM(const AffineTransform& transform)
210 {
211     if (!m_hdc)
212         return;
213
214     XFORM xform = transform.toTransformationMatrix();
215     SetWorldTransform(m_hdc, &xform);
216 }
217 #endif
218
219 }