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