]> git.saurik.com Git - wxWidgets.git/blob - src/common/gdicmn.cpp
wx/debug.h is always unconditionally included by wx/defs.h
[wxWidgets.git] / src / common / gdicmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/gdicmn.cpp
3 // Purpose: Common GDI classes
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __VMS
13 #define XtDisplay XTDISPLAY
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #include "wx/gdicmn.h"
24
25 #ifndef WX_PRECOMP
26 #include "wx/log.h"
27 #include "wx/event.h"
28 #include "wx/app.h"
29 #include "wx/utils.h"
30 #include "wx/dc.h"
31 #include "wx/pen.h"
32 #include "wx/brush.h"
33 #include "wx/palette.h"
34 #include "wx/icon.h"
35 #include "wx/cursor.h"
36 #include "wx/settings.h"
37 #endif
38
39 #include "wx/bitmap.h"
40 #include "wx/font.h"
41 #include "wx/hashmap.h"
42
43 #include <string.h>
44
45 #ifdef __WXMOTIF__
46 #ifdef __VMS__
47 #pragma message disable nosimpint
48 #endif
49 #include <Xm/Xm.h>
50 #ifdef __VMS__
51 #pragma message enable nosimpint
52 #endif
53 #endif
54
55 #ifdef __WXX11__
56 #include "X11/Xlib.h"
57 #endif
58
59 #if wxUSE_EXTENDED_RTTI
60
61 // wxPoint
62
63 template<> void wxStringReadValue(const wxString &s , wxPoint &data )
64 {
65 wxSscanf(s, wxT("%d,%d"), &data.x , &data.y ) ;
66 }
67
68 template<> void wxStringWriteValue(wxString &s , const wxPoint &data )
69 {
70 s = wxString::Format(wxT("%d,%d"), data.x , data.y ) ;
71 }
72
73 wxCUSTOM_TYPE_INFO(wxPoint, wxToStringConverter<wxPoint> , wxFromStringConverter<wxPoint>)
74
75 template<> void wxStringReadValue(const wxString &s , wxSize &data )
76 {
77 wxSscanf(s, wxT("%d,%d"), &data.x , &data.y ) ;
78 }
79
80 template<> void wxStringWriteValue(wxString &s , const wxSize &data )
81 {
82 s = wxString::Format(wxT("%d,%d"), data.x , data.y ) ;
83 }
84
85 wxCUSTOM_TYPE_INFO(wxSize, wxToStringConverter<wxSize> , wxFromStringConverter<wxSize>)
86
87 #endif
88
89 IMPLEMENT_ABSTRACT_CLASS(wxDCBase, wxObject)
90
91 wxRect::wxRect(const wxPoint& point1, const wxPoint& point2)
92 {
93 x = point1.x;
94 y = point1.y;
95 width = point2.x - point1.x;
96 height = point2.y - point1.y;
97
98 if (width < 0)
99 {
100 width = -width;
101 x = point2.x;
102 }
103 width++;
104
105 if (height < 0)
106 {
107 height = -height;
108 y = point2.y;
109 }
110 height++;
111 }
112
113 bool wxRect::operator==(const wxRect& rect) const
114 {
115 return ((x == rect.x) &&
116 (y == rect.y) &&
117 (width == rect.width) &&
118 (height == rect.height));
119 }
120
121 wxRect wxRect::operator+(const wxRect& rect) const
122 {
123 int x1 = wxMin(this->x, rect.x);
124 int y1 = wxMin(this->y, rect.y);
125 int y2 = wxMax(y+height, rect.height+rect.y);
126 int x2 = wxMax(x+width, rect.width+rect.x);
127 return wxRect(x1, y1, x2-x1, y2-y1);
128 }
129
130 wxRect& wxRect::Union(const wxRect& rect)
131 {
132 // ignore empty rectangles: union with an empty rectangle shouldn't extend
133 // this one to (0, 0)
134 if ( !width || !height )
135 {
136 *this = rect;
137 }
138 else if ( rect.width && rect.height )
139 {
140 int x1 = wxMin(x, rect.x);
141 int y1 = wxMin(y, rect.y);
142 int y2 = wxMax(y + height, rect.height + rect.y);
143 int x2 = wxMax(x + width, rect.width + rect.x);
144
145 x = x1;
146 y = y1;
147 width = x2 - x1;
148 height = y2 - y1;
149 }
150 //else: we're not empty and rect is empty
151
152 return *this;
153 }
154
155 wxRect& wxRect::Inflate(wxCoord dx, wxCoord dy)
156 {
157 if (-2*dx>width)
158 {
159 // Don't allow deflate to eat more width than we have,
160 // a well-defined rectangle cannot have negative width.
161 x+=width/2;
162 width=0;
163 }
164 else
165 {
166 // The inflate is valid.
167 x-=dx;
168 width+=2*dx;
169 }
170
171 if (-2*dy>height)
172 {
173 // Don't allow deflate to eat more height than we have,
174 // a well-defined rectangle cannot have negative height.
175 y+=height/2;
176 height=0;
177 }
178 else
179 {
180 // The inflate is valid.
181 y-=dy;
182 height+=2*dy;
183 }
184
185 return *this;
186 }
187
188 bool wxRect::Inside(int cx, int cy) const
189 {
190 return ( (cx >= x) && (cy >= y)
191 && ((cy - y) < height)
192 && ((cx - x) < width)
193 );
194 }
195
196 wxRect& wxRect::Intersect(const wxRect& rect)
197 {
198 int x2 = GetRight(),
199 y2 = GetBottom();
200
201 if ( x < rect.x )
202 x = rect.x;
203 if ( y < rect.y )
204 y = rect.y;
205 if ( x2 > rect.GetRight() )
206 x2 = rect.GetRight();
207 if ( y2 > rect.GetBottom() )
208 y2 = rect.GetBottom();
209
210 width = x2 - x + 1;
211 height = y2 - y + 1;
212
213 if ( width <= 0 || height <= 0 )
214 {
215 width =
216 height = 0;
217 }
218
219 return *this;
220 }
221
222 bool wxRect::Intersects(const wxRect& rect) const
223 {
224 wxRect r = Intersect(rect);
225
226 // if there is no intersection, both width and height are 0
227 return r.width != 0;
228 }
229
230 // ============================================================================
231 // wxColourDatabase
232 // ============================================================================
233
234 // ----------------------------------------------------------------------------
235 // wxColourDatabase ctor/dtor
236 // ----------------------------------------------------------------------------
237
238 wxColourDatabase::wxColourDatabase ()
239 {
240 // will be created on demand in Initialize()
241 m_map = NULL;
242 }
243
244 wxColourDatabase::~wxColourDatabase ()
245 {
246 if ( m_map )
247 {
248 WX_CLEAR_HASH_MAP(wxStringToColourHashMap, *m_map);
249
250 delete m_map;
251 }
252
253 #ifdef __WXPM__
254 delete [] m_palTable;
255 #endif
256 }
257
258 // Colour database stuff
259 void wxColourDatabase::Initialize()
260 {
261 if ( m_map )
262 {
263 // already initialized
264 return;
265 }
266
267 m_map = new wxStringToColourHashMap;
268
269 static const struct wxColourDesc
270 {
271 const wxChar *name;
272 unsigned char r,g,b;
273 }
274 wxColourTable[] =
275 {
276 {wxT("AQUAMARINE"),112, 219, 147},
277 {wxT("BLACK"),0, 0, 0},
278 {wxT("BLUE"), 0, 0, 255},
279 {wxT("BLUE VIOLET"), 159, 95, 159},
280 {wxT("BROWN"), 165, 42, 42},
281 {wxT("CADET BLUE"), 95, 159, 159},
282 {wxT("CORAL"), 255, 127, 0},
283 {wxT("CORNFLOWER BLUE"), 66, 66, 111},
284 {wxT("CYAN"), 0, 255, 255},
285 {wxT("DARK GREY"), 47, 47, 47}, // ?
286
287 {wxT("DARK GREEN"), 47, 79, 47},
288 {wxT("DARK OLIVE GREEN"), 79, 79, 47},
289 {wxT("DARK ORCHID"), 153, 50, 204},
290 {wxT("DARK SLATE BLUE"), 107, 35, 142},
291 {wxT("DARK SLATE GREY"), 47, 79, 79},
292 {wxT("DARK TURQUOISE"), 112, 147, 219},
293 {wxT("DIM GREY"), 84, 84, 84},
294 {wxT("FIREBRICK"), 142, 35, 35},
295 {wxT("FOREST GREEN"), 35, 142, 35},
296 {wxT("GOLD"), 204, 127, 50},
297 {wxT("GOLDENROD"), 219, 219, 112},
298 {wxT("GREY"), 128, 128, 128},
299 {wxT("GREEN"), 0, 255, 0},
300 {wxT("GREEN YELLOW"), 147, 219, 112},
301 {wxT("INDIAN RED"), 79, 47, 47},
302 {wxT("KHAKI"), 159, 159, 95},
303 {wxT("LIGHT BLUE"), 191, 216, 216},
304 {wxT("LIGHT GREY"), 192, 192, 192},
305 {wxT("LIGHT STEEL BLUE"), 143, 143, 188},
306 {wxT("LIME GREEN"), 50, 204, 50},
307 {wxT("LIGHT MAGENTA"), 255, 0, 255},
308 {wxT("MAGENTA"), 255, 0, 255},
309 {wxT("MAROON"), 142, 35, 107},
310 {wxT("MEDIUM AQUAMARINE"), 50, 204, 153},
311 {wxT("MEDIUM GREY"), 100, 100, 100},
312 {wxT("MEDIUM BLUE"), 50, 50, 204},
313 {wxT("MEDIUM FOREST GREEN"), 107, 142, 35},
314 {wxT("MEDIUM GOLDENROD"), 234, 234, 173},
315 {wxT("MEDIUM ORCHID"), 147, 112, 219},
316 {wxT("MEDIUM SEA GREEN"), 66, 111, 66},
317 {wxT("MEDIUM SLATE BLUE"), 127, 0, 255},
318 {wxT("MEDIUM SPRING GREEN"), 127, 255, 0},
319 {wxT("MEDIUM TURQUOISE"), 112, 219, 219},
320 {wxT("MEDIUM VIOLET RED"), 219, 112, 147},
321 {wxT("MIDNIGHT BLUE"), 47, 47, 79},
322 {wxT("NAVY"), 35, 35, 142},
323 {wxT("ORANGE"), 204, 50, 50},
324 {wxT("ORANGE RED"), 255, 0, 127},
325 {wxT("ORCHID"), 219, 112, 219},
326 {wxT("PALE GREEN"), 143, 188, 143},
327 {wxT("PINK"), 188, 143, 234},
328 {wxT("PLUM"), 234, 173, 234},
329 {wxT("PURPLE"), 176, 0, 255},
330 {wxT("RED"), 255, 0, 0},
331 {wxT("SALMON"), 111, 66, 66},
332 {wxT("SEA GREEN"), 35, 142, 107},
333 {wxT("SIENNA"), 142, 107, 35},
334 {wxT("SKY BLUE"), 50, 153, 204},
335 {wxT("SLATE BLUE"), 0, 127, 255},
336 {wxT("SPRING GREEN"), 0, 255, 127},
337 {wxT("STEEL BLUE"), 35, 107, 142},
338 {wxT("TAN"), 219, 147, 112},
339 {wxT("THISTLE"), 216, 191, 216},
340 {wxT("TURQUOISE"), 173, 234, 234},
341 {wxT("VIOLET"), 79, 47, 79},
342 {wxT("VIOLET RED"), 204, 50, 153},
343 {wxT("WHEAT"), 216, 216, 191},
344 {wxT("WHITE"), 255, 255, 255},
345 {wxT("YELLOW"), 255, 255, 0},
346 {wxT("YELLOW GREEN"), 153, 204, 50}
347 };
348
349 size_t n;
350
351 for ( n = 0; n < WXSIZEOF(wxColourTable); n++ )
352 {
353 const wxColourDesc& cc = wxColourTable[n];
354 (*m_map)[cc.name] = new wxColour(cc.r, cc.g, cc.b);
355 }
356
357 #ifdef __WXPM__
358 m_palTable = new long[n];
359 for ( n = 0; n < WXSIZEOF(wxColourTable); n++ )
360 {
361 const wxColourDesc& cc = wxColourTable[n];
362 m_palTable[n] = OS2RGB(cc.r,cc.g,cc.b);
363 }
364 m_nSize = n;
365 #endif
366 }
367
368 // ----------------------------------------------------------------------------
369 // wxColourDatabase operations
370 // ----------------------------------------------------------------------------
371
372 void wxColourDatabase::AddColour(const wxString& name, const wxColour& colour)
373 {
374 Initialize();
375
376 // canonicalize the colour names before using them as keys: they should be
377 // in upper case
378 wxString colName = name;
379 colName.MakeUpper();
380
381 // ... and we also allow both grey/gray
382 wxString colNameAlt = colName;
383 if ( !colNameAlt.Replace(_T("GRAY"), _T("GREY")) )
384 {
385 // but in this case it is not necessary so avoid extra search below
386 colNameAlt.clear();
387 }
388
389 wxStringToColourHashMap::iterator it = m_map->find(colName);
390 if ( it == m_map->end() && !colNameAlt.empty() )
391 it = m_map->find(colNameAlt);
392 if ( it != m_map->end() )
393 {
394 *(it->second) = colour;
395 }
396 else // new colour
397 {
398 (*m_map)[colName] = new wxColour(colour);
399 }
400 }
401
402 wxColour wxColourDatabase::Find(const wxString& colour) const
403 {
404 wxColourDatabase * const self = wxConstCast(this, wxColourDatabase);
405 self->Initialize();
406
407 // make the comparaison case insensitive and also match both grey and gray
408 wxString colName = colour;
409 colName.MakeUpper();
410 wxString colNameAlt = colName;
411 if ( !colNameAlt.Replace(_T("GRAY"), _T("GREY")) )
412 colNameAlt.clear();
413
414 wxStringToColourHashMap::iterator it = m_map->find(colName);
415 if ( it == m_map->end() && !colNameAlt.empty() )
416 it = m_map->find(colNameAlt);
417 if ( it != m_map->end() )
418 return *(it->second);
419
420 // we did not find any result in existing colours:
421 // we won't use wxString -> wxColour conversion because the
422 // wxColour::Set(const wxString &) function which does that conversion
423 // internally uses this function (wxColourDatabase::Find) and we want
424 // to avoid infinite recursion !
425 return wxNullColour;
426 }
427
428 wxString wxColourDatabase::FindName(const wxColour& colour) const
429 {
430 wxColourDatabase * const self = wxConstCast(this, wxColourDatabase);
431 self->Initialize();
432
433 typedef wxStringToColourHashMap::iterator iterator;
434
435 for ( iterator it = m_map->begin(), en = m_map->end(); it != en; ++it )
436 {
437 if ( *(it->second) == colour )
438 return it->first;
439 }
440
441 return wxEmptyString;
442 }
443
444 // ----------------------------------------------------------------------------
445 // deprecated wxColourDatabase methods
446 // ----------------------------------------------------------------------------
447
448 #if WXWIN_COMPATIBILITY_2_6
449 wxColour *wxColourDatabase::FindColour(const wxString& name)
450 {
451 // This function is deprecated, use Find() instead.
452 // Formerly this function sometimes would return a deletable pointer and
453 // sometimes a non-deletable one (when returning a colour from the database).
454 // Trying to delete the latter anyway results in problems, so probably
455 // nobody ever freed the pointers. Currently it always returns a new
456 // instance, which means there will be memory leaks.
457 wxLogDebug(wxT("wxColourDataBase::FindColour():")
458 wxT(" Please use wxColourDataBase::Find() instead"));
459
460 // using a static variable here is not the most elegant solution but unless
461 // we want to make wxStringToColourHashMap public (i.e. move it to the
462 // header) so that we could have a member function returning
463 // wxStringToColourHashMap::iterator, there is really no good way to do it
464 // otherwise
465 //
466 // and knowing that this function is going to disappear in the next release
467 // anyhow I don't want to waste time on this
468
469 static wxColour s_col;
470
471 s_col = Find(name);
472 if ( !s_col.Ok() )
473 return NULL;
474
475 return new wxColour(s_col);
476 }
477 #endif // WXWIN_COMPATIBILITY_2_6
478
479 // ============================================================================
480 // stock objects
481 // ============================================================================
482
483 static wxStockGDI gs_wxStockGDI_instance;
484 wxStockGDI* wxStockGDI::ms_instance = &gs_wxStockGDI_instance;
485 wxObject* wxStockGDI::ms_stockObject[ITEMCOUNT];
486
487 wxStockGDI::wxStockGDI()
488 {
489 }
490
491 wxStockGDI::~wxStockGDI()
492 {
493 }
494
495 void wxStockGDI::DeleteAll()
496 {
497 for (unsigned i = 0; i < ITEMCOUNT; i++)
498 {
499 delete ms_stockObject[i];
500 ms_stockObject[i] = NULL;
501 }
502 }
503
504 const wxBrush* wxStockGDI::GetBrush(Item item)
505 {
506 wxBrush* brush = wx_static_cast(wxBrush*, ms_stockObject[item]);
507 if (brush == NULL)
508 {
509 switch (item)
510 {
511 case BRUSH_BLACK:
512 brush = new wxBrush(*GetColour(COLOUR_BLACK), wxSOLID);
513 break;
514 case BRUSH_BLUE:
515 brush = new wxBrush(*GetColour(COLOUR_BLUE), wxSOLID);
516 break;
517 case BRUSH_CYAN:
518 brush = new wxBrush(*GetColour(COLOUR_CYAN), wxSOLID);
519 break;
520 case BRUSH_GREEN:
521 brush = new wxBrush(*GetColour(COLOUR_GREEN), wxSOLID);
522 break;
523 case BRUSH_GREY:
524 brush = new wxBrush(wxColour(wxT("GREY")), wxSOLID);
525 break;
526 case BRUSH_LIGHTGREY:
527 brush = new wxBrush(*GetColour(COLOUR_LIGHTGREY), wxSOLID);
528 break;
529 case BRUSH_MEDIUMGREY:
530 brush = new wxBrush(wxColour(wxT("MEDIUM GREY")), wxSOLID);
531 break;
532 case BRUSH_RED:
533 brush = new wxBrush(*GetColour(COLOUR_RED), wxSOLID);
534 break;
535 case BRUSH_TRANSPARENT:
536 brush = new wxBrush(*GetColour(COLOUR_BLACK), wxTRANSPARENT);
537 break;
538 case BRUSH_WHITE:
539 brush = new wxBrush(*GetColour(COLOUR_WHITE), wxSOLID);
540 break;
541 default:
542 wxFAIL;
543 }
544 ms_stockObject[item] = brush;
545 }
546 return brush;
547 }
548
549 const wxColour* wxStockGDI::GetColour(Item item)
550 {
551 wxColour* colour = wx_static_cast(wxColour*, ms_stockObject[item]);
552 if (colour == NULL)
553 {
554 switch (item)
555 {
556 case COLOUR_BLACK:
557 colour = new wxColour(0, 0, 0);
558 break;
559 case COLOUR_BLUE:
560 colour = new wxColour(0, 0, 255);
561 break;
562 case COLOUR_CYAN:
563 colour = new wxColour(wxT("CYAN"));
564 break;
565 case COLOUR_GREEN:
566 colour = new wxColour(0, 255, 0);
567 break;
568 case COLOUR_LIGHTGREY:
569 colour = new wxColour(wxT("LIGHT GREY"));
570 break;
571 case COLOUR_RED:
572 colour = new wxColour(255, 0, 0);
573 break;
574 case COLOUR_WHITE:
575 colour = new wxColour(255, 255, 255);
576 break;
577 default:
578 wxFAIL;
579 }
580 ms_stockObject[item] = colour;
581 }
582 return colour;
583 }
584
585 const wxCursor* wxStockGDI::GetCursor(Item item)
586 {
587 wxCursor* cursor = wx_static_cast(wxCursor*, ms_stockObject[item]);
588 if (cursor == NULL)
589 {
590 switch (item)
591 {
592 case CURSOR_CROSS:
593 cursor = new wxCursor(wxCURSOR_CROSS);
594 break;
595 case CURSOR_HOURGLASS:
596 cursor = new wxCursor(wxCURSOR_WAIT);
597 break;
598 case CURSOR_STANDARD:
599 cursor = new wxCursor(wxCURSOR_ARROW);
600 break;
601 default:
602 wxFAIL;
603 }
604 ms_stockObject[item] = cursor;
605 }
606 return cursor;
607 }
608
609 const wxFont* wxStockGDI::GetFont(Item item)
610 {
611 wxFont* font = wx_static_cast(wxFont*, ms_stockObject[item]);
612 if (font == NULL)
613 {
614 switch (item)
615 {
616 case FONT_ITALIC:
617 font = new wxFont(GetFont(FONT_NORMAL)->GetPointSize(), wxROMAN, wxITALIC, wxNORMAL);
618 break;
619 case FONT_NORMAL:
620 font = new wxFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
621 break;
622 case FONT_SMALL:
623 font = new wxFont(GetFont(FONT_NORMAL)->GetPointSize() - 2, wxSWISS, wxNORMAL, wxNORMAL);
624 break;
625 case FONT_SWISS:
626 font = new wxFont(GetFont(FONT_NORMAL)->GetPointSize(), wxSWISS, wxNORMAL, wxNORMAL);
627 break;
628 default:
629 wxFAIL;
630 }
631 ms_stockObject[item] = font;
632 }
633 return font;
634 }
635
636 const wxPen* wxStockGDI::GetPen(Item item)
637 {
638 wxPen* pen = wx_static_cast(wxPen*, ms_stockObject[item]);
639 if (pen == NULL)
640 {
641 switch (item)
642 {
643 case PEN_BLACK:
644 pen = new wxPen(*GetColour(COLOUR_BLACK), 1, wxSOLID);
645 break;
646 case PEN_BLACKDASHED:
647 pen = new wxPen(*GetColour(COLOUR_BLACK), 1, wxSHORT_DASH);
648 break;
649 case PEN_CYAN:
650 pen = new wxPen(*GetColour(COLOUR_CYAN), 1, wxSOLID);
651 break;
652 case PEN_GREEN:
653 pen = new wxPen(*GetColour(COLOUR_GREEN), 1, wxSOLID);
654 break;
655 case PEN_GREY:
656 pen = new wxPen(wxColour(wxT("GREY")), 1, wxSOLID);
657 break;
658 case PEN_LIGHTGREY:
659 pen = new wxPen(*GetColour(COLOUR_LIGHTGREY), 1, wxSOLID);
660 break;
661 case PEN_MEDIUMGREY:
662 pen = new wxPen(wxColour(wxT("MEDIUM GREY")), 1, wxSOLID);
663 break;
664 case PEN_RED:
665 pen = new wxPen(*GetColour(COLOUR_RED), 1, wxSOLID);
666 break;
667 case PEN_TRANSPARENT:
668 pen = new wxPen(*GetColour(COLOUR_BLACK), 1, wxTRANSPARENT);
669 break;
670 case PEN_WHITE:
671 pen = new wxPen(*GetColour(COLOUR_WHITE), 1, wxSOLID);
672 break;
673 default:
674 wxFAIL;
675 }
676 ms_stockObject[item] = pen;
677 }
678 return pen;
679 }
680
681 void wxInitializeStockLists()
682 {
683 wxTheColourDatabase = new wxColourDatabase;
684
685 wxTheBrushList = new wxBrushList;
686 wxThePenList = new wxPenList;
687 wxTheFontList = new wxFontList;
688 }
689
690 void wxDeleteStockLists()
691 {
692 wxDELETE(wxTheBrushList);
693 wxDELETE(wxThePenList);
694 wxDELETE(wxTheFontList);
695 }
696
697 // ============================================================================
698 // wxTheXXXList stuff (semi-obsolete)
699 // ============================================================================
700
701 wxGDIObjListBase::wxGDIObjListBase()
702 {
703 }
704
705 wxGDIObjListBase::~wxGDIObjListBase()
706 {
707 for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext())
708 {
709 delete wx_static_cast(wxObject*, node->GetData());
710 }
711 }
712
713 wxPen *wxPenList::FindOrCreatePen (const wxColour& colour, int width, int style)
714 {
715 for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext())
716 {
717 wxPen *each_pen = (wxPen *) node->GetData ();
718 if (
719 each_pen->GetWidth () == width &&
720 each_pen->GetStyle () == style &&
721 each_pen->GetColour ().Red () == colour.Red () &&
722 each_pen->GetColour ().Green () == colour.Green () &&
723 each_pen->GetColour ().Blue () == colour.Blue ())
724 return each_pen;
725 }
726
727 wxPen* pen = NULL;
728 wxPen penTmp(colour, width, style);
729 if (penTmp.Ok())
730 {
731 pen = new wxPen(penTmp);
732 list.Append(pen);
733 }
734
735 return pen;
736 }
737
738 wxBrush *wxBrushList::FindOrCreateBrush (const wxColour& colour, int style)
739 {
740 for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext())
741 {
742 wxBrush *each_brush = (wxBrush *) node->GetData ();
743 if (
744 each_brush->GetStyle () == style &&
745 each_brush->GetColour ().Red () == colour.Red () &&
746 each_brush->GetColour ().Green () == colour.Green () &&
747 each_brush->GetColour ().Blue () == colour.Blue ())
748 return each_brush;
749 }
750
751 wxBrush* brush = NULL;
752 wxBrush brushTmp(colour, style);
753 if (brushTmp.Ok())
754 {
755 brush = new wxBrush(brushTmp);
756 list.Append(brush);
757 }
758
759 return brush;
760 }
761
762 wxFont *wxFontList::FindOrCreateFont(int pointSize,
763 int family,
764 int style,
765 int weight,
766 bool underline,
767 const wxString& facename,
768 wxFontEncoding encoding)
769 {
770 wxFont *font;
771 wxList::compatibility_iterator node;
772 for (node = list.GetFirst(); node; node = node->GetNext())
773 {
774 font = (wxFont *)node->GetData();
775 if (
776 font->GetPointSize () == pointSize &&
777 font->GetStyle () == style &&
778 font->GetWeight () == weight &&
779 font->GetUnderlined () == underline )
780 {
781 int fontFamily = font->GetFamily();
782
783 #if defined(__WXGTK__)
784 // under GTK the default family is wxSWISS, so looking for a font
785 // with wxDEFAULT family should return a wxSWISS one instead of
786 // creating a new one
787 bool same = (fontFamily == family) ||
788 (fontFamily == wxSWISS && family == wxDEFAULT);
789 #else // !GTK
790 // VZ: but why elsewhere do we require an exact match? mystery...
791 bool same = fontFamily == family;
792 #endif // GTK/!GTK
793
794 // empty facename matches anything at all: this is bad because
795 // depending on which fonts are already created, we might get back
796 // a different font if we create it with empty facename, but it is
797 // still better than never matching anything in the cache at all
798 // in this case
799 if ( same && !facename.empty() )
800 {
801 const wxString& fontFace = font->GetFaceName();
802
803 // empty facename matches everything
804 same = !fontFace || fontFace == facename;
805 }
806
807 if ( same && (encoding != wxFONTENCODING_DEFAULT) )
808 {
809 // have to match the encoding too
810 same = font->GetEncoding() == encoding;
811 }
812
813 if ( same )
814 {
815 return font;
816 }
817 }
818 }
819
820 // font not found, create the new one
821 font = NULL;
822 wxFont fontTmp(pointSize, family, style, weight, underline, facename, encoding);
823 if (fontTmp.Ok())
824 {
825 font = new wxFont(fontTmp);
826 list.Append(font);
827 }
828
829 return font;
830 }
831
832 #if WXWIN_COMPATIBILITY_2_6
833 void wxBrushList::AddBrush(wxBrush*) { }
834 void wxBrushList::RemoveBrush(wxBrush*) { }
835 void wxFontList::AddFont(wxFont*) { }
836 void wxFontList::RemoveFont(wxFont*) { }
837 void wxPenList::AddPen(wxPen*) { }
838 void wxPenList::RemovePen(wxPen*) { }
839 #endif
840
841 wxSize wxGetDisplaySize()
842 {
843 int x, y;
844 wxDisplaySize(& x, & y);
845 return wxSize(x, y);
846 }
847
848 wxRect wxGetClientDisplayRect()
849 {
850 int x, y, width, height;
851 wxClientDisplayRect(&x, &y, &width, &height); // call plat-specific version
852 return wxRect(x, y, width, height);
853 }
854
855 wxSize wxGetDisplaySizeMM()
856 {
857 int x, y;
858 wxDisplaySizeMM(& x, & y);
859 return wxSize(x, y);
860 }
861
862 wxResourceCache::~wxResourceCache ()
863 {
864 wxList::compatibility_iterator node = GetFirst ();
865 while (node) {
866 wxObject *item = (wxObject *)node->GetData();
867 delete item;
868
869 node = node->GetNext ();
870 }
871 }