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