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( wxCoord x
, wxCoord y
131 ,wxCoord width
, wxCoord 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( wxCoord x
194 bool wxDC::DoGetPixel(wxCoord x
, wxCoord y
, wxColour
*col
) const
200 void wxDC::DoCrossHair(wxCoord x
, wxCoord y
)
205 void wxDC::DoDrawLine(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
210 void wxDC::DoDrawArc( wxCoord x1
, wxCoord y1
211 ,wxCoord x2
, wxCoord y2
212 ,wxCoord xc
, wxCoord yc
218 void wxDC::DoDrawPoint(wxCoord x
, wxCoord y
)
223 void wxDC::DoDrawPolygon(int n
, wxPoint points
[]
224 ,wxCoord xoffset
, wxCoord yoffset
231 void wxDC::DoDrawLines( int n
, wxPoint points
[]
232 ,wxCoord xoffset
, wxCoord yoffset
238 void wxDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
243 void wxDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
244 ,wxCoord width
, wxCoord height
251 void wxDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
256 void wxDC::DoDrawEllipticArc( wxCoord x
267 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
)
272 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
273 ,wxCoord x
, wxCoord y
280 void wxDC::DoDrawText(const wxString
& text
, wxCoord x
, wxCoord y
)
285 void wxDC::DoDrawRotatedText(const wxString
& text
,
286 wxCoord x
, wxCoord y
,
293 DoDrawText(text, x, y);
298 wxFillLogFont(&lf, &m_font);
300 // GDI wants the angle in tenth of degree
301 long angle10 = (long)(angle * 10);
302 lf.lfEscapement = angle10;
303 lf. lfOrientation = angle10;
305 HFONT hfont = ::CreateFontIndirect(&lf);
308 wxLogLastError("CreateFont");
312 HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
314 DrawAnyText(text, x, y);
316 (void)::SelectObject(GetHdc(), hfontOld);
319 // call the bounding box by adding all four vertices of the rectangle
320 // containing the text to it (simpler and probably not slower than
321 // determining which of them is really topmost/leftmost/...)
323 GetTextExtent(text, &w, &h);
325 double rad = DegToRad(angle);
327 // "upper left" and "upper right"
328 CalcBoundingBox(x, y);
329 CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
330 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
332 // "bottom left" and "bottom right"
333 x += (wxCoord)(h*sin(rad));
334 y += (wxCoord)(h*cos(rad));
335 CalcBoundingBox(x, y);
336 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
341 // ---------------------------------------------------------------------------
343 // ---------------------------------------------------------------------------
345 void wxDC::SetPalette(const wxPalette
& palette
)
350 void wxDC::SetFont(const wxFont
& font
)
355 void wxDC::SetPen(const wxPen
& pen
)
359 void wxDC::SetBrush(const wxBrush
& brush
)
364 void wxDC::SetBackground(const wxBrush
& brush
)
369 void wxDC::SetBackgroundMode(int mode
)
374 void wxDC::SetLogicalFunction(int function
)
379 void wxDC::SetRop(WXHDC dc
)
381 if (!dc
|| m_logicalFunction
< 0)
385 // These may be wrong
386 switch (m_logicalFunction
)
388 // TODO: Figure this stuff out
389 // case wxXOR: c_rop = R2_XORPEN; break;
390 // case wxXOR: c_rop = R2_NOTXORPEN; break;
391 // case wxINVERT: c_rop = R2_NOT; break;
392 // case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
393 // case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
394 // case wxCLEAR: c_rop = R2_WHITE; break;
395 // case wxSET: c_rop = R2_BLACK; break;
396 // case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
397 // case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
398 // case wxAND: c_rop = R2_MASKPEN; break;
399 // case wxOR: c_rop = R2_MERGEPEN; break;
400 // case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
405 // c_rop = R2_COPYPEN;
408 // SetROP2((HDC) dc, c_rop);
411 bool wxDC::StartDoc(const wxString
& message
)
413 // We might be previewing, so return TRUE to let it continue.
421 void wxDC::StartPage()
429 // ---------------------------------------------------------------------------
431 // ---------------------------------------------------------------------------
433 wxCoord
wxDC::GetCharHeight() const
439 wxCoord
wxDC::GetCharWidth() const
445 void wxDC::DoGetTextExtent( const wxString
& string
449 ,wxCoord
* externalLeading
456 void wxDC::SetMapMode( int mode
)
461 void wxDC::SetUserScale(double x
, double y
)
466 SetMapMode(m_mappingMode
);
469 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
471 m_signX
= xLeftRight
? 1 : -1;
472 m_signY
= yBottomUp
? -1 : 1;
474 SetMapMode(m_mappingMode
);
477 void wxDC::SetSystemScale(double x
, double y
)
482 SetMapMode(m_mappingMode
);
485 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
490 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
495 // ---------------------------------------------------------------------------
496 // coordinates transformations
497 // ---------------------------------------------------------------------------
499 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
501 wxCoord new_x
= x
- m_deviceOriginX
;
503 return (wxCoord
)((double)(new_x
) / m_scaleX
+ 0.5) * m_signX
+ m_logicalOriginX
;
505 return (wxCoord
)((double)(new_x
) / m_scaleX
- 0.5) * m_signX
+ m_logicalOriginX
;
508 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
511 return (wxCoord
)((double)(x
) / m_scaleX
+ 0.5);
513 return (wxCoord
)((double)(x
) / m_scaleX
- 0.5);
516 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
518 wxCoord new_y
= y
- m_deviceOriginY
;
520 return (wxCoord
)((double)(new_y
) / m_scaleY
+ 0.5) * m_signY
+ m_logicalOriginY
;
522 return (wxCoord
)((double)(new_y
) / m_scaleY
- 0.5) * m_signY
+ m_logicalOriginY
;
525 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
528 return (wxCoord
)((double)(y
) / m_scaleY
+ 0.5);
530 return (wxCoord
)((double)(y
) / m_scaleY
- 0.5);
533 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
535 wxCoord new_x
= x
- m_logicalOriginX
;
537 return (wxCoord
)((double)(new_x
) * m_scaleX
+ 0.5) * m_signX
+ m_deviceOriginX
;
539 return (wxCoord
)((double)(new_x
) * m_scaleX
- 0.5) * m_signX
+ m_deviceOriginX
;
542 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
545 return (wxCoord
)((double)(x
) * m_scaleX
+ 0.5);
547 return (wxCoord
)((double)(x
) * m_scaleX
- 0.5);
550 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
552 wxCoord new_y
= y
- m_logicalOriginY
;
554 return (wxCoord
)((double)(new_y
) * m_scaleY
+ 0.5) * m_signY
+ m_deviceOriginY
;
556 return (wxCoord
)((double)(new_y
) * m_scaleY
- 0.5) * m_signY
+ m_deviceOriginY
;
559 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
562 return (wxCoord
)((double)(y
) * m_scaleY
+ 0.5);
564 return (wxCoord
)((double)(y
) * m_scaleY
- 0.5);
567 // ---------------------------------------------------------------------------
569 // ---------------------------------------------------------------------------
571 bool wxDC::DoBlit( wxCoord xdest
586 void wxDC::DoGetSize( int* width
, int* height
) const
591 void wxDC::DoGetSizeMM( int* width
, int* height
) const
596 wxSize
wxDC::GetPPI() const
601 return (wxSize(x
,y
));
604 void wxDC::SetLogicalScale( double x
, double y
)
609 #if WXWIN_COMPATIBILITY
610 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
611 float *descent
, float *externalLeading
,
612 wxFont
*theFont
, bool use16bit
) const
614 wxCoord x1
, y1
, descent1
, externalLeading1
;
615 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
620 *externalLeading
= externalLeading1
;
624 // ---------------------------------------------------------------------------
625 // spline drawing code
626 // ---------------------------------------------------------------------------
630 class wxSpline
: public wxObject
636 wxSpline(wxList
*list
);
639 // Doesn't delete points
643 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
645 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
646 double a3
, double b3
, double a4
, double b4
);
647 void wx_clear_stack();
648 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
649 double *y3
, double *x4
, double *y4
);
650 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
651 double x4
, double y4
);
652 static bool wx_spline_add_point(double x
, double y
);
653 static void wx_spline_draw_point_array(wxDC
*dc
);
654 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
656 void wxDC::DoDrawSpline(wxList
*list
)
658 wxSpline
spline(list
);
660 wx_draw_open_spline(this, &spline
);
663 wxList wx_spline_point_list
;
665 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
668 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
669 double x1
, y1
, x2
, y2
;
671 wxNode
*node
= spline
->points
->First();
672 p
= (wxPoint
*)node
->Data();
678 p
= (wxPoint
*)node
->Data();
682 cx1
= (double)((x1
+ x2
) / 2);
683 cy1
= (double)((y1
+ y2
) / 2);
684 cx2
= (double)((cx1
+ x2
) / 2);
685 cy2
= (double)((cy1
+ y2
) / 2);
687 wx_spline_add_point(x1
, y1
);
689 while ((node
= node
->Next()) != NULL
)
691 p
= (wxPoint
*)node
->Data();
696 cx4
= (double)(x1
+ x2
) / 2;
697 cy4
= (double)(y1
+ y2
) / 2;
698 cx3
= (double)(x1
+ cx4
) / 2;
699 cy3
= (double)(y1
+ cy4
) / 2;
701 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
705 cx2
= (double)(cx1
+ x2
) / 2;
706 cy2
= (double)(cy1
+ y2
) / 2;
709 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
710 wx_spline_add_point(x2
, y2
);
712 wx_spline_draw_point_array(dc
);
716 /********************* CURVES FOR SPLINES *****************************
718 The following spline drawing routine is from
720 "An Algorithm for High-Speed Curve Generation"
721 by George Merrill Chaikin,
722 Computer Graphics and Image Processing, 3, Academic Press,
727 "On Chaikin's Algorithm" by R. F. Riesenfeld,
728 Computer Graphics and Image Processing, 4, Academic Press,
731 ***********************************************************************/
733 #define half(z1, z2) ((z1+z2)/2.0)
736 /* iterative version */
738 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
741 register double xmid
, ymid
;
742 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
745 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
747 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
748 xmid
= (double)half(x2
, x3
);
749 ymid
= (double)half(y2
, y3
);
750 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
751 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
752 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
753 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
755 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
756 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
757 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
758 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
764 /* utilities used by spline drawing routines */
767 typedef struct wx_spline_stack_struct
{
768 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
772 #define SPLINE_STACK_DEPTH 20
773 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
774 static Stack
*wx_stack_top
;
775 static int wx_stack_count
;
777 void wx_clear_stack()
779 wx_stack_top
= wx_spline_stack
;
783 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
785 wx_stack_top
->x1
= x1
;
786 wx_stack_top
->y1
= y1
;
787 wx_stack_top
->x2
= x2
;
788 wx_stack_top
->y2
= y2
;
789 wx_stack_top
->x3
= x3
;
790 wx_stack_top
->y3
= y3
;
791 wx_stack_top
->x4
= x4
;
792 wx_stack_top
->y4
= y4
;
797 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
798 double *x3
, double *y3
, double *x4
, double *y4
)
800 if (wx_stack_count
== 0)
804 *x1
= wx_stack_top
->x1
;
805 *y1
= wx_stack_top
->y1
;
806 *x2
= wx_stack_top
->x2
;
807 *y2
= wx_stack_top
->y2
;
808 *x3
= wx_stack_top
->x3
;
809 *y3
= wx_stack_top
->y3
;
810 *x4
= wx_stack_top
->x4
;
811 *y4
= wx_stack_top
->y4
;
815 static bool wx_spline_add_point(double x
, double y
)
817 wxPoint
*point
= new wxPoint
;
820 wx_spline_point_list
.Append((wxObject
*)point
);
824 static void wx_spline_draw_point_array(wxDC
*dc
)
826 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
827 wxNode
*node
= wx_spline_point_list
.First();
830 wxPoint
*point
= (wxPoint
*)node
->Data();
833 node
= wx_spline_point_list
.First();
837 wxSpline::wxSpline(wxList
*list
)
842 wxSpline::~wxSpline()
846 void wxSpline::DeletePoints()
848 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
850 wxPoint
*point
= (wxPoint
*)node
->Data();
858 #endif // wxUSE_SPLINES