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