]> git.saurik.com Git - wxWidgets.git/blob - src/msw/dc.cpp
Corrected missing pipe in treectrl.h, wxOK->wxID_OK in wxGetTextFromUser,
[wxWidgets.git] / src / msw / dc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dc.cpp
3 // Purpose: wxDC class
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "dc.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/frame.h"
25 #include "wx/dc.h"
26 #include "wx/utils.h"
27 #include "wx/dialog.h"
28 #include "wx/app.h"
29 #endif
30
31 #include "wx/dcprint.h"
32 #include "wx/msw/private.h"
33
34 #include <string.h>
35 #include <math.h>
36 #include <fstream.h>
37
38 #if USE_COMMON_DIALOGS
39 #include <commdlg.h>
40 #endif
41
42 #ifndef __WIN32__
43 #include <print.h>
44 #endif
45
46 #ifdef DrawText
47 #undef DrawText
48 #endif
49
50 #ifdef GetCharWidth
51 #undef GetCharWidth
52 #endif
53
54 #ifdef StartDoc
55 #undef StartDoc
56 #endif
57
58 #if !USE_SHARED_LIBRARY
59 IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
60 #endif
61
62 // Declarations local to this file
63
64 #define YSCALE(y) (yorigin - (y))
65
66 // #define wx_round(a) (int)((a)+.5)
67
68 // Default constructor
69 wxDC::wxDC(void)
70 {
71 // Stop internal GDI objects being found and pointers kept
72 // after these objects have been deleted.
73 // No - it's OK; these lists won't return them
74 // because their 'visible' status will be FALSE.
75 /*
76 wxTheFontList->RemoveFont(&m_font);
77 wxThePenList->RemovePen(&m_pen);
78 wxTheBrushList->RemoveBrush(&m_brush);
79 wxTheBrushList->RemoveBrush(&m_backgroundBrush);
80 */
81
82 m_minX = 0; m_minY = 0; m_maxX = 0; m_maxY = 0;
83 m_clipping = FALSE;
84 m_autoSetting = TRUE ;
85 // m_scaleGDI = TRUE;
86
87 m_filename = "";
88 // m_selectedBitmap = NULL;
89 m_canvas = NULL;
90 /*
91 cur_dc = NULL ;
92 cur_bk = 0 ;
93 cur_cpen = NULL ;
94 cur_cbrush = NULL ;
95 */
96 m_oldBitmap = 0;
97 m_oldPen = 0;
98 m_oldBrush = 0;
99 m_oldFont = 0;
100 m_oldPalette = 0;
101 m_minX = 0; m_minY = 0; m_maxX = 0; m_maxY = 0;
102 // m_font = NULL;
103 m_logicalOriginX = 0;
104 m_logicalOriginY = 0;
105 m_deviceOriginX = 0;
106 m_deviceOriginY = 0;
107 m_logicalScaleX = 1.0;
108 m_logicalScaleY = 1.0;
109 m_userScaleX = 1.0;
110 m_userScaleY = 1.0;
111 m_signX = 1;
112 m_signY = 1;
113 m_systemScaleX = 1.0;
114 m_systemScaleY = 1.0;
115 m_mappingMode = MM_TEXT;
116 // m_dontDelete = FALSE;
117 m_bOwnsDC = FALSE;
118 m_hDC = 0;
119 m_clipping = FALSE;
120 m_ok = TRUE;
121 m_windowExtX = VIEWPORT_EXTENT;
122 m_windowExtY = VIEWPORT_EXTENT;
123 m_logicalFunction = -1;
124
125 m_backgroundBrush = *wxWHITE_BRUSH;
126 // m_backgroundBrush.UseResource();
127
128 m_textForegroundColour = *wxBLACK;
129 m_textBackgroundColour = *wxWHITE;
130
131 m_colour = wxColourDisplay();
132
133 m_hDCCount = 0;
134 }
135
136
137 wxDC::~wxDC(void)
138 {
139 if ( m_hDC != 0 ) {
140 SelectOldObjects(m_hDC);
141 if ( m_bOwnsDC ) {
142 if ( m_canvas == NULL )
143 ::DeleteDC((HDC)m_hDC);
144 else
145 ::ReleaseDC((HWND)m_canvas->GetHWND(), (HDC)m_hDC);
146 }
147 }
148
149 /*
150 if (m_hDC)
151 {
152 SelectOldObjects(m_hDC);
153 ::DeleteDC((HDC) m_hDC);
154 }
155 */
156 }
157
158 // This will select current objects out of the DC,
159 // which is what you have to do before deleting the
160 // DC.
161 void wxDC::SelectOldObjects(WXHDC dc)
162 {
163 #if DEBUG > 1
164 wxDebugMsg("wxDC::SelectOldObjects %X\n", this);
165 #endif
166 if (dc)
167 {
168 if (m_oldBitmap)
169 {
170 #if DEBUG > 1
171 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HBITMAP %X\n", m_oldBitmap);
172 #endif
173 ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
174 if (m_selectedBitmap.Ok())
175 {
176 m_selectedBitmap.SetSelectedInto(NULL);
177 }
178 }
179 m_oldBitmap = 0 ;
180 if (m_oldPen)
181 {
182 #if DEBUG > 1
183 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HPEN %X\n", m_oldPen);
184 #endif
185 ::SelectObject((HDC) dc, (HPEN) m_oldPen);
186 }
187 m_oldPen = 0 ;
188 if (m_oldBrush)
189 {
190 #if DEBUG > 1
191 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HBRUSH %X\n", m_oldBrush);
192 #endif
193 ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
194 }
195 m_oldBrush = 0 ;
196 if (m_oldFont)
197 {
198 #if DEBUG > 1
199 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HFONT %X\n", m_oldFont);
200 #endif
201 ::SelectObject((HDC) dc, (HFONT) m_oldFont);
202 }
203 m_oldFont = 0 ;
204 if (m_oldPalette)
205 {
206 #if DEBUG > 1
207 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HPALETTE %X\n", m_oldPalette);
208 #endif
209 ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE);
210 }
211 #if DEBUG > 1
212 wxDebugMsg("wxDC::SelectOldObjects: Done.\n");
213 #endif
214 m_oldPalette = 0 ;
215 }
216 /*
217 if (m_font.Ok())
218 m_font.ReleaseResource();
219 if (m_pen.Ok())
220 m_pen.ReleaseResource();
221 if (m_brush.Ok())
222 m_brush.ReleaseResource();
223 if (m_backgroundBrush.Ok())
224 m_backgroundBrush.ReleaseResource();
225 */
226
227 m_brush = wxNullBrush ;
228 m_pen = wxNullPen;
229 m_palette = wxNullPalette;
230 m_font = wxNullFont;
231 m_backgroundBrush = wxNullBrush;
232 m_selectedBitmap = wxNullBitmap;
233 }
234
235 void wxDC::SetClippingRegion(long cx, long cy, long cw, long ch)
236 {
237 m_clipping = TRUE;
238 m_clipX1 = (int)cx;
239 m_clipY1 = (int)cy;
240 m_clipX2 = (int)(cx + cw);
241 m_clipY2 = (int)(cy + ch);
242
243 BeginDrawing();
244
245 DoClipping((WXHDC) m_hDC);
246
247 EndDrawing();
248 }
249
250 void wxDC::DoClipping(WXHDC dc)
251 {
252 if (m_clipping && dc)
253 {
254 IntersectClipRect((HDC) dc, XLOG2DEV(m_clipX1), YLOG2DEV(m_clipY1),
255 XLOG2DEV(m_clipX2), YLOG2DEV(m_clipY2));
256 #if 0
257 int x_off = 0;
258 int y_off = 0;
259 if (m_canvas)
260 {
261 m_canvas->CalcScrolledPosition(0, 0, &x_off, &y_off);
262 }
263 // HRGN rgn = CreateRectRgn(XLOG2DEV(m_clipX1 + x_off), YLOG2DEV(m_clipY1 + y_off),
264 // XLOG2DEV(m_clipX2 + x_off), YLOG2DEV(m_clipY2 + y_off));
265
266 // SelectClipRgn(dc, rgn);
267 // DeleteObject(rgn);
268 IntersectClipRect((HDC) dc, XLOG2DEV(m_clipX1 + x_off), YLOG2DEV(m_clipY1 + y_off),
269 XLOG2DEV(m_clipX2 + x_off), YLOG2DEV(m_clipY2 + y_off));
270 #endif
271 }
272 }
273
274 void wxDC::DestroyClippingRegion(void)
275 {
276 BeginDrawing();
277
278 if (m_clipping && m_hDC)
279 {
280 // SelectClipRgn(dc, NULL);
281 HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
282 #if DEBUG > 1
283 wxDebugMsg("wxDC::DestroyClippingRegion: Selecting HRGN %X\n", rgn);
284 #endif
285 SelectClipRgn((HDC) m_hDC, rgn);
286 #if DEBUG > 1
287 wxDebugMsg("wxDC::DestroyClippingRegion: Deleting HRGN %X\n", rgn);
288 #endif
289 DeleteObject(rgn);
290 }
291 m_clipping = FALSE;
292
293 EndDrawing();
294 }
295
296 bool wxDC::CanDrawBitmap(void) const
297 {
298 return TRUE;
299 }
300
301 bool wxDC::CanGetTextExtent(void) const
302 {
303 // What sort of display is it?
304 int technology = ::GetDeviceCaps((HDC) m_hDC, TECHNOLOGY);
305
306 bool ok;
307
308 if (technology != DT_RASDISPLAY && technology != DT_RASPRINTER)
309 ok = FALSE;
310 else ok = TRUE;
311
312 return ok;
313 }
314
315 void wxDC::SetPalette(const wxPalette& palette)
316 {
317 BeginDrawing();
318
319 m_palette = m_palette;
320
321 if (!m_palette.Ok())
322 {
323 // Setting a NULL colourmap is a way of restoring
324 // the original colourmap
325 if (m_oldPalette)
326 {
327 ::SelectPalette((HDC) m_hDC, (HPALETTE) m_oldPalette, TRUE);
328 #if DEBUG > 1
329 wxDebugMsg("wxDC::SetPalette: set old palette %X\n", m_oldPalette);
330 #endif
331 m_oldPalette = 0;
332 }
333
334 return;
335 }
336
337 if (m_palette.Ok() && m_palette.GetHPALETTE())
338 {
339 HPALETTE oldPal = ::SelectPalette((HDC) m_hDC, (HPALETTE) m_palette.GetHPALETTE(), TRUE);
340 if (!m_oldPalette)
341 m_oldPalette = (WXHPALETTE) oldPal;
342
343 #if DEBUG > 1
344 wxDebugMsg("wxDC::SetPalette %X: selected palette %X\n", this, m_palette.GetHPALETTE());
345 if (oldPal)
346 wxDebugMsg("wxDC::SetPalette: oldPal was palette %X\n", oldPal);
347 if (m_oldPalette)
348 wxDebugMsg("wxDC::SetPalette: m_oldPalette is palette %X\n", m_oldPalette);
349 #endif
350 ::RealizePalette((HDC) m_hDC);
351 }
352
353 EndDrawing();
354 }
355
356 void wxDC::Clear(void)
357 {
358 BeginDrawing();
359
360 RECT rect;
361 if (m_canvas)
362 GetClientRect((HWND) m_canvas->GetHWND(), &rect);
363 else if (m_selectedBitmap.Ok())
364 {
365 rect.left = 0; rect.top = 0;
366 rect.right = m_selectedBitmap.GetWidth();
367 rect.bottom = m_selectedBitmap.GetHeight();
368 }
369 (void) ::SetMapMode((HDC) m_hDC, MM_TEXT);
370
371 DWORD colour = GetBkColor((HDC) m_hDC);
372 HBRUSH brush = CreateSolidBrush(colour);
373 FillRect((HDC) m_hDC, &rect, brush);
374 DeleteObject(brush);
375
376 ::SetMapMode((HDC) m_hDC, MM_ANISOTROPIC);
377 ::SetViewportExtEx((HDC) m_hDC, VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
378 ::SetWindowExtEx((HDC) m_hDC, m_windowExtX, m_windowExtY, NULL);
379 ::SetViewportOrgEx((HDC) m_hDC, (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
380 ::SetWindowOrgEx((HDC) m_hDC, (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
381
382 EndDrawing();
383 }
384
385 void wxDC::FloodFill(long x, long y, wxColour *col, int style)
386 {
387 // int xx = (int)x;
388 // int yy = (int)y;
389
390 if (m_brush.Ok() && m_autoSetting)
391 SetBrush(m_brush);
392
393 // if (m_canvas)
394 // m_canvas->CalcScrolledPosition((int)x, (int)y, &xx, &yy);
395
396 BeginDrawing();
397
398 (void)ExtFloodFill((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y),
399 col->GetPixel(),
400 style==wxFLOOD_SURFACE?
401 FLOODFILLSURFACE:FLOODFILLBORDER
402 );
403
404 EndDrawing();
405
406 CalcBoundingBox(x, y);
407 }
408
409 bool wxDC::GetPixel(long x, long y, wxColour *col) const
410 {
411 // added by steve 29.12.94 (copied from DrawPoint)
412 // returns TRUE for pixels in the color of the current pen
413 // and FALSE for all other pixels colors
414 // if col is non-NULL return the color of the pixel
415
416 // get the color of the pixel
417 COLORREF pixelcolor = ::GetPixel((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y));
418 // get the color of the pen
419 COLORREF pencolor = 0x00ffffff;
420 if (m_pen.Ok())
421 {
422 pencolor = m_pen.GetColour().GetPixel() ;
423 }
424
425 // return the color of the pixel
426 if(col)
427 col->Set(GetRValue(pixelcolor),GetGValue(pixelcolor),GetBValue(pixelcolor));
428
429 // check, if color of the pixels is the same as the color
430 // of the current pen
431 return(pixelcolor==pencolor);
432 }
433
434 void wxDC::CrossHair(long x, long y)
435 {
436 if (m_pen.Ok() && m_autoSetting)
437 SetPen(m_pen);
438
439 // We suppose that our screen is 2000x2000 max.
440 long x1 = x-2000;
441 long y1 = y-2000;
442 long x2 = x+2000;
443 long y2 = y+2000;
444
445 BeginDrawing();
446
447 (void)MoveToEx((HDC) m_hDC, XLOG2DEV(x1), YLOG2DEV(y), NULL);
448 (void)LineTo((HDC) m_hDC, XLOG2DEV(x2), YLOG2DEV(y));
449
450 (void)MoveToEx((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y1), NULL);
451 (void)LineTo((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y2));
452
453 EndDrawing();
454
455 CalcBoundingBox(x1, y1);
456 CalcBoundingBox(x2, y2);
457 }
458
459 void wxDC::DrawLine(long x1, long y1, long x2, long y2)
460 {
461 // BUGBUG - is this necessary? YES YES YES YEs Yes yes ye....
462 if (m_pen.Ok() && m_autoSetting)
463 SetPen(m_pen);
464
465 BeginDrawing();
466
467 (void)MoveToEx((HDC) m_hDC, XLOG2DEV(x1), YLOG2DEV(y1), NULL);
468 (void)LineTo((HDC) m_hDC, XLOG2DEV(x2), YLOG2DEV(y2));
469
470 /* MATTHEW: [6] New normalization */
471 #if WX_STANDARD_GRAPHICS
472 (void)LineTo((HDC) m_hDC, XLOG2DEV(x2) + 1, YLOG2DEV(y2));
473 #endif
474
475 EndDrawing();
476
477 CalcBoundingBox(x1, y1);
478 CalcBoundingBox(x2, y2);
479 }
480
481 void wxDC::DrawArc(long x1,long y1,long x2,long y2,double xc,double yc)
482 {
483 double dx = xc-x1 ;
484 double dy = yc-y1 ;
485 double radius = (double)sqrt(dx*dx+dy*dy) ;;
486 if (x1==x2 && x2==y2)
487 {
488 DrawEllipse(xc,yc,(double)(radius*2.0),(double)(radius*2)) ;
489 return ;
490 }
491
492 // BUGBUG - is this necessary?
493 if (m_pen.Ok() && m_autoSetting)
494 SetPen(m_pen) ;
495
496 BeginDrawing();
497
498 long xx1 = XLOG2DEV(x1) ;
499 long yy1 = YLOG2DEV(y1) ;
500 long xx2 = XLOG2DEV(x2) ;
501 long yy2 = YLOG2DEV(y2) ;
502 long xxc = XLOG2DEV(xc) ;
503 long yyc = YLOG2DEV(yc) ;
504 long ray = (long) sqrt(double((xxc-xx1)*(xxc-xx1)+(yyc-yy1)*(yyc-yy1))) ;
505
506 (void)MoveToEx((HDC) m_hDC, (int) xx1, (int) yy1, NULL);
507 long xxx1 = (long) (xxc-ray);
508 long yyy1 = (long) (yyc-ray);
509 long xxx2 = (long) (xxc+ray);
510 long yyy2 = (long) (yyc+ray);
511 if (m_brush.Ok() && m_brush.GetStyle() !=wxTRANSPARENT)
512 {
513 // BUGBUG - is this necessary?
514 if (m_brush.GetStyle()!=wxTRANSPARENT&&m_autoSetting)
515 SetBrush(m_brush) ;
516 Pie((HDC) m_hDC,xxx1,yyy1,xxx2,yyy2,
517 xx1,yy1,xx2,yy2) ;
518 }
519 else
520 Arc((HDC) m_hDC,xxx1,yyy1,xxx2,yyy2,
521 xx1,yy1,xx2,yy2) ;
522
523 EndDrawing();
524
525 CalcBoundingBox((xc-radius), (yc-radius));
526 CalcBoundingBox((xc+radius), (yc+radius));
527 }
528
529 void wxDC::DrawPoint(long x, long y)
530 {
531 // BUGBUG - is this necessary?
532 if (m_pen.Ok() && m_autoSetting)
533 SetPen(m_pen) ;
534
535 BeginDrawing();
536
537 COLORREF color = 0x00ffffff;
538 if (m_pen.Ok())
539 {
540 // m_pen.RealizeResource();
541 color = m_pen.GetColour().GetPixel() ;
542 }
543
544 SetPixel((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), color);
545
546 EndDrawing();
547
548 CalcBoundingBox(x, y);
549 }
550
551 void wxDC::DrawPolygon(int n, wxPoint points[], long xoffset, long yoffset,int fillStyle)
552 {
553 // BUGBUG - is this necessary?
554 if (m_pen.Ok() && m_autoSetting)
555 SetPen(m_pen) ;
556
557 BeginDrawing();
558
559 POINT *cpoints = new POINT[n];
560 int i;
561 for (i = 0; i < n; i++)
562 {
563 cpoints[i].x = (int)(XLOG2DEV(points[i].x + xoffset));
564 cpoints[i].y = (int)(YLOG2DEV(points[i].y + yoffset));
565
566 CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
567 }
568
569 int prev = SetPolyFillMode((HDC) m_hDC,fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING) ;
570 (void)Polygon((HDC) m_hDC, cpoints, n);
571 SetPolyFillMode((HDC) m_hDC,prev) ;
572
573 EndDrawing();
574
575 delete[] cpoints;
576 }
577
578 void wxDC::DrawLines(int n, wxPoint points[], long xoffset, long yoffset)
579 {
580 // BUGBUG - is this necessary?
581 if (m_pen.Ok() && m_autoSetting)
582 SetPen(m_pen) ;
583
584 BeginDrawing();
585
586 POINT *cpoints = new POINT[n];
587 int i;
588 for (i = 0; i < n; i++)
589 {
590 cpoints[i].x = (int)(XLOG2DEV(points[i].x + xoffset));
591 cpoints[i].y = (int)(YLOG2DEV(points[i].y + yoffset));
592
593 CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
594 }
595
596 (void)Polyline((HDC) m_hDC, cpoints, n);
597
598 EndDrawing();
599
600 delete[] cpoints;
601 }
602
603 void wxDC::DrawRectangle(long x, long y, long width, long height)
604 {
605 // BUGBUG - is this necessary?
606 if (m_pen.Ok() && m_autoSetting)
607 SetPen(m_pen) ;
608
609 long x2 = x + width;
610 long y2 = y + height;
611
612 BeginDrawing();
613
614 /* MATTHEW: [6] new normalization */
615 #if WX_STANDARD_GRAPHICS
616 bool do_brush, do_pen;
617
618 do_brush = m_brush.Ok() && m_brush.GetStyle() != wxTRANSPARENT;
619 do_pen = m_pen.Ok() && m_pen.GetStyle() != wxTRANSPARENT;
620
621 if (do_brush) {
622 HPEN orig_pen = NULL;
623
624 if (do_pen || !m_pen.Ok())
625 orig_pen = ::SelectObject((HDC) m_hDC, ::GetStockObject(NULL_PEN));
626
627 (void)Rectangle((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y),
628 XLOG2DEV(x2) + 1, YLOG2DEV(y2) + 1);
629
630 if (do_pen || !m_pen.Ok())
631 ::SelectObject((HDC) m_hDC , orig_pen);
632 }
633 if (do_pen) {
634 HBRUSH orig_brush = NULL;
635
636 if (do_brush || !m_brush.Ok())
637 orig_brush = ::SelectObject((HDC) m_hDC, ::GetStockObject(NULL_BRUSH));
638
639 (void)Rectangle((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y),
640 XLOG2DEV(x2), YLOG2DEV(y2));
641
642 if (do_brush || !m_brush.Ok())
643 ::SelectObject((HDC) m_hDC, orig_brush);
644 }
645 #else
646 (void)Rectangle((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2));
647 #endif
648
649 CalcBoundingBox(x, y);
650 CalcBoundingBox(x2, y2);
651
652 EndDrawing();
653 }
654
655 void wxDC::DrawRoundedRectangle(long x, long y, long width, long height, double radius)
656 {
657 // BUGBUG - is this necessary?
658 if (m_pen.Ok() && m_autoSetting)
659 SetPen(m_pen) ;
660
661 // Now, a negative radius value is interpreted to mean
662 // 'the proportion of the smallest X or Y dimension'
663
664 if (radius < 0.0)
665 {
666 double smallest = 0.0;
667 if (width < height)
668 smallest = width;
669 else
670 smallest = height;
671 radius = (- radius * smallest);
672 }
673
674 long x2 = (x+width);
675 long y2 = (y+height);
676
677 BeginDrawing();
678
679 (void)RoundRect((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2),
680 YLOG2DEV(y2), 2*XLOG2DEV(radius), 2*YLOG2DEV(radius));
681
682 CalcBoundingBox(x, y);
683 CalcBoundingBox(x2, y2);
684
685 EndDrawing();
686 }
687
688 void wxDC::DrawEllipse(long x, long y, long width, long height)
689 {
690 // BUGBUG - is this necessary?
691 if (m_pen.Ok() && m_autoSetting)
692 SetPen(m_pen) ;
693
694 long x2 = (x+width);
695 long y2 = (y+height);
696
697 BeginDrawing();
698
699 (void)Ellipse((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2));
700
701 EndDrawing();
702
703 CalcBoundingBox(x, y);
704 CalcBoundingBox(x2, y2);
705 }
706
707 // Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
708 void wxDC::DrawEllipticArc(long x,long y,long w,long h,double sa,double ea)
709 {
710 // BUGBUG - is this necessary?
711 if (m_pen.Ok() && m_autoSetting)
712 SetPen(m_pen) ;
713
714 long x2 = (x+w);
715 long y2 = (y+h);
716
717 BeginDrawing();
718
719 const double deg2rad = 3.14159265359 / 180.0;
720 int rx1 = XLOG2DEV(x+w/2);
721 int ry1 = YLOG2DEV(y+h/2);
722 int rx2 = rx1;
723 int ry2 = ry1;
724 rx1 += (int)(100.0 * abs(w) * cos(sa * deg2rad));
725 ry1 -= (int)(100.0 * abs(h) * m_signY * sin(sa * deg2rad));
726 rx2 += (int)(100.0 * abs(w) * cos(ea * deg2rad));
727 ry2 -= (int)(100.0 * abs(h) * m_signY * sin(ea * deg2rad));
728
729 // draw pie with NULL_PEN first and then outline otherwise a line is
730 // drawn from the start and end points to the centre
731 HPEN orig_pen = ::SelectObject((HDC) m_hDC, ::GetStockObject(NULL_PEN));
732 if (m_signY > 0)
733 {
734 (void)Pie((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2)+1, YLOG2DEV(y2)+1,
735 rx1, ry1, rx2, ry2);
736 }
737 else
738 {
739 (void)Pie((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y)-1, XLOG2DEV(x2)+1, YLOG2DEV(y2),
740 rx1, ry1-1, rx2, ry2-1);
741 }
742 ::SelectObject((HDC) m_hDC, orig_pen);
743 (void)Arc((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2),
744 rx1, ry1, rx2, ry2);
745
746 EndDrawing();
747
748 CalcBoundingBox(x, y);
749 CalcBoundingBox(x2, y2);
750 }
751
752 void wxDC::DrawIcon(const wxIcon& icon, long x, long y)
753 {
754 BeginDrawing();
755
756 ::DrawIcon((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), (HICON) icon.GetHICON());
757 CalcBoundingBox(x, y);
758 CalcBoundingBox(x+icon.GetWidth(), y+icon.GetHeight());
759
760 EndDrawing();
761 }
762
763 void wxDC::SetFont(const wxFont& the_font)
764 {
765 // Release the current font from servitude (decrements the usage count)
766 // if (m_font.Ok())
767 // m_font.ReleaseResource();
768
769 BeginDrawing();
770
771 m_font = the_font;
772
773 if (!the_font.Ok())
774 {
775 if (m_oldFont)
776 ::SelectObject((HDC) m_hDC, (HFONT) m_oldFont);
777 m_oldFont = 0 ;
778 }
779
780 if (m_font.Ok() && m_font.GetResourceHandle())
781 {
782 #if DEBUG > 1
783 wxDebugMsg("wxDC::SetFont: Selecting HFONT %X\n", m_font.GetResourceHandle());
784 #endif
785 HFONT f = (HFONT) ::SelectObject((HDC) m_hDC, (HFONT) m_font.GetResourceHandle());
786 if (!m_oldFont)
787 m_oldFont = (WXHFONT) f;
788 }
789 EndDrawing();
790 }
791
792 void wxDC::SetPen(const wxPen& pen)
793 {
794 BeginDrawing();
795
796 // if (m_pen.Ok())
797 // m_pen.ReleaseResource();
798
799 m_pen = pen;
800
801 if (!m_pen.Ok())
802 {
803 if (m_oldPen)
804 ::SelectObject((HDC) m_hDC, (HPEN) m_oldPen);
805 m_oldPen = 0 ;
806 }
807
808 if (m_pen.Ok())
809 {
810 // m_pen.UseResource();
811 // m_pen.RealizeResource();
812 if (m_pen.GetResourceHandle())
813 {
814 HPEN p = (HPEN) ::SelectObject((HDC) m_hDC, (HPEN)m_pen.GetResourceHandle()) ;
815 if (!m_oldPen)
816 m_oldPen = (WXHPEN) p;
817 }
818 }
819
820 EndDrawing();
821 }
822
823 void wxDC::SetBrush(const wxBrush& brush)
824 {
825 BeginDrawing();
826
827 // if (m_brush.Ok())
828 // m_brush.ReleaseResource();
829
830 m_brush = brush;
831
832 if (!m_brush.Ok())
833 {
834 if (m_oldBrush)
835 ::SelectObject((HDC) m_hDC, (HBRUSH) m_oldBrush);
836 m_oldBrush = 0 ;
837 }
838
839 if (m_brush.Ok())
840 {
841 // m_brush.UseResource();
842 // m_brush.RealizeResource();
843
844 if (m_brush.GetResourceHandle())
845 {
846 HBRUSH b = 0;
847 b = ::SelectObject((HDC) m_hDC, (HBRUSH)m_brush.GetResourceHandle()) ;
848 if (!m_oldBrush)
849 m_oldBrush = (WXHBRUSH) b;
850 }
851 }
852 EndDrawing();
853 }
854
855 void wxDC::DrawText(const wxString& text, long x, long y, bool use16bit)
856 {
857 BeginDrawing();
858
859 if (m_font.Ok() && m_font.GetResourceHandle())
860 {
861 #if DEBUG > 1
862 wxDebugMsg("wxDC::DrawText: Selecting HFONT %X\n", m_font.GetResourceHandle());
863 #endif
864 HFONT f = ::SelectObject((HDC) m_hDC, (HFONT) m_font.GetResourceHandle());
865 if (!m_oldFont)
866 m_oldFont = (WXHFONT) f;
867 }
868
869 if (m_textForegroundColour.Ok())
870 SetTextColor((HDC) m_hDC, m_textForegroundColour.GetPixel() ) ;
871
872 DWORD old_background;
873 if (m_textBackgroundColour.Ok())
874 {
875 old_background = SetBkColor((HDC) m_hDC, m_textBackgroundColour.GetPixel() ) ;
876 }
877
878 if (m_backgroundMode == wxTRANSPARENT)
879 SetBkMode((HDC) m_hDC, TRANSPARENT);
880 else
881 SetBkMode((HDC) m_hDC, OPAQUE);
882
883 (void)TextOut((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), (char *) (const char *)text, strlen((const char *)text));
884
885 if (m_textBackgroundColour.Ok())
886 (void)SetBkColor((HDC) m_hDC, old_background);
887
888 CalcBoundingBox(x, y);
889
890 long w, h;
891 GetTextExtent(text, &w, &h);
892 CalcBoundingBox((x + w), (y + h));
893
894 EndDrawing();
895 }
896
897 void wxDC::SetBackground(const wxBrush& brush)
898 {
899 // if (m_backgroundBrush.Ok())
900 // m_backgroundBrush.ReleaseResource();
901
902 m_backgroundBrush = brush;
903
904 if (!m_backgroundBrush.Ok())
905 return;
906
907 // m_backgroundBrush.UseResource();
908 // m_backgroundBrush.RealizeResource() ;
909
910 if (m_canvas)
911 {
912 bool customColours = TRUE;
913 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
914 // change background colours from the control-panel specified colours.
915 if (m_canvas->IsKindOf(CLASSINFO(wxWindow)) && ((m_canvas->GetWindowStyleFlag() & wxUSER_COLOURS) != wxUSER_COLOURS))
916 customColours = FALSE;
917
918 if (customColours)
919 {
920 // HBRUSH br = (m_backgroundBrush.GetStyle()==wxTRANSPARENT) ?
921 // GetStockObject(NULL_BRUSH) : (HBRUSH) m_backgroundBrush.GetResourceHandle();
922 if (m_backgroundBrush.GetStyle()==wxTRANSPARENT)
923 {
924 m_canvas->m_backgroundTransparent = TRUE;
925 }
926 else
927 {
928 m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
929 m_canvas->m_backgroundTransparent = FALSE;
930 }
931 }
932 }
933 BeginDrawing();
934
935 COLORREF new_color = m_backgroundBrush.GetColour().GetPixel() ;
936 {
937 (void)SetBkColor((HDC) m_hDC, new_color);
938 }
939
940 EndDrawing();
941 }
942
943 void wxDC::SetBackgroundMode(int mode)
944 {
945 m_backgroundMode = mode;
946
947 BeginDrawing();
948
949 if (m_backgroundMode == wxTRANSPARENT)
950 ::SetBkMode((HDC) m_hDC, TRANSPARENT);
951 else
952 ::SetBkMode((HDC) m_hDC, OPAQUE);
953
954 EndDrawing();
955 }
956
957 void wxDC::SetLogicalFunction(int function)
958 {
959 m_logicalFunction = function;
960
961 BeginDrawing();
962
963 SetRop((WXHDC) m_hDC);
964
965 EndDrawing();
966 }
967
968 void wxDC::SetRop(WXHDC dc)
969 {
970 if (!dc || m_logicalFunction < 0)
971 return;
972
973 int c_rop;
974 // These may be wrong
975 switch (m_logicalFunction)
976 {
977 // case wxXOR: c_rop = R2_XORPEN; break;
978 case wxXOR: c_rop = R2_NOTXORPEN; break;
979 case wxINVERT: c_rop = R2_NOT; break;
980 case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
981 case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
982 case wxCLEAR: c_rop = R2_WHITE; break;
983 case wxSET: c_rop = R2_BLACK; break;
984 case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
985 case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
986 case wxAND: c_rop = R2_MASKPEN; break;
987 case wxOR: c_rop = R2_MERGEPEN; break;
988 case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
989 case wxEQUIV:
990 case wxNAND:
991 case wxCOPY:
992 default:
993 c_rop = R2_COPYPEN; break;
994 }
995 SetROP2((HDC) dc, c_rop);
996 }
997
998 bool wxDC::StartDoc(const wxString& message)
999 {
1000 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
1001 return TRUE;
1002
1003 bool flag = FALSE;
1004
1005 DOCINFO docinfo;
1006 docinfo.cbSize = sizeof(DOCINFO);
1007 docinfo.lpszDocName = (const char *)message;
1008 docinfo.lpszOutput = (const char *)m_filename;
1009 #if defined(__WIN95__)
1010 docinfo.lpszDatatype = NULL;
1011 docinfo.fwType = 0;
1012 #endif
1013
1014 if (m_hDC) flag = (SP_ERROR !=
1015 #ifndef __WIN32__
1016 ::StartDoc((HDC) m_hDC, &docinfo));
1017 #else
1018 #ifdef UNICODE
1019 ::StartDocW((HDC) m_hDC, &docinfo));
1020 #else
1021 ::StartDocA((HDC) m_hDC, &docinfo));
1022 #endif
1023 #endif
1024
1025 else flag = FALSE;
1026
1027 return flag;
1028 }
1029
1030 void wxDC::EndDoc(void)
1031 {
1032 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
1033 return;
1034 if (m_hDC) ::EndDoc((HDC) m_hDC);
1035 }
1036
1037 void wxDC::StartPage(void)
1038 {
1039 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
1040 return;
1041 if (m_hDC)
1042 ::StartPage((HDC) m_hDC);
1043 }
1044
1045 void wxDC::EndPage(void)
1046 {
1047 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
1048 return;
1049 if (m_hDC)
1050 ::EndPage((HDC) m_hDC);
1051 }
1052
1053 long wxDC::GetCharHeight(void) const
1054 {
1055 TEXTMETRIC lpTextMetric;
1056
1057 GetTextMetrics((HDC) m_hDC, &lpTextMetric);
1058
1059 return YDEV2LOGREL(lpTextMetric.tmHeight);
1060 }
1061
1062 long wxDC::GetCharWidth(void) const
1063 {
1064 TEXTMETRIC lpTextMetric;
1065
1066 GetTextMetrics((HDC) m_hDC, &lpTextMetric);
1067
1068 return XDEV2LOGREL(lpTextMetric.tmAveCharWidth);
1069 }
1070
1071 void wxDC::GetTextExtent(const wxString& string, long *x, long *y,
1072 long *descent, long *externalLeading, wxFont *theFont, bool use16bit) const
1073 {
1074 wxFont *fontToUse = (wxFont*) theFont;
1075 if (!fontToUse)
1076 fontToUse = (wxFont*) &m_font;
1077
1078 SIZE sizeRect;
1079 TEXTMETRIC tm;
1080
1081 GetTextExtentPoint((HDC) m_hDC, (char *)(const char *) string, strlen((char *)(const char *) string), &sizeRect);
1082 GetTextMetrics((HDC) m_hDC, &tm);
1083
1084 *x = XDEV2LOGREL(sizeRect.cx);
1085 *y = YDEV2LOGREL(sizeRect.cy);
1086 if (descent) *descent = tm.tmDescent;
1087 if (externalLeading) *externalLeading = tm.tmExternalLeading;
1088 }
1089
1090 void wxDC::SetMapMode(int mode)
1091 {
1092 m_mappingMode = mode;
1093
1094 int pixel_width = 0;
1095 int pixel_height = 0;
1096 int mm_width = 0;
1097 int mm_height = 0;
1098
1099 BeginDrawing();
1100
1101 pixel_width = GetDeviceCaps((HDC) m_hDC, HORZRES);
1102 pixel_height = GetDeviceCaps((HDC) m_hDC, VERTRES);
1103 mm_width = GetDeviceCaps((HDC) m_hDC, HORZSIZE);
1104 mm_height = GetDeviceCaps((HDC) m_hDC, VERTSIZE);
1105
1106 if ((pixel_width == 0) || (pixel_height == 0) || (mm_width == 0) || (mm_height == 0))
1107 {
1108 // if (!m_hDC && m_canvas)
1109 // m_canvas->ReleaseHDC() ;
1110 return;
1111 }
1112
1113 double mm2pixelsX = pixel_width/mm_width;
1114 double mm2pixelsY = pixel_height/mm_height;
1115
1116 switch (mode)
1117 {
1118 case MM_TWIPS:
1119 {
1120 m_logicalScaleX = (twips2mm * mm2pixelsX);
1121 m_logicalScaleY = (twips2mm * mm2pixelsY);
1122 break;
1123 }
1124 case MM_POINTS:
1125 {
1126 m_logicalScaleX = (pt2mm * mm2pixelsX);
1127 m_logicalScaleY = (pt2mm * mm2pixelsY);
1128 break;
1129 }
1130 case MM_METRIC:
1131 {
1132 m_logicalScaleX = mm2pixelsX;
1133 m_logicalScaleY = mm2pixelsY;
1134 break;
1135 }
1136 case MM_LOMETRIC:
1137 {
1138 m_logicalScaleX = (mm2pixelsX/10.0);
1139 m_logicalScaleY = (mm2pixelsY/10.0);
1140 break;
1141 }
1142 default:
1143 case MM_TEXT:
1144 {
1145 m_logicalScaleX = 1.0;
1146 m_logicalScaleY = 1.0;
1147 break;
1148 }
1149 }
1150
1151 if (::GetMapMode((HDC) m_hDC) != MM_ANISOTROPIC)
1152 ::SetMapMode((HDC) m_hDC, MM_ANISOTROPIC);
1153
1154 SetViewportExtEx((HDC) m_hDC, VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
1155 m_windowExtX = (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT);
1156 m_windowExtY = (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT);
1157 ::SetWindowExtEx((HDC) m_hDC, m_windowExtX, m_windowExtY, NULL);
1158 ::SetViewportOrgEx((HDC) m_hDC, (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
1159 ::SetWindowOrgEx((HDC) m_hDC, (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
1160
1161 EndDrawing();
1162 }
1163
1164 void wxDC::SetUserScale(double x, double y)
1165 {
1166 m_userScaleX = x;
1167 m_userScaleY = y;
1168
1169 SetMapMode(m_mappingMode);
1170 }
1171
1172 void wxDC::SetAxisOrientation(bool xLeftRight, bool yBottomUp)
1173 {
1174 m_signX = xLeftRight ? 1 : -1;
1175 m_signY = yBottomUp ? -1 : 1;
1176
1177 SetMapMode(m_mappingMode);
1178 }
1179
1180 void wxDC::SetSystemScale(double x, double y)
1181 {
1182 m_systemScaleX = x;
1183 m_systemScaleY = y;
1184
1185 SetMapMode(m_mappingMode);
1186 }
1187
1188 void wxDC::SetLogicalOrigin(long x, long y)
1189 {
1190 m_logicalOriginX = x;
1191 m_logicalOriginY = y;
1192
1193 BeginDrawing();
1194
1195 ::SetWindowOrgEx((HDC) m_hDC, (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
1196
1197 EndDrawing();
1198 }
1199
1200 void wxDC::SetDeviceOrigin(long x, long y)
1201 {
1202 m_deviceOriginX = x;
1203 m_deviceOriginY = y;
1204
1205 BeginDrawing();
1206
1207 ::SetViewportOrgEx((HDC) m_hDC, (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
1208
1209 EndDrawing();
1210 }
1211
1212 long wxDC::DeviceToLogicalX(long x) const
1213 {
1214 return (long) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX) - m_logicalOriginX) ;
1215 }
1216
1217 long wxDC::DeviceToLogicalXRel(long x) const
1218 {
1219 return (long) ((x)/(m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX)) ;
1220 }
1221
1222 long wxDC::DeviceToLogicalY(long y) const
1223 {
1224 return (long) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY) - m_logicalOriginY) ;
1225 }
1226
1227 long wxDC::DeviceToLogicalYRel(long y) const
1228 {
1229 return (long) ((y)/(m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY)) ;
1230 }
1231
1232 long wxDC::LogicalToDeviceX(long x) const
1233 {
1234 return (long) (floor((x) - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX + m_deviceOriginX) ;
1235 }
1236
1237 long wxDC::LogicalToDeviceXRel(long x) const
1238 {
1239 return (long) (floor(x)*m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX) ;
1240 }
1241
1242 long wxDC::LogicalToDeviceY(long y) const
1243 {
1244 return (long) (floor((y) - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY + m_deviceOriginY);
1245 }
1246
1247 long wxDC::LogicalToDeviceYRel(long y) const
1248 {
1249 return (long) (floor(y)*m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY) ;
1250 }
1251
1252 // This group of functions may not do any conversion
1253 // if m_scaleGDI is TRUE, since the HDC does the
1254 // conversion automatically.
1255
1256 long wxDC::ImplDeviceToLogicalX(long x) const
1257 {
1258 // return (m_scaleGDI ? x : DeviceToLogicalX(x));
1259 return x;
1260 }
1261
1262 long wxDC::ImplDeviceToLogicalY(long y) const
1263 {
1264 // return (m_scaleGDI ? y : DeviceToLogicalY(y));
1265 return y;
1266 }
1267
1268 long wxDC::ImplDeviceToLogicalXRel(long x) const
1269 {
1270 // return (m_scaleGDI ? x : DeviceToLogicalXRel(x));
1271 return x;
1272 }
1273
1274 long wxDC::ImplDeviceToLogicalYRel(long y) const
1275 {
1276 // return (m_scaleGDI ? y : DeviceToLogicalYRel(y));
1277 return y;
1278 }
1279
1280 long wxDC::ImplLogicalToDeviceX(long x) const
1281 {
1282 // return (m_scaleGDI ? (floor(double(x))) : LogicalToDeviceX(x));
1283 return x;
1284 }
1285
1286 long wxDC::ImplLogicalToDeviceY(long y) const
1287 {
1288 // return (m_scaleGDI ? (floor(double(y))) : LogicalToDeviceY(y));
1289 return y;
1290 }
1291
1292 long wxDC::ImplLogicalToDeviceXRel(long x) const
1293 {
1294 // return (m_scaleGDI ? (floor(double(x))) : LogicalToDeviceXRel(x));
1295 return x;
1296 }
1297
1298 long wxDC::ImplLogicalToDeviceYRel(long y) const
1299 {
1300 // return (m_scaleGDI ? (floor(double(y))) : LogicalToDeviceYRel(y));
1301 return y;
1302 }
1303
1304 bool wxDC::Blit(long xdest, long ydest, long width, long height,
1305 wxDC *source, long xsrc, long ysrc, int rop, bool useMask)
1306 {
1307 BeginDrawing();
1308 source->BeginDrawing();
1309
1310 long xdest1 = xdest;
1311 long ydest1 = ydest;
1312 long xsrc1 = xsrc;
1313 long ysrc1 = ysrc;
1314
1315 // Chris Breeze 18/5/98: use text foreground/background colours
1316 // when blitting from 1-bit bitmaps
1317 COLORREF old_textground = ::GetTextColor((HDC)m_hDC);
1318 COLORREF old_background = ::GetBkColor((HDC)m_hDC);
1319 if (m_textForegroundColour.Ok())
1320 {
1321 ::SetTextColor((HDC) m_hDC, m_textForegroundColour.GetPixel() ) ;
1322 }
1323 if (m_textBackgroundColour.Ok())
1324 {
1325 ::SetBkColor((HDC) m_hDC, m_textBackgroundColour.GetPixel() ) ;
1326 }
1327
1328 DWORD dwRop = rop == wxCOPY ? SRCCOPY :
1329 rop == wxCLEAR ? WHITENESS :
1330 rop == wxSET ? BLACKNESS :
1331 rop == wxINVERT ? DSTINVERT :
1332 rop == wxAND ? MERGECOPY :
1333 rop == wxOR ? MERGEPAINT :
1334 rop == wxSRC_INVERT ? NOTSRCCOPY :
1335 rop == wxXOR ? SRCINVERT :
1336 rop == wxOR_REVERSE ? MERGEPAINT :
1337 rop == wxAND_REVERSE ? SRCERASE :
1338 rop == wxSRC_OR ? SRCPAINT :
1339 rop == wxSRC_AND ? SRCAND :
1340 SRCCOPY;
1341
1342 bool success;
1343 if (useMask && source->m_selectedBitmap.Ok() && source->m_selectedBitmap.GetMask())
1344 {
1345
1346 #if 0 // __WIN32__
1347 // Not implemented under Win95 (or maybe a specific device?)
1348 if (MaskBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1349 (HDC) source->m_hDC, xsrc1, ysrc1, (HBITMAP) source->m_selectedBitmap.GetMask()->GetMaskBitmap(),
1350 0, 0, 0xAACC0020))
1351 {
1352 // Success
1353 }
1354 else
1355 #endif
1356 {
1357 // Old code
1358 #if 0
1359 HDC dc_mask = CreateCompatibleDC((HDC) source->m_hDC);
1360 ::SelectObject(dc_mask, (HBITMAP) source->m_selectedBitmap.GetMask()->GetMaskBitmap());
1361 success = (BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1362 dc_mask, xsrc1, ysrc1, 0x00220326 /* NOTSRCAND */) != 0);
1363 success = (BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1364 (HDC) source->m_hDC, xsrc1, ysrc1, SRCPAINT) != 0);
1365 ::SelectObject(dc_mask, 0);
1366 ::DeleteDC(dc_mask);
1367 #endif
1368 // New code from Chris Breeze, 8/5/98
1369
1370 // create a temp buffer bitmap and DCs to access it and the mask
1371 HDC dc_mask = ::CreateCompatibleDC((HDC) source->m_hDC);
1372 HDC dc_buffer = ::CreateCompatibleDC((HDC) m_hDC);
1373 HBITMAP buffer_bmap = ::CreateCompatibleBitmap((HDC) m_hDC, width, height);
1374 ::SelectObject(dc_mask, (HBITMAP) source->m_selectedBitmap.GetMask()->GetMaskBitmap());
1375 ::SelectObject(dc_buffer, buffer_bmap);
1376
1377 // copy dest to buffer
1378 ::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
1379 (HDC) m_hDC, xdest1, ydest1, SRCCOPY);
1380
1381 // copy src to buffer using selected raster op
1382 ::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
1383 (HDC) source->m_hDC, xsrc1, ysrc1, dwRop);
1384
1385 // set masked area in buffer to BLACK (pixel value 0)
1386 COLORREF prevBkCol = ::SetBkColor((HDC) m_hDC, RGB(255, 255, 255));
1387 COLORREF prevCol = ::SetTextColor((HDC) m_hDC, RGB(0, 0, 0));
1388 ::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
1389 dc_mask, xsrc1, ysrc1, SRCAND);
1390
1391 // set unmasked area in dest to BLACK
1392 ::SetBkColor((HDC) m_hDC, RGB(0, 0, 0));
1393 ::SetTextColor((HDC) m_hDC, RGB(255, 255, 255));
1394 ::BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1395 dc_mask, xsrc1, ysrc1, SRCAND);
1396 ::SetBkColor((HDC) m_hDC, prevBkCol); // restore colours to original values
1397 ::SetTextColor((HDC) m_hDC, prevCol);
1398
1399 // OR buffer to dest
1400 success = (::BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1401 dc_buffer, 0, 0, SRCPAINT) != 0);
1402
1403 // tidy up temporary DCs and bitmap
1404 ::SelectObject(dc_mask, 0);
1405 ::DeleteDC(dc_mask);
1406 ::SelectObject(dc_buffer, 0);
1407 ::DeleteDC(dc_buffer);
1408 ::DeleteObject(buffer_bmap);
1409 }
1410 }
1411 else
1412 {
1413 success = (BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height, (HDC) source->m_hDC,
1414 xsrc1, ysrc1, dwRop) != 0);
1415 }
1416 ::SetTextColor((HDC)m_hDC, old_textground);
1417 ::SetBkColor((HDC)m_hDC, old_background);
1418 source->EndDrawing();
1419 EndDrawing();
1420
1421 return success;
1422 }
1423
1424 void wxDC::GetSize(int* width, int* height) const
1425 {
1426 long w=::GetDeviceCaps((HDC) m_hDC,HORZRES);
1427 long h=::GetDeviceCaps((HDC) m_hDC,VERTRES);
1428 *width = w;
1429 *height = h;
1430 }
1431
1432 void wxDC::GetSizeMM(long *width, long *height) const
1433 {
1434 long w=::GetDeviceCaps((HDC) m_hDC,HORZSIZE);
1435 long h=::GetDeviceCaps((HDC) m_hDC,VERTSIZE);
1436 *width = w;
1437 *height = h;
1438 }
1439
1440 /*
1441 #if USE_SPLINES
1442 # if USE_XFIG_SPLINE_CODE
1443 # include "../common/xfspline.inc"
1444 # else
1445 # include "../common/wxspline.inc"
1446 # endif
1447 #endif // USE_SPLINES
1448 */
1449
1450 #if USE_SPLINES
1451 #include "xfspline.inc"
1452 #endif // USE_SPLINES
1453
1454 void wxDC::DrawPolygon(wxList *list, long xoffset, long yoffset,int fillStyle)
1455 {
1456 int n = list->Number();
1457 wxPoint *points = new wxPoint[n];
1458
1459 int i = 0;
1460 for(wxNode *node = list->First(); node; node = node->Next()) {
1461 wxPoint *point = (wxPoint *)node->Data();
1462 points[i].x = point->x;
1463 points[i++].y = point->y;
1464 }
1465 DrawPolygon(n, points, xoffset, yoffset,fillStyle);
1466 delete[] points;
1467 }
1468
1469 void wxDC::DrawLines(wxList *list, long xoffset, long yoffset)
1470 {
1471 int n = list->Number();
1472 wxPoint *points = new wxPoint[n];
1473
1474 int i = 0;
1475 for(wxNode *node = list->First(); node; node = node->Next()) {
1476 wxPoint *point = (wxPoint *)node->Data();
1477 points[i].x = point->x;
1478 points[i++].y = point->y;
1479 }
1480 DrawLines(n, points, xoffset, yoffset);
1481 delete []points;
1482 }
1483
1484 void wxDC::SetTextForeground(const wxColour& colour)
1485 {
1486 m_textForegroundColour = colour;
1487 }
1488
1489 void wxDC::SetTextBackground(const wxColour& colour)
1490 {
1491 m_textBackgroundColour = colour;
1492 }
1493
1494 #if USE_SPLINES
1495 // Make a 3-point spline
1496 void wxDC::DrawSpline(long x1, long y1, long x2, long y2, long x3, long y3)
1497 {
1498 wxList *point_list = new wxList;
1499
1500 wxPoint *point1 = new wxPoint;
1501 point1->x = x1; point1->y = y1;
1502 point_list->Append((wxObject*)point1);
1503
1504 wxPoint *point2 = new wxPoint;
1505 point2->x = x2; point2->y = y2;
1506 point_list->Append((wxObject*)point2);
1507
1508 wxPoint *point3 = new wxPoint;
1509 point3->x = x3; point3->y = y3;
1510 point_list->Append((wxObject*)point3);
1511
1512 DrawSpline(point_list);
1513
1514 for(wxNode *node = point_list->First(); node; node = node->Next()) {
1515 wxPoint *p = (wxPoint *)node->Data();
1516 delete p;
1517 }
1518 delete point_list;
1519 /*
1520 wxSpline spline(point_list);
1521
1522 wx_draw_open_spline(this, &spline);
1523 spline.DeletePoints();
1524 */
1525 }
1526 #endif
1527
1528 // For use by wxWindows only, unless custom units are required.
1529 void wxDC::SetLogicalScale(double x, double y)
1530 {
1531 m_logicalScaleX = x;
1532 m_logicalScaleY = y;
1533 }
1534
1535 void wxDC::CalcBoundingBox(long x, long y)
1536 {
1537 if (x < m_minX) m_minX = x;
1538 if (y < m_minY) m_minY = y;
1539 if (x > m_maxX) m_maxX = x;
1540 if (y > m_maxY) m_maxY = y;
1541 }
1542
1543 void wxDC::GetClippingBox(long *x,long *y,long *w,long *h) const
1544 {
1545 if (m_clipping)
1546 {
1547 *x = m_clipX1 ;
1548 *y = m_clipY1 ;
1549 *w = (m_clipX2 - m_clipX1) ;
1550 *h = (m_clipY2 - m_clipY1) ;
1551 }
1552 else
1553 *x = *y = *w = *h = 0 ;
1554 }
1555
1556 #if WXWIN_COMPATIBILITY
1557 void wxDC::GetTextExtent(const wxString& string, float *x, float *y,
1558 float *descent, float *externalLeading,
1559 wxFont *theFont, bool use16bit) const
1560 {
1561 long x1, y1, descent1, externalLeading1;
1562 GetTextExtent(string, & x1, & y1, & descent1, & externalLeading1, theFont, use16bit);
1563 *x = x1; *y = y1;
1564 if (descent)
1565 *descent = descent1;
1566 if (externalLeading)
1567 *externalLeading = externalLeading1;
1568 }
1569 #endif
1570