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