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 ::GpiQueryClipBox(m_hPS, &rect); \
213 m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft); \
214 m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop); \
215 m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight); \
216 m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \
219 void wxDC::DoSetClippingRegion(
229 vRect
.xLeft
= XLOG2DEV(x
);
230 vRect
.yTop
= YLOG2DEV(y
+ height
);
231 vRect
.xRight
= XLOG2DEV(x
+ width
);
232 vRect
.yBottom
= YLOG2DEV(y
);
233 ::GpiIntersectClipRectangle(m_hPS
, &vRect
);
234 DO_SET_CLIPPING_BOX()
235 } // end of wxDC::DoSetClippingRegion
237 void wxDC::DoSetClippingRegionAsRegion(
238 const wxRegion
& rRegion
241 wxCHECK_RET(rRegion
.GetHRGN(), wxT("invalid clipping region"));
245 ::GpiSetClipRegion( m_hPS
246 ,(HRGN
)rRegion
.GetHRGN()
249 DO_SET_CLIPPING_BOX()
250 } // end of wxDC::DoSetClippingRegionAsRegion
252 void wxDC::DestroyClippingRegion(void)
254 if (m_clipping
&& m_hPS
)
259 // TODO: this should restore the previous clipped region
260 // so that OnPaint processing works correctly, and
261 // the update doesn't get destroyed after the first
262 // DestroyClippingRegion
263 vRect
.xLeft
= XLOG2DEV(0);
264 vRect
.yTop
= YLOG2DEV(32000);
265 vRect
.xRight
= XLOG2DEV(32000);
266 vRect
.yBottom
= YLOG2DEV(0);
268 HRGN hRgn
= ::GpiCreateRegion(m_hPS
, 1, &vRect
);
270 ::GpiSetClipRegion(m_hPS
, hRgn
, &hRgnOld
);
273 } // end of wxDC::DestroyClippingRegion
275 // ---------------------------------------------------------------------------
276 // query capabilities
277 // ---------------------------------------------------------------------------
279 bool wxDC::CanDrawBitmap() const
284 bool wxDC::CanGetTextExtent() const
286 // What sort of display is it?
287 int technology
= 0; // TODO: ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
289 // TODO: return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
293 int wxDC::GetDepth() const
299 // ---------------------------------------------------------------------------
301 // ---------------------------------------------------------------------------
308 void wxDC::DoFloodFill(
311 , const wxColour
& rCol
319 vPtlPos
.x
= vX
; // Loads x-coordinate
320 vPtlPos
.y
= vY
; // Loads y-coordinate
321 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
322 lColor
= rCol
.GetPixel();
323 lOptions
= FF_BOUNDARY
;
324 if(wxFLOOD_SURFACE
== nStyle
)
325 lOptions
= FF_SURFACE
;
327 ::GpiFloodFill(m_hPS
, lOptions
, lColor
);
330 bool wxDC::DoGetPixel(
341 lColor
= ::GpiSetPel(m_hPS
, &vPoint
);
342 pCol
->Set((unsigned long)lColor
);
349 void wxDC::DoCrossHair(wxCoord x
, wxCoord y
)
354 void wxDC::DoDrawLine(
367 // ::GpiSetColor(m_hPS,CLR_RED); //DEbug
368 ::GpiMove(m_hPS
, &vPoint
[0]);
369 ::GpiLine(m_hPS
, &vPoint
[1]);
372 //////////////////////////////////////////////////////////////////////////////
373 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
374 // and ending at (x2, y2). The current pen is used for the outline and the
375 // current brush for filling the shape. The arc is drawn in an anticlockwise
376 // direction from the start point to the end point.
377 //////////////////////////////////////////////////////////////////////////////
378 void wxDC::DoDrawArc(
388 POINTL vPtlArc
[2]; // Structure for current position
397 ARCPARAMS vArcp
; // Structure for arc parameters
399 if((vX1
== vXc
&& vY1
== vXc
) || (vX2
== vXc
&& vY2
== vXc
))
400 return; // Draw point ??
401 dRadius
= 0.5 * ( hypot( (double)(vY1
- vYc
)
404 hypot( (double)(vY2
- vYc
)
409 dAngl1
= atan2( (double)(vY1
- vYc
)
412 dAngl2
= atan2( (double)(vY2
- vYc
)
419 // GpiPointArc can't draw full arc
421 if(dAngl2
== dAngl1
|| (vX1
== vX2
&& vY1
== vY2
) )
426 dAnglmid
= (dAngl1
+ dAngl2
)/2. + M_PI
;
427 vXm
= vXc
+ dRadius
* cos(dAnglmid
);
428 vYm
= vYc
+ dRadius
* sin(dAnglmid
);
449 dAnglmid
= (dAngl1
+ dAngl2
)/2.;
450 vXm
= vXc
+ dRadius
* cos(dAnglmid
);
451 vYm
= vYc
+ dRadius
* sin(dAnglmid
);
454 // Ellipse main axis (r,q), (p,s) with center at (0,0) */
460 ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default
462 vPtlPos
.x
= vX1
; // Loads x-coordinate
463 vPtlPos
.y
= vY1
; // Loads y-coordinate
464 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
469 ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc
472 void wxDC::DoDrawCheckMark(
483 vPoint
[1].x
= vX1
+ vWidth
;
484 vPoint
[1].y
= vY1
+ vHeight
;
486 ::GpiMove(m_hPS
, &vPoint
[0]);
487 ::GpiBox( m_hPS
// handle to a presentation space
488 ,DRO_OUTLINE
// draw the box outline ? or ?
489 ,&vPoint
[1] // address of the corner
490 ,0L // horizontal corner radius
491 ,0L // vertical corner radius
493 if(vWidth
> 4 && vHeight
> 4)
497 vPoint
[0].x
+= 2; vPoint
[0].y
+= 2;
498 vPoint
[1].x
-= 2; vPoint
[1].y
-= 2;
499 ::GpiMove(m_hPS
, &vPoint
[0]);
500 ::GpiLine(m_hPS
, &vPoint
[1]);
502 vPoint
[0].x
= vPoint
[1].x
;
504 ::GpiMove(m_hPS
, &vPoint
[0]);
505 ::GpiLine(m_hPS
, &vPoint
[1]);
509 void wxDC::DoDrawPoint(
518 ::GpiSetPel(m_hPS
, &vPoint
);
521 void wxDC::DoDrawPolygon(
529 ULONG ulCount
= 1; // Number of polygons.
530 POLYGON vPlgn
; // polygon.
531 ULONG flOptions
= 0L; // Drawing options.
533 //////////////////////////////////////////////////////////////////////////////
534 // This contains fields of option bits... to draw boundary lines as well as
535 // the area interior.
537 // Drawing boundary lines:
538 // POLYGON_NOBOUNDARY Does not draw boundary lines.
539 // POLYGON_BOUNDARY Draws boundary lines (the default).
541 // Construction of the area interior:
542 // POLYGON_ALTERNATE Constructs interior in alternate mode
544 // POLYGON_WINDING Constructs interior in winding mode.
545 //////////////////////////////////////////////////////////////////////////////
547 ULONG flModel
= 0L; // Drawing model.
549 //////////////////////////////////////////////////////////////////////////////
551 // POLYGON_INCL Fill is inclusive of bottom right (the default).
552 // POLYGON_EXCL Fill is exclusive of bottom right.
553 // This is provided to aid migration from other graphics models.
554 //////////////////////////////////////////////////////////////////////////////
556 LONG lHits
= 0L; // Correlation/error indicator.
559 int nIsTRANSPARENT
= 0;
560 LONG lBorderColor
= 0L;
563 lBorderColor
= m_pen
.GetColour().GetPixel();
564 lColor
= m_brush
.GetColour().GetPixel();
565 if(m_brush
.GetStyle() == wxTRANSPARENT
)
569 vPlgn
.aPointl
= (POINTL
*) calloc( n
+ 1
571 ); // well, new will call malloc
573 for(i
= 0; i
< n
; i
++)
575 vPlgn
.aPointl
[i
].x
= vPoints
[i
].x
; // +xoffset;
576 vPlgn
.aPointl
[i
].y
= vPoints
[i
].y
; // +yoffset;
578 flModel
= POLYGON_BOUNDARY
;
579 if(nFillStyle
== wxWINDING_RULE
)
580 flModel
|= POLYGON_WINDING
;
582 flModel
|= POLYGON_ALTERNATE
;
587 ::GpiSetColor(m_hPS
, lBorderColor
);
588 ::GpiMove(m_hPS
, &vPoint
);
589 lHits
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
);
593 void wxDC::DoDrawLines(
603 vPoint
.x
= vPoints
[0].x
+ vXoffset
;
604 vPoint
.y
= vPoints
[0].y
+ vYoffset
;
605 ::GpiMove(m_hPS
, &vPoint
);
607 LONG lBorderColor
= m_pen
.GetColour().GetPixel();
609 ::GpiSetColor(m_hPS
, lBorderColor
);
610 for(i
= 1; i
< n
; i
++)
612 vPoint
.x
= vPoints
[0].x
+ vXoffset
;
613 vPoint
.y
= vPoints
[0].y
+ vYoffset
;
614 ::GpiLine(m_hPS
, &vPoint
);
618 void wxDC::DoDrawRectangle(
629 int nIsTRANSPARENT
= 0;
633 vPoint
[1].x
= vX
+ vWidth
;
634 vPoint
[1].y
= vY
- vHeight
; //mustdie !!! ??
635 ::GpiMove(m_hPS
, &vPoint
[0]);
636 lColor
= m_brush
.GetColour().GetPixel();
637 lBorderColor
= m_pen
.GetColour().GetPixel();
638 if (m_brush
.GetStyle() == wxTRANSPARENT
)
640 if(lColor
== lBorderColor
|| nIsTRANSPARENT
)
642 lControl
= DRO_OUTLINEFILL
; //DRO_FILL;
643 if(m_brush
.GetStyle() == wxTRANSPARENT
)
644 lControl
= DRO_OUTLINE
;
646 //EK ::GpiSetColor(m_hPS,lBorderColor);
647 ::GpiSetColor(m_hPS
,CLR_GREEN
);
648 ::GpiBox( m_hPS
// handle to a presentation space
649 ,lControl
// draw the box outline ? or ?
650 ,&vPoint
[1] // address of the corner
651 ,0L // horizontal corner radius
652 ,0L // vertical corner radius
657 lControl
= DRO_OUTLINE
;
680 void wxDC::DoDrawRoundedRectangle(
693 vPoint
[1].x
= vX
+ vWidth
;
694 vPoint
[1].y
= vY
+ vHeight
;
695 ::GpiMove(m_hPS
, &vPoint
[0]);
697 lControl
= DRO_OUTLINEFILL
; //DRO_FILL;
698 if (m_brush
.GetStyle() == wxTRANSPARENT
)
699 lControl
= DRO_OUTLINE
;
700 ::GpiBox( m_hPS
// handle to a presentation space
701 ,DRO_OUTLINE
// draw the box outline ? or ?
702 ,&vPoint
[1] // address of the corner
703 ,(LONG
)dRadius
// horizontal corner radius
704 ,(LONG
)dRadius
// vertical corner radius
708 // Draw Ellipse within box (x,y) - (x+width, y+height)
709 void wxDC::DoDrawEllipse(
716 POINTL vPtlPos
; // Structure for current position
717 FIXED vFxMult
; // Multiplier for ellipse
718 ARCPARAMS vArcp
; // Structure for arc parameters
721 vArcp
.lQ
= vHeight
/2;
724 ::GpiSetArcParams( m_hPS
726 ); // Sets parameters to default
727 vPtlPos
.x
= vX
+ vWidth
/2; // Loads x-coordinate
728 vPtlPos
.y
= vY
+ vHeight
/2; // Loads y-coordinate
731 ); // Sets current position
732 vFxMult
= MAKEFIXED(1, 0); /* Sets multiplier */
735 // DRO_FILL, DRO_OTLINEFILL - where to get
740 ); // Draws full arc with center at current position
743 void wxDC::DoDrawEllipticArc(
752 POINTL vPtlPos
; // Structure for current position
753 FIXED vFxMult
; // Multiplier for ellipse
754 ARCPARAMS vArcp
; // Structure for arc parameters
756 FIXED vFSweepa
; // Start angle, sweep angle
761 dFractPart
= modf(dSa
,&dIntPart
);
762 vFSa
= MAKEFIXED((int)dIntPart
, (int)(dFractPart
* 0xffff) );
763 dFractPart
= modf(dEa
- dSa
, &dIntPart
);
764 vFSweepa
= MAKEFIXED((int)dIntPart
, (int)(dFractPart
* 0xffff) );
767 // Ellipse main axis (r,q), (p,s) with center at (0,0)
770 vArcp
.lQ
= vHeight
/2;
773 ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default
774 vPtlPos
.x
= vX
+ vWidth
/2 * (1. + cos(DegToRad(dSa
))); // Loads x-coordinate
775 vPtlPos
.y
= vY
+ vHeight
/2 * (1. + sin(DegToRad(dSa
))); // Loads y-coordinate
776 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
779 // May be not to the center ?
781 vPtlPos
.x
= vX
+ vWidth
/2 ; // Loads x-coordinate
782 vPtlPos
.y
= vY
+ vHeight
/2; // Loads y-coordinate
783 vFxMult
= MAKEFIXED(1, 0); // Sets multiplier
786 // DRO_FILL, DRO_OTLINEFILL - where to get
788 ::GpiPartialArc( m_hPS
796 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
)
801 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
802 ,wxCoord x
, wxCoord y
809 void wxDC::DoDrawText(
810 const wxString
& rsText
821 void wxDC::DrawAnyText(
822 const wxString
& rsText
827 int nOldBackground
= 0;
832 // prepare for drawing the text
836 // Set text color attributes
838 if (m_textForegroundColour
.Ok())
841 ,(int)m_textForegroundColour
.GetPixel()
845 if (m_textBackgroundColour
.Ok())
847 nOldBackground
= SetTextBkColor( m_hPS
848 ,(int)m_textBackgroundColour
.GetPixel()
857 lHits
= ::GpiCharStringAt( m_hPS
864 wxLogLastError(wxT("TextOut"));
868 // Restore the old parameters (text foreground colour may be left because
869 // it never is set to anything else, but background should remain
870 // transparent even if we just drew an opaque string)
872 if (m_textBackgroundColour
.Ok())
873 SetTextBkColor( m_hPS
881 void wxDC::DoDrawRotatedText(
882 const wxString
& rsText
900 DoDrawText(text, x, y);
905 wxFillLogFont(&lf, &m_font);
907 // GDI wants the angle in tenth of degree
908 long angle10 = (long)(angle * 10);
909 lf.lfEscapement = angle10;
910 lf. lfOrientation = angle10;
912 HFONT hfont = ::CreateFontIndirect(&lf);
915 wxLogLastError("CreateFont");
919 HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
921 DrawAnyText(text, x, y);
923 (void)::SelectObject(GetHdc(), hfontOld);
926 // call the bounding box by adding all four vertices of the rectangle
927 // containing the text to it (simpler and probably not slower than
928 // determining which of them is really topmost/leftmost/...)
930 GetTextExtent(text, &w, &h);
932 double rad = DegToRad(angle);
934 // "upper left" and "upper right"
935 CalcBoundingBox(x, y);
936 CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
937 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
939 // "bottom left" and "bottom right"
940 x += (wxCoord)(h*sin(rad));
941 y += (wxCoord)(h*cos(rad));
942 CalcBoundingBox(x, y);
943 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
948 // ---------------------------------------------------------------------------
950 // ---------------------------------------------------------------------------
952 void wxDC::SetPalette(const wxPalette
& palette
)
962 // Set the old object temporarily, in case the assignment deletes an object
963 // that's not yet selected out.
967 // ::SelectObject(GetHdc(), (HFONT) m_hOldFont);
976 // ::SelectObject(GetHdc(), (HFONT) m_hOldFont);
980 if (m_font
.Ok() && m_font
.GetResourceHandle())
982 HFONT hFont
= (HFONT
)0; //::SelectObject(GetHdc(), (HFONT) m_font.GetResourceHandle());
983 if (hFont
== (HFONT
) NULL
)
985 wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont."));
988 m_hOldFont
= (WXHFONT
) hFont
;
996 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1004 int nWidth
= m_pen
.GetWidth();
1013 ( fabs((double) XLOG2DEVREL(nWidth
)) +
1014 fabs((double) YLOG2DEVREL(nWidth
))
1018 wxColour vColor
= m_pen
.GetColour();
1020 ::GpiSetColor( m_hPS
1025 int nStyle
= m_pen
.GetStyle();
1027 nLinetype
= LINETYPE_DEFAULT
;
1031 nLinetype
= LINETYPE_DOT
;
1035 nLinetype
= LINETYPE_LONGDASH
;
1039 nLinetype
= LINETYPE_SHORTDASH
;
1043 nLinetype
= LINETYPE_DASHDOT
;
1047 nLinetype
= LINETYPE_INVISIBLE
;
1051 nLinetype
= LINETYPE_SOLID
;
1054 ::GpiSetLineType( m_hPS
1058 nWidth
= m_pen
.GetWidth();
1059 ::GpiSetLineWidth( m_hPS
1066 void wxDC::SetBrush(
1067 const wxBrush
& rBrush
1073 void wxDC::SetBackground(const wxBrush
& brush
)
1078 void wxDC::SetBackgroundMode(
1082 m_backgroundMode
= nMode
;
1085 void wxDC::SetLogicalFunction(int function
)
1090 void wxDC::SetRop(WXHDC dc
)
1092 if (!dc
|| m_logicalFunction
< 0)
1096 // These may be wrong
1097 switch (m_logicalFunction
)
1099 // TODO: Figure this stuff out
1100 // case wxXOR: c_rop = R2_XORPEN; break;
1101 // case wxXOR: c_rop = R2_NOTXORPEN; break;
1102 // case wxINVERT: c_rop = R2_NOT; break;
1103 // case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
1104 // case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
1105 // case wxCLEAR: c_rop = R2_WHITE; break;
1106 // case wxSET: c_rop = R2_BLACK; break;
1107 // case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
1108 // case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
1109 // case wxAND: c_rop = R2_MASKPEN; break;
1110 // case wxOR: c_rop = R2_MERGEPEN; break;
1111 // case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
1116 // c_rop = R2_COPYPEN;
1119 // SetROP2((HDC) dc, c_rop);
1122 bool wxDC::StartDoc(const wxString
& message
)
1124 // We might be previewing, so return TRUE to let it continue.
1132 void wxDC::StartPage()
1136 void wxDC::EndPage()
1140 // ---------------------------------------------------------------------------
1142 // ---------------------------------------------------------------------------
1144 wxCoord
wxDC::GetCharHeight() const
1150 wxCoord
wxDC::GetCharWidth() const
1156 void wxDC::DoGetTextExtent(
1157 const wxString
& rsString
1160 , wxCoord
* pvDescent
1161 , wxCoord
* pvExternalLeading
1165 POINTL avPoint
[TXTBOX_COUNT
];
1170 FONTMETRICS vFM
; // metrics structure
1173 ERRORID vErrorCode
; // last error id code
1174 wxFont
* pFontToUse
= (wxFont
*)pTheFont
;
1177 pFontToUse
= (wxFont
*)&m_font
;
1178 l
= rsString
.length();
1179 pStr
= (PCH
) rsString
.c_str();
1182 // In world coordinates.
1184 bRc
= ::GpiQueryTextBox( m_hPS
1187 ,TXTBOX_COUNT
// return maximum information
1188 ,avPoint
// array of coordinates points
1192 vErrorCode
= ::WinGetLastError(wxGetInstance());
1195 vPtMin
.x
= avPoint
[0].x
;
1196 vPtMax
.x
= avPoint
[0].x
;
1197 vPtMin
.y
= avPoint
[0].y
;
1198 vPtMax
.y
= avPoint
[0].y
;
1199 for (i
= 1; i
< 4; i
++)
1201 if(vPtMin
.x
> avPoint
[i
].x
) vPtMin
.x
= avPoint
[i
].x
;
1202 if(vPtMin
.y
> avPoint
[i
].y
) vPtMin
.y
= avPoint
[i
].y
;
1203 if(vPtMax
.x
< avPoint
[i
].x
) vPtMax
.x
= avPoint
[i
].x
;
1204 if(vPtMax
.y
< avPoint
[i
].y
) vPtMax
.y
= avPoint
[i
].y
;
1206 ::GpiQueryFontMetrics( m_hPS
1207 ,sizeof(FONTMETRICS
)
1212 *pvX
= (wxCoord
)(vPtMax
.x
- vPtMin
.x
+ 1);
1214 *pvY
= (wxCoord
)(vPtMax
.y
- vPtMin
.y
+ 1);
1216 *pvDescent
= vFM
.lMaxDescender
;
1217 if (pvExternalLeading
)
1218 *pvExternalLeading
= vFM
.lExternalLeading
;
1221 void wxDC::SetMapMode( int mode
)
1226 void wxDC::SetUserScale(double x
, double y
)
1231 SetMapMode(m_mappingMode
);
1234 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1236 m_signX
= xLeftRight
? 1 : -1;
1237 m_signY
= yBottomUp
? -1 : 1;
1239 SetMapMode(m_mappingMode
);
1242 void wxDC::SetSystemScale(double x
, double y
)
1247 SetMapMode(m_mappingMode
);
1250 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
1255 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
1260 // ---------------------------------------------------------------------------
1261 // coordinates transformations
1262 // ---------------------------------------------------------------------------
1264 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
1266 return (wxCoord
) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1269 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
1271 return (wxCoord
) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1274 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
1276 return (wxCoord
) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1279 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
1281 return (wxCoord
) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1284 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
1286 return (wxCoord
) ((x
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1289 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
1291 return (wxCoord
) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1294 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
1296 return (wxCoord
) ((y
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1299 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
1301 return (wxCoord
) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1304 // ---------------------------------------------------------------------------
1306 // ---------------------------------------------------------------------------
1308 bool wxDC::DoBlit( wxCoord xdest
1323 void wxDC::DoGetSize( int* width
, int* height
) const
1328 void wxDC::DoGetSizeMM( int* width
, int* height
) const
1333 wxSize
wxDC::GetPPI() const
1338 return (wxSize(x
,y
));
1341 void wxDC::SetLogicalScale( double x
, double y
)
1346 #if WXWIN_COMPATIBILITY
1347 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1348 float *descent
, float *externalLeading
,
1349 wxFont
*theFont
, bool use16bit
) const
1351 wxCoord x1
, y1
, descent1
, externalLeading1
;
1352 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1355 *descent
= descent1
;
1356 if (externalLeading
)
1357 *externalLeading
= externalLeading1
;
1361 // ---------------------------------------------------------------------------
1362 // spline drawing code
1363 // ---------------------------------------------------------------------------
1367 class wxSpline
: public wxObject
1373 wxSpline(wxList
*list
);
1374 void DeletePoints();
1376 // Doesn't delete points
1380 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1382 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1383 double a3
, double b3
, double a4
, double b4
);
1384 void wx_clear_stack();
1385 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1386 double *y3
, double *x4
, double *y4
);
1387 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1388 double x4
, double y4
);
1389 static bool wx_spline_add_point(double x
, double y
);
1390 static void wx_spline_draw_point_array(wxDC
*dc
);
1391 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1393 void wxDC::DoDrawSpline(wxList
*list
)
1395 wxSpline
spline(list
);
1397 wx_draw_open_spline(this, &spline
);
1400 wxList wx_spline_point_list
;
1402 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1405 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1406 double x1
, y1
, x2
, y2
;
1408 wxNode
*node
= spline
->points
->First();
1409 p
= (wxPoint
*)node
->Data();
1414 node
= node
->Next();
1415 p
= (wxPoint
*)node
->Data();
1419 cx1
= (double)((x1
+ x2
) / 2);
1420 cy1
= (double)((y1
+ y2
) / 2);
1421 cx2
= (double)((cx1
+ x2
) / 2);
1422 cy2
= (double)((cy1
+ y2
) / 2);
1424 wx_spline_add_point(x1
, y1
);
1426 while ((node
= node
->Next()) != NULL
)
1428 p
= (wxPoint
*)node
->Data();
1433 cx4
= (double)(x1
+ x2
) / 2;
1434 cy4
= (double)(y1
+ y2
) / 2;
1435 cx3
= (double)(x1
+ cx4
) / 2;
1436 cy3
= (double)(y1
+ cy4
) / 2;
1438 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1442 cx2
= (double)(cx1
+ x2
) / 2;
1443 cy2
= (double)(cy1
+ y2
) / 2;
1446 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1447 wx_spline_add_point(x2
, y2
);
1449 wx_spline_draw_point_array(dc
);
1453 /********************* CURVES FOR SPLINES *****************************
1455 The following spline drawing routine is from
1457 "An Algorithm for High-Speed Curve Generation"
1458 by George Merrill Chaikin,
1459 Computer Graphics and Image Processing, 3, Academic Press,
1464 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1465 Computer Graphics and Image Processing, 4, Academic Press,
1468 ***********************************************************************/
1470 #define half(z1, z2) ((z1+z2)/2.0)
1473 /* iterative version */
1475 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1478 register double xmid
, ymid
;
1479 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1482 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1484 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1485 xmid
= (double)half(x2
, x3
);
1486 ymid
= (double)half(y2
, y3
);
1487 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1488 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1489 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1490 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1492 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1493 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1494 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1495 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1501 /* utilities used by spline drawing routines */
1504 typedef struct wx_spline_stack_struct
{
1505 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1509 #define SPLINE_STACK_DEPTH 20
1510 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1511 static Stack
*wx_stack_top
;
1512 static int wx_stack_count
;
1514 void wx_clear_stack()
1516 wx_stack_top
= wx_spline_stack
;
1520 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1522 wx_stack_top
->x1
= x1
;
1523 wx_stack_top
->y1
= y1
;
1524 wx_stack_top
->x2
= x2
;
1525 wx_stack_top
->y2
= y2
;
1526 wx_stack_top
->x3
= x3
;
1527 wx_stack_top
->y3
= y3
;
1528 wx_stack_top
->x4
= x4
;
1529 wx_stack_top
->y4
= y4
;
1534 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1535 double *x3
, double *y3
, double *x4
, double *y4
)
1537 if (wx_stack_count
== 0)
1541 *x1
= wx_stack_top
->x1
;
1542 *y1
= wx_stack_top
->y1
;
1543 *x2
= wx_stack_top
->x2
;
1544 *y2
= wx_stack_top
->y2
;
1545 *x3
= wx_stack_top
->x3
;
1546 *y3
= wx_stack_top
->y3
;
1547 *x4
= wx_stack_top
->x4
;
1548 *y4
= wx_stack_top
->y4
;
1552 static bool wx_spline_add_point(double x
, double y
)
1554 wxPoint
*point
= new wxPoint
;
1557 wx_spline_point_list
.Append((wxObject
*)point
);
1561 static void wx_spline_draw_point_array(wxDC
*dc
)
1563 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1564 wxNode
*node
= wx_spline_point_list
.First();
1567 wxPoint
*point
= (wxPoint
*)node
->Data();
1570 node
= wx_spline_point_list
.First();
1574 wxSpline::wxSpline(wxList
*list
)
1579 wxSpline::~wxSpline()
1583 void wxSpline::DeletePoints()
1585 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1587 wxPoint
*point
= (wxPoint
*)node
->Data();
1595 #endif // wxUSE_SPLINES