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