1 /////////////////////////////////////////////////////////////////////////////
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
16 #include "wx/window.h"
19 #include "wx/dialog.h"
21 #include "wx/bitmap.h"
22 #include "wx/dcmemory.h"
27 #include "wx/dcprint.h"
32 #include "wx/os2/private.h"
34 #if !USE_SHARED_LIBRARY
35 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
38 // ---------------------------------------------------------------------------
40 // ---------------------------------------------------------------------------
42 static const int VIEWPORT_EXTENT
= 1000;
44 static const int MM_POINTS
= 9;
45 static const int MM_METRIC
= 10;
47 // ===========================================================================
49 // ===========================================================================
51 // ---------------------------------------------------------------------------
53 // ---------------------------------------------------------------------------
75 // This will select current objects out of the DC,
76 // which is what you have to do before deleting the
78 void wxDC::SelectOldObjects(WXHDC dc
)
84 // ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
85 if (m_selectedBitmap
.Ok())
87 m_selectedBitmap
.SetSelectedInto(NULL
);
93 // ::SelectObject((HDC) dc, (HPEN) m_oldPen);
98 // ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
103 // ::SelectObject((HDC) dc, (HFONT) m_oldFont);
108 // ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE);
113 m_brush
= wxNullBrush
;
115 m_palette
= wxNullPalette
;
117 m_backgroundBrush
= wxNullBrush
;
118 m_selectedBitmap
= wxNullBitmap
;
121 // ---------------------------------------------------------------------------
123 // ---------------------------------------------------------------------------
125 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
)
130 void wxDC::DoSetClippingRegion( long x
, long y
131 ,long width
, long height
137 void wxDC::DoClipping(WXHDC dc
)
139 if (m_clipping
&& dc
)
142 // IntersectClipRect((HDC) dc, XLOG2DEV(m_clipX1), YLOG2DEV(m_clipY1),
143 // XLOG2DEV(m_clipX2), YLOG2DEV(m_clipY2));
147 void wxDC::DestroyClippingRegion(void)
152 // ---------------------------------------------------------------------------
153 // query capabilities
154 // ---------------------------------------------------------------------------
156 bool wxDC::CanDrawBitmap() const
161 bool wxDC::CanGetTextExtent() const
163 // What sort of display is it?
164 int technology
= 0; // TODO: ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
166 // TODO: return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
170 int wxDC::GetDepth() const
176 // ---------------------------------------------------------------------------
178 // ---------------------------------------------------------------------------
185 void wxDC::DoFloodFill( long x
194 bool wxDC::DoGetPixel(long x
, long y
, wxColour
*col
) const
200 void wxDC::DoCrossHair(long x
, long y
)
205 void wxDC::DoDrawLine(long x1
, long y1
, long x2
, long y2
)
210 void wxDC::DoDrawArc( long x1
, long y1
218 void wxDC::DoDrawPoint(long x
, long y
)
223 void wxDC::DoDrawPolygon(int n
, wxPoint points
[]
224 ,long xoffset
, long yoffset
231 void wxDC::DoDrawLines( int n
, wxPoint points
[]
232 ,long xoffset
, long yoffset
238 void wxDC::DoDrawRectangle(long x
, long y
, long width
, long height
)
243 void wxDC::DoDrawRoundedRectangle( long x
, long y
244 ,long width
, long height
251 void wxDC::DoDrawEllipse(long x
, long y
, long width
, long height
)
256 void wxDC::DoDrawEllipticArc( long x
267 void wxDC::DoDrawIcon(const wxIcon
& icon
, long x
, long y
)
272 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
280 void wxDC::DoDrawText(const wxString
& text
, long x
, long y
)
285 // ---------------------------------------------------------------------------
287 // ---------------------------------------------------------------------------
289 void wxDC::SetPalette(const wxPalette
& palette
)
294 void wxDC::SetFont(const wxFont
& font
)
299 void wxDC::SetPen(const wxPen
& pen
)
303 void wxDC::SetBrush(const wxBrush
& brush
)
308 void wxDC::SetBackground(const wxBrush
& brush
)
313 void wxDC::SetBackgroundMode(int mode
)
318 void wxDC::SetLogicalFunction(int function
)
323 void wxDC::SetRop(WXHDC dc
)
325 if (!dc
|| m_logicalFunction
< 0)
329 // These may be wrong
330 switch (m_logicalFunction
)
332 // TODO: Figure this stuff out
333 // case wxXOR: c_rop = R2_XORPEN; break;
334 // case wxXOR: c_rop = R2_NOTXORPEN; break;
335 // case wxINVERT: c_rop = R2_NOT; break;
336 // case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
337 // case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
338 // case wxCLEAR: c_rop = R2_WHITE; break;
339 // case wxSET: c_rop = R2_BLACK; break;
340 // case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
341 // case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
342 // case wxAND: c_rop = R2_MASKPEN; break;
343 // case wxOR: c_rop = R2_MERGEPEN; break;
344 // case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
349 // c_rop = R2_COPYPEN;
352 // SetROP2((HDC) dc, c_rop);
355 bool wxDC::StartDoc(const wxString
& message
)
357 // We might be previewing, so return TRUE to let it continue.
365 void wxDC::StartPage()
373 // ---------------------------------------------------------------------------
375 // ---------------------------------------------------------------------------
377 long wxDC::GetCharHeight() const
383 long wxDC::GetCharWidth() const
389 void wxDC::GetTextExtent( const wxString
& string
393 ,long* externalLeading
400 void wxDC::SetMapMode( int mode
)
405 void wxDC::SetUserScale(double x
, double y
)
410 SetMapMode(m_mappingMode
);
413 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
415 m_signX
= xLeftRight
? 1 : -1;
416 m_signY
= yBottomUp
? -1 : 1;
418 SetMapMode(m_mappingMode
);
421 void wxDC::SetSystemScale(double x
, double y
)
426 SetMapMode(m_mappingMode
);
429 void wxDC::SetLogicalOrigin( long x
, long y
)
434 void wxDC::SetDeviceOrigin( long x
, long y
)
439 // ---------------------------------------------------------------------------
440 // coordinates transformations
441 // ---------------------------------------------------------------------------
443 long wxDCBase::DeviceToLogicalX(long x
) const
445 long new_x
= x
- m_deviceOriginX
;
447 return (long)((double)(new_x
) / m_scaleX
+ 0.5) * m_signX
+ m_logicalOriginX
;
449 return (long)((double)(new_x
) / m_scaleX
- 0.5) * m_signX
+ m_logicalOriginX
;
452 long wxDCBase::DeviceToLogicalXRel(long x
) const
455 return (long)((double)(x
) / m_scaleX
+ 0.5);
457 return (long)((double)(x
) / m_scaleX
- 0.5);
460 long wxDCBase::DeviceToLogicalY(long y
) const
462 long new_y
= y
- m_deviceOriginY
;
464 return (long)((double)(new_y
) / m_scaleY
+ 0.5) * m_signY
+ m_logicalOriginY
;
466 return (long)((double)(new_y
) / m_scaleY
- 0.5) * m_signY
+ m_logicalOriginY
;
469 long wxDCBase::DeviceToLogicalYRel(long y
) const
472 return (long)((double)(y
) / m_scaleY
+ 0.5);
474 return (long)((double)(y
) / m_scaleY
- 0.5);
477 long wxDCBase::LogicalToDeviceX(long x
) const
479 long new_x
= x
- m_logicalOriginX
;
481 return (long)((double)(new_x
) * m_scaleX
+ 0.5) * m_signX
+ m_deviceOriginX
;
483 return (long)((double)(new_x
) * m_scaleX
- 0.5) * m_signX
+ m_deviceOriginX
;
486 long wxDCBase::LogicalToDeviceXRel(long x
) const
489 return (long)((double)(x
) * m_scaleX
+ 0.5);
491 return (long)((double)(x
) * m_scaleX
- 0.5);
494 long wxDCBase::LogicalToDeviceY(long y
) const
496 long new_y
= y
- m_logicalOriginY
;
498 return (long)((double)(new_y
) * m_scaleY
+ 0.5) * m_signY
+ m_deviceOriginY
;
500 return (long)((double)(new_y
) * m_scaleY
- 0.5) * m_signY
+ m_deviceOriginY
;
503 long wxDCBase::LogicalToDeviceYRel(long y
) const
506 return (long)((double)(y
) * m_scaleY
+ 0.5);
508 return (long)((double)(y
) * m_scaleY
- 0.5);
511 // ---------------------------------------------------------------------------
513 // ---------------------------------------------------------------------------
515 bool wxDC::DoBlit( long xdest
530 void wxDC::DoGetSize( int* width
, int* height
) const
535 void wxDC::DoGetSizeMM( int* width
, int* height
) const
540 wxSize
wxDC::GetPPI() const
545 return (wxSize(x
,y
));
548 void wxDC::SetLogicalScale( double x
, double y
)
553 #if WXWIN_COMPATIBILITY
554 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
555 float *descent
, float *externalLeading
,
556 wxFont
*theFont
, bool use16bit
) const
558 long x1
, y1
, descent1
, externalLeading1
;
559 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
564 *externalLeading
= externalLeading1
;
568 // ---------------------------------------------------------------------------
569 // spline drawing code
570 // ---------------------------------------------------------------------------
574 class wxSpline
: public wxObject
580 wxSpline(wxList
*list
);
583 // Doesn't delete points
587 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
589 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
590 double a3
, double b3
, double a4
, double b4
);
591 void wx_clear_stack();
592 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
593 double *y3
, double *x4
, double *y4
);
594 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
595 double x4
, double y4
);
596 static bool wx_spline_add_point(double x
, double y
);
597 static void wx_spline_draw_point_array(wxDC
*dc
);
598 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
600 void wxDC::DoDrawSpline(wxList
*list
)
602 wxSpline
spline(list
);
604 wx_draw_open_spline(this, &spline
);
607 wxList wx_spline_point_list
;
609 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
612 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
613 double x1
, y1
, x2
, y2
;
615 wxNode
*node
= spline
->points
->First();
616 p
= (wxPoint
*)node
->Data();
622 p
= (wxPoint
*)node
->Data();
626 cx1
= (double)((x1
+ x2
) / 2);
627 cy1
= (double)((y1
+ y2
) / 2);
628 cx2
= (double)((cx1
+ x2
) / 2);
629 cy2
= (double)((cy1
+ y2
) / 2);
631 wx_spline_add_point(x1
, y1
);
633 while ((node
= node
->Next()) != NULL
)
635 p
= (wxPoint
*)node
->Data();
640 cx4
= (double)(x1
+ x2
) / 2;
641 cy4
= (double)(y1
+ y2
) / 2;
642 cx3
= (double)(x1
+ cx4
) / 2;
643 cy3
= (double)(y1
+ cy4
) / 2;
645 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
649 cx2
= (double)(cx1
+ x2
) / 2;
650 cy2
= (double)(cy1
+ y2
) / 2;
653 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
654 wx_spline_add_point(x2
, y2
);
656 wx_spline_draw_point_array(dc
);
660 /********************* CURVES FOR SPLINES *****************************
662 The following spline drawing routine is from
664 "An Algorithm for High-Speed Curve Generation"
665 by George Merrill Chaikin,
666 Computer Graphics and Image Processing, 3, Academic Press,
671 "On Chaikin's Algorithm" by R. F. Riesenfeld,
672 Computer Graphics and Image Processing, 4, Academic Press,
675 ***********************************************************************/
677 #define half(z1, z2) ((z1+z2)/2.0)
680 /* iterative version */
682 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
685 register double xmid
, ymid
;
686 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
689 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
691 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
692 xmid
= (double)half(x2
, x3
);
693 ymid
= (double)half(y2
, y3
);
694 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
695 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
696 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
697 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
699 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
700 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
701 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
702 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
708 /* utilities used by spline drawing routines */
711 typedef struct wx_spline_stack_struct
{
712 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
716 #define SPLINE_STACK_DEPTH 20
717 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
718 static Stack
*wx_stack_top
;
719 static int wx_stack_count
;
721 void wx_clear_stack()
723 wx_stack_top
= wx_spline_stack
;
727 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
729 wx_stack_top
->x1
= x1
;
730 wx_stack_top
->y1
= y1
;
731 wx_stack_top
->x2
= x2
;
732 wx_stack_top
->y2
= y2
;
733 wx_stack_top
->x3
= x3
;
734 wx_stack_top
->y3
= y3
;
735 wx_stack_top
->x4
= x4
;
736 wx_stack_top
->y4
= y4
;
741 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
742 double *x3
, double *y3
, double *x4
, double *y4
)
744 if (wx_stack_count
== 0)
748 *x1
= wx_stack_top
->x1
;
749 *y1
= wx_stack_top
->y1
;
750 *x2
= wx_stack_top
->x2
;
751 *y2
= wx_stack_top
->y2
;
752 *x3
= wx_stack_top
->x3
;
753 *y3
= wx_stack_top
->y3
;
754 *x4
= wx_stack_top
->x4
;
755 *y4
= wx_stack_top
->y4
;
759 static bool wx_spline_add_point(double x
, double y
)
761 wxPoint
*point
= new wxPoint
;
764 wx_spline_point_list
.Append((wxObject
*)point
);
768 static void wx_spline_draw_point_array(wxDC
*dc
)
770 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
771 wxNode
*node
= wx_spline_point_list
.First();
774 wxPoint
*point
= (wxPoint
*)node
->Data();
777 node
= wx_spline_point_list
.First();
781 wxSpline::wxSpline(wxList
*list
)
786 wxSpline::~wxSpline()
790 void wxSpline::DeletePoints()
792 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
794 wxPoint
*point
= (wxPoint
*)node
->Data();
802 #endif // wxUSE_SPLINES