]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/font.cpp
86663b5c27c2c1f41709c1f05476330f0b9c00b7
[wxWidgets.git] / src / gtk / font.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: font.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // ============================================================================
11 // declarations
12 // ============================================================================
13
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17
18 #ifdef __GNUG__
19 #pragma implementation "font.h"
20 #endif
21
22 #include "wx/font.h"
23 #include "wx/utils.h"
24 #include "wx/log.h"
25 #include "wx/gdicmn.h"
26 #include "wx/tokenzr.h"
27
28 #include <strings.h>
29
30 #include "gdk/gdk.h"
31
32 // ----------------------------------------------------------------------------
33 // local data
34 // ----------------------------------------------------------------------------
35
36 #if wxUSE_FONTNAMEDIRECTORY
37 extern wxFontNameDirectory *wxTheFontNameDirectory;
38 #endif
39
40 // ----------------------------------------------------------------------------
41 // wxFontRefData
42 // ----------------------------------------------------------------------------
43
44 class wxFontRefData : public wxObjectRefData
45 {
46 public:
47 wxFontRefData(int size = wxDEFAULT,
48 int family = wxDEFAULT,
49 int style = wxDEFAULT,
50 int weight = wxDEFAULT,
51 bool underlined = FALSE,
52 const wxString& faceName = wxEmptyString,
53 wxFontEncoding encoding = wxFONTENCODING_DEFAULT)
54 : m_scaled_xfonts(wxKEY_INTEGER)
55 {
56 Init(size, family, style, weight, underlined, faceName, encoding);
57 }
58
59 wxFontRefData( const wxFontRefData& data );
60
61 virtual ~wxFontRefData();
62
63 protected:
64 // common part of all ctors
65 void Init(int pointSize,
66 int family,
67 int style,
68 int weight,
69 bool underlined,
70 const wxString& faceName,
71 wxFontEncoding encoding);
72
73 private:
74 wxList m_scaled_xfonts;
75
76 int m_pointSize;
77 int m_family,
78 m_style,
79 m_weight;
80 bool m_underlined;
81 wxString m_faceName;
82 wxFontEncoding m_encoding;
83
84 bool m_byXFontName;
85 GdkFont *m_font;
86
87 friend wxFont;
88 };
89
90 // ============================================================================
91 // implementation
92 // ============================================================================
93
94 // ----------------------------------------------------------------------------
95 // wxFontRefData
96 // ----------------------------------------------------------------------------
97
98 void wxFontRefData::Init(int pointSize,
99 int family,
100 int style,
101 int weight,
102 bool underlined,
103 const wxString& faceName,
104 wxFontEncoding encoding)
105 {
106 if (family == wxDEFAULT)
107 m_family = wxSWISS;
108 else
109 m_family = family;
110
111 m_faceName = faceName;
112
113 if (style == wxDEFAULT)
114 m_style = wxNORMAL;
115 else
116 m_style = style;
117
118 if (weight == wxDEFAULT)
119 m_weight = wxNORMAL;
120 else
121 m_weight = weight;
122
123 if (pointSize == wxDEFAULT)
124 m_pointSize = 12;
125 else
126 m_pointSize = pointSize;
127
128 m_underlined = underlined;
129 m_encoding = encoding;
130
131 m_byXFontName = FALSE;
132 m_font = (GdkFont *) NULL;
133 }
134
135 wxFontRefData::wxFontRefData( const wxFontRefData& data )
136 : m_scaled_xfonts(wxKEY_INTEGER)
137 {
138 Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight,
139 data.m_underlined, data.m_faceName, data.m_encoding);
140
141 if (data.m_font)
142 m_font = gdk_font_ref( data.m_font );
143 }
144
145 wxFontRefData::~wxFontRefData()
146 {
147 wxNode *node = m_scaled_xfonts.First();
148 while (node)
149 {
150 GdkFont *font = (GdkFont*)node->Data();
151 wxNode *next = node->Next();
152 gdk_font_unref( font );
153 node = next;
154 }
155
156 if (m_font)
157 gdk_font_unref( m_font );
158 }
159
160 // ----------------------------------------------------------------------------
161 // wxFont
162 // ----------------------------------------------------------------------------
163
164 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
165
166 void wxFont::Init()
167 {
168 if (wxTheFontList)
169 wxTheFontList->Append( this );
170 }
171
172 wxFont::wxFont( GdkFont *font, char *xFontName )
173 {
174 if (!xFontName)
175 return;
176
177 // VZ: this ctor ddidn't append the font to wxTheFontList before, but
178 // there is no reason to not do it, is there?
179 Init();
180
181 m_refData = new wxFontRefData();
182
183 // M_FONTDATA->m_byXFontName = TRUE;
184 M_FONTDATA->m_font = font;
185
186 wxString tmp;
187
188 wxString fontname( xFontName );
189 wxStringTokenizer tn( fontname, _T("-") );
190
191 tn.GetNextToken(); // foundry
192
193 M_FONTDATA->m_faceName = tn.GetNextToken(); // courier
194
195 tmp = tn.GetNextToken().MakeUpper();
196 if (tmp == _T("BOLD")) M_FONTDATA->m_weight = wxBOLD;
197
198 tmp = tn.GetNextToken().MakeUpper();
199 if (tmp == _T("I")) M_FONTDATA->m_style = wxITALIC;
200 if (tmp == _T("O")) M_FONTDATA->m_style = wxITALIC;
201
202 tn.GetNextToken(); // set width
203 tn.GetNextToken(); // ?
204 tn.GetNextToken(); // pixel size
205
206 tmp = tn.GetNextToken(); // pointsize
207 int num = wxStrtol (tmp.c_str(), (wxChar **) NULL, 10);
208 M_FONTDATA->m_pointSize = num / 10;
209
210 tn.GetNextToken(); // x-res
211 tn.GetNextToken(); // y-res
212
213 tmp = tn.GetNextToken().MakeUpper();
214 if (tmp == _T("M")) M_FONTDATA->m_family = wxMODERN;
215 else if (M_FONTDATA->m_faceName == _T("TIMES")) M_FONTDATA->m_family = wxROMAN;
216 else if (M_FONTDATA->m_faceName == _T("HELVETICA")) M_FONTDATA->m_family = wxSWISS;
217 else if (M_FONTDATA->m_faceName == _T("LUCIDATYPEWRITER")) M_FONTDATA->m_family = wxTELETYPE;
218 else if (M_FONTDATA->m_faceName == _T("LUCIDA")) M_FONTDATA->m_family = wxDECORATIVE;
219 else if (M_FONTDATA->m_faceName == _T("UTOPIA")) M_FONTDATA->m_family = wxSCRIPT;
220 }
221
222 bool wxFont::Create( int pointSize,
223 int family,
224 int style,
225 int weight,
226 bool underlined,
227 const wxString& face,
228 wxFontEncoding encoding )
229 {
230 m_refData = new wxFontRefData(pointSize, family, style, weight,
231 underlined, face, encoding);
232
233 Init();
234
235 return TRUE;
236 }
237
238 void wxFont::Unshare()
239 {
240 if (!m_refData)
241 {
242 m_refData = new wxFontRefData();
243 }
244 else
245 {
246 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
247 UnRef();
248 m_refData = ref;
249 }
250 }
251
252 wxFont::~wxFont()
253 {
254 if (wxTheFontList)
255 wxTheFontList->DeleteObject( this );
256 }
257
258 // ----------------------------------------------------------------------------
259 // accessors
260 // ----------------------------------------------------------------------------
261
262 int wxFont::GetPointSize() const
263 {
264 wxCHECK_MSG( Ok(), 0, _T("invalid font") );
265
266 return M_FONTDATA->m_pointSize;
267 }
268
269 wxString wxFont::GetFaceName() const
270 {
271 wxCHECK_MSG( Ok(), _T(""), _T("invalid font") );
272
273 return M_FONTDATA->m_faceName;
274 }
275
276 int wxFont::GetFamily() const
277 {
278 wxCHECK_MSG( Ok(), 0, _T("invalid font") );
279
280 return M_FONTDATA->m_family;
281 }
282
283 int wxFont::GetStyle() const
284 {
285 wxCHECK_MSG( Ok(), 0, _T("invalid font") );
286
287 return M_FONTDATA->m_style;
288 }
289
290 int wxFont::GetWeight() const
291 {
292 wxCHECK_MSG( Ok(), 0, _T("invalid font") );
293
294 return M_FONTDATA->m_weight;
295 }
296
297 bool wxFont::GetUnderlined() const
298 {
299 wxCHECK_MSG( Ok(), FALSE, _T("invalid font") );
300
301 return M_FONTDATA->m_underlined;
302 }
303
304
305 wxFontEncoding wxFont::GetEncoding() const
306 {
307 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, _T("invalid font") );
308
309 return M_FONTDATA->m_encoding;
310 }
311
312 // ----------------------------------------------------------------------------
313 // change font attributes
314 // ----------------------------------------------------------------------------
315
316 void wxFont::SetPointSize(int pointSize)
317 {
318 Unshare();
319
320 M_FONTDATA->m_pointSize = pointSize;
321 }
322
323 void wxFont::SetFamily(int family)
324 {
325 Unshare();
326
327 M_FONTDATA->m_family = family;
328 }
329
330 void wxFont::SetStyle(int style)
331 {
332 Unshare();
333
334 M_FONTDATA->m_style = style;
335 }
336
337 void wxFont::SetWeight(int weight)
338 {
339 Unshare();
340
341 M_FONTDATA->m_weight = weight;
342 }
343
344 void wxFont::SetFaceName(const wxString& faceName)
345 {
346 Unshare();
347
348 M_FONTDATA->m_faceName = faceName;
349 }
350
351 void wxFont::SetUnderlined(bool underlined)
352 {
353 Unshare();
354
355 M_FONTDATA->m_underlined = underlined;
356 }
357
358 void wxFont::SetEncoding(wxFontEncoding encoding)
359 {
360 Unshare();
361
362 M_FONTDATA->m_encoding = encoding;
363 }
364
365 // ----------------------------------------------------------------------------
366 // get internal representation of font
367 // ----------------------------------------------------------------------------
368
369 GdkFont *wxFont::GetInternalFont( float scale ) const
370 {
371 if (!Ok())
372 {
373 wxFAIL_MSG( _T("invalid font") );
374
375 return (GdkFont*) NULL;
376 }
377
378 /* short cut if the special X font constructor has been used */
379 if (M_FONTDATA->m_byXFontName)
380 return M_FONTDATA->m_font;
381
382 long int_scale = long(scale * 100.0 + 0.5); /* key for fontlist */
383 int point_scale = (M_FONTDATA->m_pointSize * 10 * int_scale) / 100;
384 GdkFont *font = (GdkFont *) NULL;
385
386 wxNode *node = M_FONTDATA->m_scaled_xfonts.Find(int_scale);
387 if (node)
388 {
389 font = (GdkFont*)node->Data();
390 }
391 else
392 {
393 #if 0
394 if ((int_scale == 100) &&
395 (M_FONTDATA->m_family == wxSWISS) &&
396 (M_FONTDATA->m_style == wxNORMAL) &&
397 (M_FONTDATA->m_pointSize == 12) &&
398 (M_FONTDATA->m_weight == wxNORMAL) &&
399 (M_FONTDATA->m_underlined == FALSE))
400 {
401 font = gdk_font_load( "-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*" );
402 }
403 else
404 #endif // 0
405 {
406 font = wxLoadQueryNearestFont( point_scale,
407 M_FONTDATA->m_family,
408 M_FONTDATA->m_style,
409 M_FONTDATA->m_weight,
410 M_FONTDATA->m_underlined,
411 M_FONTDATA->m_faceName,
412 M_FONTDATA->m_encoding );
413 }
414
415 M_FONTDATA->m_scaled_xfonts.Append( int_scale, (wxObject*)font );
416 }
417
418 if (!font)
419 {
420 wxLogError(_T("could not load any font"));
421 }
422
423 return font;
424 }
425
426 //-----------------------------------------------------------------------------
427 // local utilities to find a X font
428 //-----------------------------------------------------------------------------
429
430 // wow, what's this stuff? Is it used/useful? (VZ)
431 #if 0
432
433 //-----------------------------------------------------------------------------
434 // face names and index functions
435 //-----------------------------------------------------------------------------
436
437 static char *font_defaults[] = {
438 "FamilyDefault", "Default",
439 "FamilyRoman", "Roman",
440 "FamilyDecorative", "Decorative",
441 "FamilyModern", "Modern",
442 "FamilyTeletype", "Teletype",
443 "FamilySwiss", "Swiss",
444 "FamilyScript", "Script",
445
446 "AfmMedium", "",
447 "AfmBold", "Bo",
448 "AfmLight", "",
449 "AfmStraight", "",
450 "AfmItalic", "${AfmSlant}",
451 "AfmSlant", "O",
452 "AfmRoman", "Ro",
453 "AfmTimes", "Times",
454 "AfmHelvetica", "Helv",
455 "AfmCourier", "Cour",
456
457 "Afm___", "${AfmTimes,$[weight],$[style]}",
458
459 "AfmTimes__", "${AfmTimes}${Afm$[weight]}${Afm$[style]}",
460 "AfmTimesMediumStraight", "${AfmTimes}${AfmRoman}",
461 "AfmTimesLightStraight", "${AfmTimes}${AfmRoman}",
462 "AfmTimes_Italic", "${AfmTimes}$[weight]${AfmItalic}",
463 "AfmTimes_Slant", "${AfmTimes}$[weight]${AfmItalic}",
464
465 "AfmSwiss__", "${AfmHelvetica}${Afm$[weight]}${Afm$[style]}",
466 "AfmModern__", "${AfmCourier}${Afm$[weight]}${Afm$[style]}",
467
468 "AfmTeletype__", "${AfmModern,$[weight],$[style]}",
469
470 "PostScriptMediumStraight", "",
471 "PostScriptMediumItalic", "-Oblique",
472 "PostScriptMediumSlant", "-Oblique",
473 "PostScriptLightStraight", "",
474 "PostScriptLightItalic", "-Oblique",
475 "PostScriptLightSlant", "-Oblique",
476 "PostScriptBoldStraight", "-Bold",
477 "PostScriptBoldItalic", "-BoldOblique",
478 "PostScriptBoldSlant", "-BoldOblique",
479
480 #if WX_NORMALIZED_PS_FONTS
481 "PostScript___", "${PostScriptTimes,$[weight],$[style]}",
482 #else
483 "PostScriptRoman__", "${PostScriptTimes,$[weight],$[style]}",
484 "PostScript___", "LucidaSans${PostScript$[weight]$[style]}",
485 #endif
486
487 "PostScriptTimesMedium", "",
488 "PostScriptTimesLight", "",
489 "PostScriptTimesBold", "Bold",
490
491 "PostScriptTimes__", "Times${PostScript$[weight]$[style]}",
492 "PostScriptTimesMediumStraight", "Times-Roman",
493 "PostScriptTimesLightStraight", "Times-Roman",
494 "PostScriptTimes_Slant", "Times-${PostScriptTimes$[weight]}Italic",
495 "PostScriptTimes_Italic", "Times-${PostScriptTimes$[weight]}Italic",
496
497 "PostScriptSwiss__", "Helvetica${PostScript$[weight]$[style]}",
498 "PostScriptModern__", "Courier${PostScript$[weight]$[style]}",
499
500 "PostScriptTeletype__", "${PostScriptModern,$[weight],$[style]}",
501
502 #if !WX_NORMALIZED_PS_FONTS
503 "PostScriptScript__", "Zapf-Chancery-MediumItalic",
504 #endif
505
506 "ScreenMedium", "medium",
507 "ScreenBold", "bold",
508 "ScreenLight", "light",
509 "ScreenStraight", "r",
510 "ScreenItalic", "i",
511 "ScreenSlant", "o",
512
513 "ScreenDefaultBase", "*-times",
514
515 "ScreenRomanBase", "*-times",
516 "ScreenDecorativeBase", "*-helvetica",
517 "ScreenModernBase", "*-courier",
518 "ScreenTeletypeBase", "*-lucidatypewriter",
519 "ScreenSwissBase", "*-lucida",
520 "ScreenScriptBase", "*-zapfchancery",
521
522 "ScreenStdSuffix", "-${Screen$[weight]}-${Screen$[style]}"
523 "-normal-*-*-%d-*-*-*-*-*-*",
524
525 "Screen___",
526 "-${ScreenDefaultBase}${ScreenStdSuffix}",
527 "ScreenRoman__",
528 "-${ScreenRomanBase}${ScreenStdSuffix}",
529 "ScreenDecorative__",
530 "-${ScreenDecorativeBase}${ScreenStdSuffix}",
531 "ScreenModern__",
532 "-${ScreenModernBase}${ScreenStdSuffix}",
533 "ScreenTeletype__",
534 "-${ScreenTeletypeBase}${ScreenStdSuffix}",
535 "ScreenSwiss__",
536 "-${ScreenSwissBase}${ScreenStdSuffix}",
537 "ScreenScript__",
538 "-${ScreenScriptBase}${ScreenStdSuffix}",
539 (char *) NULL
540 };
541
542 enum {wxWEIGHT_NORMAL, wxWEIGHT_BOLD, wxWEIGHT_LIGHT, wxNUM_WEIGHTS};
543 enum {wxSTYLE_NORMAL, wxSTYLE_ITALIC, wxSTYLE_SLANT, wxNUM_STYLES};
544
545 static int WCoordinate(int w)
546 {
547 switch (w)
548 {
549 case wxBOLD: return wxWEIGHT_BOLD;
550 case wxLIGHT: return wxWEIGHT_LIGHT;
551 case wxNORMAL:
552 default: return wxWEIGHT_NORMAL;
553 }
554 };
555
556 static int SCoordinate(int s)
557 {
558 switch (s)
559 {
560 case wxITALIC: return wxSTYLE_ITALIC;
561 case wxSLANT: return wxSTYLE_SLANT;
562 case wxNORMAL:
563 default: return wxSTYLE_NORMAL;
564 }
565 };
566
567 //-----------------------------------------------------------------------------
568 // wxSuffixMap
569 //-----------------------------------------------------------------------------
570
571 class wxSuffixMap
572 {
573 public:
574 ~wxSuffixMap();
575
576 inline char *GetName(int weight, int style)
577 {
578 return ( map [WCoordinate(weight)] [SCoordinate(style)] );
579 }
580
581 char *map[wxNUM_WEIGHTS][wxNUM_STYLES];
582 void Initialize(const char *, const char *);
583 };
584
585 static void SearchResource(const char *prefix, const char **names, int count, char **v)
586 {
587 int k, i, j;
588 char resource[1024], **defaults, *internal;
589
590 k = 1 << count;
591
592 *v = (char *) NULL;
593 internal = (char *) NULL;
594
595 for (i = 0; i < k; i++)
596 {
597 strcpy(resource, prefix);
598 for (j = 0; j < count; j++)
599 {
600 // upon failure to find a matching fontname
601 // in the default fonts above, we substitute more
602 // and more values by _ so that at last ScreenMyFontBoldNormal
603 // would turn into Screen___ and this will then get
604 // converted to -${ScreenDefaultBase}${ScreenStdSuffix}
605
606 if (!(i & (1 << j)))
607 strcat(resource, names[j]);
608 else
609 strcat(resource, "_");
610 }
611
612 // we previously search the Xt-resources here
613
614 if (!internal)
615 {
616 defaults = font_defaults;
617 while (*defaults)
618 {
619 if (!strcmp(*defaults, resource))
620 {
621 internal = defaults[1];
622 break;
623 }
624 defaults += 2;
625 }
626 }
627 }
628
629 if (internal)
630 {
631 if ((strcmp(internal,"-${ScreenDefaultBase}${ScreenStdSuffix}") == 0) &&
632 (strcmp(names[0], "Default") != 0))
633 {
634 // we did not find any font name in the standard list.
635 // this can (hopefully does) mean that someone supplied
636 // the facename in the wxFont constructor so we insert
637 // it here
638
639 strcpy( resource,"-*-" ); // any producer
640 strcat( resource, names[0] ); // facename
641 strcat( resource, "${ScreenStdSuffix}" ); // add size params later on
642 *v = copystring(resource);
643 }
644 else
645 {
646 *v = copystring(internal);
647 }
648 }
649 }
650
651 wxSuffixMap::~wxSuffixMap()
652 {
653 int k, j;
654
655 for (k = 0; k < wxNUM_WEIGHTS; ++k)
656 for (j = 0; j < wxNUM_STYLES; ++j)
657 if (map[k][j])
658 {
659 delete[] map[k][j];
660 map[k][j] = (char *) NULL;
661 }
662 }
663
664 void wxSuffixMap::Initialize(const char *resname, const char *devresname)
665 {
666 const char *weight, *style;
667 char *v;
668 int i, j, k;
669 const char *names[3];
670
671 for (k = 0; k < wxNUM_WEIGHTS; k++)
672 {
673 switch (k)
674 {
675 case wxWEIGHT_NORMAL: weight = "Medium"; break;
676 case wxWEIGHT_LIGHT: weight = "Light"; break;
677 case wxWEIGHT_BOLD:
678 default: weight = "Bold";
679 }
680 for (j = 0; j < wxNUM_STYLES; j++)
681 {
682 switch (j)
683 {
684 case wxSTYLE_NORMAL: style = "Straight"; break;
685 case wxSTYLE_ITALIC: style = "Italic"; break;
686 case wxSTYLE_SLANT:
687 default: style = "Slant";
688 }
689 names[0] = resname;
690 names[1] = weight;
691 names[2] = style;
692
693 SearchResource(devresname, names, 3, &v);
694
695 // Expand macros in the found string:
696 found:
697 int len, closer = 0, startpos = 0;
698
699 len = (v ? strlen(v) : 0);
700 for (i = 0; i < len; i++)
701 {
702 if (v[i] == '$' && ((v[i+1] == '[') || (v[i+1] == '{')))
703 {
704 startpos = i;
705 closer = (v[i+1] == '[') ? ']' : '}';
706 ++i;
707 }
708 else if (v[i] == closer)
709 {
710 int newstrlen;
711 const char *r = (char *) NULL; bool delete_r = FALSE;
712 char *name;
713
714 name = v + startpos + 2;
715 v[i] = 0;
716
717 if (closer == '}')
718 {
719 int i, count, len;
720 char **names;
721
722 for (i = 0, count = 1; name[i]; i++)
723 if (name[i] == ',')
724 count++;
725
726 len = i;
727
728 names = new char*[count];
729 names[0] = name;
730 for (i = 0, count = 1; i < len; i++)
731 if (name[i] == ',')
732 {
733 names[count++] = name + i + 1;
734 name[i] = 0;
735 }
736
737 SearchResource("", (const char **)names, count, (char **)&r);
738 delete_r = (r != 0);
739 delete[] names;
740
741 if (!r)
742 {
743 for (i = 0; i < len; i++)
744 if (!name[i])
745 name[i] = ',';
746 r = "";
747 wxLogError( "Bad resource name in font lookup." );
748 }
749 } else if (!strcmp(name, "weight")) {
750 r = weight;
751 } else if (!strcmp(name, "style")) {
752 r = style;
753 } else if (!strcmp(name, "family")) {
754 r = resname;
755 } else {
756 r = "";
757 wxLogError( "Bad font macro name." );
758 }
759
760 // add r to v
761 newstrlen = strlen(r);
762 char *naya = new char[startpos + newstrlen + len - i];
763 memcpy(naya, v, startpos);
764 memcpy(naya + startpos, r, newstrlen);
765 memcpy(naya + startpos + newstrlen, v + i + 1, len - i);
766 if (delete_r)
767 delete[] (char*)r;
768 delete[] v;
769 v = naya;
770
771 goto found;
772 }
773 }
774 // We have a final value:
775 map[k][j] = v;
776 }
777 }
778 }
779
780 //-----------------------------------------------------------------------------
781 // wxFontNameItem
782 //-----------------------------------------------------------------------------
783
784 class wxFontNameItem : public wxObject
785 {
786 DECLARE_DYNAMIC_CLASS(wxFontNameItem)
787 public:
788 wxFontNameItem(const char *name, int id, int family);
789 ~wxFontNameItem();
790
791 inline char* GetScreenName(int w, int s) {return screen.GetName(w, s);}
792 inline char* GetPostScriptName(int w, int s) {return printing.GetName(w, s);}
793 inline char* GetAFMName(int w, int s) {return afm.GetName(w, s);}
794 inline char* GetName() {return name;}
795 inline int GetFamily() {return family;}
796 inline int GetId() {return id;}
797 inline bool IsRoman() {return isroman;}
798 #if defined(__WXDEBUG__)
799 void Dump(ostream& str);
800 #endif
801
802 int id;
803 int family;
804 char *name;
805 wxSuffixMap screen, printing, afm;
806 bool isroman;
807 };
808
809 IMPLEMENT_ABSTRACT_CLASS(wxFontNameItem, wxObject)
810
811 wxFontNameItem::wxFontNameItem(const char *Name, int Id, int Family)
812 {
813 name = copystring(Name);
814 id = Id;
815 family = Family;
816
817 screen. Initialize(name, "Screen");
818 printing.Initialize(name, "PostScript");
819 afm. Initialize(name, "Afm");
820 }
821
822 wxFontNameItem::~wxFontNameItem()
823 {
824 if (name)
825 delete[] name;
826 name = (char *) NULL;
827 }
828
829 #if defined(__WXDEBUG__)
830 void wxFontNameItem::Dump(ostream& str)
831 {
832 str << "wxFontNameItem(" << name << ")";
833 }
834 #endif
835
836 //-----------------------------------------------------------------------------
837 // wxFontDirectory
838 //-----------------------------------------------------------------------------
839
840 IMPLEMENT_DYNAMIC_CLASS(wxFontNameDirectory, wxObject)
841
842 wxFontNameDirectory::wxFontNameDirectory()
843 {
844 table = new wxHashTable(wxKEY_INTEGER, 20);
845 nextFontId = -1;
846 }
847
848 wxFontNameDirectory::~wxFontNameDirectory()
849 {
850 // Cleanup wxFontNameItems allocated
851 table->BeginFind();
852 wxNode *node = table->Next();
853 while (node)
854 {
855 wxFontNameItem *item = (wxFontNameItem*)node->Data();
856 delete item;
857 node = table->Next();
858 }
859 delete table;
860 }
861
862 int wxFontNameDirectory::GetNewFontId()
863 {
864 return (nextFontId--);
865 }
866
867 void wxFontNameDirectory::Initialize()
868 {
869 Initialize(wxDEFAULT, wxDEFAULT, "Default");
870 Initialize(wxDECORATIVE, wxDECORATIVE, "Decorative");
871 Initialize(wxROMAN, wxROMAN, "Roman");
872 Initialize(wxMODERN, wxMODERN, "Modern");
873 Initialize(wxTELETYPE, wxTELETYPE, "Teletype");
874 Initialize(wxSWISS, wxSWISS, "Swiss");
875 Initialize(wxSCRIPT, wxSCRIPT, "Script");
876 }
877
878 void wxFontNameDirectory::Initialize(int fontid, int family, const char *resname)
879 {
880 char *fam, resource[256];
881
882 sprintf(resource, "Family%s", resname);
883 SearchResource((const char *)resource, (const char **) NULL, 0, (char **)&fam);
884
885 if (fam)
886 {
887 if (!strcmp(fam, "Default")) family = wxDEFAULT;
888 else if (!strcmp(fam, "Roman")) family = wxROMAN;
889 else if (!strcmp(fam, "Decorative")) family = wxDECORATIVE;
890 else if (!strcmp(fam, "Modern")) family = wxMODERN;
891 else if (!strcmp(fam, "Teletype")) family = wxTELETYPE;
892 else if (!strcmp(fam, "Swiss")) family = wxSWISS;
893 else if (!strcmp(fam, "Script")) family = wxSCRIPT;
894 delete[] fam; // free resource
895 }
896 table->Put(fontid, new wxFontNameItem(resname, fontid, family));
897 }
898
899 int wxFontNameDirectory::FindOrCreateFontId(const char *name, int family)
900 {
901 int id;
902
903 // font exists -> return id
904 if ( (id = GetFontId(name)) ) return id;
905
906 // create new font
907 Initialize(id=GetNewFontId(), family, name);
908 return id;
909 }
910
911 char *wxFontNameDirectory::GetScreenName(int fontid, int weight, int style)
912 {
913 wxFontNameItem *item = (wxFontNameItem*)table->Get(fontid); // find font
914 if (item)
915 return item->GetScreenName(weight, style);
916
917 // font does not exist
918 return (char *) NULL;
919 }
920
921 char *wxFontNameDirectory::GetPostScriptName(int fontid, int weight, int style)
922 {
923 wxFontNameItem *item = (wxFontNameItem*)table->Get(fontid); // find font
924 if (item)
925 return item->GetPostScriptName(weight, style);
926
927 // font does not exist
928 return (char *) NULL;
929 }
930
931 char *wxFontNameDirectory::GetAFMName(int fontid, int weight, int style)
932 {
933 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid); // find font
934 if (item)
935 return item->GetAFMName(weight, style);
936 // font does not exist
937 return (char *) NULL;
938 }
939
940 char *wxFontNameDirectory::GetFontName(int fontid)
941 {
942 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid); // find font
943 if (item)
944 return item->GetName();
945
946 // font does not exist
947 return (char *) NULL;
948 }
949
950 int wxFontNameDirectory::GetFontId(const char *name)
951 {
952 wxNode *node;
953
954 table->BeginFind();
955
956 while ( (node = table->Next()) )
957 {
958 wxFontNameItem *item = (wxFontNameItem*)node->Data();
959 if (!strcmp(name, item->name))
960 return item->id;
961 }
962
963 // font does not exist
964 return 0;
965 }
966
967 int wxFontNameDirectory::GetFamily(int fontid)
968 {
969 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid);
970
971 if (item)
972 return item->family;
973
974 // font does not exist
975 return wxDEFAULT;
976 }
977
978 #endif // 0