Commit d28afd73 authored by mrobinson@webkit.org's avatar mrobinson@webkit.org

2010-10-18 Martin Robinson <mrobinson@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@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
parent 8feda75d
2010-10-18 Martin Robinson <mrobinson@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@chromium.org>
Unreviewed Chromium rebaselines.
......@@ -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
......
2010-10-15 Martin Robinson <mrobinson@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@apple.com>
Reviewed by Simon Fraser.
......@@ -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 \
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -3,6 +3,7 @@
* Copyright (C) 2007 Alp Toker <alp@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
......
......@@ -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;
};
}
......
......@@ -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)
......
/*
* 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
/*
* 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*>(