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