]> git.saurik.com Git - wxWidgets.git/blob - src/mgl/fontutil.cpp
added wxListView class: this is going to be a wxListCtrl with human (inter)face
[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 SciTech Software, Inc. (www.scitechsoft.com)
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
24 #endif // PCH
25
26
27 #include "wx/fontutil.h"
28 #include "wx/fontmap.h"
29 #include "wx/tokenzr.h"
30 #include "wx/hash.h"
31 #include "wx/module.h"
32 #include "wx/listimpl.cpp"
33 #include "wx/log.h"
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]
48 bool 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
64 wxString 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
80 bool 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
140 bool 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
162 WX_DECLARE_LIST(wxMGLFontInstance, wxMGLFontInstanceList);
163 WX_DEFINE_LIST(wxMGLFontInstanceList);
164 WX_DEFINE_LIST(wxMGLFontFamilyList);
165
166 wxMGLFontInstance::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
184 wxMGLFontInstance::~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
192 wxMGLFontLibrary::wxMGLFontLibrary(const wxString& filename, int type)
193 {
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
203 wxMGLFontLibrary::~wxMGLFontLibrary()
204 {
205 wxLogTrace("mgl_font", "font library dtor '%s'", m_fileName.mb_str());
206 delete m_instances;
207 }
208
209 void 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
219 void 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
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 bool slant;
239 bool antialiased =
240 (m_fontLib->fontLibType == MGL_BITMAPFONT_LIB) ? FALSE : aa;
241 float pt = (float)font->GetPointSize() * scale;
242
243 slant = (((m_type & wxFONTFACE_ITALIC) == 0) &&
244 (font->GetStyle() == wxSLANT || font->GetStyle() == wxITALIC));
245
246 // FIXME_MGL -- MGL does not yet support slant, although the API is there
247 slant = FALSE;
248
249 wxLogTrace("mgl_font", "requested instance of '%s' slant=%i pt=%0.1f aa=%i",
250 m_fileName.mb_str(), slant, pt, antialiased);
251
252 wxMGLFontInstance *i;
253 wxMGLFontInstanceList::Node *node;
254
255 for (node = m_instances->GetFirst(); node; node = node->GetNext())
256 {
257 i = node->GetData();
258 if ( i->GetPt() == pt && i->GetSlant() == slant &&
259 i->GetAA() == antialiased )
260 {
261 wxLogTrace("mgl_font", " got from cache: slant=%i pt=%0.1f aa=%i",
262 i->GetSlant(), i->GetPt(), i->GetAA());
263 return i;
264 }
265 }
266
267 i = new wxMGLFontInstance(this, pt, slant, antialiased);
268 m_instances->Append(i);
269 return i;
270 }
271
272
273 wxMGLFontFamily::wxMGLFontFamily(const font_info_t *info)
274 {
275 m_name = info->familyName;
276 m_fontInfo = info;
277
278 if ( info->regularFace[0] == '\0' )
279 m_fontLibs[wxFONTFACE_REGULAR] = NULL;
280 else
281 m_fontLibs[wxFONTFACE_REGULAR] =
282 new wxMGLFontLibrary(info->regularFace, wxFONTFACE_REGULAR);
283
284 if ( info->italicFace[0] == '\0' )
285 m_fontLibs[wxFONTFACE_ITALIC] = NULL;
286 else
287 m_fontLibs[wxFONTFACE_ITALIC] =
288 new wxMGLFontLibrary(info->italicFace, wxFONTFACE_ITALIC);
289
290 if ( info->boldFace[0] == '\0' )
291 m_fontLibs[wxFONTFACE_BOLD] = NULL;
292 else
293 m_fontLibs[wxFONTFACE_BOLD] =
294 new wxMGLFontLibrary(info->boldFace, wxFONTFACE_BOLD);
295
296 if ( info->boldItalicFace[0] == '\0' )
297 m_fontLibs[wxFONTFACE_BOLD_ITALIC] = NULL;
298 else
299 m_fontLibs[wxFONTFACE_BOLD_ITALIC] =
300 new wxMGLFontLibrary(info->boldItalicFace, wxFONTFACE_BOLD_ITALIC);
301
302 wxLogTrace("mgl_font", "new family '%s' (r=%s, i=%s, b=%s, bi=%s)\n",
303 info->familyName, info->regularFace, info->italicFace,
304 info->boldFace, info->boldItalicFace);
305 }
306
307 wxMGLFontFamily::~wxMGLFontFamily()
308 {
309 for (size_t i = 0; i < wxFONTFACE_MAX; i++)
310 delete m_fontLibs[i];
311 }
312
313 bool wxMGLFontFamily::HasFace(int type) const
314 {
315 return (m_fontLibs[type] != NULL);
316 }
317
318
319 // ----------------------------------------------------------------------------
320 // wxFontsManager
321 // ----------------------------------------------------------------------------
322
323 wxMGLFontLibrary *wxFontsManager::GetFontLibrary(wxFont *font)
324 {
325 wxMGLFontFamily *family;
326 wxString facename;
327 int type;
328
329 if ( facename )
330 family = GetFamily(font->GetFaceName());
331 else
332 family = NULL;
333 if ( family )
334 facename = font->GetFaceName();
335 else
336 facename.Empty();
337
338 if ( !family )
339 {
340 switch (font->GetFamily())
341 {
342 case wxSCRIPT:
343 facename = wxT("Script");
344 break;
345 case wxDECORATIVE:
346 facename = wxT("Charter");
347 break;
348 case wxROMAN:
349 facename = wxT("Times");
350 break;
351 case wxTELETYPE:
352 case wxMODERN:
353 facename = wxT("Courier");
354 break;
355 case wxSWISS:
356 facename = wxT("Helvetica");
357 break;
358 case wxDEFAULT:
359 default:
360 facename = wxT("Helvetica");
361 break;
362 }
363
364 family = GetFamily(facename);
365 if ( !family )
366 {
367 if ( m_list->GetFirst() )
368 family = m_list->GetFirst()->GetData();
369 else
370 wxFAIL_MSG(wxT("Fatal error, no fonts available!"));
371 }
372 }
373
374 type = wxFONTFACE_REGULAR;
375
376 if ( font->GetWeight() == wxBOLD )
377 type |= wxFONTFACE_BOLD;
378
379 // FIXME_MGL -- this should read "if ( font->GetStyle() == wxITALIC )",
380 // but since MGL does not yet support slant, we try to display it with
381 // italic face (better than nothing...)
382 if ( font->GetStyle() == wxITALIC || font->GetStyle() == wxSLANT )
383 {
384 if ( family->HasFace(type | wxFONTFACE_ITALIC) )
385 type |= wxFONTFACE_ITALIC;
386 }
387 if ( !family->HasFace(type) )
388 {
389 for (int i = 0; i < wxFONTFACE_MAX; i++)
390 if ( family->HasFace(i) )
391 {
392 type = i;
393 break;
394 }
395 }
396
397 return family->GetLibrary(type);
398 }
399
400 static ibool enum_callback(const font_info_t *info, void *cookie)
401 {
402 wxFontsManager *db = (wxFontsManager*)cookie;
403 db->AddFamily(info);
404 return TRUE;
405 }
406
407 wxFontsManager::wxFontsManager()
408 {
409 m_hash = new wxHashTable(wxKEY_STRING);
410 m_hash->DeleteContents(FALSE);
411 m_list = new wxMGLFontFamilyList;
412 m_list->DeleteContents(TRUE);
413 MGL_enumerateFonts(enum_callback, (void*)this);
414 }
415
416 wxFontsManager::~wxFontsManager()
417 {
418 delete m_hash;
419 delete m_list;
420 }
421
422 void wxFontsManager::AddFamily(const font_info_t *info)
423 {
424 wxMGLFontFamily *f = new wxMGLFontFamily(info);
425 m_hash->Put(f->GetName().Lower(), f);
426 m_list->Append(f);
427 }
428
429 wxMGLFontFamily *wxFontsManager::GetFamily(const wxString& name) const
430 {
431 return (wxMGLFontFamily*)m_hash->Get(name.Lower());
432 }
433
434
435 wxFontsManager *wxTheFontsManager = NULL;
436
437
438 // A module that takes care of fonts DB initialization and destruction:
439
440 class wxFontutilModule: public wxModule
441 {
442 DECLARE_DYNAMIC_CLASS(wxFontutilModule)
443 public:
444 wxFontutilModule() {}
445 bool OnInit()
446 {
447 wxTheFontsManager = new wxFontsManager;
448 return TRUE;
449 }
450 void OnExit()
451 {
452 delete wxTheFontsManager;
453 }
454 };
455
456 IMPLEMENT_DYNAMIC_CLASS(wxFontutilModule, wxModule)