Factor out text measurement from wxDC and wxWindow into wxTextMeasure.
Add a new private wxTextMeasure class implementing methods for measuring text and move the often duplicated (but not always identically) code for doing the same from wxDC and wxWindow into it. Currently this class is only really implemented in wxMSW and wxGTK. Also extend the test for text measuring functions and rename it to MeasuringTextTestCase from MeasuringContextTestCase as it's not wxGC-specific any more. Closes #14705. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72699 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
185
src/gtk/textmeasure.cpp
Normal file
185
src/gtk/textmeasure.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/gtk/textmeasure.cpp
|
||||
// Purpose: wxTextMeasure implementation for wxGTK
|
||||
// Author: Manuel Martin
|
||||
// Created: 2012-10-05
|
||||
// Copyright: (c) 1997-2012 wxWidgets team
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// for compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/window.h"
|
||||
#endif //WX_PRECOMP
|
||||
|
||||
#include "wx/private/textmeasure.h"
|
||||
|
||||
#include "wx/fontutil.h"
|
||||
#include "wx/gtk/private.h"
|
||||
|
||||
#ifndef __WXGTK3__
|
||||
#include "wx/gtk/dcclient.h"
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// wxTextMeasure implementation
|
||||
// ============================================================================
|
||||
|
||||
void wxTextMeasure::Init()
|
||||
{
|
||||
wxASSERT_MSG( m_font, wxT("wxTextMeasure needs a valid wxFont") );
|
||||
|
||||
#ifndef __WXGTK3__
|
||||
m_wdc = NULL;
|
||||
#endif // GTK+ < 3
|
||||
m_context = NULL;
|
||||
m_layout = NULL;
|
||||
}
|
||||
|
||||
// Get Gtk needed elements, if we have not them yet.
|
||||
void wxTextMeasure::BeginMeasuring()
|
||||
{
|
||||
if ( m_dc )
|
||||
{
|
||||
#ifndef __WXGTK3__
|
||||
m_wdc = wxDynamicCast(m_dc->GetImpl(), wxWindowDCImpl);
|
||||
if ( m_wdc )
|
||||
{
|
||||
m_context = m_wdc->m_context;
|
||||
m_layout = m_wdc->m_layout;
|
||||
}
|
||||
#endif // GTK+ < 3
|
||||
}
|
||||
else if ( m_win )
|
||||
{
|
||||
m_context = gtk_widget_get_pango_context( m_win->GetHandle() );
|
||||
if ( m_context )
|
||||
m_layout = pango_layout_new(m_context);
|
||||
}
|
||||
|
||||
// set the font to use
|
||||
if ( m_layout )
|
||||
{
|
||||
pango_layout_set_font_description(m_layout,
|
||||
m_font->GetNativeFontInfo()->description);
|
||||
}
|
||||
}
|
||||
|
||||
void wxTextMeasure::EndMeasuring()
|
||||
{
|
||||
if ( !m_layout )
|
||||
return;
|
||||
|
||||
#ifndef __WXGTK3__
|
||||
if ( m_wdc )
|
||||
{
|
||||
// Reset dc own font description
|
||||
pango_layout_set_font_description( m_wdc->m_layout, m_wdc->m_fontdesc );
|
||||
}
|
||||
else
|
||||
#endif // GTK+ < 3
|
||||
{
|
||||
g_object_unref (m_layout);
|
||||
}
|
||||
}
|
||||
|
||||
// Notice we don't check here the font. It is supposed to be OK before the call.
|
||||
void wxTextMeasure::DoGetTextExtent(const wxString& string,
|
||||
wxCoord *width,
|
||||
wxCoord *height,
|
||||
wxCoord *descent,
|
||||
wxCoord *externalLeading)
|
||||
{
|
||||
if ( !m_context )
|
||||
{
|
||||
*width =
|
||||
*height = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set layout's text
|
||||
const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(string, *m_font);
|
||||
if ( !dataUTF8 )
|
||||
{
|
||||
// hardly ideal, but what else can we do if conversion failed?
|
||||
wxLogLastError(wxT("GetTextExtent"));
|
||||
return;
|
||||
}
|
||||
pango_layout_set_text(m_layout, dataUTF8, -1);
|
||||
|
||||
if ( m_dc )
|
||||
{
|
||||
// in device units
|
||||
pango_layout_get_pixel_size(m_layout, width, height);
|
||||
}
|
||||
else // win
|
||||
{
|
||||
// the logical rect bounds the ink rect
|
||||
PangoRectangle rect;
|
||||
pango_layout_get_extents(m_layout, NULL, &rect);
|
||||
*width = PANGO_PIXELS(rect.width);
|
||||
*height = PANGO_PIXELS(rect.height);
|
||||
}
|
||||
|
||||
if (descent)
|
||||
{
|
||||
PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
|
||||
int baseline = pango_layout_iter_get_baseline(iter);
|
||||
pango_layout_iter_free(iter);
|
||||
*descent = *height - PANGO_PIXELS(baseline);
|
||||
}
|
||||
|
||||
if (externalLeading)
|
||||
{
|
||||
// No support for MSW-like "external leading" in Pango.
|
||||
*externalLeading = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
|
||||
wxArrayInt& widths,
|
||||
double WXUNUSED(scaleX))
|
||||
{
|
||||
// Set layout's text
|
||||
const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(text, *m_font);
|
||||
if ( !dataUTF8 )
|
||||
{
|
||||
// hardly ideal, but what else can we do if conversion failed?
|
||||
wxLogLastError(wxT("GetPartialTextExtents"));
|
||||
return false;
|
||||
}
|
||||
|
||||
pango_layout_set_text(m_layout, dataUTF8, -1);
|
||||
|
||||
// Calculate the position of each character based on the widths of
|
||||
// the previous characters
|
||||
|
||||
// Code borrowed from Scintilla's PlatGTK
|
||||
PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
|
||||
PangoRectangle pos;
|
||||
pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
|
||||
size_t i = 0;
|
||||
while (pango_layout_iter_next_cluster(iter))
|
||||
{
|
||||
pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
|
||||
int position = PANGO_PIXELS(pos.x);
|
||||
widths[i++] = position;
|
||||
}
|
||||
|
||||
const size_t len = text.length();
|
||||
while (i < len)
|
||||
widths[i++] = PANGO_PIXELS(pos.x + pos.width);
|
||||
pango_layout_iter_free(iter);
|
||||
|
||||
return true;
|
||||
}
|
Reference in New Issue
Block a user