]>
Commit | Line | Data |
---|---|---|
c801d85f KB |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: font.cpp | |
3 | // Purpose: | |
4 | // Author: Robert Roebling | |
a81258be | 5 | // Id: $Id$ |
c801d85f | 6 | // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem |
8bbe427f | 7 | // Licence: wxWindows licence |
c801d85f KB |
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 | ||
a3622daa | 22 | extern wxFontNameDirectory *wxTheFontNameDirectory; |
c801d85f KB |
23 | |
24 | //----------------------------------------------------------------------------- | |
25 | // wxFont | |
26 | //----------------------------------------------------------------------------- | |
27 | ||
28 | class wxFontRefData: public wxObjectRefData | |
29 | { | |
8bbe427f VZ |
30 | public: |
31 | ||
32 | wxFontRefData(); | |
33 | ~wxFontRefData(); | |
34 | ||
c801d85f KB |
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; | |
8bbe427f | 41 | |
c801d85f KB |
42 | bool m_byXFontName; |
43 | GdkFont *m_font; | |
8bbe427f | 44 | |
c801d85f KB |
45 | friend wxFont; |
46 | }; | |
47 | ||
8bbe427f VZ |
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; | |
c67daf87 | 57 | m_faceName = (char *) NULL; |
8bbe427f VZ |
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 ); | |
ff7b1510 | 77 | } |
c801d85f KB |
78 | |
79 | //----------------------------------------------------------------------------- | |
80 | ||
81 | #define M_FONTDATA ((wxFontRefData *)m_refData) | |
82 | ||
83 | IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject) | |
84 | ||
8bbe427f | 85 | wxFont::wxFont() |
c801d85f | 86 | { |
8bbe427f | 87 | if (wxTheFontList) wxTheFontList->Append( this ); |
ff7b1510 | 88 | } |
c801d85f KB |
89 | |
90 | wxFont::wxFont( char *xFontName ) | |
91 | { | |
8bbe427f VZ |
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 ); | |
ff7b1510 | 98 | } |
c801d85f KB |
99 | |
100 | wxFont::wxFont(int PointSize, int FontIdOrFamily, int Style, int Weight, | |
8bbe427f VZ |
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 ); | |
ff7b1510 | 128 | } |
c801d85f | 129 | |
8bbe427f VZ |
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 ); | |
ff7b1510 | 144 | } |
c801d85f | 145 | |
8bbe427f VZ |
146 | wxFont::wxFont( const wxFont& font ) |
147 | { | |
148 | Ref( font ); | |
149 | ||
150 | if (wxTheFontList) wxTheFontList->Append( this ); | |
ff7b1510 | 151 | } |
c801d85f | 152 | |
8bbe427f | 153 | wxFont::~wxFont() |
c801d85f | 154 | { |
8bbe427f | 155 | if (wxTheFontList) wxTheFontList->DeleteObject( this ); |
ff7b1510 | 156 | } |
c801d85f | 157 | |
8bbe427f VZ |
158 | wxFont& wxFont::operator = ( const wxFont& font ) |
159 | { | |
160 | if (*this == font) return (*this); | |
161 | Ref( font ); | |
162 | return *this; | |
ff7b1510 | 163 | } |
c801d85f | 164 | |
8bbe427f VZ |
165 | bool wxFont::operator == ( const wxFont& font ) |
166 | { | |
167 | return m_refData == font.m_refData; | |
ff7b1510 | 168 | } |
c801d85f | 169 | |
8bbe427f VZ |
170 | bool wxFont::operator != ( const wxFont& font ) |
171 | { | |
172 | return m_refData != font.m_refData; | |
ff7b1510 | 173 | } |
c801d85f | 174 | |
d84eb083 | 175 | bool wxFont::Ok() const |
c801d85f | 176 | { |
8bbe427f | 177 | return (m_refData != NULL); |
ff7b1510 | 178 | } |
c801d85f | 179 | |
8bbe427f | 180 | int wxFont::GetPointSize() const |
c801d85f | 181 | { |
8bbe427f VZ |
182 | if (!Ok()) |
183 | { | |
184 | wxFAIL_MSG( "invalid font" ); | |
185 | return 0; | |
186 | } | |
187 | ||
188 | return M_FONTDATA->m_pointSize; | |
ff7b1510 | 189 | } |
c801d85f | 190 | |
8bbe427f | 191 | wxString wxFont::GetFaceString() const |
c801d85f | 192 | { |
8bbe427f VZ |
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; | |
ff7b1510 | 201 | } |
c801d85f | 202 | |
8bbe427f | 203 | wxString wxFont::GetFaceName() const |
c801d85f | 204 | { |
8bbe427f VZ |
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; | |
ff7b1510 | 213 | } |
c801d85f | 214 | |
8bbe427f | 215 | int wxFont::GetFamily() const |
c801d85f | 216 | { |
8bbe427f VZ |
217 | if (!Ok()) |
218 | { | |
219 | wxFAIL_MSG( "invalid font" ); | |
220 | return 0; | |
221 | } | |
222 | ||
223 | return M_FONTDATA->m_family; | |
ff7b1510 | 224 | } |
c801d85f | 225 | |
8bbe427f | 226 | wxString wxFont::GetFamilyString() const |
c801d85f | 227 | { |
8bbe427f VZ |
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 | ||
e55ad60e | 245 | return "wxDEFAULT"; |
ff7b1510 | 246 | } |
c801d85f | 247 | |
8bbe427f | 248 | int wxFont::GetFontId() const |
c801d85f | 249 | { |
8bbe427f VZ |
250 | if (!Ok()) |
251 | { | |
252 | wxFAIL_MSG( "invalid font" ); | |
253 | return 0; | |
254 | } | |
255 | ||
256 | return M_FONTDATA->m_fontId; // stub | |
ff7b1510 | 257 | } |
c801d85f | 258 | |
8bbe427f | 259 | int wxFont::GetStyle() const |
c801d85f | 260 | { |
8bbe427f VZ |
261 | if (!Ok()) |
262 | { | |
263 | wxFAIL_MSG( "invalid font" ); | |
264 | return 0; | |
265 | } | |
d84eb083 | 266 | |
8bbe427f | 267 | return M_FONTDATA->m_style; |
ff7b1510 | 268 | } |
c801d85f | 269 | |
8bbe427f | 270 | wxString wxFont::GetStyleString() const |
c801d85f | 271 | { |
8bbe427f VZ |
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 | } | |
d84eb083 | 285 | |
8bbe427f | 286 | return wxString("wxDEFAULT"); |
ff7b1510 | 287 | } |
c801d85f | 288 | |
8bbe427f | 289 | int wxFont::GetWeight() const |
c801d85f | 290 | { |
8bbe427f VZ |
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; | |
ff7b1510 | 328 | } |
c801d85f KB |
329 | |
330 | //----------------------------------------------------------------------------- | |
331 | // get internal representation of font | |
332 | //----------------------------------------------------------------------------- | |
333 | ||
334 | // local help function | |
335 | static GdkFont *wxLoadQueryNearestFont(int point_size, int fontid, | |
8bbe427f VZ |
336 | int style, int weight, |
337 | bool underlined); | |
c801d85f | 338 | |
c33c4050 | 339 | GdkFont *wxFont::GetInternalFont(float scale) const |
c801d85f | 340 | { |
8bbe427f VZ |
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; | |
ff7b1510 | 387 | } |
c801d85f KB |
388 | |
389 | //----------------------------------------------------------------------------- | |
390 | // local utilities to find a X font | |
391 | //----------------------------------------------------------------------------- | |
392 | ||
393 | static GdkFont *wxLoadQueryFont(int point_size, int fontid, int style, | |
8bbe427f | 394 | int weight, bool WXUNUSED(underlined)) |
c801d85f KB |
395 | { |
396 | char buffer[512]; | |
a3622daa | 397 | char *name = wxTheFontNameDirectory->GetScreenName( fontid, weight, style ); |
c801d85f KB |
398 | |
399 | if (!name) | |
8bbe427f | 400 | name = "-*-*-*-*-*-*-*-%d-*-*-*-*-*-*"; |
c801d85f KB |
401 | sprintf(buffer, name, point_size); |
402 | ||
403 | return gdk_font_load( buffer ); | |
404 | } | |
405 | ||
406 | static GdkFont *wxLoadQueryNearestFont(int point_size, int fontid, | |
8bbe427f VZ |
407 | int style, int weight, |
408 | bool underlined) | |
c801d85f KB |
409 | { |
410 | GdkFont *font; | |
411 | ||
412 | font = wxLoadQueryFont( point_size, fontid, style, weight, underlined ); | |
413 | ||
414 | if (!font) { | |
8bbe427f VZ |
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); | |
c801d85f KB |
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", | |
8bbe427f | 461 | |
c801d85f KB |
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", | |
8bbe427f | 484 | |
c801d85f KB |
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]}" | |
8bbe427f | 527 | "-normal-*-*-%d-*-*-*-*-*-*", |
c801d85f KB |
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}", | |
c67daf87 | 543 | (char *) NULL |
c801d85f KB |
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) { | |
8bbe427f VZ |
552 | case wxBOLD: return wxWEIGHT_BOLD; |
553 | case wxLIGHT: return wxWEIGHT_LIGHT; | |
554 | case wxNORMAL: | |
555 | default: return wxWEIGHT_NORMAL; | |
c801d85f | 556 | } |
ff7b1510 | 557 | }; |
c801d85f KB |
558 | |
559 | static int SCoordinate(int s) | |
560 | { | |
561 | switch (s) { | |
8bbe427f VZ |
562 | case wxITALIC: return wxSTYLE_ITALIC; |
563 | case wxSLANT: return wxSTYLE_SLANT; | |
564 | case wxNORMAL: | |
565 | default: return wxSTYLE_NORMAL; | |
c801d85f | 566 | } |
ff7b1510 | 567 | }; |
c801d85f KB |
568 | |
569 | //----------------------------------------------------------------------------- | |
570 | // wxSuffixMap | |
571 | //----------------------------------------------------------------------------- | |
572 | ||
573 | class wxSuffixMap { | |
574 | public: | |
8bbe427f | 575 | ~wxSuffixMap(); |
c801d85f KB |
576 | |
577 | inline char *GetName(int weight, int style) | |
578 | { | |
8bbe427f | 579 | return ( map [WCoordinate(weight)] [SCoordinate(style)] ); |
c801d85f KB |
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; | |
8bbe427f | 596 | |
c67daf87 UR |
597 | *v = (char *) NULL; |
598 | internal = (char *) NULL; | |
c801d85f KB |
599 | |
600 | for (i = 0; i < k; i++) { | |
8bbe427f VZ |
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 | } | |
c801d85f KB |
620 | } |
621 | if (internal) | |
8bbe427f | 622 | *v = copystring(internal); |
c801d85f KB |
623 | } |
624 | ||
8bbe427f | 625 | wxSuffixMap::~wxSuffixMap() |
c801d85f KB |
626 | { |
627 | int k, j; | |
628 | ||
629 | for (k = 0; k < wxNUM_WEIGHTS; ++k) | |
8bbe427f VZ |
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 | } | |
c801d85f KB |
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++) { | |
8bbe427f VZ |
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 | } | |
c801d85f KB |
739 | } |
740 | } | |
741 | ||
742 | //----------------------------------------------------------------------------- | |
743 | // wxFontNameItem | |
744 | //----------------------------------------------------------------------------- | |
745 | ||
746 | class wxFontNameItem : public wxObject { | |
8bbe427f | 747 | DECLARE_DYNAMIC_CLASS(wxFontNameItem) |
c801d85f | 748 | public: |
8bbe427f VZ |
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;} | |
ea57084d | 759 | #if defined(__WXDEBUG__) |
8bbe427f | 760 | void Dump(ostream& str); |
c801d85f KB |
761 | #endif |
762 | ||
8bbe427f VZ |
763 | int id; |
764 | int family; | |
765 | char *name; | |
766 | wxSuffixMap screen, printing, afm; | |
767 | bool isroman; | |
c801d85f KB |
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 | ||
8bbe427f | 783 | wxFontNameItem::~wxFontNameItem() |
c801d85f KB |
784 | { |
785 | if (name) | |
8bbe427f | 786 | delete[] name; |
c67daf87 | 787 | name = (char *) NULL; |
c801d85f KB |
788 | } |
789 | ||
ea57084d | 790 | #if defined(__WXDEBUG__) |
c801d85f KB |
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 | ||
8bbe427f | 803 | wxFontNameDirectory::wxFontNameDirectory() |
c801d85f KB |
804 | { |
805 | table = new wxHashTable(wxKEY_INTEGER, 20); | |
806 | nextFontId = -1; | |
c801d85f KB |
807 | } |
808 | ||
809 | wxFontNameDirectory::~wxFontNameDirectory() | |
810 | { | |
811 | // Cleanup wxFontNameItems allocated | |
812 | table->BeginFind(); | |
813 | wxNode *node = table->Next(); | |
814 | while (node) { | |
8bbe427f VZ |
815 | wxFontNameItem *item = (wxFontNameItem*)node->Data(); |
816 | delete item; | |
817 | node = table->Next(); | |
c801d85f KB |
818 | } |
819 | delete table; | |
820 | } | |
821 | ||
8bbe427f | 822 | int wxFontNameDirectory::GetNewFontId() |
c801d85f KB |
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]; | |
8bbe427f | 841 | |
c801d85f | 842 | sprintf(resource, "Family%s", resname); |
c67daf87 | 843 | SearchResource((const char *)resource, (const char **) NULL, 0, (char **)&fam); |
c801d85f | 844 | if (fam) { |
8bbe427f VZ |
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 | |
c801d85f KB |
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) | |
8bbe427f | 872 | return item->GetScreenName(weight, style); |
c801d85f | 873 | // font does not exist |
c67daf87 | 874 | return (char *) NULL; |
c801d85f KB |
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) | |
8bbe427f | 881 | return item->GetPostScriptName(weight, style); |
c801d85f | 882 | // font does not exist |
c67daf87 | 883 | return (char *) NULL; |
c801d85f KB |
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) | |
8bbe427f | 890 | return item->GetAFMName(weight, style); |
c801d85f | 891 | // font does not exist |
c67daf87 | 892 | return (char *) NULL; |
c801d85f KB |
893 | } |
894 | ||
895 | char *wxFontNameDirectory::GetFontName(int fontid) | |
896 | { | |
897 | wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid); // find font | |
898 | if (item) | |
8bbe427f | 899 | return item->GetName(); |
c801d85f | 900 | // font does not exist |
c67daf87 | 901 | return (char *) NULL; |
c801d85f KB |
902 | } |
903 | ||
904 | int wxFontNameDirectory::GetFontId(const char *name) | |
905 | { | |
906 | wxNode *node; | |
907 | ||
908 | table->BeginFind(); | |
909 | ||
910 | while ( (node = table->Next()) ) { | |
8bbe427f VZ |
911 | wxFontNameItem *item = (wxFontNameItem*)node->Data(); |
912 | if (!strcmp(name, item->name)) | |
913 | return item->id; | |
c801d85f KB |
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); | |
8bbe427f | 922 | |
c801d85f | 923 | if (item) |
8bbe427f | 924 | return item->family; |
c801d85f KB |
925 | // font does not exist |
926 | return wxDEFAULT; | |
927 | } |