]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/font.cpp
Added wxRichTextTableBlock class to help with table UI operations
[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
6c9a19aa 5// Copyright: (c) 1998 Robert Roebling and Julian Smart
65571936 6// Licence: wxWindows licence
c801d85f
KB
7/////////////////////////////////////////////////////////////////////////////
8
0c5d3e1c
VZ
9// ============================================================================
10// declarations
11// ============================================================================
12
13// ----------------------------------------------------------------------------
14// headers
15// ----------------------------------------------------------------------------
16
14f355c2
VS
17// For compilers that support precompilation, includes "wx.h".
18#include "wx/wxprec.h"
19
c801d85f 20#include "wx/font.h"
e4db172a
WS
21
22#ifndef WX_PRECOMP
23 #include "wx/log.h"
de6185e2 24 #include "wx/utils.h"
9eddec69 25 #include "wx/settings.h"
dd05139a 26 #include "wx/gdicmn.h"
e4db172a
WS
27#endif
28
7beba2fc 29#include "wx/fontutil.h"
8636aed8 30#include "wx/tokenzr.h"
0c5d3e1c 31
9e691f46 32#include "wx/gtk/private.h"
83624f79 33
409d5a58
VZ
34// ----------------------------------------------------------------------------
35// constants
36// ----------------------------------------------------------------------------
37
38// the default size (in points) for the fonts
39static const int wxDEFAULT_FONT_SIZE = 12;
40
0c5d3e1c
VZ
41// ----------------------------------------------------------------------------
42// wxFontRefData
43// ----------------------------------------------------------------------------
44
8f884a0d 45class wxFontRefData : public wxGDIRefData
c801d85f 46{
8bbe427f 47public:
409d5a58
VZ
48 // from broken down font parameters, also default ctor
49 wxFontRefData(int size = -1,
0c14b6c3
FM
50 wxFontFamily family = wxFONTFAMILY_DEFAULT,
51 wxFontStyle style = wxFONTSTYLE_NORMAL,
52 wxFontWeight weight = wxFONTWEIGHT_NORMAL,
de6185e2 53 bool underlined = false,
c7a49742 54 bool strikethrough = false,
0c5d3e1c 55 const wxString& faceName = wxEmptyString,
7826e2dd 56 wxFontEncoding encoding = wxFONTENCODING_DEFAULT);
409d5a58 57
34be948f 58 wxFontRefData(const wxString& nativeFontInfoString);
409d5a58
VZ
59
60 // copy ctor
358fc25c 61 wxFontRefData( const wxFontRefData& data );
409d5a58 62
0c5d3e1c
VZ
63 virtual ~wxFontRefData();
64
409d5a58
VZ
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);
0c14b6c3
FM
68 void SetFamily(wxFontFamily family);
69 void SetStyle(wxFontStyle style);
70 void SetWeight(wxFontWeight weight);
409d5a58 71 void SetUnderlined(bool underlined);
c7a49742 72 void SetStrikethrough(bool strikethrough);
85ab460e 73 bool SetFaceName(const wxString& facename);
409d5a58
VZ
74 void SetEncoding(wxFontEncoding encoding);
75
011ba5ed
VZ
76 // and this one also modifies all the other font data fields
77 void SetNativeFontInfo(const wxNativeFontInfo& info);
78
0c5d3e1c
VZ
79protected:
80 // common part of all ctors
81 void Init(int pointSize,
0c14b6c3
FM
82 wxFontFamily family,
83 wxFontStyle style,
84 wxFontWeight weight,
0c5d3e1c 85 bool underlined,
c7a49742 86 bool strikethrough,
0c5d3e1c 87 const wxString& faceName,
7826e2dd 88 wxFontEncoding encoding);
0c5d3e1c 89
011ba5ed
VZ
90 // set all fields from (already initialized and valid) m_nativeFontInfo
91 void InitFromNative();
92
0c5d3e1c 93private:
a349dc10
VZ
94 // The native font info: basically a PangoFontDescription, plus
95 // 'underlined' and 'strikethrough' attributes not supported by Pango.
30764ab5 96 wxNativeFontInfo m_nativeFontInfo;
8bbe427f 97
f6bcfd97 98 friend class wxFont;
c801d85f
KB
99};
100
68c95704 101#define M_FONTDATA ((wxFontRefData*)m_refData)
873fd4af 102
0c5d3e1c 103// ----------------------------------------------------------------------------
cd9a673c 104// wxFontRefData
0c5d3e1c
VZ
105// ----------------------------------------------------------------------------
106
107void wxFontRefData::Init(int pointSize,
0c14b6c3
FM
108 wxFontFamily family,
109 wxFontStyle style,
110 wxFontWeight weight,
0c5d3e1c 111 bool underlined,
c7a49742 112 bool strikethrough,
0c5d3e1c 113 const wxString& faceName,
7ce58684 114 wxFontEncoding WXUNUSED(encoding))
8bbe427f 115{
6aea1e4a
FM
116 if (family == wxFONTFAMILY_DEFAULT)
117 family = wxFONTFAMILY_SWISS;
0c5d3e1c 118
46eed000
RR
119 // Create native font info
120 m_nativeFontInfo.description = pango_font_description_new();
121
011ba5ed 122 // And set its values
ecde8361 123 if (!faceName.empty())
2b5f62a0 124 {
7ce58684 125 pango_font_description_set_family( m_nativeFontInfo.description,
ecde8361 126 wxGTK_CONV_SYS(faceName) );
2b5f62a0
VZ
127 }
128 else
129 {
6aea1e4a 130 SetFamily(family);
46eed000 131 }
cd9a673c 132
ecde8361
FM
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 );
a349dc10
VZ
138 SetUnderlined( underlined );
139 SetStrikethrough( strikethrough );
358fc25c
RR
140}
141
011ba5ed 142void wxFontRefData::InitFromNative()
409d5a58 143{
db16cab4
RR
144 // Get native info
145 PangoFontDescription *desc = m_nativeFontInfo.description;
011ba5ed 146
b6b579bd
RR
147 // Pango sometimes needs to have a size
148 int pango_size = pango_font_description_get_size( desc );
149 if (pango_size == 0)
ecde8361 150 m_nativeFontInfo.SetPointSize(wxDEFAULT_FONT_SIZE);
409d5a58
VZ
151}
152
011ba5ed 153wxFontRefData::wxFontRefData( const wxFontRefData& data )
8f884a0d 154 : wxGDIRefData()
011ba5ed 155{
cd9a673c
RD
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());
011ba5ed
VZ
160}
161
0c14b6c3 162wxFontRefData::wxFontRefData(int size, wxFontFamily family, wxFontStyle style,
c7a49742 163 wxFontWeight weight, bool underlined, bool strikethrough,
011ba5ed
VZ
164 const wxString& faceName,
165 wxFontEncoding encoding)
166{
c7a49742 167 Init(size, family, style, weight, underlined, strikethrough, faceName, encoding);
011ba5ed
VZ
168}
169
34be948f 170wxFontRefData::wxFontRefData(const wxString& nativeFontInfoString)
8bbe427f 171{
34be948f 172 m_nativeFontInfo.FromString( nativeFontInfoString );
011ba5ed
VZ
173
174 InitFromNative();
175}
176
011ba5ed
VZ
177wxFontRefData::~wxFontRefData()
178{
0c5d3e1c 179}
c801d85f 180
0c5d3e1c 181// ----------------------------------------------------------------------------
409d5a58 182// wxFontRefData SetXXX()
0c5d3e1c 183// ----------------------------------------------------------------------------
c801d85f 184
409d5a58 185void wxFontRefData::SetPointSize(int pointSize)
c801d85f 186{
8a15e8ba 187 m_nativeFontInfo.SetPointSize(pointSize);
7826e2dd
VZ
188}
189
b5791cc7
FM
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
03647350 212 pango_font_description_set_absolute_size( m_nativeFontInfo.description,
b5791cc7
FM
213 pixelSize.GetHeight() * PANGO_SCALE );
214
215 return true;
216}
b5791cc7
FM
217*/
218
0c14b6c3 219void wxFontRefData::SetFamily(wxFontFamily family)
7826e2dd 220{
6aea1e4a 221 m_nativeFontInfo.SetFamily(family);
30764ab5
VZ
222}
223
0c14b6c3 224void wxFontRefData::SetStyle(wxFontStyle style)
c801d85f 225{
6aea1e4a 226 m_nativeFontInfo.SetStyle(style);
409d5a58 227}
7beba2fc 228
0c14b6c3 229void wxFontRefData::SetWeight(wxFontWeight weight)
409d5a58 230{
6aea1e4a 231 m_nativeFontInfo.SetWeight(weight);
409d5a58 232}
30764ab5 233
409d5a58
VZ
234void wxFontRefData::SetUnderlined(bool underlined)
235{
a349dc10 236 m_nativeFontInfo.SetUnderlined(underlined);
409d5a58 237}
30760ce7 238
c7a49742
VZ
239void wxFontRefData::SetStrikethrough(bool strikethrough)
240{
a349dc10 241 m_nativeFontInfo.SetStrikethrough(strikethrough);
c7a49742
VZ
242}
243
85ab460e 244bool wxFontRefData::SetFaceName(const wxString& facename)
409d5a58 245{
85ab460e 246 return m_nativeFontInfo.SetFaceName(facename);
409d5a58 247}
284b4c88 248
7ce58684 249void wxFontRefData::SetEncoding(wxFontEncoding WXUNUSED(encoding))
409d5a58 250{
7ce58684 251 // with GTK+ 2 Pango always uses UTF8 internally, we cannot change it
409d5a58 252}
284b4c88 253
011ba5ed
VZ
254void wxFontRefData::SetNativeFontInfo(const wxNativeFontInfo& info)
255{
011ba5ed
VZ
256 m_nativeFontInfo = info;
257
258 // set all the other font parameters from the native font info
259 InitFromNative();
260}
261
409d5a58
VZ
262// ----------------------------------------------------------------------------
263// wxFont creation
264// ----------------------------------------------------------------------------
36f210c8 265
409d5a58
VZ
266wxFont::wxFont(const wxNativeFontInfo& info)
267{
011ba5ed 268 Create( info.GetPointSize(),
db16cab4
RR
269 info.GetFamily(),
270 info.GetStyle(),
271 info.GetWeight(),
272 info.GetUnderlined(),
273 info.GetFaceName(),
274 info.GetEncoding() );
a349dc10
VZ
275
276 if ( info.GetStrikethrough() )
277 SetStrikethrough(true);
409d5a58
VZ
278}
279
b960795e 280wxFont::wxFont(const wxFontInfo& info)
0634700a 281{
b960795e
VZ
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);
0634700a
VZ
294}
295
409d5a58 296bool wxFont::Create( int pointSize,
b5791cc7
FM
297 wxFontFamily family,
298 wxFontStyle style,
299 wxFontWeight weight,
409d5a58
VZ
300 bool underlined,
301 const wxString& face,
b5791cc7 302 wxFontEncoding encoding )
409d5a58 303{
2b5f62a0
VZ
304 UnRef();
305
409d5a58 306 m_refData = new wxFontRefData(pointSize, family, style, weight,
c7a49742 307 underlined, false, face, encoding);
409d5a58 308
de6185e2 309 return true;
409d5a58
VZ
310}
311
312bool wxFont::Create(const wxString& fontname)
313{
314 // VZ: does this really happen?
315 if ( fontname.empty() )
36f210c8 316 {
409d5a58 317 *this = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
7beba2fc 318
de6185e2 319 return true;
36f210c8 320 }
409d5a58
VZ
321
322 m_refData = new wxFontRefData(fontname);
323
de6185e2 324 return true;
ff7b1510 325}
c801d85f 326
8bbe427f 327wxFont::~wxFont()
c801d85f 328{
ff7b1510 329}
c801d85f 330
0c5d3e1c
VZ
331// ----------------------------------------------------------------------------
332// accessors
333// ----------------------------------------------------------------------------
c801d85f 334
8bbe427f 335int wxFont::GetPointSize() const
c801d85f 336{
ecde8361 337 wxCHECK_MSG( IsOk(), 0, wxT("invalid font") );
8bbe427f 338
ecde8361 339 return M_FONTDATA->m_nativeFontInfo.GetPointSize();
ff7b1510 340}
c801d85f 341
8bbe427f 342wxString wxFont::GetFaceName() const
c801d85f 343{
ecde8361 344 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
8bbe427f 345
ecde8361 346 return M_FONTDATA->m_nativeFontInfo.GetFaceName();
ff7b1510 347}
c801d85f 348
59b7da02 349wxFontFamily wxFont::DoGetFamily() const
c801d85f 350{
6aea1e4a 351 return M_FONTDATA->m_nativeFontInfo.GetFamily();
ff7b1510 352}
c801d85f 353
0c14b6c3 354wxFontStyle wxFont::GetStyle() const
c801d85f 355{
ecde8361 356 wxCHECK_MSG( IsOk(), wxFONTSTYLE_MAX, wxT("invalid font") );
d84eb083 357
ecde8361 358 return M_FONTDATA->m_nativeFontInfo.GetStyle();
ff7b1510 359}
c801d85f 360
0c14b6c3 361wxFontWeight wxFont::GetWeight() const
c801d85f 362{
ecde8361 363 wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX, wxT("invalid font") );
8bbe427f 364
ecde8361 365 return M_FONTDATA->m_nativeFontInfo.GetWeight();
8bbe427f
VZ
366}
367
8bbe427f
VZ
368bool wxFont::GetUnderlined() const
369{
ecde8361 370 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
8bbe427f 371
a349dc10 372 return M_FONTDATA->m_nativeFontInfo.GetUnderlined();
ff7b1510 373}
c801d85f 374
c7a49742
VZ
375bool wxFont::GetStrikethrough() const
376{
377 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
378
a349dc10 379 return M_FONTDATA->m_nativeFontInfo.GetStrikethrough();
c7a49742
VZ
380}
381
0c5d3e1c 382wxFontEncoding wxFont::GetEncoding() const
358fc25c 383{
ecde8361 384 wxCHECK_MSG( IsOk(), wxFONTENCODING_SYSTEM, wxT("invalid font") );
0c5d3e1c 385
7ce58684
FM
386 return wxFONTENCODING_UTF8;
387 // Pango always uses UTF8... see also SetEncoding()
358fc25c
RR
388}
389
3bf5a59b 390const wxNativeFontInfo *wxFont::GetNativeFontInfo() const
30764ab5 391{
ecde8361 392 wxCHECK_MSG( IsOk(), NULL, wxT("invalid font") );
30764ab5 393
3bf5a59b 394 return &(M_FONTDATA->m_nativeFontInfo);
30764ab5
VZ
395}
396
53f6aab7
VZ
397bool wxFont::IsFixedWidth() const
398{
ecde8361 399 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
53f6aab7 400
53f6aab7
VZ
401 return wxFontBase::IsFixedWidth();
402}
30764ab5 403
0c5d3e1c
VZ
404// ----------------------------------------------------------------------------
405// change font attributes
406// ----------------------------------------------------------------------------
407
358fc25c
RR
408void wxFont::SetPointSize(int pointSize)
409{
fd7a7443 410 AllocExclusive();
011ba5ed 411
409d5a58 412 M_FONTDATA->SetPointSize(pointSize);
358fc25c
RR
413}
414
0c14b6c3 415void wxFont::SetFamily(wxFontFamily family)
358fc25c 416{
fd7a7443 417 AllocExclusive();
358fc25c 418
409d5a58 419 M_FONTDATA->SetFamily(family);
358fc25c
RR
420}
421
0c14b6c3 422void wxFont::SetStyle(wxFontStyle style)
358fc25c 423{
fd7a7443 424 AllocExclusive();
358fc25c 425
409d5a58 426 M_FONTDATA->SetStyle(style);
358fc25c
RR
427}
428
0c14b6c3 429void wxFont::SetWeight(wxFontWeight weight)
358fc25c 430{
fd7a7443 431 AllocExclusive();
358fc25c 432
409d5a58 433 M_FONTDATA->SetWeight(weight);
358fc25c
RR
434}
435
85ab460e 436bool wxFont::SetFaceName(const wxString& faceName)
358fc25c 437{
fd7a7443 438 AllocExclusive();
358fc25c 439
85ab460e
VZ
440 return M_FONTDATA->SetFaceName(faceName) &&
441 wxFontBase::SetFaceName(faceName);
358fc25c
RR
442}
443
444void wxFont::SetUnderlined(bool underlined)
445{
fd7a7443 446 AllocExclusive();
358fc25c 447
409d5a58 448 M_FONTDATA->SetUnderlined(underlined);
358fc25c
RR
449}
450
c7a49742
VZ
451void wxFont::SetStrikethrough(bool strikethrough)
452{
453 AllocExclusive();
454
455 M_FONTDATA->SetStrikethrough(strikethrough);
456}
457
0c5d3e1c
VZ
458void wxFont::SetEncoding(wxFontEncoding encoding)
459{
fd7a7443 460 AllocExclusive();
c801d85f 461
409d5a58 462 M_FONTDATA->SetEncoding(encoding);
30764ab5
VZ
463}
464
9045ad9d 465void wxFont::DoSetNativeFontInfo( const wxNativeFontInfo& info )
2b5f62a0 466{
fd7a7443 467 AllocExclusive();
2b5f62a0
VZ
468
469 M_FONTDATA->SetNativeFontInfo( info );
470}
471
8f884a0d 472wxGDIRefData* wxFont::CreateGDIRefData() const
fd7a7443
PC
473{
474 return new wxFontRefData;
475}
476
8f884a0d 477wxGDIRefData* wxFont::CloneGDIRefData(const wxGDIRefData* data) const
fd7a7443 478{
5c33522f 479 return new wxFontRefData(*static_cast<const wxFontRefData*>(data));
fd7a7443 480}
c7e99122 481
99f8cf22 482bool wxFont::GTKSetPangoAttrs(PangoLayout* layout) const
c7e99122
PC
483{
484 if (!IsOk() || !(GetUnderlined() || GetStrikethrough()))
485 return false;
486
487 PangoAttrList* attrs = pango_attr_list_new();
488 PangoAttribute* a;
489
99f8cf22 490 if (wx_pango_version_check(1,16,0))
c7e99122 491 {
99f8cf22
PC
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] == ' '))
c7e99122 503 {
99f8cf22
PC
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.
c7e99122
PC
517 a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614);
518 a->start_index = 0;
99f8cf22 519 a->end_index = 3;
c7e99122
PC
520 pango_attr_list_insert(attrs, a);
521
522 a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614);
99f8cf22
PC
523 a->start_index = n + 3;
524 a->end_index = n + 6;
c7e99122
PC
525 pango_attr_list_insert(attrs, a);
526 }
527 }
99f8cf22
PC
528 if (GetUnderlined())
529 {
530 a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
531 pango_attr_list_insert(attrs, a);
532 }
c7e99122
PC
533 if (GetStrikethrough())
534 {
535 a = pango_attr_strikethrough_new(true);
c7e99122
PC
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}