]> git.saurik.com Git - wxWidgets.git/blame - src/mgl/fontutil.cpp
don't compare invalid iterators/node pointers
[wxWidgets.git] / src / mgl / fontutil.cpp
CommitLineData
32b8ec41 1/////////////////////////////////////////////////////////////////////////////
127eab18 2// Name: src/mgl/fontutil.cpp
32b8ec41
VZ
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)
65571936 8// Licence: wxWindows licence
32b8ec41
VZ
9/////////////////////////////////////////////////////////////////////////////
10
32b8ec41
VZ
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
3af1a9f8
JS
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"
32b8ec41 24
32b8ec41 25#include "wx/listimpl.cpp"
493bdcc7 26#include "wx/sysopt.h"
32b8ec41
VZ
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]
41bool 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) )
127eab18 48 return false;
32b8ec41
VZ
49 encoding = (wxFontEncoding)enc;
50
51 // ok even if empty
52 facename = tokenizer.GetNextToken();
53
127eab18 54 return true;
32b8ec41
VZ
55}
56
57wxString wxNativeEncodingInfo::ToString() const
58{
59 wxString s;
60 s << (long)encoding;
127eab18 61 if ( !facename.empty() )
32b8ec41
VZ
62 {
63 s << _T(';') << facename;
64 }
65
66 return s;
67}
68
69// ----------------------------------------------------------------------------
70// common functions
71// ----------------------------------------------------------------------------
72
73bool wxGetNativeFontEncoding(wxFontEncoding encoding,
74 wxNativeEncodingInfo *info)
75{
127eab18 76 wxCHECK_MSG( info, false, _T("bad pointer in wxGetNativeFontEncoding") );
32b8ec41
VZ
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
127eab18 125 return false;
32b8ec41
VZ
126 }
127
128 info->encoding = encoding;
129
127eab18 130 return true;
32b8ec41
VZ
131}
132
133bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
134{
135 if ( !info.facename )
127eab18
WS
136 return true;
137
32b8ec41
VZ
138 wxMGLFontFamily *family = wxTheFontsManager->GetFamily(info.facename);
139 if ( !family )
127eab18 140 return false;
32b8ec41
VZ
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
127eab18 147 return true;
32b8ec41
VZ
148}
149
150
151// ----------------------------------------------------------------------------
152// wxFontFamily, wxMGLFontInstance, wxMGLFontLibrary
153// ----------------------------------------------------------------------------
154
155WX_DECLARE_LIST(wxMGLFontInstance, wxMGLFontInstanceList);
412e0d47
DS
156WX_DEFINE_LIST(wxMGLFontInstanceList)
157WX_DEFINE_LIST(wxMGLFontFamilyList)
32b8ec41 158
127eab18 159wxMGLFontInstance::wxMGLFontInstance(wxMGLFontLibrary *fontLib,
32b8ec41
VZ
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
127eab18 170 wxLogTrace("mgl_font", "loading instance of '%s' slant=%i pt=%0.1f aa=%i",
32b8ec41 171 m_fontLib->GetMGLfont_lib_t()->name, m_slant, m_pt, m_aa);
127eab18 172 m_font = MGL_loadFontInstance(m_fontLib->GetMGLfont_lib_t(),
32b8ec41
VZ
173 m_pt, slantAngle, 0.0, aa);
174 wxASSERT_MSG( m_font, wxT("Cannot create font instance.") );
175}
176
177wxMGLFontInstance::~wxMGLFontInstance()
178{
127eab18 179 wxLogTrace("mgl_font", "unloading instance of '%s' slant=%i pt=%0.1f aa=%i",
32b8ec41
VZ
180 m_fontLib->GetMGLfont_lib_t()->name, m_slant, m_pt, m_aa);
181 if ( m_font )
182 MGL_unloadFontInstance(m_font);
183}
127eab18
WS
184
185wxMGLFontLibrary::wxMGLFontLibrary(const wxString& filename, int type,
f3437beb 186 wxMGLFontFamily *parentFamily)
32b8ec41 187{
f3437beb 188 m_family = parentFamily;
32b8ec41
VZ
189 m_type = type;
190 m_fileName = filename;
191 m_refs = 0;
192 m_fontLib = NULL;
193
194 m_instances = new wxMGLFontInstanceList;
127eab18 195 m_instances->DeleteContents(true);
32b8ec41
VZ
196}
197
198wxMGLFontLibrary::~wxMGLFontLibrary()
199{
200 wxLogTrace("mgl_font", "font library dtor '%s'", m_fileName.mb_str());
201 delete m_instances;
202}
127eab18 203
32b8ec41
VZ
204void 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
214void 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
493bdcc7
VS
227static int gs_antialiasingThreshold = -1;
228
127eab18 229wxMGLFontInstance *wxMGLFontLibrary::GetFontInstance(wxFont *font,
32b8ec41
VZ
230 float scale, bool aa)
231{
232 wxASSERT_MSG(m_refs > 0 && m_fontLib, wxT("font library not loaded!"));
233
234 wxString facename;
32b8ec41
VZ
235 float pt = (float)font->GetPointSize() * scale;
236
493bdcc7
VS
237 if ( gs_antialiasingThreshold == -1 )
238 {
239 gs_antialiasingThreshold = 10;
240#if wxUSE_SYSTEM_OPTIONS
05c9ccbe 241 if ( wxSystemOptions::HasOption(wxT("mgl.aa-threshold")) )
127eab18 242 gs_antialiasingThreshold =
493bdcc7
VS
243 wxSystemOptions::GetOptionInt(wxT("mgl.aa-threshold"));
244 wxLogTrace("mgl_font", "AA threshold set to %i", gs_antialiasingThreshold);
245#endif
246 }
247
248 // Small characters don't look good when antialiased with the algorithm
249 // that FreeType uses (mere 2x2 supersampling), so lets disable it AA
250 // completely for small fonts.
127eab18
WS
251 bool antialiased = false;
252 if (( pt > gs_antialiasingThreshold ) &&
253 ( m_fontLib->fontLibType != MGL_BITMAPFONT_LIB ) )
254 antialiased = aa;
493bdcc7 255
127eab18 256 bool slant = (((m_type & wxFONTFACE_ITALIC) == 0) &&
32b8ec41
VZ
257 (font->GetStyle() == wxSLANT || font->GetStyle() == wxITALIC));
258
259 // FIXME_MGL -- MGL does not yet support slant, although the API is there
127eab18 260 slant = false;
32b8ec41 261
127eab18 262 wxLogTrace("mgl_font", "requested instance of '%s' slant=%i pt=%0.1f aa=%i",
32b8ec41
VZ
263 m_fileName.mb_str(), slant, pt, antialiased);
264
265 wxMGLFontInstance *i;
266 wxMGLFontInstanceList::Node *node;
127eab18 267
32b8ec41
VZ
268 for (node = m_instances->GetFirst(); node; node = node->GetNext())
269 {
270 i = node->GetData();
271 if ( i->GetPt() == pt && i->GetSlant() == slant &&
272 i->GetAA() == antialiased )
273 {
127eab18 274 wxLogTrace("mgl_font", " got from cache: slant=%i pt=%0.1f aa=%i",
32b8ec41
VZ
275 i->GetSlant(), i->GetPt(), i->GetAA());
276 return i;
277 }
127eab18
WS
278 }
279
32b8ec41
VZ
280 i = new wxMGLFontInstance(this, pt, slant, antialiased);
281 m_instances->Append(i);
127eab18 282 return i;
32b8ec41
VZ
283}
284
285
286wxMGLFontFamily::wxMGLFontFamily(const font_info_t *info)
287{
288 m_name = info->familyName;
289 m_fontInfo = info;
127eab18 290
32b8ec41
VZ
291 if ( info->regularFace[0] == '\0' )
292 m_fontLibs[wxFONTFACE_REGULAR] = NULL;
293 else
127eab18 294 m_fontLibs[wxFONTFACE_REGULAR] =
f3437beb 295 new wxMGLFontLibrary(info->regularFace, wxFONTFACE_REGULAR, this);
127eab18 296
32b8ec41
VZ
297 if ( info->italicFace[0] == '\0' )
298 m_fontLibs[wxFONTFACE_ITALIC] = NULL;
299 else
127eab18 300 m_fontLibs[wxFONTFACE_ITALIC] =
f3437beb 301 new wxMGLFontLibrary(info->italicFace, wxFONTFACE_ITALIC, this);
127eab18 302
32b8ec41
VZ
303 if ( info->boldFace[0] == '\0' )
304 m_fontLibs[wxFONTFACE_BOLD] = NULL;
305 else
127eab18 306 m_fontLibs[wxFONTFACE_BOLD] =
f3437beb 307 new wxMGLFontLibrary(info->boldFace, wxFONTFACE_BOLD, this);
127eab18 308
32b8ec41
VZ
309 if ( info->boldItalicFace[0] == '\0' )
310 m_fontLibs[wxFONTFACE_BOLD_ITALIC] = NULL;
311 else
127eab18 312 m_fontLibs[wxFONTFACE_BOLD_ITALIC] =
f3437beb 313 new wxMGLFontLibrary(info->boldItalicFace, wxFONTFACE_BOLD_ITALIC, this);
127eab18 314
32b8ec41 315 wxLogTrace("mgl_font", "new family '%s' (r=%s, i=%s, b=%s, bi=%s)\n",
127eab18 316 info->familyName, info->regularFace, info->italicFace,
32b8ec41
VZ
317 info->boldFace, info->boldItalicFace);
318}
319
320wxMGLFontFamily::~wxMGLFontFamily()
321{
322 for (size_t i = 0; i < wxFONTFACE_MAX; i++)
323 delete m_fontLibs[i];
324}
325
326bool wxMGLFontFamily::HasFace(int type) const
327{
328 return (m_fontLibs[type] != NULL);
329}
330
331
332// ----------------------------------------------------------------------------
333// wxFontsManager
334// ----------------------------------------------------------------------------
335
336wxMGLFontLibrary *wxFontsManager::GetFontLibrary(wxFont *font)
337{
338 wxMGLFontFamily *family;
32b8ec41 339 int type;
fd495ab3 340 wxString facename = font->GetFaceName();
127eab18
WS
341
342 if ( !facename.empty() )
fd495ab3 343 family = GetFamily(facename);
32b8ec41
VZ
344 else
345 family = NULL;
fd495ab3 346
32b8ec41
VZ
347 if ( !family )
348 {
fd495ab3 349 facename.Empty();
32b8ec41
VZ
350 switch (font->GetFamily())
351 {
352 case wxSCRIPT:
353 facename = wxT("Script");
354 break;
355 case wxDECORATIVE:
356 facename = wxT("Charter");
357 break;
358 case wxROMAN:
359 facename = wxT("Times");
360 break;
361 case wxTELETYPE:
362 case wxMODERN:
363 facename = wxT("Courier");
364 break;
365 case wxSWISS:
366 facename = wxT("Helvetica");
367 break;
368 case wxDEFAULT:
369 default:
370 facename = wxT("Helvetica");
371 break;
372 }
373
374 family = GetFamily(facename);
375 if ( !family )
376 {
377 if ( m_list->GetFirst() )
378 family = m_list->GetFirst()->GetData();
379 else
380 wxFAIL_MSG(wxT("Fatal error, no fonts available!"));
381 }
382 }
383
384 type = wxFONTFACE_REGULAR;
385
386 if ( font->GetWeight() == wxBOLD )
387 type |= wxFONTFACE_BOLD;
388
389 // FIXME_MGL -- this should read "if ( font->GetStyle() == wxITALIC )",
390 // but since MGL does not yet support slant, we try to display it with
391 // italic face (better than nothing...)
392 if ( font->GetStyle() == wxITALIC || font->GetStyle() == wxSLANT )
393 {
394 if ( family->HasFace(type | wxFONTFACE_ITALIC) )
395 type |= wxFONTFACE_ITALIC;
396 }
397 if ( !family->HasFace(type) )
398 {
399 for (int i = 0; i < wxFONTFACE_MAX; i++)
400 if ( family->HasFace(i) )
401 {
402 type = i;
403 break;
404 }
405 }
127eab18 406
32b8ec41
VZ
407 return family->GetLibrary(type);
408}
409
dbdcff51 410static ibool MGLAPI enum_callback(const font_info_t *info, void *cookie)
32b8ec41
VZ
411{
412 wxFontsManager *db = (wxFontsManager*)cookie;
413 db->AddFamily(info);
414 return TRUE;
415}
416
417wxFontsManager::wxFontsManager()
418{
419 m_hash = new wxHashTable(wxKEY_STRING);
127eab18 420 m_hash->DeleteContents(false);
32b8ec41 421 m_list = new wxMGLFontFamilyList;
127eab18 422 m_list->DeleteContents(true);
32b8ec41
VZ
423 MGL_enumerateFonts(enum_callback, (void*)this);
424}
425
426wxFontsManager::~wxFontsManager()
427{
428 delete m_hash;
429 delete m_list;
430}
431
432void wxFontsManager::AddFamily(const font_info_t *info)
433{
434 wxMGLFontFamily *f = new wxMGLFontFamily(info);
435 m_hash->Put(f->GetName().Lower(), f);
436 m_list->Append(f);
437}
127eab18 438
32b8ec41
VZ
439wxMGLFontFamily *wxFontsManager::GetFamily(const wxString& name) const
440{
441 return (wxMGLFontFamily*)m_hash->Get(name.Lower());
442}
443
444
445wxFontsManager *wxTheFontsManager = NULL;