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