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