More Motif stuff
[wxWidgets.git] / src / motif / font.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: font.cpp
3 // Purpose: wxFont class
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "font.h"
14 #endif
15
16 #include "wx/defs.h"
17 #include "wx/string.h"
18 #include "wx/font.h"
19 #include "wx/gdicmn.h"
20 #include "wx/utils.h"
21
22 #include <X11/Xlib.h>
23
24 #if !USE_SHARED_LIBRARIES
25 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
26 #endif
27
28 wxFontRefData::wxFontRefData(): m_fontsByScale(wxKEY_INTEGER)
29 {
30 m_style = 0;
31 m_pointSize = 0;
32 m_family = 0;
33 m_style = 0;
34 m_weight = 0;
35 m_underlined = 0;
36 m_faceName = "";
37 }
38
39 wxFontRefData::wxFontRefData(const wxFontRefData& data): m_fontsByScale(wxKEY_INTEGER)
40 {
41 m_style = data.m_style;
42 m_pointSize = data.m_pointSize;
43 m_family = data.m_family;
44 m_style = data.m_style;
45 m_weight = data.m_weight;
46 m_underlined = data.m_underlined;
47 m_faceName = data.m_faceName;
48
49 // Don't have to copy actual fonts, because they'll be created
50 // on demand.
51 }
52
53 wxFontRefData::~wxFontRefData()
54 {
55 wxNode* node = m_fontsByScale.First();
56 while (node)
57 {
58 XFontStruct* fontStruct = (XFontStruct*) node->Data();
59 XFreeFont((Display*) wxGetDisplay, fontStruct);
60 node = node->Next();
61 }
62 m_fontsByScale.Clear();
63 }
64
65 wxFont::wxFont()
66 {
67 if ( wxTheFontList )
68 wxTheFontList->Append(this);
69 }
70
71 wxFont::wxFont(int pointSize, int family, int style, int weight, bool underlined, const wxString& faceName)
72 {
73 Create(pointSize, family, style, weight, underlined, faceName);
74
75 if ( wxTheFontList )
76 wxTheFontList->Append(this);
77 }
78
79 bool wxFont::Create(int pointSize, int family, int style, int weight, bool underlined, const wxString& faceName)
80 {
81 UnRef();
82 m_refData = new wxFontRefData;
83
84 M_FONTDATA->m_family = family;
85 M_FONTDATA->m_style = style;
86 M_FONTDATA->m_weight = weight;
87 M_FONTDATA->m_pointSize = pointSize;
88 M_FONTDATA->m_underlined = underlined;
89 M_FONTDATA->m_faceName = faceName;
90
91 RealizeResource();
92
93 return TRUE;
94 }
95
96 wxFont::~wxFont()
97 {
98 if (wxTheFontList)
99 wxTheFontList->DeleteObject(this);
100 }
101
102 bool wxFont::RealizeResource()
103 {
104 // TODO: create the font (if there is a native font object)
105 return FALSE;
106 }
107
108 void wxFont::Unshare()
109 {
110 // Don't change shared data
111 if (!m_refData)
112 {
113 m_refData = new wxFontRefData();
114 }
115 else
116 {
117 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
118 UnRef();
119 m_refData = ref;
120 }
121 }
122
123 void wxFont::SetPointSize(int pointSize)
124 {
125 Unshare();
126
127 M_FONTDATA->m_pointSize = pointSize;
128
129 RealizeResource();
130 }
131
132 void wxFont::SetFamily(int family)
133 {
134 Unshare();
135
136 M_FONTDATA->m_family = family;
137
138 RealizeResource();
139 }
140
141 void wxFont::SetStyle(int style)
142 {
143 Unshare();
144
145 M_FONTDATA->m_style = style;
146
147 RealizeResource();
148 }
149
150 void wxFont::SetWeight(int weight)
151 {
152 Unshare();
153
154 M_FONTDATA->m_weight = weight;
155
156 RealizeResource();
157 }
158
159 void wxFont::SetFaceName(const wxString& faceName)
160 {
161 Unshare();
162
163 M_FONTDATA->m_faceName = faceName;
164
165 RealizeResource();
166 }
167
168 void wxFont::SetUnderlined(bool underlined)
169 {
170 Unshare();
171
172 M_FONTDATA->m_underlined = underlined;
173
174 RealizeResource();
175 }
176
177 wxString wxFont::GetFamilyString() const
178 {
179 wxString fam("");
180 switch (GetFamily())
181 {
182 case wxDECORATIVE:
183 fam = "wxDECORATIVE";
184 break;
185 case wxROMAN:
186 fam = "wxROMAN";
187 break;
188 case wxSCRIPT:
189 fam = "wxSCRIPT";
190 break;
191 case wxSWISS:
192 fam = "wxSWISS";
193 break;
194 case wxMODERN:
195 fam = "wxMODERN";
196 break;
197 case wxTELETYPE:
198 fam = "wxTELETYPE";
199 break;
200 default:
201 fam = "wxDEFAULT";
202 break;
203 }
204 return fam;
205 }
206
207 /* New font system */
208 wxString wxFont::GetFaceName() const
209 {
210 wxString str("");
211 if (M_FONTDATA)
212 str = M_FONTDATA->m_faceName ;
213 return str;
214 }
215
216 wxString wxFont::GetStyleString() const
217 {
218 wxString styl("");
219 switch (GetStyle())
220 {
221 case wxITALIC:
222 styl = "wxITALIC";
223 break;
224 case wxSLANT:
225 styl = "wxSLANT";
226 break;
227 default:
228 styl = "wxNORMAL";
229 break;
230 }
231 return styl;
232 }
233
234 wxString wxFont::GetWeightString() const
235 {
236 wxString w("");
237 switch (GetWeight())
238 {
239 case wxBOLD:
240 w = "wxBOLD";
241 break;
242 case wxLIGHT:
243 w = "wxLIGHT";
244 break;
245 default:
246 w = "wxNORMAL";
247 break;
248 }
249 return w;
250 }
251
252 // Find an existing, or create a new, XFontStruct
253 // based on this wxFont and the given scale. Append the
254 // font to list in the private data for future reference.
255 WXFontStructPtr wxFont::FindOrCreateFontStruct(double scale)
256 {
257 if (!Ok())
258 return NULL;
259
260 long intScale = long(scale * 100.0 + 0.5); // key for fontlist
261 int pointSize = (M_FONTDATA->m_pointSize * 10 * intScale) / 100;
262
263 wxNode* node = M_FONTDATA->m_fontsByScale.Find(intScale);
264 if (node)
265 {
266 return (WXFontStructPtr) node->Data();
267 }
268
269 WXFontStructPtr font = LoadQueryFont(pointSize, M_FONTDATA->m_family,
270 M_FONTDATA->m_style, M_FONTDATA->m_weight, M_FONTDATA->m_underlined);
271
272 if (!font)
273 {
274 // search up and down by stepsize 10
275 int max_size = pointSize + 20 * (1 + (pointSize/180));
276 int min_size = pointSize - 20 * (1 + (pointSize/180));
277 int i;
278
279 // Search for smaller size (approx.)
280 for (i=pointSize-10; !font && i >= 10 && i >= min_size; i -= 10)
281 font = LoadQueryFont(i, M_FONTDATA->m_family, M_FONTDATA->m_style, M_FONTDATA->m_weight, M_FONTDATA->m_underlined);
282 // Search for larger size (approx.)
283 for (i=pointSize+10; !font && i <= max_size; i += 10)
284 font = LoadQueryFont(i, M_FONTDATA->m_family, M_FONTDATA->m_style, M_FONTDATA->m_weight, M_FONTDATA->m_underlined);
285 // Try default family
286 if (!font && M_FONTDATA->m_family != wxDEFAULT)
287 font = LoadQueryFont(pointSize, wxDEFAULT, M_FONTDATA->m_style,
288 M_FONTDATA->m_weight, M_FONTDATA->m_underlined);
289 // Bogus font
290 if (!font)
291 font = LoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
292 M_FONTDATA->m_underlined);
293 }
294 if (font)
295 {
296 M_FONTDATA->m_fontsByScale.Append(intScale, (wxObject*) font);
297 return (WXFontStructPtr) font;
298 }
299 return font;
300 }
301
302 WXFontStructPtr wxFont::LoadQueryFont(int pointSize, int family, int style,
303 int weight, bool underlined)
304 {
305 char *xfamily;
306 char *xstyle;
307 char *xweight;
308 switch (family)
309 {
310 case wxDECORATIVE: xfamily = "lucida";
311 break;
312 case wxROMAN: xfamily = "times";
313 break;
314 case wxMODERN: xfamily = "courier";
315 break;
316 case wxSWISS: xfamily = "lucida";
317 break;
318 case wxDEFAULT:
319 default: xfamily = "*";
320 }
321 switch (style)
322 {
323 case wxITALIC: xstyle = "i";
324 break;
325 case wxSLANT: xstyle = "o";
326 break;
327 case wxNORMAL: xstyle = "r";
328 break;
329 default: xstyle = "*";
330 break;
331 }
332 switch (weight)
333 {
334 case wxBOLD: xweight = "bold";
335 break;
336 case wxLIGHT:
337 case wxNORMAL: xweight = "medium";
338 break;
339 default: xweight = "*";
340 break;
341 }
342
343 sprintf(wxBuffer, "-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-*-*",
344 xfamily, xweight, xstyle, pointSize);
345
346 Display *dpy = (Display*) wxGetDisplay();
347 XFontStruct* font = XLoadQueryFont(dpy, wxBuffer);
348
349 return (WXFontStructPtr) font;
350 }