]>
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; | |
2d120f83 | 40 | |
f97c9854 | 41 | XmFontListFree (fontList); |
2d120f83 JS |
42 | |
43 | // TODO: why does freeing the font produce a segv??? | |
f97c9854 | 44 | // Note that XFreeFont wasn't called in wxWin 1.68 either. |
2d120f83 | 45 | // XFreeFont((Display*) m_display, fontStruct); |
f97c9854 JS |
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; | |
2d120f83 | 68 | |
dfc54541 JS |
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); | |
2d120f83 | 94 | |
4bb6408c JS |
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; | |
2d120f83 | 103 | |
4bb6408c JS |
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; | |
2d120f83 | 110 | |
4bb6408c | 111 | RealizeResource(); |
2d120f83 | 112 | |
4bb6408c JS |
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 | { | |
2d120f83 JS |
130 | // Don't change shared data |
131 | if (!m_refData) | |
4bb6408c | 132 | { |
2d120f83 JS |
133 | m_refData = new wxFontRefData(); |
134 | } | |
4bb6408c JS |
135 | else |
136 | { | |
2d120f83 JS |
137 | wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData); |
138 | UnRef(); | |
139 | m_refData = ref; | |
140 | } | |
4bb6408c JS |
141 | } |
142 | ||
143 | void wxFont::SetPointSize(int pointSize) | |
144 | { | |
145 | Unshare(); | |
2d120f83 | 146 | |
4bb6408c | 147 | M_FONTDATA->m_pointSize = pointSize; |
2d120f83 | 148 | |
4bb6408c JS |
149 | RealizeResource(); |
150 | } | |
151 | ||
152 | void wxFont::SetFamily(int family) | |
153 | { | |
154 | Unshare(); | |
2d120f83 | 155 | |
4bb6408c | 156 | M_FONTDATA->m_family = family; |
2d120f83 | 157 | |
4bb6408c JS |
158 | RealizeResource(); |
159 | } | |
160 | ||
161 | void wxFont::SetStyle(int style) | |
162 | { | |
163 | Unshare(); | |
2d120f83 | 164 | |
4bb6408c | 165 | M_FONTDATA->m_style = style; |
2d120f83 | 166 | |
4bb6408c JS |
167 | RealizeResource(); |
168 | } | |
169 | ||
170 | void wxFont::SetWeight(int weight) | |
171 | { | |
172 | Unshare(); | |
2d120f83 | 173 | |
4bb6408c | 174 | M_FONTDATA->m_weight = weight; |
2d120f83 | 175 | |
4bb6408c JS |
176 | RealizeResource(); |
177 | } | |
178 | ||
179 | void wxFont::SetFaceName(const wxString& faceName) | |
180 | { | |
181 | Unshare(); | |
2d120f83 | 182 | |
4bb6408c | 183 | M_FONTDATA->m_faceName = faceName; |
2d120f83 | 184 | |
4bb6408c JS |
185 | RealizeResource(); |
186 | } | |
187 | ||
188 | void wxFont::SetUnderlined(bool underlined) | |
189 | { | |
190 | Unshare(); | |
2d120f83 | 191 | |
4bb6408c | 192 | M_FONTDATA->m_underlined = underlined; |
2d120f83 | 193 | |
4bb6408c JS |
194 | RealizeResource(); |
195 | } | |
196 | ||
197 | wxString wxFont::GetFamilyString() const | |
198 | { | |
2d120f83 JS |
199 | wxString fam(""); |
200 | switch (GetFamily()) | |
201 | { | |
4bb6408c | 202 | case wxDECORATIVE: |
2d120f83 JS |
203 | fam = "wxDECORATIVE"; |
204 | break; | |
4bb6408c | 205 | case wxROMAN: |
2d120f83 JS |
206 | fam = "wxROMAN"; |
207 | break; | |
4bb6408c | 208 | case wxSCRIPT: |
2d120f83 JS |
209 | fam = "wxSCRIPT"; |
210 | break; | |
4bb6408c | 211 | case wxSWISS: |
2d120f83 JS |
212 | fam = "wxSWISS"; |
213 | break; | |
4bb6408c | 214 | case wxMODERN: |
2d120f83 JS |
215 | fam = "wxMODERN"; |
216 | break; | |
4bb6408c | 217 | case wxTELETYPE: |
2d120f83 JS |
218 | fam = "wxTELETYPE"; |
219 | break; | |
4bb6408c | 220 | default: |
2d120f83 JS |
221 | fam = "wxDEFAULT"; |
222 | break; | |
223 | } | |
224 | return fam; | |
4bb6408c JS |
225 | } |
226 | ||
227 | /* New font system */ | |
228 | wxString wxFont::GetFaceName() const | |
229 | { | |
230 | wxString str(""); | |
231 | if (M_FONTDATA) | |
2d120f83 | 232 | str = M_FONTDATA->m_faceName ; |
4bb6408c JS |
233 | return str; |
234 | } | |
235 | ||
236 | wxString wxFont::GetStyleString() const | |
237 | { | |
238 | wxString styl(""); | |
239 | switch (GetStyle()) | |
240 | { | |
2d120f83 JS |
241 | case wxITALIC: |
242 | styl = "wxITALIC"; | |
243 | break; | |
244 | case wxSLANT: | |
245 | styl = "wxSLANT"; | |
246 | break; | |
247 | default: | |
248 | styl = "wxNORMAL"; | |
249 | break; | |
4bb6408c JS |
250 | } |
251 | return styl; | |
252 | } | |
253 | ||
254 | wxString wxFont::GetWeightString() const | |
255 | { | |
256 | wxString w(""); | |
257 | switch (GetWeight()) | |
258 | { | |
2d120f83 JS |
259 | case wxBOLD: |
260 | w = "wxBOLD"; | |
261 | break; | |
262 | case wxLIGHT: | |
263 | w = "wxLIGHT"; | |
264 | break; | |
265 | default: | |
266 | w = "wxNORMAL"; | |
267 | break; | |
4bb6408c JS |
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 | 276 | { |
2d120f83 JS |
277 | if (!Ok()) |
278 | return (wxXFont*) NULL; | |
279 | ||
280 | long intScale = long(scale * 100.0 + 0.5); // key for wxXFont | |
281 | int pointSize = (M_FONTDATA->m_pointSize * 10 * intScale) / 100; | |
282 | ||
283 | wxNode* node = M_FONTDATA->m_fonts.First(); | |
284 | while (node) | |
285 | { | |
286 | wxXFont* f = (wxXFont*) node->Data(); | |
287 | if ((!display || (f->m_display == display)) && (f->m_scale == intScale)) | |
288 | return f; | |
289 | node = node->Next(); | |
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." ); |
2d120f83 JS |
317 | } |
318 | if (font) | |
319 | { | |
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; | |
327 | } | |
328 | return (wxXFont*) NULL; | |
dfc54541 JS |
329 | } |
330 | ||
331 | WXFontStructPtr wxFont::LoadQueryFont(int pointSize, int family, int style, | |
2d120f83 | 332 | int weight, bool underlined) const |
dfc54541 JS |
333 | { |
334 | char *xfamily; | |
335 | char *xstyle; | |
336 | char *xweight; | |
337 | switch (family) | |
338 | { | |
2d120f83 JS |
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 = "*"; | |
dfc54541 JS |
349 | } |
350 | switch (style) | |
351 | { | |
2d120f83 JS |
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; | |
dfc54541 JS |
360 | } |
361 | switch (weight) | |
362 | { | |
2d120f83 JS |
363 | case wxBOLD: xweight = "bold"; |
364 | break; | |
365 | case wxLIGHT: | |
366 | case wxNORMAL: xweight = "medium"; | |
367 | break; | |
368 | default: xweight = "*"; | |
369 | break; | |
dfc54541 | 370 | } |
2d120f83 | 371 | |
dfc54541 | 372 | sprintf(wxBuffer, "-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-*-*", |
2d120f83 JS |
373 | xfamily, xweight, xstyle, pointSize); |
374 | ||
dfc54541 JS |
375 | Display *dpy = (Display*) wxGetDisplay(); |
376 | XFontStruct* font = XLoadQueryFont(dpy, wxBuffer); | |
2d120f83 | 377 | |
dfc54541 JS |
378 | return (WXFontStructPtr) font; |
379 | } |