| 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 = _T(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 | } |