]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/textmeasure.cpp
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / src / gtk / textmeasure.cpp
CommitLineData
8cd79b7a
VZ
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"
a1624575 23 #include "wx/log.h"
8cd79b7a
VZ
24#endif //WX_PRECOMP
25
26#include "wx/private/textmeasure.h"
27
28#include "wx/fontutil.h"
29#include "wx/gtk/private.h"
1bce253a 30#include "wx/gtk/dc.h"
8cd79b7a
VZ
31
32#ifndef __WXGTK3__
33 #include "wx/gtk/dcclient.h"
34#endif
35
36// ============================================================================
37// wxTextMeasure implementation
38// ============================================================================
39
40void wxTextMeasure::Init()
41{
1bce253a
VZ
42 m_context = NULL;
43 m_layout = NULL;
44
8cd79b7a
VZ
45#ifndef __WXGTK3__
46 m_wdc = NULL;
1bce253a
VZ
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 }
8cd79b7a 59#endif // GTK+ < 3
8cd79b7a
VZ
60}
61
62// Get Gtk needed elements, if we have not them yet.
63void 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,
e0da9e87 87 GetFont().GetNativeFontInfo()->description);
8cd79b7a
VZ
88 }
89}
90
91void 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.
110void wxTextMeasure::DoGetTextExtent(const wxString& string,
111 wxCoord *width,
112 wxCoord *height,
113 wxCoord *descent,
114 wxCoord *externalLeading)
115{
116 if ( !m_context )
117 {
d76774b4
VZ
118 if ( width )
119 *width = 0;
120
121 if ( height )
122 *height = 0;
8cd79b7a
VZ
123 return;
124 }
125
126 // Set layout's text
e0da9e87 127 const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(string, GetFont());
0646084e 128 if ( !dataUTF8 && !string.empty() )
8cd79b7a
VZ
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
165bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
166 wxArrayInt& widths,
1cd86ff6 167 double scaleX)
8cd79b7a 168{
1cd86ff6
VZ
169 if ( !m_layout )
170 return wxTextMeasureBase::DoGetPartialTextExtents(text, widths, scaleX);
171
8cd79b7a 172 // Set layout's text
e0da9e87 173 const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(text, GetFont());
8cd79b7a
VZ
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}