]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/dcclient.cpp
Fix broken and missing DataView interface items for Phoenix
[wxWidgets.git] / src / gtk / dcclient.cpp
index f6a7f3a94251d39c1ba7bbef9f8bc6bf989df793..0ad9159ef58344153a28117c32e59e980ade8102 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "wx/gtk/private.h"
 #include "wx/gtk/private/object.h"
+#include "wx/private/textmeasure.h"
 
 //-----------------------------------------------------------------------------
 // local defines
@@ -129,7 +130,11 @@ enum wxPoolGCType
    wxTEXT_SCREEN,
    wxBG_SCREEN,
    wxPEN_SCREEN,
-   wxBRUSH_SCREEN
+   wxBRUSH_SCREEN,
+   wxTEXT_COLOUR_ALPHA,
+   wxBG_COLOUR_ALPHA,
+   wxPEN_COLOUR_ALPHA,
+   wxBRUSH_COLOUR_ALPHA
 };
 
 struct wxGC
@@ -295,7 +300,7 @@ wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *window ) :
         wxCHECK_RET(widget, "DC needs a widget");
 
         m_gdkwindow = widget->window;
-        if (GTK_WIDGET_NO_WINDOW(widget))
+        if (!gtk_widget_get_has_window(widget))
             SetDeviceLocalOrigin(widget->allocation.x, widget->allocation.y);
     }
 
@@ -375,6 +380,18 @@ void wxWindowDCImpl::SetUpDC( bool isMemDC )
             m_textGC = wxGetPoolGC( m_gdkwindow, wxTEXT_SCREEN );
             m_bgGC = wxGetPoolGC( m_gdkwindow, wxBG_SCREEN );
         }
