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