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