libreofficekit/Library_libreofficekitgtk.mk | 1 libreofficekit/source/gtk/lokdocview.cxx | 42 ++++++++----- libreofficekit/source/gtk/tilebuffer.cxx | 90 ++++++++++++++++++++++++++++ libreofficekit/source/gtk/tilebuffer.hxx | 78 ++++++++++++++++++++++++ 4 files changed, 196 insertions(+), 15 deletions(-)
New commits: commit 1858a2a30dcd75698af704a7ddf8fb12c89e8112 Author: Pranav Kant <pran...@gnome.org> Date: Thu Jun 4 00:06:46 2015 +0530 lokdocview: add tile buffering support The TileBuffer class now manages all the tiles. Change-Id: Ic667a93dcf1c097e0601c0496e8a083c4742e8cb diff --git a/libreofficekit/Library_libreofficekitgtk.mk b/libreofficekit/Library_libreofficekitgtk.mk index ff800d0..9240953 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 676952c..b34a501 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 { @@ -67,7 +71,7 @@ struct LOKDocView_Impl GtkWidget** m_pCanvas; GtkWidget *darea; - TileBuffer *mTileBuffer; + TileBuffer *m_pTileBuffer; float m_fZoom; @@ -781,8 +785,6 @@ gboolean LOKDocView_Impl::handleTimeoutImpl() void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial) { - const int nTileSizePixels = 256; - GdkRectangle visibleArea; lok_docview_get_visarea (m_pDocView, &visibleArea); @@ -826,20 +828,11 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial) if (bPaint) { - // Index of the current tile. - guint nTile = nRow * nColumns + nColumn; + g_info("gettile: (%d %d)", nRow, nColumn); - GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, aTileRectanglePixels.width, aTileRectanglePixels.height); + Tile& currentTile = m_pTileBuffer->tile_buffer_get_tile(nRow, nColumn); + GdkPixbuf* pPixBuf = currentTile.tile_get_buffer(); 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); gdk_cairo_set_source_pixbuf (pcairo, pPixBuf, twipToPixel(aTileRectangleTwips.x), twipToPixel(aTileRectangleTwips.y)); cairo_paint(pcairo); @@ -1218,6 +1211,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 +1237,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); diff --git a/libreofficekit/source/gtk/tilebuffer.cxx b/libreofficekit/source/gtk/tilebuffer.cxx new file mode 100644 index 0000000..ca66ae90 --- /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 0000000..7912428 --- /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_fZoomFactor(1) + , m_nTileSize(tileSize) + , m_pLOKDocument(document) + , 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; + std::vector<Tile> m_aTiles; + //TODO: Also set width and height when document size changes + int m_nWidth; + int m_nHeight; + float m_fZoomFactor; + int m_nTileSize; +}; + +#endif // INCLUDED_TILEBUFFER_HXX _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits