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 // usually this is defined in math.h
47 static const double M_PI
= 3.14159265358979323846;
50 // ---------------------------------------------------------------------------
52 // ---------------------------------------------------------------------------
54 // convert degrees to radians
55 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
59 , int nForegroundColour
64 vCbnd
.lColor
= nForegroundColour
;
65 ::GpiSetAttrs( hPS
// presentation-space handle
66 ,PRIM_CHAR
// Char primitive.
67 ,CBB_COLOR
// sets color.
69 ,&vCbnd
// buffer for attributes.
80 ::GpiQueryAttrs( hPS
// presentation-space handle
81 ,PRIM_CHAR
// Char primitive.
82 ,CBB_BACK_COLOR
// Background color.
83 ,&vCbnd
// buffer for attributes.
85 return vCbnd
.lBackColor
;
91 , int nBackgroundColour
97 rc
= QueryTextBkColor(hPS
);
99 vCbnd
.lBackColor
= nBackgroundColour
;
100 ::GpiSetAttrs(hPS
, // presentation-space handle
101 PRIM_CHAR
, // Char primitive.
102 CBB_BACK_COLOR
, // sets color.
104 &vCbnd
// buffer for attributes.
111 , int nBackgroundMode
114 if(nBackgroundMode
== wxTRANSPARENT
)
119 // the background of the primitive takes over whatever is underneath.
126 // ===========================================================================
128 // ===========================================================================
130 // ---------------------------------------------------------------------------
132 // ---------------------------------------------------------------------------
149 m_bIsPaintTime
= FALSE
;// True at Paint Time
157 // This will select current objects out of the DC,
158 // which is what you have to do before deleting the
160 void wxDC::SelectOldObjects(WXHDC dc
)
166 // ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
167 if (m_vSelectedBitmap
.Ok())
169 m_vSelectedBitmap
.SetSelectedInto(NULL
);
175 // ::SelectObject((HDC) dc, (HPEN) m_oldPen);
180 // ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
185 // ::SelectObject((HDC) dc, (HFONT) m_oldFont);
190 // ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE);
195 m_brush
= wxNullBrush
;
197 m_palette
= wxNullPalette
;
199 m_backgroundBrush
= wxNullBrush
;
200 m_vSelectedBitmap
= wxNullBitmap
;
203 // ---------------------------------------------------------------------------
205 // ---------------------------------------------------------------------------
207 #define DO_SET_CLIPPING_BOX() \
211 GetClipBox(GetHdc(), &rect); \
213 m_clipX1 = (wxCoord) XDEV2LOG(rect.left); \
214 m_clipY1 = (wxCoord) YDEV2LOG(rect.top); \
215 m_clipX2 = (wxCoord) XDEV2LOG(rect.right); \
216 m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom); \
219 void wxDC::DoSetClippingRegion( wxCoord x
, wxCoord y
220 ,wxCoord width
, wxCoord height
226 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
)
231 void wxDC::DestroyClippingRegion(void)
236 // ---------------------------------------------------------------------------
237 // query capabilities
238 // ---------------------------------------------------------------------------
240 bool wxDC::CanDrawBitmap() const
245 bool wxDC::CanGetTextExtent() const
247 // What sort of display is it?
248 int technology
= 0; // TODO: ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
250 // TODO: return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
254 int wxDC::GetDepth() const
260 // ---------------------------------------------------------------------------
262 // ---------------------------------------------------------------------------
269 void wxDC::DoFloodFill(
272 , const wxColour
& rCol
280 vPtlPos
.x
= vX
; // Loads x-coordinate
281 vPtlPos
.y
= vY
; // Loads y-coordinate
282 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
283 lColor
= rCol
.GetPixel();
284 lOptions
= FF_BOUNDARY
;
285 if(wxFLOOD_SURFACE
== nStyle
)
286 lOptions
= FF_SURFACE
;
288 ::GpiFloodFill(m_hPS
, lOptions
, lColor
);
291 bool wxDC::DoGetPixel(
302 lColor
= ::GpiSetPel(m_hPS
, &vPoint
);
310 void wxDC::DoCrossHair(wxCoord x
, wxCoord y
)
315 void wxDC::DoDrawLine(
328 // ::GpiSetColor(m_hPS,CLR_RED); //DEbug
329 ::GpiMove(m_hPS
, &vPoint
[0]);
330 ::GpiLine(m_hPS
, &vPoint
[1]);
333 //////////////////////////////////////////////////////////////////////////////
334 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
335 // and ending at (x2, y2). The current pen is used for the outline and the
336 // current brush for filling the shape. The arc is drawn in an anticlockwise
337 // direction from the start point to the end point.
338 //////////////////////////////////////////////////////////////////////////////
339 void wxDC::DoDrawArc(
349 POINTL vPtlArc
[2]; // Structure for current position
358 ARCPARAMS vArcp
; // Structure for arc parameters
360 if((vX1
== vXc
&& vY1
== vXc
) || (vX2
== vXc
&& vY2
== vXc
))
361 return; // Draw point ??
362 dRadius
= 0.5 * ( hypot( (double)(vY1
- vYc
)
365 hypot( (double)(vY2
- vYc
)
370 dAngl1
= atan2( (double)(vY1
- vYc
)
373 dAngl2
= atan2( (double)(vY2
- vYc
)
380 // GpiPointArc can't draw full arc
382 if(dAngl2
== dAngl1
|| (vX1
== vX2
&& vY1
== vY2
) )
387 dAnglmid
= (dAngl1
+ dAngl2
)/2. + M_PI
;
388 vXm
= vXc
+ dRadius
* cos(dAnglmid
);
389 vYm
= vYc
+ dRadius
* sin(dAnglmid
);
410 dAnglmid
= (dAngl1
+ dAngl2
)/2.;
411 vXm
= vXc
+ dRadius
* cos(dAnglmid
);
412 vYm
= vYc
+ dRadius
* sin(dAnglmid
);
415 // Ellipse main axis (r,q), (p,s) with center at (0,0) */
421 ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default
423 vPtlPos
.x
= vX1
; // Loads x-coordinate
424 vPtlPos
.y
= vY1
; // Loads y-coordinate
425 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
430 ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc
433 void wxDC::DoDrawCheckMark(
444 vPoint
[1].x
= vX1
+ vWidth
;
445 vPoint
[1].y
= vY1
+ vHeight
;
447 ::GpiMove(m_hPS
, &vPoint
[0]);
448 ::GpiBox( m_hPS
// handle to a presentation space
449 ,DRO_OUTLINE
// draw the box outline ? or ?
450 ,&vPoint
[1] // address of the corner
451 ,0L // horizontal corner radius
452 ,0L // vertical corner radius
454 if(vWidth
> 4 && vHeight
> 4)
458 vPoint
[0].x
+= 2; vPoint
[0].y
+= 2;
459 vPoint
[1].x
-= 2; vPoint
[1].y
-= 2;
460 ::GpiMove(m_hPS
, &vPoint
[0]);
461 ::GpiLine(m_hPS
, &vPoint
[1]);
463 vPoint
[0].x
= vPoint
[1].x
;
465 ::GpiMove(m_hPS
, &vPoint
[0]);
466 ::GpiLine(m_hPS
, &vPoint
[1]);
470 void wxDC::DoDrawPoint(
479 ::GpiSetPel(m_hPS
, &vPoint
);
482 void wxDC::DoDrawPolygon(
490 ULONG ulCount
= 1; // Number of polygons.
491 POLYGON vPlgn
; // polygon.
492 ULONG flOptions
= 0L; // Drawing options.
494 //////////////////////////////////////////////////////////////////////////////
495 // This contains fields of option bits... to draw boundary lines as well as
496 // the area interior.
498 // Drawing boundary lines:
499 // POLYGON_NOBOUNDARY Does not draw boundary lines.
500 // POLYGON_BOUNDARY Draws boundary lines (the default).
502 // Construction of the area interior:
503 // POLYGON_ALTERNATE Constructs interior in alternate mode
505 // POLYGON_WINDING Constructs interior in winding mode.
506 //////////////////////////////////////////////////////////////////////////////
508 ULONG flModel
= 0L; // Drawing model.
510 //////////////////////////////////////////////////////////////////////////////
512 // POLYGON_INCL Fill is inclusive of bottom right (the default).
513 // POLYGON_EXCL Fill is exclusive of bottom right.
514 // This is provided to aid migration from other graphics models.
515 //////////////////////////////////////////////////////////////////////////////
517 LONG lHits
= 0L; // Correlation/error indicator.
520 int nIsTRANSPARENT
= 0;
521 LONG lBorderColor
= 0L;
524 lBorderColor
= m_pen
.GetColour().GetPixel();
525 lColor
= m_brush
.GetColour().GetPixel();
526 if(m_brush
.GetStyle() == wxTRANSPARENT
)
530 vPlgn
.aPointl
= (POINTL
*) calloc( n
+ 1
532 ); // well, new will call malloc
534 for(i
= 0; i
< n
; i
++)
536 vPlgn
.aPointl
[i
].x
= vPoints
[i
].x
; // +xoffset;
537 vPlgn
.aPointl
[i
].y
= vPoints
[i
].y
; // +yoffset;
539 flModel
= POLYGON_BOUNDARY
;
540 if(nFillStyle
== wxWINDING_RULE
)
541 flModel
|= POLYGON_WINDING
;
543 flModel
|= POLYGON_ALTERNATE
;
548 ::GpiSetColor(m_hPS
, lBorderColor
);
549 ::GpiMove(m_hPS
, &vPoint
);
550 lHits
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
);
554 void wxDC::DoDrawLines(
564 vPoint
.x
= vPoints
[0].x
+ vXoffset
;
565 vPoint
.y
= vPoints
[0].y
+ vYoffset
;
566 ::GpiMove(m_hPS
, &vPoint
);
568 LONG lBorderColor
= m_pen
.GetColour().GetPixel();
570 ::GpiSetColor(m_hPS
, lBorderColor
);
571 for(i
= 1; i
< n
; i
++)
573 vPoint
.x
= vPoints
[0].x
+ vXoffset
;
574 vPoint
.y
= vPoints
[0].y
+ vYoffset
;
575 ::GpiLine(m_hPS
, &vPoint
);
579 void wxDC::DoDrawRectangle(
590 int nIsTRANSPARENT
= 0;
594 vPoint
[1].x
= vX
+ vWidth
;
595 vPoint
[1].y
= vY
- vHeight
; //mustdie !!! ??
596 ::GpiMove(m_hPS
, &vPoint
[0]);
597 lColor
= m_brush
.GetColour().GetPixel();
598 lBorderColor
= m_pen
.GetColour().GetPixel();
599 if (m_brush
.GetStyle() == wxTRANSPARENT
)
601 if(lColor
== lBorderColor
|| nIsTRANSPARENT
)
603 lControl
= DRO_OUTLINEFILL
; //DRO_FILL;
604 if(m_brush
.GetStyle() == wxTRANSPARENT
)
605 lControl
= DRO_OUTLINE
;
607 //EK ::GpiSetColor(m_hPS,lBorderColor);
608 ::GpiSetColor(m_hPS
,CLR_GREEN
);
609 ::GpiBox( m_hPS
// handle to a presentation space
610 ,lControl
// draw the box outline ? or ?
611 ,&vPoint
[1] // address of the corner
612 ,0L // horizontal corner radius
613 ,0L // vertical corner radius
618 lControl
= DRO_OUTLINE
;
641 void wxDC::DoDrawRoundedRectangle(
654 vPoint
[1].x
= vX
+ vWidth
;
655 vPoint
[1].y
= vY
+ vHeight
;
656 ::GpiMove(m_hPS
, &vPoint
[0]);
658 lControl
= DRO_OUTLINEFILL
; //DRO_FILL;
659 if (m_brush
.GetStyle() == wxTRANSPARENT
)
660 lControl
= DRO_OUTLINE
;
661 ::GpiBox( m_hPS
// handle to a presentation space
662 ,DRO_OUTLINE
// draw the box outline ? or ?
663 ,&vPoint
[1] // address of the corner
664 ,(LONG
)dRadius
// horizontal corner radius
665 ,(LONG
)dRadius
// vertical corner radius
669 // Draw Ellipse within box (x,y) - (x+width, y+height)
670 void wxDC::DoDrawEllipse(
677 POINTL vPtlPos
; // Structure for current position
678 FIXED vFxMult
; // Multiplier for ellipse
679 ARCPARAMS vArcp
; // Structure for arc parameters
682 vArcp
.lQ
= vHeight
/2;
685 ::GpiSetArcParams( m_hPS
687 ); // Sets parameters to default
688 vPtlPos
.x
= vX
+ vWidth
/2; // Loads x-coordinate
689 vPtlPos
.y
= vY
+ vHeight
/2; // Loads y-coordinate
692 ); // Sets current position
693 vFxMult
= MAKEFIXED(1, 0); /* Sets multiplier */
696 // DRO_FILL, DRO_OTLINEFILL - where to get
701 ); // Draws full arc with center at current position
704 void wxDC::DoDrawEllipticArc(
713 POINTL vPtlPos
; // Structure for current position
714 FIXED vFxMult
; // Multiplier for ellipse
715 ARCPARAMS vArcp
; // Structure for arc parameters
717 FIXED vFSweepa
; // Start angle, sweep angle
722 dFractPart
= modf(dSa
,&dIntPart
);
723 vFSa
= MAKEFIXED((int)dIntPart
, (int)(dFractPart
* 0xffff) );
724 dFractPart
= modf(dEa
- dSa
, &dIntPart
);
725 vFSweepa
= MAKEFIXED((int)dIntPart
, (int)(dFractPart
* 0xffff) );
728 // Ellipse main axis (r,q), (p,s) with center at (0,0)
731 vArcp
.lQ
= vHeight
/2;
734 ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default
735 vPtlPos
.x
= vX
+ vWidth
/2 * (1. + cos(DegToRad(dSa
))); // Loads x-coordinate
736 vPtlPos
.y
= vY
+ vHeight
/2 * (1. + sin(DegToRad(dSa
))); // Loads y-coordinate
737 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
740 // May be not to the center ?
742 vPtlPos
.x
= vX
+ vWidth
/2 ; // Loads x-coordinate
743 vPtlPos
.y
= vY
+ vHeight
/2; // Loads y-coordinate
744 vFxMult
= MAKEFIXED(1, 0); // Sets multiplier
747 // DRO_FILL, DRO_OTLINEFILL - where to get
749 ::GpiPartialArc( m_hPS
757 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
)
762 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
763 ,wxCoord x
, wxCoord y
770 void wxDC::DoDrawText(
771 const wxString
& rsText
782 void wxDC::DrawAnyText(
783 const wxString
& rsText
788 int nOldBackground
= 0;
793 // prepare for drawing the text
797 // Set text color attributes
799 if (m_textForegroundColour
.Ok())
802 ,(int)m_textForegroundColour
.GetPixel()
806 if (m_textBackgroundColour
.Ok())
808 nOldBackground
= SetTextBkColor( m_hPS
809 ,(int)m_textBackgroundColour
.GetPixel()
818 lHits
= ::GpiCharStringAt( m_hPS
825 wxLogLastError(wxT("TextOut"));
829 // Restore the old parameters (text foreground colour may be left because
830 // it never is set to anything else, but background should remain
831 // transparent even if we just drew an opaque string)
833 if (m_textBackgroundColour
.Ok())
834 SetTextBkColor( m_hPS
842 void wxDC::DoDrawRotatedText(
843 const wxString
& rsText
861 DoDrawText(text, x, y);
866 wxFillLogFont(&lf, &m_font);
868 // GDI wants the angle in tenth of degree
869 long angle10 = (long)(angle * 10);
870 lf.lfEscapement = angle10;
871 lf. lfOrientation = angle10;
873 HFONT hfont = ::CreateFontIndirect(&lf);
876 wxLogLastError("CreateFont");
880 HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
882 DrawAnyText(text, x, y);
884 (void)::SelectObject(GetHdc(), hfontOld);
887 // call the bounding box by adding all four vertices of the rectangle
888 // containing the text to it (simpler and probably not slower than
889 // determining which of them is really topmost/leftmost/...)
891 GetTextExtent(text, &w, &h);
893 double rad = DegToRad(angle);
895 // "upper left" and "upper right"
896 CalcBoundingBox(x, y);
897 CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
898 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
900 // "bottom left" and "bottom right"
901 x += (wxCoord)(h*sin(rad));
902 y += (wxCoord)(h*cos(rad));
903 CalcBoundingBox(x, y);
904 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
909 // ---------------------------------------------------------------------------
911 // ---------------------------------------------------------------------------
913 void wxDC::SetPalette(const wxPalette
& palette
)
923 // Set the old object temporarily, in case the assignment deletes an object
924 // that's not yet selected out.
928 // ::SelectObject(GetHdc(), (HFONT) m_hOldFont);
937 // ::SelectObject(GetHdc(), (HFONT) m_hOldFont);
941 if (m_font
.Ok() && m_font
.GetResourceHandle())
943 HFONT hFont
= (HFONT
)0; //::SelectObject(GetHdc(), (HFONT) m_font.GetResourceHandle());
944 if (hFont
== (HFONT
) NULL
)
946 wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont."));
949 m_hOldFont
= (WXHFONT
) hFont
;
957 wxCHECK_RET( Ok(), wxT("invalid window dc") );
965 int nWidth
= m_pen
.GetWidth();
974 ( fabs((double) XLOG2DEVREL(nWidth
)) +
975 fabs((double) YLOG2DEVREL(nWidth
))
979 wxColour vColor
= m_pen
.GetColour();
986 int nStyle
= m_pen
.GetStyle();
988 nLinetype
= LINETYPE_DEFAULT
;
992 nLinetype
= LINETYPE_DOT
;
996 nLinetype
= LINETYPE_LONGDASH
;
1000 nLinetype
= LINETYPE_SHORTDASH
;
1004 nLinetype
= LINETYPE_DASHDOT
;
1008 nLinetype
= LINETYPE_INVISIBLE
;
1012 nLinetype
= LINETYPE_SOLID
;
1015 ::GpiSetLineType( m_hPS
1019 nWidth
= m_pen
.GetWidth();
1020 ::GpiSetLineWidth( m_hPS
1027 void wxDC::SetBrush(
1028 const wxBrush
& rBrush
1034 void wxDC::SetBackground(const wxBrush
& brush
)
1039 void wxDC::SetBackgroundMode(
1043 m_backgroundMode
= nMode
;
1046 void wxDC::SetLogicalFunction(int function
)
1051 void wxDC::SetRop(WXHDC dc
)
1053 if (!dc
|| m_logicalFunction
< 0)
1057 // These may be wrong
1058 switch (m_logicalFunction
)
1060 // TODO: Figure this stuff out
1061 // case wxXOR: c_rop = R2_XORPEN; break;
1062 // case wxXOR: c_rop = R2_NOTXORPEN; break;
1063 // case wxINVERT: c_rop = R2_NOT; break;
1064 // case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
1065 // case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
1066 // case wxCLEAR: c_rop = R2_WHITE; break;
1067 // case wxSET: c_rop = R2_BLACK; break;
1068 // case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
1069 // case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
1070 // case wxAND: c_rop = R2_MASKPEN; break;
1071 // case wxOR: c_rop = R2_MERGEPEN; break;
1072 // case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
1077 // c_rop = R2_COPYPEN;
1080 // SetROP2((HDC) dc, c_rop);
1083 bool wxDC::StartDoc(const wxString
& message
)
1085 // We might be previewing, so return TRUE to let it continue.
1093 void wxDC::StartPage()
1097 void wxDC::EndPage()
1101 // ---------------------------------------------------------------------------
1103 // ---------------------------------------------------------------------------
1105 wxCoord
wxDC::GetCharHeight() const
1111 wxCoord
wxDC::GetCharWidth() const
1117 void wxDC::DoGetTextExtent(
1118 const wxString
& rsString
1121 , wxCoord
* pvDescent
1122 , wxCoord
* pvExternalLeading
1126 POINTL avPoint
[TXTBOX_COUNT
];
1131 FONTMETRICS vFM
; // metrics structure
1134 ERRORID vErrorCode
; // last error id code
1135 wxFont
* pFontToUse
= (wxFont
*)pTheFont
;
1138 pFontToUse
= (wxFont
*)&m_font
;
1139 l
= rsString
.length();
1140 pStr
= (PCH
) rsString
.c_str();
1143 // In world coordinates.
1145 bRc
= ::GpiQueryTextBox( m_hPS
1148 ,TXTBOX_COUNT
// return maximum information
1149 ,avPoint
// array of coordinates points
1153 vErrorCode
= ::WinGetLastError(wxGetInstance());
1156 vPtMin
.x
= avPoint
[0].x
;
1157 vPtMax
.x
= avPoint
[0].x
;
1158 vPtMin
.y
= avPoint
[0].y
;
1159 vPtMax
.y
= avPoint
[0].y
;
1160 for (i
= 1; i
< 4; i
++)
1162 if(vPtMin
.x
> avPoint
[i
].x
) vPtMin
.x
= avPoint
[i
].x
;
1163 if(vPtMin
.y
> avPoint
[i
].y
) vPtMin
.y
= avPoint
[i
].y
;
1164 if(vPtMax
.x
< avPoint
[i
].x
) vPtMax
.x
= avPoint
[i
].x
;
1165 if(vPtMax
.y
< avPoint
[i
].y
) vPtMax
.y
= avPoint
[i
].y
;
1167 ::GpiQueryFontMetrics( m_hPS
1168 ,sizeof(FONTMETRICS
)
1173 *pvX
= (wxCoord
)(vPtMax
.x
- vPtMin
.x
+ 1);
1175 *pvY
= (wxCoord
)(vPtMax
.y
- vPtMin
.y
+ 1);
1177 *pvDescent
= vFM
.lMaxDescender
;
1178 if (pvExternalLeading
)
1179 *pvExternalLeading
= vFM
.lExternalLeading
;
1182 void wxDC::SetMapMode( int mode
)
1187 void wxDC::SetUserScale(double x
, double y
)
1192 SetMapMode(m_mappingMode
);
1195 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1197 m_signX
= xLeftRight
? 1 : -1;
1198 m_signY
= yBottomUp
? -1 : 1;
1200 SetMapMode(m_mappingMode
);
1203 void wxDC::SetSystemScale(double x
, double y
)
1208 SetMapMode(m_mappingMode
);
1211 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
1216 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
1221 // ---------------------------------------------------------------------------
1222 // coordinates transformations
1223 // ---------------------------------------------------------------------------
1225 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
1227 return (wxCoord
) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1230 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
1232 return (wxCoord
) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1235 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
1237 return (wxCoord
) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1240 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
1242 return (wxCoord
) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1245 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
1247 return (wxCoord
) ((x
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1250 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
1252 return (wxCoord
) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1255 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
1257 return (wxCoord
) ((y
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1260 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
1262 return (wxCoord
) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1265 // ---------------------------------------------------------------------------
1267 // ---------------------------------------------------------------------------
1269 bool wxDC::DoBlit( wxCoord xdest
1284 void wxDC::DoGetSize( int* width
, int* height
) const
1289 void wxDC::DoGetSizeMM( int* width
, int* height
) const
1294 wxSize
wxDC::GetPPI() const
1299 return (wxSize(x
,y
));
1302 void wxDC::SetLogicalScale( double x
, double y
)
1307 #if WXWIN_COMPATIBILITY
1308 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1309 float *descent
, float *externalLeading
,
1310 wxFont
*theFont
, bool use16bit
) const
1312 wxCoord x1
, y1
, descent1
, externalLeading1
;
1313 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1316 *descent
= descent1
;
1317 if (externalLeading
)
1318 *externalLeading
= externalLeading1
;
1322 // ---------------------------------------------------------------------------
1323 // spline drawing code
1324 // ---------------------------------------------------------------------------
1328 class wxSpline
: public wxObject
1334 wxSpline(wxList
*list
);
1335 void DeletePoints();
1337 // Doesn't delete points
1341 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1343 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1344 double a3
, double b3
, double a4
, double b4
);
1345 void wx_clear_stack();
1346 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1347 double *y3
, double *x4
, double *y4
);
1348 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1349 double x4
, double y4
);
1350 static bool wx_spline_add_point(double x
, double y
);
1351 static void wx_spline_draw_point_array(wxDC
*dc
);
1352 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1354 void wxDC::DoDrawSpline(wxList
*list
)
1356 wxSpline
spline(list
);
1358 wx_draw_open_spline(this, &spline
);
1361 wxList wx_spline_point_list
;
1363 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1366 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1367 double x1
, y1
, x2
, y2
;
1369 wxNode
*node
= spline
->points
->First();
1370 p
= (wxPoint
*)node
->Data();
1375 node
= node
->Next();
1376 p
= (wxPoint
*)node
->Data();
1380 cx1
= (double)((x1
+ x2
) / 2);
1381 cy1
= (double)((y1
+ y2
) / 2);
1382 cx2
= (double)((cx1
+ x2
) / 2);
1383 cy2
= (double)((cy1
+ y2
) / 2);
1385 wx_spline_add_point(x1
, y1
);
1387 while ((node
= node
->Next()) != NULL
)
1389 p
= (wxPoint
*)node
->Data();
1394 cx4
= (double)(x1
+ x2
) / 2;
1395 cy4
= (double)(y1
+ y2
) / 2;
1396 cx3
= (double)(x1
+ cx4
) / 2;
1397 cy3
= (double)(y1
+ cy4
) / 2;
1399 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1403 cx2
= (double)(cx1
+ x2
) / 2;
1404 cy2
= (double)(cy1
+ y2
) / 2;
1407 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1408 wx_spline_add_point(x2
, y2
);
1410 wx_spline_draw_point_array(dc
);
1414 /********************* CURVES FOR SPLINES *****************************
1416 The following spline drawing routine is from
1418 "An Algorithm for High-Speed Curve Generation"
1419 by George Merrill Chaikin,
1420 Computer Graphics and Image Processing, 3, Academic Press,
1425 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1426 Computer Graphics and Image Processing, 4, Academic Press,
1429 ***********************************************************************/
1431 #define half(z1, z2) ((z1+z2)/2.0)
1434 /* iterative version */
1436 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1439 register double xmid
, ymid
;
1440 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1443 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1445 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1446 xmid
= (double)half(x2
, x3
);
1447 ymid
= (double)half(y2
, y3
);
1448 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1449 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1450 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1451 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1453 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1454 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1455 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1456 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1462 /* utilities used by spline drawing routines */
1465 typedef struct wx_spline_stack_struct
{
1466 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1470 #define SPLINE_STACK_DEPTH 20
1471 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1472 static Stack
*wx_stack_top
;
1473 static int wx_stack_count
;
1475 void wx_clear_stack()
1477 wx_stack_top
= wx_spline_stack
;
1481 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1483 wx_stack_top
->x1
= x1
;
1484 wx_stack_top
->y1
= y1
;
1485 wx_stack_top
->x2
= x2
;
1486 wx_stack_top
->y2
= y2
;
1487 wx_stack_top
->x3
= x3
;
1488 wx_stack_top
->y3
= y3
;
1489 wx_stack_top
->x4
= x4
;
1490 wx_stack_top
->y4
= y4
;
1495 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1496 double *x3
, double *y3
, double *x4
, double *y4
)
1498 if (wx_stack_count
== 0)
1502 *x1
= wx_stack_top
->x1
;
1503 *y1
= wx_stack_top
->y1
;
1504 *x2
= wx_stack_top
->x2
;
1505 *y2
= wx_stack_top
->y2
;
1506 *x3
= wx_stack_top
->x3
;
1507 *y3
= wx_stack_top
->y3
;
1508 *x4
= wx_stack_top
->x4
;
1509 *y4
= wx_stack_top
->y4
;
1513 static bool wx_spline_add_point(double x
, double y
)
1515 wxPoint
*point
= new wxPoint
;
1518 wx_spline_point_list
.Append((wxObject
*)point
);
1522 static void wx_spline_draw_point_array(wxDC
*dc
)
1524 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1525 wxNode
*node
= wx_spline_point_list
.First();
1528 wxPoint
*point
= (wxPoint
*)node
->Data();
1531 node
= wx_spline_point_list
.First();
1535 wxSpline::wxSpline(wxList
*list
)
1540 wxSpline::~wxSpline()
1544 void wxSpline::DeletePoints()
1546 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1548 wxPoint
*point
= (wxPoint
*)node
->Data();
1556 #endif // wxUSE_SPLINES