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 ::GpiMove(m_hPS
, &vPoint
[0]);
368 ::GpiLine(m_hPS
, &vPoint
[1]);
371 //////////////////////////////////////////////////////////////////////////////
372 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
373 // and ending at (x2, y2). The current pen is used for the outline and the
374 // current brush for filling the shape. The arc is drawn in an anticlockwise
375 // direction from the start point to the end point.
376 //////////////////////////////////////////////////////////////////////////////
377 void wxDC::DoDrawArc(
387 POINTL vPtlArc
[2]; // Structure for current position
396 ARCPARAMS vArcp
; // Structure for arc parameters
398 if((vX1
== vXc
&& vY1
== vXc
) || (vX2
== vXc
&& vY2
== vXc
))
399 return; // Draw point ??
400 dRadius
= 0.5 * ( hypot( (double)(vY1
- vYc
)
403 hypot( (double)(vY2
- vYc
)
408 dAngl1
= atan2( (double)(vY1
- vYc
)
411 dAngl2
= atan2( (double)(vY2
- vYc
)
418 // GpiPointArc can't draw full arc
420 if(dAngl2
== dAngl1
|| (vX1
== vX2
&& vY1
== vY2
) )
425 dAnglmid
= (dAngl1
+ dAngl2
)/2. + M_PI
;
426 vXm
= vXc
+ dRadius
* cos(dAnglmid
);
427 vYm
= vYc
+ dRadius
* sin(dAnglmid
);
448 dAnglmid
= (dAngl1
+ dAngl2
)/2.;
449 vXm
= vXc
+ dRadius
* cos(dAnglmid
);
450 vYm
= vYc
+ dRadius
* sin(dAnglmid
);
453 // Ellipse main axis (r,q), (p,s) with center at (0,0) */
459 ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default
461 vPtlPos
.x
= vX1
; // Loads x-coordinate
462 vPtlPos
.y
= vY1
; // Loads y-coordinate
463 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
468 ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc
471 void wxDC::DoDrawCheckMark(
482 vPoint
[1].x
= vX1
+ vWidth
;
483 vPoint
[1].y
= vY1
+ vHeight
;
485 ::GpiMove(m_hPS
, &vPoint
[0]);
486 ::GpiBox( m_hPS
// handle to a presentation space
487 ,DRO_OUTLINE
// draw the box outline ? or ?
488 ,&vPoint
[1] // address of the corner
489 ,0L // horizontal corner radius
490 ,0L // vertical corner radius
492 if(vWidth
> 4 && vHeight
> 4)
496 vPoint
[0].x
+= 2; vPoint
[0].y
+= 2;
497 vPoint
[1].x
-= 2; vPoint
[1].y
-= 2;
498 ::GpiMove(m_hPS
, &vPoint
[0]);
499 ::GpiLine(m_hPS
, &vPoint
[1]);
501 vPoint
[0].x
= vPoint
[1].x
;
503 ::GpiMove(m_hPS
, &vPoint
[0]);
504 ::GpiLine(m_hPS
, &vPoint
[1]);
508 void wxDC::DoDrawPoint(
517 ::GpiSetPel(m_hPS
, &vPoint
);
520 void wxDC::DoDrawPolygon(
528 ULONG ulCount
= 1; // Number of polygons.
529 POLYGON vPlgn
; // polygon.
530 ULONG flOptions
= 0L; // Drawing options.
532 //////////////////////////////////////////////////////////////////////////////
533 // This contains fields of option bits... to draw boundary lines as well as
534 // the area interior.
536 // Drawing boundary lines:
537 // POLYGON_NOBOUNDARY Does not draw boundary lines.
538 // POLYGON_BOUNDARY Draws boundary lines (the default).
540 // Construction of the area interior:
541 // POLYGON_ALTERNATE Constructs interior in alternate mode
543 // POLYGON_WINDING Constructs interior in winding mode.
544 //////////////////////////////////////////////////////////////////////////////
546 ULONG flModel
= 0L; // Drawing model.
548 //////////////////////////////////////////////////////////////////////////////
550 // POLYGON_INCL Fill is inclusive of bottom right (the default).
551 // POLYGON_EXCL Fill is exclusive of bottom right.
552 // This is provided to aid migration from other graphics models.
553 //////////////////////////////////////////////////////////////////////////////
555 LONG lHits
= 0L; // Correlation/error indicator.
558 int nIsTRANSPARENT
= 0;
559 LONG lBorderColor
= 0L;
562 lBorderColor
= m_pen
.GetColour().GetPixel();
563 lColor
= m_brush
.GetColour().GetPixel();
564 if(m_brush
.GetStyle() == wxTRANSPARENT
)
568 vPlgn
.aPointl
= (POINTL
*) calloc( n
+ 1
570 ); // well, new will call malloc
572 for(i
= 0; i
< n
; i
++)
574 vPlgn
.aPointl
[i
].x
= vPoints
[i
].x
; // +xoffset;
575 vPlgn
.aPointl
[i
].y
= vPoints
[i
].y
; // +yoffset;
577 flModel
= POLYGON_BOUNDARY
;
578 if(nFillStyle
== wxWINDING_RULE
)
579 flModel
|= POLYGON_WINDING
;
581 flModel
|= POLYGON_ALTERNATE
;
586 ::GpiSetColor(m_hPS
, lBorderColor
);
587 ::GpiMove(m_hPS
, &vPoint
);
588 lHits
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
);
592 void wxDC::DoDrawLines(
602 vPoint
.x
= vPoints
[0].x
+ vXoffset
;
603 vPoint
.y
= vPoints
[0].y
+ vYoffset
;
604 ::GpiMove(m_hPS
, &vPoint
);
606 LONG lBorderColor
= m_pen
.GetColour().GetPixel();
608 ::GpiSetColor(m_hPS
, lBorderColor
);
609 for(i
= 1; i
< n
; i
++)
611 vPoint
.x
= vPoints
[0].x
+ vXoffset
;
612 vPoint
.y
= vPoints
[0].y
+ vYoffset
;
613 ::GpiLine(m_hPS
, &vPoint
);
617 void wxDC::DoDrawRectangle(
628 int nIsTRANSPARENT
= 0;
632 vPoint
[1].x
= vX
+ vWidth
;
633 vPoint
[1].y
= vY
- vHeight
;
634 ::GpiMove(m_hPS
, &vPoint
[0]);
635 lColor
= m_brush
.GetColour().GetPixel();
636 lBorderColor
= m_pen
.GetColour().GetPixel();
637 if (m_brush
.GetStyle() == wxTRANSPARENT
)
639 if(lColor
== lBorderColor
|| nIsTRANSPARENT
)
641 lControl
= DRO_OUTLINEFILL
; //DRO_FILL;
642 if(m_brush
.GetStyle() == wxTRANSPARENT
)
643 lControl
= DRO_OUTLINE
;
645 ::GpiSetColor(m_hPS
, CLR_GREEN
);
646 ::GpiBox( m_hPS
// handle to a presentation space
647 ,lControl
// draw the box outline ? or ?
648 ,&vPoint
[1] // address of the corner
649 ,0L // horizontal corner radius
650 ,0L // vertical corner radius
655 lControl
= DRO_OUTLINE
;
678 void wxDC::DoDrawRoundedRectangle(
691 vPoint
[1].x
= vX
+ vWidth
;
692 vPoint
[1].y
= vY
+ vHeight
;
693 ::GpiMove(m_hPS
, &vPoint
[0]);
695 lControl
= DRO_OUTLINEFILL
; //DRO_FILL;
696 if (m_brush
.GetStyle() == wxTRANSPARENT
)
697 lControl
= DRO_OUTLINE
;
698 ::GpiBox( m_hPS
// handle to a presentation space
699 ,DRO_OUTLINE
// draw the box outline ? or ?
700 ,&vPoint
[1] // address of the corner
701 ,(LONG
)dRadius
// horizontal corner radius
702 ,(LONG
)dRadius
// vertical corner radius
706 // Draw Ellipse within box (x,y) - (x+width, y+height)
707 void wxDC::DoDrawEllipse(
714 POINTL vPtlPos
; // Structure for current position
715 FIXED vFxMult
; // Multiplier for ellipse
716 ARCPARAMS vArcp
; // Structure for arc parameters
719 vArcp
.lQ
= vHeight
/2;
722 ::GpiSetArcParams( m_hPS
724 ); // Sets parameters to default
725 vPtlPos
.x
= vX
+ vWidth
/2; // Loads x-coordinate
726 vPtlPos
.y
= vY
+ vHeight
/2; // Loads y-coordinate
729 ); // Sets current position
730 vFxMult
= MAKEFIXED(1, 0); /* Sets multiplier */
733 // DRO_FILL, DRO_OTLINEFILL - where to get
738 ); // Draws full arc with center at current position
741 void wxDC::DoDrawEllipticArc(
750 POINTL vPtlPos
; // Structure for current position
751 FIXED vFxMult
; // Multiplier for ellipse
752 ARCPARAMS vArcp
; // Structure for arc parameters
754 FIXED vFSweepa
; // Start angle, sweep angle
759 dFractPart
= modf(dSa
,&dIntPart
);
760 vFSa
= MAKEFIXED((int)dIntPart
, (int)(dFractPart
* 0xffff) );
761 dFractPart
= modf(dEa
- dSa
, &dIntPart
);
762 vFSweepa
= MAKEFIXED((int)dIntPart
, (int)(dFractPart
* 0xffff) );
765 // Ellipse main axis (r,q), (p,s) with center at (0,0)
768 vArcp
.lQ
= vHeight
/2;
771 ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default
772 vPtlPos
.x
= vX
+ vWidth
/2 * (1. + cos(DegToRad(dSa
))); // Loads x-coordinate
773 vPtlPos
.y
= vY
+ vHeight
/2 * (1. + sin(DegToRad(dSa
))); // Loads y-coordinate
774 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
777 // May be not to the center ?
779 vPtlPos
.x
= vX
+ vWidth
/2 ; // Loads x-coordinate
780 vPtlPos
.y
= vY
+ vHeight
/2; // Loads y-coordinate
781 vFxMult
= MAKEFIXED(1, 0); // Sets multiplier
784 // DRO_FILL, DRO_OTLINEFILL - where to get
786 ::GpiPartialArc( m_hPS
794 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
)
799 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
800 ,wxCoord x
, wxCoord y
807 void wxDC::DoDrawText(
808 const wxString
& rsText
819 void wxDC::DrawAnyText(
820 const wxString
& rsText
825 int nOldBackground
= 0;
830 // prepare for drawing the text
834 // Set text color attributes
836 if (m_textForegroundColour
.Ok())
839 ,(int)m_textForegroundColour
.GetPixel()
843 if (m_textBackgroundColour
.Ok())
845 nOldBackground
= SetTextBkColor( m_hPS
846 ,(int)m_textBackgroundColour
.GetPixel()
855 lHits
= ::GpiCharStringAt( m_hPS
862 wxLogLastError(wxT("TextOut"));
866 // Restore the old parameters (text foreground colour may be left because
867 // it never is set to anything else, but background should remain
868 // transparent even if we just drew an opaque string)
870 if (m_textBackgroundColour
.Ok())
871 SetTextBkColor( m_hPS
879 void wxDC::DoDrawRotatedText(
880 const wxString
& rsText
898 DoDrawText(text, x, y);
903 wxFillLogFont(&lf, &m_font);
905 // GDI wants the angle in tenth of degree
906 long angle10 = (long)(angle * 10);
907 lf.lfEscapement = angle10;
908 lf. lfOrientation = angle10;
910 HFONT hfont = ::CreateFontIndirect(&lf);
913 wxLogLastError("CreateFont");
917 HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
919 DrawAnyText(text, x, y);
921 (void)::SelectObject(GetHdc(), hfontOld);
924 // call the bounding box by adding all four vertices of the rectangle
925 // containing the text to it (simpler and probably not slower than
926 // determining which of them is really topmost/leftmost/...)
928 GetTextExtent(text, &w, &h);
930 double rad = DegToRad(angle);
932 // "upper left" and "upper right"
933 CalcBoundingBox(x, y);
934 CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
935 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
937 // "bottom left" and "bottom right"
938 x += (wxCoord)(h*sin(rad));
939 y += (wxCoord)(h*cos(rad));
940 CalcBoundingBox(x, y);
941 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
946 // ---------------------------------------------------------------------------
948 // ---------------------------------------------------------------------------
950 void wxDC::SetPalette(const wxPalette
& palette
)
960 // Set the old object temporarily, in case the assignment deletes an object
961 // that's not yet selected out.
965 // ::SelectObject(GetHdc(), (HFONT) m_hOldFont);
974 // ::SelectObject(GetHdc(), (HFONT) m_hOldFont);
978 if (m_font
.Ok() && m_font
.GetResourceHandle())
980 HFONT hFont
= (HFONT
)0; //::SelectObject(GetHdc(), (HFONT) m_font.GetResourceHandle());
981 if (hFont
== (HFONT
) NULL
)
983 wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont."));
986 m_hOldFont
= (WXHFONT
) hFont
;
994 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1010 m_pen
.SetPS((HPS
)m_hOldPen
);
1017 if (m_pen
.GetResourceHandle())
1021 m_hOldPen
= m_pen
.GetPS();
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
1107 FONTMETRICS vFM
; // metrics structure
1109 ::GpiQueryFontMetrics( m_hPS
1110 ,sizeof(FONTMETRICS
)
1113 return YDEV2LOGREL(vFM
.lXHeight
);
1116 wxCoord
wxDC::GetCharWidth() const
1118 FONTMETRICS vFM
; // metrics structure
1120 ::GpiQueryFontMetrics( m_hPS
1121 ,sizeof(FONTMETRICS
)
1124 return XDEV2LOGREL(vFM
.lAveCharWidth
);
1127 void wxDC::DoGetTextExtent(
1128 const wxString
& rsString
1131 , wxCoord
* pvDescent
1132 , wxCoord
* pvExternalLeading
1136 POINTL avPoint
[TXTBOX_COUNT
];
1141 FONTMETRICS vFM
; // metrics structure
1144 ERRORID vErrorCode
; // last error id code
1145 wxFont
* pFontToUse
= (wxFont
*)pTheFont
;
1148 pFontToUse
= (wxFont
*)&m_font
;
1149 l
= rsString
.length();
1150 pStr
= (PCH
) rsString
.c_str();
1153 // In world coordinates.
1155 bRc
= ::GpiQueryTextBox( m_hPS
1158 ,TXTBOX_COUNT
// return maximum information
1159 ,avPoint
// array of coordinates points
1163 vErrorCode
= ::WinGetLastError(wxGetInstance());
1166 vPtMin
.x
= avPoint
[0].x
;
1167 vPtMax
.x
= avPoint
[0].x
;
1168 vPtMin
.y
= avPoint
[0].y
;
1169 vPtMax
.y
= avPoint
[0].y
;
1170 for (i
= 1; i
< 4; i
++)
1172 if(vPtMin
.x
> avPoint
[i
].x
) vPtMin
.x
= avPoint
[i
].x
;
1173 if(vPtMin
.y
> avPoint
[i
].y
) vPtMin
.y
= avPoint
[i
].y
;
1174 if(vPtMax
.x
< avPoint
[i
].x
) vPtMax
.x
= avPoint
[i
].x
;
1175 if(vPtMax
.y
< avPoint
[i
].y
) vPtMax
.y
= avPoint
[i
].y
;
1177 ::GpiQueryFontMetrics( m_hPS
1178 ,sizeof(FONTMETRICS
)
1183 *pvX
= (wxCoord
)(vPtMax
.x
- vPtMin
.x
+ 1);
1185 *pvY
= (wxCoord
)(vPtMax
.y
- vPtMin
.y
+ 1);
1187 *pvDescent
= vFM
.lMaxDescender
;
1188 if (pvExternalLeading
)
1189 *pvExternalLeading
= vFM
.lExternalLeading
;
1192 void wxDC::SetMapMode( int mode
)
1197 void wxDC::SetUserScale(double x
, double y
)
1202 SetMapMode(m_mappingMode
);
1205 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1207 m_signX
= xLeftRight
? 1 : -1;
1208 m_signY
= yBottomUp
? -1 : 1;
1210 SetMapMode(m_mappingMode
);
1213 void wxDC::SetSystemScale(double x
, double y
)
1218 SetMapMode(m_mappingMode
);
1221 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
1226 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
1230 ::GpiQueryPageViewport( m_hPS
1237 ::GpiSetPageViewport( m_hPS
1242 // ---------------------------------------------------------------------------
1243 // coordinates transformations
1244 // ---------------------------------------------------------------------------
1246 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
1248 return (wxCoord
) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1251 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
1253 return (wxCoord
) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1256 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
1258 return (wxCoord
) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1261 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
1263 return (wxCoord
) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1266 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
1268 return (wxCoord
) ((x
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1271 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
1273 return (wxCoord
) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1276 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
1278 return (wxCoord
) ((y
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1281 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
1283 return (wxCoord
) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1286 // ---------------------------------------------------------------------------
1288 // ---------------------------------------------------------------------------
1290 bool wxDC::DoBlit( wxCoord xdest
1305 void wxDC::DoGetSize( int* width
, int* height
) const
1310 void wxDC::DoGetSizeMM( int* width
, int* height
) const
1315 wxSize
wxDC::GetPPI() const
1320 return (wxSize(x
,y
));
1323 void wxDC::SetLogicalScale( double x
, double y
)
1328 #if WXWIN_COMPATIBILITY
1329 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1330 float *descent
, float *externalLeading
,
1331 wxFont
*theFont
, bool use16bit
) const
1333 wxCoord x1
, y1
, descent1
, externalLeading1
;
1334 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1337 *descent
= descent1
;
1338 if (externalLeading
)
1339 *externalLeading
= externalLeading1
;
1343 // ---------------------------------------------------------------------------
1344 // spline drawing code
1345 // ---------------------------------------------------------------------------
1349 class wxSpline
: public wxObject
1355 wxSpline(wxList
*list
);
1356 void DeletePoints();
1358 // Doesn't delete points
1362 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1364 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1365 double a3
, double b3
, double a4
, double b4
);
1366 void wx_clear_stack();
1367 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1368 double *y3
, double *x4
, double *y4
);
1369 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1370 double x4
, double y4
);
1371 static bool wx_spline_add_point(double x
, double y
);
1372 static void wx_spline_draw_point_array(wxDC
*dc
);
1373 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1375 void wxDC::DoDrawSpline(wxList
*list
)
1377 wxSpline
spline(list
);
1379 wx_draw_open_spline(this, &spline
);
1382 wxList wx_spline_point_list
;
1384 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1387 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1388 double x1
, y1
, x2
, y2
;
1390 wxNode
*node
= spline
->points
->First();
1391 p
= (wxPoint
*)node
->Data();
1396 node
= node
->Next();
1397 p
= (wxPoint
*)node
->Data();
1401 cx1
= (double)((x1
+ x2
) / 2);
1402 cy1
= (double)((y1
+ y2
) / 2);
1403 cx2
= (double)((cx1
+ x2
) / 2);
1404 cy2
= (double)((cy1
+ y2
) / 2);
1406 wx_spline_add_point(x1
, y1
);
1408 while ((node
= node
->Next()) != NULL
)
1410 p
= (wxPoint
*)node
->Data();
1415 cx4
= (double)(x1
+ x2
) / 2;
1416 cy4
= (double)(y1
+ y2
) / 2;
1417 cx3
= (double)(x1
+ cx4
) / 2;
1418 cy3
= (double)(y1
+ cy4
) / 2;
1420 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1424 cx2
= (double)(cx1
+ x2
) / 2;
1425 cy2
= (double)(cy1
+ y2
) / 2;
1428 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1429 wx_spline_add_point(x2
, y2
);
1431 wx_spline_draw_point_array(dc
);
1435 /********************* CURVES FOR SPLINES *****************************
1437 The following spline drawing routine is from
1439 "An Algorithm for High-Speed Curve Generation"
1440 by George Merrill Chaikin,
1441 Computer Graphics and Image Processing, 3, Academic Press,
1446 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1447 Computer Graphics and Image Processing, 4, Academic Press,
1450 ***********************************************************************/
1452 #define half(z1, z2) ((z1+z2)/2.0)
1455 /* iterative version */
1457 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1460 register double xmid
, ymid
;
1461 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1464 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1466 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1467 xmid
= (double)half(x2
, x3
);
1468 ymid
= (double)half(y2
, y3
);
1469 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1470 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1471 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1472 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1474 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1475 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1476 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1477 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1483 /* utilities used by spline drawing routines */
1486 typedef struct wx_spline_stack_struct
{
1487 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1491 #define SPLINE_STACK_DEPTH 20
1492 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1493 static Stack
*wx_stack_top
;
1494 static int wx_stack_count
;
1496 void wx_clear_stack()
1498 wx_stack_top
= wx_spline_stack
;
1502 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1504 wx_stack_top
->x1
= x1
;
1505 wx_stack_top
->y1
= y1
;
1506 wx_stack_top
->x2
= x2
;
1507 wx_stack_top
->y2
= y2
;
1508 wx_stack_top
->x3
= x3
;
1509 wx_stack_top
->y3
= y3
;
1510 wx_stack_top
->x4
= x4
;
1511 wx_stack_top
->y4
= y4
;
1516 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1517 double *x3
, double *y3
, double *x4
, double *y4
)
1519 if (wx_stack_count
== 0)
1523 *x1
= wx_stack_top
->x1
;
1524 *y1
= wx_stack_top
->y1
;
1525 *x2
= wx_stack_top
->x2
;
1526 *y2
= wx_stack_top
->y2
;
1527 *x3
= wx_stack_top
->x3
;
1528 *y3
= wx_stack_top
->y3
;
1529 *x4
= wx_stack_top
->x4
;
1530 *y4
= wx_stack_top
->y4
;
1534 static bool wx_spline_add_point(double x
, double y
)
1536 wxPoint
*point
= new wxPoint
;
1539 wx_spline_point_list
.Append((wxObject
*)point
);
1543 static void wx_spline_draw_point_array(wxDC
*dc
)
1545 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1546 wxNode
*node
= wx_spline_point_list
.First();
1549 wxPoint
*point
= (wxPoint
*)node
->Data();
1552 node
= wx_spline_point_list
.First();
1556 wxSpline::wxSpline(wxList
*list
)
1561 wxSpline::~wxSpline()
1565 void wxSpline::DeletePoints()
1567 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1569 wxPoint
*point
= (wxPoint
*)node
->Data();
1577 #endif // wxUSE_SPLINES