]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dc.cpp
Corrected dataobj.h/.cpp, corrected listbox to use non-integral height
[wxWidgets.git] / src / msw / dc.cpp
CommitLineData
2bda0e17
KB
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
59IMPLEMENT_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
69wxDC::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;
6f65e337
JS
111 m_signX = 1;
112 m_signY = 1;
2bda0e17
KB
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
137wxDC::~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.
161void 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
235void 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
250void 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
274void 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
296bool wxDC::CanDrawBitmap(void) const
297{
298 return TRUE;
299}
300
301bool 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
315void 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
356void 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
385void 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
409bool 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
440void 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
480void 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
513void 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
2bda0e17
KB
579void 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
614void 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
650void 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
686void 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
750void 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
794void 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
6f65e337
JS
824// Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
825void 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
2bda0e17
KB
869void 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
888void 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
917void 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
948void 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
980void 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
1030void 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
1076void 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
1090void wxDC::SetLogicalFunction(int function)
1091{
1092 m_logicalFunction = function;
1093
1094 BeginDrawing();
1095
1096 SetRop((WXHDC) m_hDC);
1097
1098 EndDrawing();
1099}
1100
1101void 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
1131bool 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
1163void wxDC::EndDoc(void)
1164{
1165 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
1166 return;
1167 if (m_hDC) ::EndDoc((HDC) m_hDC);
1168}
1169
1170void wxDC::StartPage(void)
1171{
1172 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
1173 return;
1174 if (m_hDC)
1175 ::StartPage((HDC) m_hDC);
1176}
1177
1178void wxDC::EndPage(void)
1179{
1180 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
1181 return;
1182 if (m_hDC)
1183 ::EndPage((HDC) m_hDC);
1184}
1185
1186long wxDC::GetCharHeight(void) const
1187{
1188 TEXTMETRIC lpTextMetric;
1189
1190 GetTextMetrics((HDC) m_hDC, &lpTextMetric);
1191
1192 return YDEV2LOGREL(lpTextMetric.tmHeight);
1193}
1194
1195long wxDC::GetCharWidth(void) const
1196{
1197 TEXTMETRIC lpTextMetric;
1198
1199 GetTextMetrics((HDC) m_hDC, &lpTextMetric);
1200
1201 return XDEV2LOGREL(lpTextMetric.tmAveCharWidth);
1202}
1203
1204void 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
1223void 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
1297void wxDC::SetUserScale(double x, double y)
1298{
1299 m_userScaleX = x;
1300 m_userScaleY = y;
1301
1302 SetMapMode(m_mappingMode);
1303}
1304
6f65e337
JS
1305void 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
2bda0e17
KB
1313void wxDC::SetSystemScale(double x, double y)
1314{
1315 m_systemScaleX = x;
1316 m_systemScaleY = y;
1317
1318 SetMapMode(m_mappingMode);
1319}
1320
1321void 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
1333void 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
1345long wxDC::DeviceToLogicalX(long x) const
1346{
6f65e337 1347 return (long) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX) - m_logicalOriginX) ;
2bda0e17
KB
1348}
1349
1350long wxDC::DeviceToLogicalXRel(long x) const
1351{
6f65e337 1352 return (long) ((x)/(m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX)) ;
2bda0e17
KB
1353}
1354
1355long wxDC::DeviceToLogicalY(long y) const
1356{
6f65e337 1357 return (long) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY) - m_logicalOriginY) ;
2bda0e17
KB
1358}
1359
1360long wxDC::DeviceToLogicalYRel(long y) const
1361{
6f65e337 1362 return (long) ((y)/(m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY)) ;
2bda0e17
KB
1363}
1364
1365long wxDC::LogicalToDeviceX(long x) const
1366{
6f65e337 1367 return (long) (floor((x) - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX + m_deviceOriginX) ;
2bda0e17
KB
1368}
1369
1370long wxDC::LogicalToDeviceXRel(long x) const
1371{
6f65e337 1372 return (long) (floor(x)*m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX) ;
2bda0e17
KB
1373}
1374
1375long wxDC::LogicalToDeviceY(long y) const
1376{
6f65e337 1377 return (long) (floor((y) - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY + m_deviceOriginY);
2bda0e17
KB
1378}
1379
1380long wxDC::LogicalToDeviceYRel(long y) const
1381{
6f65e337 1382 return (long) (floor(y)*m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY) ;
2bda0e17
KB
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
1389long wxDC::ImplDeviceToLogicalX(long x) const
1390{
1391// return (m_scaleGDI ? x : DeviceToLogicalX(x));
1392 return x;
1393}
1394
1395long wxDC::ImplDeviceToLogicalY(long y) const
1396{
1397// return (m_scaleGDI ? y : DeviceToLogicalY(y));
1398 return y;
1399}
1400
1401long wxDC::ImplDeviceToLogicalXRel(long x) const
1402{
1403// return (m_scaleGDI ? x : DeviceToLogicalXRel(x));
1404 return x;
1405}
1406
1407long wxDC::ImplDeviceToLogicalYRel(long y) const
1408{
1409// return (m_scaleGDI ? y : DeviceToLogicalYRel(y));
1410 return y;
1411}
1412
1413long wxDC::ImplLogicalToDeviceX(long x) const
1414{
1415// return (m_scaleGDI ? (floor(double(x))) : LogicalToDeviceX(x));
1416 return x;
1417}
1418
1419long wxDC::ImplLogicalToDeviceY(long y) const
1420{
1421// return (m_scaleGDI ? (floor(double(y))) : LogicalToDeviceY(y));
1422 return y;
1423}
1424
1425long wxDC::ImplLogicalToDeviceXRel(long x) const
1426{
1427// return (m_scaleGDI ? (floor(double(x))) : LogicalToDeviceXRel(x));
1428 return x;
1429}
1430
1431long wxDC::ImplLogicalToDeviceYRel(long y) const
1432{
1433// return (m_scaleGDI ? (floor(double(y))) : LogicalToDeviceYRel(y));
1434 return y;
1435}
1436
1437bool 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
6f65e337
JS
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
2bda0e17
KB
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 }
6f65e337
JS
1549 ::SetTextColor((HDC)m_hDC, old_textground);
1550 ::SetBkColor((HDC)m_hDC, old_background);
2bda0e17
KB
1551 source->EndDrawing();
1552 EndDrawing();
1553
1554 return success;
1555}
1556
1557void 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
1565void 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
10b959e3 1573/*
2bda0e17
KB
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
10b959e3
JS
1581*/
1582
1583#if USE_SPLINES
1584#include "xfspline.inc"
1585#endif // USE_SPLINES
2bda0e17
KB
1586
1587void 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
1602void 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
1617void wxDC::SetTextForeground(const wxColour& colour)
1618{
1619 m_textForegroundColour = colour;
1620}
1621
1622void wxDC::SetTextBackground(const wxColour& colour)
1623{
1624 m_textBackgroundColour = colour;
1625}
1626
1627#if USE_SPLINES
1628// Make a 3-point spline
1629void 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.
1662void wxDC::SetLogicalScale(double x, double y)
1663{
1664 m_logicalScaleX = x;
1665 m_logicalScaleY = y;
1666}
1667
1668void 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
1676void 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
1690void 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