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 
wxFontFaceBase()44 wxFontFaceBase::wxFontFaceBase()
45     : m_refCnt(0)
46 {
47     m_instances = new wxFontInstanceList;
48     m_instances->DeleteContents(true);
49 }
50 
~wxFontFaceBase()51 wxFontFaceBase::~wxFontFaceBase()
52 {
53     delete m_instances;
54 }
55 
Acquire()56 void wxFontFaceBase::Acquire()
57 {
58     m_refCnt++;
59 }
60 
Release()61 void wxFontFaceBase::Release()
62 {
63     if ( --m_refCnt == 0 )
64     {
65         m_instances->Clear();
66     }
67 }
68 
GetFontInstance(float ptSize,bool aa)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 
wxFontBundleBase()89 wxFontBundleBase::wxFontBundleBase()
90 {
91     for (int i = 0; i < FaceType_Max; i++)
92         m_faces[i] = NULL;
93 }
94 
~wxFontBundleBase()95 wxFontBundleBase::~wxFontBundleBase()
96 {
97     for (int i = 0; i < FaceType_Max; i++)
98         delete m_faces[i];
99 }
100 
GetFace(FaceType type) const101 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 *
GetFaceForFont(const wxFontMgrFontRefData & font) const113 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 
wxFontsManagerBase()156 wxFontsManagerBase::wxFontsManagerBase()
157 {
158     m_hash = new wxFontBundleHash();
159     m_list = new wxFontBundleList;
160     m_list->DeleteContents(true);
161 }
162 
~wxFontsManagerBase()163 wxFontsManagerBase::~wxFontsManagerBase()
164 {
165     delete m_hash;
166     delete m_list;
167 }
168 
169 /* static */
Get()170 wxFontsManager *wxFontsManagerBase::Get()
171 {
172     if ( !ms_instance )
173         ms_instance = new wxFontsManager();
174     return ms_instance;
175 }
176 
177 /* static */
CleanUp()178 void wxFontsManagerBase::CleanUp()
179 {
180     wxDELETE(ms_instance);
181 }
182 
GetBundle(const wxString & name) const183 wxFontBundle *wxFontsManagerBase::GetBundle(const wxString& name) const
184 {
185     return (*m_hash)[name.Lower()];
186 }
187 
188 wxFontBundle *
GetBundleForFont(const wxFontMgrFontRefData & font) const189 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 
AddBundle(wxFontBundle * bundle)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 
wxFontMgrFontRefData(int size,wxFontFamily family,wxFontStyle style,wxFontWeight weight,bool underlined,const wxString & faceName,wxFontEncoding encoding)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 
wxFontMgrFontRefData(const wxFontMgrFontRefData & data)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 
~wxFontMgrFontRefData()263 wxFontMgrFontRefData::~wxFontMgrFontRefData()
264 {
265     if ( m_fontFace )
266         m_fontFace->Release();
267 }
268 
GetFontBundle() const269 wxFontBundle *wxFontMgrFontRefData::GetFontBundle() const
270 {
271     wxConstCast(this, wxFontMgrFontRefData)->EnsureValidFont();
272     return m_fontBundle;
273 }
274 
275 wxFontInstance *
GetFontInstance(float scale,bool antialiased) const276 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 
SetPointSize(int pointSize)283 void wxFontMgrFontRefData::SetPointSize(int pointSize)
284 {
285     m_info.pointSize = pointSize;
286     m_fontValid = false;
287 }
288 
SetFamily(wxFontFamily family)289 void wxFontMgrFontRefData::SetFamily(wxFontFamily family)
290 {
291     m_info.family = family;
292     m_fontValid = false;
293 }
294 
SetStyle(wxFontStyle style)295 void wxFontMgrFontRefData::SetStyle(wxFontStyle style)
296 {
297     m_info.style = style;
298     m_fontValid = false;
299 }
300 
SetWeight(wxFontWeight weight)301 void wxFontMgrFontRefData::SetWeight(wxFontWeight weight)
302 {
303     m_info.weight = weight;
304     m_fontValid = false;
305 }
306 
SetFaceName(const wxString & faceName)307 void wxFontMgrFontRefData::SetFaceName(const wxString& faceName)
308 {
309     m_info.faceName = faceName;
310     m_fontValid = false;
311 }
312 
SetUnderlined(bool underlined)313 void wxFontMgrFontRefData::SetUnderlined(bool underlined)
314 {
315     m_info.underlined = underlined;
316     m_fontValid = false;
317 }
318 
SetEncoding(wxFontEncoding encoding)319 void wxFontMgrFontRefData::SetEncoding(wxFontEncoding encoding)
320 {
321     m_info.encoding = encoding;
322     m_fontValid = false;
323 }
324 
EnsureValidFont()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 }
338