]> git.saurik.com Git - wxWidgets.git/blob - src/mgl/fontutil.cpp
don't declare strptime() ourselves if the system already does it, we might have a...
[wxWidgets.git] / src / mgl / fontutil.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mgl/fontutil.cpp
3 // Purpose: Font helper functions for MGL
4 // Author: Vaclav Slavik
5 // Created: 2001/04/29
6 // RCS-ID: $Id$
7 // Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
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/log.h"
19 #include "wx/fontutil.h"
20 #include "wx/encinfo.h"
21 #include "wx/fontmap.h"
22 #include "wx/tokenzr.h"
23 #include "wx/hash.h"
24
25 #include "wx/listimpl.cpp"
26 #include "wx/sysopt.h"
27 #include "wx/mgl/private.h"
28
29 #include <mgraph.h>
30
31 // ============================================================================
32 // implementation
33 // ============================================================================
34
35 // ----------------------------------------------------------------------------
36 // wxNativeEncodingInfo
37 // ----------------------------------------------------------------------------
38
39 // convert to/from the string representation: format is
40 // encoding[;facename]
41 bool wxNativeEncodingInfo::FromString(const wxString& s)
42 {
43 wxStringTokenizer tokenizer(s, _T(";"));
44
45 wxString encid = tokenizer.GetNextToken();
46 long enc;
47 if ( !encid.ToLong(&enc) )
48 return FALSE;
49 encoding = (wxFontEncoding)enc;
50
51 // ok even if empty
52 facename = tokenizer.GetNextToken();
53
54 return TRUE;
55 }
56
57 wxString wxNativeEncodingInfo::ToString() const
58 {
59 wxString s;
60 s << (long)encoding;
61 if ( !!facename )
62 {
63 s << _T(';') << facename;
64 }
65
66 return s;
67 }
68
69 // ----------------------------------------------------------------------------
70 // common functions
71 // ----------------------------------------------------------------------------
72
73 bool wxGetNativeFontEncoding(wxFontEncoding encoding,
74 wxNativeEncodingInfo *info)
75 {
76 wxCHECK_MSG( info, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
77
78 if ( encoding == wxFONTENCODING_DEFAULT )
79 {
80 encoding = wxFont::GetDefaultEncoding();
81 }
82
83 switch ( encoding )
84 {
85 case wxFONTENCODING_ISO8859_1:
86 case wxFONTENCODING_ISO8859_2:
87 case wxFONTENCODING_ISO8859_3:
88 case wxFONTENCODING_ISO8859_4:
89 case wxFONTENCODING_ISO8859_5:
90 case wxFONTENCODING_ISO8859_6:
91 case wxFONTENCODING_ISO8859_7:
92 case wxFONTENCODING_ISO8859_8:
93 case wxFONTENCODING_ISO8859_9:
94 case wxFONTENCODING_ISO8859_10:
95 case wxFONTENCODING_ISO8859_11:
96 case wxFONTENCODING_ISO8859_13:
97 case wxFONTENCODING_ISO8859_14:
98 case wxFONTENCODING_ISO8859_15:
99 info->mglEncoding = MGL_ENCODING_ISO8859_1 +
100 (encoding - wxFONTENCODING_ISO8859_1);
101 break;
102
103 case wxFONTENCODING_KOI8:
104 info->mglEncoding = MGL_ENCODING_KOI8;
105 break;
106
107 case wxFONTENCODING_CP1250:
108 case wxFONTENCODING_CP1251:
109 case wxFONTENCODING_CP1252:
110 case wxFONTENCODING_CP1253:
111 case wxFONTENCODING_CP1254:
112 case wxFONTENCODING_CP1255:
113 case wxFONTENCODING_CP1256:
114 case wxFONTENCODING_CP1257:
115 info->mglEncoding = MGL_ENCODING_CP1250 +
116 (encoding - wxFONTENCODING_CP1250);
117 break;
118
119 case wxFONTENCODING_SYSTEM:
120 info->mglEncoding = MGL_ENCODING_ASCII;
121 break;
122
123 default:
124 // encoding not known to MGL
125 return FALSE;
126 }
127
128 info->encoding = encoding;
129
130 return TRUE;
131 }
132
133 bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
134 {
135 if ( !info.facename )
136 return TRUE;
137
138 wxMGLFontFamily *family = wxTheFontsManager->GetFamily(info.facename);
139 if ( !family )
140 return FALSE;
141 if ( family->GetInfo()->fontLibType == MGL_BITMAPFONT_LIB )
142 return (info.mglEncoding == MGL_ENCODING_ASCII ||
143 info.mglEncoding == MGL_ENCODING_ISO8859_1 ||
144 info.mglEncoding == MGL_ENCODING_ISO8859_15 ||
145 info.mglEncoding == MGL_ENCODING_CP1252);
146 else
147 return TRUE;
148 }
149
150
151 // ----------------------------------------------------------------------------
152 // wxFontFamily, wxMGLFontInstance, wxMGLFontLibrary
153 // ----------------------------------------------------------------------------
154
155 WX_DECLARE_LIST(wxMGLFontInstance, wxMGLFontInstanceList);
156 WX_DEFINE_LIST(wxMGLFontInstanceList);
157 WX_DEFINE_LIST(wxMGLFontFamilyList);
158
159 wxMGLFontInstance::wxMGLFontInstance(wxMGLFontLibrary *fontLib,
160 float pt, bool slant, bool aa)
161 {
162 m_fontLib = fontLib;
163 m_font = NULL;
164 m_pt = pt;
165 m_slant = slant;
166 m_aa = aa;
167
168 float slantAngle = m_slant ? 15.0 : 0.0;
169
170 wxLogTrace("mgl_font", "loading instance of '%s' slant=%i pt=%0.1f aa=%i",
171 m_fontLib->GetMGLfont_lib_t()->name, m_slant, m_pt, m_aa);
172 m_font = MGL_loadFontInstance(m_fontLib->GetMGLfont_lib_t(),
173 m_pt, slantAngle, 0.0, aa);
174 wxASSERT_MSG( m_font, wxT("Cannot create font instance.") );
175 }
176
177 wxMGLFontInstance::~wxMGLFontInstance()
178 {
179 wxLogTrace("mgl_font", "unloading instance of '%s' slant=%i pt=%0.1f aa=%i",
180 m_fontLib->GetMGLfont_lib_t()->name, m_slant, m_pt, m_aa);
181 if ( m_font )
182 MGL_unloadFontInstance(m_font);
183 }
184
185 wxMGLFontLibrary::wxMGLFontLibrary(const wxString& filename, int type,
186 wxMGLFontFamily *parentFamily)
187 {
188 m_family = parentFamily;
189 m_type = type;
190 m_fileName = filename;
191 m_refs = 0;
192 m_fontLib = NULL;
193
194 m_instances = new wxMGLFontInstanceList;
195 m_instances->DeleteContents(TRUE);
196 }
197
198 wxMGLFontLibrary::~wxMGLFontLibrary()
199 {
200 wxLogTrace("mgl_font", "font library dtor '%s'", m_fileName.mb_str());
201 delete m_instances;
202 }
203
204 void wxMGLFontLibrary::IncRef()
205 {
206 wxLogTrace("mgl_font", "incRef(%u) '%s'", m_refs, m_fileName.c_str());
207 if ( m_refs++ == 0 )
208 {
209 wxLogTrace("mgl_font", "opening library '%s'", m_fileName.mb_str());
210 m_fontLib = MGL_openFontLib(m_fileName.mb_str());
211 }
212 }
213
214 void wxMGLFontLibrary::DecRef()
215 {
216 wxLogTrace("mgl_font", "decRef(%u) '%s'", m_refs, m_fileName.c_str());
217 if ( --m_refs == 0 )
218 {
219 wxLogTrace("mgl_font", "killing instances of '%s'", m_fileName.mb_str());
220 m_instances->Clear();
221 wxLogTrace("mgl_font", "closing library '%s'", m_fileName.mb_str());
222 MGL_closeFontLib(m_fontLib);
223 m_fontLib = NULL;
224 }
225 }
226
227 static int gs_antialiasingThreshold = -1;
228
229 wxMGLFontInstance *wxMGLFontLibrary::GetFontInstance(wxFont *font,
230 float scale, bool aa)
231 {
232 wxASSERT_MSG(m_refs > 0 && m_fontLib, wxT("font library not loaded!"));
233
234 wxString facename;
235 bool slant;
236 bool antialiased;
237 float pt = (float)font->GetPointSize() * scale;
238
239 if ( gs_antialiasingThreshold == -1 )
240 {
241 gs_antialiasingThreshold = 10;
242 #if wxUSE_SYSTEM_OPTIONS
243 if ( wxSystemOptions::HasOption(wxT("mgl.aa-threshold")) )
244 gs_antialiasingThreshold =
245 wxSystemOptions::GetOptionInt(wxT("mgl.aa-threshold"));
246 wxLogTrace("mgl_font", "AA threshold set to %i", gs_antialiasingThreshold);
247 #endif
248 }
249
250 // Small characters don't look good when antialiased with the algorithm
251 // that FreeType uses (mere 2x2 supersampling), so lets disable it AA
252 // completely for small fonts.
253 if ( pt <= gs_antialiasingThreshold )
254 antialiased = FALSE;
255 else
256 antialiased = (m_fontLib->fontLibType == MGL_BITMAPFONT_LIB) ? FALSE : aa;
257
258 slant = (((m_type & wxFONTFACE_ITALIC) == 0) &&
259 (font->GetStyle() == wxSLANT || font->GetStyle() == wxITALIC));
260
261 // FIXME_MGL -- MGL does not yet support slant, although the API is there
262 slant = FALSE;
263
264 wxLogTrace("mgl_font", "requested instance of '%s' slant=%i pt=%0.1f aa=%i",
265 m_fileName.mb_str(), slant, pt, antialiased);
266
267 wxMGLFontInstance *i;
268 wxMGLFontInstanceList::Node *node;
269
270 for (node = m_instances->GetFirst(); node; node = node->GetNext())
271 {
272 i = node->GetData();
273 if ( i->GetPt() == pt && i->GetSlant() == slant &&
274 i->GetAA() == antialiased )
275 {
276 wxLogTrace("mgl_font", " got from cache: slant=%i pt=%0.1f aa=%i",
277 i->GetSlant(), i->GetPt(), i->GetAA());
278 return i;
279 }
280 }
281
282 i = new wxMGLFontInstance(this, pt, slant, antialiased);
283 m_instances->Append(i);
284 return i;
285 }
286
287
288 wxMGLFontFamily::wxMGLFontFamily(const font_info_t *info)
289 {
290 m_name = info->familyName;
291 m_fontInfo = info;
292
293 if ( info->regularFace[0] == '\0' )
294 m_fontLibs[wxFONTFACE_REGULAR] = NULL;
295 else
296 m_fontLibs[wxFONTFACE_REGULAR] =
297 new wxMGLFontLibrary(info->regularFace, wxFONTFACE_REGULAR, this);
298
299 if ( info->italicFace[0] == '\0' )
300 m_fontLibs[wxFONTFACE_ITALIC] = NULL;
301 else
302 m_fontLibs[wxFONTFACE_ITALIC] =
303 new wxMGLFontLibrary(info->italicFace, wxFONTFACE_ITALIC, this);
304
305 if ( info->boldFace[0] == '\0' )
306 m_fontLibs[wxFONTFACE_BOLD] = NULL;
307 else
308 m_fontLibs[wxFONTFACE_BOLD] =
309 new wxMGLFontLibrary(info->boldFace, wxFONTFACE_BOLD, this);
310
311 if ( info->boldItalicFace[0] == '\0' )
312 m_fontLibs[wxFONTFACE_BOLD_ITALIC] = NULL;
313 else
314 m_fontLibs[wxFONTFACE_BOLD_ITALIC] =
315 new wxMGLFontLibrary(info->boldItalicFace, wxFONTFACE_BOLD_ITALIC, this);
316
317 wxLogTrace("mgl_font", "new family '%s' (r=%s, i=%s, b=%s, bi=%s)\n",
318 info->familyName, info->regularFace, info->italicFace,
319 info->boldFace, info->boldItalicFace);
320 }
321
322 wxMGLFontFamily::~wxMGLFontFamily()
323 {
324 for (size_t i = 0; i < wxFONTFACE_MAX; i++)
325 delete m_fontLibs[i];
326 }
327
328 bool wxMGLFontFamily::HasFace(int type) const
329 {
330 return (m_fontLibs[type] != NULL);
331 }
332
333
334 // ----------------------------------------------------------------------------
335 // wxFontsManager
336 // ----------------------------------------------------------------------------
337
338 wxMGLFontLibrary *wxFontsManager::GetFontLibrary(wxFont *font)
339 {
340 wxMGLFontFamily *family;
341 int type;
342 wxString facename = font->GetFaceName();
343
344 if ( !facename.IsEmpty() )
345 family = GetFamily(facename);
346 else
347 family = NULL;
348
349 if ( !family )
350 {
351 facename.Empty();
352 switch (font->GetFamily())
353 {
354 case wxSCRIPT:
355 facename = wxT("Script");
356 break;
357 case wxDECORATIVE:
358 facename = wxT("Charter");
359 break;
360 case wxROMAN:
361 facename = wxT("Times");
362 break;
363 case wxTELETYPE:
364 case wxMODERN:
365 facename = wxT("Courier");
366 break;
367 case wxSWISS:
368 facename = wxT("Helvetica");
369 break;
370 case wxDEFAULT:
371 default:
372 facename = wxT("Helvetica");
373 break;
374 }
375
376 family = GetFamily(facename);
377 if ( !family )
378 {
379 if ( m_list->GetFirst() )
380 family = m_list->GetFirst()->GetData();
381 else
382 wxFAIL_MSG(wxT("Fatal error, no fonts available!"));
383 }
384 }
385
386 type = wxFONTFACE_REGULAR;
387
388 if ( font->GetWeight() == wxBOLD )
389 type |= wxFONTFACE_BOLD;
390
391 // FIXME_MGL -- this should read "if ( font->GetStyle() == wxITALIC )",
392 // but since MGL does not yet support slant, we try to display it with
393 // italic face (better than nothing...)
394 if ( font->GetStyle() == wxITALIC || font->GetStyle() == wxSLANT )
395 {
396 if ( family->HasFace(type | wxFONTFACE_ITALIC) )
397 type |= wxFONTFACE_ITALIC;
398 }
399 if ( !family->HasFace(type) )
400 {
401 for (int i = 0; i < wxFONTFACE_MAX; i++)
402 if ( family->HasFace(i) )
403 {
404 type = i;
405 break;
406 }
407 }
408
409 return family->GetLibrary(type);
410 }
411
412 static ibool MGLAPI enum_callback(const font_info_t *info, void *cookie)
413 {
414 wxFontsManager *db = (wxFontsManager*)cookie;
415 db->AddFamily(info);
416 return TRUE;
417 }
418
419 wxFontsManager::wxFontsManager()
420 {
421 m_hash = new wxHashTable(wxKEY_STRING);
422 m_hash->DeleteContents(FALSE);
423 m_list = new wxMGLFontFamilyList;
424 m_list->DeleteContents(TRUE);
425 MGL_enumerateFonts(enum_callback, (void*)this);
426 }
427
428 wxFontsManager::~wxFontsManager()
429 {
430 delete m_hash;
431 delete m_list;
432 }
433
434 void wxFontsManager::AddFamily(const font_info_t *info)
435 {
436 wxMGLFontFamily *f = new wxMGLFontFamily(info);
437 m_hash->Put(f->GetName().Lower(), f);
438 m_list->Append(f);
439 }
440
441 wxMGLFontFamily *wxFontsManager::GetFamily(const wxString& name) const
442 {
443 return (wxMGLFontFamily*)m_hash->Get(name.Lower());
444 }
445
446
447 wxFontsManager *wxTheFontsManager = NULL;