]> git.saurik.com Git - wxWidgets.git/blob - src/common/fontmgrcmn.cpp
remove wxTextAttr::CreateFont(); return wxNullFont from GetFont() if we have no font...
[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
28 WX_DECLARE_HASH_MAP(wxString, wxFontBundle*,
29 wxStringHash, wxStringEqual,
30 wxFontBundleHashBase);
31 // in STL build, hash class is typedef to a template, so it can't be forward
32 // declared, as we do; solve it by having a dummy class:
33 class wxFontBundleHash : public wxFontBundleHashBase
34 {
35 };
36
37 // ============================================================================
38 // implementation
39 // ============================================================================
40
41 // ----------------------------------------------------------------------------
42 // wxFontFaceBase
43 // ----------------------------------------------------------------------------
44
45 wxFontFaceBase::wxFontFaceBase()
46 : m_refCnt(0)
47 {
48 m_instances = new wxFontInstanceList;
49 m_instances->DeleteContents(true);
50 }
51
52 wxFontFaceBase::~wxFontFaceBase()
53 {
54 delete m_instances;
55 }
56
57 void wxFontFaceBase::Acquire()
58 {
59 m_refCnt++;
60 }
61
62 void wxFontFaceBase::Release()
63 {
64 if ( --m_refCnt == 0 )
65 {
66 m_instances->Clear();
67 }
68 }
69
70 wxFontInstance *wxFontFaceBase::GetFontInstance(float ptSize, bool aa)
71 {
72 wxASSERT_MSG( m_refCnt > 0, _T("font library not loaded!") );
73
74 for ( wxFontInstanceList::const_iterator i = m_instances->begin();
75 i != m_instances->end(); ++i )
76 {
77 if ( (*i)->GetPointSize() == ptSize && (*i)->IsAntiAliased() == aa )
78 return *i;
79 }
80
81 wxFontInstance *i = CreateFontInstance(ptSize, aa);
82 m_instances->Append(i);
83 return i;
84 }
85
86 // ----------------------------------------------------------------------------
87 // wxFontBundleBase
88 // ----------------------------------------------------------------------------
89
90 wxFontBundleBase::wxFontBundleBase()
91 {
92 for (int i = 0; i < FaceType_Max; i++)
93 m_faces[i] = NULL;
94 }
95
96 wxFontBundleBase::~wxFontBundleBase()
97 {
98 for (int i = 0; i < FaceType_Max; i++)
99 delete m_faces[i];
100 }
101
102 wxFontFace *wxFontBundleBase::GetFace(FaceType type) const
103 {
104 wxFontFace *f = m_faces[type];
105
106 wxCHECK_MSG( f, NULL, _T("no such face in font bundle") );
107
108 f->Acquire();
109
110 return f;
111 }
112
113 wxFontFace *
114 wxFontBundleBase::GetFaceForFont(const wxFontMgrFontRefData& font) const
115 {
116 wxASSERT_MSG( font.GetFaceName().empty() ||
117 GetName().CmpNoCase(font.GetFaceName()) == 0,
118 _T("calling GetFaceForFont for incompatible font") );
119
120 int type = FaceType_Regular;
121
122 if ( font.GetWeight() == wxBOLD )
123 type |= FaceType_Bold;
124
125 // FIXME -- this should read "if ( font->GetStyle() == wxITALIC )",
126 // but since MGL neither DFB supports slant, we try to display it with
127 // italic face (better than nothing...)
128 if ( font.GetStyle() == wxITALIC || font.GetStyle() == wxSLANT )
129 {
130 if ( HasFace((FaceType)(type | FaceType_Italic)) )
131 type |= FaceType_Italic;
132 }
133
134 if ( !HasFace((FaceType)type) )
135 {
136 // if we can't get the exact font requested, substitute it with
137 // some other variant:
138 for (int i = 0; i < FaceType_Max; i++)
139 {
140 if ( HasFace((FaceType)i) )
141 return GetFace((FaceType)i);
142 }
143
144 wxFAIL_MSG( _T("no face") );
145 return NULL;
146 }
147
148 return GetFace((FaceType)type);
149 }
150
151 // ----------------------------------------------------------------------------
152 // wxFontsManagerBase
153 // ----------------------------------------------------------------------------
154
155 wxFontsManager *wxFontsManagerBase::ms_instance = NULL;
156
157 wxFontsManagerBase::wxFontsManagerBase()
158 {
159 m_hash = new wxFontBundleHash();
160 m_list = new wxFontBundleList;
161 m_list->DeleteContents(true);
162 }
163
164 wxFontsManagerBase::~wxFontsManagerBase()
165 {
166 delete m_hash;
167 delete m_list;
168 }
169
170 /* static */
171 wxFontsManager *wxFontsManagerBase::Get()
172 {
173 if ( !ms_instance )
174 ms_instance = new wxFontsManager();
175 return ms_instance;
176 }
177
178 /* static */
179 void wxFontsManagerBase::CleanUp()
180 {
181 wxDELETE(ms_instance);
182 }
183
184 wxFontBundle *wxFontsManagerBase::GetBundle(const wxString& name) const
185 {
186 return (*m_hash)[name.Lower()];
187 }
188
189 wxFontBundle *
190 wxFontsManagerBase::GetBundleForFont(const wxFontMgrFontRefData& font) const
191 {
192 wxFontBundle *bundle = NULL;
193
194 wxString facename = font.GetFaceName();
195 if ( !facename.empty() )
196 bundle = GetBundle(facename);
197
198 if ( !bundle )
199 {
200 facename = GetDefaultFacename((wxFontFamily)font.GetFamily());
201 if ( !facename.empty() )
202 bundle = GetBundle(facename);
203 }
204
205 if ( !bundle )
206 {
207 if ( m_list->GetFirst() )
208 bundle = m_list->GetFirst()->GetData();
209 else
210 wxFAIL_MSG(wxT("Fatal error, no fonts available!"));
211 }
212
213 return bundle;
214 }
215
216 void wxFontsManagerBase::AddBundle(wxFontBundle *bundle)
217 {
218 (*m_hash)[bundle->GetName().Lower()] = bundle;
219 m_list->Append(bundle);
220 }
221
222
223 // ----------------------------------------------------------------------------
224 // wxFontMgrFontRefData
225 // ----------------------------------------------------------------------------
226
227 wxFontMgrFontRefData::wxFontMgrFontRefData(int size,
228 int family,
229 int style,
230 int weight,
231 bool underlined,
232 const wxString& faceName,
233 wxFontEncoding encoding)
234 {
235 if ( family == wxDEFAULT )
236 family = wxSWISS;
237 if ( style == wxDEFAULT )
238 style = wxNORMAL;
239 if ( weight == wxDEFAULT )
240 weight = wxNORMAL;
241 if ( size == wxDEFAULT )
242 size = 12;
243
244 m_info.family = (wxFontFamily)family;
245 m_info.faceName = faceName;
246 m_info.style = (wxFontStyle)style;
247 m_info.weight = (wxFontWeight)weight;
248 m_info.pointSize = size;
249 m_info.underlined = underlined;
250 m_info.encoding = encoding;
251
252 m_noAA = false;
253
254 m_fontFace = NULL;
255 m_fontBundle = NULL;
256 m_fontValid = false;
257 }
258
259 wxFontMgrFontRefData::wxFontMgrFontRefData(const wxFontMgrFontRefData& data)
260 {
261 m_info = data.m_info;
262 m_noAA = data.m_noAA;
263
264 m_fontFace = data.m_fontFace;
265 m_fontBundle = data.m_fontBundle;
266 m_fontValid = data.m_fontValid;
267 if ( m_fontFace )
268 m_fontFace->Acquire();
269 }
270
271 wxFontMgrFontRefData::~wxFontMgrFontRefData()
272 {
273 if ( m_fontFace )
274 m_fontFace->Release();
275 }
276
277 wxFontBundle *wxFontMgrFontRefData::GetFontBundle() const
278 {
279 wxConstCast(this, wxFontMgrFontRefData)->EnsureValidFont();
280 return m_fontBundle;
281 }
282
283 wxFontInstance *
284 wxFontMgrFontRefData::GetFontInstance(float scale, bool antialiased) const
285 {
286 wxConstCast(this, wxFontMgrFontRefData)->EnsureValidFont();
287 return m_fontFace->GetFontInstance(m_info.pointSize * scale,
288 antialiased && !m_noAA);
289 }
290
291 void wxFontMgrFontRefData::SetPointSize(int pointSize)
292 {
293 m_info.pointSize = pointSize;
294 m_fontValid = false;
295 }
296
297 void wxFontMgrFontRefData::SetFamily(int family)
298 {
299 m_info.family = (wxFontFamily)family;
300 m_fontValid = false;
301 }
302
303 void wxFontMgrFontRefData::SetStyle(int style)
304 {
305 m_info.style = (wxFontStyle)style;
306 m_fontValid = false;
307 }
308
309 void wxFontMgrFontRefData::SetWeight(int weight)
310 {
311 m_info.weight = (wxFontWeight)weight;
312 m_fontValid = false;
313 }
314
315 void wxFontMgrFontRefData::SetFaceName(const wxString& faceName)
316 {
317 m_info.faceName = faceName;
318 m_fontValid = false;
319 }
320
321 void wxFontMgrFontRefData::SetUnderlined(bool underlined)
322 {
323 m_info.underlined = underlined;
324 m_fontValid = false;
325 }
326
327 void wxFontMgrFontRefData::SetEncoding(wxFontEncoding encoding)
328 {
329 m_info.encoding = encoding;
330 m_fontValid = false;
331 }
332
333 void wxFontMgrFontRefData::SetNoAntiAliasing(bool no)
334 {
335 m_noAA = no;
336 }
337
338
339 void wxFontMgrFontRefData::EnsureValidFont()
340 {
341 if ( !m_fontValid )
342 {
343 wxFontFace *old = m_fontFace;
344
345 m_fontBundle = wxFontsManager::Get()->GetBundleForFont(*this);
346 m_fontFace = m_fontBundle->GetFaceForFont(*this);
347
348 if ( old )
349 old->Release();
350 }
351 }