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