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