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 PLATFORM(CG)
30 #include "GraphicsContextPlatformPrivateCG.h"
31 #elif PLATFORM(CAIRO)
32 #include "GraphicsContextPlatformPrivateCairo.h"
33 #endif
34
35 #include "BitmapInfo.h"
36 #include "TransformationMatrix.h"
37 #include "NotImplemented.h"
38 #include "Path.h"
39 #include <wtf/MathExtras.h>
40
41 using namespace std;
42
43 namespace WebCore {
44
45 class SVGResourceImage;
46
fillWithClearColor(HBITMAP bitmap)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
inTransparencyLayer() const55 bool GraphicsContext::inTransparencyLayer() const { return m_data->m_transparencyCount; }
56
setShouldIncludeChildWindows(bool include)57 void GraphicsContext::setShouldIncludeChildWindows(bool include)
58 {
59 m_data->m_shouldIncludeChildWindows = include;
60 }
61
shouldIncludeChildWindows() const62 bool GraphicsContext::shouldIncludeChildWindows() const
63 {
64 return m_data->m_shouldIncludeChildWindows;
65 }
66
WindowsBitmap(HDC hdc,IntSize size)67 GraphicsContext::WindowsBitmap::WindowsBitmap(HDC hdc, IntSize size)
68 : m_hdc(0)
69 , m_size(size)
70 {
71 BitmapInfo bitmapInfo = BitmapInfo::create(m_size);
72
73 m_bitmap = CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, reinterpret_cast<void**>(&m_bitmapBuffer), 0, 0);
74 if (!m_bitmap)
75 return;
76
77 m_hdc = CreateCompatibleDC(hdc);
78 SelectObject(m_hdc, m_bitmap);
79
80 BITMAP bmpInfo;
81 GetObject(m_bitmap, sizeof(bmpInfo), &bmpInfo);
82 m_bytesPerRow = bmpInfo.bmWidthBytes;
83 m_bitmapBufferLength = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
84
85 SetGraphicsMode(m_hdc, GM_ADVANCED);
86 }
87
~WindowsBitmap()88 GraphicsContext::WindowsBitmap::~WindowsBitmap()
89 {
90 if (!m_bitmap)
91 return;
92
93 DeleteDC(m_hdc);
94 DeleteObject(m_bitmap);
95 }
96
createWindowsBitmap(IntSize size)97 GraphicsContext::WindowsBitmap* GraphicsContext::createWindowsBitmap(IntSize size)
98 {
99 return new WindowsBitmap(m_data->m_hdc, size);
100 }
101
getWindowsContext(const IntRect & dstRect,bool supportAlphaBlend,bool mayCreateBitmap)102 HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
103 {
104 // FIXME: Should a bitmap be created also when a shadow is set?
105 if (mayCreateBitmap && inTransparencyLayer()) {
106 if (dstRect.isEmpty())
107 return 0;
108
109 // Create a bitmap DC in which to draw.
110 BitmapInfo bitmapInfo = BitmapInfo::create(dstRect.size());
111
112 void* pixels = 0;
113 HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
114 if (!bitmap)
115 return 0;
116
117 HDC bitmapDC = ::CreateCompatibleDC(m_data->m_hdc);
118 ::SelectObject(bitmapDC, bitmap);
119
120 // Fill our buffer with clear if we're going to alpha blend.
121 if (supportAlphaBlend)
122 fillWithClearColor(bitmap);
123
124 // Make sure we can do world transforms.
125 SetGraphicsMode(bitmapDC, GM_ADVANCED);
126
127 // Apply a translation to our context so that the drawing done will be at (0,0) of the bitmap.
128 XFORM xform = TransformationMatrix().translate(-dstRect.x(), -dstRect.y());
129
130 ::SetWorldTransform(bitmapDC, &xform);
131
132 return bitmapDC;
133 }
134
135 m_data->flush();
136 m_data->save();
137 return m_data->m_hdc;
138 }
139
save()140 void GraphicsContextPlatformPrivate::save()
141 {
142 if (!m_hdc)
143 return;
144 SaveDC(m_hdc);
145 }
146
restore()147 void GraphicsContextPlatformPrivate::restore()
148 {
149 if (!m_hdc)
150 return;
151 RestoreDC(m_hdc, -1);
152 }
153
clip(const FloatRect & clipRect)154 void GraphicsContextPlatformPrivate::clip(const FloatRect& clipRect)
155 {
156 if (!m_hdc)
157 return;
158 IntersectClipRect(m_hdc, clipRect.x(), clipRect.y(), clipRect.right(), clipRect.bottom());
159 }
160
clip(const Path &)161 void GraphicsContextPlatformPrivate::clip(const Path&)
162 {
163 notImplemented();
164 }
165
scale(const FloatSize & size)166 void GraphicsContextPlatformPrivate::scale(const FloatSize& size)
167 {
168 if (!m_hdc)
169 return;
170
171 XFORM xform = TransformationMatrix().scaleNonUniform(size.width(), size.height());
172 ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
173 }
174
175 static const double deg2rad = 0.017453292519943295769; // pi/180
176
rotate(float degreesAngle)177 void GraphicsContextPlatformPrivate::rotate(float degreesAngle)
178 {
179 XFORM xform = TransformationMatrix().rotate(degreesAngle);
180 ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
181 }
182
translate(float x,float y)183 void GraphicsContextPlatformPrivate::translate(float x , float y)
184 {
185 if (!m_hdc)
186 return;
187
188 XFORM xform = TransformationMatrix().translate(x, y);
189 ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
190 }
191
concatCTM(const TransformationMatrix & transform)192 void GraphicsContextPlatformPrivate::concatCTM(const TransformationMatrix& transform)
193 {
194 if (!m_hdc)
195 return;
196
197 XFORM xform = transform;
198 ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
199 }
200
201 #if ENABLE(SVG)
contextForImage(SVGResourceImage *)202 GraphicsContext* contextForImage(SVGResourceImage*)
203 {
204 // FIXME: This should go in GraphicsContextCG.cpp
205 notImplemented();
206 return 0;
207 }
208 #endif
209
210 }
211