added explanatory comment
[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 // if we can't get the exact font requested, substitute it with
134 // some other variant:
135 for (int i = 0; i < FaceType_Max; i++)
136 {
137 if ( HasFace((FaceType)i) )
138 return GetFace((FaceType)i);
139 }
140
141 wxFAIL_MSG( _T("no face") );
142 return NULL;
143 }
144
145 return GetFace((FaceType)type);
146 }
147
148 // ----------------------------------------------------------------------------
149 // wxFontsManagerBase
150 // ----------------------------------------------------------------------------
151
152 wxFontsManager *wxFontsManagerBase::ms_instance = NULL;
153
154 wxFontsManagerBase::wxFontsManagerBase()
155 {
156 m_hash = new wxFontBundleHash();
157 m_list = new wxFontBundleList;
158 m_list->DeleteContents(true);
159 }
160
161 wxFontsManagerBase::~wxFontsManagerBase()
162 {
163 delete m_hash;
164 delete m_list;
165 }
166
167 /* static */
168 wxFontsManager *wxFontsManagerBase::Get()
169 {
170 if ( !ms_instance )
171 ms_instance = new wxFontsManager();
172 return ms_instance;
173 }
174
175 /* static */
176 void wxFontsManagerBase::CleanUp()
177 {
178 wxDELETE(ms_instance);
179 }
180
181 wxFontBundle *wxFontsManagerBase::GetBundle(const wxString& name) const
182 {
183 return (*m_hash)[name.Lower()];
184 }
185
186 wxFontBundle *
187 wxFontsManagerBase::GetBundleForFont(const wxFontMgrFontRefData& font) const
188 {
189 wxFontBundle *bundle = NULL;
190
191 wxString facename = font.GetFaceName();
192 if ( !facename.empty() )
193 bundle = GetBundle(facename);
194
195 if ( !bundle )
196 {
197 facename = GetDefaultFacename((wxFontFamily)font.GetFamily());
198 if ( !facename.empty() )
199 bundle = GetBundle(facename);
200 }
201
202 if ( !bundle )
203 {
204 if ( m_list->GetFirst() )
205 bundle = m_list->GetFirst()->GetData();
206 else
207 wxFAIL_MSG(wxT("Fatal error, no fonts available!"));
208 }
209
210 return bundle;
211 }
212
213 void wxFontsManagerBase::AddBundle(wxFontBundle *bundle)
214 {
215 (*m_hash)[bundle->GetName().Lower()] = bundle;
216 m_list->Append(bundle);
217 }
218
219
220 // ----------------------------------------------------------------------------
221 // wxFontMgrFontRefData
222 // ----------------------------------------------------------------------------
223
224 wxFontMgrFontRefData::wxFontMgrFontRefData(int size,
225 int family,
226 int style,
227 int weight,
228 bool underlined,
229 const wxString& faceName,
230 wxFontEncoding encoding)
231 {
232 if ( family == wxDEFAULT )
233 family = wxSWISS;
234 if ( style == wxDEFAULT )
235 style = wxNORMAL;
236 if ( weight == wxDEFAULT )
237 weight = wxNORMAL;
238 if ( size == wxDEFAULT )
239 size = 12;
240
241 m_info.family = (wxFontFamily)family;
242 m_info.faceName = faceName;
243 m_info.style = (wxFontStyle)style;
244 m_info.weight = (wxFontWeight)weight;
245 m_info.pointSize = size;
246 m_info.underlined = underlined;
247 m_info.encoding = encoding;
248
249 m_noAA = false;
250
251 m_fontFace = NULL;
252 m_fontBundle = NULL;
253 m_fontValid = false;
254 }
255
256 wxFontMgrFontRefData::wxFontMgrFontRefData(const wxFontMgrFontRefData& data)
257 {
258 m_info = data.m_info;
259 m_noAA = data.m_noAA;
260
261 m_fontFace = data.m_fontFace;
262 m_fontBundle = data.m_fontBundle;
263 m_fontValid = data.m_fontValid;
264 if ( m_fontFace )
265 m_fontFace->Acquire();
266 }
267
268 wxFontMgrFontRefData::~wxFontMgrFontRefData()
269 {
270 if ( m_fontFace )
271 m_fontFace->Release();
272 }
273
274 wxFontBundle *wxFontMgrFontRefData::GetFontBundle() const
275 {
276 wxConstCast(this, wxFontMgrFontRefData)->EnsureValidFont();
277 return m_fontBundle;
278 }
279
280 wxFontInstance *
281 wxFontMgrFontRefData::GetFontInstance(float scale, bool antialiased) const
282 {
283 wxConstCast(this, wxFontMgrFontRefData)->EnsureValidFont();
284 return m_fontFace->GetFontInstance(m_info.pointSize * scale,
285 antialiased && !m_noAA);
286 }
287
288 void wxFontMgrFontRefData::SetPointSize(int pointSize)
289 {
290 m_info.pointSize = pointSize;
291 m_fontValid = false;
292 }
293
294 void wxFontMgrFontRefData::SetFamily(int family)
295 {
296 m_info.family = (wxFontFamily)family;
297 m_fontValid = false;
298 }
299
300 void wxFontMgrFontRefData::SetStyle(int style)
301 {
302 m_info.style = (wxFontStyle)style;
303 m_fontValid = false;
304 }
305
306 void wxFontMgrFontRefData::SetWeight(int weight)
307 {
308 m_info.weight = (wxFontWeight)weight;
309 m_fontValid = false;
310 }
311
312 void wxFontMgrFontRefData::SetFaceName(const wxString& faceName)
313 {
314 m_info.faceName = faceName;
315 m_fontValid = false;
316 }
317
318 void wxFontMgrFontRefData::SetUnderlined(bool underlined)
319 {
320 m_info.underlined = underlined;
321 m_fontValid = false;
322 }
323
324 void wxFontMgrFontRefData::SetEncoding(wxFontEncoding encoding)
325 {
326 m_info.encoding = encoding;
327 m_fontValid = false;
328 }
329
330 void wxFontMgrFontRefData::SetNoAntiAliasing(bool no)
331 {
332 m_noAA = no;
333 }
334
335
336 void wxFontMgrFontRefData::EnsureValidFont()
337 {
338 if ( !m_fontValid )
339 {
340 wxFontFace *old = m_fontFace;
341
342 m_fontBundle = wxFontsManager::Get()->GetBundleForFont(*this);
343 m_fontFace = m_fontBundle->GetFaceForFont(*this);
344
345 if ( old )
346 old->Release();
347 }
348 }