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