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
156 // This will select current objects out of the DC,
157 // which is what you have to do before deleting the
159 void wxDC::SelectOldObjects(WXHDC dc
)
165 // ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
166 if (m_vSelectedBitmap
.Ok())
168 m_vSelectedBitmap
.SetSelectedInto(NULL
);
174 // ::SelectObject((HDC) dc, (HPEN) m_oldPen);
179 // ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
184 // ::SelectObject((HDC) dc, (HFONT) m_oldFont);
189 // ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE);
194 m_brush
= wxNullBrush
;
196 m_palette
= wxNullPalette
;
198 m_backgroundBrush
= wxNullBrush
;
199 m_vSelectedBitmap
= wxNullBitmap
;
202 // ---------------------------------------------------------------------------
204 // ---------------------------------------------------------------------------
206 #define DO_SET_CLIPPING_BOX() \
210 ::GpiQueryClipBox(m_hPS, &rect); \
212 m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft); \
213 m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop); \
214 m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight); \
215 m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \
218 void wxDC::DoSetClippingRegion(
228 vRect
.xLeft
= XLOG2DEV(x
);
229 vRect
.yTop
= YLOG2DEV(y
+ height
);
230 vRect
.xRight
= XLOG2DEV(x
+ width
);
231 vRect
.yBottom
= YLOG2DEV(y
);
232 ::GpiIntersectClipRectangle(m_hPS
, &vRect
);
233 DO_SET_CLIPPING_BOX()
234 } // end of wxDC::DoSetClippingRegion
236 void wxDC::DoSetClippingRegionAsRegion(
237 const wxRegion
& rRegion
240 wxCHECK_RET(rRegion
.GetHRGN(), wxT("invalid clipping region"));
244 ::GpiSetClipRegion( m_hPS
245 ,(HRGN
)rRegion
.GetHRGN()
248 DO_SET_CLIPPING_BOX()
249 } // end of wxDC::DoSetClippingRegionAsRegion
251 void wxDC::DestroyClippingRegion(void)
253 if (m_clipping
&& m_hPS
)
258 // TODO: this should restore the previous clipped region
259 // so that OnPaint processing works correctly, and
260 // the update doesn't get destroyed after the first
261 // DestroyClippingRegion
262 vRect
.xLeft
= XLOG2DEV(0);
263 vRect
.yTop
= YLOG2DEV(32000);
264 vRect
.xRight
= XLOG2DEV(32000);
265 vRect
.yBottom
= YLOG2DEV(0);
267 HRGN hRgn
= ::GpiCreateRegion(m_hPS
, 1, &vRect
);
269 ::GpiSetClipRegion(m_hPS
, hRgn
, &hRgnOld
);
272 } // end of wxDC::DestroyClippingRegion
274 // ---------------------------------------------------------------------------
275 // query capabilities
276 // ---------------------------------------------------------------------------
278 bool wxDC::CanDrawBitmap() const
283 bool wxDC::CanGetTextExtent() const
285 // What sort of display is it?
286 int technology
= 0; // TODO: ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
288 // TODO: return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
292 int wxDC::GetDepth() const
298 // ---------------------------------------------------------------------------
300 // ---------------------------------------------------------------------------
307 void wxDC::DoFloodFill(
310 , const wxColour
& rCol
318 vPtlPos
.x
= vX
; // Loads x-coordinate
319 vPtlPos
.y
= vY
; // Loads y-coordinate
320 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
321 lColor
= rCol
.GetPixel();
322 lOptions
= FF_BOUNDARY
;
323 if(wxFLOOD_SURFACE
== nStyle
)
324 lOptions
= FF_SURFACE
;
326 ::GpiFloodFill(m_hPS
, lOptions
, lColor
);
329 bool wxDC::DoGetPixel(
340 lColor
= ::GpiSetPel(m_hPS
, &vPoint
);
341 pCol
->Set((unsigned long)lColor
);
348 void wxDC::DoCrossHair(wxCoord x
, wxCoord y
)
353 void wxDC::DoDrawLine(
366 ::GpiMove(m_hPS
, &vPoint
[0]);
367 ::GpiLine(m_hPS
, &vPoint
[1]);
370 //////////////////////////////////////////////////////////////////////////////
371 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
372 // and ending at (x2, y2). The current pen is used for the outline and the
373 // current brush for filling the shape. The arc is drawn in an anticlockwise
374 // direction from the start point to the end point.
375 //////////////////////////////////////////////////////////////////////////////
376 void wxDC::DoDrawArc(
386 POINTL vPtlArc
[2]; // Structure for current position
395 ARCPARAMS vArcp
; // Structure for arc parameters
397 if((vX1
== vXc
&& vY1
== vXc
) || (vX2
== vXc
&& vY2
== vXc
))
398 return; // Draw point ??
399 dRadius
= 0.5 * ( hypot( (double)(vY1
- vYc
)
402 hypot( (double)(vY2
- vYc
)
407 dAngl1
= atan2( (double)(vY1
- vYc
)
410 dAngl2
= atan2( (double)(vY2
- vYc
)
417 // GpiPointArc can't draw full arc
419 if(dAngl2
== dAngl1
|| (vX1
== vX2
&& vY1
== vY2
) )
424 dAnglmid
= (dAngl1
+ dAngl2
)/2. + M_PI
;
425 vXm
= vXc
+ dRadius
* cos(dAnglmid
);
426 vYm
= vYc
+ dRadius
* sin(dAnglmid
);
441 dAnglmid
= (dAngl1
+ dAngl2
)/2.;
442 vXm
= vXc
+ dRadius
* cos(dAnglmid
);
443 vYm
= vYc
+ dRadius
* sin(dAnglmid
);
446 // Ellipse main axis (r,q), (p,s) with center at (0,0) */
452 ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default
454 vPtlPos
.x
= vX1
; // Loads x-coordinate
455 vPtlPos
.y
= vY1
; // Loads y-coordinate
456 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
461 ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc
464 void wxDC::DoDrawCheckMark(
475 vPoint
[1].x
= vX1
+ vWidth
;
476 vPoint
[1].y
= vY1
+ vHeight
;
478 ::GpiMove(m_hPS
, &vPoint
[0]);
479 ::GpiBox( m_hPS
// handle to a presentation space
480 ,DRO_OUTLINE
// draw the box outline ? or ?
481 ,&vPoint
[1] // address of the corner
482 ,0L // horizontal corner radius
483 ,0L // vertical corner radius
485 if(vWidth
> 4 && vHeight
> 4)
489 vPoint
[0].x
+= 2; vPoint
[0].y
+= 2;
490 vPoint
[1].x
-= 2; vPoint
[1].y
-= 2;
491 ::GpiMove(m_hPS
, &vPoint
[0]);
492 ::GpiLine(m_hPS
, &vPoint
[1]);
494 vPoint
[0].x
= vPoint
[1].x
;
496 ::GpiMove(m_hPS
, &vPoint
[0]);
497 ::GpiLine(m_hPS
, &vPoint
[1]);
501 void wxDC::DoDrawPoint(
510 ::GpiSetPel(m_hPS
, &vPoint
);
513 void wxDC::DoDrawPolygon(
521 ULONG ulCount
= 1; // Number of polygons.
522 POLYGON vPlgn
; // polygon.
523 ULONG flOptions
= 0L; // Drawing options.
525 //////////////////////////////////////////////////////////////////////////////
526 // This contains fields of option bits... to draw boundary lines as well as
527 // the area interior.
529 // Drawing boundary lines:
530 // POLYGON_NOBOUNDARY Does not draw boundary lines.
531 // POLYGON_BOUNDARY Draws boundary lines (the default).
533 // Construction of the area interior:
534 // POLYGON_ALTERNATE Constructs interior in alternate mode
536 // POLYGON_WINDING Constructs interior in winding mode.
537 //////////////////////////////////////////////////////////////////////////////
539 ULONG flModel
= 0L; // Drawing model.
541 //////////////////////////////////////////////////////////////////////////////
543 // POLYGON_INCL Fill is inclusive of bottom right (the default).
544 // POLYGON_EXCL Fill is exclusive of bottom right.
545 // This is provided to aid migration from other graphics models.
546 //////////////////////////////////////////////////////////////////////////////
548 LONG lHits
= 0L; // Correlation/error indicator.
551 int nIsTRANSPARENT
= 0;
552 LONG lBorderColor
= 0L;
555 lBorderColor
= m_pen
.GetColour().GetPixel();
556 lColor
= m_brush
.GetColour().GetPixel();
557 if(m_brush
.GetStyle() == wxTRANSPARENT
)
561 vPlgn
.aPointl
= (POINTL
*) calloc( n
+ 1
563 ); // well, new will call malloc
565 for(i
= 0; i
< n
; i
++)
567 vPlgn
.aPointl
[i
].x
= vPoints
[i
].x
; // +xoffset;
568 vPlgn
.aPointl
[i
].y
= vPoints
[i
].y
; // +yoffset;
570 flModel
= POLYGON_BOUNDARY
;
571 if(nFillStyle
== wxWINDING_RULE
)
572 flModel
|= POLYGON_WINDING
;
574 flModel
|= POLYGON_ALTERNATE
;
579 ::GpiSetColor(m_hPS
, lBorderColor
);
580 ::GpiMove(m_hPS
, &vPoint
);
581 lHits
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
);
585 void wxDC::DoDrawLines(
595 vPoint
.x
= vPoints
[0].x
+ vXoffset
;
596 vPoint
.y
= vPoints
[0].y
+ vYoffset
;
597 ::GpiMove(m_hPS
, &vPoint
);
599 LONG lBorderColor
= m_pen
.GetColour().GetPixel();
601 ::GpiSetColor(m_hPS
, lBorderColor
);
602 for(i
= 1; i
< n
; i
++)
604 vPoint
.x
= vPoints
[0].x
+ vXoffset
;
605 vPoint
.y
= vPoints
[0].y
+ vYoffset
;
606 ::GpiLine(m_hPS
, &vPoint
);
610 void wxDC::DoDrawRectangle(
621 int nIsTRANSPARENT
= 0;
625 vPoint
[1].x
= vX
+ vWidth
;
626 vPoint
[1].y
= vY
- vHeight
;
627 ::GpiMove(m_hPS
, &vPoint
[0]);
628 lColor
= m_brush
.GetColour().GetPixel();
629 lBorderColor
= m_pen
.GetColour().GetPixel();
630 if (m_brush
.GetStyle() == wxTRANSPARENT
)
632 if(lColor
== lBorderColor
|| nIsTRANSPARENT
)
634 lControl
= DRO_OUTLINEFILL
; //DRO_FILL;
635 if(m_brush
.GetStyle() == wxTRANSPARENT
)
636 lControl
= DRO_OUTLINE
;
638 ::GpiSetColor(m_hPS
, CLR_GREEN
);
639 ::GpiBox( m_hPS
// handle to a presentation space
640 ,lControl
// draw the box outline ? or ?
641 ,&vPoint
[1] // address of the corner
642 ,0L // horizontal corner radius
643 ,0L // vertical corner radius
648 lControl
= DRO_OUTLINE
;
671 void wxDC::DoDrawRoundedRectangle(
684 vPoint
[1].x
= vX
+ vWidth
;
685 vPoint
[1].y
= vY
+ vHeight
;
686 ::GpiMove(m_hPS
, &vPoint
[0]);
688 lControl
= DRO_OUTLINEFILL
; //DRO_FILL;
689 if (m_brush
.GetStyle() == wxTRANSPARENT
)
690 lControl
= DRO_OUTLINE
;
691 ::GpiBox( m_hPS
// handle to a presentation space
692 ,DRO_OUTLINE
// draw the box outline ? or ?
693 ,&vPoint
[1] // address of the corner
694 ,(LONG
)dRadius
// horizontal corner radius
695 ,(LONG
)dRadius
// vertical corner radius
699 // Draw Ellipse within box (x,y) - (x+width, y+height)
700 void wxDC::DoDrawEllipse(
707 POINTL vPtlPos
; // Structure for current position
708 FIXED vFxMult
; // Multiplier for ellipse
709 ARCPARAMS vArcp
; // Structure for arc parameters
712 vArcp
.lQ
= vHeight
/2;
715 ::GpiSetArcParams( m_hPS
717 ); // Sets parameters to default
718 vPtlPos
.x
= vX
+ vWidth
/2; // Loads x-coordinate
719 vPtlPos
.y
= vY
+ vHeight
/2; // Loads y-coordinate
722 ); // Sets current position
723 vFxMult
= MAKEFIXED(1, 0); /* Sets multiplier */
726 // DRO_FILL, DRO_OTLINEFILL - where to get
731 ); // Draws full arc with center at current position
734 void wxDC::DoDrawEllipticArc(
743 POINTL vPtlPos
; // Structure for current position
744 FIXED vFxMult
; // Multiplier for ellipse
745 ARCPARAMS vArcp
; // Structure for arc parameters
747 FIXED vFSweepa
; // Start angle, sweep angle
752 dFractPart
= modf(dSa
,&dIntPart
);
753 vFSa
= MAKEFIXED((int)dIntPart
, (int)(dFractPart
* 0xffff) );
754 dFractPart
= modf(dEa
- dSa
, &dIntPart
);
755 vFSweepa
= MAKEFIXED((int)dIntPart
, (int)(dFractPart
* 0xffff) );
758 // Ellipse main axis (r,q), (p,s) with center at (0,0)
761 vArcp
.lQ
= vHeight
/2;
764 ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default
765 vPtlPos
.x
= vX
+ vWidth
/2 * (1. + cos(DegToRad(dSa
))); // Loads x-coordinate
766 vPtlPos
.y
= vY
+ vHeight
/2 * (1. + sin(DegToRad(dSa
))); // Loads y-coordinate
767 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
770 // May be not to the center ?
772 vPtlPos
.x
= vX
+ vWidth
/2 ; // Loads x-coordinate
773 vPtlPos
.y
= vY
+ vHeight
/2; // Loads y-coordinate
774 vFxMult
= MAKEFIXED(1, 0); // Sets multiplier
777 // DRO_FILL, DRO_OTLINEFILL - where to get
779 ::GpiPartialArc( m_hPS
787 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
)
792 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
793 ,wxCoord x
, wxCoord y
800 void wxDC::DoDrawText(
801 const wxString
& rsText
812 void wxDC::DrawAnyText(
813 const wxString
& rsText
818 int nOldBackground
= 0;
823 // prepare for drawing the text
827 // Set text color attributes
829 if (m_textForegroundColour
.Ok())
832 ,(int)m_textForegroundColour
.GetPixel()
836 if (m_textBackgroundColour
.Ok())
838 nOldBackground
= SetTextBkColor( m_hPS
839 ,(int)m_textBackgroundColour
.GetPixel()
848 lHits
= ::GpiCharStringAt( m_hPS
855 wxLogLastError(wxT("TextOut"));
859 // Restore the old parameters (text foreground colour may be left because
860 // it never is set to anything else, but background should remain
861 // transparent even if we just drew an opaque string)
863 if (m_textBackgroundColour
.Ok())
864 SetTextBkColor( m_hPS
872 void wxDC::DoDrawRotatedText(
873 const wxString
& rsText
891 DoDrawText(text, x, y);
896 wxFillLogFont(&lf, &m_font);
898 // GDI wants the angle in tenth of degree
899 long angle10 = (long)(angle * 10);
900 lf.lfEscapement = angle10;
901 lf. lfOrientation = angle10;
903 HFONT hfont = ::CreateFontIndirect(&lf);
906 wxLogLastError("CreateFont");
910 HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
912 DrawAnyText(text, x, y);
914 (void)::SelectObject(GetHdc(), hfontOld);
917 // call the bounding box by adding all four vertices of the rectangle
918 // containing the text to it (simpler and probably not slower than
919 // determining which of them is really topmost/leftmost/...)
921 GetTextExtent(text, &w, &h);
923 double rad = DegToRad(angle);
925 // "upper left" and "upper right"
926 CalcBoundingBox(x, y);
927 CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
928 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
930 // "bottom left" and "bottom right"
931 x += (wxCoord)(h*sin(rad));
932 y += (wxCoord)(h*cos(rad));
933 CalcBoundingBox(x, y);
934 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
939 // ---------------------------------------------------------------------------
941 // ---------------------------------------------------------------------------
943 void wxDC::SetPalette(const wxPalette
& palette
)
953 // Set the old object temporarily, in case the assignment deletes an object
954 // that's not yet selected out.
966 m_font
.SetPS(m_hPS
); // this will realize the font
970 HFONT hFont
= m_font
.GetResourceHandle();
971 if (hFont
== (HFONT
) NULL
)
973 wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont."));
976 m_hOldFont
= (WXHFONT
) hFont
;
978 } // end of wxDC::SetFont
984 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1000 m_pen
.SetPS((HPS
)m_hOldPen
);
1007 if (m_pen
.GetResourceHandle())
1011 m_hOldPen
= m_pen
.GetPS();
1016 void wxDC::SetBrush(
1017 const wxBrush
& rBrush
1020 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1022 if (m_brush
== rBrush
)
1036 m_brush
.SetPS((HPS
)m_hOldBrush
);
1043 if (m_brush
.GetResourceHandle())
1045 m_brush
.SetPS(m_hPS
);
1047 m_hOldBrush
= m_brush
.GetPS();
1050 } // end of wxDC::SetBrush
1052 void wxDC::SetBackground(const wxBrush
& brush
)
1057 void wxDC::SetBackgroundMode(
1061 m_backgroundMode
= nMode
;
1064 void wxDC::SetLogicalFunction(int function
)
1069 void wxDC::SetRop(WXHDC dc
)
1071 if (!dc
|| m_logicalFunction
< 0)
1075 // These may be wrong
1076 switch (m_logicalFunction
)
1078 // TODO: Figure this stuff out
1079 // case wxXOR: c_rop = R2_XORPEN; break;
1080 // case wxXOR: c_rop = R2_NOTXORPEN; break;
1081 // case wxINVERT: c_rop = R2_NOT; break;
1082 // case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
1083 // case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
1084 // case wxCLEAR: c_rop = R2_WHITE; break;
1085 // case wxSET: c_rop = R2_BLACK; break;
1086 // case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
1087 // case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
1088 // case wxAND: c_rop = R2_MASKPEN; break;
1089 // case wxOR: c_rop = R2_MERGEPEN; break;
1090 // case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
1095 // c_rop = R2_COPYPEN;
1098 // SetROP2((HDC) dc, c_rop);
1101 bool wxDC::StartDoc(const wxString
& message
)
1103 // We might be previewing, so return TRUE to let it continue.
1111 void wxDC::StartPage()
1115 void wxDC::EndPage()
1119 // ---------------------------------------------------------------------------
1121 // ---------------------------------------------------------------------------
1123 wxCoord
wxDC::GetCharHeight() const
1125 FONTMETRICS vFM
; // metrics structure
1127 ::GpiQueryFontMetrics( m_hPS
1128 ,sizeof(FONTMETRICS
)
1131 return YDEV2LOGREL(vFM
.lXHeight
);
1134 wxCoord
wxDC::GetCharWidth() const
1136 FONTMETRICS vFM
; // metrics structure
1138 ::GpiQueryFontMetrics( m_hPS
1139 ,sizeof(FONTMETRICS
)
1142 return XDEV2LOGREL(vFM
.lAveCharWidth
);
1145 void wxDC::DoGetTextExtent(
1146 const wxString
& rsString
1149 , wxCoord
* pvDescent
1150 , wxCoord
* pvExternalLeading
1154 POINTL avPoint
[TXTBOX_COUNT
];
1159 FONTMETRICS vFM
; // metrics structure
1162 ERRORID vErrorCode
; // last error id code
1163 wxFont
* pFontToUse
= (wxFont
*)pTheFont
;
1166 pFontToUse
= (wxFont
*)&m_font
;
1167 l
= rsString
.length();
1168 pStr
= (PCH
) rsString
.c_str();
1171 // In world coordinates.
1173 bRc
= ::GpiQueryTextBox( m_hPS
1176 ,TXTBOX_COUNT
// return maximum information
1177 ,avPoint
// array of coordinates points
1181 vErrorCode
= ::WinGetLastError(wxGetInstance());
1184 vPtMin
.x
= avPoint
[0].x
;
1185 vPtMax
.x
= avPoint
[0].x
;
1186 vPtMin
.y
= avPoint
[0].y
;
1187 vPtMax
.y
= avPoint
[0].y
;
1188 for (i
= 1; i
< 4; i
++)
1190 if(vPtMin
.x
> avPoint
[i
].x
) vPtMin
.x
= avPoint
[i
].x
;
1191 if(vPtMin
.y
> avPoint
[i
].y
) vPtMin
.y
= avPoint
[i
].y
;
1192 if(vPtMax
.x
< avPoint
[i
].x
) vPtMax
.x
= avPoint
[i
].x
;
1193 if(vPtMax
.y
< avPoint
[i
].y
) vPtMax
.y
= avPoint
[i
].y
;
1195 ::GpiQueryFontMetrics( m_hPS
1196 ,sizeof(FONTMETRICS
)
1201 *pvX
= (wxCoord
)(vPtMax
.x
- vPtMin
.x
+ 1);
1203 *pvY
= (wxCoord
)(vPtMax
.y
- vPtMin
.y
+ 1);
1205 *pvDescent
= vFM
.lMaxDescender
;
1206 if (pvExternalLeading
)
1207 *pvExternalLeading
= vFM
.lExternalLeading
;
1210 void wxDC::SetMapMode( int mode
)
1215 void wxDC::SetUserScale(double x
, double y
)
1220 SetMapMode(m_mappingMode
);
1223 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1225 m_signX
= xLeftRight
? 1 : -1;
1226 m_signY
= yBottomUp
? -1 : 1;
1228 SetMapMode(m_mappingMode
);
1231 void wxDC::SetSystemScale(double x
, double y
)
1236 SetMapMode(m_mappingMode
);
1239 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
1244 void wxDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
1248 ::GpiQueryPageViewport( m_hPS
1255 ::GpiSetPageViewport( m_hPS
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