]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk1/font.cpp
1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
7 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "font.h"
19 //-----------------------------------------------------------------------------
21 //-----------------------------------------------------------------------------
23 static char *wx_font_family
[] = {
24 "wxDEFAULT", "wxDECORATIVE", "wxMODERN", "wxROMAN", "wxSCRIPT",
25 "wxSWISS", "wxTELETYPE",
28 static char *wx_font_style
[] = {
29 "wxDEFAULT", "wxNORMAL", "wxSLANT", "wxITALIC",
32 static char *wx_font_weight
[] = {
33 "wxDEFAULT", "wxNORMAL", "wxBOLD", "wxLIGHT",
36 extern wxFontNameDirectory
*wxTheFontNameDirectory
;
38 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
42 class wxFontRefData
: public wxObjectRefData
49 wxList m_scaled_xfonts
;
51 int m_family
, m_style
, m_weight
;
62 wxFontRefData::wxFontRefData(void) : m_scaled_xfonts(wxKEY_INTEGER
)
64 m_byXFontName
= FALSE
;
75 wxFontRefData::~wxFontRefData(void)
77 wxNode
*node
= m_scaled_xfonts
.First();
80 GdkFont
*font
= (GdkFont
*)node
->Data();
81 wxNode
*next
= node
->Next();
82 gdk_font_unref( font
);
90 if (m_font
) gdk_font_unref( m_font
);
93 //-----------------------------------------------------------------------------
95 #define M_FONTDATA ((wxFontRefData *)m_refData)
97 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
101 if (wxTheFontList
) wxTheFontList
->Append( this );
104 wxFont::wxFont( char *xFontName
)
106 if (!xFontName
) return;
108 m_refData
= new wxFontRefData();
110 M_FONTDATA
->m_byXFontName
= TRUE
;
111 M_FONTDATA
->m_font
= gdk_font_load( xFontName
);
114 wxFont::wxFont(int PointSize
, int FontIdOrFamily
, int Style
, int Weight
,
115 bool Underlined
, const char* Face
)
117 m_refData
= new wxFontRefData();
119 if ((M_FONTDATA
->m_faceName
= (Face
) ? copystring(Face
) : (char*)NULL
) )
121 M_FONTDATA
->m_fontId
= wxTheFontNameDirectory
->FindOrCreateFontId( Face
, FontIdOrFamily
);
122 M_FONTDATA
->m_family
= wxTheFontNameDirectory
->GetFamily( FontIdOrFamily
);
126 M_FONTDATA
->m_fontId
= FontIdOrFamily
;
127 M_FONTDATA
->m_family
= wxTheFontNameDirectory
->GetFamily( FontIdOrFamily
);
129 M_FONTDATA
->m_style
= Style
;
130 M_FONTDATA
->m_weight
= Weight
;
131 M_FONTDATA
->m_pointSize
= PointSize
;
132 M_FONTDATA
->m_underlined
= Underlined
;
134 if (wxTheFontList
) wxTheFontList
->Append( this );
137 wxFont::wxFont(int PointSize
, const char *Face
, int Family
, int Style
,
138 int Weight
, bool Underlined
)
140 m_refData
= new wxFontRefData();
142 M_FONTDATA
->m_fontId
= wxTheFontNameDirectory
->FindOrCreateFontId( Face
, Family
);
143 M_FONTDATA
->m_faceName
= (Face
) ? copystring(Face
) : (char*)NULL
;
144 M_FONTDATA
->m_family
= wxTheFontNameDirectory
->GetFamily( M_FONTDATA
->m_fontId
);
145 M_FONTDATA
->m_style
= Style
;
146 M_FONTDATA
->m_weight
= Weight
;
147 M_FONTDATA
->m_pointSize
= PointSize
;
148 M_FONTDATA
->m_underlined
= Underlined
;
150 if (wxTheFontList
) wxTheFontList
->Append( this );
153 wxFont::wxFont( const wxFont
& font
)
158 wxFont::wxFont( const wxFont
* font
)
161 if (font
) Ref( *font
);
164 wxFont::~wxFont(void)
166 if (wxTheFontList
) wxTheFontList
->DeleteObject( this );
169 wxFont
& wxFont::operator = ( const wxFont
& font
)
171 if (*this == font
) return (*this);
176 bool wxFont::operator == ( const wxFont
& font
)
178 return m_refData
== font
.m_refData
;
181 bool wxFont::operator != ( const wxFont
& font
)
183 return m_refData
!= font
.m_refData
;
188 return (m_refData
!= NULL
);
191 int wxFont::GetPointSize(void) const
193 return M_FONTDATA
->m_pointSize
;
196 wxString
wxFont::GetFaceString(void) const
198 wxString s
= wxTheFontNameDirectory
->GetFontName( M_FONTDATA
->m_fontId
);
202 wxString
wxFont::GetFaceName(void) const
204 wxString s
= wxTheFontNameDirectory
->GetFontName( M_FONTDATA
->m_fontId
);
208 int wxFont::GetFamily(void) const
210 return M_FONTDATA
->m_family
;
213 wxString
wxFont::GetFamilyString(void) const
215 wxString s
= wx_font_family
[M_FONTDATA
->m_family
];
219 int wxFont::GetFontId(void) const
221 return M_FONTDATA
->m_fontId
; // stub
224 int wxFont::GetStyle(void) const
226 return M_FONTDATA
->m_style
;
229 wxString
wxFont::GetStyleString(void) const
231 wxString s
= wx_font_style
[M_FONTDATA
->m_style
];
235 int wxFont::GetWeight(void) const
237 return M_FONTDATA
->m_weight
;
240 wxString
wxFont::GetWeightString(void) const
242 wxString s
= wx_font_weight
[M_FONTDATA
->m_weight
];
246 bool wxFont::GetUnderlined(void) const
248 return M_FONTDATA
->m_underlined
;
251 //-----------------------------------------------------------------------------
252 // get internal representation of font
253 //-----------------------------------------------------------------------------
255 // local help function
256 static GdkFont
*wxLoadQueryNearestFont(int point_size
, int fontid
,
257 int style
, int weight
,
260 GdkFont
*wxFont::GetInternalFont(float scale
) const
262 if (M_FONTDATA
->m_byXFontName
) return M_FONTDATA
->m_font
;
264 long int_scale
= long(scale
* 100.0 + 0.5); // key for fontlist
265 int point_scale
= (M_FONTDATA
->m_pointSize
* 10 * int_scale
) / 100;
266 GdkFont
*font
= NULL
;
268 wxNode
*node
= M_FONTDATA
->m_scaled_xfonts
.Find(int_scale
);
271 font
= (GdkFont
*)node
->Data();
275 font
= wxLoadQueryNearestFont( point_scale
, M_FONTDATA
->m_fontId
, M_FONTDATA
->m_style
,
276 M_FONTDATA
->m_weight
, M_FONTDATA
->m_underlined
);
277 M_FONTDATA
->m_scaled_xfonts
.Append( int_scale
, (wxObject
*)font
);
280 printf("could not load any font");
281 // wxError("could not load any font", "wxFont");
285 //-----------------------------------------------------------------------------
286 // local utilities to find a X font
287 //-----------------------------------------------------------------------------
289 static GdkFont
*wxLoadQueryFont(int point_size
, int fontid
, int style
,
290 int weight
, bool WXUNUSED(underlined
))
293 char *name
= wxTheFontNameDirectory
->GetScreenName( fontid
, weight
, style
);
296 name
= "-*-*-*-*-*-*-*-%d-*-*-*-*-*-*";
297 sprintf(buffer
, name
, point_size
);
299 return gdk_font_load( buffer
);
302 static GdkFont
*wxLoadQueryNearestFont(int point_size
, int fontid
,
303 int style
, int weight
,
308 font
= wxLoadQueryFont( point_size
, fontid
, style
, weight
, underlined
);
311 // search up and down by stepsize 10
312 int max_size
= point_size
+ 20 * (1 + (point_size
/180));
313 int min_size
= point_size
- 20 * (1 + (point_size
/180));
316 // Search for smaller size (approx.)
317 for (i
=point_size
-10; !font
&& i
>= 10 && i
>= min_size
; i
-= 10)
318 font
= wxLoadQueryFont(i
, fontid
, style
, weight
, underlined
);
319 // Search for larger size (approx.)
320 for (i
=point_size
+10; !font
&& i
<= max_size
; i
+= 10)
321 font
= wxLoadQueryFont(i
, fontid
, style
, weight
, underlined
);
322 // Try default family
323 if (!font
&& fontid
!= wxDEFAULT
)
324 font
= wxLoadQueryFont(point_size
, wxDEFAULT
, style
,
328 font
= wxLoadQueryFont(120, wxDEFAULT
, wxNORMAL
, wxNORMAL
,
334 //-----------------------------------------------------------------------------
335 // face names and index functions
336 //-----------------------------------------------------------------------------
338 static char *font_defaults
[] = {
339 "FamilyDefault", "Default",
340 "FamilyRoman", "Roman",
341 "FamilyDecorative", "Decorative",
342 "FamilyModern", "Modern",
343 "FamilyTeletype", "Teletype",
344 "FamilySwiss", "Swiss",
345 "FamilyScript", "Script",
351 "AfmItalic", "${AfmSlant}",
355 "AfmHelvetica", "Helv",
356 "AfmCourier", "Cour",
358 "Afm___", "${AfmTimes,$[weight],$[style]}",
360 "AfmTimes__", "${AfmTimes}${Afm$[weight]}${Afm$[style]}",
361 "AfmTimesMediumStraight", "${AfmTimes}${AfmRoman}",
362 "AfmTimesLightStraight", "${AfmTimes}${AfmRoman}",
363 "AfmTimes_Italic", "${AfmTimes}$[weight]${AfmItalic}",
364 "AfmTimes_Slant", "${AfmTimes}$[weight]${AfmItalic}",
366 "AfmSwiss__", "${AfmHelvetica}${Afm$[weight]}${Afm$[style]}",
367 "AfmModern__", "${AfmCourier}${Afm$[weight]}${Afm$[style]}",
369 "AfmTeletype__", "${AfmModern,$[weight],$[style]}",
371 "PostScriptMediumStraight", "",
372 "PostScriptMediumItalic", "-Oblique",
373 "PostScriptMediumSlant", "-Oblique",
374 "PostScriptLightStraight", "",
375 "PostScriptLightItalic", "-Oblique",
376 "PostScriptLightSlant", "-Oblique",
377 "PostScriptBoldStraight", "-Bold",
378 "PostScriptBoldItalic", "-BoldOblique",
379 "PostScriptBoldSlant", "-BoldOblique",
381 #if WX_NORMALIZED_PS_FONTS
382 "PostScript___", "${PostScriptTimes,$[weight],$[style]}",
384 "PostScriptRoman__", "${PostScriptTimes,$[weight],$[style]}",
385 "PostScript___", "LucidaSans${PostScript$[weight]$[style]}",
388 "PostScriptTimesMedium", "",
389 "PostScriptTimesLight", "",
390 "PostScriptTimesBold", "Bold",
392 "PostScriptTimes__", "Times${PostScript$[weight]$[style]}",
393 "PostScriptTimesMediumStraight", "Times-Roman",
394 "PostScriptTimesLightStraight", "Times-Roman",
395 "PostScriptTimes_Slant", "Times-${PostScriptTimes$[weight]}Italic",
396 "PostScriptTimes_Italic", "Times-${PostScriptTimes$[weight]}Italic",
398 "PostScriptSwiss__", "Helvetica${PostScript$[weight]$[style]}",
399 "PostScriptModern__", "Courier${PostScript$[weight]$[style]}",
401 "PostScriptTeletype__", "${PostScriptModern,$[weight],$[style]}",
403 #if !WX_NORMALIZED_PS_FONTS
404 "PostScriptScript__", "Zapf-Chancery-MediumItalic",
407 "ScreenMedium", "medium",
408 "ScreenBold", "bold",
409 "ScreenLight", "light",
410 "ScreenStraight", "r",
414 "ScreenDefaultBase", "misc-fixed",
415 "ScreenRomanBase", "*-times",
416 "ScreenDecorativeBase", "*-helvetica",
417 "ScreenModernBase", "*-courier",
418 "ScreenTeletypeBase", "*-lucidatypewriter",
419 "ScreenSwissBase", "*-lucida",
420 "ScreenScriptBase", "*-zapfchancery",
422 "ScreenStdSuffix", "-${Screen$[weight]}-${Screen$[style]}"
423 "-normal-*-*-%d-*-*-*-*-*-*",
426 "-${ScreenDefaultBase}${ScreenStdSuffix}",
428 "-${ScreenRomanBase}${ScreenStdSuffix}",
429 "ScreenDecorative__",
430 "-${ScreenDecorativeBase}${ScreenStdSuffix}",
432 "-${ScreenModernBase}${ScreenStdSuffix}",
434 "-${ScreenTeletypeBase}${ScreenStdSuffix}",
436 "-${ScreenSwissBase}${ScreenStdSuffix}",
438 "-${ScreenScriptBase}${ScreenStdSuffix}",
442 enum {wxWEIGHT_NORMAL
, wxWEIGHT_BOLD
, wxWEIGHT_LIGHT
, wxNUM_WEIGHTS
};
443 enum {wxSTYLE_NORMAL
, wxSTYLE_ITALIC
, wxSTYLE_SLANT
, wxNUM_STYLES
};
445 static int WCoordinate(int w
)
448 case wxBOLD
: return wxWEIGHT_BOLD
;
449 case wxLIGHT
: return wxWEIGHT_LIGHT
;
451 default: return wxWEIGHT_NORMAL
;
455 static int SCoordinate(int s
)
458 case wxITALIC
: return wxSTYLE_ITALIC
;
459 case wxSLANT
: return wxSTYLE_SLANT
;
461 default: return wxSTYLE_NORMAL
;
465 //-----------------------------------------------------------------------------
467 //-----------------------------------------------------------------------------
473 inline char *GetName(int weight
, int style
)
475 return ( map
[WCoordinate(weight
)] [SCoordinate(style
)] );
478 char *map
[wxNUM_WEIGHTS
][wxNUM_STYLES
];
479 void Initialize(const char *, const char *);
483 #define wxGetResource(a, b, c) 0
486 static void SearchResource(const char *prefix
, const char **names
, int count
, char **v
)
489 char resource
[1024], **defaults
, *internal
;
496 for (i
= 0; i
< k
; i
++) {
497 strcpy(resource
, prefix
);
498 for (j
= 0; j
< count
; j
++) {
500 strcat(resource
, names
[j
]);
502 strcat(resource
, "_");
504 if (wxGetResource(wxAPP_CLASS
, (char *)resource
, v
))
507 defaults
= font_defaults
;
509 if (!strcmp(*defaults
, resource
)) {
510 internal
= defaults
[1];
518 *v
= copystring(internal
);
521 wxSuffixMap::~wxSuffixMap(void)
525 for (k
= 0; k
< wxNUM_WEIGHTS
; ++k
)
526 for (j
= 0; j
< wxNUM_STYLES
; ++j
)
533 void wxSuffixMap::Initialize(const char *resname
, const char *devresname
)
535 const char *weight
, *style
;
538 const char *names
[3];
540 for (k
= 0; k
< wxNUM_WEIGHTS
; k
++) {
542 case wxWEIGHT_NORMAL
: weight
= "Medium"; break;
543 case wxWEIGHT_LIGHT
: weight
= "Light"; break;
545 default: weight
= "Bold";
547 for (j
= 0; j
< wxNUM_STYLES
; j
++) {
549 case wxSTYLE_NORMAL
: style
= "Straight"; break;
550 case wxSTYLE_ITALIC
: style
= "Italic"; break;
552 default: style
= "Slant";
558 SearchResource(devresname
, names
, 3, &v
);
560 /* Expand macros in the found string: */
562 int len
, closer
= 0, startpos
= 0;
564 len
= (v
? strlen(v
) : 0);
565 for (i
= 0; i
< len
; i
++) {
566 if (v
[i
] == '$' && ((v
[i
+1] == '[') || (v
[i
+1] == '{'))) {
568 closer
= (v
[i
+1] == '[') ? ']' : '}';
570 } else if (v
[i
] == closer
) {
572 const char *r
= NULL
; bool delete_r
= FALSE
;
575 name
= v
+ startpos
+ 2;
582 for (i
= 0, count
= 1; name
[i
]; i
++)
588 names
= new char*[count
];
590 for (i
= 0, count
= 1; i
< len
; i
++)
591 if (name
[i
] == ',') {
592 names
[count
++] = name
+ i
+ 1;
596 SearchResource("", (const char **)names
, count
, (char **)&r
);
601 for (i
= 0; i
< len
; i
++)
605 printf("Bad resource name \"%s\" in font lookup\n", name
);
607 } else if (!strcmp(name
, "weight")) {
609 } else if (!strcmp(name
, "style")) {
611 } else if (!strcmp(name
, "family")) {
615 printf("Bad font macro name \"%s\"\n", name
);
619 newstrlen
= strlen(r
);
620 char *naya
= new char[startpos
+ newstrlen
+ len
- i
];
621 memcpy(naya
, v
, startpos
);
622 memcpy(naya
+ startpos
, r
, newstrlen
);
623 memcpy(naya
+ startpos
+ newstrlen
, v
+ i
+ 1, len
- i
);
632 /* We have a final value: */
638 //-----------------------------------------------------------------------------
640 //-----------------------------------------------------------------------------
642 class wxFontNameItem
: public wxObject
{
643 DECLARE_DYNAMIC_CLASS(wxFontNameItem
)
645 wxFontNameItem(const char *name
, int id
, int family
);
648 inline char* GetScreenName(int w
, int s
) {return screen
.GetName(w
, s
);}
649 inline char* GetPostScriptName(int w
, int s
) {return printing
.GetName(w
, s
);}
650 inline char* GetAFMName(int w
, int s
) {return afm
.GetName(w
, s
);}
651 inline char* GetName(void) {return name
;}
652 inline int GetFamily(void) {return family
;}
653 inline int GetId(void) {return id
;}
654 inline bool IsRoman(void) {return isroman
;}
656 void Dump(ostream
& str
);
662 wxSuffixMap screen
, printing
, afm
;
666 IMPLEMENT_ABSTRACT_CLASS(wxFontNameItem
, wxObject
)
668 wxFontNameItem::wxFontNameItem(const char *Name
, int Id
, int Family
)
670 name
= copystring(Name
);
674 screen
. Initialize(name
, "Screen");
675 printing
.Initialize(name
, "PostScript");
676 afm
. Initialize(name
, "Afm");
679 wxFontNameItem::~wxFontNameItem(void)
687 void wxFontNameItem::Dump(ostream
& str
)
689 str
<< "wxFontNameItem(" << name
<< ")";
693 //-----------------------------------------------------------------------------
695 //-----------------------------------------------------------------------------
697 IMPLEMENT_DYNAMIC_CLASS(wxFontNameDirectory
, wxObject
)
699 wxFontNameDirectory::wxFontNameDirectory(void)
701 table
= new wxHashTable(wxKEY_INTEGER
, 20);
705 wxFontNameDirectory::~wxFontNameDirectory()
707 // Cleanup wxFontNameItems allocated
709 wxNode
*node
= table
->Next();
711 wxFontNameItem
*item
= (wxFontNameItem
*)node
->Data();
713 node
= table
->Next();
718 int wxFontNameDirectory::GetNewFontId(void)
720 return (nextFontId
--);
723 void wxFontNameDirectory::Initialize()
725 Initialize(wxDEFAULT
, wxDEFAULT
, "Default");
726 Initialize(wxDECORATIVE
, wxDECORATIVE
, "Decorative");
727 Initialize(wxROMAN
, wxROMAN
, "Roman");
728 Initialize(wxMODERN
, wxMODERN
, "Modern");
729 Initialize(wxTELETYPE
, wxTELETYPE
, "Teletype");
730 Initialize(wxSWISS
, wxSWISS
, "Swiss");
731 Initialize(wxSCRIPT
, wxSCRIPT
, "Script");
734 void wxFontNameDirectory::Initialize(int fontid
, int family
, const char *resname
)
736 char *fam
, resource
[256];
738 sprintf(resource
, "Family%s", resname
);
739 SearchResource((const char *)resource
, NULL
, 0, (char **)&fam
);
741 if (!strcmp(fam
, "Default")) family
= wxDEFAULT
;
742 else if (!strcmp(fam
, "Roman")) family
= wxROMAN
;
743 else if (!strcmp(fam
, "Decorative")) family
= wxDECORATIVE
;
744 else if (!strcmp(fam
, "Modern")) family
= wxMODERN
;
745 else if (!strcmp(fam
, "Teletype")) family
= wxTELETYPE
;
746 else if (!strcmp(fam
, "Swiss")) family
= wxSWISS
;
747 else if (!strcmp(fam
, "Script")) family
= wxSCRIPT
;
748 delete[] fam
; // free resource
750 table
->Put(fontid
, new wxFontNameItem(resname
, fontid
, family
));
753 int wxFontNameDirectory::FindOrCreateFontId(const char *name
, int family
)
757 // font exists -> return id
758 if ( (id
= GetFontId(name
)) ) return id
;
760 Initialize(id
=GetNewFontId(), family
, name
);
764 char *wxFontNameDirectory::GetScreenName(int fontid
, int weight
, int style
)
766 wxFontNameItem
*item
= (wxFontNameItem
*)table
->Get(fontid
); // find font
768 return item
->GetScreenName(weight
, style
);
769 // font does not exist
773 char *wxFontNameDirectory::GetPostScriptName(int fontid
, int weight
, int style
)
775 wxFontNameItem
*item
= (wxFontNameItem
*)table
->Get(fontid
); // find font
777 return item
->GetPostScriptName(weight
, style
);
778 // font does not exist
782 char *wxFontNameDirectory::GetAFMName(int fontid
, int weight
, int style
)
784 wxFontNameItem
*item
= (wxFontNameItem
*)table
->Get(fontid
); // find font
786 return item
->GetAFMName(weight
, style
);
787 // font does not exist
791 char *wxFontNameDirectory::GetFontName(int fontid
)
793 wxFontNameItem
*item
= (wxFontNameItem
*)table
->Get(fontid
); // find font
795 return item
->GetName();
796 // font does not exist
800 int wxFontNameDirectory::GetFontId(const char *name
)
806 while ( (node
= table
->Next()) ) {
807 wxFontNameItem
*item
= (wxFontNameItem
*)node
->Data();
808 if (!strcmp(name
, item
->name
))
811 // font does not exist
815 int wxFontNameDirectory::GetFamily(int fontid
)
817 wxFontNameItem
*item
= (wxFontNameItem
*)table
->Get(fontid
);
821 // font does not exist