]>
Commit | Line | Data |
---|---|---|
4bb6408c JS |
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" | |
dfc54541 JS |
20 | #include "wx/utils.h" |
21 | ||
f97c9854 | 22 | #include <Xm/Xm.h> |
4bb6408c JS |
23 | |
24 | #if !USE_SHARED_LIBRARIES | |
25 | IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject) | |
26 | #endif | |
27 | ||
f97c9854 JS |
28 | wxXFont::wxXFont() |
29 | { | |
30 | m_fontStruct = (WXFontStructPtr) 0; | |
31 | m_fontList = (WXFontList) 0; | |
32 | m_display = (WXDisplay*) 0; | |
33 | m_scale = 100; | |
34 | } | |
35 | ||
36 | wxXFont::~wxXFont() | |
37 | { | |
38 | XFontStruct* fontStruct = (XFontStruct*) m_fontStruct; | |
39 | XmFontList fontList = (XmFontList) m_fontList; | |
40 | ||
41 | XmFontListFree (fontList); | |
42 | ||
43 | // TODO: why does freeing the font produce a segv??? | |
44 | // Note that XFreeFont wasn't called in wxWin 1.68 either. | |
45 | // XFreeFont((Display*) m_display, fontStruct); | |
46 | } | |
47 | ||
48 | wxFontRefData::wxFontRefData() | |
4bb6408c | 49 | { |
dfc54541 JS |
50 | m_style = 0; |
51 | m_pointSize = 0; | |
52 | m_family = 0; | |
53 | m_style = 0; | |
54 | m_weight = 0; | |
55 | m_underlined = 0; | |
56 | m_faceName = ""; | |
4bb6408c JS |
57 | } |
58 | ||
f97c9854 | 59 | wxFontRefData::wxFontRefData(const wxFontRefData& data) |
4bb6408c | 60 | { |
dfc54541 JS |
61 | m_style = data.m_style; |
62 | m_pointSize = data.m_pointSize; | |
63 | m_family = data.m_family; | |
64 | m_style = data.m_style; | |
65 | m_weight = data.m_weight; | |
66 | m_underlined = data.m_underlined; | |
67 | m_faceName = data.m_faceName; | |
68 | ||
69 | // Don't have to copy actual fonts, because they'll be created | |
70 | // on demand. | |
4bb6408c JS |
71 | } |
72 | ||
73 | wxFontRefData::~wxFontRefData() | |
74 | { | |
f97c9854 | 75 | wxNode* node = m_fonts.First(); |
dfc54541 JS |
76 | while (node) |
77 | { | |
f97c9854 JS |
78 | wxXFont* f = (wxXFont*) node->Data(); |
79 | delete f; | |
dfc54541 JS |
80 | node = node->Next(); |
81 | } | |
f97c9854 | 82 | m_fonts.Clear(); |
4bb6408c JS |
83 | } |
84 | ||
85 | wxFont::wxFont() | |
86 | { | |
87 | if ( wxTheFontList ) | |
88 | wxTheFontList->Append(this); | |
89 | } | |
90 | ||
91 | wxFont::wxFont(int pointSize, int family, int style, int weight, bool underlined, const wxString& faceName) | |
92 | { | |
93 | Create(pointSize, family, style, weight, underlined, faceName); | |
94 | ||
95 | if ( wxTheFontList ) | |
96 | wxTheFontList->Append(this); | |
97 | } | |
98 | ||
99 | bool wxFont::Create(int pointSize, int family, int style, int weight, bool underlined, const wxString& faceName) | |
100 | { | |
101 | UnRef(); | |
102 | m_refData = new wxFontRefData; | |
103 | ||
104 | M_FONTDATA->m_family = family; | |
105 | M_FONTDATA->m_style = style; | |
106 | M_FONTDATA->m_weight = weight; | |
107 | M_FONTDATA->m_pointSize = pointSize; | |
108 | M_FONTDATA->m_underlined = underlined; | |
109 | M_FONTDATA->m_faceName = faceName; | |
110 | ||
111 | RealizeResource(); | |
112 | ||
113 | return TRUE; | |
114 | } | |
115 | ||
116 | wxFont::~wxFont() | |
117 | { | |
118 | if (wxTheFontList) | |
119 | wxTheFontList->DeleteObject(this); | |
120 | } | |
121 | ||
122 | bool wxFont::RealizeResource() | |
123 | { | |
124 | // TODO: create the font (if there is a native font object) | |
125 | return FALSE; | |
126 | } | |
127 | ||
128 | void wxFont::Unshare() | |
129 | { | |
130 | // Don't change shared data | |
131 | if (!m_refData) | |
132 | { | |
133 | m_refData = new wxFontRefData(); | |
134 | } | |
135 | else | |
136 | { | |
137 | wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData); | |
138 | UnRef(); | |
139 | m_refData = ref; | |
140 | } | |
141 | } | |
142 | ||
143 | void wxFont::SetPointSize(int pointSize) | |
144 | { | |
145 | Unshare(); | |
146 | ||
147 | M_FONTDATA->m_pointSize = pointSize; | |
148 | ||
149 | RealizeResource(); | |
150 | } | |
151 | ||
152 | void wxFont::SetFamily(int family) | |
153 | { | |
154 | Unshare(); | |
155 | ||
156 | M_FONTDATA->m_family = family; | |
157 | ||
158 | RealizeResource(); | |
159 | } | |
160 | ||
161 | void wxFont::SetStyle(int style) | |
162 | { | |
163 | Unshare(); | |
164 | ||
165 | M_FONTDATA->m_style = style; | |
166 | ||
167 | RealizeResource(); | |
168 | } | |
169 | ||
170 | void wxFont::SetWeight(int weight) | |
171 | { | |
172 | Unshare(); | |
173 | ||
174 | M_FONTDATA->m_weight = weight; | |
175 | ||
176 | RealizeResource(); | |
177 | } | |
178 | ||
179 | void wxFont::SetFaceName(const wxString& faceName) | |
180 | { | |
181 | Unshare(); | |
182 | ||
183 | M_FONTDATA->m_faceName = faceName; | |
184 | ||
185 | RealizeResource(); | |
186 | } | |
187 | ||
188 | void wxFont::SetUnderlined(bool underlined) | |
189 | { | |
190 | Unshare(); | |
191 | ||
192 | M_FONTDATA->m_underlined = underlined; | |
193 | ||
194 | RealizeResource(); | |
195 | } | |
196 | ||
197 | wxString wxFont::GetFamilyString() const | |
198 | { | |
199 | wxString fam(""); | |
200 | switch (GetFamily()) | |
201 | { | |
202 | case wxDECORATIVE: | |
203 | fam = "wxDECORATIVE"; | |
204 | break; | |
205 | case wxROMAN: | |
206 | fam = "wxROMAN"; | |
207 | break; | |
208 | case wxSCRIPT: | |
209 | fam = "wxSCRIPT"; | |
210 | break; | |
211 | case wxSWISS: | |
212 | fam = "wxSWISS"; | |
213 | break; | |
214 | case wxMODERN: | |
215 | fam = "wxMODERN"; | |
216 | break; | |
217 | case wxTELETYPE: | |
218 | fam = "wxTELETYPE"; | |
219 | break; | |
220 | default: | |
221 | fam = "wxDEFAULT"; | |
222 | break; | |
223 | } | |
224 | return fam; | |
225 | } | |
226 | ||
227 | /* New font system */ | |
228 | wxString wxFont::GetFaceName() const | |
229 | { | |
230 | wxString str(""); | |
231 | if (M_FONTDATA) | |
232 | str = M_FONTDATA->m_faceName ; | |
233 | return str; | |
234 | } | |
235 | ||
236 | wxString wxFont::GetStyleString() const | |
237 | { | |
238 | wxString styl(""); | |
239 | switch (GetStyle()) | |
240 | { | |
241 | case wxITALIC: | |
242 | styl = "wxITALIC"; | |
243 | break; | |
244 | case wxSLANT: | |
245 | styl = "wxSLANT"; | |
246 | break; | |
247 | default: | |
248 | styl = "wxNORMAL"; | |
249 | break; | |
250 | } | |
251 | return styl; | |
252 | } | |
253 | ||
254 | wxString wxFont::GetWeightString() const | |
255 | { | |
256 | wxString w(""); | |
257 | switch (GetWeight()) | |
258 | { | |
259 | case wxBOLD: | |
260 | w = "wxBOLD"; | |
261 | break; | |
262 | case wxLIGHT: | |
263 | w = "wxLIGHT"; | |
264 | break; | |
265 | default: | |
266 | w = "wxNORMAL"; | |
267 | break; | |
268 | } | |
269 | return w; | |
270 | } | |
271 | ||
dfc54541 JS |
272 | // Find an existing, or create a new, XFontStruct |
273 | // based on this wxFont and the given scale. Append the | |
274 | // font to list in the private data for future reference. | |
f97c9854 | 275 | wxXFont* wxFont::GetInternalFont(double scale, WXDisplay* display) const |
dfc54541 JS |
276 | { |
277 | if (!Ok()) | |
f97c9854 | 278 | return (wxXFont*) NULL; |
dfc54541 | 279 | |
f97c9854 | 280 | long intScale = long(scale * 100.0 + 0.5); // key for wxXFont |
dfc54541 JS |
281 | int pointSize = (M_FONTDATA->m_pointSize * 10 * intScale) / 100; |
282 | ||
f97c9854 JS |
283 | wxNode* node = M_FONTDATA->m_fonts.First(); |
284 | while (node) | |
dfc54541 | 285 | { |
f97c9854 JS |
286 | wxXFont* f = (wxXFont*) node->Data(); |
287 | if ((!display || (f->m_display == display)) && (f->m_scale == intScale)) | |
288 | return f; | |
289 | node = node->Next(); | |
dfc54541 JS |
290 | } |
291 | ||
292 | WXFontStructPtr font = LoadQueryFont(pointSize, M_FONTDATA->m_family, | |
293 | M_FONTDATA->m_style, M_FONTDATA->m_weight, M_FONTDATA->m_underlined); | |
294 | ||
295 | if (!font) | |
296 | { | |
297 | // search up and down by stepsize 10 | |
298 | int max_size = pointSize + 20 * (1 + (pointSize/180)); | |
299 | int min_size = pointSize - 20 * (1 + (pointSize/180)); | |
300 | int i; | |
301 | ||
302 | // Search for smaller size (approx.) | |
303 | for (i=pointSize-10; !font && i >= 10 && i >= min_size; i -= 10) | |
304 | font = LoadQueryFont(i, M_FONTDATA->m_family, M_FONTDATA->m_style, M_FONTDATA->m_weight, M_FONTDATA->m_underlined); | |
305 | // Search for larger size (approx.) | |
306 | for (i=pointSize+10; !font && i <= max_size; i += 10) | |
307 | font = LoadQueryFont(i, M_FONTDATA->m_family, M_FONTDATA->m_style, M_FONTDATA->m_weight, M_FONTDATA->m_underlined); | |
308 | // Try default family | |
309 | if (!font && M_FONTDATA->m_family != wxDEFAULT) | |
310 | font = LoadQueryFont(pointSize, wxDEFAULT, M_FONTDATA->m_style, | |
311 | M_FONTDATA->m_weight, M_FONTDATA->m_underlined); | |
312 | // Bogus font | |
313 | if (!font) | |
314 | font = LoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL, | |
315 | M_FONTDATA->m_underlined); | |
e97f20a0 | 316 | wxASSERT_MSG( (font != (XFontStruct*) NULL), "Could not allocate even a default font -- something is wrong." ); |
dfc54541 JS |
317 | } |
318 | if (font) | |
319 | { | |
f97c9854 JS |
320 | wxXFont* f = new wxXFont; |
321 | f->m_fontStruct = font; | |
322 | f->m_display = ( display ? display : wxGetDisplay() ); | |
323 | f->m_scale = intScale; | |
324 | f->m_fontList = XmFontListCreate ((XFontStruct*) font, XmSTRING_DEFAULT_CHARSET); | |
325 | M_FONTDATA->m_fonts.Append(f); | |
326 | return f; | |
dfc54541 | 327 | } |
f97c9854 | 328 | return (wxXFont*) NULL; |
dfc54541 JS |
329 | } |
330 | ||
331 | WXFontStructPtr wxFont::LoadQueryFont(int pointSize, int family, int style, | |
f97c9854 | 332 | int weight, bool underlined) const |
dfc54541 JS |
333 | { |
334 | char *xfamily; | |
335 | char *xstyle; | |
336 | char *xweight; | |
337 | switch (family) | |
338 | { | |
339 | case wxDECORATIVE: xfamily = "lucida"; | |
340 | break; | |
341 | case wxROMAN: xfamily = "times"; | |
342 | break; | |
343 | case wxMODERN: xfamily = "courier"; | |
344 | break; | |
345 | case wxSWISS: xfamily = "lucida"; | |
346 | break; | |
347 | case wxDEFAULT: | |
348 | default: xfamily = "*"; | |
349 | } | |
350 | switch (style) | |
351 | { | |
352 | case wxITALIC: xstyle = "i"; | |
353 | break; | |
354 | case wxSLANT: xstyle = "o"; | |
355 | break; | |
356 | case wxNORMAL: xstyle = "r"; | |
357 | break; | |
358 | default: xstyle = "*"; | |
359 | break; | |
360 | } | |
361 | switch (weight) | |
362 | { | |
363 | case wxBOLD: xweight = "bold"; | |
364 | break; | |
365 | case wxLIGHT: | |
366 | case wxNORMAL: xweight = "medium"; | |
367 | break; | |
368 | default: xweight = "*"; | |
369 | break; | |
370 | } | |
371 | ||
372 | sprintf(wxBuffer, "-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-*-*", | |
373 | xfamily, xweight, xstyle, pointSize); | |
374 | ||
375 | Display *dpy = (Display*) wxGetDisplay(); | |
376 | XFontStruct* font = XLoadQueryFont(dpy, wxBuffer); | |
377 | ||
378 | return (WXFontStructPtr) font; | |
379 | } |