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 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
36 // ---------------------------------------------------------------------------
38 // ---------------------------------------------------------------------------
40 static const int VIEWPORT_EXTENT
= 1000;
42 static const int MM_POINTS
= 9;
43 static const int MM_METRIC
= 10;
45 // ===========================================================================
47 // ===========================================================================
49 // ---------------------------------------------------------------------------
51 // ---------------------------------------------------------------------------
73 // This will select current objects out of the DC,
74 // which is what you have to do before deleting the
76 void wxDC::SelectOldObjects(WXHDC dc
)
82 // ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
83 if (m_selectedBitmap
.Ok())
85 m_selectedBitmap
.SetSelectedInto(NULL
);
91 // ::SelectObject((HDC) dc, (HPEN) m_oldPen);
96 // ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
101 // ::SelectObject((HDC) dc, (HFONT) m_oldFont);
106 // ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE);
111 m_brush
= wxNullBrush
;
113 m_palette
= wxNullPalette
;
115 m_backgroundBrush
= wxNullBrush
;
116 m_selectedBitmap
= wxNullBitmap
;
119 // ---------------------------------------------------------------------------
121 // ---------------------------------------------------------------------------
123 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
)
128 void wxDC::DoSetClippingRegion( wxCoord x
, wxCoord y
129 ,wxCoord width
, wxCoord height
135 void wxDC::DoClipping(WXHDC dc
)
137 if (m_clipping
&& dc
)
140 // IntersectClipRect((HDC) dc, XLOG2DEV(m_clipX1), YLOG2DEV(m_clipY1),
141 // XLOG2DEV(m_clipX2), YLOG2DEV(m_clipY2));
145 void wxDC::DestroyClippingRegion(void)
150 // ---------------------------------------------------------------------------
151 // query capabilities
152 // ---------------------------------------------------------------------------
154 bool wxDC::CanDrawBitmap() const
159 bool wxDC::CanGetTextExtent() const
161 // What sort of display is it?
162 int technology
= 0; // TODO: ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
164 // TODO: return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
168 int wxDC::GetDepth() const
174 // ---------------------------------------------------------------------------
176 // ---------------------------------------------------------------------------
183 void wxDC::DoFloodFill( wxCoord x
192 bool wxDC::DoGetPixel(wxCoord x
, wxCoord y
, wxColour
*col
) const
198 void wxDC::DoCrossHair(wxCoord x
, wxCoord y
)
203 void wxDC::DoDrawLine(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
208 void wxDC::DoDrawArc( wxCoord x1
, wxCoord y1
209 ,wxCoord x2
, wxCoord y2
210 ,wxCoord xc
, wxCoord yc
216 void wxDC::DoDrawPoint(wxCoord x
, wxCoord y
)
221 void wxDC::DoDrawPolygon(int n
, wxPoint points
[]
222 ,wxCoord xoffset
, wxCoord yoffset
229 void wxDC::DoDrawLines( int n
, wxPoint points
[]
230 ,wxCoord xoffset
, wxCoord yoffset
236 void wxDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
241 void wxDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
242 ,wxCoord width
, wxCoord height
249 void wxDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
254 void wxDC::DoDrawEllipticArc( wxCoord x
265 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
)
270 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
271 ,wxCoord x
, wxCoord y
278 void wxDC::DoDrawText(const wxString
& text
, wxCoord x
, wxCoord y
)
283 void wxDC::DoDrawRotatedText(const wxString
& text
,
284 wxCoord x
, wxCoord y
,
291 DoDrawText(text, x, y);
296 wxFillLogFont(&lf, &m_font);
298 // GDI wants the angle in tenth of degree
299 long angle10 = (long)(angle * 10);
300 lf.lfEscapement = angle10;
301 lf. lfOrientation = angle10;
303 HFONT hfont = ::CreateFontIndirect(&lf);
306 wxLogLastError("CreateFont");
310 HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
312 DrawAnyText(text, x, y);
314 (void)::SelectObject(GetHdc(), hfontOld);
317 // call the bounding box by adding all four vertices of the rectangle
318 // containing the text to it (simpler and probably not slower than
319 // determining which of them is really topmost/leftmost/...)
321 GetTextExtent(text, &w, &h);
323 double rad = DegToRad(angle);
325 // "upper left" and "upper right"
326 CalcBoundingBox(x, y);
327 CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
328 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
330 // "bottom left" and "bottom right"
331 x += (wxCoord)(h*sin(rad));
332 y += (wxCoord)(h*cos(rad));
333 CalcBoundingBox(x, y);
334 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
339 // ---------------------------------------------------------------------------
341 // ---------------------------------------------------------------------------
343 void wxDC::SetPalette(const wxPalette
& palette
)
348 void wxDC::SetFont(const wxFont
& font
)
353 void wxDC::SetPen(const wxPen
& pen
)
357 void wxDC::SetBrush(const wxBrush
& brush
)
362 void wxDC::SetBackground(const wxBrush
& brush
)
367 void wxDC::SetBackgroundMode(int mode
)
372 void wxDC::SetLogicalFunction(int function
)
377 void wxDC::SetRop(WXHDC dc
)
379 if (!dc
|| m_logicalFunction
< 0)
383 // These may be wrong
384 switch (m_logicalFunction
)
386 // TODO: Figure this stuff out
387 // case wxXOR: c_rop = R2_XORPEN; break;
388 // case wxXOR: c_rop = R2_NOTXORPEN; break;
389 // case wxINVERT: c_rop = R2_NOT; break;
390 // case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
391 // case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
392 // case wxCLEAR: c_rop = R2_WHITE; break;
393 // case wxSET: c_rop = R2_BLACK; break;
394 // case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
395 // case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
396 // case wxAND: c_rop = R2_MASKPEN; break;
397 // case wxOR: c_rop = R2_MERGEPEN; break;
398 // case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
403 // c_rop = R2_COPYPEN;
406 // SetROP2((HDC) dc, c_rop);
409 bool wxDC::StartDoc(const wxString
& message
)
411 // We might be previewing, so return TRUE to let it continue.
419 void wxDC::StartPage()
427 // ---------------------------------------------------------------------------
429 // ---------------------------------------------------------------------------
431 wxCoord
wxDC::GetCharHeight() const
437 wxCoord
wxDC::GetCharWidth() const
443 void wxDC::DoGetTextExtent( const wxString
& string
447 ,wxCoord
* externalLeading
454 void wxDC::SetMapMode( int mode
)
459 void wxDC::SetUserScale(double x
, double y
)
464 SetMapMode(m_mappingMode
);
467 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
469 m_signX
= xLeftRight
? 1 : -1;
470 m_signY
= yBottomUp
? -1 : 1;
472 SetMapMode(m_mappingMode
);
475 void wxDC::SetSystemScale(double x
, double y
)
480 SetMapMode(m_mappingMode
);
483 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
488 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
493 // ---------------------------------------------------------------------------
494 // coordinates transformations
495 // ---------------------------------------------------------------------------
497 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
499 wxCoord new_x
= x
- m_deviceOriginX
;
501 return (wxCoord
)((double)(new_x
) / m_scaleX
+ 0.5) * m_signX
+ m_logicalOriginX
;
503 return (wxCoord
)((double)(new_x
) / m_scaleX
- 0.5) * m_signX
+ m_logicalOriginX
;
506 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
509 return (wxCoord
)((double)(x
) / m_scaleX
+ 0.5);
511 return (wxCoord
)((double)(x
) / m_scaleX
- 0.5);
514 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
516 wxCoord new_y
= y
- m_deviceOriginY
;
518 return (wxCoord
)((double)(new_y
) / m_scaleY
+ 0.5) * m_signY
+ m_logicalOriginY
;
520 return (wxCoord
)((double)(new_y
) / m_scaleY
- 0.5) * m_signY
+ m_logicalOriginY
;
523 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
526 return (wxCoord
)((double)(y
) / m_scaleY
+ 0.5);
528 return (wxCoord
)((double)(y
) / m_scaleY
- 0.5);
531 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
533 wxCoord new_x
= x
- m_logicalOriginX
;
535 return (wxCoord
)((double)(new_x
) * m_scaleX
+ 0.5) * m_signX
+ m_deviceOriginX
;
537 return (wxCoord
)((double)(new_x
) * m_scaleX
- 0.5) * m_signX
+ m_deviceOriginX
;
540 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
543 return (wxCoord
)((double)(x
) * m_scaleX
+ 0.5);
545 return (wxCoord
)((double)(x
) * m_scaleX
- 0.5);
548 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
550 wxCoord new_y
= y
- m_logicalOriginY
;
552 return (wxCoord
)((double)(new_y
) * m_scaleY
+ 0.5) * m_signY
+ m_deviceOriginY
;
554 return (wxCoord
)((double)(new_y
) * m_scaleY
- 0.5) * m_signY
+ m_deviceOriginY
;
557 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
560 return (wxCoord
)((double)(y
) * m_scaleY
+ 0.5);
562 return (wxCoord
)((double)(y
) * m_scaleY
- 0.5);
565 // ---------------------------------------------------------------------------
567 // ---------------------------------------------------------------------------
569 bool wxDC::DoBlit( wxCoord xdest
584 void wxDC::DoGetSize( int* width
, int* height
) const
589 void wxDC::DoGetSizeMM( int* width
, int* height
) const
594 wxSize
wxDC::GetPPI() const
599 return (wxSize(x
,y
));
602 void wxDC::SetLogicalScale( double x
, double y
)
607 #if WXWIN_COMPATIBILITY
608 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
609 float *descent
, float *externalLeading
,
610 wxFont
*theFont
, bool use16bit
) const
612 wxCoord x1
, y1
, descent1
, externalLeading1
;
613 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
618 *externalLeading
= externalLeading1
;
622 // ---------------------------------------------------------------------------
623 // spline drawing code
624 // ---------------------------------------------------------------------------
628 class wxSpline
: public wxObject
634 wxSpline(wxList
*list
);
637 // Doesn't delete points
641 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
643 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
644 double a3
, double b3
, double a4
, double b4
);
645 void wx_clear_stack();
646 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
647 double *y3
, double *x4
, double *y4
);
648 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
649 double x4
, double y4
);
650 static bool wx_spline_add_point(double x
, double y
);
651 static void wx_spline_draw_point_array(wxDC
*dc
);
652 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
654 void wxDC::DoDrawSpline(wxList
*list
)
656 wxSpline
spline(list
);
658 wx_draw_open_spline(this, &spline
);
661 wxList wx_spline_point_list
;
663 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
666 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
667 double x1
, y1
, x2
, y2
;
669 wxNode
*node
= spline
->points
->First();
670 p
= (wxPoint
*)node
->Data();
676 p
= (wxPoint
*)node
->Data();
680 cx1
= (double)((x1
+ x2
) / 2);
681 cy1
= (double)((y1
+ y2
) / 2);
682 cx2
= (double)((cx1
+ x2
) / 2);
683 cy2
= (double)((cy1
+ y2
) / 2);
685 wx_spline_add_point(x1
, y1
);
687 while ((node
= node
->Next()) != NULL
)
689 p
= (wxPoint
*)node
->Data();
694 cx4
= (double)(x1
+ x2
) / 2;
695 cy4
= (double)(y1
+ y2
) / 2;
696 cx3
= (double)(x1
+ cx4
) / 2;
697 cy3
= (double)(y1
+ cy4
) / 2;
699 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
703 cx2
= (double)(cx1
+ x2
) / 2;
704 cy2
= (double)(cy1
+ y2
) / 2;
707 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
708 wx_spline_add_point(x2
, y2
);
710 wx_spline_draw_point_array(dc
);
714 /********************* CURVES FOR SPLINES *****************************
716 The following spline drawing routine is from
718 "An Algorithm for High-Speed Curve Generation"
719 by George Merrill Chaikin,
720 Computer Graphics and Image Processing, 3, Academic Press,
725 "On Chaikin's Algorithm" by R. F. Riesenfeld,
726 Computer Graphics and Image Processing, 4, Academic Press,
729 ***********************************************************************/
731 #define half(z1, z2) ((z1+z2)/2.0)
734 /* iterative version */
736 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
739 register double xmid
, ymid
;
740 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
743 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
745 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
746 xmid
= (double)half(x2
, x3
);
747 ymid
= (double)half(y2
, y3
);
748 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
749 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
750 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
751 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
753 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
754 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
755 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
756 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
762 /* utilities used by spline drawing routines */
765 typedef struct wx_spline_stack_struct
{
766 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
770 #define SPLINE_STACK_DEPTH 20
771 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
772 static Stack
*wx_stack_top
;
773 static int wx_stack_count
;
775 void wx_clear_stack()
777 wx_stack_top
= wx_spline_stack
;
781 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
783 wx_stack_top
->x1
= x1
;
784 wx_stack_top
->y1
= y1
;
785 wx_stack_top
->x2
= x2
;
786 wx_stack_top
->y2
= y2
;
787 wx_stack_top
->x3
= x3
;
788 wx_stack_top
->y3
= y3
;
789 wx_stack_top
->x4
= x4
;
790 wx_stack_top
->y4
= y4
;
795 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
796 double *x3
, double *y3
, double *x4
, double *y4
)
798 if (wx_stack_count
== 0)
802 *x1
= wx_stack_top
->x1
;
803 *y1
= wx_stack_top
->y1
;
804 *x2
= wx_stack_top
->x2
;
805 *y2
= wx_stack_top
->y2
;
806 *x3
= wx_stack_top
->x3
;
807 *y3
= wx_stack_top
->y3
;
808 *x4
= wx_stack_top
->x4
;
809 *y4
= wx_stack_top
->y4
;
813 static bool wx_spline_add_point(double x
, double y
)
815 wxPoint
*point
= new wxPoint
;
818 wx_spline_point_list
.Append((wxObject
*)point
);
822 static void wx_spline_draw_point_array(wxDC
*dc
)
824 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
825 wxNode
*node
= wx_spline_point_list
.First();
828 wxPoint
*point
= (wxPoint
*)node
->Data();
831 node
= wx_spline_point_list
.First();
835 wxSpline::wxSpline(wxList
*list
)
840 wxSpline::~wxSpline()
844 void wxSpline::DeletePoints()
846 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
848 wxPoint
*point
= (wxPoint
*)node
->Data();
856 #endif // wxUSE_SPLINES