Blob Blame History Raw
From a47531dc2f5b90eedb4afb4dd2b3b52fb5a59365 Mon Sep 17 00:00:00 2001
From: Pranav Kant <pranavk@libreoffice.org>
Date: Sun, 1 Nov 2015 13:22:25 +0530
Subject: [PATCH 261/398] lokdocview: Separate "painting" and "saving" of tiles

Lets separate the task of painting the tile, and saving the tile
in tile buffer using GAsyncReadyCallback. This will provide us
with better control over tiles -- cancelling the painting operation,
and filtering tiles that should not be saved in the tile buffer.

Change-Id: I6aae928d8cc0c906034570ed0e9a054763d493a3
Reviewed-on: https://gerrit.libreoffice.org/19725
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Tested-by: Miklos Vajna <vmiklos@collabora.co.uk>
(cherry picked from commit de0c7e1783edc6a36037f2657f823dc9812c0804)
---
 libreofficekit/source/gtk/lokdocview.cxx | 56 ++++++++++++++++++++++++++++----
 libreofficekit/source/gtk/tilebuffer.cxx | 10 ------
 2 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 2ec27305af4e..867c0d165448 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -873,6 +873,47 @@ renderGraphicHandle(LOKDocView* pDocView,
     }
 }
 
+/// Finishes the paint tile operation and returns the result, if any
+static gpointer
+paintTileFinish(LOKDocView* pDocView, GAsyncResult* res, GError **error)
+{
+    GTask* task = G_TASK(res);
+
+    g_return_val_if_fail(LOK_IS_DOC_VIEW(pDocView), NULL);
+    g_return_val_if_fail(g_task_is_valid(res, pDocView), NULL);
+    g_return_val_if_fail(error == NULL || *error == NULL, NULL);
+
+    return g_task_propagate_pointer(task, error);
+}
+
+/// Callback called in the main UI thread when paintTileInThread in LOK thread has finished
+static void
+paintTileCallback(GObject* sourceObject, GAsyncResult* res, gpointer userData)
+{
+    LOKDocView* pDocView = LOK_DOC_VIEW(sourceObject);
+    LOKDocViewPrivate& priv = getPrivate(pDocView);
+    LOEvent* pLOEvent = static_cast<LOEvent*>(userData);
+    std::unique_ptr<TileBuffer>& buffer = priv->m_pTileBuffer;
+    int index = pLOEvent->m_nPaintTileX * buffer->m_nWidth + pLOEvent->m_nPaintTileY;
+    GError* error;
+
+    error = NULL;
+    GdkPixbuf* pPixBuf = static_cast<GdkPixbuf*>(paintTileFinish(pDocView, res, &error));
+    if (error != NULL)
+    {
+        g_warning("Unable to get painted GdkPixbuf: %s", error->message);
+        g_error_free(error);
+        return;
+    }
+
+    buffer->m_mTiles[index].setPixbuf(pPixBuf);
+    buffer->m_mTiles[index].valid = true;
+    gdk_threads_add_idle(queueDraw, GTK_WIDGET(pDocView));
+
+    g_object_unref(pPixBuf);
+}
+
+
 static gboolean
 renderDocument(LOKDocView* pDocView, cairo_t* pCairo)
 {
@@ -921,7 +962,13 @@ renderDocument(LOKDocView* pDocView, cairo_t* pCairo)
 
             if (bPaint)
             {
-                GTask* task = g_task_new(pDocView, NULL, NULL, NULL);
+                LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE);
+                pLOEvent->m_nPaintTileX = nRow;
+                pLOEvent->m_nPaintTileY = nColumn;
+                pLOEvent->m_fPaintTileZoom = priv->m_fZoom;
+                GTask* task = g_task_new(pDocView, NULL, paintTileCallback, pLOEvent);
+                g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
+
                 Tile& currentTile = priv->m_pTileBuffer->getTile(nRow, nColumn, priv->m_fZoom, task, priv->lokThreadPool);
                 GdkPixbuf* pPixBuf = currentTile.getBuffer();
                 gdk_cairo_set_source_pixbuf (pCairo, pPixBuf,
@@ -1516,12 +1563,7 @@ paintTileInThread (gpointer data)
                                          pixelToTwip(nTileSizePixels, pLOEvent->m_fPaintTileZoom),
                                          pixelToTwip(nTileSizePixels, pLOEvent->m_fPaintTileZoom));
 
-    //create a mapping for it
-    buffer->m_mTiles[index].setPixbuf(pPixBuf);
-    buffer->m_mTiles[index].valid = true;
-    gdk_threads_add_idle(queueDraw, GTK_WIDGET(pDocView));
-
-    g_object_unref(pPixBuf);
+    g_task_return_pointer(task, pPixBuf, g_object_unref);
 }
 
 
diff --git a/libreofficekit/source/gtk/tilebuffer.cxx b/libreofficekit/source/gtk/tilebuffer.cxx
index 811fcc61ef46..6c9847674e53 100644
--- a/libreofficekit/source/gtk/tilebuffer.cxx
+++ b/libreofficekit/source/gtk/tilebuffer.cxx
@@ -93,11 +93,6 @@ Tile& TileBuffer::getTile(int x, int y, float fZoom, GTask* task,
 
     if (m_mTiles.find(index) != m_mTiles.end() && !m_mTiles[index].valid)
     {
-        LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE);
-        pLOEvent->m_nPaintTileX = x;
-        pLOEvent->m_nPaintTileY = y;
-        pLOEvent->m_fPaintTileZoom = fZoom;
-        g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
         g_thread_pool_push(lokThreadPool, g_object_ref(task), &error);
         if (error != NULL)
         {
@@ -108,11 +103,6 @@ Tile& TileBuffer::getTile(int x, int y, float fZoom, GTask* task,
     }
     else if(m_mTiles.find(index) == m_mTiles.end())
     {
-        LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE);
-        pLOEvent->m_nPaintTileX = x;
-        pLOEvent->m_nPaintTileY = y;
-        pLOEvent->m_fPaintTileZoom = fZoom;
-        g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
         g_thread_pool_push(lokThreadPool, g_object_ref(task), &error);
         if (error != NULL)
         {
-- 
2.12.0