DC updates and an associated .Def file update
[wxWidgets.git] / src / os2 / dc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dc.cpp
3 // Purpose: wxDC class
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/14/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
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"
25 #endif
26
27 #include "wx/dcprint.h"
28
29 #include <string.h>
30 #include <math.h>
31
32 #include "wx/os2/private.h"
33
34 IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
35
36 // ---------------------------------------------------------------------------
37 // constants
38 // ---------------------------------------------------------------------------
39
40 static const int VIEWPORT_EXTENT = 1000;
41
42 static const int MM_POINTS = 9;
43 static const int MM_METRIC = 10;
44
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
55 static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
56
57 int 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
74 int QueryTextBkColor(
75 HPS hPS
76 )
77 {
78 CHARBUNDLE vCbnd;
79
80 ::GpiQueryAttrs( hPS // presentation-space handle
81 ,PRIM_CHAR // Char primitive.
82 ,CBB_BACK_COLOR // Background color.
83 ,&vCbnd // buffer for attributes.
84 );
85 return vCbnd.lBackColor;
86 }
87
88
89 int 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
109 int 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
126 // ===========================================================================
127 // implementation
128 // ===========================================================================
129
130 // ---------------------------------------------------------------------------
131 // wxDC
132 // ---------------------------------------------------------------------------
133
134 wxDC::wxDC(void)
135 {
136 m_pCanvas = NULL;
137
138 m_hOldBitmap = 0;
139 m_hOldPen = 0;
140 m_hOldBrush = 0;
141 m_hOldFont = 0;
142 m_hOldPalette = 0;
143
144 m_bOwnsDC = FALSE;
145 m_hDC = 0;
146 m_hOldPS = NULL;
147 m_hPS = NULL;
148 m_bIsPaintTime = FALSE; // True at Paint Time
149 m_brush.GetColour().Set("WHITE");
150 } // end of wxDC::wxDC
151
152 wxDC::~wxDC(void)
153 {
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
182
183 // This will select current objects out of the DC,
184 // which is what you have to do before deleting the
185 // DC.
186 void wxDC::SelectOldObjects(
187 WXHDC hPS
188 )
189 {
190 if (hPS)
191 {
192 if (m_hOldBitmap)
193 {
194 ::GpiSetBitmap(hPS, (HBITMAP) m_hOldBitmap);
195 if (m_vSelectedBitmap.Ok())
196 {
197 m_vSelectedBitmap.SetSelectedInto(NULL);
198 }
199 }
200 m_hOldBitmap = 0;
201 //
202 // OS/2 has no other native GDI objects to set in a PS/DC like windows
203 //
204 m_hOldPen = 0;
205 m_hOldBrush = 0;
206 m_hOldFont = 0;
207 m_hOldPalette = 0;
208 }
209
210 m_brush = wxNullBrush;
211 m_pen = wxNullPen;
212 m_palette = wxNullPalette;
213 m_font = wxNullFont;
214 m_backgroundBrush = wxNullBrush;
215 m_vSelectedBitmap = wxNullBitmap;
216 } // end of wxDC::SelectOldObjects
217
218 // ---------------------------------------------------------------------------
219 // clipping
220 // ---------------------------------------------------------------------------
221
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); \
232 }
233
234 void wxDC::DoSetClippingRegion(
235 wxCoord x
236 , wxCoord y
237 , wxCoord width
238 , wxCoord height
239 )
240 {
241 RECTL vRect;
242
243 m_clipping = TRUE;
244 vRect.xLeft = XLOG2DEV(x);
245 vRect.yTop = YLOG2DEV(m_vRclPaint.yTop - y);
246 vRect.xRight = XLOG2DEV(x + width);
247 vRect.yBottom = YLOG2DEV(m_vRclPaint.yTop - (y + height));
248 ::GpiIntersectClipRectangle(m_hPS, &vRect);
249 DO_SET_CLIPPING_BOX()
250 } // end of wxDC::DoSetClippingRegion
251
252 void wxDC::DoSetClippingRegionAsRegion(
253 const wxRegion& rRegion
254 )
255 {
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
266
267 void wxDC::DestroyClippingRegion(void)
268 {
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
289
290 // ---------------------------------------------------------------------------
291 // query capabilities
292 // ---------------------------------------------------------------------------
293
294 bool wxDC::CanDrawBitmap() const
295 {
296 return TRUE;
297 }
298
299 bool wxDC::CanGetTextExtent() const
300 {
301 LONG lTechnology = 0L;
302
303 ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY, 1L, &lTechnology);
304 return (lTechnology == CAPS_TECH_RASTER_DISPLAY) || (lTechnology == CAPS_TECH_RASTER_PRINTER);
305 } // end of wxDC::CanGetTextExtent
306
307 int wxDC::GetDepth() const
308 {
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
322
323 // ---------------------------------------------------------------------------
324 // drawing
325 // ---------------------------------------------------------------------------
326
327 void wxDC::Clear()
328 {
329 ::GpiErase(m_hPS);
330 }
331
332 void wxDC::DoFloodFill(
333 wxCoord vX
334 , wxCoord vY
335 , const wxColour& rCol
336 , int nStyle
337 )
338 {
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);
352 }
353
354 bool wxDC::DoGetPixel(
355 wxCoord vX
356 , wxCoord vY
357 , wxColour* pCol
358 ) const
359 {
360 POINTL vPoint;
361 LONG lColor;
362
363 vPoint.x = vX;
364 vPoint.y = vY;
365 lColor = ::GpiSetPel(m_hPS, &vPoint);
366 pCol->Set((unsigned long)lColor);
367 if(lColor>= 0)
368 return(TRUE);
369 else
370 return(FALSE);
371 }
372
373 void wxDC::DoCrossHair(
374 wxCoord vX
375 , wxCoord vY
376 )
377 {
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
402
403 void wxDC::DoDrawLine(
404 wxCoord vX1
405 , wxCoord vY1
406 , wxCoord vX2
407 , wxCoord vY2
408 )
409 {
410 POINTL vPoint[2];
411
412 vPoint[0].x = vX1;
413 vPoint[0].y = m_vRclPaint.yTop - vY1;
414 vPoint[1].x = vX2;
415 vPoint[1].y = m_vRclPaint.yTop - vY2;
416 ::GpiMove(m_hPS, &vPoint[0]);
417 ::GpiLine(m_hPS, &vPoint[1]);
418 } // end of wxDC::DoDrawLine
419
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 //////////////////////////////////////////////////////////////////////////////
426 void wxDC::DoDrawArc(
427 wxCoord vX1
428 , wxCoord vY1
429 , wxCoord vX2
430 , wxCoord vY2
431 , wxCoord vXc
432 , wxCoord vYc
433 )
434 {
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);
477 DoDrawArc( vX1, vY1
478 ,vXm, vYm
479 ,vXc, vYc
480 );
481 DoDrawArc( vXm, vYm
482 ,vX2, vY2
483 ,vXc, vYc
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
507 vPtlArc[0].x = vXm;
508 vPtlArc[0].y = vYm;
509 vPtlArc[1].x = vX2;
510 vPtlArc[1].y = vY2;
511 ::GpiPointArc(m_hPS, vPtlArc); // Draws the arc
512 } // end of wxDC::DoDrawArc
513
514 void wxDC::DoDrawCheckMark(
515 wxCoord vX1
516 , wxCoord vY1
517 , wxCoord vWidth
518 , wxCoord vHeight
519 )
520 {
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 }
549 } // end of wxDC::DoDrawCheckMark
550
551 void wxDC::DoDrawPoint(
552 wxCoord vX
553 , wxCoord vY
554 )
555 {
556 POINTL vPoint;
557
558 vPoint.x = vX;
559 vPoint.y = m_vRclPaint.yTop - vY;
560 ::GpiSetPel(m_hPS, &vPoint);
561 } // end of wxDC::DoDrawPoint
562
563 void wxDC::DoDrawPolygon(
564 int n
565 , wxPoint vPoints[]
566 , wxCoord vXoffset
567 , wxCoord vYoffset
568 , int nFillStyle
569 )
570 {
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);
633 } // end of wxDC::DoDrawPolygon
634
635 void wxDC::DoDrawLines(
636 int n
637 , wxPoint vPoints[]
638 , wxCoord vXoffset
639 , wxCoord vYoffset
640 )
641 {
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 }
658 } // end of wxDC::DoDrawLines
659
660 void wxDC::DoDrawRectangle(
661 wxCoord vX
662 , wxCoord vY
663 , wxCoord vWidth
664 , wxCoord vHeight
665 )
666 {
667 POINTL vPoint[2];
668 LONG lControl;
669 LONG lColor;
670 LONG lBorderColor;
671 int nIsTRANSPARENT = 0;
672
673 vPoint[0].x = vX;
674 vPoint[0].y = m_vRclPaint.yTop - (vY + vHeight);
675 vPoint[1].x = vX + vWidth;
676 vPoint[1].y = m_vRclPaint.yTop - vY;
677 ::GpiMove(m_hPS, &vPoint[0]);
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
688 ::GpiSetColor(m_hPS, lColor);
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 );
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]);
717 ::GpiBox( m_hPS
718 ,lControl
719 ,&vPoint[1]
720 ,0L
721 ,0L
722 );
723 }
724 } // end of wxDC::DoDrawRectangle
725
726 void wxDC::DoDrawRoundedRectangle(
727 wxCoord vX
728 , wxCoord vY
729 , wxCoord vWidth
730 , wxCoord vHeight
731 , double dRadius
732 )
733 {
734 POINTL vPoint[2];
735 LONG lControl;
736
737 vPoint[0].x = vX;
738 vPoint[0].y = YLOG2DEV(vY) - vHeight;
739 vPoint[1].x = vX + vWidth;
740 vPoint[1].y = vY;
741 ::GpiMove(m_hPS, &vPoint[0]);
742
743 lControl = DRO_OUTLINEFILL; //DRO_FILL;
744 if (m_brush.GetStyle() == wxTRANSPARENT)
745 lControl = DRO_OUTLINE;
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
751 );
752 } // end of wxDC::DoDrawRoundedRectangle
753
754 // Draw Ellipse within box (x,y) - (x+width, y+height)
755 void wxDC::DoDrawEllipse(
756 wxCoord vX
757 , wxCoord vY
758 , wxCoord vWidth
759 , wxCoord vHeight
760 )
761 {
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
787 } // end of wxDC::DoDrawEllipse
788
789 void wxDC::DoDrawEllipticArc(
790 wxCoord vX
791 , wxCoord vY
792 , wxCoord vWidth
793 , wxCoord vHeight
794 , double dSa
795 , double dEa
796 )
797 {
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 );
840 } // end of wxDC::DoDrawEllipticArc
841
842 void wxDC::DoDrawIcon(
843 const wxIcon& rIcon
844 , wxCoord vX
845 , wxCoord vY
846 )
847 {
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
858 void wxDC::DoDrawBitmap(
859 const wxBitmap& rBmp
860 , wxCoord vX
861 , wxCoord vY
862 , bool bUseMask
863 )
864 {
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
876
877 void wxDC::DoDrawText(
878 const wxString& rsText
879 , wxCoord vX
880 , wxCoord vY
881 )
882 {
883 DrawAnyText( rsText
884 ,vX
885 ,vY
886 );
887 }
888
889 void wxDC::DrawAnyText(
890 const wxString& rsText
891 , wxCoord vX
892 , wxCoord vY
893 )
894 {
895 int nOldBackground = 0;
896 POINTL vPtlStart;
897 LONG lHits;
898
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
949 void wxDC::DoDrawRotatedText(
950 const wxString& rsText
951 , wxCoord vX
952 , wxCoord vY
953 , double dAngle
954 )
955 {
956 if (dAngle == 0.0)
957 {
958 DoDrawText( rsText
959 ,vX
960 ,vY
961 );
962 }
963
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
1016 // ---------------------------------------------------------------------------
1017 // set GDI objects
1018 // ---------------------------------------------------------------------------
1019
1020 void wxDC::SetPalette(const wxPalette& palette)
1021 {
1022 // TODO
1023 }
1024
1025 void wxDC::SetFont(
1026 const wxFont& rFont
1027 )
1028 {
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 {
1035 m_hOldFont = 0;
1036 }
1037 m_font = rFont;
1038 if (!rFont.Ok())
1039 {
1040 m_hOldFont = 0;
1041 }
1042
1043 m_font.SetPS(m_hPS); // this will realize the font
1044
1045 if (m_font.Ok())
1046 {
1047 HFONT hFont = m_font.GetResourceHandle();
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 }
1055 } // end of wxDC::SetFont
1056
1057 void wxDC::SetPen(
1058 const wxPen& rPen
1059 )
1060 {
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
1069 if (m_hOldPen)
1070 m_hOldPen = 0L;
1071 m_pen = rPen;
1072
1073 if (!m_pen.Ok())
1074 {
1075 if (m_hOldPen)
1076 {
1077 m_pen.SetPS((HPS)m_hOldPen);
1078 }
1079 m_hOldPen = 0L;
1080 }
1081
1082 if (m_pen.Ok())
1083 {
1084 if (m_pen.GetResourceHandle())
1085 {
1086 m_pen.SetPS(m_hPS);
1087 if (!m_hOldPen)
1088 m_hOldPen = m_pen.GetPS();
1089 }
1090 }
1091 }
1092
1093 void wxDC::SetBrush(
1094 const wxBrush& rBrush
1095 )
1096 {
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
1128
1129 void wxDC::SetBackground(const wxBrush& brush)
1130 {
1131 // TODO
1132 }
1133
1134 void wxDC::SetBackgroundMode(
1135 int nMode
1136 )
1137 {
1138 m_backgroundMode = nMode;
1139 }
1140
1141 void wxDC::SetLogicalFunction(int function)
1142 {
1143 // TODO
1144 }
1145
1146 void 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
1178 bool wxDC::StartDoc(const wxString& message)
1179 {
1180 // We might be previewing, so return TRUE to let it continue.
1181 return TRUE;
1182 }
1183
1184 void wxDC::EndDoc()
1185 {
1186 }
1187
1188 void wxDC::StartPage()
1189 {
1190 }
1191
1192 void wxDC::EndPage()
1193 {
1194 }
1195
1196 // ---------------------------------------------------------------------------
1197 // text metrics
1198 // ---------------------------------------------------------------------------
1199
1200 wxCoord wxDC::GetCharHeight() const
1201 {
1202 FONTMETRICS vFM; // metrics structure
1203
1204 ::GpiQueryFontMetrics( m_hPS
1205 ,sizeof(FONTMETRICS)
1206 ,&vFM
1207 );
1208 return YDEV2LOGREL(vFM.lXHeight);
1209 }
1210
1211 wxCoord wxDC::GetCharWidth() const
1212 {
1213 FONTMETRICS vFM; // metrics structure
1214
1215 ::GpiQueryFontMetrics( m_hPS
1216 ,sizeof(FONTMETRICS)
1217 ,&vFM
1218 );
1219 return XDEV2LOGREL(vFM.lAveCharWidth);
1220 }
1221
1222 void wxDC::DoGetTextExtent(
1223 const wxString& rsString
1224 , wxCoord* pvX
1225 , wxCoord* pvY
1226 , wxCoord* pvDescent
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
1242 char zMsg[128]; // DEBUG
1243 wxString sError;
1244
1245 if (!pFontToUse)
1246 pFontToUse = (wxFont*)&m_font;
1247 l = rsString.length();
1248 pStr = (PCH) rsString.c_str();
1249
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
1258 );
1259 if(!bRc)
1260 {
1261 vErrorCode = ::WinGetLastError(wxGetInstance());
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 );
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;
1293 if (pvExternalLeading)
1294 *pvExternalLeading = vFM.lExternalLeading;
1295 }
1296
1297 void wxDC::SetMapMode( int mode )
1298 {
1299 // TODO:
1300 };
1301
1302 void wxDC::SetUserScale(double x, double y)
1303 {
1304 m_userScaleX = x;
1305 m_userScaleY = y;
1306
1307 SetMapMode(m_mappingMode);
1308 }
1309
1310 void 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
1318 void wxDC::SetSystemScale(double x, double y)
1319 {
1320 m_scaleX = x;
1321 m_scaleY = y;
1322
1323 SetMapMode(m_mappingMode);
1324 }
1325
1326 void wxDC::SetLogicalOrigin( wxCoord x, wxCoord y )
1327 {
1328 // TODO:
1329 };
1330
1331 void wxDC::SetDeviceOrigin(
1332 wxCoord x
1333 , wxCoord y
1334 )
1335 {
1336 RECTL vRect;
1337
1338 m_deviceOriginX = x;
1339 m_deviceOriginY = y;
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 );
1350 };
1351
1352 // ---------------------------------------------------------------------------
1353 // coordinates transformations
1354 // ---------------------------------------------------------------------------
1355
1356 wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
1357 {
1358 return (wxCoord) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX) - m_logicalOriginX);
1359 }
1360
1361 wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
1362 {
1363 return (wxCoord) ((x)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX));
1364 }
1365
1366 wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
1367 {
1368 return (wxCoord) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY) - m_logicalOriginY);
1369 }
1370
1371 wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
1372 {
1373 return (wxCoord) ((y)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY));
1374 }
1375
1376 wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
1377 {
1378 return (wxCoord) ((x - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX + m_deviceOriginX);
1379 }
1380
1381 wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
1382 {
1383 return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX);
1384 }
1385
1386 wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
1387 {
1388 return (wxCoord) ((y - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY + m_deviceOriginY);
1389 }
1390
1391 wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
1392 {
1393 return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY);
1394 }
1395
1396 // ---------------------------------------------------------------------------
1397 // bit blit
1398 // ---------------------------------------------------------------------------
1399
1400 bool 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 )
1411 {
1412 wxMask* pMask = NULL;
1413 CHARBUNDLE vCbnd;
1414 COLORREF vOldTextColor;
1415 COLORREF vOldBackground = ::GpiQueryBackColor(m_hPS);
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;
1476
1477 if (bUseMask)
1478 {
1479 //
1480 // Blit bitmap with mask
1481 //
1482
1483 //
1484 // Create a temp buffer bitmap and DCs/PSs to access it and the mask
1485 //
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
1519 ,vXdest + vWidth, vYdest + vHeight
1520 ,vXsrc, vYsrc
1521 ,vXsrc + vWidth, vYsrc + vHeight
1522 };
1523 POINTL aPoint4[4] = { vXdest, vYdest
1524 ,vXdest + vWidth, vYdest + vHeight
1525 ,0, 0
1526 ,vWidth, vHeight
1527 };
1528 ::GpiSetBitmap(hPSMask, (HBITMAP) pMask->GetMaskBitmap());
1529 ::GpiSetBitmap(hPSBuffer, (HBITMAP) hBufBitmap);
1530
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 }
1545
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 }
1560
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 }
1581
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
1590 ,aPoint3
1591 ,ROP_SRCAND
1592 ,BBO_IGNORE
1593 );
1594 if (rc == GPI_ERROR)
1595 {
1596 wxLogLastError(wxT("BitBlt"));
1597 }
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
1611 ,aPoint4
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;
1632 }
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
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 }
1652 }
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;
1662 }
1663
1664 void wxDC::DoGetSize( int* width, int* height ) const
1665 {
1666 // TODO:
1667 };
1668
1669 void wxDC::DoGetSizeMM( int* width, int* height ) const
1670 {
1671 // TODO:
1672 };
1673
1674 wxSize wxDC::GetPPI() const
1675 {
1676 int x = 1;
1677 int y = 1;
1678 // TODO:
1679 return (wxSize(x,y));
1680 }
1681
1682 void wxDC::SetLogicalScale( double x, double y )
1683 {
1684 // TODO:
1685 };
1686
1687 #if WXWIN_COMPATIBILITY
1688 void wxDC::DoGetTextExtent(const wxString& string, float *x, float *y,
1689 float *descent, float *externalLeading,
1690 wxFont *theFont, bool use16bit) const
1691 {
1692 wxCoord x1, y1, descent1, externalLeading1;
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