summaryrefslogtreecommitdiff
path: root/libreofficekit
diff options
context:
space:
mode:
Diffstat (limited to 'libreofficekit')
-rw-r--r--libreofficekit/source/gtk/lokdocview.cxx38
-rw-r--r--libreofficekit/source/gtk/tilebuffer.cxx6
-rw-r--r--libreofficekit/source/gtk/tilebuffer.hxx15
3 files changed, 57 insertions, 2 deletions
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 82d119c262a8..dcf6d5ff77cd 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -912,7 +912,12 @@ paintTileCallback(GObject* sourceObject, GAsyncResult* res, gpointer userData)
GdkPixbuf* pPixBuf = static_cast<GdkPixbuf*>(paintTileFinish(pDocView, res, &error));
if (error != NULL)
{
- g_warning("Unable to get painted GdkPixbuf: %s", error->message);
+ if (error->domain == LOK_TILEBUFFER_ERROR &&
+ error->code == LOK_TILEBUFFER_CHANGED)
+ g_info("Skipping paint tile request because corresponding"
+ "tile buffer has been destroyed");
+ else
+ g_warning("Unable to get painted GdkPixbuf: %s", error->message);
g_error_free(error);
return;
}
@@ -977,6 +982,7 @@ renderDocument(LOKDocView* pDocView, cairo_t* pCairo)
pLOEvent->m_nPaintTileX = nRow;
pLOEvent->m_nPaintTileY = nColumn;
pLOEvent->m_fPaintTileZoom = priv->m_fZoom;
+ pLOEvent->m_pTileBuffer = &*priv->m_pTileBuffer;
GTask* task = g_task_new(pDocView, NULL, paintTileCallback, pLOEvent);
g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
@@ -1541,6 +1547,17 @@ paintTileInThread (gpointer data)
LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
LOKDocViewPrivate& priv = getPrivate(pDocView);
LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task));
+
+ // check if "source" tile buffer is different from "current" tile buffer
+ if (pLOEvent->m_pTileBuffer != &*priv->m_pTileBuffer)
+ {
+ pLOEvent->m_pTileBuffer = nullptr;
+ g_task_return_new_error(task,
+ LOK_TILEBUFFER_ERROR,
+ LOK_TILEBUFFER_CHANGED,
+ "TileBuffer has changed");
+ return;
+ }
std::unique_ptr<TileBuffer>& buffer = priv->m_pTileBuffer;
int index = pLOEvent->m_nPaintTileX * buffer->m_nWidth + pLOEvent->m_nPaintTileY;
if (buffer->m_mTiles.find(index) != buffer->m_mTiles.end() &&
@@ -1550,7 +1567,10 @@ paintTileInThread (gpointer data)
GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, nTileSizePixels, nTileSizePixels);
if (!pPixBuf)
{
- g_info ("Error allocating memory to pixbuf");
+ g_task_return_new_error(task,
+ LOK_TILEBUFFER_ERROR,
+ LOK_TILEBUFFER_MEMORY,
+ "Error allocating memory to GdkPixbuf");
return;
}
@@ -1574,6 +1594,20 @@ paintTileInThread (gpointer data)
pixelToTwip(nTileSizePixels, pLOEvent->m_fPaintTileZoom),
pixelToTwip(nTileSizePixels, pLOEvent->m_fPaintTileZoom));
+ // Its likely that while the tilebuffer has changed, one of the paint tile
+ // requests has passed the previous check at start of this function, and has
+ // rendered the tile already. We want to stop such rendered tiles from being
+ // stored in new tile buffer.
+ if (pLOEvent->m_pTileBuffer != &*priv->m_pTileBuffer)
+ {
+ pLOEvent->m_pTileBuffer = nullptr;
+ g_task_return_new_error(task,
+ LOK_TILEBUFFER_ERROR,
+ LOK_TILEBUFFER_CHANGED,
+ "TileBuffer has changed");
+ return;
+ }
+
g_task_return_pointer(task, pPixBuf, g_object_unref);
}
diff --git a/libreofficekit/source/gtk/tilebuffer.cxx b/libreofficekit/source/gtk/tilebuffer.cxx
index 6d447a8dc296..330b44675c9c 100644
--- a/libreofficekit/source/gtk/tilebuffer.cxx
+++ b/libreofficekit/source/gtk/tilebuffer.cxx
@@ -115,4 +115,10 @@ void LOEvent::destroy(void* pMemory)
delete pLOEvent;
}
+GQuark
+LOKTileBufferErrorQuark(void)
+{
+ return g_quark_from_static_string("lok-tilebuffer-error");
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx
index e7a794a8a283..7127e0b1b498 100644
--- a/libreofficekit/source/gtk/tilebuffer.hxx
+++ b/libreofficekit/source/gtk/tilebuffer.hxx
@@ -19,6 +19,8 @@
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <LibreOfficeKit/LibreOfficeKitGtk.h>
+#define LOK_TILEBUFFER_ERROR (LOKTileBufferErrorQuark())
+
// We know that VirtualDevices use a DPI of 96.
const int DPI = 96;
// Lets use a square of side 256 pixels for each tile.
@@ -45,6 +47,11 @@ float pixelToTwip(float fInput, float zoom);
float twipToPixel(float fInput, float zoom);
/**
+ Gets GQuark identifying this tile buffer errors
+*/
+GQuark LOKTileBufferErrorQuark(void);
+
+/**
This class represents a single tile in the tile buffer.
It encloses a reference to GdkPixBuf containing the pixel data of the tile.
*/
@@ -153,6 +160,12 @@ enum
LOK_SET_GRAPHIC_SELECTION
};
+enum
+{
+ LOK_TILEBUFFER_CHANGED,
+ LOK_TILEBUFFER_MEMORY
+};
+
/**
A struct that we use to store the data about the LOK call.
@@ -198,6 +211,7 @@ struct LOEvent
int m_nPaintTileX;
int m_nPaintTileY;
float m_fPaintTileZoom;
+ TileBuffer* m_pTileBuffer;
///@}
/// @name postMouseEvent parameters
@@ -233,6 +247,7 @@ struct LOEvent
, m_nPaintTileX(0)
, m_nPaintTileY(0)
, m_fPaintTileZoom(0)
+ , m_pTileBuffer(nullptr)
, m_nPostMouseEventType(0)
, m_nPostMouseEventX(0)
, m_nPostMouseEventY(0)