[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

mrobinson at webkit.org mrobinson at webkit.org
Wed Dec 22 15:43:28 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit d28afd73f74a3dda6464f3d07a7d85bf74124f7f
Author: mrobinson at webkit.org <mrobinson at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Nov 11 02:28:56 2010 +0000

    2010-10-18  Martin Robinson  <mrobinson at igalia.com>
    
            Reviewed by Xan Lopez.
    
            [GTK] Widgets do not support CSS transformations
            https://bugs.webkit.org/show_bug.cgi?id=40139
    
            Added a platform-specific baseline for the slider transformation
            test. This baseline says "FAIL" because the test has platform-specific
            offsets hard-coded. The result is only one tick off from expected though,
            so it's likely correct for us.
    
            * platform/gtk/Skipped: Unskip.
            * platform/gtk/fast/forms/slider-transformed-expected.txt: Added.
    2010-10-15  Martin Robinson  <mrobinson at igalia.com>
    
            Reviewed by Xan Lopez.
    
            [GTK] Widgets do not support CSS transformations
            https://bugs.webkit.org/show_bug.cgi?id=40139
    
            Instead of rendering directly onto the target drawable when rendering
            form controls on GTK+ 2.0, render onto an intermediate surface and use
            cairo to blit the result back to the target surface. This has two
            benefits. The first is that it always honors the current Cairo
            transformation. The second is that since the intermediate drawable is
            always a 32-bit GdkPixmap, we do not have to have a set of widgets
            per-colormap any longer.
    
            This change also begins the abstraction of widget rendering so that GTK+
            2 and GTK+ 3 can use the same code path. The WidgetRenderingContext will
            eventually hide all version differences from RenderThemeGtk, which can
            just focus on interpreting the GtkStyle properties.
    
            * GNUmakefile.am: Add WidgetRenderinContext source files to the sources list.
            * platform/graphics/cairo/PlatformRefPtrCairo.cpp:
            (WTF::refPlatformPtr): Add a specialization for Cairo patterns.
            (WTF::derefPlatformPtr): Ditto.
            * platform/graphics/cairo/PlatformRefPtrCairo.h: Ditto.
            * platform/gtk/RenderThemeGtk.cpp:
            (WebCore::RenderThemeGtk::RenderThemeGtk): No longer keep a set of
            widgets per-colormap for GTK+, instead just determine if we can use RGBA
            colormaps and go from there.
            (WebCore::RenderThemeGtk::~RenderThemeGtk): Ditto.
            (WebCore::RenderThemeGtk::getIndicatorMetrics): Put the logic for
            getting toggle button indicator metrics into this helper.
            (WebCore::RenderThemeGtk::paintRenderObject): Now uses
            WidgetRenderingContext to do widget rendering.
            (WebCore::setToggleSize): Use the new getIndicatorMetrics helper.
            * platform/gtk/RenderThemeGtk.h: Added a member to track whether or not
              the widgets are using a RGBA colormap. Also remove a defunct Page*
              member.
            * platform/gtk/ScrollbarThemeGtk.cpp: Switch all widget drawing
            operations to use WidgetRenderingContext.
            (WebCore::ScrollbarThemeGtk::paintTrackBackground): Ditto.
            (WebCore::ScrollbarThemeGtk::paintScrollbarBackground): Ditto.
            (WebCore::ScrollbarThemeGtk::paintThumb): Ditto.
            (WebCore::ScrollbarThemeGtk::paint): Ditto.
            (WebCore::ScrollbarThemeGtk::paintButton): Ditto.
            * platform/gtk/WidgetRenderingContext.h: Added.
            * platform/gtk/WidgetRenderingContextGtk2.cpp: Added.
            (WebCore::purgeScratchBuffer): Added, this is similar to the scratch
            buffer implementation from ContextShadow.
            (WebCore::PurgeScratchBufferTimer::fired): Ditto.
            (WebCore::scheduleScratchBufferPurge): Ditto.
            (WebCore::getExtraSpaceForWidget):
            (WebCore::WidgetRenderingContext::WidgetRenderingContext): Added.
            (WebCore::WidgetRenderingContext::~WidgetRenderingContext): Added.
            (WebCore::WidgetRenderingContext::paintMozillaWidget): Added.
            * platform/gtk/WidgetRenderingContextGtk3.cpp: Added.
            (WebCore::WidgetRenderingContext::WidgetRenderingContext): Added.
            (WebCore::~WidgetRenderingContext::WidgetRenderingContext): Added.
            (WebCore::WidgetRenderingContext::paintMozillaWidget): Added.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@71791 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 301a446..89a53b7 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,18 @@
+2010-10-18  Martin Robinson  <mrobinson at igalia.com>
+
+        Reviewed by Xan Lopez.
+
+        [GTK] Widgets do not support CSS transformations
+        https://bugs.webkit.org/show_bug.cgi?id=40139
+
+        Added a platform-specific baseline for the slider transformation
+        test. This baseline says "FAIL" because the test has platform-specific
+        offsets hard-coded. The result is only one tick off from expected though,
+        so it's likely correct for us.
+
+        * platform/gtk/Skipped: Unskip.
+        * platform/gtk/fast/forms/slider-transformed-expected.txt: Added.
+
 2010-11-10  Mihai Parparita  <mihaip at chromium.org>
 
         Unreviewed Chromium rebaselines.
diff --git a/LayoutTests/platform/gtk/Skipped b/LayoutTests/platform/gtk/Skipped
index a034fca..99379ce 100644
--- a/LayoutTests/platform/gtk/Skipped
+++ b/LayoutTests/platform/gtk/Skipped
@@ -5234,11 +5234,6 @@ fast/dom/Geolocation/disconnected-frame.html
 fast/dom/Geolocation/disconnected-frame-already.html
 fast/dom/Geolocation/disconnected-frame-permission-denied.html
 
-# GTK+ theme-rendered widgets do not support CSS transforms
-# https://bugs.webkit.org/show_bug.cgi?id=40139
-fast/forms/slider-transformed.html
-fast/forms/slider-transformed.html
-
 # Some input type=range tests fail because of the size 
 # of the slider thumb in GTK+ themes.
 fast/forms/slider-mouse-events.html
diff --git a/LayoutTests/platform/gtk/fast/forms/slider-transformed-expected.txt b/LayoutTests/platform/gtk/fast/forms/slider-transformed-expected.txt
new file mode 100644
index 0000000..3dce259
--- /dev/null
+++ b/LayoutTests/platform/gtk/fast/forms/slider-transformed-expected.txt
@@ -0,0 +1,2 @@
+
+FAIL: expected slider value 39, got 38
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 269f7c3..644e00d 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,63 @@
+2010-10-15  Martin Robinson  <mrobinson at igalia.com>
+
+        Reviewed by Xan Lopez.
+
+        [GTK] Widgets do not support CSS transformations
+        https://bugs.webkit.org/show_bug.cgi?id=40139
+
+        Instead of rendering directly onto the target drawable when rendering
+        form controls on GTK+ 2.0, render onto an intermediate surface and use
+        cairo to blit the result back to the target surface. This has two
+        benefits. The first is that it always honors the current Cairo
+        transformation. The second is that since the intermediate drawable is
+        always a 32-bit GdkPixmap, we do not have to have a set of widgets
+        per-colormap any longer.
+
+        This change also begins the abstraction of widget rendering so that GTK+
+        2 and GTK+ 3 can use the same code path. The WidgetRenderingContext will
+        eventually hide all version differences from RenderThemeGtk, which can
+        just focus on interpreting the GtkStyle properties. 
+
+        * GNUmakefile.am: Add WidgetRenderinContext source files to the sources list.
+        * platform/graphics/cairo/PlatformRefPtrCairo.cpp:
+        (WTF::refPlatformPtr): Add a specialization for Cairo patterns.
+        (WTF::derefPlatformPtr): Ditto.
+        * platform/graphics/cairo/PlatformRefPtrCairo.h: Ditto.
+        * platform/gtk/RenderThemeGtk.cpp:
+        (WebCore::RenderThemeGtk::RenderThemeGtk): No longer keep a set of
+        widgets per-colormap for GTK+, instead just determine if we can use RGBA
+        colormaps and go from there.
+        (WebCore::RenderThemeGtk::~RenderThemeGtk): Ditto.
+        (WebCore::RenderThemeGtk::getIndicatorMetrics): Put the logic for
+        getting toggle button indicator metrics into this helper.
+        (WebCore::RenderThemeGtk::paintRenderObject): Now uses
+        WidgetRenderingContext to do widget rendering.
+        (WebCore::setToggleSize): Use the new getIndicatorMetrics helper.
+        * platform/gtk/RenderThemeGtk.h: Added a member to track whether or not
+          the widgets are using a RGBA colormap. Also remove a defunct Page*
+          member.
+        * platform/gtk/ScrollbarThemeGtk.cpp: Switch all widget drawing
+        operations to use WidgetRenderingContext.
+        (WebCore::ScrollbarThemeGtk::paintTrackBackground): Ditto.
+        (WebCore::ScrollbarThemeGtk::paintScrollbarBackground): Ditto.
+        (WebCore::ScrollbarThemeGtk::paintThumb): Ditto.
+        (WebCore::ScrollbarThemeGtk::paint): Ditto.
+        (WebCore::ScrollbarThemeGtk::paintButton): Ditto.
+        * platform/gtk/WidgetRenderingContext.h: Added.
+        * platform/gtk/WidgetRenderingContextGtk2.cpp: Added.
+        (WebCore::purgeScratchBuffer): Added, this is similar to the scratch
+        buffer implementation from ContextShadow.
+        (WebCore::PurgeScratchBufferTimer::fired): Ditto.
+        (WebCore::scheduleScratchBufferPurge): Ditto.
+        (WebCore::getExtraSpaceForWidget):
+        (WebCore::WidgetRenderingContext::WidgetRenderingContext): Added.
+        (WebCore::WidgetRenderingContext::~WidgetRenderingContext): Added.
+        (WebCore::WidgetRenderingContext::paintMozillaWidget): Added.
+        * platform/gtk/WidgetRenderingContextGtk3.cpp: Added.
+        (WebCore::WidgetRenderingContext::WidgetRenderingContext): Added.
+        (WebCore::~WidgetRenderingContext::WidgetRenderingContext): Added.
+        (WebCore::WidgetRenderingContext::paintMozillaWidget): Added.
+
 2010-11-10  Beth Dakin  <bdakin at apple.com>
 
         Reviewed by Simon Fraser.
diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am
index cdafd9f..1d1bfdb 100644
--- a/WebCore/GNUmakefile.am
+++ b/WebCore/GNUmakefile.am
@@ -3631,6 +3631,9 @@ webcoregtk_sources += \
 	WebCore/platform/gtk/TemporaryLinkStubs.cpp \
 	WebCore/platform/gtk/WheelEventGtk.cpp \
 	WebCore/platform/gtk/WidgetGtk.cpp \
+	WebCore/platform/gtk/WidgetRenderingContextGtk2.cpp \
+	WebCore/platform/gtk/WidgetRenderingContextGtk3.cpp \
+	WebCore/platform/gtk/WidgetRenderingContext.h \
 	WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp \
 	WebCore/platform/image-decoders/bmp/BMPImageDecoder.h \
 	WebCore/platform/image-decoders/bmp/BMPImageReader.cpp \
diff --git a/WebCore/platform/graphics/cairo/RefPtrCairo.cpp b/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
index a6c983e..c8b242c 100644
--- a/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
+++ b/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
@@ -76,6 +76,18 @@ template<> void derefIfNotNull(cairo_scaled_font_t* ptr)
         cairo_scaled_font_destroy(ptr);
 }
 
