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