log missing font directories with wxLogDebug, not wxLogTrace, for more visibility
[wxWidgets.git] / src / dfb / fontmgr.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/dfb/fontmgr.cpp
3 // Purpose: font management for wxDFB
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 #ifndef WX_PRECOMP
20 #include "wx/utils.h"
21 #include "wx/log.h"
22 #endif
23
24 #include "wx/fileconf.h"
25 #include "wx/filename.h"
26 #include "wx/tokenzr.h"
27 #include "wx/dir.h"
28
29 #include "wx/private/fontmgr.h"
30 #include "wx/dfb/wrapdfb.h"
31
32 // ============================================================================
33 // implementation
34 // ============================================================================
35
36 // ----------------------------------------------------------------------------
37 // wxFontInstance
38 // ----------------------------------------------------------------------------
39
40 wxFontInstance::wxFontInstance(float ptSize, bool aa,
41 const wxString& filename)
42 : wxFontInstanceBase(ptSize, aa)
43 {
44 int scrSizePx, scrSizeMM;
45 wxDisplaySize(NULL, &scrSizePx);
46 wxDisplaySizeMM(NULL, &scrSizeMM);
47 double dpi = (scrSizePx / (scrSizeMM * mm2inches));
48 // NB: DFB's fract_height value is 32bit integer with the last 6 bit
49 // representing fractional value, hence the multiplication by 64;
50 // 1pt=1/72inch, hence "/ 72"
51 int pixSize = int(ptSize * dpi * 64 / 72);
52
53 DFBFontDescription desc;
54 desc.flags = (DFBFontDescriptionFlags)(
55 DFDESC_ATTRIBUTES | DFDESC_FRACT_HEIGHT);
56 desc.attributes = aa ? DFFA_NONE : DFFA_MONOCHROME;
57 desc.fract_height = pixSize;
58 m_font = wxIDirectFB::Get()->CreateFont(filename.fn_str(), &desc);
59
60 wxASSERT_MSG( m_font, _T("cannot create font instance") );
61 }
62
63 // ----------------------------------------------------------------------------
64 // wxFontFace
65 // ----------------------------------------------------------------------------
66
67 wxFontInstance *wxFontFace::CreateFontInstance(float ptSize, bool aa)
68 {
69 return new wxFontInstance(ptSize, aa, m_fileName);
70 }
71
72 // ----------------------------------------------------------------------------
73 // wxFontBundle
74 // ----------------------------------------------------------------------------
75
76 wxFontBundle::wxFontBundle(const wxString& name,
77 const wxString& fileRegular,
78 const wxString& fileBold,
79 const wxString& fileItalic,
80 const wxString& fileBoldItalic,
81 bool isFixed)
82 {
83 m_name = name;
84 m_isFixed = isFixed;
85
86 if ( !fileRegular.empty() )
87 m_faces[FaceType_Regular] = new wxFontFace(fileRegular);
88 if ( !fileItalic.empty() )
89 m_faces[FaceType_Italic] = new wxFontFace(fileItalic);
90 if ( !fileBold.empty() )
91 m_faces[FaceType_Bold] = new wxFontFace(fileBold);
92 if ( !fileBoldItalic.empty() )
93 m_faces[FaceType_BoldItalic] = new wxFontFace(fileBoldItalic);
94 }
95
96 // ----------------------------------------------------------------------------
97 // wxFontsManager
98 // ----------------------------------------------------------------------------
99
100 /*
101 The code below looks up and parses font configuration files FontsIndex.
102 The files are looked up in directories specified in the WXDFB_FONTPATH
103 environment variable (separated with :, similarly to the PATH variable).
104 If the variable is not set, $prefix/share/wx/fonts directory is used.
105 All subdirectories of directories on the path are scanned for FontsIndex
106 files.
107
108 The FontsIndex file is standard wxFileConfig file text file. Each toplevel
109 group specifies one font bundle, font's name is the name of group. Group's
110 entries look like this:
111
112 [Font Name]
113 # font files (at least one of them must be present):
114 Regular=RegularFaceFile.ttf
115 Italic=ItalicFaceFile.ttf
116 Bold=BoldFaceFile.ttf
117 BoldItalic=BoldItalicFaceFile.ttf
118 # optional tag indicating this font is fixed-with (default is false):
119 IsFixed=1
120
121 Additionally, there may be DefaultXXX entries at the toplevel for every
122 family XXX and a Default entry that is shortcut for setting all families'
123 default, their value is name of the default font:
124
125 # optional tags indicating the default font for given family:
126 DefaultDecorative=Font Name
127 DefaultRoman=Font Name
128 DefaultScript=Font Name
129 DefaultSwiss=Font Name
130 DefaultModern=Font Name
131 DefaultTeletype=Font Name
132 # indicate the font that is default for all families (optional):
133 Default=Font Name
134 */
135
136 void wxFontsManager::AddAllFonts()
137 {
138 wxString path;
139 if ( !wxGetEnv(_T("WXDFB_FONTPATH"), &path) )
140 path = _T(wxINSTALL_PREFIX "/share/wx/fonts");
141
142 wxStringTokenizer tkn(path, wxPATH_SEP);
143 while ( tkn.HasMoreTokens() )
144 {
145 wxString dir = tkn.GetNextToken();
146
147 if ( !wxDir::Exists(dir) )
148 {
149 wxLogDebug(_T("font directory %s doesn't exist"), dir);
150 continue;
151 }
152
153 wxArrayString indexFiles;
154 if ( !wxDir::GetAllFiles(dir, &indexFiles, _T("FontsIndex")) )
155 continue;
156
157 for ( wxArrayString::const_iterator i = indexFiles.begin();
158 i != indexFiles.end(); ++i )
159 {
160 AddFontsFromDir(*i);
161 }
162 }
163
164 if ( GetBundles().empty() )
165 {
166 // wxDFB is unusable without fonts, so terminate the app
167 wxLogFatalError(_("No fonts found in %s."), path.c_str());
168 }
169 }
170
171 void wxFontsManager::AddFontsFromDir(const wxString& indexFile)
172 {
173 wxFileName fn(indexFile);
174 wxString dir = fn.GetPath();
175
176 if ( !fn.FileExists() )
177 {
178 wxLogWarning(_("Fonts index file %s disappeared while loading fonts."),
179 indexFile.c_str());
180 return;
181 }
182
183 wxLogTrace(_T("font"), _T("adding fonts from %s"), dir.c_str());
184
185 wxFileConfig cfg(wxEmptyString, wxEmptyString,
186 indexFile, wxEmptyString,
187 wxCONFIG_USE_LOCAL_FILE);
188
189 long i;
190 wxString name;
191 for ( bool cont = cfg.GetFirstGroup(name, i);
192 cont;
193 cont = cfg.GetNextGroup(name, i) )
194 {
195 AddFont(dir, name, cfg);
196 }
197
198 // set default fonts for families:
199 SetDefaultFonts(cfg);
200 }
201
202 static wxString
203 ReadFilePath(const wxString& name, const wxString& dir, wxFileConfig& cfg)
204 {
205 wxString p = cfg.Read(name, wxEmptyString);
206
207 if ( p.empty() || wxFileName(p).IsAbsolute() )
208 return p;
209
210 return dir + _T("/") + p;
211 }
212
213 void wxFontsManager::AddFont(const wxString& dir,
214 const wxString& name,
215 wxFileConfig& cfg)
216 {
217 wxLogTrace(_T("font"), _T("adding font '%s'"), name.c_str());
218
219 wxConfigPathChanger ch(&cfg, wxString::Format(_T("/%s/"), name.c_str()));
220
221 AddBundle
222 (
223 new wxFontBundle
224 (
225 name,
226 ReadFilePath(_T("Regular"), dir, cfg),
227 ReadFilePath(_T("Italic"), dir, cfg),
228 ReadFilePath(_T("Bold"), dir, cfg),
229 ReadFilePath(_T("BoldItalic"), dir, cfg),
230 cfg.Read(_T("IsFixed"), (long)false)
231 )
232 );
233 }
234
235 void wxFontsManager::SetDefaultFonts(wxFileConfig& cfg)
236 {
237 wxString name;
238
239 if ( cfg.Read(_T("Default"), &name) )
240 {
241 m_defaultFacenames[wxFONTFAMILY_DECORATIVE] =
242 m_defaultFacenames[wxFONTFAMILY_ROMAN] =
243 m_defaultFacenames[wxFONTFAMILY_SCRIPT] =
244 m_defaultFacenames[wxFONTFAMILY_SWISS] =
245 m_defaultFacenames[wxFONTFAMILY_MODERN] =
246 m_defaultFacenames[wxFONTFAMILY_TELETYPE] = name;
247 }
248
249 if ( cfg.Read(_T("DefaultDecorative"), &name) )
250 m_defaultFacenames[wxFONTFAMILY_DECORATIVE] = name;
251 if ( cfg.Read(_T("DefaultRoman"), &name) )
252 m_defaultFacenames[wxFONTFAMILY_ROMAN] = name;
253 if ( cfg.Read(_T("DefaultScript"), &name) )
254 m_defaultFacenames[wxFONTFAMILY_SCRIPT] = name;
255 if ( cfg.Read(_T("DefaultSwiss"), &name) )
256 m_defaultFacenames[wxFONTFAMILY_SWISS] = name;
257 if ( cfg.Read(_T("DefaultModern"), &name) )
258 m_defaultFacenames[wxFONTFAMILY_MODERN] = name;
259 if ( cfg.Read(_T("DefaultTeletype"), &name) )
260 m_defaultFacenames[wxFONTFAMILY_TELETYPE] = name;
261 }