]> git.saurik.com Git - wxWidgets.git/blame - src/common/dcbase.cpp
on demand creation of native CGContexts , so that pure text measuring contexts don...
[wxWidgets.git] / src / common / dcbase.cpp
CommitLineData
dbe94982 1/////////////////////////////////////////////////////////////////////////////
06052f3f 2// Name: src/common/dcbase.cpp
1e6feb95
VZ
3// Purpose: generic methods of the wxDC Class
4// Author: Vadim Zeitlin
dbe94982
BM
5// Modified by:
6// Created: 05/25/99
7// RCS-ID: $Id$
77ffb593 8// Copyright: (c) wxWidgets team
65571936 9// Licence: wxWindows licence
dbe94982
BM
10/////////////////////////////////////////////////////////////////////////////
11
1e6feb95
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
1e6feb95
VZ
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
dbe94982
BM
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
bd1e9c12 24 #pragma hdrstop
dbe94982
BM
25#endif
26
dbe94982 27#include "wx/dc.h"
653752be 28#include "wx/dcbuffer.h" // for IMPLEMENT_DYNAMIC_CLASS
18680f86
WS
29
30#ifndef WX_PRECOMP
31 #include "wx/math.h"
32#endif
dbe94982 33
68379eaf 34// bool wxDCBase::sm_cacheing = false;
0cbff120 35
e7445ff8
PC
36IMPLEMENT_ABSTRACT_CLASS(wxDCBase, wxObject)
37
1e6feb95
VZ
38// ============================================================================
39// implementation
40// ============================================================================
41
653752be
MB
42IMPLEMENT_DYNAMIC_CLASS(wxBufferedDC, wxMemoryDC)
43IMPLEMENT_ABSTRACT_CLASS(wxBufferedPaintDC, wxBufferedDC)
44
68df211f
JG
45#if WXWIN_COMPATIBILITY_2_6
46void wxDCBase::BeginDrawing()
47{
48}
49
50void wxDCBase::EndDrawing()
51{
52}
53#endif // WXWIN_COMPATIBILITY_2_6
54
1e6feb95
VZ
55// ----------------------------------------------------------------------------
56// special symbols
57// ----------------------------------------------------------------------------
58
cd9da200
VZ
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
1e6feb95
VZ
80// ----------------------------------------------------------------------------
81// line/polygons
82// ----------------------------------------------------------------------------
83
72cdf4c9 84void wxDCBase::DrawLines(const wxList *list, wxCoord xoffset, wxCoord yoffset)
dbe94982 85{
b1d4dd7a 86 int n = list->GetCount();
dbe94982
BM
87 wxPoint *points = new wxPoint[n];
88
89 int i = 0;
222ed1d6 90 for ( wxList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
dbe94982 91 {
b1d4dd7a 92 wxPoint *point = (wxPoint *)node->GetData();
dbe94982
BM
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,
72cdf4c9 104 wxCoord xoffset, wxCoord yoffset,
dbe94982
BM
105 int fillStyle)
106{
b1d4dd7a 107 int n = list->GetCount();
dbe94982
BM
108 wxPoint *points = new wxPoint[n];
109
110 int i = 0;
222ed1d6 111 for ( wxList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
dbe94982 112 {
b1d4dd7a 113 wxPoint *point = (wxPoint *)node->GetData();
dbe94982
BM
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
63b9e659
VZ
123void
124wxDCBase::DoDrawPolyPolygon(int n,
793db755 125 int count[],
63b9e659
VZ
126 wxPoint points[],
127 wxCoord xoffset, wxCoord yoffset,
128 int fillStyle)
129{
130 if ( n == 1 )
131 {
793db755 132 DoDrawPolygon(count[0], points, xoffset, yoffset, fillStyle);
63b9e659
VZ
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;
793db755 143 j += count[i];
63b9e659
VZ
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 {
793db755 150 lastOfs -= count[n-i];
63b9e659
VZ
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 {
793db755
VZ
160 DoDrawLines(count[i], pts+j, xoffset, yoffset);
161 j += count[i];
63b9e659 162 }
6db1f43b 163 delete[] pts;
63b9e659
VZ
164}
165
1e6feb95
VZ
166// ----------------------------------------------------------------------------
167// splines
168// ----------------------------------------------------------------------------
dbe94982 169
88ac883a 170#if wxUSE_SPLINES
dbe94982
BM
171
172// TODO: this API needs fixing (wxPointList, why (!const) "wxList *"?)
72cdf4c9 173void wxDCBase::DrawSpline(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord x3, wxCoord y3)
dbe94982
BM
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
222ed1d6 191 for( wxList::compatibility_iterator node = point_list.GetFirst(); node; node = node->GetNext() )
dbe94982 192 {
b1d4dd7a 193 wxPoint *p = (wxPoint *)node->GetData();
dbe94982
BM
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
fe2e4366
VS
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);
68379eaf 308 return true;
fe2e4366
VS
309}
310
311static void wx_spline_draw_point_array(wxDCBase *dc)
312{
313 dc->DrawLines(&wx_spline_point_list, 0, 0 );
222ed1d6 314 wxList::compatibility_iterator node = wx_spline_point_list.GetFirst();
fe2e4366
VS
315 while (node)
316 {
b1d4dd7a 317 wxPoint *point = (wxPoint *)node->GetData();
fe2e4366 318 delete point;
222ed1d6 319 wx_spline_point_list.Erase(node);
b1d4dd7a 320 node = wx_spline_point_list.GetFirst();
fe2e4366
VS
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
222ed1d6 332 wxList::compatibility_iterator node = points->GetFirst();
55e3f1c4 333 if (node == wxList::compatibility_iterator())
410bb8c1
RD
334 // empty list
335 return;
e0d31471 336
b1d4dd7a 337 p = (wxPoint *)node->GetData();
fe2e4366
VS
338
339 x1 = p->x;
340 y1 = p->y;
341
b1d4dd7a
RL
342 node = node->GetNext();
343 p = (wxPoint *)node->GetData();
fe2e4366
VS
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
28b4db7f
VZ
354 while ((node = node->GetNext())
355#if !wxUSE_STL
356 != NULL
357#endif // !wxUSE_STL
358 )
fe2e4366 359 {
b1d4dd7a 360 p = (wxPoint *)node->GetData();
fe2e4366
VS
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
88ac883a 384#endif // wxUSE_SPLINES
1e6feb95 385
0919e93e
RD
386// ----------------------------------------------------------------------------
387// Partial Text Extents
388// ----------------------------------------------------------------------------
389
390
174ee1b3 391// Each element of the widths array will be the width of the string up to and
3103e8a9 392// including the corresponding character in text. This is the generic
0919e93e 393// implementation, the port-specific classes should do this with native APIs
174ee1b3
RD
394// if available and if faster. Note: pango_layout_index_to_pos is much slower
395// than calling GetTextExtent!!
396
06fe86b7 397#define FWC_SIZE 256
174ee1b3
RD
398
399class FontWidthCache
400{
401public:
402 FontWidthCache() : m_scaleX(1), m_widths(NULL) { }
403 ~FontWidthCache() { delete []m_widths; }
2aaa050c
VZ
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
174ee1b3
RD
413 wxFont m_font;
414 double m_scaleX;
415 int *m_widths;
416};
417
418static FontWidthCache s_fontWidthCache;
0919e93e
RD
419
420bool wxDCBase::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
421{
422 int totalWidth = 0;
0919e93e 423
18680f86 424 const size_t len = text.length();
0919e93e 425 widths.Empty();
174ee1b3 426 widths.Add(0, len);
2aaa050c 427
174ee1b3 428 // reset the cache if font or horizontal scale have changed
c77a6796
VZ
429 if ( !s_fontWidthCache.m_widths ||
430 !wxIsSameDouble(s_fontWidthCache.m_scaleX, m_scaleX) ||
431 (s_fontWidthCache.m_font != GetFont()) )
174ee1b3
RD
432 {
433 s_fontWidthCache.Reset();
434 s_fontWidthCache.m_font = GetFont();
435 s_fontWidthCache.m_scaleX = m_scaleX;
436 }
437
0919e93e
RD
438 // Calculate the position of each character based on the widths of
439 // the previous characters
c77a6796
VZ
440 int w, h;
441 for ( size_t i = 0; i < len; i++ )
174ee1b3
RD
442 {
443 const wxChar c = text[i];
444 unsigned int c_int = (unsigned int)c;
445
2aaa050c 446 if ((c_int < FWC_SIZE) && (s_fontWidthCache.m_widths[c_int] != 0))
174ee1b3
RD
447 {
448 w = s_fontWidthCache.m_widths[c_int];
449 }
2aaa050c 450 else
174ee1b3
RD
451 {
452 GetTextExtent(c, &w, &h);
453 if (c_int < FWC_SIZE)
454 s_fontWidthCache.m_widths[c_int] = w;
455 }
456
0919e93e
RD
457 totalWidth += w;
458 widths[i] = totalWidth;
459 }
2aaa050c 460
0919e93e
RD
461 return true;
462}
463
464
1e6feb95
VZ
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{
c7aaa64f
VS
475 wxCoord widthTextMax = 0, widthLine,
476 heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
1e6feb95
VZ
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 {
68379eaf 592 DrawBitmap(bitmap, x, y, true /* use mask */);
1e6feb95
VZ
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 {
328bfc22 655 if ( pc - text.c_str() == indexAccel )
1e6feb95
VZ
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}
12bdd77c 691
213ad8e7
VZ
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
fb63a242 783void wxDCBase::DoGradientFillConcentric(const wxRect& rect,
213ad8e7
VZ
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
213ad8e7
VZ
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
e35d07b9 813 for ( wxInt32 x = 0; x < rect.GetWidth(); x++ )
213ad8e7 814 {
e35d07b9 815 for ( wxInt32 y = 0; y < rect.GetHeight(); y++ )
213ad8e7
VZ
816 {
817 //get color difference
e35d07b9
VZ
818 wxInt32 nGradient = ((nRadius -
819 (wxInt32)sqrt(
820 pow((double)(x - cx - nCircleOffX), 2) +
821 pow((double)(y - cy - nCircleOffY), 2)
822 )) * 100) / nRadius;
213ad8e7
VZ
823
824 //normalize Gradient
825 if (nGradient < 0 )
826 nGradient = 0;
827
828 //get dest colors
06052f3f
WS
829 nR = (wxUint8)(nR1 + ((nR2 - nR1) * nGradient / 100));
830 nG = (wxUint8)(nG1 + ((nG2 - nG1) * nGradient / 100));
831 nB = (wxUint8)(nB1 + ((nB2 - nB1) * nGradient / 100));
213ad8e7
VZ
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
12bdd77c 842/*
77ffb593 843Notes for wxWidgets DrawEllipticArcRot(...)
12bdd77c
JS
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
2aaa050c 854of an elliptic arc. The algorithm is pixel-based: In every row (in flat
12bdd77c
JS
855parts) or every column (in steep parts) only one pixel is calculated.
856Trigonometric calculation (sin, cos, tan, atan) is only done if the
2aaa050c 857starting angle is not equal to the ending angle. The calculation of the
12bdd77c
JS
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.
2aaa050c 862For instance: an ellipse rotated 180 degrees is drawn
12bdd77c
JS
863slightly different from the original.
864
2aaa050c
VZ
865The points are then moved to an array and used to draw a polyline and/or polygon
866(with center added, the pie).
12bdd77c
JS
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
2aaa050c 874If you draw an arc with this new method, you will see the starting and ending angles
12bdd77c
JS
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__
2aaa050c
VZ
884void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y,
885 wxCoord w, wxCoord h,
12bdd77c
JS
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
2c3ebf8b 897 int n = list.GetCount();
12bdd77c
JS
898 wxPoint *points = new wxPoint[n];
899 int i = 0;
2aaa050c 900 wxNode* node = 0;
2c3ebf8b 901 for ( node = list.GetFirst(); node; node = node->GetNext(), i++ )
12bdd77c 902 {
2c3ebf8b 903 wxPoint *point = (wxPoint *)node->GetData();
12bdd77c
JS
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
63b9e659 910 if( GetBrush() != *wxTRANSPARENT_BRUSH )
12bdd77c
JS
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
63b9e659 919 if( GetPen() != *wxTRANSPARENT_PEN )
12bdd77c
JS
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 {
e0d31471 933 double pi(M_PI);
12bdd77c
JS
934 double dSinA = -sin(angle*2.0*pi/360.0);
935 double dCosA = cos(angle*2.0*pi/360.0);
2c3ebf8b 936 for ( wxNode* node = points->GetFirst(); node; node = node->GetNext() )
12bdd77c 937 {
2c3ebf8b 938 wxPoint* point = (wxPoint*)node->GetData();
2aaa050c 939
12bdd77c
JS
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
2aaa050c
VZ
956void wxDCBase::CalculateEllipticPoints( wxList* points,
957 wxCoord xStart, wxCoord yStart,
958 wxCoord w, wxCoord h,
12bdd77c
JS
959 double sa, double ea )
960{
e0d31471 961 double pi = M_PI;
12bdd77c
JS
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;
2aaa050c 978 if( 2*a == w ) decrX = 1;
12bdd77c 979 int decrY = 0;
2aaa050c 980 if( 2*b == h ) decrY = 1;
12bdd77c
JS
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 ) );
2aaa050c 1004 if ( sq == 1 || sq == 2 ) sar += pi;
12bdd77c
JS
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 }
2aaa050c 1043 // old y now to big: set point with old y, old x
12bdd77c
JS
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
2aaa050c 1054
12bdd77c
JS
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 {
2c3ebf8b 1074 for( wxNode *node = pointsarray[q].GetFirst(); node; node = node->GetNext() )
12bdd77c
JS
1075 {
1076 // once: go to starting point in start quadrant
1077 if( !bStarted &&
2aaa050c 1078 (
2c3ebf8b 1079 ( (wxPoint*) node->GetData() )->x < xsa+1 && q <= 1
2aaa050c 1080 ||
2c3ebf8b 1081 ( (wxPoint*) node->GetData() )->x > xsa-1 && q >= 2
12bdd77c 1082 )
2aaa050c 1083 )
12bdd77c
JS
1084 {
1085 bStarted = true;
1086 }
1087
1088 // copy point, if not at ending point
1089 if( bStarted )
1090 {
1091 if( q != eq || bForceTurn
1092 ||
2c3ebf8b 1093 ( (wxPoint*) node->GetData() )->x > xea+1 && q <= 1
2aaa050c 1094 ||
2c3ebf8b 1095 ( (wxPoint*) node->GetData() )->x < xea-1 && q >= 2
12bdd77c
JS
1096 )
1097 {
1098 // copy point
2c3ebf8b 1099 wxPoint* pPoint = new wxPoint( *((wxPoint*) node->GetData() ) );
12bdd77c
JS
1100 points->Append( (wxObject*) pPoint );
1101 }
2c3ebf8b 1102 else if( q == eq && !bForceTurn || ( (wxPoint*) node->GetData() )->x == xea)
12bdd77c 1103 {
2aaa050c 1104 bReady = true;
12bdd77c
JS
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 {
2c3ebf8b 1118 for( wxNode *node = pointsarray[q].GetFirst(); node; node = node->GetNext() )
12bdd77c 1119 {
2c3ebf8b 1120 wxPoint *p = (wxPoint *)node->GetData();
12bdd77c
JS
1121 delete p;
1122 }
2aaa050c 1123 }
12bdd77c
JS
1124 }
1125 else
1126 {
b1c6a00e 1127 wxNode* node;
12bdd77c 1128 // copy whole ellipse, wxPoints will be deleted outside
2c3ebf8b 1129 for( node = pointsarray[0].GetFirst(); node; node = node->GetNext() )
12bdd77c 1130 {
2c3ebf8b 1131 wxObject *p = node->GetData();
12bdd77c
JS
1132 points->Append( p );
1133 }
2c3ebf8b 1134 for( node = pointsarray[1].GetFirst(); node; node = node->GetNext() )
12bdd77c 1135 {
2c3ebf8b 1136 wxObject *p = node->GetData();
12bdd77c
JS
1137 points->Append( p );
1138 }
2c3ebf8b 1139 for( node = pointsarray[2].GetFirst(); node; node = node->GetNext() )
12bdd77c 1140 {
2c3ebf8b 1141 wxObject *p = node->GetData();
12bdd77c
JS
1142 points->Append( p );
1143 }
2c3ebf8b 1144 for( node = pointsarray[3].GetFirst(); node; node = node->GetNext() )
12bdd77c 1145 {
2c3ebf8b 1146 wxObject *p = node->GetData();
12bdd77c
JS
1147 points->Append( p );
1148 }
1149 } // not iUseAngles
1150} // CalculateEllipticPoints
1151
abeb53aa
SC
1152#endif
1153
af76254d
SC
1154//
1155// temporary home for wxOverlay
1156//
1157
8ea2d232
SC
1158#include "wx/dcclient.h"
1159#include "wx/dcmemory.h"
1160
af76254d
SC
1161#if defined(wxMAC_USE_CORE_GRAPHICS) && wxMAC_USE_CORE_GRAPHICS
1162
1163#include "wx/mac/private.h"
250e4028 1164#include "wx/toplevel.h"
8acd14d1 1165#include "wx/graphics.h"
af76254d
SC
1166
1167class wxOverlayImpl
1168{
1169public:
1170 wxOverlayImpl() ;
1171 ~wxOverlayImpl() ;
1172
1173
1174 // clears the overlay without restoring the former state
1175 // to be done eg when the window content has been changed and repainted
1176 void Reset();
1177
1178 // returns true if it has been setup
1179 bool IsOk();
1180
1181 void Init( wxWindowDC* dc, int x , int y , int width , int height );
1182
1183 void BeginDrawing( wxWindowDC* dc);
1184
1185 void EndDrawing( wxWindowDC* dc);
1186
1187 void Clear( wxWindowDC* dc);
1188
1189private:
250e4028
SC
1190 OSStatus CreateOverlayWindow();
1191
1192 void MacGetBounds( Rect *bounds );
1193
1194 WindowRef m_overlayWindow;
1195 WindowRef m_overlayParentWindow;
af76254d
SC
1196 CGContextRef m_overlayContext ;
1197 // we store the window in case we would have to issue a Refresh()
1198 wxWindow* m_window ;
250e4028 1199
250e4028
SC
1200 int m_x ;
1201 int m_y ;
1202 int m_width ;
1203 int m_height ;
af76254d
SC
1204} ;
1205
1206wxOverlayImpl::wxOverlayImpl()
1207{
1208 m_window = NULL ;
1209 m_overlayContext = NULL ;
1210 m_overlayWindow = NULL ;
1211}
1212
1213wxOverlayImpl::~wxOverlayImpl()
1214{
1215 Reset();
1216}
1217
1218bool wxOverlayImpl::IsOk()
1219{
d72e4d13 1220 return m_overlayWindow != NULL ;
250e4028
SC
1221}
1222
1223void wxOverlayImpl::MacGetBounds( Rect *bounds )
1224{
af76254d
SC
1225 wxPoint origin(0,0);
1226 origin = m_window->ClientToScreen( origin );
250e4028
SC
1227 bounds->top = origin.y;
1228 bounds->left = origin.x;
1229 bounds->bottom = origin.y+m_y+m_height;
1230 bounds->right = origin.x+m_x+m_width;
1231}
1232
1233OSStatus wxOverlayImpl::CreateOverlayWindow()
1234{
1235 OSStatus err;
1236
d72e4d13
SC
1237 WindowAttributes overlayAttributes = kWindowIgnoreClicksAttribute;
1238
513b47e9
SC
1239 if ( m_window )
1240 {
1241 m_overlayParentWindow =(WindowRef) m_window->MacGetTopLevelWindowRef();
af76254d 1242
513b47e9
SC
1243 Rect bounds ;
1244 MacGetBounds(&bounds);
1245 err = CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, &m_overlayWindow );
1246 if ( err == noErr )
1247 {
d72e4d13 1248 SetWindowGroup( m_overlayWindow, GetWindowGroup(m_overlayParentWindow)); // Put them in the same group so that their window layers are consistent
513b47e9
SC
1249 }
1250 }
1251 else
1252 {
1253 m_overlayParentWindow = NULL ;
1254 CGRect cgbounds ;
1255 cgbounds = CGDisplayBounds(CGMainDisplayID());
1256 Rect bounds;
1257 bounds.top = cgbounds.origin.y;
1258 bounds.left = cgbounds.origin.x;
1259 bounds.bottom = bounds.top + cgbounds.size.height;
1260 bounds.right = bounds.left + cgbounds.size.width;
1261 err = CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, &m_overlayWindow );
1262 }
1263 ShowWindow(m_overlayWindow);
1264 return err;
250e4028
SC
1265}
1266
1267void wxOverlayImpl::Init( wxWindowDC* dc, int x , int y , int width , int height )
1268{
1269 wxASSERT_MSG( !IsOk() , _("You cannot Init an overlay twice") );
1270
1271 m_window = dc->GetWindow();
1272 m_x = x ;
1273 m_y = y ;
1274 m_width = width ;
1275 m_height = height ;
1276
1277 OSStatus err = CreateOverlayWindow();
af76254d 1278 wxASSERT_MSG( err == noErr , _("Couldn't create the overlay window") );
fb743cab 1279#ifndef __LP64__
af76254d 1280 err = QDBeginCGContext(GetWindowPort(m_overlayWindow), &m_overlayContext);
fb743cab 1281#endif
250e4028 1282 CGContextTranslateCTM( m_overlayContext, 0, m_height+m_y );
af76254d
SC
1283 CGContextScaleCTM( m_overlayContext, 1, -1 );
1284 wxASSERT_MSG( err == noErr , _("Couldn't init the context on the overlay window") );
1285}
1286
1287void wxOverlayImpl::BeginDrawing( wxWindowDC* dc)
1288{
cd7d36c0
SC
1289// TODO CS
1290 dc->SetGraphicsContext( wxGraphicsContext::CreateFromNative( m_overlayContext ) );
1291/*
af76254d
SC
1292 delete dc->m_graphicContext ;
1293 dc->m_graphicContext = new wxMacCGContext( m_overlayContext );
e69d5138
SC
1294 // we are right now startin at 0,0 not at the wxWindow's origin, so most of the calculations
1295 // int dc are already corect
1296 // just to make sure :
af76254d
SC
1297 dc->m_macLocalOrigin.x = 0 ;
1298 dc->m_macLocalOrigin.y = 0 ;
cd7d36c0 1299 */
513b47e9 1300 wxSize size = dc->GetSize() ;
e69d5138 1301 dc->SetClippingRegion( 0 , 0 , size.x , size.y ) ;
af76254d
SC
1302}
1303
1304void wxOverlayImpl::EndDrawing( wxWindowDC* dc)
1305{
cd7d36c0 1306 dc->SetGraphicsContext(NULL);
af76254d
SC
1307}
1308
1309void wxOverlayImpl::Clear(wxWindowDC* dc)
1310{
1311 wxASSERT_MSG( IsOk() , _("You cannot Clear an overlay that is not inited") );
d72e4d13
SC
1312 CGRect box = CGRectMake( m_x - 1, m_y - 1 , m_width + 2 , m_height + 2 );
1313 CGContextClearRect( m_overlayContext, box );
af76254d
SC
1314}
1315
1316void wxOverlayImpl::Reset()
1317{
1318 if ( m_overlayContext )
1319 {
fb743cab 1320#ifndef __LP64__
af76254d
SC
1321 OSStatus err = QDEndCGContext(GetWindowPort(m_overlayWindow), &m_overlayContext);
1322 wxASSERT_MSG( err == noErr , _("Couldn't end the context on the overlay window") );
fb743cab 1323#endif
af76254d 1324 m_overlayContext = NULL ;
d72e4d13 1325 }
af76254d
SC
1326
1327 // todo : don't dispose, only hide and reposition on next run
1328 if (m_overlayWindow)
1329 {
1330 DisposeWindow(m_overlayWindow);
1331 m_overlayWindow = NULL ;
1332 }
1333}
1334
1335//
1336//
1337//
1338
4857f07f 1339#else // ie not wxMAC_USE_CORE_GRAPHICS
af76254d
SC
1340
1341class wxOverlayImpl
1342{
1343public:
1344 wxOverlayImpl() ;
1345 ~wxOverlayImpl() ;
1346
1347
1348 // clears the overlay without restoring the former state
1349 // to be done eg when the window content has been changed and repainted
1350 void Reset();
1351
1352 // returns true if it has been setup
1353 bool IsOk();
1354
1355 void Init( wxWindowDC* dc, int x , int y , int width , int height );
1356
1357 void BeginDrawing( wxWindowDC* dc);
1358
1359 void EndDrawing( wxWindowDC* dc);
1360
1361 void Clear( wxWindowDC* dc);
1362
1363private:
1364 wxBitmap m_bmpSaved ;
1365 int m_x ;
1366 int m_y ;
1367 int m_width ;
1368 int m_height ;
4857f07f
CE
1369// this is to enable wxMOTIF and UNIV to compile....
1370// currently (10 oct 06) we don't use m_window
1371// ce - how do we fix this
1372#if defined(__WXGTK__) || defined(__WXMSW__)
1373//
af76254d 1374 wxWindow* m_window ;
4857f07f 1375#endif
af76254d
SC
1376} ;
1377
1378wxOverlayImpl::wxOverlayImpl()
1379{
4857f07f
CE
1380#if defined(__WXGTK__) || defined(__WXMSW__)
1381 m_window = NULL ;
1382#endif
af76254d
SC
1383 m_x = m_y = m_width = m_height = 0 ;
1384}
1385
1386wxOverlayImpl::~wxOverlayImpl()
1387{
1388}
1389
1390bool wxOverlayImpl::IsOk()
1391{
1392 return m_bmpSaved.Ok() ;
1393}
1394
1395void wxOverlayImpl::Init( wxWindowDC* dc, int x , int y , int width , int height )
1396{
b954afc9
SC
1397#if defined(__WXGTK__)
1398 m_window = dc->m_owner;
1399#else
4857f07f 1400 #if defined (__WXMSW__)
af76254d 1401 m_window = dc->GetWindow();
4857f07f
CE
1402 #endif // __WXMSW__
1403
b954afc9 1404#endif
af76254d
SC
1405 wxMemoryDC dcMem ;
1406 m_bmpSaved.Create( width, height );
1407 dcMem.SelectObject( m_bmpSaved );
1408 m_x = x ;
1409 m_y = y ;
1410 m_width = width ;
1411 m_height = height ;
1412#if defined(__WXGTK__) && !defined(__WX_DC_BLIT_FIXED__)
d10e22fe 1413 wxPoint pt = dc->GetDeviceOrigin();
af76254d
SC
1414 x += pt.x;
1415 y += pt.y;
1416#endif // broken wxGTK wxDC::Blit
1417 dcMem.Blit(0, 0, m_width, m_height,
1418 dc, x, y);
1419 dcMem.SelectObject( wxNullBitmap );
1420}
1421
1422void wxOverlayImpl::Clear(wxWindowDC* dc)
1423{
1424 wxMemoryDC dcMem ;
1425 dcMem.SelectObject( m_bmpSaved );
1426 dc->Blit( m_x, m_y, m_width, m_height , &dcMem , 0 , 0 );
1427 dcMem.SelectObject( wxNullBitmap );
1428}
1429
1430void wxOverlayImpl::Reset()
1431{
1432 m_bmpSaved = wxBitmap();
1433}
1434
1435void wxOverlayImpl::BeginDrawing(wxWindowDC* WXUNUSED(dc))
1436{
1437}
1438
1439void wxOverlayImpl::EndDrawing(wxWindowDC* WXUNUSED(dc))
1440{
1441}
1442
1443#endif
1444
1445// common code
1446
1447wxOverlay::wxOverlay()
1448{
1449 m_impl = new wxOverlayImpl();
1450 m_inDrawing = false;
1451}
1452
1453wxOverlay::~wxOverlay()
1454{
1455 wxDELETE( m_impl );
1456}
1457
1458bool wxOverlay::IsOk()
1459{
1460 return m_impl->IsOk();
1461}
1462
1463void wxOverlay::Init( wxWindowDC* dc, int x , int y , int width , int height )
1464{
1465 m_impl->Init(dc, x, y, width, height);
1466}
1467
1468void wxOverlay::BeginDrawing( wxWindowDC* dc)
1469{
1470 m_impl->BeginDrawing(dc);
1471 m_inDrawing = true ;
1472}
1473
1474void wxOverlay::EndDrawing( wxWindowDC* dc)
1475{
1476 m_impl->EndDrawing(dc);
1477 m_inDrawing = false ;
1478}
1479
1480void wxOverlay::Clear( wxWindowDC* dc)
1481{
1482 m_impl->Clear(dc);
1483}
1484
1485void wxOverlay::Reset()
1486{
1487 wxASSERT_MSG(m_inDrawing==false,wxT("cannot reset overlay during drawing"));
1488 m_impl->Reset();
1489}
1490
1491// dc connector
1492
1493wxDCOverlay::wxDCOverlay(wxOverlay &overlay, wxWindowDC *dc, int x , int y , int width , int height) :
1494 m_overlay(overlay)
1495{
1496 Init(dc, x, y, width, height);
1497}
1498
1499wxDCOverlay::wxDCOverlay(wxOverlay &overlay, wxWindowDC *dc) :
1500 m_overlay(overlay)
1501{
1502 int width;
1503 int height;
1504 dc->GetSize(&width,&height);
1505 Init(dc, 0, 0, width, height);
1506}
1507
1508wxDCOverlay::~wxDCOverlay()
1509{
1510 m_overlay.EndDrawing(m_dc);
1511}
1512
1513void wxDCOverlay::Init(wxWindowDC *dc, int x , int y , int width , int height )
1514{
1515 m_dc = dc ;
1516 if ( !m_overlay.IsOk() )
1517 {
1518 m_overlay.Init(dc,x,y,width,height);
1519 }
1520 m_overlay.BeginDrawing(dc);
1521}
1522
1523void wxDCOverlay::Clear()
1524{
1525 m_overlay.Clear(m_dc);
1526}