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 43using namespace std; 44 45namespace WebCore { 46 47static 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) 56void GraphicsContext::setShouldIncludeChildWindows(bool include) 57{ 58 m_data->m_shouldIncludeChildWindows = include; 59} 60 61bool GraphicsContext::shouldIncludeChildWindows() const 62{ 63 return m_data->m_shouldIncludeChildWindows; 64} 65 66GraphicsContext::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 86GraphicsContext::WindowsBitmap::~WindowsBitmap() 87{ 88 if (!m_bitmap) 89 return; 90 91 DeleteDC(m_hdc); 92 DeleteObject(m_bitmap); 93} 94 95PassOwnPtr<GraphicsContext::WindowsBitmap> GraphicsContext::createWindowsBitmap(const IntSize& size) 96{ 97 return adoptPtr(new WindowsBitmap(m_data->m_hdc, size)); 98} 99#endif 100 101HDC 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#if PLATFORM(WIN) 140void GraphicsContextPlatformPrivate::save() 141{ 142 if (!m_hdc) 143 return; 144 SaveDC(m_hdc); 145} 146 147void GraphicsContextPlatformPrivate::restore() 148{ 149 if (!m_hdc) 150 return; 151 RestoreDC(m_hdc, -1); 152} 153 154void GraphicsContextPlatformPrivate::clip(const FloatRect& clipRect) 155{ 156 if (!m_hdc) 157 return; 158 IntersectClipRect(m_hdc, clipRect.x(), clipRect.y(), clipRect.maxX(), clipRect.maxY()); 159} 160 161void GraphicsContextPlatformPrivate::clip(const Path&) 162{ 163 notImplemented(); 164} 165 166void 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 175static const double deg2rad = 0.017453292519943295769; // pi/180 176 177void GraphicsContextPlatformPrivate::rotate(float degreesAngle) 178{ 179 XFORM xform = TransformationMatrix().rotate(degreesAngle); 180 ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY); 181} 182 183void 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 192void GraphicsContextPlatformPrivate::concatCTM(const AffineTransform& transform) 193{ 194 if (!m_hdc) 195 return; 196 197 XFORM xform = transform.toTransformationMatrix(); 198 ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY); 199} 200 201void GraphicsContextPlatformPrivate::setCTM(const AffineTransform& transform) 202{ 203 if (!m_hdc) 204 return; 205 206 XFORM xform = transform.toTransformationMatrix(); 207 SetWorldTransform(m_hdc, &xform); 208} 209#endif 210 211} 212