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