Home | History | Annotate | Download | only in win
      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 
     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 
     54 bool GraphicsContext::inTransparencyLayer() const { return m_data->m_transparencyCount; }
     55 
     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, 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 GraphicsContext::WindowsBitmap* GraphicsContext::createWindowsBitmap(IntSize size)
     96 {
     97     return new WindowsBitmap(m_data->m_hdc, size);
     98 }
     99 
    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 
    138 void GraphicsContextPlatformPrivate::save()
    139 {
    140     if (!m_hdc)
    141         return;
    142     SaveDC(m_hdc);
    143 }
    144 
    145 void GraphicsContextPlatformPrivate::restore()
    146 {
    147     if (!m_hdc)
    148         return;
    149     RestoreDC(m_hdc, -1);
    150 }
    151 
    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 
    159 void GraphicsContextPlatformPrivate::clip(const Path&)
    160 {
    161     notImplemented();
    162 }
    163 
    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 
    175 void GraphicsContextPlatformPrivate::rotate(float degreesAngle)
    176 {
    177     XFORM xform = TransformationMatrix().rotate(degreesAngle);
    178     ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
    179 }
    180 
    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 
    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 
    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