+#if GTK_CHECK_VERSION(2,12,0)
+        // gdk_screen_get_rgba_colormap was added in 2.8, but this code is for
+        // compositing which requires 2.12
+        else if (gtk_check_version(2,12,0) == NULL &&
+            m_cmap == gdk_screen_get_rgba_colormap(gdk_colormap_get_screen(m_cmap)))
+        {
+            m_penGC = wxGetPoolGC( m_gdkwindow, wxPEN_COLOUR_ALPHA );
+            m_brushGC = wxGetPoolGC( m_gdkwindow, wxBRUSH_COLOUR_ALPHA );
+            m_textGC = wxGetPoolGC( m_gdkwindow, wxTEXT_COLOUR_ALPHA );
+            m_bgGC = wxGetPoolGC( m_gdkwindow, wxBG_COLOUR_ALPHA );
+        }
+#endif
         else
         {
             m_penGC = wxGetPoolGC( m_gdkwindow, wxPEN_COLOUR );
@@ -947,7 +964,7 @@ void wxWindowDCImpl::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord
 
             // If the pen is transparent pen we increase the size
             // for better compatibility with other platforms.
-            if ( m_pen.IsNonTransparent() )
+            if (m_pen.IsTransparent())
             {
                 ++ww;
                 ++hh;
@@ -1372,69 +1389,12 @@ void wxWindowDCImpl::DoDrawText(const wxString& text,
 
     gdk_pango_context_set_colormap( m_context, m_cmap );  // not needed in gtk+ >= 2.6
 
-    bool underlined = m_font.IsOk() && m_font.GetUnderlined();
-
     wxCharBuffer data = wxGTK_CONV(text);
     if ( !data )
         return;
-    size_t datalen = strlen(data);
-
-    // in Pango >= 1.16 the "underline of leading/trailing spaces" bug
-    // has been fixed and thus the hack implemented below should never be used
-    static bool pangoOk = !wx_pango_version_check(1, 16, 0);
-
-    bool needshack = underlined && !pangoOk;
 
-    if (needshack)
-    {
-        // a PangoLayout which has leading/trailing spaces with underlined font
-        // is not correctly drawn by this pango version: Pango won't underline the spaces.
-        // This can be a problem; e.g. wxHTML rendering of underlined text relies on
-        // this behaviour. To workaround this problem, we use a special hack here
-        // suggested by pango maintainer Behdad Esfahbod: we prepend and append two
-        // empty space characters and give them a dummy colour attribute.
-        // This will force Pango to underline the leading/trailing spaces, too.
-
-        wxCharBuffer data_tmp(datalen + 6);
-        // copy the leading U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format
-        memcpy(data_tmp.data(), "\342\200\214", 3);
-        // copy the user string
-        memcpy(data_tmp.data() + 3, data, datalen);
-        // copy the trailing U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format
-        memcpy(data_tmp.data() + 3 + datalen, "\342\200\214", 3);
-
-        data = data_tmp;
-        datalen += 6;
-    }
-
-    pango_layout_set_text(m_layout, data, datalen);
-
-    if (underlined)
-    {
-        PangoAttrList *attrs = pango_attr_list_new();
-        PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
-        a->start_index = 0;
-        a->end_index = datalen;
-        pango_attr_list_insert(attrs, a);
-
-        if (needshack)
-        {
-            // dummy colour for the leading space
-            a = pango_attr_foreground_new (0x0057, 0x52A9, 0xD614);
-            a->start_index = 0;
-            a->end_index = 1;
-            pango_attr_list_insert(attrs, a);
-
-            // dummy colour for the trailing space
-            a = pango_attr_foreground_new (0x0057, 0x52A9, 0xD614);
-            a->start_index = datalen - 1;
-            a->end_index = datalen;
-            pango_attr_list_insert(attrs, a);
-        }
-
-        pango_layout_set_attributes(m_layout, attrs);
-        pango_attr_list_unref(attrs);
-    }
+    pango_layout_set_text(m_layout, data, data.length());
+    const bool setAttrs = m_font.GTKSetPangoAttrs(m_layout);
 
     int oldSize = 0;
     const bool isScaled = fabs(m_scaleY - 1.0) > 0.00001;
@@ -1473,7 +1433,7 @@ void wxWindowDCImpl::DoDrawText(const wxString& text,
          // actually apply unscaled font
          pango_layout_set_font_description( m_layout, m_fontdesc );
     }
-    if (underlined)
+    if (setAttrs)
     {
         // undo underline attributes setting:
         pango_layout_set_attributes(m_layout, NULL);
@@ -1492,197 +1452,80 @@ void wxWindowDCImpl::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord
 
     wxCHECK_RET( IsOk(), wxT("invalid window dc") );
 
-#if __WXGTK26__
-    if (!gtk_check_version(2,6,0))
-    {
-        x = XLOG2DEV(x);
-        y = YLOG2DEV(y);
-
-        pango_layout_set_text(m_layout, wxGTK_CONV(text), -1);
+    x = XLOG2DEV(x);
+    y = YLOG2DEV(y);
 
-        if (m_font.GetUnderlined())
-        {
-            PangoAttrList *attrs = pango_attr_list_new();
-            PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
-            pango_attr_list_insert(attrs, a);
-            pango_layout_set_attributes(m_layout, attrs);
-            pango_attr_list_unref(attrs);
-        }
+    pango_layout_set_text(m_layout, wxGTK_CONV(text), -1);
+    const bool setAttrs = m_font.GTKSetPangoAttrs(m_layout);
+    int oldSize = 0;
+    const bool isScaled = fabs(m_scaleY - 1.0) > 0.00001;
+    if (isScaled)
+    {
+        //TODO: when Pango >= 1.6 is required, use pango_matrix_scale()
+         // If there is a user or actually any scale applied to
+         // the device context, scale the font.
 
-        int oldSize = 0;
-        const bool isScaled = fabs(m_scaleY - 1.0) > 0.00001;
-        if (isScaled)
-        {
-            //TODO: when Pango >= 1.6 is required, use pango_matrix_scale()
-             // If there is a user or actually any scale applied to
-             // the device context, scale the font.
+         // scale font description
+        oldSize = pango_font_description_get_size(m_fontdesc);
+        pango_font_description_set_size(m_fontdesc, int(oldSize * m_scaleY));
 
-             // scale font description
-            oldSize = pango_font_description_get_size(m_fontdesc);
-            pango_font_description_set_size(m_fontdesc, int(oldSize * m_scaleY));
+         // actually apply scaled font
+         pango_layout_set_font_description( m_layout, m_fontdesc );
+    }
 
-             // actually apply scaled font
-             pango_layout_set_font_description( m_layout, m_fontdesc );
-        }
+    int w, h;
+    pango_layout_get_pixel_size(m_layout, &w, &h);
 
-        int w, h;
-        pango_layout_get_pixel_size(m_layout, &w, &h);
-
-        const GdkColor* bg_col = NULL;
-        if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
-            bg_col = m_textBackgroundColour.GetColor();
-
-        // rotate the text
-        PangoMatrix matrix = PANGO_MATRIX_INIT;
-        pango_matrix_rotate (&matrix, angle);
-        pango_context_set_matrix (m_context, &matrix);
-        pango_layout_context_changed (m_layout);
-
-        // To be compatible with MSW, the rotation axis must be in the old
-        // top-left corner.
-        // Calculate the vertices of the rotated rectangle containing the text,
-        // relative to the old top-left vertex.
-        // We could use the matrix for this, but it's simpler with trignonometry.
-        double rad = DegToRad(angle);
-        // the rectangle vertices are counted clockwise with the first one
-        // being at (0, 0)
-        double x2 = w * cos(rad);
-        double y2 = -w * sin(rad);   // y axis points to the bottom, hence minus
-        double x4 = h * sin(rad);
-        double y4 = h * cos(rad);
-        double x3 = x4 + x2;
-        double y3 = y4 + y2;
-        // Then we calculate max and min of the rotated rectangle.
-        wxCoord maxX = (wxCoord)(dmax(dmax(0, x2), dmax(x3, x4)) + 0.5),
-                maxY = (wxCoord)(dmax(dmax(0, y2), dmax(y3, y4)) + 0.5),
-                minX = (wxCoord)(dmin(dmin(0, x2), dmin(x3, x4)) - 0.5),
-                minY = (wxCoord)(dmin(dmin(0, y2), dmin(y3, y4)) - 0.5);
-
-        gdk_draw_layout_with_colors(m_gdkwindow, m_textGC, x+minX, y+minY,
-                                    m_layout, NULL, bg_col);
-
-        if (m_font.GetUnderlined())
-            pango_layout_set_attributes(m_layout, NULL);
-
-        // clean up the transformation matrix
-        pango_context_set_matrix(m_context, NULL);
+    const GdkColor* bg_col = NULL;
+    if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
+        bg_col = m_textBackgroundColour.GetColor();
 
-        if (isScaled)
-        {
-             // reset unscaled size
-             pango_font_description_set_size( m_fontdesc, oldSize );
+    // rotate the text
+    PangoMatrix matrix = PANGO_MATRIX_INIT;
+    pango_matrix_rotate (&matrix, angle);
+    pango_context_set_matrix (m_context, &matrix);
+    pango_layout_context_changed (m_layout);
+
+    // To be compatible with MSW, the rotation axis must be in the old
+    // top-left corner.
+    // Calculate the vertices of the rotated rectangle containing the text,
+    // relative to the old top-left vertex.
+    // We could use the matrix for this, but it's simpler with trignonometry.
+    double rad = DegToRad(angle);
+    // the rectangle vertices are counted clockwise with the first one
+    // being at (0, 0)
+    double x2 = w * cos(rad);
+    double y2 = -w * sin(rad);   // y axis points to the bottom, hence minus
+    double x4 = h * sin(rad);
+    double y4 = h * cos(rad);
+    double x3 = x4 + x2;
+    double y3 = y4 + y2;
+    // Then we calculate max and min of the rotated rectangle.
+    wxCoord maxX = (wxCoord)(dmax(dmax(0, x2), dmax(x3, x4)) + 0.5),
+            maxY = (wxCoord)(dmax(dmax(0, y2), dmax(y3, y4)) + 0.5),
+            minX = (wxCoord)(dmin(dmin(0, x2), dmin(x3, x4)) - 0.5),
+            minY = (wxCoord)(dmin(dmin(0, y2), dmin(y3, y4)) - 0.5);
+
+    gdk_draw_layout_with_colors(m_gdkwindow, m_textGC, x+minX, y+minY,
+                                m_layout, NULL, bg_col);
+
+    if (setAttrs)
+        pango_layout_set_attributes(m_layout, NULL);
 
-             // actually apply unscaled font
-             pango_layout_set_font_description( m_layout, m_fontdesc );
-        }
+    // clean up the transformation matrix
+    pango_context_set_matrix(m_context, NULL);
 
-        CalcBoundingBox(x+minX, y+minY);
-        CalcBoundingBox(x+maxX, y+maxY);
-    }
-    else
-#endif //__WXGTK26__
-    {
-#if wxUSE_IMAGE
-    if ( wxIsNullDouble(angle) )
+    if (isScaled)
     {
-        DoDrawText(text, x, y);
-        return;
-    }
-
-    wxCoord w;
-    wxCoord h;
-
-    // TODO: implement later without GdkFont for GTK 2.0
-    DoGetTextExtent(text, &w, &h, NULL,NULL, &m_font);
-
-    // draw the string normally
-    wxBitmap src(w, h);
-    wxMemoryDC dc;
-    dc.SelectObject(src);
-    dc.SetFont(GetFont());
-    dc.SetBackground(*wxBLACK_BRUSH);
-    dc.SetBrush(*wxBLACK_BRUSH);
-    dc.Clear();
-    dc.SetTextForeground( *wxWHITE );
-    dc.DrawText(text, 0, 0);
-    dc.SelectObject(wxNullBitmap);
+         // reset unscaled size
+         pango_font_description_set_size( m_fontdesc, oldSize );
 
-    // Calculate the size of the rotated bounding box.
-    double rad = DegToRad(angle);
-    double dx = cos(rad),
-           dy = sin(rad);
-
-    // the rectngle vertices are counted clockwise with the first one being at
-    // (0, 0) (or, rather, at (x, y))
-    double x2 = w*dx,
-           y2 = -w*dy;      // y axis points to the bottom, hence minus
-    double x4 = h*dy,
-           y4 = h*dx;
-    double x3 = x4 + x2,
-           y3 = y4 + y2;
-
-    // calc max and min
-    wxCoord maxX = (wxCoord)(dmax(x2, dmax(x3, x4)) + 0.5),
-            maxY = (wxCoord)(dmax(y2, dmax(y3, y4)) + 0.5),
-            minX = (wxCoord)(dmin(x2, dmin(x3, x4)) - 0.5),
-            minY = (wxCoord)(dmin(y2, dmin(y3, y4)) - 0.5);
-
-
-    wxImage image = src.ConvertToImage();
-
-    image.ConvertColourToAlpha( m_textForegroundColour.Red(),
-                                m_textForegroundColour.Green(),
-                                m_textForegroundColour.Blue() );
-    image = image.Rotate( rad, wxPoint(0,0) );
-
-    int i_angle = (int) angle;
-    i_angle = i_angle % 360;
-    if (i_angle < 0)
-        i_angle += 360;
-    int xoffset = 0;
-    if ((i_angle >= 90.0) && (i_angle < 270.0))
-        xoffset = image.GetWidth();
-    int yoffset = 0;
-    if ((i_angle >= 0.0) && (i_angle < 180.0))
-        yoffset = image.GetHeight();
-
-    if ((i_angle >= 0) && (i_angle < 90))
-        yoffset -= (int)( cos(rad)*h );
-    if ((i_angle >= 90) && (i_angle < 180))
-        xoffset -= (int)( sin(rad)*h );
-    if ((i_angle >= 180) && (i_angle < 270))
-        yoffset -= (int)( cos(rad)*h );
-    if ((i_angle >= 270) && (i_angle < 360))
-        xoffset -= (int)( sin(rad)*h );
-
-    int i_x = x - xoffset;
-    int i_y = y - yoffset;
-
-    src = image;
-    DoDrawBitmap( src, i_x, i_y, true );
-
-
-    // it would be better to draw with non underlined font and draw the line
-    // manually here (it would be more straight...)
-#if 0
-    if ( m_font.GetUnderlined() )
-    {
-        gdk_draw_line( m_gdkwindow, m_textGC,
-                       XLOG2DEV(x + x4), YLOG2DEV(y + y4 + font->descent),
-                       XLOG2DEV(x + x3), YLOG2DEV(y + y3 + font->descent));
-    }
-#endif // 0
-
-    // update the bounding box
-    CalcBoundingBox(x + minX, y + minY);
-    CalcBoundingBox(x + maxX, y + maxY);
-#else // !wxUSE_IMAGE
-    wxUnusedVar(text);
-    wxUnusedVar(x);
-    wxUnusedVar(y);
-    wxUnusedVar(angle);
-#endif // wxUSE_IMAGE/!wxUSE_IMAGE
+         // actually apply unscaled font
+         pango_layout_set_font_description( m_layout, m_fontdesc );
     }
+
+    CalcBoundingBox(x+minX, y+minY);
+    CalcBoundingBox(x+maxX, y+maxY);
 }
 
 void wxWindowDCImpl::DoGetTextExtent(const wxString &string,
@@ -1690,100 +1533,27 @@ void wxWindowDCImpl::DoGetTextExtent(const wxString &string,
                                  wxCoord *descent, wxCoord *externalLeading,
                                  const wxFont *theFont) const
 {
-    if ( width )
-        *width = 0;
-    if ( height )
-        *height = 0;
-    if ( descent )
-        *descent = 0;
-    if ( externalLeading )
-        *externalLeading = 0;
-
-    if (string.empty())
-        return;
-
-    // ensure that theFont is always non-NULL
+    // ensure we work with a valid font
+    const wxFont *fontToUse;
     if ( !theFont || !theFont->IsOk() )
-        theFont = &m_font;
-
-    // and use it if it's valid
-    if ( theFont->IsOk() )
-    {
-        pango_layout_set_font_description
-        (
-            m_layout,
-            theFont->GetNativeFontInfo()->description
-        );
-    }
-
-    // Set layout's text
-    const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(string, *theFont);
-    if ( !dataUTF8 )
-    {
-        // hardly ideal, but what else can we do if conversion failed?
-        return;
-    }
-
-    pango_layout_set_text(m_layout, dataUTF8, -1);
+        fontToUse = &m_font;
+    else
+        fontToUse = theFont;
 
-    int h;
-    pango_layout_get_pixel_size(m_layout, width, &h);
-    if (descent)
-    {
-        PangoLayoutIter *iter = pango_layout_get_iter(m_layout);
-        int baseline = pango_layout_iter_get_baseline(iter);
-        pango_layout_iter_free(iter);
-        *descent = h - PANGO_PIXELS(baseline);
-    }
-    if (height)
-        *height = h;
+    wxCHECK_RET( fontToUse->IsOk(), wxT("invalid font") );
 
-    // Reset old font description
-    if (theFont->IsOk())
-        pango_layout_set_font_description( m_layout, m_fontdesc );
+    wxTextMeasure txm(GetOwner(), fontToUse);
+    txm.GetTextExtent(string, width, height, descent, externalLeading);
 }
 
 
 bool wxWindowDCImpl::DoGetPartialTextExtents(const wxString& text,
                                          wxArrayInt& widths) const
 {
-    const size_t len = text.length();
-    widths.Empty();
-    widths.Add(0, len);
-
-    if (text.empty())
-        return true;
+    wxCHECK_MSG( m_font.IsOk(), false, wxT("Invalid font") );
 
-    // 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("DoGetPartialTextExtents"));
-        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;
-    }
-    while (i < len)
-        widths[i++] = PANGO_PIXELS(pos.x + pos.width);
-    pango_layout_iter_free(iter);
-
-    return true;
+    wxTextMeasure txm(GetOwner(), &m_font);
+    return txm.GetPartialTextExtents(text, widths, m_scaleX);
 }
 
 
@@ -2304,7 +2074,6 @@ int wxWindowDCImpl::GetDepth() const
     return gdk_drawable_get_depth(m_gdkwindow);
 }
 
-
 //-----------------------------------------------------------------------------
 // wxClientDCImpl
 //-----------------------------------------------------------------------------