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