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
150 m_brush
.GetColour().Set("WHITE");
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(m_vRclPaint
.yTop
- y
);
231 vRect
.xRight
= XLOG2DEV(x
+ width
);
232 vRect
.yBottom
= YLOG2DEV(m_vRclPaint
.yTop
- (y
+ height
));
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(
364 vPoint
[0].y
= m_vRclPaint
.yTop
- vY1
;
366 vPoint
[1].y
= m_vRclPaint
.yTop
- vY2
;
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
);
442 dAnglmid
= (dAngl1
+ dAngl2
)/2.;
443 vXm
= vXc
+ dRadius
* cos(dAnglmid
);
444 vYm
= vYc
+ dRadius
* sin(dAnglmid
);
447 // Ellipse main axis (r,q), (p,s) with center at (0,0) */
453 ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default
455 vPtlPos
.x
= vX1
; // Loads x-coordinate
456 vPtlPos
.y
= vY1
; // Loads y-coordinate
457 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
462 ::GpiPointArc(m_hPS
, vPtlArc
); // Draws the arc
465 void wxDC::DoDrawCheckMark(
476 vPoint
[1].x
= vX1
+ vWidth
;
477 vPoint
[1].y
= vY1
+ vHeight
;
479 ::GpiMove(m_hPS
, &vPoint
[0]);
480 ::GpiBox( m_hPS
// handle to a presentation space
481 ,DRO_OUTLINE
// draw the box outline ? or ?
482 ,&vPoint
[1] // address of the corner
483 ,0L // horizontal corner radius
484 ,0L // vertical corner radius
486 if(vWidth
> 4 && vHeight
> 4)
490 vPoint
[0].x
+= 2; vPoint
[0].y
+= 2;
491 vPoint
[1].x
-= 2; vPoint
[1].y
-= 2;
492 ::GpiMove(m_hPS
, &vPoint
[0]);
493 ::GpiLine(m_hPS
, &vPoint
[1]);
495 vPoint
[0].x
= vPoint
[1].x
;
497 ::GpiMove(m_hPS
, &vPoint
[0]);
498 ::GpiLine(m_hPS
, &vPoint
[1]);
502 void wxDC::DoDrawPoint(
510 vPoint
.y
= m_vRclPaint
.yTop
- vY
;
511 ::GpiSetPel(m_hPS
, &vPoint
);
514 void wxDC::DoDrawPolygon(
522 ULONG ulCount
= 1; // Number of polygons.
523 POLYGON vPlgn
; // polygon.
524 ULONG flOptions
= 0L; // Drawing options.
526 //////////////////////////////////////////////////////////////////////////////
527 // This contains fields of option bits... to draw boundary lines as well as
528 // the area interior.
530 // Drawing boundary lines:
531 // POLYGON_NOBOUNDARY Does not draw boundary lines.
532 // POLYGON_BOUNDARY Draws boundary lines (the default).
534 // Construction of the area interior:
535 // POLYGON_ALTERNATE Constructs interior in alternate mode
537 // POLYGON_WINDING Constructs interior in winding mode.
538 //////////////////////////////////////////////////////////////////////////////
540 ULONG flModel
= 0L; // Drawing model.
542 //////////////////////////////////////////////////////////////////////////////
544 // POLYGON_INCL Fill is inclusive of bottom right (the default).
545 // POLYGON_EXCL Fill is exclusive of bottom right.
546 // This is provided to aid migration from other graphics models.
547 //////////////////////////////////////////////////////////////////////////////
549 LONG lHits
= 0L; // Correlation/error indicator.
552 int nIsTRANSPARENT
= 0;
553 LONG lBorderColor
= 0L;
556 lBorderColor
= m_pen
.GetColour().GetPixel();
557 lColor
= m_brush
.GetColour().GetPixel();
558 if(m_brush
.GetStyle() == wxTRANSPARENT
)
562 vPlgn
.aPointl
= (POINTL
*) calloc( n
+ 1
564 ); // well, new will call malloc
566 for(i
= 0; i
< n
; i
++)
568 vPlgn
.aPointl
[i
].x
= vPoints
[i
].x
; // +xoffset;
569 vPlgn
.aPointl
[i
].y
= vPoints
[i
].y
; // +yoffset;
571 flModel
= POLYGON_BOUNDARY
;
572 if(nFillStyle
== wxWINDING_RULE
)
573 flModel
|= POLYGON_WINDING
;
575 flModel
|= POLYGON_ALTERNATE
;
580 ::GpiSetColor(m_hPS
, lBorderColor
);
581 ::GpiMove(m_hPS
, &vPoint
);
582 lHits
= ::GpiPolygons(m_hPS
, ulCount
, &vPlgn
, flOptions
, flModel
);
586 void wxDC::DoDrawLines(
596 vPoint
.x
= vPoints
[0].x
+ vXoffset
;
597 vPoint
.y
= vPoints
[0].y
+ vYoffset
;
598 ::GpiMove(m_hPS
, &vPoint
);
600 LONG lBorderColor
= m_pen
.GetColour().GetPixel();
602 ::GpiSetColor(m_hPS
, lBorderColor
);
603 for(i
= 1; i
< n
; i
++)
605 vPoint
.x
= vPoints
[0].x
+ vXoffset
;
606 vPoint
.y
= vPoints
[0].y
+ vYoffset
;
607 ::GpiLine(m_hPS
, &vPoint
);
611 void wxDC::DoDrawRectangle(
622 int nIsTRANSPARENT
= 0;
625 vPoint
[0].y
= m_vRclPaint
.yTop
- (vY
+ vHeight
);
626 vPoint
[1].x
= vX
+ vWidth
;
627 vPoint
[1].y
= m_vRclPaint
.yTop
- vY
;
628 ::GpiMove(m_hPS
, &vPoint
[0]);
629 lColor
= m_brush
.GetColour().GetPixel();
630 lBorderColor
= m_pen
.GetColour().GetPixel();
631 if (m_brush
.GetStyle() == wxTRANSPARENT
)
633 if(lColor
== lBorderColor
|| nIsTRANSPARENT
)
635 lControl
= DRO_OUTLINEFILL
; //DRO_FILL;
636 if(m_brush
.GetStyle() == wxTRANSPARENT
)
637 lControl
= DRO_OUTLINE
;
639 ::GpiSetColor(m_hPS
, lColor
);
640 ::GpiBox( m_hPS
// handle to a presentation space
641 ,lControl
// draw the box outline ? or ?
642 ,&vPoint
[1] // address of the corner
643 ,0L // horizontal corner radius
644 ,0L // vertical corner radius
649 lControl
= DRO_OUTLINE
;
663 vPoint
[0].x
= vX
+ 1;
664 vPoint
[0].y
= m_vRclPaint
.yTop
- (vY
+ vHeight
) + 1;
665 vPoint
[1].x
= vX
+ vWidth
- 2;
666 vPoint
[1].y
= m_vRclPaint
.yTop
- (vY
+ 2);
667 ::GpiMove(m_hPS
, &vPoint
[0]);
677 void wxDC::DoDrawRoundedRectangle(
689 vPoint
[0].y
= YLOG2DEV(vY
) - vHeight
;
690 vPoint
[1].x
= vX
+ vWidth
;
692 ::GpiMove(m_hPS
, &vPoint
[0]);
694 lControl
= DRO_OUTLINEFILL
; //DRO_FILL;
695 if (m_brush
.GetStyle() == wxTRANSPARENT
)
696 lControl
= DRO_OUTLINE
;
697 ::GpiBox( m_hPS
// handle to a presentation space
698 ,DRO_OUTLINE
// draw the box outline ? or ?
699 ,&vPoint
[1] // address of the corner
700 ,(LONG
)dRadius
// horizontal corner radius
701 ,(LONG
)dRadius
// vertical corner radius
705 // Draw Ellipse within box (x,y) - (x+width, y+height)
706 void wxDC::DoDrawEllipse(
713 POINTL vPtlPos
; // Structure for current position
714 FIXED vFxMult
; // Multiplier for ellipse
715 ARCPARAMS vArcp
; // Structure for arc parameters
718 vArcp
.lQ
= vHeight
/2;
721 ::GpiSetArcParams( m_hPS
723 ); // Sets parameters to default
724 vPtlPos
.x
= vX
+ vWidth
/2; // Loads x-coordinate
725 vPtlPos
.y
= vY
+ vHeight
/2; // Loads y-coordinate
728 ); // Sets current position
729 vFxMult
= MAKEFIXED(1, 0); /* Sets multiplier */
732 // DRO_FILL, DRO_OTLINEFILL - where to get
737 ); // Draws full arc with center at current position
740 void wxDC::DoDrawEllipticArc(
749 POINTL vPtlPos
; // Structure for current position
750 FIXED vFxMult
; // Multiplier for ellipse
751 ARCPARAMS vArcp
; // Structure for arc parameters
753 FIXED vFSweepa
; // Start angle, sweep angle
758 dFractPart
= modf(dSa
,&dIntPart
);
759 vFSa
= MAKEFIXED((int)dIntPart
, (int)(dFractPart
* 0xffff) );
760 dFractPart
= modf(dEa
- dSa
, &dIntPart
);
761 vFSweepa
= MAKEFIXED((int)dIntPart
, (int)(dFractPart
* 0xffff) );
764 // Ellipse main axis (r,q), (p,s) with center at (0,0)
767 vArcp
.lQ
= vHeight
/2;
770 ::GpiSetArcParams(m_hPS
, &vArcp
); // Sets parameters to default
771 vPtlPos
.x
= vX
+ vWidth
/2 * (1. + cos(DegToRad(dSa
))); // Loads x-coordinate
772 vPtlPos
.y
= vY
+ vHeight
/2 * (1. + sin(DegToRad(dSa
))); // Loads y-coordinate
773 ::GpiMove(m_hPS
, &vPtlPos
); // Sets current position
776 // May be not to the center ?
778 vPtlPos
.x
= vX
+ vWidth
/2 ; // Loads x-coordinate
779 vPtlPos
.y
= vY
+ vHeight
/2; // Loads y-coordinate
780 vFxMult
= MAKEFIXED(1, 0); // Sets multiplier
783 // DRO_FILL, DRO_OTLINEFILL - where to get
785 ::GpiPartialArc( m_hPS
793 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
)
798 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
799 ,wxCoord x
, wxCoord y
806 void wxDC::DoDrawText(
807 const wxString
& rsText
818 void wxDC::DrawAnyText(
819 const wxString
& rsText
824 int nOldBackground
= 0;
829 // prepare for drawing the text
833 // Set text color attributes
835 if (m_textForegroundColour
.Ok())
838 ,(int)m_textForegroundColour
.GetPixel()
842 if (m_textBackgroundColour
.Ok())
844 nOldBackground
= SetTextBkColor( m_hPS
845 ,(int)m_textBackgroundColour
.GetPixel()
854 lHits
= ::GpiCharStringAt( m_hPS
861 wxLogLastError(wxT("TextOut"));
865 // Restore the old parameters (text foreground colour may be left because
866 // it never is set to anything else, but background should remain
867 // transparent even if we just drew an opaque string)
869 if (m_textBackgroundColour
.Ok())
870 SetTextBkColor( m_hPS
878 void wxDC::DoDrawRotatedText(
879 const wxString
& rsText
897 DoDrawText(text, x, y);
902 wxFillLogFont(&lf, &m_font);
904 // GDI wants the angle in tenth of degree
905 long angle10 = (long)(angle * 10);
906 lf.lfEscapement = angle10;
907 lf. lfOrientation = angle10;
909 HFONT hfont = ::CreateFontIndirect(&lf);
912 wxLogLastError("CreateFont");
916 HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
918 DrawAnyText(text, x, y);
920 (void)::SelectObject(GetHdc(), hfontOld);
923 // call the bounding box by adding all four vertices of the rectangle
924 // containing the text to it (simpler and probably not slower than
925 // determining which of them is really topmost/leftmost/...)
927 GetTextExtent(text, &w, &h);
929 double rad = DegToRad(angle);
931 // "upper left" and "upper right"
932 CalcBoundingBox(x, y);
933 CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
934 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
936 // "bottom left" and "bottom right"
937 x += (wxCoord)(h*sin(rad));
938 y += (wxCoord)(h*cos(rad));
939 CalcBoundingBox(x, y);
940 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
945 // ---------------------------------------------------------------------------
947 // ---------------------------------------------------------------------------
949 void wxDC::SetPalette(const wxPalette
& palette
)
959 // Set the old object temporarily, in case the assignment deletes an object
960 // that's not yet selected out.
972 m_font
.SetPS(m_hPS
); // this will realize the font
976 HFONT hFont
= m_font
.GetResourceHandle();
977 if (hFont
== (HFONT
) NULL
)
979 wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont."));
982 m_hOldFont
= (WXHFONT
) hFont
;
984 } // end of wxDC::SetFont
990 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1006 m_pen
.SetPS((HPS
)m_hOldPen
);
1013 if (m_pen
.GetResourceHandle())
1017 m_hOldPen
= m_pen
.GetPS();
1022 void wxDC::SetBrush(
1023 const wxBrush
& rBrush
1026 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1028 if (m_brush
== rBrush
)
1042 m_brush
.SetPS((HPS
)m_hOldBrush
);
1049 if (m_brush
.GetResourceHandle())
1051 m_brush
.SetPS(m_hPS
);
1053 m_hOldBrush
= m_brush
.GetPS();
1056 } // end of wxDC::SetBrush
1058 void wxDC::SetBackground(const wxBrush
& brush
)
1063 void wxDC::SetBackgroundMode(
1067 m_backgroundMode
= nMode
;
1070 void wxDC::SetLogicalFunction(int function
)
1075 void wxDC::SetRop(WXHDC dc
)
1077 if (!dc
|| m_logicalFunction
< 0)
1081 // These may be wrong
1082 switch (m_logicalFunction
)
1084 // TODO: Figure this stuff out
1085 // case wxXOR: c_rop = R2_XORPEN; break;
1086 // case wxXOR: c_rop = R2_NOTXORPEN; break;
1087 // case wxINVERT: c_rop = R2_NOT; break;
1088 // case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
1089 // case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
1090 // case wxCLEAR: c_rop = R2_WHITE; break;
1091 // case wxSET: c_rop = R2_BLACK; break;
1092 // case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
1093 // case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
1094 // case wxAND: c_rop = R2_MASKPEN; break;
1095 // case wxOR: c_rop = R2_MERGEPEN; break;
1096 // case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
1101 // c_rop = R2_COPYPEN;
1104 // SetROP2((HDC) dc, c_rop);
1107 bool wxDC::StartDoc(const wxString
& message
)
1109 // We might be previewing, so return TRUE to let it continue.
1117 void wxDC::StartPage()
1121 void wxDC::EndPage()
1125 // ---------------------------------------------------------------------------
1127 // ---------------------------------------------------------------------------
1129 wxCoord
wxDC::GetCharHeight() const
1131 FONTMETRICS vFM
; // metrics structure
1133 ::GpiQueryFontMetrics( m_hPS
1134 ,sizeof(FONTMETRICS
)
1137 return YDEV2LOGREL(vFM
.lXHeight
);
1140 wxCoord
wxDC::GetCharWidth() const
1142 FONTMETRICS vFM
; // metrics structure
1144 ::GpiQueryFontMetrics( m_hPS
1145 ,sizeof(FONTMETRICS
)
1148 return XDEV2LOGREL(vFM
.lAveCharWidth
);
1151 void wxDC::DoGetTextExtent(
1152 const wxString
& rsString
1155 , wxCoord
* pvDescent
1156 , wxCoord
* pvExternalLeading
1160 POINTL avPoint
[TXTBOX_COUNT
];
1165 FONTMETRICS vFM
; // metrics structure
1168 ERRORID vErrorCode
; // last error id code
1169 wxFont
* pFontToUse
= (wxFont
*)pTheFont
;
1172 pFontToUse
= (wxFont
*)&m_font
;
1173 l
= rsString
.length();
1174 pStr
= (PCH
) rsString
.c_str();
1177 // In world coordinates.
1179 bRc
= ::GpiQueryTextBox( m_hPS
1182 ,TXTBOX_COUNT
// return maximum information
1183 ,avPoint
// array of coordinates points
1187 vErrorCode
= ::WinGetLastError(wxGetInstance());
1190 vPtMin
.x
= avPoint
[0].x
;
1191 vPtMax
.x
= avPoint
[0].x
;
1192 vPtMin
.y
= avPoint
[0].y
;
1193 vPtMax
.y
= avPoint
[0].y
;
1194 for (i
= 1; i
< 4; i
++)
1196 if(vPtMin
.x
> avPoint
[i
].x
) vPtMin
.x
= avPoint
[i
].x
;
1197 if(vPtMin
.y
> avPoint
[i
].y
) vPtMin
.y
= avPoint
[i
].y
;
1198 if(vPtMax
.x
< avPoint
[i
].x
) vPtMax
.x
= avPoint
[i
].x
;
1199 if(vPtMax
.y
< avPoint
[i
].y
) vPtMax
.y
= avPoint
[i
].y
;
1201 ::GpiQueryFontMetrics( m_hPS
1202 ,sizeof(FONTMETRICS
)
1207 *pvX
= (wxCoord
)(vPtMax
.x
- vPtMin
.x
+ 1);
1209 *pvY
= (wxCoord
)(vPtMax
.y
- vPtMin
.y
+ 1);
1211 *pvDescent
= vFM
.lMaxDescender
;
1212 if (pvExternalLeading
)
1213 *pvExternalLeading
= vFM
.lExternalLeading
;
1216 void wxDC::SetMapMode( int mode
)
1221 void wxDC::SetUserScale(double x
, double y
)
1226 SetMapMode(m_mappingMode
);
1229 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1231 m_signX
= xLeftRight
? 1 : -1;
1232 m_signY
= yBottomUp
? -1 : 1;
1234 SetMapMode(m_mappingMode
);
1237 void wxDC::SetSystemScale(double x
, double y
)
1242 SetMapMode(m_mappingMode
);
1245 void wxDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
1250 void wxDC::SetDeviceOrigin(
1257 m_deviceOriginX
= x
;
1258 m_deviceOriginY
= y
;
1259 ::GpiQueryPageViewport( m_hPS
1266 ::GpiSetPageViewport( m_hPS
1271 // ---------------------------------------------------------------------------
1272 // coordinates transformations
1273 // ---------------------------------------------------------------------------
1275 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
1277 return (wxCoord
) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1280 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
1282 return (wxCoord
) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1285 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
1287 return (wxCoord
) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1290 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
1292 return (wxCoord
) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1295 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
1297 return (wxCoord
) ((x
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1300 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
1302 return (wxCoord
) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1305 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
1307 return (wxCoord
) ((y
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1310 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
1312 return (wxCoord
) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1315 // ---------------------------------------------------------------------------
1317 // ---------------------------------------------------------------------------
1319 bool wxDC::DoBlit( wxCoord xdest
1334 void wxDC::DoGetSize( int* width
, int* height
) const
1339 void wxDC::DoGetSizeMM( int* width
, int* height
) const
1344 wxSize
wxDC::GetPPI() const
1349 return (wxSize(x
,y
));
1352 void wxDC::SetLogicalScale( double x
, double y
)
1357 #if WXWIN_COMPATIBILITY
1358 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1359 float *descent
, float *externalLeading
,
1360 wxFont
*theFont
, bool use16bit
) const
1362 wxCoord x1
, y1
, descent1
, externalLeading1
;
1363 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1366 *descent
= descent1
;
1367 if (externalLeading
)
1368 *externalLeading
= externalLeading1
;
1372 // ---------------------------------------------------------------------------
1373 // spline drawing code
1374 // ---------------------------------------------------------------------------
1378 class wxSpline
: public wxObject
1384 wxSpline(wxList
*list
);
1385 void DeletePoints();
1387 // Doesn't delete points
1391 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1393 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1394 double a3
, double b3
, double a4
, double b4
);
1395 void wx_clear_stack();
1396 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1397 double *y3
, double *x4
, double *y4
);
1398 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1399 double x4
, double y4
);
1400 static bool wx_spline_add_point(double x
, double y
);
1401 static void wx_spline_draw_point_array(wxDC
*dc
);
1402 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1404 void wxDC::DoDrawSpline(wxList
*list
)
1406 wxSpline
spline(list
);
1408 wx_draw_open_spline(this, &spline
);
1411 wxList wx_spline_point_list
;
1413 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1416 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1417 double x1
, y1
, x2
, y2
;
1419 wxNode
*node
= spline
->points
->First();
1420 p
= (wxPoint
*)node
->Data();
1425 node
= node
->Next();
1426 p
= (wxPoint
*)node
->Data();
1430 cx1
= (double)((x1
+ x2
) / 2);
1431 cy1
= (double)((y1
+ y2
) / 2);
1432 cx2
= (double)((cx1
+ x2
) / 2);
1433 cy2
= (double)((cy1
+ y2
) / 2);
1435 wx_spline_add_point(x1
, y1
);
1437 while ((node
= node
->Next()) != NULL
)
1439 p
= (wxPoint
*)node
->Data();
1444 cx4
= (double)(x1
+ x2
) / 2;
1445 cy4
= (double)(y1
+ y2
) / 2;
1446 cx3
= (double)(x1
+ cx4
) / 2;
1447 cy3
= (double)(y1
+ cy4
) / 2;
1449 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1453 cx2
= (double)(cx1
+ x2
) / 2;
1454 cy2
= (double)(cy1
+ y2
) / 2;
1457 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1458 wx_spline_add_point(x2
, y2
);
1460 wx_spline_draw_point_array(dc
);
1464 /********************* CURVES FOR SPLINES *****************************
1466 The following spline drawing routine is from
1468 "An Algorithm for High-Speed Curve Generation"
1469 by George Merrill Chaikin,
1470 Computer Graphics and Image Processing, 3, Academic Press,
1475 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1476 Computer Graphics and Image Processing, 4, Academic Press,
1479 ***********************************************************************/
1481 #define half(z1, z2) ((z1+z2)/2.0)
1484 /* iterative version */
1486 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1489 register double xmid
, ymid
;
1490 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1493 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1495 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1496 xmid
= (double)half(x2
, x3
);
1497 ymid
= (double)half(y2
, y3
);
1498 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1499 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1500 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1501 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1503 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1504 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1505 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1506 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1512 /* utilities used by spline drawing routines */
1515 typedef struct wx_spline_stack_struct
{
1516 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1520 #define SPLINE_STACK_DEPTH 20
1521 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1522 static Stack
*wx_stack_top
;
1523 static int wx_stack_count
;
1525 void wx_clear_stack()
1527 wx_stack_top
= wx_spline_stack
;
1531 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1533 wx_stack_top
->x1
= x1
;
1534 wx_stack_top
->y1
= y1
;
1535 wx_stack_top
->x2
= x2
;
1536 wx_stack_top
->y2
= y2
;
1537 wx_stack_top
->x3
= x3
;
1538 wx_stack_top
->y3
= y3
;
1539 wx_stack_top
->x4
= x4
;
1540 wx_stack_top
->y4
= y4
;
1545 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1546 double *x3
, double *y3
, double *x4
, double *y4
)
1548 if (wx_stack_count
== 0)
1552 *x1
= wx_stack_top
->x1
;
1553 *y1
= wx_stack_top
->y1
;
1554 *x2
= wx_stack_top
->x2
;
1555 *y2
= wx_stack_top
->y2
;
1556 *x3
= wx_stack_top
->x3
;
1557 *y3
= wx_stack_top
->y3
;
1558 *x4
= wx_stack_top
->x4
;
1559 *y4
= wx_stack_top
->y4
;
1563 static bool wx_spline_add_point(double x
, double y
)
1565 wxPoint
*point
= new wxPoint
;
1568 wx_spline_point_list
.Append((wxObject
*)point
);
1572 static void wx_spline_draw_point_array(wxDC
*dc
)
1574 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1575 wxNode
*node
= wx_spline_point_list
.First();
1578 wxPoint
*point
= (wxPoint
*)node
->Data();
1581 node
= wx_spline_point_list
.First();
1585 wxSpline::wxSpline(wxList
*list
)
1590 wxSpline::~wxSpline()
1594 void wxSpline::DeletePoints()
1596 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1598 wxPoint
*point
= (wxPoint
*)node
->Data();
1606 #endif // wxUSE_SPLINES