]> git.saurik.com Git - wxWidgets.git/blob - src/msw/dc.cpp
wxTempFile bug corrected: the temp file is now created in the same dir
[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 int xx1 = (int)x;
417 int yy1 = (int)y;
418 if (m_canvas)
419 m_canvas->CalcScrolledPosition((int)x, (int)y, &xx1, &yy1);
420 */
421
422 // get the color of the pixel
423 COLORREF pixelcolor = ::GetPixel((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y));
424 // get the color of the pen
425 COLORREF pencolor = 0x00ffffff;
426 if (m_pen.Ok())
427 {
428 pencolor = m_pen.GetColour().GetPixel() ;
429 }
430
431 // return the color of the pixel
432 if(col)
433 col->Set(GetRValue(pixelcolor),GetGValue(pixelcolor),GetBValue(pixelcolor));
434
435 // check, if color of the pixels is the same as the color
436 // of the current pen
437 return(pixelcolor==pencolor);
438 }
439
440 void wxDC::CrossHair(long x, long y)
441 {
442 if (m_pen.Ok() && m_autoSetting)
443 SetPen(m_pen);
444
445 // We suppose that our screen is 2000x2000 max.
446 long x1 = x-2000;
447 long y1 = y-2000;
448 long x2 = x+2000;
449 long y2 = y+2000;
450 /*
451 long xx1 = x1 ;
452 long yy1 = y1 ;
453 long xx2 = x2 ;
454 long yy2 = y2 ;
455 long xx = x ;
456 long yy = y ;
457
458 if (m_canvas)
459 {
460 m_canvas->CalcScrolledPosition(x1, y1, &xx1, &yy1);
461 m_canvas->CalcScrolledPosition(x2, y2, &xx2, &yy2);
462 m_canvas->CalcScrolledPosition(x, y, &xx, &yy);
463 }
464 */
465
466 BeginDrawing();
467
468 (void)MoveToEx((HDC) m_hDC, XLOG2DEV(x1), YLOG2DEV(y), NULL);
469 (void)LineTo((HDC) m_hDC, XLOG2DEV(x2), YLOG2DEV(y));
470
471 (void)MoveToEx((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y1), NULL);
472 (void)LineTo((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y2));
473
474 EndDrawing();
475
476 CalcBoundingBox(x1, y1);
477 CalcBoundingBox(x2, y2);
478 }
479
480 void wxDC::DrawLine(long x1, long y1, long x2, long y2)
481 {
482 // BUGBUG - is this necessary? YES YES YES YEs Yes yes ye....
483 if (m_pen.Ok() && m_autoSetting)
484 SetPen(m_pen);
485 /*
486 int xx1 = (int)x1;
487 int yy1 = (int)y1;
488 int xx2 = (int)x2;
489 int yy2 = (int)y2;
490 if (m_canvas)
491 {
492 m_canvas->CalcScrolledPosition((int)x1, (int)y1, &xx1, &yy1);
493 m_canvas->CalcScrolledPosition((int)x2, (int)y2, &xx2, &yy2);
494 }
495 */
496
497 BeginDrawing();
498
499 (void)MoveToEx((HDC) m_hDC, XLOG2DEV(x1), YLOG2DEV(y1), NULL);
500 (void)LineTo((HDC) m_hDC, XLOG2DEV(x2), YLOG2DEV(y2));
501
502 /* MATTHEW: [6] New normalization */
503 #if WX_STANDARD_GRAPHICS
504 (void)LineTo((HDC) m_hDC, XLOG2DEV(x2) + 1, YLOG2DEV(y2));
505 #endif
506
507 EndDrawing();
508
509 CalcBoundingBox(x1, y1);
510 CalcBoundingBox(x2, y2);
511 }
512
513 void wxDC::DrawArc(long x1,long y1,long x2,long y2,double xc,double yc)
514 {
515 /*
516 int xx1 = (int)x1;
517 int yy1 = (int)y1;
518 int xx2 = (int)x2;
519 int yy2 = (int)y2;
520 int xxc = (int)xc ;
521 int yyc = (int)yc;
522 */
523
524 double dx = xc-x1 ;
525 double dy = yc-y1 ;
526 double radius = (double)sqrt(dx*dx+dy*dy) ;;
527 if (x1==x2 && x2==y2)
528 {
529 DrawEllipse(xc,yc,(double)(radius*2.0),(double)(radius*2)) ;
530 return ;
531 }
532
533 // BUGBUG - is this necessary?
534 if (m_pen.Ok() && m_autoSetting)
535 SetPen(m_pen) ;
536
537 /*
538 if (m_canvas)
539 {
540 m_canvas->CalcScrolledPosition((int)x1, (int)y1, &xx1, &yy1);
541 m_canvas->CalcScrolledPosition((int)x2, (int)y2, &xx2, &yy2);
542 m_canvas->CalcScrolledPosition((int)xc, (int)yc, &xxc, &yyc);
543 }
544 */
545
546 BeginDrawing();
547
548 long xx1 = XLOG2DEV(x1) ;
549 long yy1 = YLOG2DEV(y1) ;
550 long xx2 = XLOG2DEV(x2) ;
551 long yy2 = YLOG2DEV(y2) ;
552 long xxc = XLOG2DEV(xc) ;
553 long yyc = YLOG2DEV(yc) ;
554 long ray = (long) sqrt(double((xxc-xx1)*(xxc-xx1)+(yyc-yy1)*(yyc-yy1))) ;
555
556 (void)MoveToEx((HDC) m_hDC, (int) xx1, (int) yy1, NULL);
557 long xxx1 = (long) (xxc-ray);
558 long yyy1 = (long) (yyc-ray);
559 long xxx2 = (long) (xxc+ray);
560 long yyy2 = (long) (yyc+ray);
561 if (m_brush.Ok() && m_brush.GetStyle() !=wxTRANSPARENT)
562 {
563 // BUGBUG - is this necessary?
564 if (m_brush.GetStyle()!=wxTRANSPARENT&&m_autoSetting)
565 SetBrush(m_brush) ;
566 Pie((HDC) m_hDC,xxx1,yyy1,xxx2,yyy2,
567 xx1,yy1,xx2,yy2) ;
568 }
569 else
570 Arc((HDC) m_hDC,xxx1,yyy1,xxx2,yyy2,
571 xx1,yy1,xx2,yy2) ;
572
573 EndDrawing();
574
575 CalcBoundingBox((xc-radius), (yc-radius));
576 CalcBoundingBox((xc+radius), (yc+radius));
577 }
578
579 void wxDC::DrawPoint(long x, long y)
580 {
581 // BUGBUG - is this necessary?
582 if (m_pen.Ok() && m_autoSetting)
583 SetPen(m_pen) ;
584
585 /*
586 int xx1 = (int)x;
587 int yy1 = (int)y;
588 if (m_canvas)
589 m_canvas->CalcScrolledPosition((int)x, (int)y, &xx1, &yy1);
590 */
591
592 BeginDrawing();
593
594 COLORREF color = 0x00ffffff;
595 if (m_pen.Ok())
596 {
597 // m_pen.RealizeResource();
598 color = m_pen.GetColour().GetPixel() ;
599 }
600
601 /*
602 color = RGB(m_pen->GetColour().Red(),
603 m_pen->GetColour().Green(),
604 m_pen->GetColour().Blue());
605 */
606
607 SetPixel((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), color);
608
609 EndDrawing();
610
611 CalcBoundingBox(x, y);
612 }
613
614 void wxDC::DrawPolygon(int n, wxPoint points[], long xoffset, long yoffset,int fillStyle)
615 {
616 // BUGBUG - is this necessary?
617 if (m_pen.Ok() && m_autoSetting)
618 SetPen(m_pen) ;
619 /*
620 int xoffset1 = 0;
621 int yoffset1 = 0;
622
623 if (m_canvas)
624 m_canvas->CalcScrolledPosition(0, 0, &xoffset1, &yoffset1);
625
626 xoffset1 += (int)xoffset; yoffset1 += (int)yoffset;
627 */
628
629 BeginDrawing();
630
631 POINT *cpoints = new POINT[n];
632 int i;
633 for (i = 0; i < n; i++)
634 {
635 cpoints[i].x = (int)(XLOG2DEV(points[i].x));
636 cpoints[i].y = (int)(YLOG2DEV(points[i].y));
637
638 CalcBoundingBox(points[i].x, points[i].y);
639 }
640
641 int prev = SetPolyFillMode((HDC) m_hDC,fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING) ;
642 (void)Polygon((HDC) m_hDC, cpoints, n);
643 SetPolyFillMode((HDC) m_hDC,prev) ;
644
645 EndDrawing();
646
647 delete[] cpoints;
648 }
649
650 void wxDC::DrawLines(int n, wxPoint points[], long xoffset, long yoffset)
651 {
652 // BUGBUG - is this necessary?
653 if (m_pen.Ok() && m_autoSetting)
654 SetPen(m_pen) ;
655
656 /*
657 int xoffset1 = 0;
658 int yoffset1 = 0;
659
660 if (m_canvas)
661 {
662 m_canvas->CalcScrolledPosition(0, 0, &xoffset1, &yoffset1);
663 }
664 xoffset1 += (int)xoffset; yoffset1 += (int)yoffset;
665 */
666
667 BeginDrawing();
668
669 POINT *cpoints = new POINT[n];
670 int i;
671 for (i = 0; i < n; i++)
672 {
673 cpoints[i].x = (int)(XLOG2DEV(points[i].x));
674 cpoints[i].y = (int)(YLOG2DEV(points[i].y));
675
676 CalcBoundingBox(points[i].x, points[i].y);
677 }
678
679 (void)Polyline((HDC) m_hDC, cpoints, n);
680
681 EndDrawing();
682
683 delete[] cpoints;
684 }
685
686 void wxDC::DrawRectangle(long x, long y, long width, long height)
687 {
688 // BUGBUG - is this necessary?
689 if (m_pen.Ok() && m_autoSetting)
690 SetPen(m_pen) ;
691
692 /*
693 int x1 = (int)x;
694 int y1 = (int)y;
695 int x2 = (int)(x+width);
696 int y2 = (int)(y+height);
697
698 if (m_canvas)
699 {
700 m_canvas->CalcScrolledPosition((int)x, (int)y, &x1, &y1);
701 m_canvas->CalcScrolledPosition((int)(x+width), (int)(y+height), &x2, &y2);
702 }
703 */
704 long x2 = x + width;
705 long y2 = y + height;
706
707 BeginDrawing();
708
709 /* MATTHEW: [6] new normalization */
710 #if WX_STANDARD_GRAPHICS
711 bool do_brush, do_pen;
712
713 do_brush = m_brush.Ok() && m_brush.GetStyle() != wxTRANSPARENT;
714 do_pen = m_pen.Ok() && m_pen.GetStyle() != wxTRANSPARENT;
715
716 if (do_brush) {
717 HPEN orig_pen = NULL;
718
719 if (do_pen || !m_pen.Ok())
720 orig_pen = ::SelectObject((HDC) m_hDC, ::GetStockObject(NULL_PEN));
721
722 (void)Rectangle((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y),
723 XLOG2DEV(x2) + 1, YLOG2DEV(y2) + 1);
724
725 if (do_pen || !m_pen.Ok())
726 ::SelectObject((HDC) m_hDC , orig_pen);
727 }
728 if (do_pen) {
729 HBRUSH orig_brush = NULL;
730
731 if (do_brush || !m_brush.Ok())
732 orig_brush = ::SelectObject((HDC) m_hDC, ::GetStockObject(NULL_BRUSH));
733
734 (void)Rectangle((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y),
735 XLOG2DEV(x2), YLOG2DEV(y2));
736
737 if (do_brush || !m_brush.Ok())
738 ::SelectObject((HDC) m_hDC, orig_brush);
739 }
740 #else
741 (void)Rectangle((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2));
742 #endif
743
744 CalcBoundingBox(x, y);
745 CalcBoundingBox(x2, y2);
746
747 EndDrawing();
748 }
749
750 void wxDC::DrawRoundedRectangle(long x, long y, long width, long height, double radius)
751 {
752 // BUGBUG - is this necessary?
753 if (m_pen.Ok() && m_autoSetting)
754 SetPen(m_pen) ;
755
756 // Now, a negative radius value is interpreted to mean
757 // 'the proportion of the smallest X or Y dimension'
758
759 if (radius < 0.0)
760 {
761 double smallest = 0.0;
762 if (width < height)
763 smallest = width;
764 else
765 smallest = height;
766 radius = (- radius * smallest);
767 }
768
769 /*
770 int x1 = (int)x;
771 int y1 = (int)y;
772
773 if (m_canvas)
774 {
775 m_canvas->CalcScrolledPosition((int)x, (int)y, &x1, &y1);
776 m_canvas->CalcScrolledPosition((int)(x+width), (int)(y+height), &x2, &y2);
777 }
778 */
779
780 long x2 = (x+width);
781 long y2 = (y+height);
782
783 BeginDrawing();
784
785 (void)RoundRect((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2),
786 YLOG2DEV(y2), 2*XLOG2DEV(radius), 2*YLOG2DEV(radius));
787
788 CalcBoundingBox(x, y);
789 CalcBoundingBox(x2, y2);
790
791 EndDrawing();
792 }
793
794 void wxDC::DrawEllipse(long x, long y, long width, long height)
795 {
796 // BUGBUG - is this necessary?
797 if (m_pen.Ok() && m_autoSetting)
798 SetPen(m_pen) ;
799
800 /*
801 int x1 = (int)x;
802 int y1 = (int)y;
803
804 if (m_canvas)
805 {
806 m_canvas->CalcScrolledPosition((int)x, (int)y, &x1, &y1);
807 m_canvas->CalcScrolledPosition((int)(x+width), (int)(y+height), &x2, &y2);
808 }
809 */
810
811 long x2 = (x+width);
812 long y2 = (y+height);
813
814 BeginDrawing();
815
816 (void)Ellipse((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2));
817
818 EndDrawing();
819
820 CalcBoundingBox(x, y);
821 CalcBoundingBox(x2, y2);
822 }
823
824 // Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
825 void wxDC::DrawEllipticArc(long x,long y,long w,long h,double sa,double ea)
826 {
827 // BUGBUG - is this necessary?
828 if (m_pen.Ok() && m_autoSetting)
829 SetPen(m_pen) ;
830
831 long x2 = (x+w);
832 long y2 = (y+h);
833
834 BeginDrawing();
835
836 const double deg2rad = 3.14159265359 / 180.0;
837 int rx1 = XLOG2DEV(x+w/2);
838 int ry1 = YLOG2DEV(y+h/2);
839 int rx2 = rx1;
840 int ry2 = ry1;
841 rx1 += (int)(100.0 * abs(w) * cos(sa * deg2rad));
842 ry1 -= (int)(100.0 * abs(h) * m_signY * sin(sa * deg2rad));
843 rx2 += (int)(100.0 * abs(w) * cos(ea * deg2rad));
844 ry2 -= (int)(100.0 * abs(h) * m_signY * sin(ea * deg2rad));
845
846 // draw pie with NULL_PEN first and then outline otherwise a line is
847 // drawn from the start and end points to the centre
848 HPEN orig_pen = ::SelectObject((HDC) m_hDC, ::GetStockObject(NULL_PEN));
849 if (m_signY > 0)
850 {
851 (void)Pie((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2)+1, YLOG2DEV(y2)+1,
852 rx1, ry1, rx2, ry2);
853 }
854 else
855 {
856 (void)Pie((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y)-1, XLOG2DEV(x2)+1, YLOG2DEV(y2),
857 rx1, ry1-1, rx2, ry2-1);
858 }
859 ::SelectObject((HDC) m_hDC, orig_pen);
860 (void)Arc((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2),
861 rx1, ry1, rx2, ry2);
862
863 EndDrawing();
864
865 CalcBoundingBox(x, y);
866 CalcBoundingBox(x2, y2);
867 }
868
869 void wxDC::DrawIcon(const wxIcon& icon, long x, long y)
870 {
871 /*
872 int x1 = (int)x;
873 int y1 = (int)y;
874
875 if (m_canvas)
876 m_canvas->CalcScrolledPosition(int)x, (int)y, &x1, &y1);
877 */
878
879 BeginDrawing();
880
881 ::DrawIcon((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), (HICON) icon.GetHICON());
882 CalcBoundingBox(x, y);
883 CalcBoundingBox(x+icon.GetWidth(), y+icon.GetHeight());
884
885 EndDrawing();
886 }
887
888 void wxDC::SetFont(const wxFont& the_font)
889 {
890 // Release the current font from servitude (decrements the usage count)
891 // if (m_font.Ok())
892 // m_font.ReleaseResource();
893
894 BeginDrawing();
895
896 m_font = the_font;
897
898 if (!the_font.Ok())
899 {
900 if (m_oldFont)
901 ::SelectObject((HDC) m_hDC, (HFONT) m_oldFont);
902 m_oldFont = 0 ;
903 }
904
905 if (m_font.Ok() && m_font.GetResourceHandle())
906 {
907 #if DEBUG > 1
908 wxDebugMsg("wxDC::SetFont: Selecting HFONT %X\n", m_font.GetResourceHandle());
909 #endif
910 HFONT f = (HFONT) ::SelectObject((HDC) m_hDC, (HFONT) m_font.GetResourceHandle());
911 if (!m_oldFont)
912 m_oldFont = (WXHFONT) f;
913 }
914 EndDrawing();
915 }
916
917 void wxDC::SetPen(const wxPen& pen)
918 {
919 BeginDrawing();
920
921 // if (m_pen.Ok())
922 // m_pen.ReleaseResource();
923
924 m_pen = pen;
925
926 if (!m_pen.Ok())
927 {
928 if (m_oldPen)
929 ::SelectObject((HDC) m_hDC, (HPEN) m_oldPen);
930 m_oldPen = 0 ;
931 }
932
933 if (m_pen.Ok())
934 {
935 // m_pen.UseResource();
936 // m_pen.RealizeResource();
937 if (m_pen.GetResourceHandle())
938 {
939 HPEN p = (HPEN) ::SelectObject((HDC) m_hDC, (HPEN)m_pen.GetResourceHandle()) ;
940 if (!m_oldPen)
941 m_oldPen = (WXHPEN) p;
942 }
943 }
944
945 EndDrawing();
946 }
947
948 void wxDC::SetBrush(const wxBrush& brush)
949 {
950 BeginDrawing();
951
952 // if (m_brush.Ok())
953 // m_brush.ReleaseResource();
954
955 m_brush = brush;
956
957 if (!m_brush.Ok())
958 {
959 if (m_oldBrush)
960 ::SelectObject((HDC) m_hDC, (HBRUSH) m_oldBrush);
961 m_oldBrush = 0 ;
962 }
963
964 if (m_brush.Ok())
965 {
966 // m_brush.UseResource();
967 // m_brush.RealizeResource();
968
969 if (m_brush.GetResourceHandle())
970 {
971 HBRUSH b = 0;
972 b = ::SelectObject((HDC) m_hDC, (HBRUSH)m_brush.GetResourceHandle()) ;
973 if (!m_oldBrush)
974 m_oldBrush = (WXHBRUSH) b;
975 }
976 }
977 EndDrawing();
978 }
979
980 void wxDC::DrawText(const wxString& text, long x, long y, bool use16bit)
981 {
982 /*
983 int xx1 = (int)x;
984 int yy1 = (int)y;
985
986 if (m_canvas)
987 m_canvas->CalcScrolledPosition((int)x, (int)y, &xx1, &yy1);
988 */
989
990 BeginDrawing();
991
992 if (m_font.Ok() && m_font.GetResourceHandle())
993 {
994 #if DEBUG > 1
995 wxDebugMsg("wxDC::DrawText: Selecting HFONT %X\n", m_font.GetResourceHandle());
996 #endif
997 HFONT f = ::SelectObject((HDC) m_hDC, (HFONT) m_font.GetResourceHandle());
998 if (!m_oldFont)
999 m_oldFont = (WXHFONT) f;
1000 }
1001
1002 if (m_textForegroundColour.Ok())
1003 SetTextColor((HDC) m_hDC, m_textForegroundColour.GetPixel() ) ;
1004
1005 DWORD old_background;
1006 if (m_textBackgroundColour.Ok())
1007 {
1008 old_background = SetBkColor((HDC) m_hDC, m_textBackgroundColour.GetPixel() ) ;
1009 }
1010
1011 if (m_backgroundMode == wxTRANSPARENT)
1012 SetBkMode((HDC) m_hDC, TRANSPARENT);
1013 else
1014 SetBkMode((HDC) m_hDC, OPAQUE);
1015
1016 (void)TextOut((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), (char *) (const char *)text, strlen((const char *)text));
1017
1018 if (m_textBackgroundColour.Ok())
1019 (void)SetBkColor((HDC) m_hDC, old_background);
1020
1021 CalcBoundingBox(x, y);
1022
1023 long w, h;
1024 GetTextExtent(text, &w, &h);
1025 CalcBoundingBox((x + w), (y + h));
1026
1027 EndDrawing();
1028 }
1029
1030 void wxDC::SetBackground(const wxBrush& brush)
1031 {
1032 // if (m_backgroundBrush.Ok())
1033 // m_backgroundBrush.ReleaseResource();
1034
1035 m_backgroundBrush = brush;
1036
1037 if (!m_backgroundBrush.Ok())
1038 return;
1039
1040 // m_backgroundBrush.UseResource();
1041 // m_backgroundBrush.RealizeResource() ;
1042
1043 if (m_canvas)
1044 {
1045 bool customColours = TRUE;
1046 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
1047 // change background colours from the control-panel specified colours.
1048 if (m_canvas->IsKindOf(CLASSINFO(wxWindow)) && ((m_canvas->GetWindowStyleFlag() & wxUSER_COLOURS) != wxUSER_COLOURS))
1049 customColours = FALSE;
1050
1051 if (customColours)
1052 {
1053 // HBRUSH br = (m_backgroundBrush.GetStyle()==wxTRANSPARENT) ?
1054 // GetStockObject(NULL_BRUSH) : (HBRUSH) m_backgroundBrush.GetResourceHandle();
1055 if (m_backgroundBrush.GetStyle()==wxTRANSPARENT)
1056 {
1057 m_canvas->m_backgroundTransparent = TRUE;
1058 }
1059 else
1060 {
1061 m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
1062 m_canvas->m_backgroundTransparent = FALSE;
1063 }
1064 }
1065 }
1066 BeginDrawing();
1067
1068 COLORREF new_color = m_backgroundBrush.GetColour().GetPixel() ;
1069 {
1070 (void)SetBkColor((HDC) m_hDC, new_color);
1071 }
1072
1073 EndDrawing();
1074 }
1075
1076 void wxDC::SetBackgroundMode(int mode)
1077 {
1078 m_backgroundMode = mode;
1079
1080 BeginDrawing();
1081
1082 if (m_backgroundMode == wxTRANSPARENT)
1083 ::SetBkMode((HDC) m_hDC, TRANSPARENT);
1084 else
1085 ::SetBkMode((HDC) m_hDC, OPAQUE);
1086
1087 EndDrawing();
1088 }
1089
1090 void wxDC::SetLogicalFunction(int function)
1091 {
1092 m_logicalFunction = function;
1093
1094 BeginDrawing();
1095
1096 SetRop((WXHDC) m_hDC);
1097
1098 EndDrawing();
1099 }
1100
1101 void wxDC::SetRop(WXHDC dc)
1102 {
1103 if (!dc || m_logicalFunction < 0)
1104 return;
1105
1106 int c_rop;
1107 // These may be wrong
1108 switch (m_logicalFunction)
1109 {
1110 // case wxXOR: c_rop = R2_XORPEN; break;
1111 case wxXOR: c_rop = R2_NOTXORPEN; break;
1112 case wxINVERT: c_rop = R2_NOT; break;
1113 case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
1114 case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
1115 case wxCLEAR: c_rop = R2_WHITE; break;
1116 case wxSET: c_rop = R2_BLACK; break;
1117 case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
1118 case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
1119 case wxAND: c_rop = R2_MASKPEN; break;
1120 case wxOR: c_rop = R2_MERGEPEN; break;
1121 case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
1122 case wxEQUIV:
1123 case wxNAND:
1124 case wxCOPY:
1125 default:
1126 c_rop = R2_COPYPEN; break;
1127 }
1128 SetROP2((HDC) dc, c_rop);
1129 }
1130
1131 bool wxDC::StartDoc(const wxString& message)
1132 {
1133 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
1134 return TRUE;
1135
1136 bool flag = FALSE;
1137
1138 DOCINFO docinfo;
1139 docinfo.cbSize = sizeof(DOCINFO);
1140 docinfo.lpszDocName = (const char *)message;
1141 docinfo.lpszOutput = (const char *)m_filename;
1142 #if defined(__WIN95__)
1143 docinfo.lpszDatatype = NULL;
1144 docinfo.fwType = 0;
1145 #endif
1146
1147 if (m_hDC) flag = (SP_ERROR !=
1148 #ifndef __WIN32__
1149 ::StartDoc((HDC) m_hDC, &docinfo));
1150 #else
1151 #ifdef UNICODE
1152 ::StartDocW((HDC) m_hDC, &docinfo));
1153 #else
1154 ::StartDocA((HDC) m_hDC, &docinfo));
1155 #endif
1156 #endif
1157
1158 else flag = FALSE;
1159
1160 return flag;
1161 }
1162
1163 void wxDC::EndDoc(void)
1164 {
1165 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
1166 return;
1167 if (m_hDC) ::EndDoc((HDC) m_hDC);
1168 }
1169
1170 void wxDC::StartPage(void)
1171 {
1172 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
1173 return;
1174 if (m_hDC)
1175 ::StartPage((HDC) m_hDC);
1176 }
1177
1178 void wxDC::EndPage(void)
1179 {
1180 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
1181 return;
1182 if (m_hDC)
1183 ::EndPage((HDC) m_hDC);
1184 }
1185
1186 long wxDC::GetCharHeight(void) const
1187 {
1188 TEXTMETRIC lpTextMetric;
1189
1190 GetTextMetrics((HDC) m_hDC, &lpTextMetric);
1191
1192 return YDEV2LOGREL(lpTextMetric.tmHeight);
1193 }
1194
1195 long wxDC::GetCharWidth(void) const
1196 {
1197 TEXTMETRIC lpTextMetric;
1198
1199 GetTextMetrics((HDC) m_hDC, &lpTextMetric);
1200
1201 return XDEV2LOGREL(lpTextMetric.tmAveCharWidth);
1202 }
1203
1204 void wxDC::GetTextExtent(const wxString& string, long *x, long *y,
1205 long *descent, long *externalLeading, wxFont *theFont, bool use16bit) const
1206 {
1207 wxFont *fontToUse = (wxFont*) theFont;
1208 if (!fontToUse)
1209 fontToUse = (wxFont*) &m_font;
1210
1211 SIZE sizeRect;
1212 TEXTMETRIC tm;
1213
1214 GetTextExtentPoint((HDC) m_hDC, (char *)(const char *) string, strlen((char *)(const char *) string), &sizeRect);
1215 GetTextMetrics((HDC) m_hDC, &tm);
1216
1217 *x = XDEV2LOGREL(sizeRect.cx);
1218 *y = YDEV2LOGREL(sizeRect.cy);
1219 if (descent) *descent = tm.tmDescent;
1220 if (externalLeading) *externalLeading = tm.tmExternalLeading;
1221 }
1222
1223 void wxDC::SetMapMode(int mode)
1224 {
1225 m_mappingMode = mode;
1226
1227 int pixel_width = 0;
1228 int pixel_height = 0;
1229 int mm_width = 0;
1230 int mm_height = 0;
1231
1232 BeginDrawing();
1233
1234 pixel_width = GetDeviceCaps((HDC) m_hDC, HORZRES);
1235 pixel_height = GetDeviceCaps((HDC) m_hDC, VERTRES);
1236 mm_width = GetDeviceCaps((HDC) m_hDC, HORZSIZE);
1237 mm_height = GetDeviceCaps((HDC) m_hDC, VERTSIZE);
1238
1239 if ((pixel_width == 0) || (pixel_height == 0) || (mm_width == 0) || (mm_height == 0))
1240 {
1241 // if (!m_hDC && m_canvas)
1242 // m_canvas->ReleaseHDC() ;
1243 return;
1244 }
1245
1246 double mm2pixelsX = pixel_width/mm_width;
1247 double mm2pixelsY = pixel_height/mm_height;
1248
1249 switch (mode)
1250 {
1251 case MM_TWIPS:
1252 {
1253 m_logicalScaleX = (twips2mm * mm2pixelsX);
1254 m_logicalScaleY = (twips2mm * mm2pixelsY);
1255 break;
1256 }
1257 case MM_POINTS:
1258 {
1259 m_logicalScaleX = (pt2mm * mm2pixelsX);
1260 m_logicalScaleY = (pt2mm * mm2pixelsY);
1261 break;
1262 }
1263 case MM_METRIC:
1264 {
1265 m_logicalScaleX = mm2pixelsX;
1266 m_logicalScaleY = mm2pixelsY;
1267 break;
1268 }
1269 case MM_LOMETRIC:
1270 {
1271 m_logicalScaleX = (mm2pixelsX/10.0);
1272 m_logicalScaleY = (mm2pixelsY/10.0);
1273 break;
1274 }
1275 default:
1276 case MM_TEXT:
1277 {
1278 m_logicalScaleX = 1.0;
1279 m_logicalScaleY = 1.0;
1280 break;
1281 }
1282 }
1283
1284 if (::GetMapMode((HDC) m_hDC) != MM_ANISOTROPIC)
1285 ::SetMapMode((HDC) m_hDC, MM_ANISOTROPIC);
1286
1287 SetViewportExtEx((HDC) m_hDC, VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
1288 m_windowExtX = (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT);
1289 m_windowExtY = (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT);
1290 ::SetWindowExtEx((HDC) m_hDC, m_windowExtX, m_windowExtY, NULL);
1291 ::SetViewportOrgEx((HDC) m_hDC, (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
1292 ::SetWindowOrgEx((HDC) m_hDC, (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
1293
1294 EndDrawing();
1295 }
1296
1297 void wxDC::SetUserScale(double x, double y)
1298 {
1299 m_userScaleX = x;
1300 m_userScaleY = y;
1301
1302 SetMapMode(m_mappingMode);
1303 }
1304
1305 void wxDC::SetAxisOrientation(bool xLeftRight, bool yBottomUp)
1306 {
1307 m_signX = xLeftRight ? 1 : -1;
1308 m_signY = yBottomUp ? -1 : 1;
1309
1310 SetMapMode(m_mappingMode);
1311 }
1312
1313 void wxDC::SetSystemScale(double x, double y)
1314 {
1315 m_systemScaleX = x;
1316 m_systemScaleY = y;
1317
1318 SetMapMode(m_mappingMode);
1319 }
1320
1321 void wxDC::SetLogicalOrigin(long x, long y)
1322 {
1323 m_logicalOriginX = x;
1324 m_logicalOriginY = y;
1325
1326 BeginDrawing();
1327
1328 ::SetWindowOrgEx((HDC) m_hDC, (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
1329
1330 EndDrawing();
1331 }
1332
1333 void wxDC::SetDeviceOrigin(long x, long y)
1334 {
1335 m_deviceOriginX = x;
1336 m_deviceOriginY = y;
1337
1338 BeginDrawing();
1339
1340 ::SetViewportOrgEx((HDC) m_hDC, (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
1341
1342 EndDrawing();
1343 }
1344
1345 long wxDC::DeviceToLogicalX(long x) const
1346 {
1347 return (long) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX) - m_logicalOriginX) ;
1348 }
1349
1350 long wxDC::DeviceToLogicalXRel(long x) const
1351 {
1352 return (long) ((x)/(m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX)) ;
1353 }
1354
1355 long wxDC::DeviceToLogicalY(long y) const
1356 {
1357 return (long) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY) - m_logicalOriginY) ;
1358 }
1359
1360 long wxDC::DeviceToLogicalYRel(long y) const
1361 {
1362 return (long) ((y)/(m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY)) ;
1363 }
1364
1365 long wxDC::LogicalToDeviceX(long x) const
1366 {
1367 return (long) (floor((x) - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX + m_deviceOriginX) ;
1368 }
1369
1370 long wxDC::LogicalToDeviceXRel(long x) const
1371 {
1372 return (long) (floor(x)*m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX) ;
1373 }
1374
1375 long wxDC::LogicalToDeviceY(long y) const
1376 {
1377 return (long) (floor((y) - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY + m_deviceOriginY);
1378 }
1379
1380 long wxDC::LogicalToDeviceYRel(long y) const
1381 {
1382 return (long) (floor(y)*m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY) ;
1383 }
1384
1385 // This group of functions may not do any conversion
1386 // if m_scaleGDI is TRUE, since the HDC does the
1387 // conversion automatically.
1388
1389 long wxDC::ImplDeviceToLogicalX(long x) const
1390 {
1391 // return (m_scaleGDI ? x : DeviceToLogicalX(x));
1392 return x;
1393 }
1394
1395 long wxDC::ImplDeviceToLogicalY(long y) const
1396 {
1397 // return (m_scaleGDI ? y : DeviceToLogicalY(y));
1398 return y;
1399 }
1400
1401 long wxDC::ImplDeviceToLogicalXRel(long x) const
1402 {
1403 // return (m_scaleGDI ? x : DeviceToLogicalXRel(x));
1404 return x;
1405 }
1406
1407 long wxDC::ImplDeviceToLogicalYRel(long y) const
1408 {
1409 // return (m_scaleGDI ? y : DeviceToLogicalYRel(y));
1410 return y;
1411 }
1412
1413 long wxDC::ImplLogicalToDeviceX(long x) const
1414 {
1415 // return (m_scaleGDI ? (floor(double(x))) : LogicalToDeviceX(x));
1416 return x;
1417 }
1418
1419 long wxDC::ImplLogicalToDeviceY(long y) const
1420 {
1421 // return (m_scaleGDI ? (floor(double(y))) : LogicalToDeviceY(y));
1422 return y;
1423 }
1424
1425 long wxDC::ImplLogicalToDeviceXRel(long x) const
1426 {
1427 // return (m_scaleGDI ? (floor(double(x))) : LogicalToDeviceXRel(x));
1428 return x;
1429 }
1430
1431 long wxDC::ImplLogicalToDeviceYRel(long y) const
1432 {
1433 // return (m_scaleGDI ? (floor(double(y))) : LogicalToDeviceYRel(y));
1434 return y;
1435 }
1436
1437 bool wxDC::Blit(long xdest, long ydest, long width, long height,
1438 wxDC *source, long xsrc, long ysrc, int rop, bool useMask)
1439 {
1440 BeginDrawing();
1441 source->BeginDrawing();
1442
1443 long xdest1 = xdest;
1444 long ydest1 = ydest;
1445 long xsrc1 = xsrc;
1446 long ysrc1 = ysrc;
1447
1448 // Chris Breeze 18/5/98: use text foreground/background colours
1449 // when blitting from 1-bit bitmaps
1450 COLORREF old_textground = ::GetTextColor((HDC)m_hDC);
1451 COLORREF old_background = ::GetBkColor((HDC)m_hDC);
1452 if (m_textForegroundColour.Ok())
1453 {
1454 ::SetTextColor((HDC) m_hDC, m_textForegroundColour.GetPixel() ) ;
1455 }
1456 if (m_textBackgroundColour.Ok())
1457 {
1458 ::SetBkColor((HDC) m_hDC, m_textBackgroundColour.GetPixel() ) ;
1459 }
1460
1461 DWORD dwRop = rop == wxCOPY ? SRCCOPY :
1462 rop == wxCLEAR ? WHITENESS :
1463 rop == wxSET ? BLACKNESS :
1464 rop == wxINVERT ? DSTINVERT :
1465 rop == wxAND ? MERGECOPY :
1466 rop == wxOR ? MERGEPAINT :
1467 rop == wxSRC_INVERT ? NOTSRCCOPY :
1468 rop == wxXOR ? SRCINVERT :
1469 rop == wxOR_REVERSE ? MERGEPAINT :
1470 rop == wxAND_REVERSE ? SRCERASE :
1471 rop == wxSRC_OR ? SRCPAINT :
1472 rop == wxSRC_AND ? SRCAND :
1473 SRCCOPY;
1474
1475 bool success;
1476 if (useMask && source->m_selectedBitmap.Ok() && source->m_selectedBitmap.GetMask())
1477 {
1478
1479 #if 0 // __WIN32__
1480 // Not implemented under Win95 (or maybe a specific device?)
1481 if (MaskBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1482 (HDC) source->m_hDC, xsrc1, ysrc1, (HBITMAP) source->m_selectedBitmap.GetMask()->GetMaskBitmap(),
1483 0, 0, 0xAACC0020))
1484 {
1485 // Success
1486 }
1487 else
1488 #endif
1489 {
1490 // Old code
1491 #if 0
1492 HDC dc_mask = CreateCompatibleDC((HDC) source->m_hDC);
1493 ::SelectObject(dc_mask, (HBITMAP) source->m_selectedBitmap.GetMask()->GetMaskBitmap());
1494 success = (BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1495 dc_mask, xsrc1, ysrc1, 0x00220326 /* NOTSRCAND */) != 0);
1496 success = (BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1497 (HDC) source->m_hDC, xsrc1, ysrc1, SRCPAINT) != 0);
1498 ::SelectObject(dc_mask, 0);
1499 ::DeleteDC(dc_mask);
1500 #endif
1501 // New code from Chris Breeze, 8/5/98
1502
1503 // create a temp buffer bitmap and DCs to access it and the mask
1504 HDC dc_mask = ::CreateCompatibleDC((HDC) source->m_hDC);
1505 HDC dc_buffer = ::CreateCompatibleDC((HDC) m_hDC);
1506 HBITMAP buffer_bmap = ::CreateCompatibleBitmap((HDC) m_hDC, width, height);
1507 ::SelectObject(dc_mask, (HBITMAP) source->m_selectedBitmap.GetMask()->GetMaskBitmap());
1508 ::SelectObject(dc_buffer, buffer_bmap);
1509
1510 // copy dest to buffer
1511 ::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
1512 (HDC) m_hDC, xdest1, ydest1, SRCCOPY);
1513
1514 // copy src to buffer using selected raster op
1515 ::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
1516 (HDC) source->m_hDC, xsrc1, ysrc1, dwRop);
1517
1518 // set masked area in buffer to BLACK (pixel value 0)
1519 COLORREF prevBkCol = ::SetBkColor((HDC) m_hDC, RGB(255, 255, 255));
1520 COLORREF prevCol = ::SetTextColor((HDC) m_hDC, RGB(0, 0, 0));
1521 ::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
1522 dc_mask, xsrc1, ysrc1, SRCAND);
1523
1524 // set unmasked area in dest to BLACK
1525 ::SetBkColor((HDC) m_hDC, RGB(0, 0, 0));
1526 ::SetTextColor((HDC) m_hDC, RGB(255, 255, 255));
1527 ::BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1528 dc_mask, xsrc1, ysrc1, SRCAND);
1529 ::SetBkColor((HDC) m_hDC, prevBkCol); // restore colours to original values
1530 ::SetTextColor((HDC) m_hDC, prevCol);
1531
1532 // OR buffer to dest
1533 success = (::BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1534 dc_buffer, 0, 0, SRCPAINT) != 0);
1535
1536 // tidy up temporary DCs and bitmap
1537 ::SelectObject(dc_mask, 0);
1538 ::DeleteDC(dc_mask);
1539 ::SelectObject(dc_buffer, 0);
1540 ::DeleteDC(dc_buffer);
1541 ::DeleteObject(buffer_bmap);
1542 }
1543 }
1544 else
1545 {
1546 success = (BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height, (HDC) source->m_hDC,
1547 xsrc1, ysrc1, dwRop) != 0);
1548 }
1549 ::SetTextColor((HDC)m_hDC, old_textground);
1550 ::SetBkColor((HDC)m_hDC, old_background);
1551 source->EndDrawing();
1552 EndDrawing();
1553
1554 return success;
1555 }
1556
1557 void wxDC::GetSize(int* width, int* height) const
1558 {
1559 long w=::GetDeviceCaps((HDC) m_hDC,HORZRES);
1560 long h=::GetDeviceCaps((HDC) m_hDC,VERTRES);
1561 *width = w;
1562 *height = h;
1563 }
1564
1565 void wxDC::GetSizeMM(long *width, long *height) const
1566 {
1567 long w=::GetDeviceCaps((HDC) m_hDC,HORZSIZE);
1568 long h=::GetDeviceCaps((HDC) m_hDC,VERTSIZE);
1569 *width = w;
1570 *height = h;
1571 }
1572
1573 /*
1574 #if USE_SPLINES
1575 # if USE_XFIG_SPLINE_CODE
1576 # include "../common/xfspline.inc"
1577 # else
1578 # include "../common/wxspline.inc"
1579 # endif
1580 #endif // USE_SPLINES
1581 */
1582
1583 #if USE_SPLINES
1584 #include "xfspline.inc"
1585 #endif // USE_SPLINES
1586
1587 void wxDC::DrawPolygon(wxList *list, long xoffset, long yoffset,int fillStyle)
1588 {
1589 int n = list->Number();
1590 wxPoint *points = new wxPoint[n];
1591
1592 int i = 0;
1593 for(wxNode *node = list->First(); node; node = node->Next()) {
1594 wxPoint *point = (wxPoint *)node->Data();
1595 points[i].x = point->x;
1596 points[i++].y = point->y;
1597 }
1598 DrawPolygon(n, points, xoffset, yoffset,fillStyle);
1599 delete[] points;
1600 }
1601
1602 void wxDC::DrawLines(wxList *list, long xoffset, long yoffset)
1603 {
1604 int n = list->Number();
1605 wxPoint *points = new wxPoint[n];
1606
1607 int i = 0;
1608 for(wxNode *node = list->First(); node; node = node->Next()) {
1609 wxPoint *point = (wxPoint *)node->Data();
1610 points[i].x = point->x;
1611 points[i++].y = point->y;
1612 }
1613 DrawLines(n, points, xoffset, yoffset);
1614 delete []points;
1615 }
1616
1617 void wxDC::SetTextForeground(const wxColour& colour)
1618 {
1619 m_textForegroundColour = colour;
1620 }
1621
1622 void wxDC::SetTextBackground(const wxColour& colour)
1623 {
1624 m_textBackgroundColour = colour;
1625 }
1626
1627 #if USE_SPLINES
1628 // Make a 3-point spline
1629 void wxDC::DrawSpline(long x1, long y1, long x2, long y2, long x3, long y3)
1630 {
1631 wxList *point_list = new wxList;
1632
1633 wxPoint *point1 = new wxPoint;
1634 point1->x = x1; point1->y = y1;
1635 point_list->Append((wxObject*)point1);
1636
1637 wxPoint *point2 = new wxPoint;
1638 point2->x = x2; point2->y = y2;
1639 point_list->Append((wxObject*)point2);
1640
1641 wxPoint *point3 = new wxPoint;
1642 point3->x = x3; point3->y = y3;
1643 point_list->Append((wxObject*)point3);
1644
1645 DrawSpline(point_list);
1646
1647 for(wxNode *node = point_list->First(); node; node = node->Next()) {
1648 wxPoint *p = (wxPoint *)node->Data();
1649 delete p;
1650 }
1651 delete point_list;
1652 /*
1653 wxSpline spline(point_list);
1654
1655 wx_draw_open_spline(this, &spline);
1656 spline.DeletePoints();
1657 */
1658 }
1659 #endif
1660
1661 // For use by wxWindows only, unless custom units are required.
1662 void wxDC::SetLogicalScale(double x, double y)
1663 {
1664 m_logicalScaleX = x;
1665 m_logicalScaleY = y;
1666 }
1667
1668 void wxDC::CalcBoundingBox(long x, long y)
1669 {
1670 if (x < m_minX) m_minX = x;
1671 if (y < m_minY) m_minY = y;
1672 if (x > m_maxX) m_maxX = x;
1673 if (y > m_maxY) m_maxY = y;
1674 }
1675
1676 void wxDC::GetClippingBox(long *x,long *y,long *w,long *h) const
1677 {
1678 if (m_clipping)
1679 {
1680 *x = m_clipX1 ;
1681 *y = m_clipY1 ;
1682 *w = (m_clipX2 - m_clipX1) ;
1683 *h = (m_clipY2 - m_clipY1) ;
1684 }
1685 else
1686 *x = *y = *w = *h = 0 ;
1687 }
1688
1689 #if WXWIN_COMPATIBILITY
1690 void wxDC::GetTextExtent(const wxString& string, float *x, float *y,
1691 float *descent, float *externalLeading,
1692 wxFont *theFont, bool use16bit) const
1693 {
1694 long x1, y1, descent1, externalLeading1;
1695 GetTextExtent(string, & x1, & y1, & descent1, & externalLeading1, theFont, use16bit);
1696 *x = x1; *y = y1;
1697 if (descent)
1698 *descent = descent1;
1699 if (externalLeading)
1700 *externalLeading = externalLeading1;
1701 }
1702 #endif
1703