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