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