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