summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPranav Kant <pranavk@gnome.org>2015-06-04 00:06:46 +0530
committerMiklos Vajna <vmiklos@collabora.co.uk>2015-06-09 10:44:21 +0200
commit42dc4f3ed8b7b41597dd9851c31dee4d0e352f46 (patch)
treeed27bc3f45cd0ed9678f56260fa978b696af1886
parenta13d4671bf1f557b3104e745277554ed11b3e6da (diff)
Add tile buffering support
The TileBuffer class now manages all the tiles. The tile rendering calls to LO core is also managed by this class. Change-Id: Ic667a93dcf1c097e0601c0496e8a083c4742e8cb
-rw-r--r--libreofficekit/Library_libreofficekitgtk.mk1
-rw-r--r--libreofficekit/source/gtk/lokdocview.cxx76
-rw-r--r--libreofficekit/source/gtk/tilebuffer.cxx90
-rw-r--r--libreofficekit/source/gtk/tilebuffer.hxx78
4 files changed, 209 insertions, 36 deletions
diff --git a/libreofficekit/Library_libreofficekitgtk.mk b/libreofficekit/Library_libreofficekitgtk.mk
index ff800d0f1d96..92409537f4e8 100644
--- a/libreofficekit/Library_libreofficekitgtk.mk
+++ b/libreofficekit/Library_libreofficekitgtk.mk
@@ -17,6 +17,7 @@ $(eval $(call gb_Library_use_externals,libreofficekitgtk,\
$(eval $(call gb_Library_add_exception_objects,libreofficekitgtk,\
libreofficekit/source/gtk/lokdocview \
+ libreofficekit/source/gtk/tilebuffer \
))
ifeq ($(OS),LINUX)
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index d5af092c9720..27fc2151578f 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -22,6 +22,8 @@
#include <LibreOfficeKit/LibreOfficeKitGtk.h>
#include <rsc/rsc-vcl-shared-types.hxx>
+#include "tilebuffer.hxx"
+
#if !GLIB_CHECK_VERSION(2,32,0)
#define G_SOURCE_REMOVE FALSE
#define G_SOURCE_CONTINUE TRUE
@@ -37,6 +39,8 @@
// We know that VirtualDevices use a DPI of 96.
static const int DPI = 96;
+// Lets use a square of side 256 pixels.
+static const int nTileSizePixels = 256;
namespace {
@@ -62,12 +66,8 @@ void payloadToSize(const char* pPayload, long& rWidth, long& rHeight)
struct LOKDocView_Impl
{
LOKDocView* m_pDocView;
- GtkWidget* m_pEventBox;
- GtkWidget* m_pTable;
- GtkWidget** m_pCanvas;
- GtkWidget *darea;
-
- TileBuffer *mTileBuffer;
+ GtkWidget *m_pDrawingArea;
+ TileBuffer *m_pTileBuffer;
float m_fZoom;
@@ -262,10 +262,7 @@ LOKDocView_Impl::CallbackData::CallbackData(int nType, const std::string& rPaylo
LOKDocView_Impl::LOKDocView_Impl(LOKDocView* pDocView)
: m_pDocView(pDocView),
- m_pEventBox(gtk_event_box_new()),
- darea(gtk_drawing_area_new()),
- m_pTable(0),
- m_pCanvas(0),
+ m_pDrawingArea(gtk_drawing_area_new()),
m_fZoom(1),
m_pOffice(0),
m_pDocument(0),
@@ -313,7 +310,7 @@ void LOKDocView_Impl::destroy(LOKDocView* pDocView, gpointer /*pData*/)
delete pDocView->m_pImpl;
}
-void LOKDocView_Impl::on_exposed(GtkWidget *widget, GdkEvent *event, gpointer userdata)
+void LOKDocView_Impl::on_exposed(GtkWidget* /*widget*/, GdkEvent* /*event*/, gpointer userdata)
{
LOKDocView *pDocView = LOK_DOCVIEW (userdata);
pDocView->m_pImpl->renderDocument(0);
@@ -773,7 +770,7 @@ gboolean LOKDocView_Impl::handleTimeoutImpl()
m_bCursorOverlayVisible = false;
else
m_bCursorOverlayVisible = true;
- gtk_widget_queue_draw(GTK_WIDGET(m_pEventBox));
+ gtk_widget_queue_draw(GTK_WIDGET(m_pDrawingArea));
}
return G_SOURCE_CONTINUE;
@@ -781,8 +778,6 @@ gboolean LOKDocView_Impl::handleTimeoutImpl()
void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
{
- const int nTileSizePixels = 256;
-
GdkRectangle visibleArea;
lok_docview_get_visarea (m_pDocView, &visibleArea);
@@ -792,8 +787,8 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels);
- gtk_widget_set_size_request(darea, nDocumentWidthPixels, nDocumentHeightPixels);
- cairo_t *pcairo = gdk_cairo_create(darea->window);
+ gtk_widget_set_size_request(m_pDrawingArea, nDocumentWidthPixels, nDocumentHeightPixels);
+ cairo_t *pcairo = gdk_cairo_create(m_pDrawingArea->window);
// Render the tiles.
for (guint nRow = 0; nRow < nRows; ++nRow)
@@ -826,20 +821,10 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
if (bPaint)
{
- // Index of the current tile.
- guint nTile = nRow * nColumns + nColumn;
-
- GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, aTileRectanglePixels.width, aTileRectanglePixels.height);
- unsigned char* pBuffer = gdk_pixbuf_get_pixels(pPixBuf);
- g_info("renderDocument: paintTile(%d, %d)", nRow, nColumn);
- m_pDocument->pClass->paintTile(m_pDocument,
- // Buffer and its size, depends on the position only.
- pBuffer,
- aTileRectanglePixels.width, aTileRectanglePixels.height,
- // Position of the tile.
- aTileRectangleTwips.x, aTileRectangleTwips.y,
- // Size of the tile, depends on the zoom factor and the tile position only.
- aTileRectangleTwips.width, aTileRectangleTwips.height);
+ g_info("gettile: (%d %d)", nRow, nColumn);
+
+ Tile& currentTile = m_pTileBuffer->tile_buffer_get_tile(nRow, nColumn);
+ GdkPixbuf* pPixBuf = currentTile.tile_get_buffer();
gdk_cairo_set_source_pixbuf (pcairo, pPixBuf, twipToPixel(aTileRectangleTwips.x), twipToPixel(aTileRectangleTwips.y));
cairo_paint(pcairo);
@@ -959,7 +944,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
{
m_aVisibleCursor = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str());
m_bCursorOverlayVisible = true;
- gtk_widget_queue_draw(GTK_WIDGET(m_pEventBox));
+ gtk_widget_queue_draw(GTK_WIDGET(m_pDrawingArea));
}
break;
case LOK_CALLBACK_TEXT_SELECTION:
@@ -976,7 +961,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
}
else
memset(&m_aHandleMiddleRect, 0, sizeof(m_aHandleMiddleRect));
- gtk_widget_queue_draw(GTK_WIDGET(m_pEventBox));
+ gtk_widget_queue_draw(GTK_WIDGET(m_pDrawingArea));
}
break;
case LOK_CALLBACK_TEXT_SELECTION_START:
@@ -1000,7 +985,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
m_aGraphicSelection = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str());
else
memset(&m_aGraphicSelection, 0, sizeof(m_aGraphicSelection));
- gtk_widget_queue_draw(GTK_WIDGET(m_pEventBox));
+ gtk_widget_queue_draw(GTK_WIDGET(m_pDrawingArea));
}
break;
case LOK_CALLBACK_HYPERLINK_CLICKED:
@@ -1154,9 +1139,9 @@ static void lok_docview_init( GTypeInstance* pInstance, gpointer )
pDocView->m_pImpl = new LOKDocView_Impl(pDocView);
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(pDocView),
- pDocView->m_pImpl->darea );
+ pDocView->m_pImpl->m_pDrawingArea );
- g_signal_connect(GTK_OBJECT(pDocView->m_pImpl->darea),
+ g_signal_connect(GTK_OBJECT(pDocView->m_pImpl->m_pDrawingArea),
"expose-event",
GTK_SIGNAL_FUNC(LOKDocView_Impl::on_exposed), pDocView);
@@ -1218,6 +1203,18 @@ SAL_DLLPUBLIC_EXPORT gboolean lok_docview_open_document( LOKDocView* pDocView, c
pDocView->m_pImpl->m_pDocument->pClass->registerCallback(pDocView->m_pImpl->m_pDocument, &LOKDocView_Impl::callbackWorker, pDocView);
pDocView->m_pImpl->m_pDocument->pClass->getDocumentSize(pDocView->m_pImpl->m_pDocument, &pDocView->m_pImpl->m_nDocumentWidthTwips, &pDocView->m_pImpl->m_nDocumentHeightTwips);
g_timeout_add(600, &LOKDocView_Impl::handleTimeout, pDocView);
+
+ long nDocumentWidthTwips = pDocView->m_pImpl->m_nDocumentWidthTwips;
+ long nDocumentHeightTwips = pDocView->m_pImpl->m_nDocumentHeightTwips;
+ long nDocumentWidthPixels = pDocView->m_pImpl->twipToPixel(nDocumentWidthTwips);
+ long nDocumentHeightPixels = pDocView->m_pImpl->twipToPixel(nDocumentHeightTwips);
+ // Total number of rows / columns in this document.
+ guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
+ guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels);
+ pDocView->m_pImpl->m_pTileBuffer = new TileBuffer(pDocView->m_pImpl->m_pDocument,
+ nTileSizePixels,
+ nRows,
+ nColumns);
pDocView->m_pImpl->renderDocument(0);
}
@@ -1232,6 +1229,13 @@ SAL_DLLPUBLIC_EXPORT LibreOfficeKitDocument* lok_docview_get_document(LOKDocView
SAL_DLLPUBLIC_EXPORT void lok_docview_set_zoom ( LOKDocView* pDocView, float fZoom )
{
pDocView->m_pImpl->m_fZoom = fZoom;
+ long nDocumentWidthPixels = pDocView->m_pImpl->twipToPixel(pDocView->m_pImpl->m_nDocumentWidthTwips);
+ long nDocumentHeightPixels = pDocView->m_pImpl->twipToPixel(pDocView->m_pImpl->m_nDocumentHeightTwips);
+ // Total number of rows / columns in this document.
+ guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
+ guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels);
+
+ pDocView->m_pImpl->m_pTileBuffer->tile_buffer_set_zoom(fZoom, nRows, nColumns);
if ( pDocView->m_pImpl->m_pDocument )
pDocView->m_pImpl->renderDocument(0);
@@ -1283,7 +1287,7 @@ SAL_DLLPUBLIC_EXPORT void lok_docview_set_edit( LOKDocView* pDocView,
}
pDocView->m_pImpl->m_bEdit = bEdit;
g_signal_emit(pDocView, docview_signals[EDIT_CHANGED], 0, bWasEdit);
- gtk_widget_queue_draw(GTK_WIDGET(pDocView->m_pImpl->m_pEventBox));
+ gtk_widget_queue_draw(GTK_WIDGET(pDocView->m_pImpl->m_pDrawingArea));
}
SAL_DLLPUBLIC_EXPORT gboolean lok_docview_get_edit(LOKDocView* pDocView)
diff --git a/libreofficekit/source/gtk/tilebuffer.cxx b/libreofficekit/source/gtk/tilebuffer.cxx
new file mode 100644
index 000000000000..ca66ae904f71
--- /dev/null
+++ b/libreofficekit/source/gtk/tilebuffer.cxx
@@ -0,0 +1,90 @@
+/* -*- 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 "tilebuffer.hxx"
+
+static const int DPI = 96;
+
+static float pixelToTwip(float fInput, float zoom)
+{
+ return (fInput / DPI / zoom) * 1440.0f;
+}
+
+static float twipToPixel(float fInput, float zoom)
+{
+ return fInput / 1440.0f * DPI * zoom;
+}
+
+GdkPixbuf* Tile::tile_get_buffer()
+{
+ return m_pBuffer;
+}
+
+void Tile::tile_release()
+{
+ gdk_pixbuf_unref(m_pBuffer);
+ m_pBuffer = NULL;
+}
+
+void TileBuffer::tile_buffer_set_zoom(float newZoomFactor, int rows, int columns)
+{
+ m_fZoomFactor = newZoomFactor;
+
+ tile_buffer_reset_all_tiles();
+
+ // set new buffer width and height
+ m_nWidth = columns;
+ m_nHeight = rows;
+ m_aTiles.resize(m_nWidth * m_nHeight);
+}
+
+void TileBuffer::tile_buffer_reset_all_tiles()
+{
+ for (size_t i = 0; i < m_aTiles.size(); i++)
+ {
+ m_aTiles[i].tile_release();
+ }
+ m_aTiles.clear();
+}
+
+Tile& TileBuffer::tile_buffer_get_tile(int x, int y)
+{
+ int index = x * m_nWidth + y;
+ if(!m_aTiles[index].valid)
+ {
+ GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, m_nTileSize, m_nTileSize);
+ if (!pPixBuf){
+ g_info ("error allocating memory to pixbuf");
+ }
+ unsigned char* pBuffer = gdk_pixbuf_get_pixels(pPixBuf);
+ GdkRectangle aTileRectangle;
+ aTileRectangle.x = pixelToTwip(m_nTileSize, m_fZoomFactor) * y;
+ aTileRectangle.y = pixelToTwip(m_nTileSize, m_fZoomFactor) * x;
+
+ g_info ("rendering (%d %d)", x, y);
+ m_pLOKDocument->pClass->paintTile(m_pLOKDocument,
+ // Buffer and its size, depends on the position only.
+ pBuffer,
+ m_nTileSize, m_nTileSize,
+ // Position of the tile.
+ aTileRectangle.x, aTileRectangle.y,
+ // Size of the tile, depends on the zoom factor and the tile position only.
+ pixelToTwip(m_nTileSize, m_fZoomFactor), pixelToTwip(m_nTileSize, m_fZoomFactor));
+
+ m_aTiles[index].tile_set_pixbuf(pPixBuf);
+ m_aTiles[index].valid = 1;
+ }
+
+ return m_aTiles[index];
+}
+
+void Tile::tile_set_pixbuf(GdkPixbuf *buffer)
+{
+ m_pBuffer = buffer;
+}
diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx
new file mode 100644
index 000000000000..a5ed0dc8ec61
--- /dev/null
+++ b/libreofficekit/source/gtk/tilebuffer.hxx
@@ -0,0 +1,78 @@
+/* -*- 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_TILEBUFFER_HXX
+#define INCLUDED_TILEBUFFER_HXX
+
+#include <gdk/gdkkeysyms.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <vector>
+
+#define LOK_USE_UNSTABLE_API
+#include <LibreOfficeKit/LibreOfficeKit.h>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <LibreOfficeKit/LibreOfficeKitGtk.h>
+
+/*
+ This class represents a single tile in the tile buffer.
+ TODO: Extend it to support features like double buffering
+*/
+class Tile
+{
+public:
+ Tile() : valid(0) {}
+ ~Tile() {
+ tile_release();
+ }
+
+ GdkPixbuf* tile_get_buffer();
+ void tile_release();
+ void tile_set_pixbuf(GdkPixbuf*);
+ bool valid;
+private:
+ GdkPixbuf *m_pBuffer;
+};
+
+/*
+ TileBuffer is the buffer caching all the recently rendered tiles.
+ The buffer is set to invalid when zoom factor changes.
+*/
+class TileBuffer
+{
+public:
+ TileBuffer(LibreOfficeKitDocument *document,
+ int tileSize,
+ int rows,
+ int columns)
+ : m_pLOKDocument(document)
+ , m_nTileSize(tileSize)
+ , m_fZoomFactor(1)
+ , m_nWidth(columns)
+ , m_nHeight(rows)
+ {
+ m_aTiles.resize(rows * columns);
+ }
+
+ ~TileBuffer() {}
+
+ void tile_buffer_set_zoom(float zoomFactor, int rows, int columns);
+ Tile& tile_buffer_get_tile(int x, int y);
+ void tile_buffer_update();
+ void tile_buffer_reset_all_tiles();
+private:
+ LibreOfficeKitDocument *m_pLOKDocument;
+ int m_nTileSize;
+ float m_fZoomFactor;
+ std::vector<Tile> m_aTiles;
+ //TODO: Also set width and height when document size changes
+ int m_nWidth;
+ int m_nHeight;
+};
+
+#endif // INCLUDED_TILEBUFFER_HXX