]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/font.cpp
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / src / gtk / font.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk/font.cpp
3// Purpose: wxFont for wxGTK
4// Author: Robert Roebling
5// Copyright: (c) 1998 Robert Roebling and Julian Smart
6// Licence: wxWindows licence
7/////////////////////////////////////////////////////////////////////////////
8
9// ============================================================================
10// declarations
11// ============================================================================
12
13// ----------------------------------------------------------------------------
14// headers
15// ----------------------------------------------------------------------------
16
17// For compilers that support precompilation, includes "wx.h".
18#include "wx/wxprec.h"
19
20#include "wx/font.h"
21
22#ifndef WX_PRECOMP
23 #include "wx/log.h"
24 #include "wx/utils.h"
25 #include "wx/settings.h"
26 #include "wx/gdicmn.h"
27#endif
28
29#include "wx/fontutil.h"
30#include "wx/tokenzr.h"
31
32#include "wx/gtk/private.h"
33
34// ----------------------------------------------------------------------------
35// constants
36// ----------------------------------------------------------------------------
37
38// the default size (in points) for the fonts
39static const int wxDEFAULT_FONT_SIZE = 12;
40
41// ----------------------------------------------------------------------------
42// wxFontRefData
43// ----------------------------------------------------------------------------
44
45class wxFontRefData : public wxGDIRefData
46{
47public:
48 // from broken down font parameters, also default ctor
49 wxFontRefData(int size = -1,
50 wxFontFamily family = wxFONTFAMILY_DEFAULT,
51 wxFontStyle style = wxFONTSTYLE_NORMAL,
52 wxFontWeight weight = wxFONTWEIGHT_NORMAL,
53 bool underlined = false,
54 bool strikethrough = false,
55 const wxString& faceName = wxEmptyString,
56 wxFontEncoding encoding = wxFONTENCODING_DEFAULT);
57
58 wxFontRefData(const wxString& nativeFontInfoString);
59
60 // copy ctor
61 wxFontRefData( const wxFontRefData& data );
62
63 virtual ~wxFontRefData();
64
65 // setters: all of them also take care to modify m_nativeFontInfo if we
66 // have it so as to not lose the information not carried by our fields
67 void SetPointSize(int pointSize);
68 void SetFamily(wxFontFamily family);
69 void SetStyle(wxFontStyle style);
70 void SetWeight(wxFontWeight weight);
71 void SetUnderlined(bool underlined);
72 void SetStrikethrough(bool strikethrough);
73 bool SetFaceName(const wxString& facename);
74 void SetEncoding(wxFontEncoding encoding);
75
76 // and this one also modifies all the other font data fields
77 void SetNativeFontInfo(const wxNativeFontInfo& info);
78
79protected:
80 // common part of all ctors
81 void Init(int pointSize,
82 wxFontFamily family,
83 wxFontStyle style,
84 wxFontWeight weight,
85 bool underlined,
86 bool strikethrough,
87 const wxString& faceName,
88 wxFontEncoding encoding);
89
90 // set all fields from (already initialized and valid) m_nativeFontInfo
91 void InitFromNative();
92
93private:
94 // The native font info: basically a PangoFontDescription, plus
95 // 'underlined' and 'strikethrough' attributes not supported by Pango.
96 wxNativeFontInfo m_nativeFontInfo;
97
98 friend class wxFont;
99};
100
101#define M_FONTDATA ((wxFontRefData*)m_refData)
102
103// ----------------------------------------------------------------------------
104// wxFontRefData
105// ----------------------------------------------------------------------------
106
107void wxFontRefData::Init(int pointSize,
108 wxFontFamily family,
109 wxFontStyle style,
110 wxFontWeight weight,
111 bool underlined,
112 bool strikethrough,
113 const wxString& faceName,
114 wxFontEncoding WXUNUSED(encoding))
115{
116 if (family == wxFONTFAMILY_DEFAULT)
117 family = wxFONTFAMILY_SWISS;
118
119 // Create native font info
120 m_nativeFontInfo.description = pango_font_description_new();
121
122 // And set its values
123 if (!faceName.empty())
124 {
125 pango_font_description_set_family( m_nativeFontInfo.description,
126 wxGTK_CONV_SYS(faceName) );
127 }
128 else
129 {
130 SetFamily(family);
131 }
132
133 SetStyle( style == wxDEFAULT ? wxFONTSTYLE_NORMAL : style );
134 SetPointSize( (pointSize == wxDEFAULT || pointSize == -1)
135 ? wxDEFAULT_FONT_SIZE
136 : pointSize );
137 SetWeight( weight == wxDEFAULT ? wxFONTWEIGHT_NORMAL : weight );
138 SetUnderlined( underlined );
139 SetStrikethrough( strikethrough );
140}
141
142void wxFontRefData::InitFromNative()
143{
144 // Get native info
145 PangoFontDescription *desc = m_nativeFontInfo.description;
146
147 // Pango sometimes needs to have a size
148 int pango_size = pango_font_description_get_size( desc );
149 if (pango_size == 0)
150 m_nativeFontInfo.SetPointSize(wxDEFAULT_FONT_SIZE);
151}
152
153wxFontRefData::wxFontRefData( const wxFontRefData& data )
154 : wxGDIRefData()
155{
156 // Forces a copy of the internal data. wxNativeFontInfo should probably
157 // have a copy ctor and assignment operator to fix this properly but that
158 // would break binary compatibility...
159 m_nativeFontInfo.FromString(data.m_nativeFontInfo.ToString());
160}
161
162wxFontRefData::wxFontRefData(int size, wxFontFamily family, wxFontStyle style,
163 wxFontWeight weight, bool underlined, bool strikethrough,
164 const wxString& faceName,
165 wxFontEncoding encoding)
166{
167 Init(size, family, style, weight, underlined, strikethrough, faceName, encoding);
168}
169
170wxFontRefData::wxFontRefData(const wxString& nativeFontInfoString)
171{
172 m_nativeFontInfo.FromString( nativeFontInfoString );
173
174 InitFromNative();
175}
176
177wxFontRefData::~wxFontRefData()
178{
179}
180
181// ----------------------------------------------------------------------------
182// wxFontRefData SetXXX()
183// ----------------------------------------------------------------------------
184
185void wxFontRefData::SetPointSize(int pointSize)
186{
187 m_nativeFontInfo.SetPointSize(pointSize);
188}
189
190/*
191 NOTE: disabled because pango_font_description_set_absolute_size() and
192 wxDC::GetCharHeight() do not mix well: setting with the former a pixel
193 size of "30" makes the latter return 36...
194 Besides, we need to return GetPointSize() a point size value even if
195 SetPixelSize() was used and this would require further changes
196 (and use of pango_font_description_get_size_is_absolute in some places).
197
198bool wxFontRefData::SetPixelSize(const wxSize& pixelSize)
199{
200 wxCHECK_MSG( pixelSize.GetWidth() >= 0 && pixelSize.GetHeight() > 0, false,
201 "Negative values for the pixel size or zero pixel height are not allowed" );
202
203 if (wx_pango_version_check(1,8,0) != NULL ||
204 pixelSize.GetWidth() != 0)
205 {
206 // NOTE: pango_font_description_set_absolute_size() only sets the font height;
207 // if the user set the pixel width of the font explicitly or the pango
208 // library is too old, we cannot proceed
209 return false;
210 }
211
212 pango_font_description_set_absolute_size( m_nativeFontInfo.description,
213 pixelSize.GetHeight() * PANGO_SCALE );
214
215 return true;
216}
217*/
218
219void wxFontRefData::SetFamily(wxFontFamily family)
220{
221 m_nativeFontInfo.SetFamily(family);
222}
223
224void wxFontRefData::SetStyle(wxFontStyle style)
225{
226 m_nativeFontInfo.SetStyle(style);
227}
228
229void wxFontRefData::SetWeight(wxFontWeight weight)
230{
231 m_nativeFontInfo.SetWeight(weight);
232}
233
234void wxFontRefData::SetUnderlined(bool underlined)
235{
236 m_nativeFontInfo.SetUnderlined(underlined);
237}
238
239void wxFontRefData::SetStrikethrough(bool strikethrough)
240{
241 m_nativeFontInfo.SetStrikethrough(strikethrough);
242}
243
244bool wxFontRefData::SetFaceName(const wxString& facename)
245{
246 return m_nativeFontInfo.SetFaceName(facename);
247}
248
249void wxFontRefData::SetEncoding(wxFontEncoding WXUNUSED(encoding))
250{
251 // with GTK+ 2 Pango always uses UTF8 internally, we cannot change it
252}
253
254void wxFontRefData::SetNativeFontInfo(const wxNativeFontInfo& info)
255{
256 m_nativeFontInfo = info;
257
258 // set all the other font parameters from the native font info
259 InitFromNative();
260}
261
262// ----------------------------------------------------------------------------
263// wxFont creation
264// ----------------------------------------------------------------------------
265
266wxFont::wxFont(const wxNativeFontInfo& info)
267{
268 Create( info.GetPointSize(),
269 info.GetFamily(),
270 info.GetStyle(),
271 info.GetWeight(),
272 info.GetUnderlined(),
273 info.GetFaceName(),
274 info.GetEncoding() );
275
276 if ( info.GetStrikethrough() )
277 SetStrikethrough(true);
278}
279
280wxFont::wxFont(const wxFontInfo& info)
281{
282 m_refData = new wxFontRefData(info.GetPointSize(),
283 info.GetFamily(),
284 info.GetStyle(),
285 info.GetWeight(),
286 info.IsUnderlined(),
287 info.IsStrikethrough(),
288 info.GetFaceName(),
289 info.GetEncoding());
290
291 wxSize pixelSize = info.GetPixelSize();
292 if ( pixelSize != wxDefaultSize )
293 SetPixelSize(pixelSize);
294}
295
296bool wxFont::Create( int pointSize,
297 wxFontFamily family,
298 wxFontStyle style,
299 wxFontWeight weight,
300 bool underlined,
301 const wxString& face,
302 wxFontEncoding encoding )
303{
304 UnRef();
305
306 m_refData = new wxFontRefData(pointSize, family, style, weight,
307 underlined, false, face, encoding);
308
309 return true;
310}
311
312bool wxFont::Create(const wxString& fontname)
313{
314 // VZ: does this really happen?
315 if ( fontname.empty() )
316 {
317 *this = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
318
319 return true;
320 }
321
322 m_refData = new wxFontRefData(fontname);
323
324 return true;
325}
326
327wxFont::~wxFont()
328{
329}
330
331// ----------------------------------------------------------------------------
332// accessors
333// ----------------------------------------------------------------------------
334
335int wxFont::GetPointSize() const
336{
337 wxCHECK_MSG( IsOk(), 0, wxT("invalid font") );
338
339 return M_FONTDATA->m_nativeFontInfo.GetPointSize();
340}
341
342wxString wxFont::GetFaceName() const
343{
344 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
345
346 return M_FONTDATA->m_nativeFontInfo.GetFaceName();
347}
348
349wxFontFamily wxFont::DoGetFamily() const
350{
351 return M_FONTDATA->m_nativeFontInfo.GetFamily();
352}
353
354wxFontStyle wxFont::GetStyle() const
355{
356 wxCHECK_MSG( IsOk(), wxFONTSTYLE_MAX, wxT("invalid font") );
357
358 return M_FONTDATA->m_nativeFontInfo.GetStyle();
359}
360
361wxFontWeight wxFont::GetWeight() const
362{
363 wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX, wxT("invalid font") );
364
365 return M_FONTDATA->m_nativeFontInfo.GetWeight();
366}
367
368bool wxFont::GetUnderlined() const
369{
370 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
371
372 return M_FONTDATA->m_nativeFontInfo.GetUnderlined();
373}
374
375bool wxFont::GetStrikethrough() const
376{
377 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
378
379 return M_FONTDATA->m_nativeFontInfo.GetStrikethrough();
380}
381
382wxFontEncoding wxFont::GetEncoding() const
383{
384 wxCHECK_MSG( IsOk(), wxFONTENCODING_SYSTEM, wxT("invalid font") );
385
386 return wxFONTENCODING_UTF8;
387 // Pango always uses UTF8... see also SetEncoding()
388}
389
390const wxNativeFontInfo *wxFont::GetNativeFontInfo() const
391{
392 wxCHECK_MSG( IsOk(), NULL, wxT("invalid font") );
393
394 return &(M_FONTDATA->m_nativeFontInfo);
395}
396
397bool wxFont::IsFixedWidth() const
398{
399 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
400
401 return wxFontBase::IsFixedWidth();
402}
403
404// ----------------------------------------------------------------------------
405// change font attributes
406// ----------------------------------------------------------------------------
407
408void wxFont::SetPointSize(int pointSize)
409{
410 AllocExclusive();
411
412 M_FONTDATA->SetPointSize(pointSize);
413}
414
415void wxFont::SetFamily(wxFontFamily family)
416{
417 AllocExclusive();
418
419 M_FONTDATA->SetFamily(family);
420}
421
422void wxFont::SetStyle(wxFontStyle style)
423{
424 AllocExclusive();
425
426 M_FONTDATA->SetStyle(style);
427}
428
429void wxFont::SetWeight(wxFontWeight weight)
430{
431 AllocExclusive();
432
433 M_FONTDATA->SetWeight(weight);
434}
435
436bool wxFont::SetFaceName(const wxString& faceName)
437{
438 AllocExclusive();
439
440 return M_FONTDATA->SetFaceName(faceName) &&
441 wxFontBase::SetFaceName(faceName);
442}
443
444void wxFont::SetUnderlined(bool underlined)
445{
446 AllocExclusive();
447
448 M_FONTDATA->SetUnderlined(underlined);
449}
450
451void wxFont::SetStrikethrough(bool strikethrough)
452{
453 AllocExclusive();
454
455 M_FONTDATA->SetStrikethrough(strikethrough);
456}
457
458void wxFont::SetEncoding(wxFontEncoding encoding)
459{
460 AllocExclusive();
461
462 M_FONTDATA->SetEncoding(encoding);
463}
464
465void wxFont::DoSetNativeFontInfo( const wxNativeFontInfo& info )
466{
467 AllocExclusive();
468
469 M_FONTDATA->SetNativeFontInfo( info );
470}
471
472wxGDIRefData* wxFont::CreateGDIRefData() const
473{
474 return new wxFontRefData;
475}
476
477wxGDIRefData* wxFont::CloneGDIRefData(const wxGDIRefData* data) const
478{
479 return new wxFontRefData(*static_cast<const wxFontRefData*>(data));
480}
481
482bool wxFont::GTKSetPangoAttrs(PangoLayout* layout) const
483{
484 if (!IsOk() || !(GetUnderlined() || GetStrikethrough()))
485 return false;
486
487 PangoAttrList* attrs = pango_attr_list_new();
488 PangoAttribute* a;
489
490 if (wx_pango_version_check(1,16,0))
491 {
492 // a PangoLayout which has leading/trailing spaces with underlined font
493 // is not correctly drawn by this pango version: Pango won't underline the spaces.
494 // This can be a problem; e.g. wxHTML rendering of underlined text relies on
495 // this behaviour. To workaround this problem, we use a special hack here
496 // suggested by pango maintainer Behdad Esfahbod: we prepend and append two
497 // empty space characters and give them a dummy colour attribute.
498 // This will force Pango to underline the leading/trailing spaces, too.
499
500 const char* text = pango_layout_get_text(layout);
501 const size_t n = strlen(text);
502 if ((n > 0 && text[0] == ' ') || (n > 1 && text[n - 1] == ' '))
503 {
504 wxCharBuffer buf(n + 6);
505 // copy the leading U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format
506 memcpy(buf.data(), "\342\200\214", 3);
507 // copy the user string
508 memcpy(buf.data() + 3, text, n);
509 // copy the trailing U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format
510 memcpy(buf.data() + 3 + n, "\342\200\214", 3);
511
512 pango_layout_set_text(layout, buf, n + 6);
513
514 // Add dummy attributes (use colour as it's invisible anyhow for 0
515 // width spaces) to ensure that the spaces in the beginning/end of the
516 // string are underlined too.
517 a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614);
518 a->start_index = 0;
519 a->end_index = 3;
520 pango_attr_list_insert(attrs, a);
521
522 a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614);
523 a->start_index = n + 3;
524 a->end_index = n + 6;
525 pango_attr_list_insert(attrs, a);
526 }
527 }
528 if (GetUnderlined())
529 {
530 a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
531 pango_attr_list_insert(attrs, a);
532 }
533 if (GetStrikethrough())
534 {
535 a = pango_attr_strikethrough_new(true);
536 pango_attr_list_insert(attrs, a);
537 }
538
539 pango_layout_set_attributes(layout, attrs);
540 pango_attr_list_unref(attrs);
541
542 return true;
543}