]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dc.cpp
My iconv (GLIBC 2.2) uses char** as the second
[wxWidgets.git] / src / os2 / dc.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: dc.cpp
3// Purpose: wxDC class
fb46a9a6 4// Author: David Webster
0e320a79 5// Modified by:
fb46a9a6 6// Created: 10/14/99
0e320a79 7// RCS-ID: $Id$
fb46a9a6
DW
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
fb46a9a6
DW
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifndef WX_PRECOMP
16 #include "wx/window.h"
17 #include "wx/dc.h"
18 #include "wx/utils.h"
19 #include "wx/dialog.h"
20 #include "wx/app.h"
21 #include "wx/bitmap.h"
22 #include "wx/dcmemory.h"
23 #include "wx/log.h"
24 #include "wx/icon.h"
0e320a79
DW
25#endif
26
fb46a9a6
DW
27#include "wx/dcprint.h"
28
29#include <string.h>
30#include <math.h>
31
32#include "wx/os2/private.h"
0e320a79 33
fb46a9a6 34 IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
0e320a79 35
fb46a9a6 36// ---------------------------------------------------------------------------
0e320a79 37// constants
fb46a9a6 38// ---------------------------------------------------------------------------
1408104d 39
fb46a9a6 40static const int VIEWPORT_EXTENT = 1000;
1408104d 41
fb46a9a6
DW
42static const int MM_POINTS = 9;
43static const int MM_METRIC = 10;
1408104d 44
f6bcfd97
BP
45// usually this is defined in math.h
46#ifndef M_PI
47 static const double M_PI = 3.14159265358979323846;
48#endif // M_PI
49
50// ---------------------------------------------------------------------------
51// private functions
52// ---------------------------------------------------------------------------
53
54// convert degrees to radians
55static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
56
7e99520b
DW
57int SetTextColor(
58 HPS hPS
59, int nForegroundColour
60)
61{
62 CHARBUNDLE vCbnd;
63
64 vCbnd.lColor = nForegroundColour;
65 ::GpiSetAttrs( hPS // presentation-space handle
66 ,PRIM_CHAR // Char primitive.
67 ,CBB_COLOR // sets color.
68 ,0 //
69 ,&vCbnd // buffer for attributes.
70 );
71 return 0;
72}
73
74int QueryTextBkColor(
75 HPS hPS
76)
77{
78 CHARBUNDLE vCbnd;
79
f44fdfb0
DW
80 ::GpiQueryAttrs( hPS // presentation-space handle
81 ,PRIM_CHAR // Char primitive.
82 ,CBB_BACK_COLOR // Background color.
83 ,&vCbnd // buffer for attributes.
84 );
7e99520b
DW
85 return vCbnd.lBackColor;
86}
87
88
89int SetTextBkColor(
90 HPS hPS
91, int nBackgroundColour
92)
93{
94 CHARBUNDLE vCbnd;
95 int rc;
96
97 rc = QueryTextBkColor(hPS);
98
99 vCbnd.lBackColor = nBackgroundColour;
100 ::GpiSetAttrs(hPS, // presentation-space handle
101 PRIM_CHAR, // Char primitive.
102 CBB_BACK_COLOR, // sets color.
103 0,
104 &vCbnd // buffer for attributes.
105 );
106 return rc;
107}
108
109int SetBkMode(
110 HPS hPS
111, int nBackgroundMode
112)
113{
114 if(nBackgroundMode == wxTRANSPARENT)
115 ::GpiSetBackMix( hPS
116 ,BM_LEAVEALONE
117 );
118 else
119 // the background of the primitive takes over whatever is underneath.
120 ::GpiSetBackMix( hPS
121 ,BM_OVERPAINT
122 );
123 return 0;
124}
125
fb46a9a6
DW
126// ===========================================================================
127// implementation
128// ===========================================================================
1408104d 129
fb46a9a6 130// ---------------------------------------------------------------------------
0e320a79 131// wxDC
fb46a9a6 132// ---------------------------------------------------------------------------
0e320a79
DW
133
134wxDC::wxDC(void)
135{
7e99520b 136 m_pCanvas = NULL;
c3d43472 137
7e99520b
DW
138 m_hOldBitmap = 0;
139 m_hOldPen = 0;
140 m_hOldBrush = 0;
141 m_hOldFont = 0;
142 m_hOldPalette = 0;
ce44c50e 143
7e99520b
DW
144 m_bOwnsDC = FALSE;
145 m_hDC = 0;
7e99520b
DW
146 m_hOldPS = NULL;
147 m_hPS = NULL;
e99762c0 148 m_bIsPaintTime = FALSE; // True at Paint Time
8d854fa9 149 m_brush.GetColour().Set("WHITE");
e1a688e4 150} // end of wxDC::wxDC
0e320a79
DW
151
152wxDC::~wxDC(void)
153{
e1a688e4
DW
154 if ( m_hDC != 0 )
155 {
156 SelectOldObjects(m_hDC);
157
158 // if we own the HDC, we delete it, otherwise we just release it
159
160 if (m_bOwnsDC)
161 {
162 if(m_hPS)
163 {
164 ::GpiAssociate(m_hPS, NULLHANDLE);
165 ::GpiDestroyPS(m_hPS);
166 }
167 m_hPS = NULLHANDLE;
168 ::DevCloseDC((HDC)m_hDC);
169 }
170 else
171 {
172 //
173 // Just Dissacociate, not destroy if we don't own the DC
174 //
175 if(m_hPS)
176 {
177 ::GpiAssociate(m_hPS, NULLHANDLE);
178 }
179 }
180 }
181} // end of wxDC::~wxDC
0e320a79 182
fb46a9a6
DW
183// This will select current objects out of the DC,
184// which is what you have to do before deleting the
185// DC.
f07bb01b
DW
186void wxDC::SelectOldObjects(
187 WXHDC hPS
188)
0e320a79 189{
f07bb01b 190 if (hPS)
fb46a9a6 191 {
f6bcfd97 192 if (m_hOldBitmap)
fb46a9a6 193 {
f07bb01b 194 ::GpiSetBitmap(hPS, (HBITMAP) m_hOldBitmap);
f6bcfd97 195 if (m_vSelectedBitmap.Ok())
fb46a9a6 196 {
f6bcfd97 197 m_vSelectedBitmap.SetSelectedInto(NULL);
fb46a9a6
DW
198 }
199 }
f6bcfd97 200 m_hOldBitmap = 0;
f07bb01b
DW
201 //
202 // OS/2 has no other native GDI objects to set in a PS/DC like windows
203 //
f6bcfd97 204 m_hOldPen = 0;
f6bcfd97 205 m_hOldBrush = 0;
f6bcfd97 206 m_hOldFont = 0;
f6bcfd97 207 m_hOldPalette = 0;
fb46a9a6 208 }
0e320a79 209
f6bcfd97
BP
210 m_brush = wxNullBrush;
211 m_pen = wxNullPen;
212 m_palette = wxNullPalette;
213 m_font = wxNullFont;
fb46a9a6 214 m_backgroundBrush = wxNullBrush;
f6bcfd97 215 m_vSelectedBitmap = wxNullBitmap;
e1a688e4 216} // end of wxDC::SelectOldObjects
0e320a79 217
fb46a9a6
DW
218// ---------------------------------------------------------------------------
219// clipping
220// ---------------------------------------------------------------------------
0e320a79 221
fa5593ac
DW
222#define DO_SET_CLIPPING_BOX() \
223{ \
224 RECTL rect; \
225 \
226 ::GpiQueryClipBox(m_hPS, &rect); \
227 \
228 m_clipX1 = (wxCoord) XDEV2LOG(rect.xLeft); \
229 m_clipY1 = (wxCoord) YDEV2LOG(rect.yTop); \
230 m_clipX2 = (wxCoord) XDEV2LOG(rect.xRight); \
231 m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \
fb46a9a6 232}
0e320a79 233
fa5593ac
DW
234void wxDC::DoSetClippingRegion(
235 wxCoord x
236, wxCoord y
237, wxCoord width
238, wxCoord height
239)
0e320a79 240{
fa5593ac
DW
241 RECTL vRect;
242
243 m_clipping = TRUE;
244 vRect.xLeft = XLOG2DEV(x);
8d854fa9 245 vRect.yTop = YLOG2DEV(m_vRclPaint.yTop - y);
fa5593ac 246 vRect.xRight = XLOG2DEV(x + width);
8d854fa9 247 vRect.yBottom = YLOG2DEV(m_vRclPaint.yTop - (y + height));
fa5593ac
DW
248 ::GpiIntersectClipRectangle(m_hPS, &vRect);
249 DO_SET_CLIPPING_BOX()
250} // end of wxDC::DoSetClippingRegion
251
252void wxDC::DoSetClippingRegionAsRegion(
253 const wxRegion& rRegion
254)
0e320a79 255{
fa5593ac
DW
256 wxCHECK_RET(rRegion.GetHRGN(), wxT("invalid clipping region"));
257 HRGN hRgnOld;
258
259 m_clipping = TRUE;
260 ::GpiSetClipRegion( m_hPS
261 ,(HRGN)rRegion.GetHRGN()
262 ,&hRgnOld
263 );
264 DO_SET_CLIPPING_BOX()
265} // end of wxDC::DoSetClippingRegionAsRegion
0e320a79 266
fb46a9a6 267void wxDC::DestroyClippingRegion(void)
0e320a79 268{
fa5593ac
DW
269 if (m_clipping && m_hPS)
270 {
271 HRGN hRgnOld;
272 RECTL vRect;
273
274 // TODO: this should restore the previous clipped region
275 // so that OnPaint processing works correctly, and
276 // the update doesn't get destroyed after the first
277 // DestroyClippingRegion
278 vRect.xLeft = XLOG2DEV(0);
279 vRect.yTop = YLOG2DEV(32000);
280 vRect.xRight = XLOG2DEV(32000);
281 vRect.yBottom = YLOG2DEV(0);
282
283 HRGN hRgn = ::GpiCreateRegion(m_hPS, 1, &vRect);
284
285 ::GpiSetClipRegion(m_hPS, hRgn, &hRgnOld);
286 }
287 m_clipping = FALSE;
288} // end of wxDC::DestroyClippingRegion
0e320a79 289
fb46a9a6
DW
290// ---------------------------------------------------------------------------
291// query capabilities
292// ---------------------------------------------------------------------------
0e320a79 293
fb46a9a6 294bool wxDC::CanDrawBitmap() const
0e320a79 295{
fb46a9a6
DW
296 return TRUE;
297}
0e320a79 298
fb46a9a6 299bool wxDC::CanGetTextExtent() const
0e320a79 300{
f07bb01b 301 LONG lTechnology = 0L;
0e320a79 302
f07bb01b
DW
303 ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY, 1L, &lTechnology);
304 return (lTechnology == CAPS_TECH_RASTER_DISPLAY) || (lTechnology == CAPS_TECH_RASTER_PRINTER);
305} // end of wxDC::CanGetTextExtent
1408104d
DW
306
307int wxDC::GetDepth() const
0e320a79 308{
f07bb01b
DW
309 LONG lArray[CAPS_COLOR_BITCOUNT];
310 int nBitsPerPixel;
311
312 if(::DevQueryCaps( GetHDC()
313 ,CAPS_FAMILY
314 ,CAPS_COLOR_BITCOUNT
315 ,lArray
316 ))
317 {
318 nBitsPerPixel = (int)lArray[CAPS_COLOR_BITCOUNT];
319 }
320 return nBitsPerPixel;
321} // end of wxDC::GetDepth
0e320a79 322
fb46a9a6
DW
323// ---------------------------------------------------------------------------
324// drawing
325// ---------------------------------------------------------------------------
0e320a79 326
1408104d 327void wxDC::Clear()
0e320a79 328{
445c7bca 329 ::GpiErase(m_hPS);
1408104d 330}
0e320a79 331
51c1d535
DW
332void wxDC::DoFloodFill(
333 wxCoord vX
334, wxCoord vY
335, const wxColour& rCol
336, int nStyle
337)
0e320a79 338{
51c1d535
DW
339 POINTL vPtlPos;
340 LONG lColor;
341 LONG lOptions;
342
343 vPtlPos.x = vX; // Loads x-coordinate
344 vPtlPos.y = vY; // Loads y-coordinate
345 ::GpiMove(m_hPS, &vPtlPos); // Sets current position
346 lColor = rCol.GetPixel();
347 lOptions = FF_BOUNDARY;
348 if(wxFLOOD_SURFACE == nStyle)
349 lOptions = FF_SURFACE;
350
351 ::GpiFloodFill(m_hPS, lOptions, lColor);
1408104d 352}
0e320a79 353
51c1d535
DW
354bool wxDC::DoGetPixel(
355 wxCoord vX
356, wxCoord vY
357, wxColour* pCol
358) const
1408104d 359{
51c1d535
DW
360 POINTL vPoint;
361 LONG lColor;
362
363 vPoint.x = vX;
364 vPoint.y = vY;
365 lColor = ::GpiSetPel(m_hPS, &vPoint);
fa5593ac 366 pCol->Set((unsigned long)lColor);
51c1d535
DW
367 if(lColor>= 0)
368 return(TRUE);
6f952627 369 else
51c1d535 370 return(FALSE);
1408104d 371}
0e320a79 372
f07bb01b
DW
373void wxDC::DoCrossHair(
374 wxCoord vX
375, wxCoord vY
376)
0e320a79 377{
f07bb01b
DW
378 wxCoord vX1 = vX - VIEWPORT_EXTENT;
379 wxCoord vY1 = vY - VIEWPORT_EXTENT;
380 wxCoord vX2 = vX + VIEWPORT_EXTENT;
381 wxCoord vY2 = vY + VIEWPORT_EXTENT;
382 POINTL vPoint[4];
383
384 vPoint[0].x = vX1;
385 vPoint[0].y = m_vRclPaint.yTop - vY;
386
387 vPoint[1].x = vX2;
388 vPoint[1].y = m_vRclPaint.yTop - vY;
389
390 ::GpiMove(m_hPS, &vPoint[0]);
391 ::GpiLine(m_hPS, &vPoint[1]);
392
393 vPoint[2].x = vX;
394 vPoint[2].y = m_vRclPaint.yTop - vY1;
395
396 vPoint[3].x = vX;
397 vPoint[3].y = m_vRclPaint.yTop - vY2;
398
399 ::GpiMove(m_hPS, &vPoint[2]);
400 ::GpiLine(m_hPS, &vPoint[3]);
401} // end of wxDC::DoCrossHair
1408104d 402
7e99520b
DW
403void wxDC::DoDrawLine(
404 wxCoord vX1
405, wxCoord vY1
406, wxCoord vX2
407, wxCoord vY2
408)
0e320a79 409{
7e99520b
DW
410 POINTL vPoint[2];
411
412 vPoint[0].x = vX1;
8d854fa9 413 vPoint[0].y = m_vRclPaint.yTop - vY1;
7e99520b 414 vPoint[1].x = vX2;
8d854fa9 415 vPoint[1].y = m_vRclPaint.yTop - vY2;
7e99520b
DW
416 ::GpiMove(m_hPS, &vPoint[0]);
417 ::GpiLine(m_hPS, &vPoint[1]);
f07bb01b 418} // end of wxDC::DoDrawLine
1408104d 419
51c1d535
DW
420//////////////////////////////////////////////////////////////////////////////
421// Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
422// and ending at (x2, y2). The current pen is used for the outline and the
423// current brush for filling the shape. The arc is drawn in an anticlockwise
424// direction from the start point to the end point.
425//////////////////////////////////////////////////////////////////////////////
426void wxDC::DoDrawArc(
427 wxCoord vX1
428, wxCoord vY1
429, wxCoord vX2
430, wxCoord vY2
431, wxCoord vXc
432, wxCoord vYc
433)
1408104d 434{
51c1d535
DW
435 POINTL vPtlPos;
436 POINTL vPtlArc[2]; // Structure for current position
437 int nDx;
438 int nDy;
439 double dRadius;
440 double dAngl1;
441 double dAngl2;
442 double dAnglmid;
443 wxCoord vXm;
444 wxCoord vYm;
445 ARCPARAMS vArcp; // Structure for arc parameters
446
447 if((vX1 == vXc && vY1 == vXc) || (vX2 == vXc && vY2 == vXc))
448 return; // Draw point ??
449 dRadius = 0.5 * ( hypot( (double)(vY1 - vYc)
450 ,(double)(vX1 - vXc)
451 ) +
452 hypot( (double)(vY2 - vYc)
453 ,(double)(vX2 - vXc)
454 )
455 );
456
457 dAngl1 = atan2( (double)(vY1 - vYc)
458 ,(double)(vX1 - vXc)
459 );
460 dAngl2 = atan2( (double)(vY2 - vYc)
461 ,(double)(vX2 - vXc)
462 );
463 if(dAngl2 < dAngl1)
464 dAngl2 += M_PI * 2;
465
466 //
467 // GpiPointArc can't draw full arc
468 //
469 if(dAngl2 == dAngl1 || (vX1 == vX2 && vY1 == vY2) )
470 {
471 //
472 // Medium point
473 //
474 dAnglmid = (dAngl1 + dAngl2)/2. + M_PI;
475 vXm = vXc + dRadius * cos(dAnglmid);
476 vYm = vYc + dRadius * sin(dAnglmid);
e99762c0
DW
477 DoDrawArc( vX1, vY1
478 ,vXm, vYm
479 ,vXc, vYc
51c1d535 480 );
e99762c0
DW
481 DoDrawArc( vXm, vYm
482 ,vX2, vY2
483 ,vXc, vYc
51c1d535
DW
484 );
485 return;
486 }
487
488 //
489 // Medium point
490 //
491 dAnglmid = (dAngl1 + dAngl2)/2.;
492 vXm = vXc + dRadius * cos(dAnglmid);
493 vYm = vYc + dRadius * sin(dAnglmid);
494
495 //
496 // Ellipse main axis (r,q), (p,s) with center at (0,0) */
497 //
498 vArcp.lR = 0;
499 vArcp.lQ = 1;
500 vArcp.lP = 1;
501 vArcp.lS = 0;
502 ::GpiSetArcParams(m_hPS, &vArcp); // Sets parameters to default
503
504 vPtlPos.x = vX1; // Loads x-coordinate
505 vPtlPos.y = vY1; // Loads y-coordinate
506 ::GpiMove(m_hPS, &vPtlPos); // Sets current position
e99762c0
DW
507 vPtlArc[0].x = vXm;
508 vPtlArc[0].y = vYm;
51c1d535
DW
509 vPtlArc[1].x = vX2;
510 vPtlArc[1].y = vY2;
511 ::GpiPointArc(m_hPS, vPtlArc); // Draws the arc
f07bb01b 512} // end of wxDC::DoDrawArc
1408104d 513
51c1d535
DW
514void wxDC::DoDrawCheckMark(
515 wxCoord vX1
516, wxCoord vY1
517, wxCoord vWidth
518, wxCoord vHeight
519)
f6bcfd97 520{
51c1d535
DW
521 POINTL vPoint[2];
522
523 vPoint[0].x = vX1;
524 vPoint[0].y = vY1;
525 vPoint[1].x = vX1 + vWidth;
526 vPoint[1].y = vY1 + vHeight;
527
528 ::GpiMove(m_hPS, &vPoint[0]);
529 ::GpiBox( m_hPS // handle to a presentation space
530 ,DRO_OUTLINE // draw the box outline ? or ?
531 ,&vPoint[1] // address of the corner
532 ,0L // horizontal corner radius
533 ,0L // vertical corner radius
534 );
535 if(vWidth > 4 && vHeight > 4)
536 {
537 int nTmp;
538
539 vPoint[0].x += 2; vPoint[0].y += 2;
540 vPoint[1].x -= 2; vPoint[1].y -= 2;
541 ::GpiMove(m_hPS, &vPoint[0]);
542 ::GpiLine(m_hPS, &vPoint[1]);
543 nTmp = vPoint[0].x;
544 vPoint[0].x = vPoint[1].x;
545 vPoint[1].x = nTmp;
546 ::GpiMove(m_hPS, &vPoint[0]);
547 ::GpiLine(m_hPS, &vPoint[1]);
548 }
f07bb01b 549} // end of wxDC::DoDrawCheckMark
f6bcfd97 550
51c1d535
DW
551void wxDC::DoDrawPoint(
552 wxCoord vX
553, wxCoord vY
554)
1408104d 555{
51c1d535
DW
556 POINTL vPoint;
557
558 vPoint.x = vX;
8d854fa9 559 vPoint.y = m_vRclPaint.yTop - vY;
51c1d535 560 ::GpiSetPel(m_hPS, &vPoint);
f07bb01b 561} // end of wxDC::DoDrawPoint
1408104d 562
51c1d535
DW
563void wxDC::DoDrawPolygon(
564 int n
565, wxPoint vPoints[]
566, wxCoord vXoffset
567, wxCoord vYoffset
568, int nFillStyle
569)
1408104d 570{
51c1d535
DW
571 ULONG ulCount = 1; // Number of polygons.
572 POLYGON vPlgn; // polygon.
573 ULONG flOptions = 0L; // Drawing options.
574
575//////////////////////////////////////////////////////////////////////////////
576// This contains fields of option bits... to draw boundary lines as well as
577// the area interior.
578//
579// Drawing boundary lines:
580// POLYGON_NOBOUNDARY Does not draw boundary lines.
581// POLYGON_BOUNDARY Draws boundary lines (the default).
582//
583// Construction of the area interior:
584// POLYGON_ALTERNATE Constructs interior in alternate mode
585// (the default).
586// POLYGON_WINDING Constructs interior in winding mode.
587//////////////////////////////////////////////////////////////////////////////
588
589 ULONG flModel = 0L; // Drawing model.
590
591//////////////////////////////////////////////////////////////////////////////
592// Drawing model.
593// POLYGON_INCL Fill is inclusive of bottom right (the default).
594// POLYGON_EXCL Fill is exclusive of bottom right.
595// This is provided to aid migration from other graphics models.
596//////////////////////////////////////////////////////////////////////////////
597
598 LONG lHits = 0L; // Correlation/error indicator.
599 POINTL vPoint;
600 int i;
601 int nIsTRANSPARENT = 0;
602 LONG lBorderColor = 0L;
603 LONG lColor = 0L;
604
605 lBorderColor = m_pen.GetColour().GetPixel();
606 lColor = m_brush.GetColour().GetPixel();
607 if(m_brush.GetStyle() == wxTRANSPARENT)
608 nIsTRANSPARENT = 1;
609
610 vPlgn.ulPoints = n;
611 vPlgn.aPointl = (POINTL*) calloc( n + 1
612 ,sizeof(POINTL)
613 ); // well, new will call malloc
614
615 for(i = 0; i < n; i++)
616 {
617 vPlgn.aPointl[i].x = vPoints[i].x; // +xoffset;
618 vPlgn.aPointl[i].y = vPoints[i].y; // +yoffset;
619 }
620 flModel = POLYGON_BOUNDARY;
621 if(nFillStyle == wxWINDING_RULE)
622 flModel |= POLYGON_WINDING;
623 else
624 flModel |= POLYGON_ALTERNATE;
625
626 vPoint.x = vXoffset;
627 vPoint.y = vYoffset;
628
629 ::GpiSetColor(m_hPS, lBorderColor);
630 ::GpiMove(m_hPS, &vPoint);
631 lHits = ::GpiPolygons(m_hPS, ulCount, &vPlgn, flOptions, flModel);
632 free(vPlgn.aPointl);
f07bb01b 633} // end of wxDC::DoDrawPolygon
1408104d 634
51c1d535
DW
635void wxDC::DoDrawLines(
636 int n
637, wxPoint vPoints[]
638, wxCoord vXoffset
639, wxCoord vYoffset
640)
1408104d 641{
51c1d535
DW
642 int i;
643 POINTL vPoint;
644
645 vPoint.x = vPoints[0].x + vXoffset;
646 vPoint.y = vPoints[0].y + vYoffset;
647 ::GpiMove(m_hPS, &vPoint);
648
649 LONG lBorderColor = m_pen.GetColour().GetPixel();
650
651 ::GpiSetColor(m_hPS, lBorderColor);
652 for(i = 1; i < n; i++)
653 {
654 vPoint.x = vPoints[0].x + vXoffset;
655 vPoint.y = vPoints[0].y + vYoffset;
656 ::GpiLine(m_hPS, &vPoint);
657 }
f07bb01b 658} // end of wxDC::DoDrawLines
1408104d 659
7e99520b 660void wxDC::DoDrawRectangle(
f44fdfb0 661 wxCoord vX
7e99520b
DW
662, wxCoord vY
663, wxCoord vWidth
664, wxCoord vHeight
665)
1408104d 666{
7e99520b 667 POINTL vPoint[2];
51c1d535
DW
668 LONG lControl;
669 LONG lColor;
670 LONG lBorderColor;
671 int nIsTRANSPARENT = 0;
7e99520b
DW
672
673 vPoint[0].x = vX;
8d854fa9 674 vPoint[0].y = m_vRclPaint.yTop - (vY + vHeight);
f44fdfb0 675 vPoint[1].x = vX + vWidth;
8d854fa9 676 vPoint[1].y = m_vRclPaint.yTop - vY;
7e99520b 677 ::GpiMove(m_hPS, &vPoint[0]);
51c1d535
DW
678 lColor = m_brush.GetColour().GetPixel();
679 lBorderColor = m_pen.GetColour().GetPixel();
680 if (m_brush.GetStyle() == wxTRANSPARENT)
681 nIsTRANSPARENT = 1;
682 if(lColor == lBorderColor || nIsTRANSPARENT)
683 {
684 lControl = DRO_OUTLINEFILL; //DRO_FILL;
685 if(m_brush.GetStyle() == wxTRANSPARENT)
686 lControl = DRO_OUTLINE;
687
8d854fa9 688 ::GpiSetColor(m_hPS, lColor);
51c1d535
DW
689 ::GpiBox( m_hPS // handle to a presentation space
690 ,lControl // draw the box outline ? or ?
691 ,&vPoint[1] // address of the corner
692 ,0L // horizontal corner radius
693 ,0L // vertical corner radius
694 );
695 }
696 else
697 {
698 lControl = DRO_OUTLINE;
699 ::GpiSetColor( m_hPS
700 ,lBorderColor
701 );
702 ::GpiBox( m_hPS
703 ,lControl
704 ,&vPoint[1]
705 ,0L
706 ,0L
707 );
708 lControl = DRO_FILL;
709 ::GpiSetColor( m_hPS
710 ,lColor
711 );
8d854fa9
DW
712 vPoint[0].x = vX + 1;
713 vPoint[0].y = m_vRclPaint.yTop - (vY + vHeight) + 1;
714 vPoint[1].x = vX + vWidth - 2;
715 vPoint[1].y = m_vRclPaint.yTop - (vY + 2);
716 ::GpiMove(m_hPS, &vPoint[0]);
51c1d535
DW
717 ::GpiBox( m_hPS
718 ,lControl
719 ,&vPoint[1]
720 ,0L
721 ,0L
722 );
723 }
f07bb01b 724} // end of wxDC::DoDrawRectangle
1408104d 725
7e99520b
DW
726void wxDC::DoDrawRoundedRectangle(
727 wxCoord vX
728, wxCoord vY
729, wxCoord vWidth
730, wxCoord vHeight
731, double dRadius
732)
1408104d 733{
7e99520b 734 POINTL vPoint[2];
51c1d535 735 LONG lControl;
7e99520b
DW
736
737 vPoint[0].x = vX;
8d854fa9 738 vPoint[0].y = YLOG2DEV(vY) - vHeight;
7e99520b 739 vPoint[1].x = vX + vWidth;
8d854fa9 740 vPoint[1].y = vY;
7e99520b 741 ::GpiMove(m_hPS, &vPoint[0]);
51c1d535
DW
742
743 lControl = DRO_OUTLINEFILL; //DRO_FILL;
744 if (m_brush.GetStyle() == wxTRANSPARENT)
745 lControl = DRO_OUTLINE;
f44fdfb0
DW
746 ::GpiBox( m_hPS // handle to a presentation space
747 ,DRO_OUTLINE // draw the box outline ? or ?
748 ,&vPoint[1] // address of the corner
749 ,(LONG)dRadius // horizontal corner radius
750 ,(LONG)dRadius // vertical corner radius
7e99520b 751 );
f07bb01b 752} // end of wxDC::DoDrawRoundedRectangle
1408104d 753
51c1d535
DW
754// Draw Ellipse within box (x,y) - (x+width, y+height)
755void wxDC::DoDrawEllipse(
756 wxCoord vX
757, wxCoord vY
758, wxCoord vWidth
759, wxCoord vHeight
760)
1408104d 761{
51c1d535
DW
762 POINTL vPtlPos; // Structure for current position
763 FIXED vFxMult; // Multiplier for ellipse
764 ARCPARAMS vArcp; // Structure for arc parameters
765
766 vArcp.lR = 0;
767 vArcp.lQ = vHeight/2;
768 vArcp.lP = vWidth/2;
769 vArcp.lS = 0;
770 ::GpiSetArcParams( m_hPS
771 ,&vArcp
772 ); // Sets parameters to default
773 vPtlPos.x = vX + vWidth/2; // Loads x-coordinate
774 vPtlPos.y = vY + vHeight/2; // Loads y-coordinate
775 ::GpiMove( m_hPS
776 ,&vPtlPos
777 ); // Sets current position
778 vFxMult = MAKEFIXED(1, 0); /* Sets multiplier */
779
780 //
781 // DRO_FILL, DRO_OTLINEFILL - where to get
782 //
783 ::GpiFullArc( m_hPS
784 ,DRO_OUTLINE
785 ,vFxMult
786 ); // Draws full arc with center at current position
f07bb01b 787} // end of wxDC::DoDrawEllipse
1408104d 788
51c1d535
DW
789void wxDC::DoDrawEllipticArc(
790 wxCoord vX
791, wxCoord vY
792, wxCoord vWidth
793, wxCoord vHeight
794, double dSa
795, double dEa
796)
1408104d 797{
51c1d535
DW
798 POINTL vPtlPos; // Structure for current position
799 FIXED vFxMult; // Multiplier for ellipse
800 ARCPARAMS vArcp; // Structure for arc parameters
801 FIXED vFSa;
802 FIXED vFSweepa; // Start angle, sweep angle
803 double dIntPart;
804 double dFractPart;
805 double dRadius;
806
807 dFractPart = modf(dSa,&dIntPart);
808 vFSa = MAKEFIXED((int)dIntPart, (int)(dFractPart * 0xffff) );
809 dFractPart = modf(dEa - dSa, &dIntPart);
810 vFSweepa = MAKEFIXED((int)dIntPart, (int)(dFractPart * 0xffff) );
811
812 //
813 // Ellipse main axis (r,q), (p,s) with center at (0,0)
814 //
815 vArcp.lR = 0;
816 vArcp.lQ = vHeight/2;
817 vArcp.lP = vWidth/2;
818 vArcp.lS = 0;
819 ::GpiSetArcParams(m_hPS, &vArcp); // Sets parameters to default
820 vPtlPos.x = vX + vWidth/2 * (1. + cos(DegToRad(dSa))); // Loads x-coordinate
821 vPtlPos.y = vY + vHeight/2 * (1. + sin(DegToRad(dSa))); // Loads y-coordinate
822 ::GpiMove(m_hPS, &vPtlPos); // Sets current position
823
824 //
825 // May be not to the center ?
826 //
827 vPtlPos.x = vX + vWidth/2 ; // Loads x-coordinate
828 vPtlPos.y = vY + vHeight/2; // Loads y-coordinate
829 vFxMult = MAKEFIXED(1, 0); // Sets multiplier
830
831 //
832 // DRO_FILL, DRO_OTLINEFILL - where to get
833 //
834 ::GpiPartialArc( m_hPS
835 ,&vPtlPos
836 ,vFxMult
837 ,vFSa
838 ,vFSweepa
839 );
f07bb01b 840} // end of wxDC::DoDrawEllipticArc
1408104d 841
f07bb01b
DW
842void wxDC::DoDrawIcon(
843 const wxIcon& rIcon
844, wxCoord vX
845, wxCoord vY
846)
1408104d 847{
f07bb01b
DW
848 wxCHECK_RET( rIcon.Ok(), wxT("invalid icon in DrawIcon") );
849
850 ::WinDrawPointer( GetHPS()
851 ,vX
852 ,vY
853 ,(HPOINTER)GetHiconOf(rIcon)
854 ,DP_NORMAL
855 );
856} // end of wxDC::DoDrawIcon
857
858void wxDC::DoDrawBitmap(
859 const wxBitmap& rBmp
860, wxCoord vX
861, wxCoord vY
862, bool bUseMask
863)
1408104d 864{
f07bb01b
DW
865 POINTL vPoint = {vX, vY};
866
867 ::WinDrawBitmap( GetHPS()
868 ,(HBITMAP)GetHbitmapOf(rBmp)
869 ,NULL
870 ,&vPoint
871 ,0L
872 ,0L
873 ,DBM_NORMAL
874 );
875} // end of wxDC::DoDrawBitmap
1408104d 876
7e99520b
DW
877void wxDC::DoDrawText(
878 const wxString& rsText
879, wxCoord vX
880, wxCoord vY
881)
1408104d 882{
7e99520b
DW
883 DrawAnyText( rsText
884 ,vX
885 ,vY
886 );
1408104d
DW
887}
888
7e99520b
DW
889void wxDC::DrawAnyText(
890 const wxString& rsText
891, wxCoord vX
892, wxCoord vY
893)
f6bcfd97 894{
7e99520b
DW
895 int nOldBackground = 0;
896 POINTL vPtlStart;
897 LONG lHits;
f6bcfd97 898
7e99520b
DW
899 //
900 // prepare for drawing the text
901 //
902
903 //
904 // Set text color attributes
905 //
906 if (m_textForegroundColour.Ok())
907 {
908 SetTextColor( m_hPS
909 ,(int)m_textForegroundColour.GetPixel()
910 );
911 }
912
913 if (m_textBackgroundColour.Ok())
914 {
915 nOldBackground = SetTextBkColor( m_hPS
916 ,(int)m_textBackgroundColour.GetPixel()
917 );
918 }
919 SetBkMode( m_hPS
920 ,m_backgroundMode
921 );
922 vPtlStart.x = vX;
923 vPtlStart.y = vY;
924
925 lHits = ::GpiCharStringAt( m_hPS
926 ,&vPtlStart
927 ,rsText.length()
928 ,(PCH)rsText.c_str()
929 );
930 if (lHits != GPI_OK)
931 {
932 wxLogLastError(wxT("TextOut"));
933 }
934
935 //
936 // Restore the old parameters (text foreground colour may be left because
937 // it never is set to anything else, but background should remain
938 // transparent even if we just drew an opaque string)
939 //
940 if (m_textBackgroundColour.Ok())
941 SetTextBkColor( m_hPS
942 ,nOldBackground
943 );
944 SetBkMode( m_hPS
945 ,wxTRANSPARENT
946 );
947}
948
949void wxDC::DoDrawRotatedText(
950 const wxString& rsText
951, wxCoord vX
952, wxCoord vY
953, double dAngle
954)
c8ce6bcc 955{
7e99520b
DW
956 if (dAngle == 0.0)
957 {
958 DoDrawText( rsText
959 ,vX
960 ,vY
961 );
962 }
963
c8ce6bcc
DW
964 // TODO:
965 /*
966 if ( angle == 0.0 )
967 {
968 DoDrawText(text, x, y);
969 }
970 else
971 {
972 LOGFONT lf;
973 wxFillLogFont(&lf, &m_font);
974
975 // GDI wants the angle in tenth of degree
976 long angle10 = (long)(angle * 10);
977 lf.lfEscapement = angle10;
978 lf. lfOrientation = angle10;
979
980 HFONT hfont = ::CreateFontIndirect(&lf);
981 if ( !hfont )
982 {
983 wxLogLastError("CreateFont");
984 }
985 else
986 {
987 HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
988
989 DrawAnyText(text, x, y);
990
991 (void)::SelectObject(GetHdc(), hfontOld);
992 }
993
994 // call the bounding box by adding all four vertices of the rectangle
995 // containing the text to it (simpler and probably not slower than
996 // determining which of them is really topmost/leftmost/...)
997 wxCoord w, h;
998 GetTextExtent(text, &w, &h);
999
1000 double rad = DegToRad(angle);
1001
1002 // "upper left" and "upper right"
1003 CalcBoundingBox(x, y);
1004 CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
1005 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
1006
1007 // "bottom left" and "bottom right"
1008 x += (wxCoord)(h*sin(rad));
1009 y += (wxCoord)(h*cos(rad));
1010 CalcBoundingBox(x, y);
1011 CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
1012 }
1013*/
1014}
1015
fb46a9a6
DW
1016// ---------------------------------------------------------------------------
1017// set GDI objects
1018// ---------------------------------------------------------------------------
1408104d 1019
fb46a9a6 1020void wxDC::SetPalette(const wxPalette& palette)
1408104d
DW
1021{
1022 // TODO
1023}
1024
f6bcfd97
BP
1025void wxDC::SetFont(
1026 const wxFont& rFont
1027)
1408104d 1028{
f6bcfd97
BP
1029 //
1030 // Set the old object temporarily, in case the assignment deletes an object
1031 // that's not yet selected out.
1032 //
1033 if (m_hOldFont)
1034 {
f6bcfd97
BP
1035 m_hOldFont = 0;
1036 }
f6bcfd97 1037 m_font = rFont;
f6bcfd97
BP
1038 if (!rFont.Ok())
1039 {
f6bcfd97
BP
1040 m_hOldFont = 0;
1041 }
1042
e99762c0
DW
1043 m_font.SetPS(m_hPS); // this will realize the font
1044
1045 if (m_font.Ok())
f6bcfd97 1046 {
e99762c0 1047 HFONT hFont = m_font.GetResourceHandle();
f6bcfd97
BP
1048 if (hFont == (HFONT) NULL)
1049 {
1050 wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont."));
1051 }
1052 if (!m_hOldFont)
1053 m_hOldFont = (WXHFONT) hFont;
1054 }
e99762c0 1055} // end of wxDC::SetFont
1408104d 1056
7e99520b
DW
1057void wxDC::SetPen(
1058 const wxPen& rPen
1059)
1408104d 1060{
7e99520b
DW
1061 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1062
1063 if (m_pen == rPen)
1064 return;
1065 m_pen = rPen;
1066 if (!m_pen.Ok())
1067 return;
1068
26ac77db
DW
1069 if (m_hOldPen)
1070 m_hOldPen = 0L;
1071 m_pen = rPen;
7e99520b 1072
26ac77db 1073 if (!m_pen.Ok())
7e99520b 1074 {
26ac77db
DW
1075 if (m_hOldPen)
1076 {
1077 m_pen.SetPS((HPS)m_hOldPen);
1078 }
1079 m_hOldPen = 0L;
7e99520b 1080 }
51c1d535 1081
26ac77db 1082 if (m_pen.Ok())
51c1d535 1083 {
26ac77db
DW
1084 if (m_pen.GetResourceHandle())
1085 {
1086 m_pen.SetPS(m_hPS);
1087 if (!m_hOldPen)
1088 m_hOldPen = m_pen.GetPS();
1089 }
51c1d535 1090 }
1408104d 1091}
7e99520b 1092
51c1d535
DW
1093void wxDC::SetBrush(
1094 const wxBrush& rBrush
1095)
1408104d 1096{
15f03b25
DW
1097 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1098
1099 if (m_brush == rBrush)
1100 return;
1101 m_brush = rBrush;
1102 if (!m_brush.Ok())
1103 return;
1104
1105 if (m_hOldBrush)
1106 m_hOldBrush = 0L;
1107 m_brush = rBrush;
1108
1109 if (!m_brush.Ok())
1110 {
1111 if (m_hOldBrush)
1112 {
1113 m_brush.SetPS((HPS)m_hOldBrush);
1114 }
1115 m_hOldBrush = 0L;
1116 }
1117
1118 if (m_brush.Ok())
1119 {
1120 if (m_brush.GetResourceHandle())
1121 {
1122 m_brush.SetPS(m_hPS);
1123 if (!m_hOldBrush)
1124 m_hOldBrush = m_brush.GetPS();
1125 }
1126 }
1127} // end of wxDC::SetBrush
1408104d 1128
fb46a9a6 1129void wxDC::SetBackground(const wxBrush& brush)
1408104d
DW
1130{
1131 // TODO
1132}
1133
7e99520b
DW
1134void wxDC::SetBackgroundMode(
1135 int nMode
1136)
1408104d 1137{
7e99520b 1138 m_backgroundMode = nMode;
1408104d
DW
1139}
1140
fb46a9a6 1141void wxDC::SetLogicalFunction(int function)
1408104d
DW
1142{
1143 // TODO
1144}
1408104d 1145
ce44c50e
DW
1146void wxDC::SetRop(WXHDC dc)
1147{
1148 if (!dc || m_logicalFunction < 0)
1149 return;
1150
1151 int c_rop;
1152 // These may be wrong
1153 switch (m_logicalFunction)
1154 {
1155// TODO: Figure this stuff out
1156 // case wxXOR: c_rop = R2_XORPEN; break;
1157// case wxXOR: c_rop = R2_NOTXORPEN; break;
1158// case wxINVERT: c_rop = R2_NOT; break;
1159// case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
1160// case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
1161// case wxCLEAR: c_rop = R2_WHITE; break;
1162// case wxSET: c_rop = R2_BLACK; break;
1163// case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
1164// case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
1165// case wxAND: c_rop = R2_MASKPEN; break;
1166// case wxOR: c_rop = R2_MERGEPEN; break;
1167// case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
1168// case wxEQUIV:
1169// case wxNAND:
1170// case wxCOPY:
1171 default:
1172// c_rop = R2_COPYPEN;
1173 break;
1174 }
1175// SetROP2((HDC) dc, c_rop);
1176}
1177
fb46a9a6 1178bool wxDC::StartDoc(const wxString& message)
ce44c50e 1179{
fb46a9a6
DW
1180 // We might be previewing, so return TRUE to let it continue.
1181 return TRUE;
1182}
1183
1184void wxDC::EndDoc()
1185{
1186}
1187
1188void wxDC::StartPage()
1189{
1190}
1191
1192void wxDC::EndPage()
1193{
1194}
1195
1196// ---------------------------------------------------------------------------
1197// text metrics
1198// ---------------------------------------------------------------------------
1199
7cdc2f1e 1200wxCoord wxDC::GetCharHeight() const
fb46a9a6 1201{
05a8bfed
DW
1202 FONTMETRICS vFM; // metrics structure
1203
1204 ::GpiQueryFontMetrics( m_hPS
1205 ,sizeof(FONTMETRICS)
1206 ,&vFM
1207 );
1208 return YDEV2LOGREL(vFM.lXHeight);
fb46a9a6
DW
1209}
1210
7cdc2f1e 1211wxCoord wxDC::GetCharWidth() const
fb46a9a6 1212{
05a8bfed
DW
1213 FONTMETRICS vFM; // metrics structure
1214
1215 ::GpiQueryFontMetrics( m_hPS
1216 ,sizeof(FONTMETRICS)
1217 ,&vFM
1218 );
1219 return XDEV2LOGREL(vFM.lAveCharWidth);
7e99520b
DW
1220}
1221
1222void wxDC::DoGetTextExtent(
1223 const wxString& rsString
1224, wxCoord* pvX
1225, wxCoord* pvY
f44fdfb0 1226, wxCoord* pvDescent
7e99520b
DW
1227, wxCoord* pvExternalLeading
1228, wxFont* pTheFont
1229) const
1230{
1231 POINTL avPoint[TXTBOX_COUNT];
1232 POINTL vPtMin;
1233 POINTL vPtMax;
1234 int i;
1235 int l;
1236 FONTMETRICS vFM; // metrics structure
1237 BOOL bRc;
1238 char* pStr;
1239 ERRORID vErrorCode; // last error id code
1240 wxFont* pFontToUse = (wxFont*)pTheFont;
1241
2c4a8d17
DW
1242 char zMsg[128]; // DEBUG
1243 wxString sError;
1244
7e99520b
DW
1245 if (!pFontToUse)
1246 pFontToUse = (wxFont*)&m_font;
1247 l = rsString.length();
1248 pStr = (PCH) rsString.c_str();
fb46a9a6 1249
7e99520b
DW
1250 //
1251 // In world coordinates.
1252 //
1253 bRc = ::GpiQueryTextBox( m_hPS
1254 ,l
1255 ,pStr
1256 ,TXTBOX_COUNT // return maximum information
1257 ,avPoint // array of coordinates points
f44fdfb0 1258 );
7e99520b
DW
1259 if(!bRc)
1260 {
1261 vErrorCode = ::WinGetLastError(wxGetInstance());
2c4a8d17
DW
1262 sError = wxPMErrorToStr(vErrorCode);
1263 // DEBUG
1264 sprintf(zMsg, "GpiQueryTextBox for %s: failed with Error: %x - %s", pStr, vErrorCode, sError.c_str());
1265 (void)wxMessageBox( "wxWindows Menu sample"
1266 ,zMsg
1267 ,wxICON_INFORMATION
1268 );
7e99520b
DW
1269 }
1270
1271 vPtMin.x = avPoint[0].x;
1272 vPtMax.x = avPoint[0].x;
1273 vPtMin.y = avPoint[0].y;
1274 vPtMax.y = avPoint[0].y;
1275 for (i = 1; i < 4; i++)
1276 {
1277 if(vPtMin.x > avPoint[i].x) vPtMin.x = avPoint[i].x;
1278 if(vPtMin.y > avPoint[i].y) vPtMin.y = avPoint[i].y;
1279 if(vPtMax.x < avPoint[i].x) vPtMax.x = avPoint[i].x;
1280 if(vPtMax.y < avPoint[i].y) vPtMax.y = avPoint[i].y;
1281 }
1282 ::GpiQueryFontMetrics( m_hPS
1283 ,sizeof(FONTMETRICS)
1284 ,&vFM
1285 );
1286
1287 if (pvX)
1288 *pvX = (wxCoord)(vPtMax.x - vPtMin.x + 1);
1289 if (pvY)
1290 *pvY = (wxCoord)(vPtMax.y - vPtMin.y + 1);
1291 if (pvDescent)
1292 *pvDescent = vFM.lMaxDescender;
f44fdfb0 1293 if (pvExternalLeading)
7e99520b 1294 *pvExternalLeading = vFM.lExternalLeading;
fb46a9a6
DW
1295}
1296
1297void wxDC::SetMapMode( int mode )
1298{
1299 // TODO:
1300};
1301
1302void wxDC::SetUserScale(double x, double y)
1303{
1304 m_userScaleX = x;
1305 m_userScaleY = y;
1306
1307 SetMapMode(m_mappingMode);
1308}
1309
1310void wxDC::SetAxisOrientation(bool xLeftRight, bool yBottomUp)
1311{
1312 m_signX = xLeftRight ? 1 : -1;
1313 m_signY = yBottomUp ? -1 : 1;
1314
1315 SetMapMode(m_mappingMode);
1316}
1317
1318void wxDC::SetSystemScale(double x, double y)
1319{
1320 m_scaleX = x;
1321 m_scaleY = y;
1322
1323 SetMapMode(m_mappingMode);
1324}
1325
7cdc2f1e 1326void wxDC::SetLogicalOrigin( wxCoord x, wxCoord y )
fb46a9a6
DW
1327{
1328 // TODO:
1329};
1330
8d854fa9
DW
1331void wxDC::SetDeviceOrigin(
1332 wxCoord x
1333, wxCoord y
1334)
fb46a9a6 1335{
26ac77db
DW
1336 RECTL vRect;
1337
8d854fa9
DW
1338 m_deviceOriginX = x;
1339 m_deviceOriginY = y;
26ac77db
DW
1340 ::GpiQueryPageViewport( m_hPS
1341 ,&vRect
1342 );
1343 vRect.xLeft += x;
1344 vRect.xRight += x;
1345 vRect.yBottom -= y;
1346 vRect.yTop -= y;
1347 ::GpiSetPageViewport( m_hPS
1348 ,&vRect
1349 );
fb46a9a6
DW
1350};
1351
1352// ---------------------------------------------------------------------------
1353// coordinates transformations
1354// ---------------------------------------------------------------------------
1355
7cdc2f1e 1356wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
fb46a9a6 1357{
f6bcfd97
BP
1358 return (wxCoord) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX) - m_logicalOriginX);
1359}
fb46a9a6 1360
7cdc2f1e 1361wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
fb46a9a6 1362{
f6bcfd97
BP
1363 return (wxCoord) ((x)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX));
1364}
fb46a9a6 1365
7cdc2f1e 1366wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
fb46a9a6 1367{
f6bcfd97
BP
1368 return (wxCoord) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY) - m_logicalOriginY);
1369}
fb46a9a6 1370
7cdc2f1e 1371wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
fb46a9a6 1372{
f6bcfd97
BP
1373 return (wxCoord) ((y)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY));
1374}
fb46a9a6 1375
7cdc2f1e 1376wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
fb46a9a6 1377{
f6bcfd97
BP
1378 return (wxCoord) ((x - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX + m_deviceOriginX);
1379}
fb46a9a6 1380
7cdc2f1e 1381wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
fb46a9a6 1382{
f6bcfd97
BP
1383 return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX);
1384}
fb46a9a6 1385
7cdc2f1e 1386wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
fb46a9a6 1387{
f6bcfd97
BP
1388 return (wxCoord) ((y - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY + m_deviceOriginY);
1389}
fb46a9a6 1390
7cdc2f1e 1391wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
fb46a9a6 1392{
f6bcfd97
BP
1393 return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY);
1394}
fb46a9a6
DW
1395
1396// ---------------------------------------------------------------------------
1397// bit blit
1398// ---------------------------------------------------------------------------
1399
5afb9458
DW
1400bool wxDC::DoBlit(
1401 wxCoord vXdest
1402, wxCoord vYdest
1403, wxCoord vWidth
1404, wxCoord vHeight
1405, wxDC* pSource
1406, wxCoord vXsrc
1407, wxCoord vYsrc
1408, int nRop
1409, bool bUseMask
1410)
fb46a9a6 1411{
5afb9458
DW
1412 wxMask* pMask = NULL;
1413 CHARBUNDLE vCbnd;
1414 COLORREF vOldTextColor;
1415 COLORREF vOldBackground = ::GpiQueryBackColor(m_hPS);
5afb9458
DW
1416
1417 if (bUseMask)
1418 {
1419 const wxBitmap& rBmp = pSource->m_vSelectedBitmap;
1420
1421 pMask = rBmp.GetMask();
1422 if (!(rBmp.Ok() && pMask && pMask->GetMaskBitmap()))
1423 {
1424 bUseMask = FALSE;
1425 }
1426 }
1427
1428 ::GpiQueryAttrs( m_hPS
1429 ,PRIM_CHAR
1430 ,CBB_COLOR
1431 ,&vCbnd
1432 );
1433 vOldTextColor = (COLORREF)vCbnd.lColor;
1434
1435 if (m_textForegroundColour.Ok())
1436 {
1437 vCbnd.lColor = (LONG)m_textForegroundColour.GetPixel();
1438 ::GpiSetAttrs( m_hPS // presentation-space handle
1439 ,PRIM_CHAR // Char primitive.
1440 ,CBB_COLOR // sets color.
1441 ,0
1442 ,&vCbnd // buffer for attributes.
1443 );
1444 }
1445 if (m_textBackgroundColour.Ok())
1446 {
1447 ::GpiSetBackColor(m_hPS, (LONG)m_textBackgroundColour.GetPixel());
1448 }
1449
1450 LONG lRop = ROP_SRCCOPY;
1451
1452 switch (nRop)
1453 {
1454 case wxXOR: lRop = ROP_SRCINVERT; break;
1455 case wxINVERT: lRop = ROP_DSTINVERT; break;
1456 case wxOR_REVERSE: lRop = 0x00DD0228; break;
1457 case wxAND_REVERSE: lRop = ROP_SRCERASE; break;
1458 case wxCLEAR: lRop = ROP_ZERO; break;
1459 case wxSET: lRop = ROP_ONE; break;
1460 case wxOR_INVERT: lRop = ROP_MERGEPAINT; break;
1461 case wxAND: lRop = ROP_SRCAND; break;
1462 case wxOR: lRop = ROP_SRCPAINT; break;
1463 case wxEQUIV: lRop = 0x00990066; break;
1464 case wxNAND: lRop = 0x007700E6; break;
1465 case wxAND_INVERT: lRop = 0x00220326; break;
1466 case wxCOPY: lRop = ROP_SRCCOPY; break;
1467 case wxNO_OP: lRop = ROP_NOTSRCERASE; break;
1468 case wxSRC_INVERT: lRop = ROP_SRCINVERT; break;
1469 case wxNOR: lRop = ROP_NOTSRCCOPY; break;
1470 default:
1471 wxFAIL_MSG( wxT("unsupported logical function") );
1472 return FALSE;
1473 }
1474
1475 bool bSuccess;
b02121c3 1476
5afb9458
DW
1477 if (bUseMask)
1478 {
1479 //
1480 // Blit bitmap with mask
1481 //
1482
1483 //
b02121c3 1484 // Create a temp buffer bitmap and DCs/PSs to access it and the mask
5afb9458 1485 //
b02121c3
DW
1486 HDC hDCMask;
1487 HDC hDCBuffer;
1488 HPS hPSMask;
1489 HPS hPSBuffer;
1490 DEVOPENSTRUC vDOP = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1491 BITMAPINFOHEADER2 vBmpHdr;
1492 SIZEL vSize = {0, 0};
1493 LONG rc;
1494
1495 hDCMask = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE);
1496 hDCBuffer = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE);
1497 hPSMask = ::GpiCreatePS(vHabmain, hDCMask, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
1498 hPSBuffer = ::GpiCreatePS(vHabmain, hDCBuffer, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
1499
1500 memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2));
1501 vBmpHdr.cbFix = sizeof(BITMAPINFOHEADER2);
1502 vBmpHdr.cx = vWidth;
1503 vBmpHdr.cy = vHeight;
1504 vBmpHdr.cPlanes = 1;
1505 vBmpHdr.cBitCount = 24;
1506
1507 HBITMAP hBufBitmap = ::GpiCreateBitmap(GetHPS(), &vBmpHdr, 0L, NULL, NULL);
1508 POINTL aPoint1[4] = { 0, 0
1509 ,vWidth, vHeight
1510 ,vXdest, vYdest
1511 ,vXdest + vWidth, vYdest + vHeight
1512 };
1513 POINTL aPoint2[4] = { 0, 0
1514 ,vWidth, vHeight
1515 ,vXsrc, vYsrc
1516 ,vXsrc + vWidth, vYsrc + vHeight
1517 };
1518 POINTL aPoint3[4] = { vXdest, vYdest
23e356de
DW
1519 ,vXdest + vWidth, vYdest + vHeight
1520 ,vXsrc, vYsrc
1521 ,vXsrc + vWidth, vYsrc + vHeight
1522 };
1523 POINTL aPoint4[4] = { vXdest, vYdest
b02121c3
DW
1524 ,vXdest + vWidth, vYdest + vHeight
1525 ,0, 0
1526 ,vWidth, vHeight
1527 };
1528 ::GpiSetBitmap(hPSMask, (HBITMAP) pMask->GetMaskBitmap());
1529 ::GpiSetBitmap(hPSBuffer, (HBITMAP) hBufBitmap);
5afb9458 1530
b02121c3
DW
1531 //
1532 // Copy dest to buffer
1533 //
1534 rc = ::GpiBitBlt( hPSBuffer
1535 ,GetHPS()
1536 ,4L
1537 ,aPoint1
1538 ,ROP_SRCCOPY
1539 ,BBO_IGNORE
1540 );
1541 if (rc == GPI_ERROR)
1542 {
1543 wxLogLastError(wxT("BitBlt"));
1544 }
5afb9458 1545
b02121c3
DW
1546 //
1547 // Copy src to buffer using selected raster op
1548 //
1549 rc = ::GpiBitBlt( hPSBuffer
1550 ,GetHPS()
1551 ,4L
1552 ,aPoint2
1553 ,lRop
1554 ,BBO_IGNORE
1555 );
1556 if (rc == GPI_ERROR)
1557 {
1558 wxLogLastError(wxT("BitBlt"));
1559 }
5afb9458 1560
b02121c3
DW
1561 //
1562 // Set masked area in buffer to BLACK (pixel value 0)
1563 //
1564 COLORREF vPrevBkCol = ::GpiQueryBackColor(GetHPS());
1565 COLORREF vPrevCol = ::GpiQueryColor(GetHPS());
1566
1567 ::GpiSetBackColor(GetHPS(), OS2RGB(255, 255, 255));
1568 ::GpiSetColor(GetHPS(), OS2RGB(0, 0, 0));
1569
1570 rc = ::GpiBitBlt( hPSBuffer
1571 ,hPSMask
1572 ,4L
1573 ,aPoint2
1574 ,ROP_SRCAND
1575 ,BBO_IGNORE
1576 );
1577 if (rc == GPI_ERROR)
1578 {
1579 wxLogLastError(wxT("BitBlt"));
1580 }
5afb9458 1581
b02121c3
DW
1582 //
1583 // Set unmasked area in dest to BLACK
1584 //
1585 ::GpiSetBackColor(GetHPS(), OS2RGB(0, 0, 0));
1586 ::GpiSetColor(GetHPS(), OS2RGB(255, 255, 255));
1587 rc = ::GpiBitBlt( GetHPS()
1588 ,hPSMask
1589 ,4L
23e356de 1590 ,aPoint3
b02121c3
DW
1591 ,ROP_SRCAND
1592 ,BBO_IGNORE
1593 );
1594 if (rc == GPI_ERROR)
1595 {
1596 wxLogLastError(wxT("BitBlt"));
5afb9458 1597 }
b02121c3
DW
1598
1599 //
1600 // Restore colours to original values
1601 //
1602 ::GpiSetBackColor(GetHPS(), vPrevBkCol);
1603 ::GpiSetColor(GetHPS(), vPrevCol);
1604
1605 //
1606 // OR buffer to dest
1607 //
1608 rc = ::GpiBitBlt( GetHPS()
1609 ,hPSMask
1610 ,4L
23e356de 1611 ,aPoint4
b02121c3
DW
1612 ,ROP_SRCPAINT
1613 ,BBO_IGNORE
1614 );
1615 if (rc == GPI_ERROR)
1616 {
1617 bSuccess = FALSE;
1618 wxLogLastError(wxT("BitBlt"));
1619 }
1620
1621 //
1622 // Tidy up temporary DCs and bitmap
1623 //
1624 ::GpiSetBitmap(hPSMask, NULLHANDLE);
1625 ::GpiSetBitmap(hPSBuffer, NULLHANDLE);
1626 ::GpiDestroyPS(hPSMask);
1627 ::GpiDestroyPS(hPSBuffer);
1628 ::DevCloseDC(hDCMask);
1629 ::DevCloseDC(hDCBuffer);
1630 ::GpiDeleteBitmap(hBufBitmap);
1631 bSuccess = TRUE;
5afb9458 1632 }
b02121c3
DW
1633 else // no mask, just BitBlt() it
1634 {
1635 POINTL aPoint[4] = { vXdest, vYdest
1636 ,vXdest + vWidth, vYdest + vHeight
1637 ,vXsrc, vYsrc
1638 ,vXsrc + vWidth, vYsrc + vHeight
1639 };
1640
5afb9458
DW
1641 bSuccess = (::GpiBitBlt( m_hPS
1642 ,pSource->GetHPS()
1643 ,4L
1644 ,aPoint
1645 ,lRop
1646 ,BBO_IGNORE
1647 ) != GPI_ERROR);
1648 if (!bSuccess )
1649 {
1650 wxLogLastError(wxT("BitBlt"));
1651 }
b02121c3 1652 }
5afb9458
DW
1653 vCbnd.lColor = (LONG)vOldTextColor;
1654 ::GpiSetAttrs( m_hPS // presentation-space handle
1655 ,PRIM_CHAR // Char primitive.
1656 ,CBB_COLOR // sets color.
1657 ,0
1658 ,&vCbnd // buffer for attributes.
1659 );
1660 ::GpiSetBackColor(m_hPS, (LONG)vOldBackground);
1661 return bSuccess;
fb46a9a6
DW
1662}
1663
1664void wxDC::DoGetSize( int* width, int* height ) const
1665{
1666 // TODO:
1667};
1668
1669void wxDC::DoGetSizeMM( int* width, int* height ) const
1670{
1671 // TODO:
1672};
1673
1674wxSize wxDC::GetPPI() const
1675{
1676 int x = 1;
1677 int y = 1;
1678 // TODO:
1679 return (wxSize(x,y));
1680}
1681
1682void wxDC::SetLogicalScale( double x, double y )
1683{
1684 // TODO:
1685};
1686
1687#if WXWIN_COMPATIBILITY
1688void wxDC::DoGetTextExtent(const wxString& string, float *x, float *y,
1689 float *descent, float *externalLeading,
1690 wxFont *theFont, bool use16bit) const
1691{
7cdc2f1e 1692 wxCoord x1, y1, descent1, externalLeading1;
fb46a9a6
DW
1693 GetTextExtent(string, & x1, & y1, & descent1, & externalLeading1, theFont, use16bit);
1694 *x = x1; *y = y1;
1695 if (descent)
1696 *descent = descent1;
1697 if (externalLeading)
1698 *externalLeading = externalLeading1;
1699}
1700#endif
1701