[Libreoffice-commits] core.git: vcl/inc vcl/Library_vclplug_gtk3.mk vcl/unx

Caolán McNamara caolanm at redhat.com
Mon Mar 23 05:47:54 PDT 2015


 vcl/Library_vclplug_gtk3.mk                   |    1 
 vcl/inc/unx/gtk/gtkframe.hxx                  |    2 
 vcl/inc/unx/gtk/gtkgdi.hxx                    |    7 +
 vcl/unx/gtk/window/gtksalframe.cxx            |   12 ++
 vcl/unx/gtk3/gdi/cairo_gtk3_cairo.cxx         |  117 ++++++++++++++++++++++++++
 vcl/unx/gtk3/gdi/cairo_gtk3_cairo.hxx         |   51 +++++++++++
 vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx |   24 +++++
 7 files changed, 208 insertions(+), 6 deletions(-)

New commits:
commit 707a8bc1e47b57421412de3f1f47ec31be28c5a9
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Mar 18 09:57:41 2015 +0000

    enable gtk3 to support cairo canvas
    
    Change-Id: Ie6edf155288d1514ce7a0c859ba751cdebc93391

diff --git a/vcl/Library_vclplug_gtk3.mk b/vcl/Library_vclplug_gtk3.mk
index 5ba5722..515a81c 100644
--- a/vcl/Library_vclplug_gtk3.mk
+++ b/vcl/Library_vclplug_gtk3.mk
@@ -102,6 +102,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gtk3,\
     vcl/unx/gtk3/app/gtk3gtkinst \
     vcl/unx/gtk3/app/gtk3gtksys \
     vcl/unx/gtk3/app/gtk3fpicker \
+    vcl/unx/gtk3/gdi/cairo_gtk3_cairo \
     vcl/unx/gtk3/gdi/gtk3cairotextrender \
     vcl/unx/gtk3/gdi/gtk3gtkprintwrapper \
     vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk \
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
index 56225cc..d5148b7 100644
--- a/vcl/inc/unx/gtk/gtkframe.hxx
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
@@ -343,7 +343,7 @@ public:
 
 #if GTK_CHECK_VERSION(3,0,0)
     // only for gtk3 ...
-    cairo_t* getCairoContext();
+    cairo_t* getCairoContext() const;
     void damaged (const basegfx::B2IBox& rDamageRect);
 #endif
     virtual ~GtkSalFrame();
diff --git a/vcl/inc/unx/gtk/gtkgdi.hxx b/vcl/inc/unx/gtk/gtkgdi.hxx
index 26f2efb..2c8a8dc 100644
--- a/vcl/inc/unx/gtk/gtkgdi.hxx
+++ b/vcl/inc/unx/gtk/gtkgdi.hxx
@@ -49,11 +49,16 @@ public:
                                                     const OUString& rCaption,
                                                     Rectangle &rNativeBoundingRegion,
                                                     Rectangle &rNativeContentRegion ) SAL_OVERRIDE;
+    virtual bool        SupportsCairo() const SAL_OVERRIDE;
+    virtual cairo::SurfaceSharedPtr CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const SAL_OVERRIDE;
+    virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const SAL_OVERRIDE;
+    void WidgetQueueDraw() const;
+
     void updateSettings( AllSettings& rSettings );
     static void refreshFontconfig( GtkSettings *pSettings );
     static void signalSettingsNotify( GObject*, GParamSpec *pSpec, gpointer );
 
-    cairo_t* getCairoContext();
+    cairo_t* getCairoContext() const;
 
     void clipRegion(cairo_t* cr);
 
