]> git.saurik.com Git - wxWidgets.git/blame - src/common/fontmgrcmn.cpp
Workaround for #15404: wxRichTextCtrl: caret does not disappear when focus is lost...
[wxWidgets.git] / src / common / fontmgrcmn.cpp
CommitLineData
d7ae4a62
VS
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
d7ae4a62
VS
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
23WX_DECLARE_LIST(wxFontInstance, wxFontInstanceList);
24WX_DEFINE_LIST(wxFontInstanceList)
25WX_DEFINE_LIST(wxFontBundleList)
9580fdc3 26
d7ae4a62
VS
27WX_DECLARE_HASH_MAP(wxString, wxFontBundle*,
28 wxStringHash, wxStringEqual,
9580fdc3
VS
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:
32class wxFontBundleHash : public wxFontBundleHashBase
33{
34};
d7ae4a62
VS
35
36// ============================================================================
37// implementation
38// ============================================================================
39
40// ----------------------------------------------------------------------------
41// wxFontFaceBase
42// ----------------------------------------------------------------------------
43
44wxFontFaceBase::wxFontFaceBase()
45 : m_refCnt(0)
46{
47 m_instances = new wxFontInstanceList;
48 m_instances->DeleteContents(true);
49}
50
51wxFontFaceBase::~wxFontFaceBase()
52{
53 delete m_instances;
54}
55
56void wxFontFaceBase::Acquire()
57{
58 m_refCnt++;
59}
60
61void wxFontFaceBase::Release()
62{
63 if ( --m_refCnt == 0 )
64 {
65 m_instances->Clear();
66 }
67}
68
69wxFontInstance *wxFontFaceBase::GetFontInstance(float ptSize, bool aa)
70{
9a83f860 71 wxASSERT_MSG( m_refCnt > 0, wxT("font library not loaded!") );
d7ae4a62 72
9580fdc3
VS
73 for ( wxFontInstanceList::const_iterator i = m_instances->begin();
74 i != m_instances->end(); ++i )
d7ae4a62 75 {
9580fdc3
VS
76 if ( (*i)->GetPointSize() == ptSize && (*i)->IsAntiAliased() == aa )
77 return *i;
d7ae4a62
VS
78 }
79
9580fdc3 80 wxFontInstance *i = CreateFontInstance(ptSize, aa);
d7ae4a62
VS
81 m_instances->Append(i);
82 return i;
83}
84
85// ----------------------------------------------------------------------------
86// wxFontBundleBase
87// ----------------------------------------------------------------------------
88
89wxFontBundleBase::wxFontBundleBase()
90{
91 for (int i = 0; i < FaceType_Max; i++)
92 m_faces[i] = NULL;
93}
94
95wxFontBundleBase::~wxFontBundleBase()
96{
97 for (int i = 0; i < FaceType_Max; i++)
98 delete m_faces[i];
99}
100
101wxFontFace *wxFontBundleBase::GetFace(FaceType type) const
102{
103 wxFontFace *f = m_faces[type];
104
9a83f860 105 wxCHECK_MSG( f, NULL, wxT("no such face in font bundle") );
d7ae4a62
VS
106
107 f->Acquire();
108
109 return f;
110}
111
112wxFontFace *
113wxFontBundleBase::GetFaceForFont(const wxFontMgrFontRefData& font) const
114{
dff1625b
VS
115 wxASSERT_MSG( font.GetFaceName().empty() ||
116 GetName().CmpNoCase(font.GetFaceName()) == 0,
9a83f860 117 wxT("calling GetFaceForFont for incompatible font") );
d7ae4a62
VS
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 )",
0e1f8ea4
VZ
125 // but since DFB doesn't support slant, we try to display it with italic
126 // face (better than nothing...)
d7ae4a62
VS
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 {
209ce629
VS
135 // if we can't get the exact font requested, substitute it with
136 // some other variant:
d7ae4a62
VS
137 for (int i = 0; i < FaceType_Max; i++)
138 {
139 if ( HasFace((FaceType)i) )
140 return GetFace((FaceType)i);
141 }
142
9a83f860 143 wxFAIL_MSG( wxT("no face") );
d7ae4a62
VS
144 return NULL;
145 }
146
147 return GetFace((FaceType)type);
148}
149
150// ----------------------------------------------------------------------------
151// wxFontsManagerBase
152// ----------------------------------------------------------------------------
153
154wxFontsManager *wxFontsManagerBase::ms_instance = NULL;
155
156wxFontsManagerBase::wxFontsManagerBase()
157{
158 m_hash = new wxFontBundleHash();
159 m_list = new wxFontBundleList;
160 m_list->DeleteContents(true);
161}
162
163wxFontsManagerBase::~wxFontsManagerBase()
164{
165 delete m_hash;
166 delete m_list;
167}
168
169/* static */
170wxFontsManager *wxFontsManagerBase::Get()
171{
172 if ( !ms_instance )
173 ms_instance = new wxFontsManager();
174 return ms_instance;
175}
176
177/* static */
178void wxFontsManagerBase::CleanUp()
179{
180 wxDELETE(ms_instance);
181}
182
183wxFontBundle *wxFontsManagerBase::GetBundle(const wxString& name) const
184{
185 return (*m_hash)[name.Lower()];
186}
187
188wxFontBundle *
189wxFontsManagerBase::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
215void 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
226wxFontMgrFontRefData::wxFontMgrFontRefData(int size,
5a2c086a
VZ
227 wxFontFamily family,
228 wxFontStyle style,
229 wxFontWeight weight,
d7ae4a62
VS
230 bool underlined,
231 const wxString& faceName,
232 wxFontEncoding encoding)
233{
5a2c086a
VZ
234 if ( family == wxFONTFAMILY_DEFAULT )
235 family = wxFONTFAMILY_SWISS;
d7ae4a62
VS
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
d7ae4a62
VS
247 m_fontFace = NULL;
248 m_fontBundle = NULL;
249 m_fontValid = false;
250}
251
252wxFontMgrFontRefData::wxFontMgrFontRefData(const wxFontMgrFontRefData& data)
253{
254 m_info = data.m_info;
d7ae4a62
VS
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
263wxFontMgrFontRefData::~wxFontMgrFontRefData()
264{
265 if ( m_fontFace )
266 m_fontFace->Release();
267}
268
269wxFontBundle *wxFontMgrFontRefData::GetFontBundle() const
270{
271 wxConstCast(this, wxFontMgrFontRefData)->EnsureValidFont();
272 return m_fontBundle;
273}
274
275wxFontInstance *
276wxFontMgrFontRefData::GetFontInstance(float scale, bool antialiased) const
277{
278 wxConstCast(this, wxFontMgrFontRefData)->EnsureValidFont();
279 return m_fontFace->GetFontInstance(m_info.pointSize * scale,
8462a84b 280 antialiased);
d7ae4a62
VS
281}
282
283void wxFontMgrFontRefData::SetPointSize(int pointSize)
284{
285 m_info.pointSize = pointSize;
286 m_fontValid = false;
287}
288
5a2c086a 289void wxFontMgrFontRefData::SetFamily(wxFontFamily family)
d7ae4a62 290{
5a2c086a 291 m_info.family = family;
d7ae4a62
VS
292 m_fontValid = false;
293}
294
5a2c086a 295void wxFontMgrFontRefData::SetStyle(wxFontStyle style)
d7ae4a62 296{
5a2c086a 297 m_info.style = style;
d7ae4a62
VS
298 m_fontValid = false;
299}
300
5a2c086a 301void wxFontMgrFontRefData::SetWeight(wxFontWeight weight)
d7ae4a62 302{
5a2c086a 303 m_info.weight = weight;
d7ae4a62
VS
304 m_fontValid = false;
305}
306
307void wxFontMgrFontRefData::SetFaceName(const wxString& faceName)
308{
309 m_info.faceName = faceName;
310 m_fontValid = false;
311}
312
313void wxFontMgrFontRefData::SetUnderlined(bool underlined)
314{
315 m_info.underlined = underlined;
316 m_fontValid = false;
317}
318
319void wxFontMgrFontRefData::SetEncoding(wxFontEncoding encoding)
320{
321 m_info.encoding = encoding;
322 m_fontValid = false;
323}
324
d7ae4a62
VS
325void 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}