]> git.saurik.com Git - wxWidgets.git/blame - src/mgl/fontutil.cpp
GetSpacer returns a copy, not a reference to the size
[wxWidgets.git] / src / mgl / fontutil.cpp
CommitLineData
32b8ec41 1/////////////////////////////////////////////////////////////////////////////
127eab18 2// Name: src/mgl/fontutil.cpp
32b8ec41
VZ
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)
65571936 8// Licence: wxWindows licence
32b8ec41
VZ
9/////////////////////////////////////////////////////////////////////////////
10
32b8ec41
VZ
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
32d4c30a
WS
18#ifndef WX_PRECOMP
19 #include "wx/hash.h"
e4db172a 20 #include "wx/log.h"
32d4c30a
WS
21#endif
22
3af1a9f8
JS
23#include "wx/fontutil.h"
24#include "wx/encinfo.h"
25#include "wx/fontmap.h"
26#include "wx/tokenzr.h"
32b8ec41 27
32b8ec41 28#include "wx/listimpl.cpp"
493bdcc7 29#include "wx/sysopt.h"
32b8ec41
VZ
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]
44bool 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) )
127eab18 51 return false;
32b8ec41
VZ
52 encoding = (wxFontEncoding)enc;
53
54 // ok even if empty
55 facename = tokenizer.GetNextToken();
56
127eab18 57 return true;
32b8ec41
VZ
58}
59
60wxString wxNativeEncodingInfo::ToString() const
61{
62 wxString s;
63 s << (long)encoding;
127eab18 64 if ( !facename.empty() )
32b8ec41
VZ
65 {
66 s << _T(';') << facename;
67 }
68
69 return s;
70}
71
72// ----------------------------------------------------------------------------
73// common functions
74// ----------------------------------------------------------------------------
75
76bool wxGetNativeFontEncoding(wxFontEncoding encoding,
77 wxNativeEncodingInfo *info)
78{
127eab18 79 wxCHECK_MSG( info, false, _T("bad pointer in wxGetNativeFontEncoding") );
32b8ec41
VZ
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
127eab18 128 return false;
32b8ec41
VZ
129 }
130
131 info->encoding = encoding;
132
127eab18 133 return true;
32b8ec41
VZ
134}
135
136bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
137{
138 if ( !info.facename )
127eab18
WS
139 return true;
140
32b8ec41
VZ
141 wxMGLFontFamily *family = wxTheFontsManager->GetFamily(info.facename);
142 if ( !family )
127eab18 143 return false;
32b8ec41
VZ
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
127eab18 150 return true;
32b8ec41
VZ
151}
152
153
154// ----------------------------------------------------------------------------
155// wxFontFamily, wxMGLFontInstance, wxMGLFontLibrary
156// ----------------------------------------------------------------------------
157
158WX_DECLARE_LIST(wxMGLFontInstance, wxMGLFontInstanceList);
412e0d47
DS
159WX_DEFINE_LIST(wxMGLFontInstanceList)
160WX_DEFINE_LIST(wxMGLFontFamilyList)
32b8ec41 161
127eab18 162wxMGLFontInstance::wxMGLFontInstance(wxMGLFontLibrary *fontLib,
32b8ec41
VZ
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
127eab18 173 wxLogTrace("mgl_font", "loading instance of '%s' slant=%i pt=%0.1f aa=%i",
32b8ec41 174 m_fontLib->GetMGLfont_lib_t()->name, m_slant, m_pt, m_aa);
127eab18 175 m_font = MGL_loadFontInstance(m_fontLib->GetMGLfont_lib_t(),
32b8ec41
VZ
176 m_pt, slantAngle, 0.0, aa);
177 wxASSERT_MSG( m_font, wxT("Cannot create font instance.") );
178}
179
180wxMGLFontInstance::~wxMGLFontInstance()
181{
127eab18 182 wxLogTrace("mgl_font", "unloading instance of '%s' slant=%i pt=%0.1f aa=%i",
32b8ec41
VZ
183 m_fontLib->GetMGLfont_lib_t()->name, m_slant, m_pt, m_aa);
184 if ( m_font )
185 MGL_unloadFontInstance(m_font);
186}
127eab18
WS
187
188wxMGLFontLibrary::wxMGLFontLibrary(const wxString& filename, int type,
f3437beb 189 wxMGLFontFamily *parentFamily)
32b8ec41 190{
f3437beb 191 m_family = parentFamily;
32b8ec41
VZ
192 m_type = type;
193 m_fileName = filename;
194 m_refs = 0;
195 m_fontLib = NULL;
196
197 m_instances = new wxMGLFontInstanceList;
127eab18 198 m_instances->DeleteContents(true);
32b8ec41
VZ
199}
200
201wxMGLFontLibrary::~wxMGLFontLibrary()
202{
203 wxLogTrace("mgl_font", "font library dtor '%s'", m_fileName.mb_str());
204 delete m_instances;
205}
127eab18 206
32b8ec41
VZ
207void 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
217void 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
493bdcc7
VS
230static int gs_antialiasingThreshold = -1;
231
127eab18 232wxMGLFontInstance *wxMGLFontLibrary::GetFontInstance(wxFont *font,
32b8ec41
VZ
233 float scale, bool aa)
234{
235 wxASSERT_MSG(m_refs > 0 && m_fontLib, wxT("font library not loaded!"));
236
237 wxString facename;
32b8ec41
VZ
238 float pt = (float)font->GetPointSize() * scale;
239
493bdcc7
VS
240 if ( gs_antialiasingThreshold == -1 )
241 {
242 gs_antialiasingThreshold = 10;
243#if wxUSE_SYSTEM_OPTIONS
05c9ccbe 244 if ( wxSystemOptions::HasOption(wxT("mgl.aa-threshold")) )
127eab18 245 gs_antialiasingThreshold =
493bdcc7
VS
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.
127eab18
WS
254 bool antialiased = false;
255 if (( pt > gs_antialiasingThreshold ) &&
256 ( m_fontLib->fontLibType != MGL_BITMAPFONT_LIB ) )
257 antialiased = aa;
493bdcc7 258
127eab18 259 bool slant = (((m_type & wxFONTFACE_ITALIC) == 0) &&
32b8ec41
VZ
260 (font->GetStyle() == wxSLANT || font->GetStyle() == wxITALIC));
261
262 // FIXME_MGL -- MGL does not yet support slant, although the API is there
127eab18 263 slant = false;
32b8ec41 264
127eab18 265 wxLogTrace("mgl_font", "requested instance of '%s' slant=%i pt=%0.1f aa=%i",
32b8ec41
VZ
266 m_fileName.mb_str(), slant, pt, antialiased);
267
268 wxMGLFontInstance *i;
269 wxMGLFontInstanceList::Node *node;
127eab18 270
32b8ec41
VZ
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 {
127eab18 277 wxLogTrace("mgl_font", " got from cache: slant=%i pt=%0.1f aa=%i",
32b8ec41
VZ
278 i->GetSlant(), i->GetPt(), i->GetAA());
279 return i;
280 }
127eab18
WS
281 }
282
32b8ec41
VZ
283 i = new wxMGLFontInstance(this, pt, slant, antialiased);
284 m_instances->Append(i);
127eab18 285 return i;
32b8ec41
VZ
286}
287
288
289wxMGLFontFamily::wxMGLFontFamily(const font_info_t *info)
290{
291 m_name = info->familyName;
292 m_fontInfo = info;
127eab18 293
32b8ec41
VZ
294 if ( info->regularFace[0] == '\0' )
295 m_fontLibs[wxFONTFACE_REGULAR] = NULL;
296 else
127eab18 297 m_fontLibs[wxFONTFACE_REGULAR] =
f3437beb 298 new wxMGLFontLibrary(info->regularFace, wxFONTFACE_REGULAR, this);
127eab18 299
32b8ec41
VZ
300 if ( info->italicFace[0] == '\0' )
301 m_fontLibs[wxFONTFACE_ITALIC] = NULL;
302 else
127eab18 303 m_fontLibs[wxFONTFACE_ITALIC] =
f3437beb 304 new wxMGLFontLibrary(info->italicFace, wxFONTFACE_ITALIC, this);
127eab18 305
32b8ec41
VZ
306 if ( info->boldFace[0] == '\0' )
307 m_fontLibs[wxFONTFACE_BOLD] = NULL;
308 else
127eab18 309 m_fontLibs[wxFONTFACE_BOLD] =
f3437beb 310 new wxMGLFontLibrary(info->boldFace, wxFONTFACE_BOLD, this);
127eab18 311
32b8ec41
VZ
312 if ( info->boldItalicFace[0] == '\0' )
313 m_fontLibs[wxFONTFACE_BOLD_ITALIC] = NULL;
314 else
127eab18 315 m_fontLibs[wxFONTFACE_BOLD_ITALIC] =
f3437beb 316 new wxMGLFontLibrary(info->boldItalicFace, wxFONTFACE_BOLD_ITALIC, this);
127eab18 317
32b8ec41 318 wxLogTrace("mgl_font", "new family '%s' (r=%s, i=%s, b=%s, bi=%s)\n",
127eab18 319 info->familyName, info->regularFace, info->italicFace,
32b8ec41
VZ
320 info->boldFace, info->boldItalicFace);
321}
322
323wxMGLFontFamily::~wxMGLFontFamily()
324{
325 for (size_t i = 0; i < wxFONTFACE_MAX; i++)
326 delete m_fontLibs[i];
327}
328
329bool wxMGLFontFamily::HasFace(int type) const
330{
331 return (m_fontLibs[type] != NULL);
332}
333
334
335// ----------------------------------------------------------------------------
336// wxFontsManager
337// ----------------------------------------------------------------------------
338
339wxMGLFontLibrary *wxFontsManager::GetFontLibrary(wxFont *font)
340{
341 wxMGLFontFamily *family;
32b8ec41 342 int type;
fd495ab3 343 wxString facename = font->GetFaceName();
127eab18
WS
344
345 if ( !facename.empty() )
fd495ab3 346 family = GetFamily(facename);
32b8ec41
VZ
347 else
348 family = NULL;
fd495ab3 349
32b8ec41
VZ
350 if ( !family )
351 {
fd495ab3 352 facename.Empty();
32b8ec41
VZ
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 }
127eab18 409
32b8ec41
VZ
410 return family->GetLibrary(type);
411}
412
dbdcff51 413static ibool MGLAPI enum_callback(const font_info_t *info, void *cookie)
32b8ec41
VZ
414{
415 wxFontsManager *db = (wxFontsManager*)cookie;
416 db->AddFamily(info);
417 return TRUE;
418}
419
420wxFontsManager::wxFontsManager()
421{
422 m_hash = new wxHashTable(wxKEY_STRING);
127eab18 423 m_hash->DeleteContents(false);
32b8ec41 424 m_list = new wxMGLFontFamilyList;
127eab18 425 m_list->DeleteContents(true);
32b8ec41
VZ
426 MGL_enumerateFonts(enum_callback, (void*)this);
427}
428
429wxFontsManager::~wxFontsManager()
430{
431 delete m_hash;
432 delete m_list;
433}
434
435void 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}
127eab18 441
32b8ec41
VZ
442wxMGLFontFamily *wxFontsManager::GetFamily(const wxString& name) const
443{
444 return (wxMGLFontFamily*)m_hash->Get(name.Lower());
445}
446
447
448wxFontsManager *wxTheFontsManager = NULL;