]> git.saurik.com Git - wxWidgets.git/blob - src/mgl/fontutil.cpp
fixed bug/assert failure when refreshing items in non report mode
[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 #include "wx/log.h"
25 #include "wx/fontutil.h"
26 #include "wx/fontmap.h"
27 #include "wx/tokenzr.h"
28 #include "wx/hash.h"
29 #endif // PCH
30
31
32 #include "wx/listimpl.cpp"
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]
47 bool 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
63 wxString 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
79 bool 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
139 bool 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
161 WX_DECLARE_LIST(wxMGLFontInstance, wxMGLFontInstanceList);
162 WX_DEFINE_LIST(wxMGLFontInstanceList);
163 WX_DEFINE_LIST(wxMGLFontFamilyList);
164
165 wxMGLFontInstance::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
183 wxMGLFontInstance::~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
191 wxMGLFontLibrary::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
202 wxMGLFontLibrary::~wxMGLFontLibrary()
203 {
204 wxLogTrace("mgl_font", "font library dtor '%s'", m_fileName.mb_str());
205 delete m_instances;
206 }
207
208 void 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
218 void 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
231 wxMGLFontInstance *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
272 wxMGLFontFamily::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
306 wxMGLFontFamily::~wxMGLFontFamily()
307 {
308 for (size_t i = 0; i < wxFONTFACE_MAX; i++)
309 delete m_fontLibs[i];
310 }
311
312 bool wxMGLFontFamily::HasFace(int type) const
313 {
314 return (m_fontLibs[type] != NULL);
315 }
316
317
318 // ----------------------------------------------------------------------------
319 // wxFontsManager
320 // ----------------------------------------------------------------------------
321
322 wxMGLFontLibrary *wxFontsManager::GetFontLibrary(wxFont *font)
323 {
324 wxMGLFontFamily *family;
325 int type;
326 wxString facename = font->GetFaceName();
327
328 if ( !facename.IsEmpty() )
329 family = GetFamily(facename);
330 else
331 family = NULL;
332
333 if ( !family )
334 {
335 facename.Empty();
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
396 static 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
403 wxFontsManager::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
412 wxFontsManager::~wxFontsManager()
413 {
414 delete m_hash;
415 delete m_list;
416 }
417
418 void 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
425 wxMGLFontFamily *wxFontsManager::GetFamily(const wxString& name) const
426 {
427 return (wxMGLFontFamily*)m_hash->Get(name.Lower());
428 }
429
430
431 wxFontsManager *wxTheFontsManager = NULL;