replacing old core graphics with new graphics context implementation
[wxWidgets.git] / src / common / dcbase.cpp
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
36 IMPLEMENT_ABSTRACT_CLASS(wxDCBase, wxObject)
37
38 // ============================================================================
39 // implementation
40 // ============================================================================
41
42 IMPLEMENT_DYNAMIC_CLASS(wxBufferedDC, wxMemoryDC)
43 IMPLEMENT_ABSTRACT_CLASS(wxBufferedPaintDC, wxBufferedDC)
44
45 #if WXWIN_COMPATIBILITY_2_6
46 void wxDCBase::BeginDrawing()
47 {
48 }
49
50 void wxDCBase::EndDrawing()
51 {
52 }
53 #endif // WXWIN_COMPATIBILITY_2_6
54
55 // ----------------------------------------------------------------------------
56 // special symbols
57 // ----------------------------------------------------------------------------
58
59 void 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
84 void 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
103 void 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
123 void
124 wxDCBase::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 *"?)
173 void 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
198 void 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
211 void wx_quadratic_spline(double a1, double b1, double a2, double b2,
212 double a3, double b3, double a4, double b4);
213 void wx_clear_stack();
214 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
215 double *y3, double *x4, double *y4);
216 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
217 double x4, double y4);
218 static bool wx_spline_add_point(double x, double y);
219 static void wx_spline_draw_point_array(wxDCBase *dc);
220
221 wxList wx_spline_point_list;
222
223 #define half(z1, z2) ((z1+z2)/2.0)
224 #define THRESHOLD 5
225
226 /* iterative version */
227
228 void 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
255 typedef struct wx_spline_stack_struct {
256 double x1, y1, x2, y2, x3, y3, x4, y4;
257 } Stack;
258
259 #define SPLINE_STACK_DEPTH 20
260 static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
261 static Stack *wx_stack_top;
262 static int wx_stack_count;
263
264 void wx_clear_stack()
265 {
266 wx_stack_top = wx_spline_stack;
267 wx_stack_count = 0;
268 }
269
270 void 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
284 int 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
302 static 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
311 static 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
324 void 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
399 class FontWidthCache
400 {
401 public:
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
418 static FontWidthCache s_fontWidthCache;
419
420 bool 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
469 void 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
536 void 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
693 void 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
783 void 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 /*
843 Notes for wxWidgets DrawEllipticArcRot(...)
844
845 wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse.
846 It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...),
847 which are also new.
848
849 All methods are generic, so they can be implemented in wxDCBase.
850 DoDrawEllipticArcRot(...) is virtual, so it can be called from deeper
851 methods like (WinCE) wxDC::DoDrawArc(...).
852
853 CalculateEllipticPoints(...) fills a given list of wxPoints with some points
854 of an elliptic arc. The algorithm is pixel-based: In every row (in flat
855 parts) or every column (in steep parts) only one pixel is calculated.
856 Trigonometric calculation (sin, cos, tan, atan) is only done if the
857 starting angle is not equal to the ending angle. The calculation of the
858 pixels is done using simple arithmetic only and should perform not too
859 bad even on devices without floating point processor. I didn't test this yet.
860
861 Rotate(...) rotates a list of point pixel-based, you will see rounding errors.
862 For instance: an ellipse rotated 180 degrees is drawn
863 slightly different from the original.
864
865 The points are then moved to an array and used to draw a polyline and/or polygon
866 (with center added, the pie).
867 The result looks quite similar to the native ellipse, only e few pixels differ.
868
869 The performance on a desktop system (Athlon 1800, WinXP) is about 7 times
870 slower as DrawEllipse(...), which calls the native API.
871 An rotated ellipse outside the clipping region takes nearly the same time,
872 while an native ellipse outside takes nearly no time to draw.
873
874 If you draw an arc with this new method, you will see the starting and ending angles
875 are calculated properly.
876 If you use DrawEllipticArc(...), you will see they are only correct for circles
877 and not properly calculated for ellipses.
878
879 Peter Lenhard
880 p.lenhard@t-online.de
881 */
882
883 #ifdef __WXWINCE__
884 void 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
929 void 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
956 void 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
1166 class wxOverlayImpl
1167 {
1168 public:
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
1188 private:
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
1205 wxOverlayImpl::wxOverlayImpl()
1206 {
1207 m_window = NULL ;
1208 m_overlayContext = NULL ;
1209 m_overlayWindow = NULL ;
1210 }
1211
1212 wxOverlayImpl::~wxOverlayImpl()
1213 {
1214 Reset();
1215 }
1216
1217 bool wxOverlayImpl::IsOk()
1218 {
1219 return m_overlayWindow != NULL ;
1220 }
1221
1222 void 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
1232 OSStatus 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
1251 void 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
1271 void wxOverlayImpl::BeginDrawing( wxWindowDC* dc)
1272 {
1273 // TODO CS
1274 dc->SetGraphicsContext( wxGraphicsContext::CreateFromNative( m_overlayContext ) );
1275 /*
1276 delete dc->m_graphicContext ;
1277 dc->m_graphicContext = new wxMacCGContext( m_overlayContext );
1278 // we are right now startin at 0,0 not at the wxWindow's origin, so most of the calculations
1279 // int dc are already corect
1280 // just to make sure :
1281 dc->m_macLocalOrigin.x = 0 ;
1282 dc->m_macLocalOrigin.y = 0 ;
1283 */
1284 wxSize size = m_window->GetSize() ;
1285 dc->SetClippingRegion( 0 , 0 , size.x , size.y ) ;
1286 }
1287
1288 void wxOverlayImpl::EndDrawing( wxWindowDC* dc)
1289 {
1290 dc->SetGraphicsContext(NULL);
1291 }
1292
1293 void wxOverlayImpl::Clear(wxWindowDC* dc)
1294 {
1295 wxASSERT_MSG( IsOk() , _("You cannot Clear an overlay that is not inited") );
1296 CGRect box = CGRectMake( m_x - 1, m_y - 1 , m_width + 2 , m_height + 2 );
1297 CGContextClearRect( m_overlayContext, box );
1298 }
1299
1300 void wxOverlayImpl::Reset()
1301 {
1302 if ( m_overlayContext )
1303 {
1304 #ifndef __LP64__
1305 OSStatus err = QDEndCGContext(GetWindowPort(m_overlayWindow), &m_overlayContext);
1306 wxASSERT_MSG( err == noErr , _("Couldn't end the context on the overlay window") );
1307 #endif
1308 m_overlayContext = NULL ;
1309 }
1310
1311 // todo : don't dispose, only hide and reposition on next run
1312 if (m_overlayWindow)
1313 {
1314 DisposeWindow(m_overlayWindow);
1315 m_overlayWindow = NULL ;
1316 }
1317 }
1318
1319 //
1320 //
1321 //
1322
1323 #else // ie not wxMAC_USE_CORE_GRAPHICS
1324
1325 class wxOverlayImpl
1326 {
1327 public:
1328 wxOverlayImpl() ;
1329 ~wxOverlayImpl() ;
1330
1331
1332 // clears the overlay without restoring the former state
1333 // to be done eg when the window content has been changed and repainted
1334 void Reset();
1335
1336 // returns true if it has been setup
1337 bool IsOk();
1338
1339 void Init( wxWindowDC* dc, int x , int y , int width , int height );
1340
1341 void BeginDrawing( wxWindowDC* dc);
1342
1343 void EndDrawing( wxWindowDC* dc);
1344
1345 void Clear( wxWindowDC* dc);
1346
1347 private:
1348 wxBitmap m_bmpSaved ;
1349 int m_x ;
1350 int m_y ;
1351 int m_width ;
1352 int m_height ;
1353 // this is to enable wxMOTIF and UNIV to compile....
1354 // currently (10 oct 06) we don't use m_window
1355 // ce - how do we fix this
1356 #if defined(__WXGTK__) || defined(__WXMSW__)
1357 //
1358 wxWindow* m_window ;
1359 #endif
1360 } ;
1361
1362 wxOverlayImpl::wxOverlayImpl()
1363 {
1364 #if defined(__WXGTK__) || defined(__WXMSW__)
1365 m_window = NULL ;
1366 #endif
1367 m_x = m_y = m_width = m_height = 0 ;
1368 }
1369
1370 wxOverlayImpl::~wxOverlayImpl()
1371 {
1372 }
1373
1374 bool wxOverlayImpl::IsOk()
1375 {
1376 return m_bmpSaved.Ok() ;
1377 }
1378
1379 void wxOverlayImpl::Init( wxWindowDC* dc, int x , int y , int width , int height )
1380 {
1381 #if defined(__WXGTK__)
1382 m_window = dc->m_owner;
1383 #else
1384 #if defined (__WXMSW__)
1385 m_window = dc->GetWindow();
1386 #endif // __WXMSW__
1387
1388 #endif
1389 wxMemoryDC dcMem ;
1390 m_bmpSaved.Create( width, height );
1391 dcMem.SelectObject( m_bmpSaved );
1392 m_x = x ;
1393 m_y = y ;
1394 m_width = width ;
1395 m_height = height ;
1396 #if defined(__WXGTK__) && !defined(__WX_DC_BLIT_FIXED__)
1397 wxPoint pt = dc->GetDeviceOrigin();
1398 x += pt.x;
1399 y += pt.y;
1400 #endif // broken wxGTK wxDC::Blit
1401 dcMem.Blit(0, 0, m_width, m_height,
1402 dc, x, y);
1403 dcMem.SelectObject( wxNullBitmap );
1404 }
1405
1406 void wxOverlayImpl::Clear(wxWindowDC* dc)
1407 {
1408 wxMemoryDC dcMem ;
1409 dcMem.SelectObject( m_bmpSaved );
1410 dc->Blit( m_x, m_y, m_width, m_height , &dcMem , 0 , 0 );
1411 dcMem.SelectObject( wxNullBitmap );
1412 }
1413
1414 void wxOverlayImpl::Reset()
1415 {
1416 m_bmpSaved = wxBitmap();
1417 }
1418
1419 void wxOverlayImpl::BeginDrawing(wxWindowDC* WXUNUSED(dc))
1420 {
1421 }
1422
1423 void wxOverlayImpl::EndDrawing(wxWindowDC* WXUNUSED(dc))
1424 {
1425 }
1426
1427 #endif
1428
1429 // common code
1430
1431 wxOverlay::wxOverlay()
1432 {
1433 m_impl = new wxOverlayImpl();
1434 m_inDrawing = false;
1435 }
1436
1437 wxOverlay::~wxOverlay()
1438 {
1439 wxDELETE( m_impl );
1440 }
1441
1442 bool wxOverlay::IsOk()
1443 {
1444 return m_impl->IsOk();
1445 }
1446
1447 void wxOverlay::Init( wxWindowDC* dc, int x , int y , int width , int height )
1448 {
1449 m_impl->Init(dc, x, y, width, height);
1450 }
1451
1452 void wxOverlay::BeginDrawing( wxWindowDC* dc)
1453 {
1454 m_impl->BeginDrawing(dc);
1455 m_inDrawing = true ;
1456 }
1457
1458 void wxOverlay::EndDrawing( wxWindowDC* dc)
1459 {
1460 m_impl->EndDrawing(dc);
1461 m_inDrawing = false ;
1462 }
1463
1464 void wxOverlay::Clear( wxWindowDC* dc)
1465 {
1466 m_impl->Clear(dc);
1467 }
1468
1469 void wxOverlay::Reset()
1470 {
1471 wxASSERT_MSG(m_inDrawing==false,wxT("cannot reset overlay during drawing"));
1472 m_impl->Reset();
1473 }
1474
1475 // dc connector
1476
1477 wxDCOverlay::wxDCOverlay(wxOverlay &overlay, wxWindowDC *dc, int x , int y , int width , int height) :
1478 m_overlay(overlay)
1479 {
1480 Init(dc, x, y, width, height);
1481 }
1482
1483 wxDCOverlay::wxDCOverlay(wxOverlay &overlay, wxWindowDC *dc) :
1484 m_overlay(overlay)
1485 {
1486 int width;
1487 int height;
1488 dc->GetSize(&width,&height);
1489 Init(dc, 0, 0, width, height);
1490 }
1491
1492 wxDCOverlay::~wxDCOverlay()
1493 {
1494 m_overlay.EndDrawing(m_dc);
1495 }
1496
1497 void wxDCOverlay::Init(wxWindowDC *dc, int x , int y , int width , int height )
1498 {
1499 m_dc = dc ;
1500 if ( !m_overlay.IsOk() )
1501 {
1502 m_overlay.Init(dc,x,y,width,height);
1503 }
1504 m_overlay.BeginDrawing(dc);
1505 }
1506
1507 void wxDCOverlay::Clear()
1508 {
1509 m_overlay.Clear(m_dc);
1510 }