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