non-pch build fix
[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
31 #ifndef __WXGTK3__
32 #include "wx/gtk/dcclient.h"
33 #endif
34
35 // ============================================================================
36 // wxTextMeasure implementation
37 // ============================================================================
38
39 void wxTextMeasure::Init()
40 {
41 wxASSERT_MSG( m_font, wxT("wxTextMeasure needs a valid wxFont") );
42
43 #ifndef __WXGTK3__
44 m_wdc = NULL;
45 #endif // GTK+ < 3
46 m_context = NULL;
47 m_layout = NULL;
48 }
49
50 // Get Gtk needed elements, if we have not them yet.
51 void wxTextMeasure::BeginMeasuring()
52 {
53 if ( m_dc )
54 {
55 #ifndef __WXGTK3__
56 m_wdc = wxDynamicCast(m_dc->GetImpl(), wxWindowDCImpl);
57 if ( m_wdc )
58 {
59 m_context = m_wdc->m_context;
60 m_layout = m_wdc->m_layout;
61 }
62 #endif // GTK+ < 3
63 }
64 else if ( m_win )
65 {
66 m_context = gtk_widget_get_pango_context( m_win->GetHandle() );
67 if ( m_context )
68 m_layout = pango_layout_new(m_context);
69 }
70
71 // set the font to use
72 if ( m_layout )
73 {
74 pango_layout_set_font_description(m_layout,
75 m_font->GetNativeFontInfo()->description);
76 }
77 }
78
79 void wxTextMeasure::EndMeasuring()
80 {
81 if ( !m_layout )
82 return;
83
84 #ifndef __WXGTK3__
85 if ( m_wdc )
86 {
87 // Reset dc own font description
88 pango_layout_set_font_description( m_wdc->m_layout, m_wdc->m_fontdesc );
89 }
90 else
91 #endif // GTK+ < 3
92 {
93 g_object_unref (m_layout);
94 }
95 }
96
97 // Notice we don't check here the font. It is supposed to be OK before the call.
98 void wxTextMeasure::DoGetTextExtent(const wxString& string,
99 wxCoord *width,
100 wxCoord *height,
101 wxCoord *descent,
102 wxCoord *externalLeading)
103 {
104 if ( !m_context )
105 {
106 *width =
107 *height = 0;
108 return;
109 }
110
111 // Set layout's text
112 const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(string, *m_font);
113 if ( !dataUTF8 )
114 {
115 // hardly ideal, but what else can we do if conversion failed?
116 wxLogLastError(wxT("GetTextExtent"));
117 return;
118 }
119 pango_layout_set_text(m_layout, dataUTF8, -1);
120
121 if ( m_dc )
122 {
123 // in device units
124 pango_layout_get_pixel_size(m_layout, width, height);
125 }
126 else // win
127 {
128 // the logical rect bounds the ink rect
129 PangoRectangle rect;
130 pango_layout_get_extents(m_layout, NULL, &rect);
131 *width = PANGO_PIXELS(rect.width);
132 *height = PANGO_PIXELS(rect.height);
133 }
134
135 if (descent)
136 {
137 PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
138 int baseline = pango_layout_iter_get_baseline(iter);
139 pango_layout_iter_free(iter);
140 *descent = *height - PANGO_PIXELS(baseline);
141 }
142
143 if (externalLeading)
144 {
145 // No support for MSW-like "external leading" in Pango.
146 *externalLeading = 0;
147 }
148 }
149
150 bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
151 wxArrayInt& widths,
152 double WXUNUSED(scaleX))
153 {
154 // Set layout's text
155 const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(text, *m_font);
156 if ( !dataUTF8 )
157 {
158 // hardly ideal, but what else can we do if conversion failed?
159 wxLogLastError(wxT("GetPartialTextExtents"));
160 return false;
161 }
162
163 pango_layout_set_text(m_layout, dataUTF8, -1);
164
165 // Calculate the position of each character based on the widths of
166 // the previous characters
167
168 // Code borrowed from Scintilla's PlatGTK
169 PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
170 PangoRectangle pos;
171 pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
172 size_t i = 0;
173 while (pango_layout_iter_next_cluster(iter))
174 {
175 pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
176 int position = PANGO_PIXELS(pos.x);
177 widths[i++] = position;
178 }
179
180 const size_t len = text.length();
181 while (i < len)
182 widths[i++] = PANGO_PIXELS(pos.x + pos.width);
183 pango_layout_iter_free(iter);
184
185 return true;
186 }