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: fontmgrcmn.cpp 54757 2008-07-21 17:34:48Z VZ $ |
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() || font.GetFaceName() == GetName(), |
117 |
_T("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 MGL neither DFB supports slant, we try to display it with |
126 |
// italic 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 |
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 |
} |