]> git.saurik.com Git - wxWidgets.git/blame - src/motif/font.cpp
drawing optimization fix
[wxWidgets.git] / src / motif / font.cpp
CommitLineData
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
25IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
26#endif
27
f97c9854
JS
28wxXFont::wxXFont()
29{
30 m_fontStruct = (WXFontStructPtr) 0;
31 m_fontList = (WXFontList) 0;
32 m_display = (WXDisplay*) 0;
33 m_scale = 100;
34}
35
36wxXFont::~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
48wxFontRefData::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 59wxFontRefData::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
73wxFontRefData::~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
85wxFont::wxFont()
86{
87 if ( wxTheFontList )
88 wxTheFontList->Append(this);
89}
90
91wxFont::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
99bool 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
116wxFont::~wxFont()
117{
118 if (wxTheFontList)
119 wxTheFontList->DeleteObject(this);
120}
121
122bool wxFont::RealizeResource()
123{
124 // TODO: create the font (if there is a native font object)
125 return FALSE;
126}
127
128void 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
143void wxFont::SetPointSize(int pointSize)
144{
145 Unshare();
146
147 M_FONTDATA->m_pointSize = pointSize;
148
149 RealizeResource();
150}
151
152void wxFont::SetFamily(int family)
153{
154 Unshare();
155
156 M_FONTDATA->m_family = family;
157
158 RealizeResource();
159}
160
161void wxFont::SetStyle(int style)
162{
163 Unshare();
164
165 M_FONTDATA->m_style = style;
166
167 RealizeResource();
168}
169
170void wxFont::SetWeight(int weight)
171{
172 Unshare();
173
174 M_FONTDATA->m_weight = weight;
175
176 RealizeResource();
177}
178
179void wxFont::SetFaceName(const wxString& faceName)
180{
181 Unshare();
182
183 M_FONTDATA->m_faceName = faceName;
184
185 RealizeResource();
186}
187
188void wxFont::SetUnderlined(bool underlined)
189{
190 Unshare();
191
192 M_FONTDATA->m_underlined = underlined;
193
194 RealizeResource();
195}
196
197wxString 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 */
228wxString wxFont::GetFaceName() const
229{
230 wxString str("");
231 if (M_FONTDATA)
232 str = M_FONTDATA->m_faceName ;
233 return str;
234}
235
236wxString 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
254wxString 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 275wxXFont* 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
331WXFontStructPtr 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}