1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 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 "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
42 using namespace std;
43
44 namespace WebCore {
45
fillWithClearColor(HBITMAP bitmap)46 static void fillWithClearColor(HBITMAP bitmap)
47 {
48 BITMAP bmpInfo;
49 GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
50 int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
51 memset(bmpInfo.bmBits, 0, bufferSize);
52 }
53
inTransparencyLayer() const54 bool GraphicsContext::inTransparencyLayer() const { return m_data->m_transparencyCount; }
55
setShouldIncludeChildWindows(bool include)56 void GraphicsContext::setShouldIncludeChildWindows(bool include)
57 {
58 m_data->m_shouldIncludeChildWindows = include;
59 }
60
shouldIncludeChildWindows() const61 bool GraphicsContext::shouldIncludeChildWindows() const
62 {
63 return m_data->m_shouldIncludeChildWindows;
64 }
65
WindowsBitmap(HDC hdc,IntSize size)66 GraphicsContext::WindowsBitmap::WindowsBitmap(HDC hdc, 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
~WindowsBitmap()86 GraphicsContext::WindowsBitmap::~WindowsBitmap()
87 {
88 if (!m_bitmap)
89 return;
90
91 DeleteDC(m_hdc);
92 DeleteObject(m_bitmap);
93 }
94
createWindowsBitmap(IntSize size)95 GraphicsContext::WindowsBitmap* GraphicsContext::createWindowsBitmap(IntSize size)
96 {
97 return new WindowsBitmap(m_data->m_hdc, size);
98 }
99
getWindowsContext(const IntRect & dstRect,bool supportAlphaBlend,bool mayCreateBitmap)100 HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
101 {
102 // FIXME: Should a bitmap be created also when a shadow is set?
103 if (mayCreateBitmap && (!m_data->m_hdc || inTransparencyLayer())) {
104 if (dstRect.isEmpty())
105 return 0;
106
107 // Create a bitmap DC in which to draw.
108 BitmapInfo bitmapInfo = BitmapInfo::create(dstRect.size());
109
110 void* pixels = 0;
111 HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
112 if (!bitmap)
113 return 0;
114
115 HDC bitmapDC = ::CreateCompatibleDC(m_data->m_hdc);
116 ::SelectObject(bitmapDC, bitmap);
117
118 // Fill our buffer with clear if we're going to alpha blend.
119 if (supportAlphaBlend)
120 fillWithClearColor(bitmap);
121
122 // Make sure we can do world transforms.
123 SetGraphicsMode(bitmapDC, GM_ADVANCED);
124
125 // Apply a translation to our context so that the drawing done will be at (0,0) of the bitmap.
126 XFORM xform = TransformationMatrix().translate(-dstRect.x(), -dstRect.y());
127
128 ::SetWorldTransform(bitmapDC, &xform);
129
130 return bitmapDC;
131 }
132
133 m_data->flush();
134 m_data->save();
135 return m_data->m_hdc;
136 }
137
save()138 void GraphicsContextPlatformPrivate::save()
139 {
140 if (!m_hdc)
141 return;
142 SaveDC(m_hdc);
143 }
144
restore()145 void GraphicsContextPlatformPrivate::restore()
146 {
147 if (!m_hdc)
148 return;
149 RestoreDC(m_hdc, -1);
150 }
151
clip(const FloatRect & clipRect)152 void GraphicsContextPlatformPrivate::clip(const FloatRect& clipRect)
153 {
154 if (!m_hdc)
155 return;
156 IntersectClipRect(m_hdc, clipRect.x(), clipRect.y(), clipRect.maxX(), clipRect.maxY());
157 }
158
clip(const Path &)159 void GraphicsContextPlatformPrivate::clip(const Path&)
160 {
161 notImplemented();
162 }
163
scale(const FloatSize & size)164 void GraphicsContextPlatformPrivate::scale(const FloatSize& size)
165 {
166 if (!m_hdc)
167 return;
168
169 XFORM xform = TransformationMatrix().scaleNonUniform(size.width(), size.height());
170 ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
171 }
172
173 static const double deg2rad = 0.017453292519943295769; // pi/180
174
rotate(float degreesAngle)175 void GraphicsContextPlatformPrivate::rotate(float degreesAngle)
176 {
177 XFORM xform = TransformationMatrix().rotate(degreesAngle);
178 ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
179 }
180
translate(float x,float y)181 void GraphicsContextPlatformPrivate::translate(float x , float y)
182 {
183 if (!m_hdc)
184 return;
185
186 XFORM xform = TransformationMatrix().translate(x, y);
187 ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
188 }
189
concatCTM(const AffineTransform & transform)190 void GraphicsContextPlatformPrivate::concatCTM(const AffineTransform& transform)
191 {
192 if (!m_hdc)
193 return;
194
195 XFORM xform = transform.toTransformationMatrix();
196 ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
197 }
198
setCTM(const AffineTransform & transform)199 void GraphicsContextPlatformPrivate::setCTM(const AffineTransform& transform)
200 {
201 if (!m_hdc)
202 return;
203
204 XFORM xform = transform.toTransformationMatrix();
205 SetWorldTransform(m_hdc, &xform);
206 }
207
208 }
209