f032537618bd172702e780c4de2bb09910d8795c
[WebKit-https.git] / Source / WebCore / platform / graphics / wx / GraphicsContextWx.cpp
1 /*
2  * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com>
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 #include "AffineTransform.h"
30 #include "FloatRect.h"
31 #include "Font.h"
32 #include "IntRect.h"
33 #include "NotImplemented.h"
34 #include "Path.h"
35 #include <wtf/MathExtras.h>
36
37 #include <math.h>
38 #include <stdio.h>
39
40 // see http://trac.wxwidgets.org/ticket/11482
41 #ifdef __WXMSW__
42 #   include "wx/msw/winundef.h"
43 #endif
44
45 #include <wx/defs.h>
46 #include <wx/window.h>
47 #include <wx/dcclient.h>
48 #include <wx/dcgraph.h>
49 #include <wx/graphics.h>
50
51 #if __WXMAC__
52 #include <Carbon/Carbon.h>
53 #elif __WXMSW__
54
55 #include "wx/msw/private.h"
56 // TODO remove this dependency (gdiplus needs the macros)
57
58 #undef max
59 #define max(a, b)            (((a) > (b)) ? (a) : (b))
60
61 #undef min
62 #define min(a, b)            (((a) < (b)) ? (a) : (b))
63
64 #include <windows.h>
65
66 #include <gdiplus.h>
67 #endif
68
69 namespace WebCore {
70
71 int getWxCompositingOperation(CompositeOperator op, bool hasAlpha)
72 {
73     // FIXME: Add support for more operators.
74     if (op == CompositeSourceOver && !hasAlpha)
75         op = CompositeCopy;
76
77     int function;
78     switch (op) {
79         case CompositeClear:
80             function = wxCLEAR;
81         case CompositeCopy:
82             function = wxCOPY; 
83             break;
84         default:
85             function = wxCOPY;
86     }
87     return function;
88 }
89
90 static int strokeStyleToWxPenStyle(int p)
91 {
92     if (p == SolidStroke)
93         return wxSOLID;
94     if (p == DottedStroke)
95         return wxDOT;
96     if (p == DashedStroke)
97         return wxLONG_DASH;
98     if (p == NoStroke)
99         return wxTRANSPARENT;
100     
101     return wxSOLID;
102 }
103
104 class GraphicsContextPlatformPrivate {
105 public:
106     GraphicsContextPlatformPrivate();
107     ~GraphicsContextPlatformPrivate();
108
109 #if USE(WXGC)
110     wxGCDC* context;
111 #else
112     wxWindowDC* context;
113 #endif
114     int mswDCStateID;
115     FloatSize currentScale;
116     wxRegion gtkCurrentClipRgn;
117     wxRegion gtkPaintClipRgn;
118 };
119
120 GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate() :
121     context(0),
122     mswDCStateID(0),
123     gtkCurrentClipRgn(wxRegion()),
124     gtkPaintClipRgn(wxRegion()),
125     currentScale(1.0, 1.0)
126 {
127 }
128
129 GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
130 {
131 }
132
133
134 void GraphicsContext::platformInit(PlatformGraphicsContext* context)
135 {
136     m_data = new GraphicsContextPlatformPrivate;
137     setPaintingDisabled(!context);
138
139     if (context) {
140         // Make sure the context starts in sync with our state.
141         setPlatformFillColor(fillColor(), ColorSpaceDeviceRGB);
142         setPlatformStrokeColor(strokeColor(), ColorSpaceDeviceRGB);
143     }
144 #if USE(WXGC)
145     m_data->context = (wxGCDC*)context;
146 #else
147     m_data->context = (wxWindowDC*)context;
148 #endif
149 }
150
151 void GraphicsContext::platformDestroy()
152 {
153     delete m_data;
154 }
155
156 PlatformGraphicsContext* GraphicsContext::platformContext() const
157 {
158     return (PlatformGraphicsContext*)m_data->context;
159 }
160
161 void GraphicsContext::savePlatformState()
162 {
163     if (m_data->context)
164     {
165 #if USE(WXGC)
166         wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
167         gc->PushState();
168 #else
169     // when everything is working with USE_WXGC, we can remove this
170     #if __WXMAC__
171         CGContextRef context;
172         wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
173         if (gc)
174             context = (CGContextRef)gc->GetNativeContext();
175         if (context)
176             CGContextSaveGState(context);
177     #elif __WXMSW__
178         HDC dc = (HDC)m_data->context->GetHDC();
179         m_data->mswDCStateID = ::SaveDC(dc);
180     #elif __WXGTK__
181         m_data->gtkCurrentClipRgn = m_data->context->m_currentClippingRegion;
182         m_data->gtkPaintClipRgn = m_data->context->m_paintClippingRegion;
183     #endif
184 #endif // __WXMAC__
185     }
186 }
187
188 void GraphicsContext::restorePlatformState()
189 {
190     if (m_data->context)
191     {
192 #if USE(WXGC)
193         wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
194         gc->PopState();
195 #else
196     #if __WXMAC__
197         CGContextRef context;
198         wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
199         if (gc)
200             context = (CGContextRef)gc->GetNativeContext();
201         if (context)
202             CGContextRestoreGState(context); 
203     #elif __WXMSW__
204         HDC dc = (HDC)m_data->context->GetHDC();
205         ::RestoreDC(dc, m_data->mswDCStateID);
206     #elif __WXGTK__
207         m_data->context->m_currentClippingRegion = m_data->gtkCurrentClipRgn;
208         m_data->context->m_paintClippingRegion = m_data->gtkPaintClipRgn;
209     #endif
210
211 #endif // USE_WXGC 
212     }
213 }
214
215 // Draws a filled rectangle with a stroked border.
216 void GraphicsContext::drawRect(const IntRect& rect)
217 {
218     if (paintingDisabled())
219         return;
220
221     save();
222     m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
223     m_data->context->DrawRectangle(rect.x(), rect.y(), rect.width(), rect.height());
224     restore();
225 }
226
227 // This is only used to draw borders.
228 void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
229 {
230     if (paintingDisabled())
231         return;
232
233     FloatPoint p1 = point1;
234     FloatPoint p2 = point2;
235     
236     save();
237     m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
238     m_data->context->DrawLine(point1.x(), point1.y(), point2.x(), point2.y());
239     restore();
240 }
241
242 // This method is only used to draw the little circles used in lists.
243 void GraphicsContext::drawEllipse(const IntRect& rect)
244 {
245     if (paintingDisabled())
246         return;
247
248     save();
249     m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
250     m_data->context->DrawEllipse(rect.x(), rect.y(), rect.width(), rect.height());
251     restore();
252 }
253
254 void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
255 {
256     if (paintingDisabled())
257         return;
258     
259     save();
260     m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
261     m_data->context->DrawEllipticArc(rect.x(), rect.y(), rect.width(), rect.height(), startAngle, startAngle + angleSpan);
262     restore();
263 }
264
265 void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
266 {
267     if (paintingDisabled())
268         return;
269
270     if (npoints <= 1)
271         return;
272
273     save();
274     wxPoint* polygon = new wxPoint[npoints];
275     for (size_t i = 0; i < npoints; i++)
276         polygon[i] = wxPoint(points[i].x(), points[i].y());
277     m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
278     m_data->context->DrawPolygon((int)npoints, polygon);
279     delete [] polygon;
280     restore();
281 }
282
283 void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
284 {
285     if (paintingDisabled())
286         return;
287
288     if (numPoints <= 1)
289         return;
290
291     notImplemented();
292 }
293
294 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
295 {
296     if (paintingDisabled())
297         return;
298
299     save();
300
301     m_data->context->SetPen(*wxTRANSPARENT_PEN);
302     m_data->context->SetBrush(wxBrush(color));
303     m_data->context->DrawRectangle(rect.x(), rect.y(), rect.width(), rect.height());
304
305     restore();
306 }
307
308 void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
309 {
310     if (paintingDisabled())
311         return;
312     
313 #if USE(WXGC)
314     Path path;
315     path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
316     m_data->context->SetBrush(wxBrush(color));
317     wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
318     gc->FillPath(*path.platformPath());
319 #endif
320 }
321
322 void GraphicsContext::drawFocusRing(const Path& path, int width, int offset, const Color& color)
323 {
324     // FIXME: implement
325     notImplemented();
326 }
327
328 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
329 {
330     if (paintingDisabled())
331         return;
332
333     notImplemented();
334 }
335
336 void GraphicsContext::clip(const FloatRect& r)
337 {
338     m_data->context->SetClippingRegion(r.x(), r.y(), r.width(), r.height());
339 }
340
341 void GraphicsContext::clipOut(const Path&)
342 {
343     if (paintingDisabled())
344         return;
345
346     notImplemented();
347 }
348
349 void GraphicsContext::clipOut(const IntRect& rect)
350 {
351     if (paintingDisabled())
352         return;
353
354 #if USE(WXGC)
355     wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
356
357 #ifdef __WXMAC__
358     CGContextRef context = (CGContextRef)gc->GetNativeContext();
359
360     CGRect rects[2] = { CGContextGetClipBoundingBox(context), CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()) };
361     CGContextBeginPath(context);
362     CGContextAddRects(context, rects, 2);
363     CGContextEOClip(context);
364     return;
365 #endif
366
367 #ifdef __WXMSW__
368     Gdiplus::Graphics* g = (Gdiplus::Graphics*)gc->GetNativeContext();
369     Gdiplus::Region excludeRegion(Gdiplus::Rect(rect.x(), rect.y(), rect.width(), rect.height()));
370     g->ExcludeClip(&excludeRegion);
371     return; 
372 #endif
373
374 #endif // USE(WXGC)
375
376     notImplemented();
377 }
378
379 void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
380 {
381     if (paintingDisabled())
382         return;
383         
384     if (path.isEmpty())
385         return; 
386     
387     wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
388
389 #if __WXMAC__
390     CGContextRef context = (CGContextRef)gc->GetNativeContext();   
391     CGPathRef nativePath = (CGPathRef)path.platformPath()->GetNativePath(); 
392     
393     CGContextBeginPath(context);
394     CGContextAddPath(context, nativePath);
395     if (clipRule == RULE_EVENODD)
396         CGContextEOClip(context);
397     else
398         CGContextClip(context);
399 #elif __WXMSW__
400     Gdiplus::Graphics* g = (Gdiplus::Graphics*)gc->GetNativeContext();
401     Gdiplus::GraphicsPath* nativePath = (Gdiplus::GraphicsPath*)path.platformPath()->GetNativePath();
402     if (clipRule == RULE_EVENODD)
403         nativePath->SetFillMode(Gdiplus::FillModeAlternate);
404     else
405         nativePath->SetFillMode(Gdiplus::FillModeWinding);
406     g->SetClip(nativePath);
407 #endif
408 }
409
410 void GraphicsContext::drawLineForText(const FloatPoint& origin, float width, bool printing)
411 {
412     if (paintingDisabled())
413         return;
414
415     save();
416     FloatPoint endPoint = origin + FloatSize(width, 0);
417     m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), wxSOLID));
418     m_data->context->DrawLine(origin.x(), origin.y(), endPoint.x(), endPoint.y());
419     restore();
420 }
421
422 void GraphicsContext::drawLineForTextChecking(const FloatPoint& origin, float width, TextCheckingLineStyle style)
423 {
424     switch (style) {
425     case TextCheckingSpellingLineStyle:
426         m_data->context->SetPen(wxPen(*wxRED, 2, wxLONG_DASH));
427         break;
428     case TextCheckingGrammarLineStyle:
429         m_data->context->SetPen(wxPen(*wxGREEN, 2, wxLONG_DASH));
430         break;
431     default:
432         return;
433     }
434     m_data->context->DrawLine(origin.x(), origin.y(), origin.x() + width, origin.y());
435 }
436
437 void GraphicsContext::clip(const Path& path) 
438
439     if (paintingDisabled())
440         return;
441
442     // if the path is empty, we clip against a zero rect to reduce the clipping region to
443     // nothing - which is the intended behavior of clip() if the path is empty.
444     if (path.isEmpty())
445         m_data->context->SetClippingRegion(0, 0, 0, 0);
446     else
447         clipPath(path, RULE_NONZERO);
448 }
449
450 void GraphicsContext::canvasClip(const Path& path)
451 {
452     clip(path);
453 }
454
455 AffineTransform GraphicsContext::getCTM() const
456
457 #if USE(WXGC)
458     wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
459     if (gc) {
460         wxGraphicsMatrix matrix = gc->GetTransform();
461         double a, b, c, d, e, f;
462         matrix.Get(&a, &b, &c, &d, &e, &f);
463         return AffineTransform(a, b, c, d, e, f);
464     }
465 #endif
466     return AffineTransform();
467 }
468
469 void GraphicsContext::translate(float tx, float ty) 
470
471 #if USE(WXGC)
472     if (m_data->context) {
473         wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
474         gc->Translate(tx, ty);
475     }
476 #endif
477 }
478
479 void GraphicsContext::rotate(float angle) 
480
481 #if USE(WXGC)
482     if (m_data->context) {
483         wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
484         gc->Rotate(angle);
485     }
486 #endif
487 }
488
489 void GraphicsContext::scale(const FloatSize& scale) 
490 {
491 #if USE(WXGC)
492     if (m_data->context) {
493         wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
494         gc->Scale(scale.width(), scale.height());
495         m_data->currentScale = scale;
496     }
497 #endif
498 }
499
500 FloatSize GraphicsContext::currentScale()
501 {
502     return m_data->currentScale;
503 }
504 FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect, RoundingMode)
505 {
506     FloatRect result;
507
508     wxCoord x = (wxCoord)frect.x();
509     wxCoord y = (wxCoord)frect.y();
510
511     x = m_data->context->LogicalToDeviceX(x);
512     y = m_data->context->LogicalToDeviceY(y);
513     result.setX((float)x);
514     result.setY((float)y);
515     x = (wxCoord)frect.width();
516     y = (wxCoord)frect.height();
517     x = m_data->context->LogicalToDeviceXRel(x);
518     y = m_data->context->LogicalToDeviceYRel(y);
519     result.setWidth((float)x);
520     result.setHeight((float)y);
521     return result; 
522 }
523
524 void GraphicsContext::setURLForRect(const KURL&, const IntRect&)
525 {
526     notImplemented();
527 }
528
529 void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
530 {
531     if (m_data->context)
532     {
533 #if wxCHECK_VERSION(2,9,0)
534         m_data->context->SetLogicalFunction(static_cast<wxRasterOperationMode>(getWxCompositingOperation(op, false)));
535 #else
536         m_data->context->SetLogicalFunction(getWxCompositingOperation(op, false));
537 #endif
538     }
539 }
540
541 void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
542 {
543     if (paintingDisabled())
544         return;
545
546     if (m_data->context)
547         m_data->context->SetPen(wxPen(color, strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
548 }
549
550 void GraphicsContext::setPlatformStrokeThickness(float thickness)
551 {
552     if (paintingDisabled())
553         return;
554     
555     if (m_data->context)
556         m_data->context->SetPen(wxPen(strokeColor(), thickness, strokeStyleToWxPenStyle(strokeStyle())));
557
558 }
559
560 void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
561 {
562     if (paintingDisabled())
563         return;
564     
565     if (m_data->context)
566         m_data->context->SetBrush(wxBrush(color));
567 }
568
569 void GraphicsContext::concatCTM(const AffineTransform& transform)
570 {
571     if (paintingDisabled())
572         return;
573
574 #if USE(WXGC)
575     wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
576     if (gc)
577         gc->ConcatTransform(transform);
578 #endif
579     return;
580 }
581
582 void GraphicsContext::setCTM(const AffineTransform& transform)
583 {
584     if (paintingDisabled())
585         return;
586
587 #if USE(WXGC)
588     wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
589     if (gc)
590         gc->SetTransform(transform);
591 #endif
592     return;
593 }
594
595 void GraphicsContext::setPlatformShouldAntialias(bool enable)
596 {
597     if (paintingDisabled())
598         return;
599     notImplemented();
600 }
601
602 void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
603 {
604 }
605
606 InterpolationQuality GraphicsContext::imageInterpolationQuality() const
607 {
608     return InterpolationDefault;
609 }
610
611 void GraphicsContext::fillPath(const Path& path)
612 {
613 #if USE(WXGC)
614     wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
615     if (gc)
616         gc->FillPath(*path.platformPath());
617 #endif
618 }
619
620 void GraphicsContext::strokePath(const Path& path)
621 {
622 #if USE(WXGC)
623     wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
624     if (gc)
625         gc->StrokePath(*path.platformPath());
626 #endif
627 }
628
629 void GraphicsContext::fillRect(const FloatRect& rect)
630 {
631     if (paintingDisabled())
632         return;
633 }
634
635 void GraphicsContext::setPlatformShadow(FloatSize const&, float, Color const&, ColorSpace)
636
637     notImplemented(); 
638 }
639
640 void GraphicsContext::clearPlatformShadow() 
641
642     notImplemented(); 
643 }
644
645 void GraphicsContext::beginTransparencyLayer(float) 
646
647     notImplemented(); 
648 }
649
650 void GraphicsContext::endTransparencyLayer() 
651
652     notImplemented(); 
653 }
654
655 void GraphicsContext::clearRect(const FloatRect&) 
656
657     notImplemented(); 
658 }
659
660 void GraphicsContext::strokeRect(const FloatRect&, float)
661
662     notImplemented(); 
663 }
664
665 void GraphicsContext::setLineCap(LineCap) 
666 {
667     notImplemented(); 
668 }
669
670 void GraphicsContext::setLineDash(const DashArray&, float dashOffset)
671 {
672     notImplemented();
673 }
674
675 void GraphicsContext::setLineJoin(LineJoin)
676 {
677     notImplemented();
678 }
679
680 void GraphicsContext::setMiterLimit(float)
681 {
682     notImplemented();
683 }
684
685 void GraphicsContext::setAlpha(float)
686 {
687     notImplemented();
688 }
689
690 void GraphicsContext::addInnerRoundedRectClip(const IntRect& r, int thickness)
691 {
692     if (paintingDisabled())
693         return;
694
695     FloatRect rect(r);
696     clip(rect);
697     Path path;
698     path.addEllipse(rect);
699     rect.inflate(-thickness);
700     path.addEllipse(rect);
701     clipPath(path, RULE_EVENODD);
702 }
703
704 #if OS(WINDOWS)
705 HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
706 {
707     if (dstRect.isEmpty())
708         return 0;
709
710     // Create a bitmap DC in which to draw.
711     BITMAPINFO bitmapInfo;
712     bitmapInfo.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
713     bitmapInfo.bmiHeader.biWidth         = dstRect.width();
714     bitmapInfo.bmiHeader.biHeight        = dstRect.height();
715     bitmapInfo.bmiHeader.biPlanes        = 1;
716     bitmapInfo.bmiHeader.biBitCount      = 32;
717     bitmapInfo.bmiHeader.biCompression   = BI_RGB;
718     bitmapInfo.bmiHeader.biSizeImage     = 0;
719     bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
720     bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
721     bitmapInfo.bmiHeader.biClrUsed       = 0;
722     bitmapInfo.bmiHeader.biClrImportant  = 0;
723
724     void* pixels = 0;
725     HBITMAP bitmap = ::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
726     if (!bitmap)
727         return 0;
728
729     HDC displayDC = ::GetDC(0);
730     HDC bitmapDC = ::CreateCompatibleDC(displayDC);
731     ::ReleaseDC(0, displayDC);
732
733     ::SelectObject(bitmapDC, bitmap);
734
735     // Fill our buffer with clear if we're going to alpha blend.
736     if (supportAlphaBlend) {
737         BITMAP bmpInfo;
738         GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
739         int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
740         memset(bmpInfo.bmBits, 0, bufferSize);
741     }
742     return bitmapDC;
743 }
744
745 void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
746 {
747     if (hdc) {
748
749         if (!dstRect.isEmpty()) {
750
751             HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
752             BITMAP info;
753             GetObject(bitmap, sizeof(info), &info);
754             ASSERT(info.bmBitsPixel == 32);
755
756             wxBitmap bmp;
757             bmp.SetHBITMAP(bitmap);
758 #if !wxCHECK_VERSION(2,9,0)
759             if (supportAlphaBlend)
760                 bmp.UseAlpha();
761 #endif
762             m_data->context->DrawBitmap(bmp, dstRect.x(), dstRect.y(), supportAlphaBlend);
763
764             ::DeleteObject(bitmap);
765         }
766
767         ::DeleteDC(hdc);
768     }
769 }
770 #endif
771
772 }