fix setting background color in wxGTK3 with themes which use background images or...
[wxWidgets.git] / src / gtk / textmeasure.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/textmeasure.cpp
3 // Purpose: wxTextMeasure implementation for wxGTK
4 // Author: Manuel Martin
5 // Created: 2012-10-05
6 // RCS-ID: $Id:
7 // Copyright: (c) 1997-2012 wxWidgets team
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifndef WX_PRECOMP
23 #include "wx/window.h"
24 #include "wx/log.h"
25 #endif //WX_PRECOMP
26
27 #include "wx/private/textmeasure.h"
28
29 #include "wx/fontutil.h"
30 #include "wx/gtk/private.h"
31 #include "wx/gtk/dc.h"
32
33 #ifndef __WXGTK3__
34 #include "wx/gtk/dcclient.h"
35 #endif
36
37 // ============================================================================
38 // wxTextMeasure implementation
39 // ============================================================================
40
41 void wxTextMeasure::Init()
42 {
43 m_context = NULL;
44 m_layout = NULL;
45
46 #ifndef __WXGTK3__
47 m_wdc = NULL;
48
49 if ( m_dc )
50 {
51 wxClassInfo* const ci = m_dc->GetImpl()->GetClassInfo();
52
53 // Currently the code here only works with wxWindowDCImpl and only in
54 // wxGTK2 as wxGTK3 uses Cairo and not Pango for all its DCs.
55 if ( ci->IsKindOf(wxCLASSINFO(wxWindowDCImpl)))
56 {
57 m_useDCImpl = false;
58 }
59 }
60 #endif // GTK+ < 3
61 }
62
63 // Get Gtk needed elements, if we have not them yet.
64 void wxTextMeasure::BeginMeasuring()
65 {
66 if ( m_dc )
67 {
68 #ifndef __WXGTK3__
69 m_wdc = wxDynamicCast(m_dc->GetImpl(), wxWindowDCImpl);
70 if ( m_wdc )
71 {
72 m_context = m_wdc->m_context;
73 m_layout = m_wdc->m_layout;
74 }
75 #endif // GTK+ < 3
76 }
77 else if ( m_win )
78 {
79 m_context = gtk_widget_get_pango_context( m_win->GetHandle() );
80 if ( m_context )
81 m_layout = pango_layout_new(m_context);
82 }
83
84 // set the font to use
85 if ( m_layout )
86 {
87 pango_layout_set_font_description(m_layout,
88 GetFont().GetNativeFontInfo()->description);
89 }
90 }
91
92 void wxTextMeasure::EndMeasuring()
93 {
94 if ( !m_layout )
95 return;
96
97 #ifndef __WXGTK3__
98 if ( m_wdc )
99 {
100 // Reset dc own font description
101 pango_layout_set_font_description( m_wdc->m_layout, m_wdc->m_fontdesc );
102 }
103 else
104 #endif // GTK+ < 3
105 {
106 g_object_unref (m_layout);
107 }
108 }
109
110 // Notice we don't check here the font. It is supposed to be OK before the call.
111 void wxTextMeasure::DoGetTextExtent(const wxString& string,
112 wxCoord *width,
113 wxCoord *height,
114 wxCoord *descent,
115 wxCoord *externalLeading)
116 {
117 if ( !m_context )
118 {
119 *width =
120 *height = 0;
121 return;
122 }
123
124 // Set layout's text
125 const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(string, GetFont());
126 if ( !dataUTF8 )
127 {
128 // hardly ideal, but what else can we do if conversion failed?
129 wxLogLastError(wxT("GetTextExtent"));
130 return;
131 }
132 pango_layout_set_text(m_layout, dataUTF8, -1);
133
134 if ( m_dc )
135 {
136 // in device units
137 pango_layout_get_pixel_size(m_layout, width, height);
138 }
139 else // win
140 {
141 // the logical rect bounds the ink rect
142 PangoRectangle rect;
143 pango_layout_get_extents(m_layout, NULL, &rect);
144 *width = PANGO_PIXELS(rect.width);
145 *height = PANGO_PIXELS(rect.height);
146 }
147
148 if (descent)
149 {
150 PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
151 int baseline = pango_layout_iter_get_baseline(iter);
152 pango_layout_iter_free(iter);
153 *descent = *height - PANGO_PIXELS(baseline);
154 }
155
156 if (externalLeading)
157 {
158 // No support for MSW-like "external leading" in Pango.
159 *externalLeading = 0;
160 }
161 }
162
163 bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
164 wxArrayInt& widths,
165 double WXUNUSED(scaleX))
166 {
167 // Set layout's text
168 const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(text, GetFont());
169 if ( !dataUTF8 )
170 {
171 // hardly ideal, but what else can we do if conversion failed?
172 wxLogLastError(wxT("GetPartialTextExtents"));
173 return false;
174 }
175
176 pango_layout_set_text(m_layout, dataUTF8, -1);
177
178 // Calculate the position of each character based on the widths of
179 // the previous characters
180
181 // Code borrowed from Scintilla's PlatGTK
182 PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
183 PangoRectangle pos;
184 pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
185 size_t i = 0;
186 while (pango_layout_iter_next_cluster(iter))
187 {
188 pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
189 int position = PANGO_PIXELS(pos.x);
190 widths[i++] = position;
191 }
192
193 const size_t len = text.length();
194 while (i < len)
195 widths[i++] = PANGO_PIXELS(pos.x + pos.width);
196 pango_layout_iter_free(iter);
197
198 return true;
199 }