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