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