X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2b5f62a0b2db198609b45dec622a018dae37008e..d1fc6f065885a749930c86fdb0200f3220ad86b5:/src/gtk/dcclient.cpp diff --git a/src/gtk/dcclient.cpp b/src/gtk/dcclient.cpp index d36b26b870..47c3ec2174 100644 --- a/src/gtk/dcclient.cpp +++ b/src/gtk/dcclient.cpp @@ -3,14 +3,17 @@ // Purpose: // Author: Robert Roebling // RCS-ID: $Id$ -// Copyright: (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze +// Copyright: (c) 1998 Robert Roebling, Chris Breeze // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "dcclient.h" #endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + #ifdef __VMS #define XCopyPlane XCOPYPLANE #endif @@ -298,6 +301,7 @@ wxWindowDC::wxWindowDC() m_owner = (wxWindow *)NULL; #ifdef __WXGTK20__ m_context = (PangoContext *)NULL; + m_layout = (PangoLayout *)NULL; m_fontdesc = (PangoFontDescription *)NULL; #endif } @@ -318,9 +322,9 @@ wxWindowDC::wxWindowDC( wxWindow *window ) GtkWidget *widget = window->m_wxwindow; - // some controls don't have m_wxwindow - like wxStaticBox, but the user + // Some controls don't have m_wxwindow - like wxStaticBox, but the user // code should still be able to create wxClientDCs for them, so we will - // use the parent window here then + // use the parent window here then. if ( !widget ) { window = window->GetParent(); @@ -331,16 +335,17 @@ wxWindowDC::wxWindowDC( wxWindow *window ) #ifdef __WXGTK20__ m_context = window->GtkGetPangoDefaultContext(); - m_fontdesc = widget->style->font_desc; + m_layout = pango_layout_new( m_context ); + m_fontdesc = pango_font_description_copy( widget->style->font_desc ); #endif GtkPizza *pizza = GTK_PIZZA( widget ); m_window = pizza->bin_window; - /* not realized ? */ + // Window not realized ? if (!m_window) { - /* don't report problems */ + // Don't report problems as per MSW. m_ok = TRUE; return; @@ -363,6 +368,13 @@ wxWindowDC::wxWindowDC( wxWindow *window ) wxWindowDC::~wxWindowDC() { Destroy(); + +#ifdef __WXGTK20__ + if (m_layout) + g_object_unref( G_OBJECT( m_layout ) ); + if (m_fontdesc) + pango_font_description_free( m_fontdesc ); +#endif } void wxWindowDC::SetUpDC() @@ -686,20 +698,28 @@ void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord if (m_pen.GetStyle() == wxTRANSPARENT) return; if (n <= 0) return; - CalcBoundingBox( points[0].x + xoffset, points[0].y + yoffset ); + GdkPoint *gpts = new GdkPoint[n]; + if (! gpts) + { + wxFAIL_MSG( wxT("Cannot allocate PolyLine") ); + return; + } - for (int i = 0; i < n-1; i++) + for (int i = 0; i < n; i++) { wxCoord x1 = XLOG2DEV(points[i].x + xoffset); - wxCoord x2 = XLOG2DEV(points[i+1].x + xoffset); - wxCoord y1 = YLOG2DEV(points[i].y + yoffset); // oh, what a waste - wxCoord y2 = YLOG2DEV(points[i+1].y + yoffset); + wxCoord y1 = YLOG2DEV(points[i].y + yoffset); - if (m_window) - gdk_draw_line( m_window, m_penGC, x1, y1, x2, y2 ); + CalcBoundingBox( x1 + xoffset, y1 + yoffset ); - CalcBoundingBox( points[i+1].x + xoffset, points[i+1].y + yoffset ); + gpts[i].x = x1; + gpts[i].y = y1; } + + if (m_window) + gdk_draw_lines( m_window, m_penGC, gpts, n); + + delete[] gpts; } void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset, int WXUNUSED(fillStyle) ) @@ -1418,38 +1438,71 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) wxCHECK_RET( font, wxT("invalid font") ); #endif -#ifdef __WXGTK20__ - wxCHECK_RET( m_context, wxT("no Pango context") ); -#endif - x = XLOG2DEV(x); y = YLOG2DEV(y); #ifdef __WXGTK20__ - // TODO: the layout engine should be abstracted at a higher level! - PangoLayout *layout = pango_layout_new(m_context); - pango_layout_set_font_description(layout, m_fontdesc); - { + wxCHECK_RET( m_context, wxT("no Pango context") ); + wxCHECK_RET( m_layout, wxT("no Pango layout") ); + wxCHECK_RET( m_fontdesc, wxT("no Pango font description") ); + #if wxUSE_UNICODE - const wxCharBuffer data = wxConvUTF8.cWC2MB( text ); - pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); + const wxCharBuffer data = wxConvUTF8.cWC2MB( text ); #else - const wxWCharBuffer wdata = wxConvLocal.cMB2WC( text ); - const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata ); - pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); + const wxWCharBuffer wdata = wxConvLocal.cMB2WC( text ); + const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata ); #endif + pango_layout_set_text( m_layout, (const char*) data, strlen( (const char*) data )); + + int w,h; + + if (m_scaleY != 1.0) + { + // If there is a user or actually any scale applied to + // the device context, scale the font. + + // scale font description + gint oldSize = pango_font_description_get_size( m_fontdesc ); + double size = oldSize; + size = size * m_scaleY; + pango_font_description_set_size( m_fontdesc, (gint)size ); + + // actually apply scaled font + pango_layout_set_font_description( m_layout, m_fontdesc ); + + pango_layout_get_pixel_size( m_layout, &w, &h ); + if ( m_backgroundMode == wxSOLID ) + { + gdk_gc_set_foreground(m_textGC, m_textBackgroundColour.GetColor()); + gdk_draw_rectangle(m_window, m_textGC, TRUE, x, y, w, h); + gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor()); + } + + // Draw layout. + gdk_draw_layout( m_window, m_textGC, x, y, m_layout ); + + // reset unscaled size + pango_font_description_set_size( m_fontdesc, oldSize ); + + // actually apply unscaled font + pango_layout_set_font_description( m_layout, m_fontdesc ); + } + else + { + pango_layout_get_pixel_size( m_layout, &w, &h ); + if ( m_backgroundMode == wxSOLID ) + { + gdk_gc_set_foreground(m_textGC, m_textBackgroundColour.GetColor()); + gdk_draw_rectangle(m_window, m_textGC, TRUE, x, y, w, h); + gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor()); + } + // Draw layout. + gdk_draw_layout( m_window, m_textGC, x, y, m_layout ); } - // Measure layout. - int w,h; - pango_layout_get_pixel_size(layout, &w, &h); wxCoord width = w; wxCoord height = h; - // Draw layout. - gdk_draw_layout( m_window, m_textGC, x, y, layout ); - - g_object_unref( G_OBJECT( layout ) ); #else // GTK+ 1.x wxCoord width = gdk_string_width( font, text.mbc_str() ); wxCoord height = font->ascent + font->descent; @@ -1473,7 +1526,6 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) } #endif // GTK+ 2.0/1.x - width = wxCoord(width / m_scaleX); height = wxCoord(height / m_scaleY); CalcBoundingBox (x + width, y + height); @@ -1492,6 +1544,10 @@ void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, if (!m_window) return; +#ifdef __WXGTK20__ + // implement later without GdkFont for GTK 2.0 + return; +#else GdkFont *font = m_font.GetInternalFont( m_scaleY ); wxCHECK_RET( font, wxT("invalid font") ); @@ -1590,6 +1646,7 @@ void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, // update the bounding box CalcBoundingBox(x + minX, y + minY); CalcBoundingBox(x + maxX, y + maxY); +#endif } void wxWindowDC::DoGetTextExtent(const wxString &string, @@ -1605,26 +1662,22 @@ void wxWindowDC::DoGetTextExtent(const wxString &string, } #ifdef __WXGTK20__ - // Create layout and set font description - PangoLayout *layout = pango_layout_new(m_context); + // Set new font description if (theFont) - pango_layout_set_font_description( layout, theFont->GetNativeFontInfo()->description ); - else - pango_layout_set_font_description(layout, m_fontdesc); + pango_layout_set_font_description( m_layout, theFont->GetNativeFontInfo()->description ); // Set layout's text #if wxUSE_UNICODE - const wxCharBuffer data = wxConvUTF8.cWC2MB( string ); - pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); + const wxCharBuffer data = wxConvUTF8.cWC2MB( string ); + pango_layout_set_text( m_layout, (const char*) data, strlen( (const char*) data )); #else - const wxWCharBuffer wdata = wxConvLocal.cMB2WC( string ); - const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata ); - pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data )); + const wxWCharBuffer wdata = wxConvLocal.cMB2WC( string ); + const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata ); + pango_layout_set_text( m_layout, (const char*) data, strlen( (const char*) data )); #endif - // Measure text. int w,h; - pango_layout_get_pixel_size(layout, &w, &h); + pango_layout_get_pixel_size( m_layout, &w, &h ); if (width) (*width) = (wxCoord) w; if (height) (*height) = (wxCoord) h; @@ -1635,7 +1688,9 @@ void wxWindowDC::DoGetTextExtent(const wxString &string, } if (externalLeading) (*externalLeading) = 0; // ?? - g_object_unref( G_OBJECT( layout ) ); + // Reset old font description + if (theFont) + pango_layout_set_font_description( m_layout, m_fontdesc ); #else wxFont fontToUse = m_font; if (theFont) fontToUse = *theFont; @@ -1651,13 +1706,9 @@ void wxWindowDC::DoGetTextExtent(const wxString &string, wxCoord wxWindowDC::GetCharWidth() const { #ifdef __WXGTK20__ - // There should be an easier way. - PangoLayout *layout = pango_layout_new(m_context); - pango_layout_set_font_description(layout, m_fontdesc); - pango_layout_set_text(layout, "H", 1 ); + pango_layout_set_text( m_layout, "H", 1 ); int w,h; - pango_layout_get_pixel_size(layout, &w, &h); - g_object_unref( G_OBJECT( layout ) ); + pango_layout_get_pixel_size( m_layout, &w, &h ); return w; #else GdkFont *font = m_font.GetInternalFont( m_scaleY ); @@ -1670,13 +1721,9 @@ wxCoord wxWindowDC::GetCharWidth() const wxCoord wxWindowDC::GetCharHeight() const { #ifdef __WXGTK20__ - // There should be an easier way. - PangoLayout *layout = pango_layout_new(m_context); - pango_layout_set_font_description(layout, m_fontdesc); - pango_layout_set_text(layout, "H", 1 ); + pango_layout_set_text( m_layout, "H", 1 ); int w,h; - pango_layout_get_pixel_size(layout, &w, &h); - g_object_unref( G_OBJECT( layout ) ); + pango_layout_get_pixel_size( m_layout, &w, &h ); return h; #else GdkFont *font = m_font.GetInternalFont( m_scaleY ); @@ -1726,20 +1773,41 @@ void wxWindowDC::Clear() void wxWindowDC::SetFont( const wxFont &font ) { - // It is common practice to set the font to wxNullFont, so - // don't consider it to be an error - // wxCHECK_RET( font.Ok(), _T("invalid font in wxWindowDC::SetFont") ); - m_font = font; + #ifdef __WXGTK20__ - m_fontdesc = m_font.GetNativeFontInfo()->description; - - if (m_owner) + if (m_font.Ok()) { - if (m_font.GetNoAntiAliasing()) - m_context = m_owner->GtkGetPangoX11Context(); - else - m_context = m_owner->GtkGetPangoDefaultContext(); + if (m_fontdesc) + pango_font_description_free( m_fontdesc ); + + m_fontdesc = pango_font_description_copy( m_font.GetNativeFontInfo()->description ); + + + if (m_owner) + { + PangoContext *oldContext = m_context; + + // We might want to use the X11 context for faster + // rendering on screen + if (m_font.GetNoAntiAliasing()) + m_context = m_owner->GtkGetPangoX11Context(); + else + m_context = m_owner->GtkGetPangoDefaultContext(); + + // If we switch back/forth between different contexts + // we also have to create a new layout. I think so, + // at least, and it doesn't hurt to do it. + if (oldContext != m_context) + { + if (m_layout) + g_object_unref( G_OBJECT( m_layout ) ); + + m_layout = pango_layout_new( m_context ); + } + } + + pango_layout_set_font_description( m_layout, m_fontdesc ); } #endif }