diff --git a/vcl/unx/gtk/window/gtksalframe.cxx b/vcl/unx/gtk/window/gtksalframe.cxx
index 9d1021a..b678d81 100644
--- a/vcl/unx/gtk/window/gtksalframe.cxx
+++ b/vcl/unx/gtk/window/gtksalframe.cxx
@@ -3356,7 +3356,7 @@ gboolean GtkSalFrame::signalCrossing( GtkWidget*, GdkEventCrossing* pEvent, gpoi
 
 #if GTK_CHECK_VERSION(3,0,0)
 
-cairo_t* GtkSalFrame::getCairoContext()
+cairo_t* GtkSalFrame::getCairoContext() const
 {
     basebmp::RawMemorySharedArray data = m_aFrame->getBuffer();
     basegfx::B2IVector size = m_aFrame->getSize();
@@ -3391,7 +3391,9 @@ void GtkSalFrame::damaged (const basegfx::B2IBox& rDamageRect)
     {
         static int frame;
         OString tmp("/tmp/frame" + OString::number(frame++) + ".png");
-        cairo_surface_write_to_png(cairo_get_target(getCairoContext()), tmp.getStr());
+        cairo_t* cr = getCairoContext();
+        cairo_surface_write_to_png(cairo_get_target(cr), tmp.getStr());
+        cairo_destroy(cr);
     }
 
     gtk_widget_queue_draw_area(m_pWindow,
@@ -3408,11 +3410,15 @@ gboolean GtkSalFrame::signalDraw( GtkWidget*, cairo_t *cr, gpointer frame )
 
     cairo_save(cr);
 
-    cairo_surface_t *pSurface = cairo_get_target(pThis->getCairoContext());
+    cairo_t* source = pThis->getCairoContext();
+    cairo_surface_t *pSurface = cairo_get_target(source);
+
     cairo_set_operator( cr, CAIRO_OPERATOR_OVER );
     cairo_set_source_surface(cr, pSurface, 0, 0);
     cairo_paint(cr);
 
+    cairo_destroy(source);
+
     cairo_restore(cr);
 
     cairo_surface_flush(cairo_get_target(cr));
diff --git a/vcl/unx/gtk3/gdi/cairo_gtk3_cairo.cxx b/vcl/unx/gtk3/gdi/cairo_gtk3_cairo.cxx
new file mode 100644
index 0000000..6917596
--- /dev/null
+++ b/vcl/unx/gtk3/gdi/cairo_gtk3_cairo.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <utility>
+
+#include "cairo_cairo.hxx"
+#include "cairo_gtk3_cairo.hxx"
+
+#include <vcl/sysdata.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/window.hxx>
+#include <basegfx/vector/b2isize.hxx>
+
+#include "unx/gtk/gtkgdi.hxx"
+
+namespace cairo
+{
+    /**
+     * Surface::Surface:     Create generic Canvas surface using given Cairo Surface
+     *
+     * @param pSurface Cairo Surface
+     *
+     * This constructor only stores data, it does no processing.
+     * It is used with e.g. cairo_image_surface_create_for_data()
+     *
+     * Set the mpSurface as pSurface
+     **/
+    Gtk3Surface::Gtk3Surface(const CairoSurfaceSharedPtr& pSurface)
+        : mpGraphics(NULL)
+        , cr(NULL)
+        , mpSurface(pSurface)
+    {}
+
+    /**
+     * Surface::Surface:   Create Canvas surface from Window reference.
+     * @param x horizontal location of the new surface
+     * @param y vertical location of the new surface
+     * @param width width of the new surface
+     * @param height height of the new surface
+     *
+     * Set the mpSurface to the new surface or NULL
+     **/
+    Gtk3Surface::Gtk3Surface(const GtkSalGraphics* pGraphics, int x, int y, int width, int height)
+        : mpGraphics(pGraphics)
+        , cr(pGraphics->getCairoContext())
+    {
+        cairo_surface_t* surface = cairo_get_target(cr);
+        mpSurface.reset(
+            cairo_surface_create_for_rectangle(surface, x, y, width, height),
+            &cairo_surface_destroy);
+    }
+
+    Gtk3Surface::~Gtk3Surface()
+    {
+        if (cr)
+            cairo_destroy(cr);
+    }
+
+    /**
+     * Surface::getCairo:  Create Cairo (drawing object) for the Canvas surface
+     *
+     * @return new Cairo or NULL
+     **/
+    CairoSharedPtr Gtk3Surface::getCairo() const
+    {
+        return CairoSharedPtr( cairo_create(mpSurface.get()),
+                               &cairo_destroy );
+    }
+
+    /**
+     * Surface::getSimilar:  Create new similar Canvas surface
+     * @param cairo_content_type format of the new surface (cairo_content_t from cairo/src/cairo.h)
+     * @param width width of the new surface
+     * @param height height of the new surface
+     *
+     * Creates a new Canvas surface. This normally creates platform native surface, even though
+     * generic function is used.
+     *
+     * Cairo surface from cairo_content_type (cairo_content_t)
+     *
+     * @return new surface or NULL
+     **/
+    SurfaceSharedPtr Gtk3Surface::getSimilar(int cairo_content_type, int width, int height ) const
+    {
+        return SurfaceSharedPtr(
+            new Gtk3Surface(
+                            CairoSurfaceSharedPtr(
+                                cairo_surface_create_similar( mpSurface.get(),
+                                    static_cast<cairo_content_t>(cairo_content_type), width, height ),
+                                &cairo_surface_destroy )));
+    }
+
+    void Gtk3Surface::flush() const
+    {
+        cairo_surface_flush(mpSurface.get());
+        //Wonder if there is any benefit in using cairo_fill/stroke extents on
+        //every canvas call and only redrawing the union of those in a
+        //poor-mans-damage tracking
+        if (mpGraphics)
+            mpGraphics->WidgetQueueDraw();
+    }
+
+    boost::shared_ptr<VirtualDevice> Gtk3Surface::createVirtualDevice() const
+    {
+        return boost::shared_ptr<VirtualDevice>(new VirtualDevice(NULL, Size(1, 1), 0));
+    }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/gdi/cairo_gtk3_cairo.hxx b/vcl/unx/gtk3/gdi/cairo_gtk3_cairo.hxx
new file mode 100644
index 0000000..1d6e36f
--- /dev/null
+++ b/vcl/unx/gtk3/gdi/cairo_gtk3_cairo.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_CANVAS_SOURCE_CAIRO_CAIRO_GTK3_CAIRO_HXX
+#define INCLUDED_CANVAS_SOURCE_CAIRO_CAIRO_GTK3_CAIRO_HXX
+
+#include <sal/config.h>
+
+#include <sal/types.h>
+
+#include <vcl/cairo.hxx>
+
+class GtkSalGraphics;
+class OutputDevice;
+
+namespace cairo {
+
+    class Gtk3Surface : public Surface
+    {
+        const GtkSalGraphics* mpGraphics;
+        cairo_t* cr;
+        CairoSurfaceSharedPtr mpSurface;
+    public:
+        /// takes over ownership of passed cairo_surface
+        explicit Gtk3Surface(const CairoSurfaceSharedPtr& pSurface);
+        /// create surface on subarea of given drawable
+        explicit Gtk3Surface(const GtkSalGraphics* pGraphics, int x, int y, int width, int height);
+
+        // Surface interface
+        virtual CairoSharedPtr getCairo() const SAL_OVERRIDE;
+        virtual CairoSurfaceSharedPtr getCairoSurface() const SAL_OVERRIDE { return mpSurface; }
+        virtual SurfaceSharedPtr getSimilar(int nContentType, int width, int height) const SAL_OVERRIDE;
+
+        virtual boost::shared_ptr<VirtualDevice> createVirtualDevice() const SAL_OVERRIDE;
+
+        virtual void flush() const SAL_OVERRIDE;
+
+        ~Gtk3Surface();
+    };
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx b/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx
index 3006d62..d92d6d9 100644
--- a/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx
@@ -17,6 +17,7 @@
 #include <vcl/settings.hxx>
 #include "fontmanager.hxx"
 #include "gtk3cairotextrender.hxx"
+#include "cairo_gtk3_cairo.hxx"
 
 GtkStyleContext* GtkSalGraphics::mpButtonStyle = NULL;
 GtkStyleContext* GtkSalGraphics::mpEntryStyle = NULL;
@@ -1447,6 +1448,27 @@ bool GtkSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nP
     return false;
 }
 
+bool GtkSalGraphics::SupportsCairo() const
+{
+    return true;
+}
+
+cairo::SurfaceSharedPtr GtkSalGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const
+{
+    return cairo::SurfaceSharedPtr(new cairo::Gtk3Surface(rSurface));
+}
+
+cairo::SurfaceSharedPtr GtkSalGraphics::CreateSurface(const OutputDevice& /*rRefDevice*/, int x, int y, int width, int height) const
+{
+    return cairo::SurfaceSharedPtr(new cairo::Gtk3Surface(this, x, y, width, height));
+}
+
+void GtkSalGraphics::WidgetQueueDraw() const
+{
+    //request gtk to sync the entire contents
+    gtk_widget_queue_draw(mpWindow);
+}
+
 static GtkWidget* gCacheWindow;
 static GtkWidget* gDumbContainer;
 
@@ -1551,7 +1573,7 @@ GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow )
     gtk_widget_path_free(path);
 }
 
-cairo_t* GtkSalGraphics::getCairoContext()
+cairo_t* GtkSalGraphics::getCairoContext() const
 {
     return mpFrame->getCairoContext();
 }


More information about the Libreoffice-commits mailing list