]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/textmeasure.cpp
Cache HDC used for painting for the entire duration of WM_PAINT processing.
[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
c70155b8 6// RCS-ID: $Id:
8cd79b7a
VZ
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"
a1624575 24 #include "wx/log.h"
8cd79b7a
VZ
25#endif //WX_PRECOMP
26
27#include "wx/private/textmeasure.h"
28
29#include "wx/fontutil.h"
30#include "wx/gtk/private.h"
1bce253a 31#include "wx/gtk/dc.h"
8cd79b7a
VZ
32
33#ifndef __WXGTK3__
34 #include "wx/gtk/dcclient.h"
35#endif
36
37// ============================================================================
38// wxTextMeasure implementation
39// ============================================================================
40
41void wxTextMeasure::Init()
42{
1bce253a
VZ
43 m_context = NULL;
44 m_layout = NULL;
45
8cd79b7a
VZ
46#ifndef __WXGTK3__
47 m_wdc = NULL;
1bce253a
VZ
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 }
8cd79b7a 60#endif // GTK+ < 3
8cd79b7a
VZ
61}
62
63// Get Gtk needed elements, if we have not them yet.
64void 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,
e0da9e87 88 GetFont().GetNativeFontInfo()->description);
8cd79b7a
VZ
89 }
90}
91
92void 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.
111void 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
e0da9e87 125 const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(string, GetFont());
8cd79b7a
VZ
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
163bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
164 wxArrayInt& widths,
165 double WXUNUSED(scaleX))
166{
167 // Set layout's text
e0da9e87 168 const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(text, GetFont());
8cd79b7a
VZ
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}