]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/dcbase.cpp
bump subrelease number
[wxWidgets.git] / src / common / dcbase.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/dcbase.cpp
3// Purpose: generic methods of the wxDC Class
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 05/25/99
7// RCS-ID: $Id$
8// Copyright: (c) wxWidgets team
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#include "wx/dc.h"
28#include "wx/dcbuffer.h" // for IMPLEMENT_DYNAMIC_CLASS
29
30#ifndef WX_PRECOMP
31 #include "wx/math.h"
32#endif
33
34// bool wxDCBase::sm_cacheing = false;
35
36IMPLEMENT_ABSTRACT_CLASS(wxDCBase, wxObject)
37
38// ============================================================================
39// implementation
40// ============================================================================
41
42IMPLEMENT_DYNAMIC_CLASS(wxBufferedDC, wxMemoryDC)
43IMPLEMENT_ABSTRACT_CLASS(wxBufferedPaintDC, wxBufferedDC)
44
45#if WXWIN_COMPATIBILITY_2_6
46void wxDCBase::BeginDrawing()
47{
48}
49
50void wxDCBase::EndDrawing()
51{
52}
53#endif // WXWIN_COMPATIBILITY_2_6
54
55// ----------------------------------------------------------------------------
56// special symbols
57// ----------------------------------------------------------------------------
58
59void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1,
60 wxCoord width, wxCoord height)
61{
62 wxCHECK_RET( Ok(), wxT("invalid window dc") );
63
64 wxCoord x2 = x1 + width,
65 y2 = y1 + height;
66
67 // this is to yield width of 3 for width == height == 10
68 SetPen(wxPen(GetTextForeground(), (width + height + 1) / 7, wxSOLID));
69
70 // we're drawing a scaled version of wx/generic/tick.xpm here
71 wxCoord x3 = x1 + (4*width) / 10, // x of the tick bottom
72 y3 = y1 + height / 2; // y of the left tick branch
73 DoDrawLine(x1, y3, x3, y2);
74 DoDrawLine(x3, y2, x2, y1);
75
76 CalcBoundingBox(x1, y1);
77 CalcBoundingBox(x2, y2);
78}
79
80// ----------------------------------------------------------------------------
81// line/polygons
82// ----------------------------------------------------------------------------
83
84void wxDCBase::DrawLines(const wxList *list, wxCoord xoffset, wxCoord yoffset)
85{
86 int n = list->GetCount();
87 wxPoint *points = new wxPoint[n];
88
89 int i = 0;
90 for ( wxList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
91 {
92 wxPoint *point = (wxPoint *)node->GetData();
93 points[i].x = point->x;
94 points[i].y = point->y;
95 }
96
97 DoDrawLines(n, points, xoffset, yoffset);
98
99 delete [] points;
100}
101
102
103void wxDCBase::DrawPolygon(const wxList *list,
104 wxCoord xoffset, wxCoord yoffset,
105 int fillStyle)
106{
107 int n = list->GetCount();
108 wxPoint *points = new wxPoint[n];
109
110 int i = 0;
111 for ( wxList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
112 {
113 wxPoint *point = (wxPoint *)node->GetData();
114 points[i].x = point->x;
115 points[i].y = point->y;
116 }
117
118 DoDrawPolygon(n, points, xoffset, yoffset, fillStyle);
119
120 delete [] points;
121}
122
123void
124wxDCBase::DoDrawPolyPolygon(int n,
125 int count[],
126 wxPoint points[],
127 wxCoord xoffset, wxCoord yoffset,
128 int fillStyle)
129{
130 if ( n == 1 )
131 {
132 DoDrawPolygon(count[0], points, xoffset, yoffset, fillStyle);
133 return;
134 }
135
136 int i, j, lastOfs;
137 wxPoint* pts;
138 wxPen pen;
139
140 for (i = j = lastOfs = 0; i < n; i++)
141 {
142 lastOfs = j;
143 j += count[i];
144 }
145 pts = new wxPoint[j+n-1];
146 for (i = 0; i < j; i++)
147 pts[i] = points[i];
148 for (i = 2; i <= n; i++)
149 {
150 lastOfs -= count[n-i];
151 pts[j++] = pts[lastOfs];
152 }
153
154 pen = GetPen();
155 SetPen(wxPen(*wxBLACK, 0, wxTRANSPARENT));
156 DoDrawPolygon(j, pts, xoffset, yoffset, fillStyle);
157 SetPen(pen);
158 for (i = j = 0; i < n; i++)
159 {
160 DoDrawLines(count[i], pts+j, xoffset, yoffset);
161 j += count[i];
162 }
163 delete[] pts;
164}
165
166// ----------------------------------------------------------------------------
167// splines
168// ----------------------------------------------------------------------------
169
170#if wxUSE_SPLINES
171
172// TODO: this API needs fixing (wxPointList, why (!const) "wxList *"?)
173void wxDCBase::DrawSpline(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord x3, wxCoord y3)
174{
175 wxList point_list;
176
177 wxPoint *point1 = new wxPoint;
178 point1->x = x1; point1->y = y1;
179 point_list.Append((wxObject*)point1);
180
181 wxPoint *point2 = new wxPoint;
182 point2->x = x2; point2->y = y2;
183 point_list.Append((wxObject*)point2);
184
185 wxPoint *point3 = new wxPoint;
186 point3->x = x3; point3->y = y3;
187 point_list.Append((wxObject*)point3);
188
189 DrawSpline(&point_list);
190
191 for( wxList::compatibility_iterator node = point_list.GetFirst(); node; node = node->GetNext() )
192 {
193 wxPoint *p = (wxPoint *)node->GetData();
194 delete p;
195 }
196}
197
198void wxDCBase::DrawSpline(int n, wxPoint points[])
199{
200 wxList list;
201 for (int i =0; i < n; i++)
202 {
203 list.Append((wxObject*)&points[i]);
204 }
205
206 DrawSpline(&list);
207}
208
209// ----------------------------------- spline code ----------------------------------------
210
211void wx_quadratic_spline(double a1, double b1, double a2, double b2,
212 double a3, double b3, double a4, double b4);
213void wx_clear_stack();
214int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
215 double *y3, double *x4, double *y4);
216void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
217 double x4, double y4);
218static bool wx_spline_add_point(double x, double y);
219static void wx_spline_draw_point_array(wxDCBase *dc);
220
221wxList wx_spline_point_list;
222
223#define half(z1, z2) ((z1+z2)/2.0)
224#define THRESHOLD 5
225
226/* iterative version */
227
228void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
229 double b4)
230{
231 register double xmid, ymid;
232 double x1, y1, x2, y2, x3, y3, x4, y4;
233
234 wx_clear_stack();
235 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
236
237 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
238 xmid = (double)half(x2, x3);
239 ymid = (double)half(y2, y3);
240 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
241 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
242 wx_spline_add_point( x1, y1 );
243 wx_spline_add_point( xmid, ymid );
244 } else {
245 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
246 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
247 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
248 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
249 }
250 }
251}
252
253/* utilities used by spline drawing routines */
254
255typedef struct wx_spline_stack_struct {
256 double x1, y1, x2, y2, x3, y3, x4, y4;
257} Stack;
258
259#define SPLINE_STACK_DEPTH 20
260static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
261static Stack *wx_stack_top;
262static int wx_stack_count;
263
264void wx_clear_stack()
265{
266 wx_stack_top = wx_spline_stack;
267 wx_stack_count = 0;
268}
269
270void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
271{
272 wx_stack_top->x1 = x1;
273 wx_stack_top->y1 = y1;
274 wx_stack_top->x2 = x2;
275 wx_stack_top->y2 = y2;
276 wx_stack_top->x3 = x3;
277 wx_stack_top->y3 = y3;
278 wx_stack_top->x4 = x4;
279 wx_stack_top->y4 = y4;
280 wx_stack_top++;
281 wx_stack_count++;
282}
283
284int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
285 double *x3, double *y3, double *x4, double *y4)
286{
287 if (wx_stack_count == 0)
288 return (0);
289 wx_stack_top--;
290 wx_stack_count--;
291 *x1 = wx_stack_top->x1;
292 *y1 = wx_stack_top->y1;
293 *x2 = wx_stack_top->x2;
294 *y2 = wx_stack_top->y2;
295 *x3 = wx_stack_top->x3;
296 *y3 = wx_stack_top->y3;
297 *x4 = wx_stack_top->x4;
298 *y4 = wx_stack_top->y4;
299 return (1);
300}
301
302static bool wx_spline_add_point(double x, double y)
303{
304 wxPoint *point = new wxPoint ;
305 point->x = (int) x;
306 point->y = (int) y;
307 wx_spline_point_list.Append((wxObject*)point);
308 return true;
309}
310
311static void wx_spline_draw_point_array(wxDCBase *dc)
312{
313 dc->DrawLines(&wx_spline_point_list, 0, 0 );
314 wxList::compatibility_iterator node = wx_spline_point_list.GetFirst();
315 while (node)
316 {
317 wxPoint *point = (wxPoint *)node->GetData();
318 delete point;
319 wx_spline_point_list.Erase(node);
320 node = wx_spline_point_list.GetFirst();
321 }
322}
323
324void wxDCBase::DoDrawSpline( wxList *points )
325{
326 wxCHECK_RET( Ok(), wxT("invalid window dc") );
327
328 wxPoint *p;
329 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
330 double x1, y1, x2, y2;
331
332 wxList::compatibility_iterator node = points->GetFirst();
333 if (node == wxList::compatibility_iterator())
334 // empty list
335 return;
336
337 p = (wxPoint *)node->GetData();
338
339 x1 = p->x;
340 y1 = p->y;
341
342 node = node->GetNext();
343 p = (wxPoint *)node->GetData();
344
345 x2 = p->x;
346 y2 = p->y;
347 cx1 = (double)((x1 + x2) / 2);
348 cy1 = (double)((y1 + y2) / 2);
349 cx2 = (double)((cx1 + x2) / 2);
350 cy2 = (double)((cy1 + y2) / 2);
351
352 wx_spline_add_point(x1, y1);
353
354 while ((node = node->GetNext())
355#if !wxUSE_STL
356 != NULL
357#endif // !wxUSE_STL
358 )
359 {
360 p = (wxPoint *)node->GetData();
361 x1 = x2;
362 y1 = y2;
363 x2 = p->x;
364 y2 = p->y;
365 cx4 = (double)(x1 + x2) / 2;
366 cy4 = (double)(y1 + y2) / 2;
367 cx3 = (double)(x1 + cx4) / 2;
368 cy3 = (double)(y1 + cy4) / 2;
369
370 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
371
372 cx1 = cx4;
373 cy1 = cy4;
374 cx2 = (double)(cx1 + x2) / 2;
375 cy2 = (double)(cy1 + y2) / 2;
376 }
377
378 wx_spline_add_point( cx1, cy1 );
379 wx_spline_add_point( x2, y2 );
380
381 wx_spline_draw_point_array( this );
382}
383
384#endif // wxUSE_SPLINES
385
386// ----------------------------------------------------------------------------
387// Partial Text Extents
388// ----------------------------------------------------------------------------
389
390
391// Each element of the widths array will be the width of the string up to and
392// including the corresponding character in text. This is the generic
393// implementation, the port-specific classes should do this with native APIs
394// if available and if faster. Note: pango_layout_index_to_pos is much slower
395// than calling GetTextExtent!!
396
397#define FWC_SIZE 256
398
399class FontWidthCache
400{
401public:
402 FontWidthCache() : m_scaleX(1), m_widths(NULL) { }
403 ~FontWidthCache() { delete []m_widths; }
404
405 void Reset()
406 {
407 if (!m_widths)
408 m_widths = new int[FWC_SIZE];
409
410 memset(m_widths, 0, sizeof(int)*FWC_SIZE);
411 }
412
413 wxFont m_font;
414 double m_scaleX;
415 int *m_widths;
416};
417
418static FontWidthCache s_fontWidthCache;
419
420bool wxDCBase::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
421{
422 int totalWidth = 0;
423
424 const size_t len = text.length();
425 widths.Empty();
426 widths.Add(0, len);
427
428 // reset the cache if font or horizontal scale have changed
429 if ( !s_fontWidthCache.m_widths ||
430 !wxIsSameDouble(s_fontWidthCache.m_scaleX, m_scaleX) ||
431 (s_fontWidthCache.m_font != GetFont()) )
432 {
433 s_fontWidthCache.Reset();
434 s_fontWidthCache.m_font = GetFont();
435 s_fontWidthCache.m_scaleX = m_scaleX;
436 }
437
438 // Calculate the position of each character based on the widths of
439 // the previous characters
440 int w, h;
441 for ( size_t i = 0; i < len; i++ )
442 {
443 const wxChar c = text[i];
444 unsigned int c_int = (unsigned int)c;
445
446 if ((c_int < FWC_SIZE) && (s_fontWidthCache.m_widths[c_int] != 0))
447 {
448 w = s_fontWidthCache.m_widths[c_int];
449 }
450 else
451 {
452 GetTextExtent(c, &w, &h);
453 if (c_int < FWC_SIZE)
454 s_fontWidthCache.m_widths[c_int] = w;
455 }
456
457 totalWidth += w;
458 widths[i] = totalWidth;
459 }
460
461 return true;
462}
463
464
465// ----------------------------------------------------------------------------
466// enhanced text drawing
467// ----------------------------------------------------------------------------
468
469void wxDCBase::GetMultiLineTextExtent(const wxString& text,
470 wxCoord *x,
471 wxCoord *y,
472 wxCoord *h,
473 wxFont *font)
474{
475 wxCoord widthTextMax = 0, widthLine,
476 heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
477
478 wxString curLine;
479 for ( const wxChar *pc = text; ; pc++ )
480 {
481 if ( *pc == _T('\n') || *pc == _T('\0') )
482 {
483 if ( curLine.empty() )
484 {
485 // we can't use GetTextExtent - it will return 0 for both width
486 // and height and an empty line should count in height
487 // calculation
488
489 // assume that this line has the same height as the previous
490 // one
491 if ( !heightLineDefault )
492 heightLineDefault = heightLine;
493
494 if ( !heightLineDefault )
495 {
496 // but we don't know it yet - choose something reasonable
497 GetTextExtent(_T("W"), NULL, &heightLineDefault,
498 NULL, NULL, font);
499 }
500
501 heightTextTotal += heightLineDefault;
502 }
503 else
504 {
505 GetTextExtent(curLine, &widthLine, &heightLine,
506 NULL, NULL, font);
507 if ( widthLine > widthTextMax )
508 widthTextMax = widthLine;
509 heightTextTotal += heightLine;
510 }
511
512 if ( *pc == _T('\n') )
513 {
514 curLine.clear();
515 }
516 else
517 {
518 // the end of string
519 break;
520 }
521 }
522 else
523 {
524 curLine += *pc;
525 }
526 }
527
528 if ( x )
529 *x = widthTextMax;
530 if ( y )
531 *y = heightTextTotal;
532 if ( h )
533 *h = heightLine;
534}
535
536void wxDCBase::DrawLabel(const wxString& text,
537 const wxBitmap& bitmap,
538 const wxRect& rect,
539 int alignment,
540 int indexAccel,
541 wxRect *rectBounding)
542{
543 // find the text position
544 wxCoord widthText, heightText, heightLine;
545 GetMultiLineTextExtent(text, &widthText, &heightText, &heightLine);
546
547 wxCoord width, height;
548 if ( bitmap.Ok() )
549 {
550 width = widthText + bitmap.GetWidth();
551 height = bitmap.GetHeight();
552 }
553 else // no bitmap
554 {
555 width = widthText;
556 height = heightText;
557 }
558
559 wxCoord x, y;
560 if ( alignment & wxALIGN_RIGHT )
561 {
562 x = rect.GetRight() - width;
563 }
564 else if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
565 {
566 x = (rect.GetLeft() + rect.GetRight() + 1 - width) / 2;
567 }
568 else // alignment & wxALIGN_LEFT
569 {
570 x = rect.GetLeft();
571 }
572
573 if ( alignment & wxALIGN_BOTTOM )
574 {
575 y = rect.GetBottom() - height;
576 }
577 else if ( alignment & wxALIGN_CENTRE_VERTICAL )
578 {
579 y = (rect.GetTop() + rect.GetBottom() + 1 - height) / 2;
580 }
581 else // alignment & wxALIGN_TOP
582 {
583 y = rect.GetTop();
584 }
585
586 // draw the bitmap first
587 wxCoord x0 = x,
588 y0 = y,
589 width0 = width;
590 if ( bitmap.Ok() )
591 {
592 DrawBitmap(bitmap, x, y, true /* use mask */);
593
594 wxCoord offset = bitmap.GetWidth() + 4;
595 x += offset;
596 width -= offset;
597
598 y += (height - heightText) / 2;
599 }
600
601 // we will draw the underscore under the accel char later
602 wxCoord startUnderscore = 0,
603 endUnderscore = 0,
604 yUnderscore = 0;
605
606 // split the string into lines and draw each of them separately
607 wxString curLine;
608 for ( const wxChar *pc = text; ; pc++ )
609 {
610 if ( *pc == _T('\n') || *pc == _T('\0') )
611 {
612 int xRealStart = x; // init it here to avoid compielr warnings
613
614 if ( !curLine.empty() )
615 {
616 // NB: can't test for !(alignment & wxALIGN_LEFT) because
617 // wxALIGN_LEFT is 0
618 if ( alignment & (wxALIGN_RIGHT | wxALIGN_CENTRE_HORIZONTAL) )
619 {
620 wxCoord widthLine;
621 GetTextExtent(curLine, &widthLine, NULL);
622
623 if ( alignment & wxALIGN_RIGHT )
624 {
625 xRealStart += width - widthLine;
626 }
627 else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
628 {
629 xRealStart += (width - widthLine) / 2;
630 }
631 }
632 //else: left aligned, nothing to do
633
634 DrawText(curLine, xRealStart, y);
635 }
636
637 y += heightLine;
638
639 // do we have underscore in this line? we can check yUnderscore
640 // because it is set below to just y + heightLine if we do
641 if ( y == yUnderscore )
642 {
643 // adjust the horz positions to account for the shift
644 startUnderscore += xRealStart;
645 endUnderscore += xRealStart;
646 }
647
648 if ( *pc == _T('\0') )
649 break;
650
651 curLine.clear();
652 }
653 else // not end of line
654 {
655 if ( pc - text.c_str() == indexAccel )
656 {
657 // remeber to draw underscore here
658 GetTextExtent(curLine, &startUnderscore, NULL);
659 curLine += *pc;
660 GetTextExtent(curLine, &endUnderscore, NULL);
661
662 yUnderscore = y + heightLine;
663 }
664 else
665 {
666 curLine += *pc;
667 }
668 }
669 }
670
671 // draw the underscore if found
672 if ( startUnderscore != endUnderscore )
673 {
674 // it should be of the same colour as text
675 SetPen(wxPen(GetTextForeground(), 0, wxSOLID));
676
677 yUnderscore--;
678
679 DrawLine(startUnderscore, yUnderscore, endUnderscore, yUnderscore);
680 }
681
682 // return bounding rect if requested
683 if ( rectBounding )
684 {
685 *rectBounding = wxRect(x, y - heightText, widthText, heightText);
686 }
687
688 CalcBoundingBox(x0, y0);
689 CalcBoundingBox(x0 + width0, y0 + height);
690}
691
692
693void wxDCBase::DoGradientFillLinear(const wxRect& rect,
694 const wxColour& initialColour,
695 const wxColour& destColour,
696 wxDirection nDirection)
697{
698 // save old pen
699 wxPen oldPen = m_pen;
700
701 wxUint8 nR1 = destColour.Red();
702 wxUint8 nG1 = destColour.Green();
703 wxUint8 nB1 = destColour.Blue();
704 wxUint8 nR2 = initialColour.Red();
705 wxUint8 nG2 = initialColour.Green();
706 wxUint8 nB2 = initialColour.Blue();
707 wxUint8 nR, nG, nB;
708
709 if ( nDirection == wxEAST || nDirection == wxWEST )
710 {
711 wxInt32 x = rect.GetWidth();
712 wxInt32 w = x; // width of area to shade
713 wxInt32 xDelta = w/256; // height of one shade bend
714 if (xDelta < 1)
715 xDelta = 1;
716
717 while (x >= xDelta)
718 {
719 x -= xDelta;
720 if (nR1 > nR2)
721 nR = nR1 - (nR1-nR2)*(w-x)/w;
722 else
723 nR = nR1 + (nR2-nR1)*(w-x)/w;
724
725 if (nG1 > nG2)
726 nG = nG1 - (nG1-nG2)*(w-x)/w;
727 else
728 nG = nG1 + (nG2-nG1)*(w-x)/w;
729
730 if (nB1 > nB2)
731 nB = nB1 - (nB1-nB2)*(w-x)/w;
732 else
733 nB = nB1 + (nB2-nB1)*(w-x)/w;
734
735 SetPen(wxPen(wxColour(nR, nG, nB), 1, wxSOLID));
736 if(nDirection == wxEAST)
737 DrawRectangle(rect.GetLeft()+x, rect.GetTop(),
738 xDelta, rect.GetHeight());
739 else //nDirection == wxWEST
740 DrawRectangle(rect.GetRight()-x-xDelta, rect.GetTop(),
741 xDelta, rect.GetHeight());
742 }
743 }
744 else // nDirection == wxNORTH || nDirection == wxSOUTH
745 {
746 wxInt32 y = rect.GetHeight();
747 wxInt32 w = y; // height of area to shade
748 wxInt32 yDelta = w/255; // height of one shade bend
749 if (yDelta < 1)
750 yDelta = 1;
751
752 while (y > 0)
753 {
754 y -= yDelta;
755 if (nR1 > nR2)
756 nR = nR1 - (nR1-nR2)*(w-y)/w;
757 else
758 nR = nR1 + (nR2-nR1)*(w-y)/w;
759
760 if (nG1 > nG2)
761 nG = nG1 - (nG1-nG2)*(w-y)/w;
762 else
763 nG = nG1 + (nG2-nG1)*(w-y)/w;
764
765 if (nB1 > nB2)
766 nB = nB1 - (nB1-nB2)*(w-y)/w;
767 else
768 nB = nB1 + (nB2-nB1)*(w-y)/w;
769
770 SetPen(wxPen(wxColour(nR, nG, nB), 1, wxSOLID));
771 if(nDirection == wxNORTH)
772 DrawRectangle(rect.GetLeft(), rect.GetTop()+y,
773 rect.GetWidth(), yDelta);
774 else //nDirection == wxSOUTH
775 DrawRectangle(rect.GetLeft(), rect.GetBottom()-y-yDelta,
776 rect.GetWidth(), yDelta);
777 }
778 }
779
780 SetPen(oldPen);
781}
782
783void wxDCBase::DoGradientFillConcentric(const wxRect& rect,
784 const wxColour& initialColour,
785 const wxColour& destColour,
786 const wxPoint& circleCenter)
787{
788 //save the old pen color
789 wxColour oldPenColour = m_pen.GetColour();
790
791 wxUint8 nR1 = destColour.Red();
792 wxUint8 nG1 = destColour.Green();
793 wxUint8 nB1 = destColour.Blue();
794 wxUint8 nR2 = initialColour.Red();
795 wxUint8 nG2 = initialColour.Green();
796 wxUint8 nB2 = initialColour.Blue();
797 wxUint8 nR, nG, nB;
798
799
800 //Radius
801 wxInt32 cx = rect.GetWidth() / 2;
802 wxInt32 cy = rect.GetHeight() / 2;
803 wxInt32 nRadius;
804 if (cx < cy)
805 nRadius = cx;
806 else
807 nRadius = cy;
808
809 //Offset of circle
810 wxInt32 nCircleOffX = circleCenter.x - (rect.GetWidth() / 2);
811 wxInt32 nCircleOffY = circleCenter.y - (rect.GetHeight() / 2);
812
813 for ( wxInt32 x = 0; x < rect.GetWidth(); x++ )
814 {
815 for ( wxInt32 y = 0; y < rect.GetHeight(); y++ )
816 {
817 //get color difference
818 wxInt32 nGradient = ((nRadius -
819 (wxInt32)sqrt(
820 pow((double)(x - cx - nCircleOffX), 2) +
821 pow((double)(y - cy - nCircleOffY), 2)
822 )) * 100) / nRadius;
823
824 //normalize Gradient
825 if (nGradient < 0 )
826 nGradient = 0;
827
828 //get dest colors
829 nR = (wxUint8)(nR1 + ((nR2 - nR1) * nGradient / 100));
830 nG = (wxUint8)(nG1 + ((nG2 - nG1) * nGradient / 100));
831 nB = (wxUint8)(nB1 + ((nB2 - nB1) * nGradient / 100));
832
833 //set the pixel
834 m_pen.SetColour(wxColour(nR,nG,nB));
835 DrawPoint(wxPoint(x + rect.GetLeft(), y + rect.GetTop()));
836 }
837 }
838 //return old pen color
839 m_pen.SetColour(oldPenColour);
840}
841
842/*
843Notes for wxWidgets DrawEllipticArcRot(...)
844
845wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse.
846It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...),
847which are also new.
848
849All methods are generic, so they can be implemented in wxDCBase.
850DoDrawEllipticArcRot(...) is virtual, so it can be called from deeper
851methods like (WinCE) wxDC::DoDrawArc(...).
852
853CalculateEllipticPoints(...) fills a given list of wxPoints with some points
854of an elliptic arc. The algorithm is pixel-based: In every row (in flat
855parts) or every column (in steep parts) only one pixel is calculated.
856Trigonometric calculation (sin, cos, tan, atan) is only done if the
857starting angle is not equal to the ending angle. The calculation of the
858pixels is done using simple arithmetic only and should perform not too
859bad even on devices without floating point processor. I didn't test this yet.
860
861Rotate(...) rotates a list of point pixel-based, you will see rounding errors.
862For instance: an ellipse rotated 180 degrees is drawn
863slightly different from the original.
864
865The points are then moved to an array and used to draw a polyline and/or polygon
866(with center added, the pie).
867The result looks quite similar to the native ellipse, only e few pixels differ.
868
869The performance on a desktop system (Athlon 1800, WinXP) is about 7 times
870slower as DrawEllipse(...), which calls the native API.
871An rotated ellipse outside the clipping region takes nearly the same time,
872while an native ellipse outside takes nearly no time to draw.
873
874If you draw an arc with this new method, you will see the starting and ending angles
875are calculated properly.
876If you use DrawEllipticArc(...), you will see they are only correct for circles
877and not properly calculated for ellipses.
878
879Peter Lenhard
880p.lenhard@t-online.de
881*/
882
883#ifdef __WXWINCE__
884void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y,
885 wxCoord w, wxCoord h,
886 double sa, double ea, double angle )
887{
888 wxList list;
889
890 CalculateEllipticPoints( &list, x, y, w, h, sa, ea );
891 Rotate( &list, angle, wxPoint( x+w/2, y+h/2 ) );
892
893 // Add center (for polygon/pie)
894 list.Append( (wxObject*) new wxPoint( x+w/2, y+h/2 ) );
895
896 // copy list into array and delete list elements
897 int n = list.GetCount();
898 wxPoint *points = new wxPoint[n];
899 int i = 0;
900 wxNode* node = 0;
901 for ( node = list.GetFirst(); node; node = node->GetNext(), i++ )
902 {
903 wxPoint *point = (wxPoint *)node->GetData();
904 points[i].x = point->x;
905 points[i].y = point->y;
906 delete point;
907 }
908
909 // first draw the pie without pen, if necessary
910 if( GetBrush() != *wxTRANSPARENT_BRUSH )
911 {
912 wxPen tempPen( GetPen() );
913 SetPen( *wxTRANSPARENT_PEN );
914 DoDrawPolygon( n, points, 0, 0 );
915 SetPen( tempPen );
916 }
917
918 // then draw the arc without brush, if necessary
919 if( GetPen() != *wxTRANSPARENT_PEN )
920 {
921 // without center
922 DoDrawLines( n-1, points, 0, 0 );
923 }
924
925 delete [] points;
926
927} // DrawEllipticArcRot
928
929void wxDCBase::Rotate( wxList* points, double angle, wxPoint center )
930{
931 if( angle != 0.0 )
932 {
933 double pi(M_PI);
934 double dSinA = -sin(angle*2.0*pi/360.0);
935 double dCosA = cos(angle*2.0*pi/360.0);
936 for ( wxNode* node = points->GetFirst(); node; node = node->GetNext() )
937 {
938 wxPoint* point = (wxPoint*)node->GetData();
939
940 // transform coordinates, if necessary
941 if( center.x ) point->x -= center.x;
942 if( center.y ) point->y -= center.y;
943
944 // calculate rotation, rounding simply by implicit cast to integer
945 int xTemp = point->x * dCosA - point->y * dSinA;
946 point->y = point->x * dSinA + point->y * dCosA;
947 point->x = xTemp;
948
949 // back transform coordinates, if necessary
950 if( center.x ) point->x += center.x;
951 if( center.y ) point->y += center.y;
952 }
953 }
954}
955
956void wxDCBase::CalculateEllipticPoints( wxList* points,
957 wxCoord xStart, wxCoord yStart,
958 wxCoord w, wxCoord h,
959 double sa, double ea )
960{
961 double pi = M_PI;
962 double sar = 0;
963 double ear = 0;
964 int xsa = 0;
965 int ysa = 0;
966 int xea = 0;
967 int yea = 0;
968 int sq = 0;
969 int eq = 0;
970 bool bUseAngles = false;
971 if( w<0 ) w = -w;
972 if( h<0 ) h = -h;
973 // half-axes
974 wxCoord a = w/2;
975 wxCoord b = h/2;
976 // decrement 1 pixel if ellipse is smaller than 2*a, 2*b
977 int decrX = 0;
978 if( 2*a == w ) decrX = 1;
979 int decrY = 0;
980 if( 2*b == h ) decrY = 1;
981 // center
982 wxCoord xCenter = xStart + a;
983 wxCoord yCenter = yStart + b;
984 // calculate data for start and end, if necessary
985 if( sa != ea )
986 {
987 bUseAngles = true;
988 // normalisation of angles
989 while( sa<0 ) sa += 360;
990 while( ea<0 ) ea += 360;
991 while( sa>=360 ) sa -= 360;
992 while( ea>=360 ) ea -= 360;
993 // calculate quadrant numbers
994 if( sa > 270 ) sq = 3;
995 else if( sa > 180 ) sq = 2;
996 else if( sa > 90 ) sq = 1;
997 if( ea > 270 ) eq = 3;
998 else if( ea > 180 ) eq = 2;
999 else if( ea > 90 ) eq = 1;
1000 sar = sa * pi / 180.0;
1001 ear = ea * pi / 180.0;
1002 // correct angle circle -> ellipse
1003 sar = atan( -a/(double)b * tan( sar ) );
1004 if ( sq == 1 || sq == 2 ) sar += pi;
1005 ear = atan( -a/(double)b * tan( ear ) );
1006 if ( eq == 1 || eq == 2 ) ear += pi;
1007 // coordinates of points
1008 xsa = xCenter + a * cos( sar );
1009 if( sq == 0 || sq == 3 ) xsa -= decrX;
1010 ysa = yCenter + b * sin( sar );
1011 if( sq == 2 || sq == 3 ) ysa -= decrY;
1012 xea = xCenter + a * cos( ear );
1013 if( eq == 0 || eq == 3 ) xea -= decrX;
1014 yea = yCenter + b * sin( ear );
1015 if( eq == 2 || eq == 3 ) yea -= decrY;
1016 } // if iUseAngles
1017 // calculate c1 = b^2, c2 = b^2/a^2 with a = w/2, b = h/2
1018 double c1 = b * b;
1019 double c2 = 2.0 / w;
1020 c2 *= c2;
1021 c2 *= c1;
1022 wxCoord x = 0;
1023 wxCoord y = b;
1024 long x2 = 1;
1025 long y2 = y*y;
1026 long y2_old = 0;
1027 long y_old = 0;
1028 // Lists for quadrant 1 to 4
1029 wxList pointsarray[4];
1030 // Calculate points for first quadrant and set in all quadrants
1031 for( x = 0; x <= a; ++x )
1032 {
1033 x2 = x2+x+x-1;
1034 y2_old = y2;
1035 y_old = y;
1036 bool bNewPoint = false;
1037 while( y2 > c1 - c2 * x2 && y > 0 )
1038 {
1039 bNewPoint = true;
1040 y2 = y2-y-y+1;
1041 --y;
1042 }
1043 // old y now to big: set point with old y, old x
1044 if( bNewPoint && x>1)
1045 {
1046 int x1 = x - 1;
1047 // remove points on the same line
1048 pointsarray[0].Insert( (wxObject*) new wxPoint( xCenter + x1 - decrX, yCenter - y_old ) );
1049 pointsarray[1].Append( (wxObject*) new wxPoint( xCenter - x1, yCenter - y_old ) );
1050 pointsarray[2].Insert( (wxObject*) new wxPoint( xCenter - x1, yCenter + y_old - decrY ) );
1051 pointsarray[3].Append( (wxObject*) new wxPoint( xCenter + x1 - decrX, yCenter + y_old - decrY ) );
1052 } // set point
1053 } // calculate point
1054
1055 // Starting and/or ending points for the quadrants, first quadrant gets both.
1056 pointsarray[0].Insert( (wxObject*) new wxPoint( xCenter + a - decrX, yCenter ) );
1057 pointsarray[0].Append( (wxObject*) new wxPoint( xCenter, yCenter - b ) );
1058 pointsarray[1].Append( (wxObject*) new wxPoint( xCenter - a, yCenter ) );
1059 pointsarray[2].Append( (wxObject*) new wxPoint( xCenter, yCenter + b - decrY ) );
1060 pointsarray[3].Append( (wxObject*) new wxPoint( xCenter + a - decrX, yCenter ) );
1061
1062 // copy quadrants in original list
1063 if( bUseAngles )
1064 {
1065 // Copy the right part of the points in the lists
1066 // and delete the wxPoints, because they do not leave this method.
1067 points->Append( (wxObject*) new wxPoint( xsa, ysa ) );
1068 int q = sq;
1069 bool bStarted = false;
1070 bool bReady = false;
1071 bool bForceTurn = ( sq == eq && sa > ea );
1072 while( !bReady )
1073 {
1074 for( wxNode *node = pointsarray[q].GetFirst(); node; node = node->GetNext() )
1075 {
1076 // once: go to starting point in start quadrant
1077 if( !bStarted &&
1078 (
1079 ( (wxPoint*) node->GetData() )->x < xsa+1 && q <= 1
1080 ||
1081 ( (wxPoint*) node->GetData() )->x > xsa-1 && q >= 2
1082 )
1083 )
1084 {
1085 bStarted = true;
1086 }
1087
1088 // copy point, if not at ending point
1089 if( bStarted )
1090 {
1091 if( q != eq || bForceTurn
1092 ||
1093 ( (wxPoint*) node->GetData() )->x > xea+1 && q <= 1
1094 ||
1095 ( (wxPoint*) node->GetData() )->x < xea-1 && q >= 2
1096 )
1097 {
1098 // copy point
1099 wxPoint* pPoint = new wxPoint( *((wxPoint*) node->GetData() ) );
1100 points->Append( (wxObject*) pPoint );
1101 }
1102 else if( q == eq && !bForceTurn || ( (wxPoint*) node->GetData() )->x == xea)
1103 {
1104 bReady = true;
1105 }
1106 }
1107 } // for node
1108 ++q;
1109 if( q > 3 ) q = 0;
1110 bForceTurn = false;
1111 bStarted = true;
1112 } // while not bReady
1113 points->Append( (wxObject*) new wxPoint( xea, yea ) );
1114
1115 // delete points
1116 for( q = 0; q < 4; ++q )
1117 {
1118 for( wxNode *node = pointsarray[q].GetFirst(); node; node = node->GetNext() )
1119 {
1120 wxPoint *p = (wxPoint *)node->GetData();
1121 delete p;
1122 }
1123 }
1124 }
1125 else
1126 {
1127 wxNode* node;
1128 // copy whole ellipse, wxPoints will be deleted outside
1129 for( node = pointsarray[0].GetFirst(); node; node = node->GetNext() )
1130 {
1131 wxObject *p = node->GetData();
1132 points->Append( p );
1133 }
1134 for( node = pointsarray[1].GetFirst(); node; node = node->GetNext() )
1135 {
1136 wxObject *p = node->GetData();
1137 points->Append( p );
1138 }
1139 for( node = pointsarray[2].GetFirst(); node; node = node->GetNext() )
1140 {
1141 wxObject *p = node->GetData();
1142 points->Append( p );
1143 }
1144 for( node = pointsarray[3].GetFirst(); node; node = node->GetNext() )
1145 {
1146 wxObject *p = node->GetData();
1147 points->Append( p );
1148 }
1149 } // not iUseAngles
1150} // CalculateEllipticPoints
1151
1152#endif
1153
1154//
1155// temporary home for wxOverlay
1156//
1157
1158#include "wx/dcclient.h"
1159#include "wx/dcmemory.h"
1160
1161#if defined(wxMAC_USE_CORE_GRAPHICS) && wxMAC_USE_CORE_GRAPHICS
1162
1163#include "wx/mac/private.h"
1164#include "wx/toplevel.h"
1165
1166class wxOverlayImpl
1167{
1168public:
1169 wxOverlayImpl() ;
1170 ~wxOverlayImpl() ;
1171
1172
1173 // clears the overlay without restoring the former state
1174 // to be done eg when the window content has been changed and repainted
1175 void Reset();
1176
1177 // returns true if it has been setup
1178 bool IsOk();
1179
1180 void Init( wxWindowDC* dc, int x , int y , int width , int height );
1181
1182 void BeginDrawing( wxWindowDC* dc);
1183
1184 void EndDrawing( wxWindowDC* dc);
1185
1186 void Clear( wxWindowDC* dc);
1187
1188private:
1189 OSStatus CreateOverlayWindow();
1190
1191 void MacGetBounds( Rect *bounds );
1192
1193 WindowRef m_overlayWindow;
1194 WindowRef m_overlayParentWindow;
1195 CGContextRef m_overlayContext ;
1196 // we store the window in case we would have to issue a Refresh()
1197 wxWindow* m_window ;
1198
1199 int m_x ;
1200 int m_y ;
1201 int m_width ;
1202 int m_height ;
1203} ;
1204
1205wxOverlayImpl::wxOverlayImpl()
1206{
1207 m_window = NULL ;
1208 m_overlayContext = NULL ;
1209 m_overlayWindow = NULL ;
1210}
1211
1212wxOverlayImpl::~wxOverlayImpl()
1213{
1214 Reset();
1215}
1216
1217bool wxOverlayImpl::IsOk()
1218{
1219 return m_overlayWindow != NULL ;
1220}
1221
1222void wxOverlayImpl::MacGetBounds( Rect *bounds )
1223{
1224 wxPoint origin(0,0);
1225 origin = m_window->ClientToScreen( origin );
1226 bounds->top = origin.y;
1227 bounds->left = origin.x;
1228 bounds->bottom = origin.y+m_y+m_height;
1229 bounds->right = origin.x+m_x+m_width;
1230}
1231
1232OSStatus wxOverlayImpl::CreateOverlayWindow()
1233{
1234 OSStatus err;
1235
1236 WindowAttributes overlayAttributes = kWindowIgnoreClicksAttribute;
1237
1238 m_overlayParentWindow =(WindowRef) m_window->MacGetTopLevelWindowRef();
1239
1240 Rect bounds ;
1241 MacGetBounds(&bounds);
1242 err = CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, &m_overlayWindow );
1243 if ( err == noErr )
1244 {
1245 SetWindowGroup( m_overlayWindow, GetWindowGroup(m_overlayParentWindow)); // Put them in the same group so that their window layers are consistent
1246 ShowWindow(m_overlayWindow);
1247 }
1248 return err;
1249}
1250
1251void wxOverlayImpl::Init( wxWindowDC* dc, int x , int y , int width , int height )
1252{
1253 wxASSERT_MSG( !IsOk() , _("You cannot Init an overlay twice") );
1254
1255 m_window = dc->GetWindow();
1256 m_x = x ;
1257 m_y = y ;
1258 m_width = width ;
1259 m_height = height ;
1260
1261 OSStatus err = CreateOverlayWindow();
1262 wxASSERT_MSG( err == noErr , _("Couldn't create the overlay window") );
1263#ifndef __LP64__
1264 err = QDBeginCGContext(GetWindowPort(m_overlayWindow), &m_overlayContext);
1265#endif
1266 CGContextTranslateCTM( m_overlayContext, 0, m_height+m_y );
1267 CGContextScaleCTM( m_overlayContext, 1, -1 );
1268 wxASSERT_MSG( err == noErr , _("Couldn't init the context on the overlay window") );
1269}
1270
1271void wxOverlayImpl::BeginDrawing( wxWindowDC* dc)
1272{
1273 delete dc->m_graphicContext ;
1274 dc->m_graphicContext = new wxMacCGContext( m_overlayContext );
1275 // we are right now startin at 0,0 not at the wxWindow's origin, so most of the calculations
1276 // int dc are already corect
1277 // just to make sure :
1278 dc->m_macLocalOrigin.x = 0 ;
1279 dc->m_macLocalOrigin.y = 0 ;
1280 wxSize size = m_window->GetSize() ;
1281 dc->SetClippingRegion( 0 , 0 , size.x , size.y ) ;
1282}
1283
1284void wxOverlayImpl::EndDrawing( wxWindowDC* dc)
1285{
1286 delete dc->m_graphicContext ;
1287 dc->m_graphicContext = NULL ;
1288
1289}
1290
1291void wxOverlayImpl::Clear(wxWindowDC* dc)
1292{
1293 wxASSERT_MSG( IsOk() , _("You cannot Clear an overlay that is not inited") );
1294 CGRect box = CGRectMake( m_x - 1, m_y - 1 , m_width + 2 , m_height + 2 );
1295 CGContextClearRect( m_overlayContext, box );
1296}
1297
1298void wxOverlayImpl::Reset()
1299{
1300 if ( m_overlayContext )
1301 {
1302#ifndef __LP64__
1303 OSStatus err = QDEndCGContext(GetWindowPort(m_overlayWindow), &m_overlayContext);
1304 wxASSERT_MSG( err == noErr , _("Couldn't end the context on the overlay window") );
1305#endif
1306 m_overlayContext = NULL ;
1307 }
1308
1309 // todo : don't dispose, only hide and reposition on next run
1310 if (m_overlayWindow)
1311 {
1312 DisposeWindow(m_overlayWindow);
1313 m_overlayWindow = NULL ;
1314 }
1315}
1316
1317//
1318//
1319//
1320
1321#else // ie not wxMAC_USE_CORE_GRAPHICS
1322
1323class wxOverlayImpl
1324{
1325public:
1326 wxOverlayImpl() ;
1327 ~wxOverlayImpl() ;
1328
1329
1330 // clears the overlay without restoring the former state
1331 // to be done eg when the window content has been changed and repainted
1332 void Reset();
1333
1334 // returns true if it has been setup
1335 bool IsOk();
1336
1337 void Init( wxWindowDC* dc, int x , int y , int width , int height );
1338
1339 void BeginDrawing( wxWindowDC* dc);
1340
1341 void EndDrawing( wxWindowDC* dc);
1342
1343 void Clear( wxWindowDC* dc);
1344
1345private:
1346 wxBitmap m_bmpSaved ;
1347 int m_x ;
1348 int m_y ;
1349 int m_width ;
1350 int m_height ;
1351// this is to enable wxMOTIF and UNIV to compile....
1352// currently (10 oct 06) we don't use m_window
1353// ce - how do we fix this
1354#if defined(__WXGTK__) || defined(__WXMSW__)
1355//
1356 wxWindow* m_window ;
1357#endif
1358} ;
1359
1360wxOverlayImpl::wxOverlayImpl()
1361{
1362#if defined(__WXGTK__) || defined(__WXMSW__)
1363 m_window = NULL ;
1364#endif
1365 m_x = m_y = m_width = m_height = 0 ;
1366}
1367
1368wxOverlayImpl::~wxOverlayImpl()
1369{
1370}
1371
1372bool wxOverlayImpl::IsOk()
1373{
1374 return m_bmpSaved.Ok() ;
1375}
1376
1377void wxOverlayImpl::Init( wxWindowDC* dc, int x , int y , int width , int height )
1378{
1379#if defined(__WXGTK__)
1380 m_window = dc->m_owner;
1381#else
1382 #if defined (__WXMSW__)
1383 m_window = dc->GetWindow();
1384 #endif // __WXMSW__
1385
1386#endif
1387 wxMemoryDC dcMem ;
1388 m_bmpSaved.Create( width, height );
1389 dcMem.SelectObject( m_bmpSaved );
1390 m_x = x ;
1391 m_y = y ;
1392 m_width = width ;
1393 m_height = height ;
1394#if defined(__WXGTK__) && !defined(__WX_DC_BLIT_FIXED__)
1395 wxPoint pt = dc->GetDeviceOrigin();
1396 x += pt.x;
1397 y += pt.y;
1398#endif // broken wxGTK wxDC::Blit
1399 dcMem.Blit(0, 0, m_width, m_height,
1400 dc, x, y);
1401 dcMem.SelectObject( wxNullBitmap );
1402}
1403
1404void wxOverlayImpl::Clear(wxWindowDC* dc)
1405{
1406 wxMemoryDC dcMem ;
1407 dcMem.SelectObject( m_bmpSaved );
1408 dc->Blit( m_x, m_y, m_width, m_height , &dcMem , 0 , 0 );
1409 dcMem.SelectObject( wxNullBitmap );
1410}
1411
1412void wxOverlayImpl::Reset()
1413{
1414 m_bmpSaved = wxBitmap();
1415}
1416
1417void wxOverlayImpl::BeginDrawing(wxWindowDC* WXUNUSED(dc))
1418{
1419}
1420
1421void wxOverlayImpl::EndDrawing(wxWindowDC* WXUNUSED(dc))
1422{
1423}
1424
1425#endif
1426
1427// common code
1428
1429wxOverlay::wxOverlay()
1430{
1431 m_impl = new wxOverlayImpl();
1432 m_inDrawing = false;
1433}
1434
1435wxOverlay::~wxOverlay()
1436{
1437 wxDELETE( m_impl );
1438}
1439
1440bool wxOverlay::IsOk()
1441{
1442 return m_impl->IsOk();
1443}
1444
1445void wxOverlay::Init( wxWindowDC* dc, int x , int y , int width , int height )
1446{
1447 m_impl->Init(dc, x, y, width, height);
1448}
1449
1450void wxOverlay::BeginDrawing( wxWindowDC* dc)
1451{
1452 m_impl->BeginDrawing(dc);
1453 m_inDrawing = true ;
1454}
1455
1456void wxOverlay::EndDrawing( wxWindowDC* dc)
1457{
1458 m_impl->EndDrawing(dc);
1459 m_inDrawing = false ;
1460}
1461
1462void wxOverlay::Clear( wxWindowDC* dc)
1463{
1464 m_impl->Clear(dc);
1465}
1466
1467void wxOverlay::Reset()
1468{
1469 wxASSERT_MSG(m_inDrawing==false,wxT("cannot reset overlay during drawing"));
1470 m_impl->Reset();
1471}
1472
1473// dc connector
1474
1475wxDCOverlay::wxDCOverlay(wxOverlay &overlay, wxWindowDC *dc, int x , int y , int width , int height) :
1476 m_overlay(overlay)
1477{
1478 Init(dc, x, y, width, height);
1479}
1480
1481wxDCOverlay::wxDCOverlay(wxOverlay &overlay, wxWindowDC *dc) :
1482 m_overlay(overlay)
1483{
1484 int width;
1485 int height;
1486 dc->GetSize(&width,&height);
1487 Init(dc, 0, 0, width, height);
1488}
1489
1490wxDCOverlay::~wxDCOverlay()
1491{
1492 m_overlay.EndDrawing(m_dc);
1493}
1494
1495void wxDCOverlay::Init(wxWindowDC *dc, int x , int y , int width , int height )
1496{
1497 m_dc = dc ;
1498 if ( !m_overlay.IsOk() )
1499 {
1500 m_overlay.Init(dc,x,y,width,height);
1501 }
1502 m_overlay.BeginDrawing(dc);
1503}
1504
1505void wxDCOverlay::Clear()
1506{
1507 m_overlay.Clear(m_dc);
1508}