no message
[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 #if !USE_SHARED_LIBRARY
35 IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
36 #endif
37
38 // ---------------------------------------------------------------------------
39 // constants
40 // ---------------------------------------------------------------------------
41
42 static const int VIEWPORT_EXTENT = 1000;
43
44 static const int MM_POINTS = 9;
45 static const int MM_METRIC = 10;
46
47 // ===========================================================================
48 // implementation
49 // ===========================================================================
50
51 // ---------------------------------------------------------------------------
52 // wxDC
53 // ---------------------------------------------------------------------------
54
55 wxDC::wxDC(void)
56 {
57 m_canvas = NULL;
58
59 m_oldBitmap = 0;
60 m_oldPen = 0;
61 m_oldBrush = 0;
62 m_oldFont = 0;
63 m_oldPalette = 0;
64
65 m_bOwnsDC = FALSE;
66 m_hDC = 0;
67 m_hDCCount = 0;
68 };
69
70 wxDC::~wxDC(void)
71 {
72 // TODO:
73 };
74
75 // This will select current objects out of the DC,
76 // which is what you have to do before deleting the
77 // DC.
78 void wxDC::SelectOldObjects(WXHDC dc)
79 {
80 if (dc)
81 {
82 if (m_oldBitmap)
83 {
84 // ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
85 if (m_selectedBitmap.Ok())
86 {
87 m_selectedBitmap.SetSelectedInto(NULL);
88 }
89 }
90 m_oldBitmap = 0;
91 if (m_oldPen)
92 {
93 // ::SelectObject((HDC) dc, (HPEN) m_oldPen);
94 }
95 m_oldPen = 0;
96 if (m_oldBrush)
97 {
98 // ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
99 }
100 m_oldBrush = 0;
101 if (m_oldFont)
102 {
103 // ::SelectObject((HDC) dc, (HFONT) m_oldFont);
104 }
105 m_oldFont = 0;
106 if (m_oldPalette)
107 {
108 // ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE);
109 }
110 m_oldPalette = 0;
111 }
112
113 m_brush = wxNullBrush;
114 m_pen = wxNullPen;
115 m_palette = wxNullPalette;
116 m_font = wxNullFont;
117 m_backgroundBrush = wxNullBrush;
118 m_selectedBitmap = wxNullBitmap;
119 }
120
121 // ---------------------------------------------------------------------------
122 // clipping
123 // ---------------------------------------------------------------------------
124
125 void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
126 {
127 // TODO
128 }
129
130 void wxDC::DoSetClippingRegion( long x, long y
131 ,long width, long height
132 )
133 {
134 // TODO
135 }
136
137 void wxDC::DoClipping(WXHDC dc)
138 {
139 if (m_clipping && dc)
140 {
141 // TODO:
142 // IntersectClipRect((HDC) dc, XLOG2DEV(m_clipX1), YLOG2DEV(m_clipY1),
143 // XLOG2DEV(m_clipX2), YLOG2DEV(m_clipY2));
144 }
145 }
146
147 void wxDC::DestroyClippingRegion(void)
148 {
149 // TODO:
150 };
151
152 // ---------------------------------------------------------------------------
153 // query capabilities
154 // ---------------------------------------------------------------------------
155
156 bool wxDC::CanDrawBitmap() const
157 {
158 return TRUE;
159 }
160
161 bool wxDC::CanGetTextExtent() const
162 {
163 // What sort of display is it?
164 int technology = 0; // TODO: ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
165
166 // TODO: return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
167 return FALSE;
168 }
169
170 int wxDC::GetDepth() const
171 {
172 // TODO:
173 return (1);
174 }
175
176 // ---------------------------------------------------------------------------
177 // drawing
178 // ---------------------------------------------------------------------------
179
180 void wxDC::Clear()
181 {
182 // TODO
183 }
184
185 void wxDC::DoFloodFill( long x
186 ,long y
187 ,const wxColour& col
188 ,int style
189 )
190 {
191 // TODO
192 }
193
194 bool wxDC::DoGetPixel(long x, long y, wxColour *col) const
195 {
196 // TODO
197 return(TRUE);
198 }
199
200 void wxDC::DoCrossHair(long x, long y)
201 {
202 // TODO
203 }
204
205 void wxDC::DoDrawLine(long x1, long y1, long x2, long y2)
206 {
207 // TODO
208 }
209
210 void wxDC::DoDrawArc( long x1, long y1
211 ,long x2, long y2
212 ,long xc, long yc
213 )
214 {
215 // TODO
216 }
217
218 void wxDC::DoDrawPoint(long x, long y)
219 {
220 // TODO
221 }
222
223 void wxDC::DoDrawPolygon(int n, wxPoint points[]
224 ,long xoffset, long yoffset
225 ,int fillStyle
226 )
227 {
228 // TODO
229 }
230
231 void wxDC::DoDrawLines( int n, wxPoint points[]
232 ,long xoffset, long yoffset
233 )
234 {
235 // TODO
236 }
237
238 void wxDC::DoDrawRectangle(long x, long y, long width, long height)
239 {
240 // TODO
241 }
242
243 void wxDC::DoDrawRoundedRectangle( long x, long y
244 ,long width, long height
245 ,double radius
246 )
247 {
248 // TODO
249 }
250
251 void wxDC::DoDrawEllipse(long x, long y, long width, long height)
252 {
253 // TODO
254 }
255
256 void wxDC::DoDrawEllipticArc( long x
257 ,long y
258 ,long w
259 ,long h
260 ,double sa
261 ,double ea
262 )
263 {
264 // TODO
265 }
266
267 void wxDC::DoDrawIcon(const wxIcon& icon, long x, long y)
268 {
269 // TODO
270 }
271
272 void wxDC::DoDrawBitmap( const wxBitmap &bmp
273 ,long x, long y
274 ,bool useMask
275 )
276 {
277 // TODO
278 }
279
280 void wxDC::DoDrawText(const wxString& text, long x, long y)
281 {
282 // TODO
283 }
284
285 // ---------------------------------------------------------------------------
286 // set GDI objects
287 // ---------------------------------------------------------------------------
288
289 void wxDC::SetPalette(const wxPalette& palette)
290 {
291 // TODO
292 }
293
294 void wxDC::SetFont(const wxFont& font)
295 {
296 // TODO
297 }
298
299 void wxDC::SetPen(const wxPen& pen)
300 {
301 // TODO
302 }
303 void wxDC::SetBrush(const wxBrush& brush)
304 {
305 // TODO
306 }
307
308 void wxDC::SetBackground(const wxBrush& brush)
309 {
310 // TODO
311 }
312
313 void wxDC::SetBackgroundMode(int mode)
314 {
315 // TODO
316 }
317
318 void wxDC::SetLogicalFunction(int function)
319 {
320 // TODO
321 }
322
323 void wxDC::SetRop(WXHDC dc)
324 {
325 if (!dc || m_logicalFunction < 0)
326 return;
327
328 int c_rop;
329 // These may be wrong
330 switch (m_logicalFunction)
331 {
332 // TODO: Figure this stuff out
333 // case wxXOR: c_rop = R2_XORPEN; break;
334 // case wxXOR: c_rop = R2_NOTXORPEN; break;
335 // case wxINVERT: c_rop = R2_NOT; break;
336 // case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
337 // case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
338 // case wxCLEAR: c_rop = R2_WHITE; break;
339 // case wxSET: c_rop = R2_BLACK; break;
340 // case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
341 // case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
342 // case wxAND: c_rop = R2_MASKPEN; break;
343 // case wxOR: c_rop = R2_MERGEPEN; break;
344 // case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
345 // case wxEQUIV:
346 // case wxNAND:
347 // case wxCOPY:
348 default:
349 // c_rop = R2_COPYPEN;
350 break;
351 }
352 // SetROP2((HDC) dc, c_rop);
353 }
354
355 bool wxDC::StartDoc(const wxString& message)
356 {
357 // We might be previewing, so return TRUE to let it continue.
358 return TRUE;
359 }
360
361 void wxDC::EndDoc()
362 {
363 }
364
365 void wxDC::StartPage()
366 {
367 }
368
369 void wxDC::EndPage()
370 {
371 }
372
373 // ---------------------------------------------------------------------------
374 // text metrics
375 // ---------------------------------------------------------------------------
376
377 long wxDC::GetCharHeight() const
378 {
379 // TODO
380 return(1);
381 }
382
383 long wxDC::GetCharWidth() const
384 {
385 // TODO
386 return(1);
387 }
388
389 void wxDC::GetTextExtent( const wxString& string
390 ,long* x
391 ,long* y
392 ,long* decent
393 ,long* externalLeading
394 ,wxFont* theFont
395 ) const
396 {
397 // TODO:
398 }
399
400 void wxDC::SetMapMode( int mode )
401 {
402 // TODO:
403 };
404
405 void wxDC::SetUserScale(double x, double y)
406 {
407 m_userScaleX = x;
408 m_userScaleY = y;
409
410 SetMapMode(m_mappingMode);
411 }
412
413 void wxDC::SetAxisOrientation(bool xLeftRight, bool yBottomUp)
414 {
415 m_signX = xLeftRight ? 1 : -1;
416 m_signY = yBottomUp ? -1 : 1;
417
418 SetMapMode(m_mappingMode);
419 }
420
421 void wxDC::SetSystemScale(double x, double y)
422 {
423 m_scaleX = x;
424 m_scaleY = y;
425
426 SetMapMode(m_mappingMode);
427 }
428
429 void wxDC::SetLogicalOrigin( long x, long y )
430 {
431 // TODO:
432 };
433
434 void wxDC::SetDeviceOrigin( long x, long y )
435 {
436 // TODO:
437 };
438
439 // ---------------------------------------------------------------------------
440 // coordinates transformations
441 // ---------------------------------------------------------------------------
442
443 long wxDCBase::DeviceToLogicalX(long x) const
444 {
445 long new_x = x - m_deviceOriginX;
446 if (new_x > 0)
447 return (long)((double)(new_x) / m_scaleX + 0.5) * m_signX + m_logicalOriginX;
448 else
449 return (long)((double)(new_x) / m_scaleX - 0.5) * m_signX + m_logicalOriginX;
450 };
451
452 long wxDCBase::DeviceToLogicalXRel(long x) const
453 {
454 if (x > 0)
455 return (long)((double)(x) / m_scaleX + 0.5);
456 else
457 return (long)((double)(x) / m_scaleX - 0.5);
458 };
459
460 long wxDCBase::DeviceToLogicalY(long y) const
461 {
462 long new_y = y - m_deviceOriginY;
463 if (new_y > 0)
464 return (long)((double)(new_y) / m_scaleY + 0.5) * m_signY + m_logicalOriginY;
465 else
466 return (long)((double)(new_y) / m_scaleY - 0.5) * m_signY + m_logicalOriginY;
467 };
468
469 long wxDCBase::DeviceToLogicalYRel(long y) const
470 {
471 if (y > 0)
472 return (long)((double)(y) / m_scaleY + 0.5);
473 else
474 return (long)((double)(y) / m_scaleY - 0.5);
475 };
476
477 long wxDCBase::LogicalToDeviceX(long x) const
478 {
479 long new_x = x - m_logicalOriginX;
480 if (new_x > 0)
481 return (long)((double)(new_x) * m_scaleX + 0.5) * m_signX + m_deviceOriginX;
482 else
483 return (long)((double)(new_x) * m_scaleX - 0.5) * m_signX + m_deviceOriginX;
484 };
485
486 long wxDCBase::LogicalToDeviceXRel(long x) const
487 {
488 if (x > 0)
489 return (long)((double)(x) * m_scaleX + 0.5);
490 else
491 return (long)((double)(x) * m_scaleX - 0.5);
492 };
493
494 long wxDCBase::LogicalToDeviceY(long y) const
495 {
496 long new_y = y - m_logicalOriginY;
497 if (new_y > 0)
498 return (long)((double)(new_y) * m_scaleY + 0.5) * m_signY + m_deviceOriginY;
499 else
500 return (long)((double)(new_y) * m_scaleY - 0.5) * m_signY + m_deviceOriginY;
501 };
502
503 long wxDCBase::LogicalToDeviceYRel(long y) const
504 {
505 if (y > 0)
506 return (long)((double)(y) * m_scaleY + 0.5);
507 else
508 return (long)((double)(y) * m_scaleY - 0.5);
509 };
510
511 // ---------------------------------------------------------------------------
512 // bit blit
513 // ---------------------------------------------------------------------------
514
515 bool wxDC::DoBlit( long xdest
516 ,long ydest
517 ,long width
518 ,long height
519 ,wxDC *source
520 ,long xsrc
521 ,long ysrc
522 ,int rop
523 ,bool useMask
524 )
525 {
526 // TODO
527 return(TRUE);
528 }
529
530 void wxDC::DoGetSize( int* width, int* height ) const
531 {
532 // TODO:
533 };
534
535 void wxDC::DoGetSizeMM( int* width, int* height ) const
536 {
537 // TODO:
538 };
539
540 wxSize wxDC::GetPPI() const
541 {
542 int x = 1;
543 int y = 1;
544 // TODO:
545 return (wxSize(x,y));
546 }
547
548 void wxDC::SetLogicalScale( double x, double y )
549 {
550 // TODO:
551 };
552
553 #if WXWIN_COMPATIBILITY
554 void wxDC::DoGetTextExtent(const wxString& string, float *x, float *y,
555 float *descent, float *externalLeading,
556 wxFont *theFont, bool use16bit) const
557 {
558 long x1, y1, descent1, externalLeading1;
559 GetTextExtent(string, & x1, & y1, & descent1, & externalLeading1, theFont, use16bit);
560 *x = x1; *y = y1;
561 if (descent)
562 *descent = descent1;
563 if (externalLeading)
564 *externalLeading = externalLeading1;
565 }
566 #endif
567
568 // ---------------------------------------------------------------------------
569 // spline drawing code
570 // ---------------------------------------------------------------------------
571
572 #if wxUSE_SPLINES
573
574 class wxSpline: public wxObject
575 {
576 public:
577 int type;
578 wxList *points;
579
580 wxSpline(wxList *list);
581 void DeletePoints();
582
583 // Doesn't delete points
584 ~wxSpline();
585 };
586
587 void wx_draw_open_spline(wxDC *dc, wxSpline *spline);
588
589 void wx_quadratic_spline(double a1, double b1, double a2, double b2,
590 double a3, double b3, double a4, double b4);
591 void wx_clear_stack();
592 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
593 double *y3, double *x4, double *y4);
594 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
595 double x4, double y4);
596 static bool wx_spline_add_point(double x, double y);
597 static void wx_spline_draw_point_array(wxDC *dc);
598 wxSpline *wx_make_spline(int x1, int y1, int x2, int y2, int x3, int y3);
599
600 void wxDC::DoDrawSpline(wxList *list)
601 {
602 wxSpline spline(list);
603
604 wx_draw_open_spline(this, &spline);
605 }
606
607 wxList wx_spline_point_list;
608
609 void wx_draw_open_spline(wxDC *dc, wxSpline *spline)
610 {
611 wxPoint *p;
612 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
613 double x1, y1, x2, y2;
614
615 wxNode *node = spline->points->First();
616 p = (wxPoint *)node->Data();
617
618 x1 = p->x;
619 y1 = p->y;
620
621 node = node->Next();
622 p = (wxPoint *)node->Data();
623
624 x2 = p->x;
625 y2 = p->y;
626 cx1 = (double)((x1 + x2) / 2);
627 cy1 = (double)((y1 + y2) / 2);
628 cx2 = (double)((cx1 + x2) / 2);
629 cy2 = (double)((cy1 + y2) / 2);
630
631 wx_spline_add_point(x1, y1);
632
633 while ((node = node->Next()) != NULL)
634 {
635 p = (wxPoint *)node->Data();
636 x1 = x2;
637 y1 = y2;
638 x2 = p->x;
639 y2 = p->y;
640 cx4 = (double)(x1 + x2) / 2;
641 cy4 = (double)(y1 + y2) / 2;
642 cx3 = (double)(x1 + cx4) / 2;
643 cy3 = (double)(y1 + cy4) / 2;
644
645 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
646
647 cx1 = cx4;
648 cy1 = cy4;
649 cx2 = (double)(cx1 + x2) / 2;
650 cy2 = (double)(cy1 + y2) / 2;
651 }
652
653 wx_spline_add_point((double)wx_round(cx1), (double)wx_round(cy1));
654 wx_spline_add_point(x2, y2);
655
656 wx_spline_draw_point_array(dc);
657
658 }
659
660 /********************* CURVES FOR SPLINES *****************************
661
662 The following spline drawing routine is from
663
664 "An Algorithm for High-Speed Curve Generation"
665 by George Merrill Chaikin,
666 Computer Graphics and Image Processing, 3, Academic Press,
667 1974, 346-349.
668
669 and
670
671 "On Chaikin's Algorithm" by R. F. Riesenfeld,
672 Computer Graphics and Image Processing, 4, Academic Press,
673 1975, 304-310.
674
675 ***********************************************************************/
676
677 #define half(z1, z2) ((z1+z2)/2.0)
678 #define THRESHOLD 5
679
680 /* iterative version */
681
682 void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
683 double b4)
684 {
685 register double xmid, ymid;
686 double x1, y1, x2, y2, x3, y3, x4, y4;
687
688 wx_clear_stack();
689 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
690
691 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
692 xmid = (double)half(x2, x3);
693 ymid = (double)half(y2, y3);
694 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
695 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
696 wx_spline_add_point((double)wx_round(x1), (double)wx_round(y1));
697 wx_spline_add_point((double)wx_round(xmid), (double)wx_round(ymid));
698 } else {
699 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
700 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
701 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
702 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
703 }
704 }
705 }
706
707
708 /* utilities used by spline drawing routines */
709
710
711 typedef struct wx_spline_stack_struct {
712 double x1, y1, x2, y2, x3, y3, x4, y4;
713 }
714 Stack;
715
716 #define SPLINE_STACK_DEPTH 20
717 static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
718 static Stack *wx_stack_top;
719 static int wx_stack_count;
720
721 void wx_clear_stack()
722 {
723 wx_stack_top = wx_spline_stack;
724 wx_stack_count = 0;
725 }
726
727 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
728 {
729 wx_stack_top->x1 = x1;
730 wx_stack_top->y1 = y1;
731 wx_stack_top->x2 = x2;
732 wx_stack_top->y2 = y2;
733 wx_stack_top->x3 = x3;
734 wx_stack_top->y3 = y3;
735 wx_stack_top->x4 = x4;
736 wx_stack_top->y4 = y4;
737 wx_stack_top++;
738 wx_stack_count++;
739 }
740
741 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
742 double *x3, double *y3, double *x4, double *y4)
743 {
744 if (wx_stack_count == 0)
745 return (0);
746 wx_stack_top--;
747 wx_stack_count--;
748 *x1 = wx_stack_top->x1;
749 *y1 = wx_stack_top->y1;
750 *x2 = wx_stack_top->x2;
751 *y2 = wx_stack_top->y2;
752 *x3 = wx_stack_top->x3;
753 *y3 = wx_stack_top->y3;
754 *x4 = wx_stack_top->x4;
755 *y4 = wx_stack_top->y4;
756 return (1);
757 }
758
759 static bool wx_spline_add_point(double x, double y)
760 {
761 wxPoint *point = new wxPoint;
762 point->x = (int) x;
763 point->y = (int) y;
764 wx_spline_point_list.Append((wxObject*)point);
765 return TRUE;
766 }
767
768 static void wx_spline_draw_point_array(wxDC *dc)
769 {
770 dc->DrawLines(&wx_spline_point_list, 0, 0);
771 wxNode *node = wx_spline_point_list.First();
772 while (node)
773 {
774 wxPoint *point = (wxPoint *)node->Data();
775 delete point;
776 delete node;
777 node = wx_spline_point_list.First();
778 }
779 }
780
781 wxSpline::wxSpline(wxList *list)
782 {
783 points = list;
784 }
785
786 wxSpline::~wxSpline()
787 {
788 }
789
790 void wxSpline::DeletePoints()
791 {
792 for(wxNode *node = points->First(); node; node = points->First())
793 {
794 wxPoint *point = (wxPoint *)node->Data();
795 delete point;
796 delete node;
797 }
798 delete points;
799 }
800
801
802 #endif // wxUSE_SPLINES
803