fixed too restrictive assert: fonts matching is case-insensitive
[wxWidgets.git] / src / common / fontmgrcmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/fontmgrcmn.cpp
3 // Purpose: font management for ports that don't have their own
4 // Author: Vaclav Slavik
5 // Created: 2006-11-18
6 // RCS-ID: $Id$
7 // Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
8 // (c) 2006 REA Elektronik GmbH
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #include "wx/private/fontmgr.h"
20
21 #include "wx/listimpl.cpp"
22 #include "wx/hashmap.h"
23
24 WX_DECLARE_LIST(wxFontInstance, wxFontInstanceList);
25 WX_DEFINE_LIST(wxFontInstanceList)
26 WX_DEFINE_LIST(wxFontBundleList)
27 WX_DECLARE_HASH_MAP(wxString, wxFontBundle*,
28 wxStringHash, wxStringEqual,
29 wxFontBundleHash);
30
31 // ============================================================================
32 // implementation
33 // ============================================================================
34
35 // ----------------------------------------------------------------------------
36 // wxFontFaceBase
37 // ----------------------------------------------------------------------------
38
39 wxFontFaceBase::wxFontFaceBase()
40 : m_refCnt(0)
41 {
42 m_instances = new wxFontInstanceList;
43 m_instances->DeleteContents(true);
44 }
45
46 wxFontFaceBase::~wxFontFaceBase()
47 {
48 delete m_instances;
49 }
50
51 void wxFontFaceBase::Acquire()
52 {
53 m_refCnt++;
54 }
55
56 void wxFontFaceBase::Release()
57 {
58 if ( --m_refCnt == 0 )
59 {
60 m_instances->Clear();
61 }
62 }
63
64 wxFontInstance *wxFontFaceBase::GetFontInstance(float ptSize, bool aa)
65 {
66 wxASSERT_MSG( m_refCnt > 0, _T("font library not loaded!") );
67
68 wxFontInstance *i;
69 wxFontInstanceList::Node *node;
70
71 for ( node = m_instances->GetFirst(); node; node = node->GetNext() )
72 {
73 i = node->GetData();
74 if ( i->GetPointSize() == ptSize && i->IsAntiAliased() == aa )
75 return i;
76 }
77
78 i = CreateFontInstance(ptSize, aa);
79 m_instances->Append(i);
80 return i;
81 }
82
83 // ----------------------------------------------------------------------------
84 // wxFontBundleBase
85 // ----------------------------------------------------------------------------
86
87 wxFontBundleBase::wxFontBundleBase()
88 {
89 for (int i = 0; i < FaceType_Max; i++)
90 m_faces[i] = NULL;
91 }
92
93 wxFontBundleBase::~wxFontBundleBase()
94 {
95 for (int i = 0; i < FaceType_Max; i++)
96 delete m_faces[i];
97 }
98
99 wxFontFace *wxFontBundleBase::GetFace(FaceType type) const
100 {
101 wxFontFace *f = m_faces[type];
102
103 wxCHECK_MSG( f, NULL, _T("no such face in font bundle") );
104
105 f->Acquire();
106
107 return f;
108 }
109
110 wxFontFace *
111 wxFontBundleBase::GetFaceForFont(const wxFontMgrFontRefData& font) const
112 {
113 wxASSERT_MSG( font.GetFaceName().empty() ||
114 GetName().CmpNoCase(font.GetFaceName()) == 0,
115 _T("calling GetFaceForFont for incompatible font") );
116
117 int type = FaceType_Regular;
118
119 if ( font.GetWeight() == wxBOLD )
120 type |= FaceType_Bold;
121
122 // FIXME -- this should read "if ( font->GetStyle() == wxITALIC )",
123 // but since MGL neither DFB supports slant, we try to display it with
124 // italic face (better than nothing...)
125 if ( font.GetStyle() == wxITALIC || font.GetStyle() == wxSLANT )
126 {
127 if ( HasFace((FaceType)(type | FaceType_Italic)) )
128 type |= FaceType_Italic;
129 }
130
131 if ( !HasFace((FaceType)type) )
132 {
133 for (int i = 0; i < FaceType_Max; i++)
134 {
135 if ( HasFace((FaceType)i) )
136 return GetFace((FaceType)i);
137 }
138
139 wxFAIL_MSG( _T("no face") );
140 return NULL;
141 }
142
143 return GetFace((FaceType)type);
144 }
145
146 // ----------------------------------------------------------------------------
147 // wxFontsManagerBase
148 // ----------------------------------------------------------------------------
149
150 wxFontsManager *wxFontsManagerBase::ms_instance = NULL;
151
152 wxFontsManagerBase::wxFontsManagerBase()
153 {
154 m_hash = new wxFontBundleHash();
155 m_list = new wxFontBundleList;
156 m_list->DeleteContents(true);
157 }
158
159 wxFontsManagerBase::~wxFontsManagerBase()
160 {
161 delete m_hash;
162 delete m_list;
163 }
164
165 /* static */
166 wxFontsManager *wxFontsManagerBase::Get()
167 {
168 if ( !ms_instance )
169 ms_instance = new wxFontsManager();
170 return ms_instance;
171 }
172
173 /* static */
174 void wxFontsManagerBase::CleanUp()
175 {
176 wxDELETE(ms_instance);
177 }
178
179 wxFontBundle *wxFontsManagerBase::GetBundle(const wxString& name) const
180 {
181 return (*m_hash)[name.Lower()];
182 }
183
184 wxFontBundle *
185 wxFontsManagerBase::GetBundleForFont(const wxFontMgrFontRefData& font) const
186 {
187 wxFontBundle *bundle = NULL;
188
189 wxString facename = font.GetFaceName();
190 if ( !facename.empty() )
191 bundle = GetBundle(facename);
192
193 if ( !bundle )
194 {
195 facename = GetDefaultFacename((wxFontFamily)font.GetFamily());
196 if ( !facename.empty() )
197 bundle = GetBundle(facename);
198 }
199
200 if ( !bundle )
201 {
202 if ( m_list->GetFirst() )
203 bundle = m_list->GetFirst()->GetData();
204 else
205 wxFAIL_MSG(wxT("Fatal error, no fonts available!"));
206 }
207
208 return bundle;
209 }
210
211 void wxFontsManagerBase::AddBundle(wxFontBundle *bundle)
212 {
213 (*m_hash)[bundle->GetName().Lower()] = bundle;
214 m_list->Append(bundle);
215 }
216
217
218 // ----------------------------------------------------------------------------
219 // wxFontMgrFontRefData
220 // ----------------------------------------------------------------------------
221
222 wxFontMgrFontRefData::wxFontMgrFontRefData(int size,
223 int family,
224 int style,
225 int weight,
226 bool underlined,
227 const wxString& faceName,
228 wxFontEncoding encoding)
229 {
230 if ( family == wxDEFAULT )
231 family = wxSWISS;
232 if ( style == wxDEFAULT )
233 style = wxNORMAL;
234 if ( weight == wxDEFAULT )
235 weight = wxNORMAL;
236 if ( size == wxDEFAULT )
237 size = 12;
238
239 m_info.family = (wxFontFamily)family;
240 m_info.faceName = faceName;
241 m_info.style = (wxFontStyle)style;
242 m_info.weight = (wxFontWeight)weight;
243 m_info.pointSize = size;
244 m_info.underlined = underlined;
245 m_info.encoding = encoding;
246
247 m_noAA = false;
248
249 m_fontFace = NULL;
250 m_fontBundle = NULL;
251 m_fontValid = false;
252 }
253
254 wxFontMgrFontRefData::wxFontMgrFontRefData(const wxFontMgrFontRefData& data)
255 {
256 m_info = data.m_info;
257 m_noAA = data.m_noAA;
258
259 m_fontFace = data.m_fontFace;
260 m_fontBundle = data.m_fontBundle;
261 m_fontValid = data.m_fontValid;
262 if ( m_fontFace )
263 m_fontFace->Acquire();
264 }
265
266 wxFontMgrFontRefData::~wxFontMgrFontRefData()
267 {
268 if ( m_fontFace )
269 m_fontFace->Release();
270 }
271
272 wxFontBundle *wxFontMgrFontRefData::GetFontBundle() const
273 {
274 wxConstCast(this, wxFontMgrFontRefData)->EnsureValidFont();
275 return m_fontBundle;
276 }
277
278 wxFontInstance *
279 wxFontMgrFontRefData::GetFontInstance(float scale, bool antialiased) const
280 {
281 wxConstCast(this, wxFontMgrFontRefData)->EnsureValidFont();
282 return m_fontFace->GetFontInstance(m_info.pointSize * scale,
283 antialiased && !m_noAA);
284 }
285
286 void wxFontMgrFontRefData::SetPointSize(int pointSize)
287 {
288 m_info.pointSize = pointSize;
289 m_fontValid = false;
290 }
291
292 void wxFontMgrFontRefData::SetFamily(int family)
293 {
294 m_info.family = (wxFontFamily)family;
295 m_fontValid = false;
296 }
297
298 void wxFontMgrFontRefData::SetStyle(int style)
299 {
300 m_info.style = (wxFontStyle)style;
301 m_fontValid = false;
302 }
303
304 void wxFontMgrFontRefData::SetWeight(int weight)
305 {
306 m_info.weight = (wxFontWeight)weight;
307 m_fontValid = false;
308 }
309
310 void wxFontMgrFontRefData::SetFaceName(const wxString& faceName)
311 {
312 m_info.faceName = faceName;
313 m_fontValid = false;
314 }
315
316 void wxFontMgrFontRefData::SetUnderlined(bool underlined)
317 {
318 m_info.underlined = underlined;
319 m_fontValid = false;
320 }
321
322 void wxFontMgrFontRefData::SetEncoding(wxFontEncoding encoding)
323 {
324 m_info.encoding = encoding;
325 m_fontValid = false;
326 }
327
328 void wxFontMgrFontRefData::SetNoAntiAliasing(bool no)
329 {
330 m_noAA = no;
331 }
332
333
334 void wxFontMgrFontRefData::EnsureValidFont()
335 {
336 if ( !m_fontValid )
337 {
338 wxFontFace *old = m_fontFace;
339
340 m_fontBundle = wxFontsManager::Get()->GetBundleForFont(*this);
341 m_fontFace = m_fontBundle->GetFaceForFont(*this);
342
343 if ( old )
344 old->Release();
345 }
346 }