Files
wxWidgets/src/gtk/textmeasure.cpp
2012-10-27 12:27:48 +00:00

188 lines
5.1 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: src/gtk/textmeasure.cpp
// Purpose: wxTextMeasure implementation for wxGTK
// Author: Manuel Martin
// Created: 2012-10-05
// RCS-ID: $Id:
// 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"
#include "wx/log.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;
}