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