+template<> void refIfNotNull(cairo_pattern_t* ptr)
+{
+    if (LIKELY(ptr != 0))
+        cairo_pattern_reference(ptr);
+}
+
+template<> void derefIfNotNull(cairo_pattern_t* ptr)
+{
+    if (LIKELY(ptr != 0))
+        cairo_pattern_destroy(ptr);
+}
+
 #if defined(USE_FREETYPE)
 template<> void refIfNotNull(FcPattern* ptr)
 {
diff --git a/WebCore/platform/graphics/cairo/RefPtrCairo.h b/WebCore/platform/graphics/cairo/RefPtrCairo.h
index 0429ec5..204d1e3 100644
--- a/WebCore/platform/graphics/cairo/RefPtrCairo.h
+++ b/WebCore/platform/graphics/cairo/RefPtrCairo.h
@@ -26,6 +26,7 @@ typedef struct _cairo cairo_t;
 typedef struct _cairo_surface cairo_surface_t;
 typedef struct _cairo_font_face cairo_font_face_t;
 typedef struct _cairo_scaled_font cairo_scaled_font_t;
+typedef struct _cairo_pattern cairo_pattern_t;
 
 #if defined(USE_FREETYPE)
 typedef struct _FcPattern FcPattern;
@@ -45,6 +46,9 @@ template<> void derefIfNotNull(cairo_font_face_t* ptr);
 template<> void refIfNotNull(cairo_scaled_font_t* ptr);
 template<> void derefIfNotNull(cairo_scaled_font_t* ptr);
 
+template<> void refIfNotNull(cairo_pattern_t*);
+template<> void derefIfNotNull(cairo_pattern_t*);
+
 #if defined(USE_FREETYPE)
 template<> void refIfNotNull(FcPattern* ptr);
 template<> void derefIfNotNull(FcPattern* ptr);
diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp
index 8df5cda..fe6c9e9 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.cpp
+++ b/WebCore/platform/gtk/RenderThemeGtk.cpp
@@ -3,6 +3,7 @@
  * Copyright (C) 2007 Alp Toker <alp at atoker.com>
  * Copyright (C) 2008 Collabora Ltd.
  * Copyright (C) 2009 Kenneth Rohde Christiansen
+ * Copyright (C) 2010 Igalia S.L.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -40,6 +41,7 @@
 #include "Scrollbar.h"
 #include "TimeRanges.h"
 #include "UserAgentStyleSheets.h"
+#include "WidgetRenderingContext.h"
 #include "gtkdrawing.h"
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
@@ -151,15 +153,26 @@ RenderThemeGtk::RenderThemeGtk()
     , m_pauseButton(0)
     , m_seekBackButton(0)
     , m_seekForwardButton(0)
-    , m_partsTable(adoptPlatformRef(g_hash_table_new_full(0, 0, 0, g_free)))
+#ifdef GTK_API_VERSION_2
+    , m_themePartsHaveRGBAColormap(true)
+#endif
 {
-    if (!mozGtkRefCount) {
-        moz_gtk_init();
 
-        // Use the theme parts for the default drawable.
-        moz_gtk_use_theme_parts(partsForDrawable(0));
+    memset(&m_themeParts, 0, sizeof(GtkThemeParts));
+#ifdef GTK_API_VERSION_2
+    GdkColormap* colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default());
+    if (!colormap) {
+        m_themePartsHaveRGBAColormap = false;
+        colormap = gdk_screen_get_default_colormap(gdk_screen_get_default());
     }
+    m_themeParts.colormap = colormap;
+#endif
 
+    // Initialize the Mozilla theme drawing code.
+    if (!mozGtkRefCount) {
+        moz_gtk_init();
+        moz_gtk_use_theme_parts(&m_themeParts);
+    }
     ++mozGtkRefCount;
 
 #if ENABLE(VIDEO)
@@ -182,36 +195,19 @@ RenderThemeGtk::~RenderThemeGtk()
     m_seekBackButton.clear();
     m_seekForwardButton.clear();
 
-    GList* values = g_hash_table_get_values(m_partsTable.get());
-    for (guint i = 0; i < g_list_length(values); i++)
-        moz_gtk_destroy_theme_parts_widgets(
-            static_cast<GtkThemeParts*>(g_list_nth_data(values, i)));
-
     gtk_widget_destroy(m_gtkWindow);
 }
 
-GtkThemeParts* RenderThemeGtk::partsForDrawable(GdkDrawable* drawable) const
+void RenderThemeGtk::getIndicatorMetrics(ControlPart part, int& indicatorSize, int& indicatorSpacing) const
 {
-#ifdef GTK_API_VERSION_2
-    // A null drawable represents the default screen colormap.
-    GdkColormap* colormap = 0;
-    if (!drawable)
-        colormap = gdk_screen_get_default_colormap(gdk_screen_get_default());
-    else
-        colormap = gdk_drawable_get_colormap(drawable);
-
-    GtkThemeParts* parts = static_cast<GtkThemeParts*>(g_hash_table_lookup(m_partsTable.get(), colormap));
-    if (!parts) {
-        parts = g_new0(GtkThemeParts, 1);
-        parts->colormap = colormap;
-        g_hash_table_insert(m_partsTable.get(), colormap, parts);
+    ASSERT(part == CheckboxPart || part == RadioPart);
+    if (part == CheckboxPart) {
+        moz_gtk_checkbox_get_metrics(&indicatorSize, &indicatorSpacing);
+        return;
     }
-#else
-    // For GTK+ 3.0 we no longer have to worry about maintaining a set of widgets per-colormap.
-    static GtkThemeParts* parts = g_slice_new0(GtkThemeParts);
-#endif // GTK_API_VERSION_2
 
-    return parts;
+    // RadioPart
+    moz_gtk_radio_get_metrics(&indicatorSize, &indicatorSpacing);
 }
 
 static bool supportsFocus(ControlPart appearance)
@@ -289,69 +285,6 @@ static void adjustMozillaStyle(const RenderThemeGtk* theme, RenderStyle* style,
     style->setPaddingBottom(Length(ypadding + bottom, Fixed));
 }
 
-#ifdef GTK_API_VERSION_2
-bool RenderThemeGtk::paintMozillaGtkWidget(GtkThemeWidgetType type, GraphicsContext* context, const IntRect& rect, GtkWidgetState* widgetState, int flags, GtkTextDirection textDirection)
-{
-    // Painting is disabled so just claim to have succeeded
-    if (context->paintingDisabled())
-        return false;
-
-    PlatformRefPtr<GdkDrawable> drawable(context->gdkDrawable());
-    GdkRectangle paintRect, clipRect;
-    if (drawable) {
-        AffineTransform ctm = context->getCTM();
-        IntPoint pos = ctm.mapPoint(rect.location());
-        paintRect = IntRect(pos.x(), pos.y(), rect.width(), rect.height());
-
-        // Intersect the cairo rectangle with the target widget region. This  will
-        // prevent the theme drawing code from drawing into regions that cairo will
-        // clip anyway.
-        double clipX1, clipX2, clipY1, clipY2;
-        cairo_clip_extents(context->platformContext(), &clipX1, &clipY1, &clipX2, &clipY2);
-        IntPoint clipPos = ctm.mapPoint(IntPoint(clipX1, clipY1));
-
-        clipRect.width = clipX2 - clipX1;
-        clipRect.height = clipY2 - clipY1;
-        clipRect.x = clipPos.x();
-        clipRect.y = clipPos.y();
-        gdk_rectangle_intersect(&paintRect, &clipRect, &clipRect);
-
-    } else {
-        // In some situations, like during print previews, this GraphicsContext is not
-        // backed by a GdkDrawable. In those situations, we render onto a pixmap and then
-        // copy the rendered data back to the GraphicsContext via Cairo.
-        drawable = adoptPlatformRef(gdk_pixmap_new(0, rect.width(), rect.height(), gdk_visual_get_depth(gdk_visual_get_system())));
-        paintRect = clipRect = IntRect(0, 0, rect.width(), rect.height());
-    }
-
-    moz_gtk_use_theme_parts(partsForDrawable(drawable.get()));
-    bool success = moz_gtk_widget_paint(type, drawable.get(), &paintRect, &clipRect, widgetState, flags, textDirection) == MOZ_GTK_SUCCESS;
-
-    // If the drawing was successful and we rendered onto a pixmap, copy the
-    // results back to the original GraphicsContext.
-    if (success && !context->gdkDrawable()) {
-        cairo_t* cairoContext = context->platformContext();
-        cairo_save(cairoContext);
-        gdk_cairo_set_source_pixmap(cairoContext, drawable.get(), rect.x(), rect.y());
-        cairo_paint(cairoContext);
-        cairo_restore(cairoContext);
-    }
-
-    return !success;
-}
-#else
-bool RenderThemeGtk::paintMozillaGtkWidget(GtkThemeWidgetType type, GraphicsContext* context, const IntRect& rect, GtkWidgetState* widgetState, int flags, GtkTextDirection textDirection)
-{
-    // Painting is disabled so just claim to have succeeded
-    if (context->paintingDisabled())
-        return false;
-
-    // false == success, because of awesome.
-    GdkRectangle paintRect = rect;
-    return moz_gtk_widget_paint(type, context->platformContext(), &paintRect, widgetState, flags, textDirection) != MOZ_GTK_SUCCESS;
-}
-#endif
-
 bool RenderThemeGtk::paintRenderObject(GtkThemeWidgetType type, RenderObject* renderObject, GraphicsContext* context, const IntRect& rect, int flags)
 {
     // Painting is disabled so just claim to have succeeded
@@ -382,8 +315,8 @@ bool RenderThemeGtk::paintRenderObject(GtkThemeWidgetType type, RenderObject* re
     else
         widgetState.depressed = false;
 
-    GtkTextDirection textDirection = gtkTextDirection(renderObject->style()->direction());
-    return paintMozillaGtkWidget(type, context, rect, &widgetState, flags, textDirection);
+    WidgetRenderingContext widgetContext(context, rect);
+    return !widgetContext.paintMozillaWidget(type, &widgetState, flags, gtkTextDirection(renderObject->style()->direction()));
 }
 
 static void setToggleSize(const RenderThemeGtk* theme, RenderStyle* style, ControlPart appearance)
@@ -394,19 +327,7 @@ static void setToggleSize(const RenderThemeGtk* theme, RenderStyle* style, Contr
 
     // FIXME: This is probably not correct use of indicatorSize and indicatorSpacing.
     gint indicatorSize, indicatorSpacing;
-
-    switch (appearance) {
-    case CheckboxPart:
-        if (moz_gtk_checkbox_get_metrics(&indicatorSize, &indicatorSpacing) != MOZ_GTK_SUCCESS)
-            return;
-        break;
-    case RadioPart:
-        if (moz_gtk_radio_get_metrics(&indicatorSize, &indicatorSpacing) != MOZ_GTK_SUCCESS)
-            return;
-        break;
-    default:
-        return;
-    }
+    theme->getIndicatorMetrics(appearance, indicatorSize, indicatorSpacing);
 
     // Other ports hard-code this to 13, but GTK+ users tend to demand the native look.
     // It could be made a configuration option values other than 13 actually break site compatibility.
@@ -614,7 +535,7 @@ bool RenderThemeGtk::paintSliderTrack(RenderObject* object, const PaintInfo& inf
     if (part == SliderVerticalPart)
         gtkPart = MOZ_GTK_SCALE_VERTICAL;
 
-    return paintRenderObject(gtkPart, object, info.context, toRenderBox(object)->absoluteContentBox());
+    return paintRenderObject(gtkPart, object, info.context, rect);
 }
 
 void RenderThemeGtk::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
diff --git a/WebCore/platform/gtk/RenderThemeGtk.h b/WebCore/platform/gtk/RenderThemeGtk.h
index 6d324b6..ac08cf1 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.h
+++ b/WebCore/platform/gtk/RenderThemeGtk.h
@@ -83,7 +83,7 @@ public:
     virtual String extraMediaControlsStyleSheet();
 #endif
 
-    bool paintMozillaGtkWidget(GtkThemeWidgetType, GraphicsContext*, const IntRect&, GtkWidgetState*, int flags, GtkTextDirection = GTK_TEXT_DIR_NONE);
+    void getIndicatorMetrics(ControlPart, int& indicatorSize, int& indicatorSpacing) const;
 
     GtkWidget* gtkScrollbar();
 
@@ -169,7 +169,6 @@ private:
     GtkContainer* gtkContainer() const;
 
     bool paintRenderObject(GtkThemeWidgetType, RenderObject*, GraphicsContext*, const IntRect& rect, int flags = 0);
-    GtkThemeParts* partsForDrawable(GdkDrawable*) const;
 
     mutable GtkWidget* m_gtkWindow;
     mutable GtkContainer* m_gtkContainer;
@@ -193,9 +192,11 @@ private:
     RefPtr<Image> m_pauseButton;
     RefPtr<Image> m_seekBackButton;
     RefPtr<Image> m_seekForwardButton;
-    Page* m_page;
-    PlatformRefPtr<GHashTable> m_partsTable;
-
+    GtkThemeParts m_themeParts;
+#ifdef GTK_API_VERSION_2
+    bool m_themePartsHaveRGBAColormap;
+#endif
+    friend class WidgetRenderingContext;
 };
 
 }
diff --git a/WebCore/platform/gtk/ScrollbarThemeGtk.cpp b/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
index 19b897c..f92dd20 100644
--- a/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
+++ b/WebCore/platform/gtk/ScrollbarThemeGtk.cpp
@@ -30,6 +30,7 @@
 #include "RenderThemeGtk.h"
 #include "ScrollView.h"
 #include "Scrollbar.h"
+#include "WidgetRenderingContext.h"
 #include "gtkdrawing.h"
 #include <gtk/gtk.h>
 
@@ -216,7 +217,8 @@ void ScrollbarThemeGtk::paintTrackBackground(GraphicsContext* context, Scrollbar
         fullScrollbarRect = IntRect(scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height());
 
     GtkThemeWidgetType type = scrollbar->orientation() == VerticalScrollbar ? MOZ_GTK_SCROLLBAR_TRACK_VERTICAL : MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL;
-    static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->paintMozillaGtkWidget(type, context, fullScrollbarRect, &state, 0);
+    WidgetRenderingContext widgetContext(context, fullScrollbarRect);
+    widgetContext.paintMozillaWidget(type, &state, 0);
 }
 
 void ScrollbarThemeGtk::paintScrollbarBackground(GraphicsContext* context, Scrollbar* scrollbar)
@@ -224,7 +226,8 @@ void ScrollbarThemeGtk::paintScrollbarBackground(GraphicsContext* context, Scrol
     // This is unused by the moz_gtk_scrollecd_window_paint.
     GtkWidgetState state;
     IntRect fullScrollbarRect = IntRect(scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height());
-    static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->paintMozillaGtkWidget(MOZ_GTK_SCROLLED_WINDOW, context, fullScrollbarRect, &state, 0);
+    WidgetRenderingContext widgetContext(context, fullScrollbarRect);
+    widgetContext.paintMozillaWidget(MOZ_GTK_SCROLLED_WINDOW, &state, 0);
 }
 
 void ScrollbarThemeGtk::paintThumb(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
@@ -240,7 +243,8 @@ void ScrollbarThemeGtk::paintThumb(GraphicsContext* context, Scrollbar* scrollba
     state.curpos = scrollbar->currentPos();
 
     GtkThemeWidgetType type = scrollbar->orientation() == VerticalScrollbar ? MOZ_GTK_SCROLLBAR_THUMB_VERTICAL : MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL;
-    static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->paintMozillaGtkWidget(type, context, rect, &state, 0);
+    WidgetRenderingContext widgetContext(context, rect);
+    widgetContext.paintMozillaWidget(type, &state, 0);
 }
 
 IntRect ScrollbarThemeGtk::thumbRect(Scrollbar* scrollbar, const IntRect& unconstrainedTrackRect)
@@ -256,6 +260,9 @@ IntRect ScrollbarThemeGtk::thumbRect(Scrollbar* scrollbar, const IntRect& uncons
 
 bool ScrollbarThemeGtk::paint(Scrollbar* scrollbar, GraphicsContext* graphicsContext, const IntRect& damageRect)
 {
+    if (graphicsContext->paintingDisabled())
+        return false;
+
     // Create the ScrollbarControlPartMask based on the damageRect
     ScrollbarControlPartMask scrollMask = NoPart;
 
@@ -348,7 +355,8 @@ void ScrollbarThemeGtk::paintButton(GraphicsContext* context, Scrollbar* scrollb
         state.inHover = FALSE;
     }
 
-    static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->paintMozillaGtkWidget(MOZ_GTK_SCROLLBAR_BUTTON, context, rect, &state, flags);
+    WidgetRenderingContext widgetContext(context, rect);
+    widgetContext.paintMozillaWidget(MOZ_GTK_SCROLLBAR_BUTTON, &state, flags);
 }
 
 void ScrollbarThemeGtk::paintScrollCorner(ScrollView* view, GraphicsContext* context, const IntRect& cornerRect)
diff --git a/WebCore/platform/gtk/WidgetRenderingContext.h b/WebCore/platform/gtk/WidgetRenderingContext.h
new file mode 100644
index 0000000..3bb8065
--- /dev/null
+++ b/WebCore/platform/gtk/WidgetRenderingContext.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 Igalia S.L.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WidgetRenderingContext_h
+#define WidgetRenderingContext_h
+
+#include "IntRect.h"
+#include "gtkdrawing.h"
+
+namespace WebCore {
+
+class GraphicsContext;
+class RenderThemeGtk;
+
+class WidgetRenderingContext {
+public:
+    WidgetRenderingContext(GraphicsContext*, const IntRect&);
+    ~WidgetRenderingContext();
+    bool paintMozillaWidget(GtkThemeWidgetType, GtkWidgetState*, int flags, GtkTextDirection = GTK_TEXT_DIR_NONE);
+
+private:
+    GraphicsContext* m_graphicsContext;
+    IntRect m_targetRect;
+    GdkRectangle m_paintRect;
+    IntSize m_extraSpace;
+    bool m_hadError;
+
+#ifdef GTK_API_VERSION_2
+    GdkDrawable* m_target;
+#else
+    cairo_t* m_target;
+#endif
+
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/gtk/WidgetRenderingContextGtk2.cpp b/WebCore/platform/gtk/WidgetRenderingContextGtk2.cpp
new file mode 100644
index 0000000..b8712d2
--- /dev/null
+++ b/WebCore/platform/gtk/WidgetRenderingContextGtk2.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2010 Sencha, Inc.
+ * Copyright (C) 2010 Igalia S.L.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef GTK_API_VERSION_2
+
+#include "config.h"
+#include "WidgetRenderingContext.h"
+
+#include "GraphicsContext.h"
+#include "RefPtrCairo.h"
+#include "RenderThemeGtk.h"
+#include "Timer.h"
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+static GdkPixmap* gScratchBuffer = 0;
+static void purgeScratchBuffer()
+{
+    if (gScratchBuffer)
+        g_object_unref(gScratchBuffer);
+    gScratchBuffer = 0;
+}
+
+// FIXME: Perhaps we can share some of this code with the ContextShadowCairo.
+// Widget rendering needs a scratch image as the buffer for the intermediate
+// render. Instead of creating and destroying the buffer for every operation,
+// we create a buffer which will be automatically purged via a timer.
+class PurgeScratchBufferTimer : public TimerBase {
+private:
+    virtual void fired() { purgeScratchBuffer(); }
+};
+static PurgeScratchBufferTimer purgeScratchBufferTimer;
+static void scheduleScratchBufferPurge()
+{
+    if (purgeScratchBufferTimer.isActive())
+        purgeScratchBufferTimer.stop();
+    purgeScratchBufferTimer.startOneShot(2);
+}
+
+static IntSize getExtraSpaceForWidget(RenderThemeGtk* theme)
+{
+    // Checkboxes and scrollbar thumbs often draw outside their boundaries. Here we figure out
+    // the maximum amount of space we need for any type of widget and use that to increase the
+    // size of the scratch buffer, while preserving the final widget position.
+
+    // The checkbox extra space is calculated by looking at the widget style.
+    int indicatorSize, indicatorSpacing;
+    theme->getIndicatorMetrics(CheckboxPart, indicatorSize, indicatorSpacing);
+    IntSize extraSpace(indicatorSpacing, indicatorSpacing);
+
+    // Scrollbar thumbs need at least an extra pixel along their movement axis.
+    return extraSpace.expandedTo(IntSize(1, 1));
+}
+
+WidgetRenderingContext::WidgetRenderingContext(GraphicsContext* graphicsContext, const IntRect& targetRect)
+    : m_graphicsContext(graphicsContext)
+    , m_targetRect(targetRect)
+    , m_hadError(false)
+{
+    RenderThemeGtk* theme = static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get());
+
+    // Fallback: We failed to create an RGBA colormap earlier, so we cannot properly paint 
+    // to a temporary surface and preserve transparency. To ensure decent widget rendering, just
+    // paint directly to the target drawable. This will not render CSS rotational transforms properly.
+    if (!theme->m_themePartsHaveRGBAColormap && graphicsContext->gdkDrawable()) {
+        m_paintRect = graphicsContext->getCTM().mapRect(targetRect);
+        m_target = graphicsContext->gdkDrawable();
+        return;
+    }
+
+    // Some widgets render outside their rectangles. We need to account for this.
+    m_extraSpace = getExtraSpaceForWidget(theme);
+
+    // Offset the target rectangle so that the extra space is within the boundaries of the scratch buffer.
+    m_paintRect = IntRect(IntPoint(m_extraSpace.width(), m_extraSpace.height()),
+                                   m_targetRect.size());
+
+    int width = m_targetRect.width() + (m_extraSpace.width() * 2);
+    int height = m_targetRect.height() + (m_extraSpace.height() * 2);
+    int scratchWidth = 0;
+    int scratchHeight = 0;
+    if (gScratchBuffer)
+        gdk_drawable_get_size(gScratchBuffer, &scratchWidth, &scratchHeight);
+
+    // We do not need to recreate the buffer if the current buffer is large enough.
+    if (!gScratchBuffer || scratchWidth < width || scratchHeight < height) {
+        purgeScratchBuffer();
+        // Round to the nearest 32 pixels so we do not grow the buffer for similar sized requests.
+        width = (1 + (width >> 5)) << 5;
+        height = (1 + (height >> 5)) << 5;
+
+        gScratchBuffer = gdk_pixmap_new(0, width, height, gdk_colormap_get_visual(theme->m_themeParts.colormap)->depth);
+        gdk_drawable_set_colormap(gScratchBuffer, theme->m_themeParts.colormap);
+    }
+    m_target = gScratchBuffer;
+
+    // Clear the scratch buffer.
+    RefPtr<cairo_t> scratchBufferContext = adoptRef(gdk_cairo_create(gScratchBuffer));
+    cairo_set_operator(scratchBufferContext.get(), CAIRO_OPERATOR_CLEAR);
+    cairo_paint(scratchBufferContext.get());
+}
+
+WidgetRenderingContext::~WidgetRenderingContext()
+{
+    // We do not need to blit back to the target in the fallback case. See above.
+    RenderThemeGtk* theme = static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get());
+    if (!theme->m_themePartsHaveRGBAColormap && m_graphicsContext->gdkDrawable())
+        return;
+
+    // Don't paint the results back if there was an error.
+    if (m_hadError) {
+        scheduleScratchBufferPurge();
+        return;
+    }
+
+    // FIXME: It's unclear if it is necessary to preserve the current source here.
+    cairo_t* cairoContext = m_graphicsContext->platformContext();
+    RefPtr<cairo_pattern_t> previousSource(cairo_get_source(cairoContext));
+
+    // The blit rectangle is the original target rectangle adjusted for any extra space.
+    IntRect fullTargetRect(m_targetRect);
+    fullTargetRect.inflateX(m_extraSpace.width());
+    fullTargetRect.inflateY(m_extraSpace.height());
+
+    gdk_cairo_set_source_pixmap(cairoContext, gScratchBuffer, fullTargetRect.x(), fullTargetRect.y());
+    cairo_rectangle(cairoContext, fullTargetRect.x(), fullTargetRect.y(), fullTargetRect.width(), fullTargetRect.height());
+    cairo_fill(cairoContext);
+    cairo_set_source(cairoContext, previousSource.get());
+    scheduleScratchBufferPurge();
+}
+
+bool WidgetRenderingContext::paintMozillaWidget(GtkThemeWidgetType type, GtkWidgetState* state, int flags, GtkTextDirection textDirection)
+{
+    // Sometimes moz_gtk_widget_paint modifies the clipping rectangle, so we must use a copy.
+    GdkRectangle clipRect = m_paintRect;
+    m_hadError = moz_gtk_widget_paint(type, m_target, &clipRect, &m_paintRect,
+        state, flags, textDirection) != MOZ_GTK_SUCCESS;
+    return !m_hadError;
+}
+
+}
+
+#endif // GTK_API_VERSION_2
diff --git a/WebCore/platform/gtk/WidgetRenderingContextGtk3.cpp b/WebCore/platform/gtk/WidgetRenderingContextGtk3.cpp
new file mode 100644
index 0000000..1665785
--- /dev/null
+++ b/WebCore/platform/gtk/WidgetRenderingContextGtk3.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "WidgetRenderingContext.h"
+
+#include "GraphicsContext.h"
+#include "IntRect.h"
+
+#ifndef GTK_API_VERSION_2
+
+namespace WebCore {
+
+WidgetRenderingContext::WidgetRenderingContext(GraphicsContext* graphicsContext, const IntRect& targetRect)
+    : m_graphicsContext(graphicsContext)
+    , m_targetRect(targetRect)
+    , m_paintRect(targetRect)
+    , m_hadError(false)
+    , m_target(context->platformContext())
+{
+}
+
+WidgetRenderingContext::~WidgetRenderingContext()
+{
+}
+
+bool WidgetRenderingContext::paintMozillaWidget(GtkThemeWidgetType type, GtkWidgetState* state, int flags, GtkTextDirection textDirection)
+{
+    m_hadError = moz_gtk_widget_paint(type, m_target, &m_paintRect, state, flags, textDirection) != MOZ_GTK_SUCCESS;
+    return !m_hadError;
+}
+
+}
+
+#endif // !GTK_API_VERSION_2

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list