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