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