Kaydet (Commit) 42dc4f3e authored tarafından Pranav Kant's avatar Pranav Kant Kaydeden (comit) Miklos Vajna

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
üst a13d4671
...@@ -17,6 +17,7 @@ $(eval $(call gb_Library_use_externals,libreofficekitgtk,\ ...@@ -17,6 +17,7 @@ $(eval $(call gb_Library_use_externals,libreofficekitgtk,\
$(eval $(call gb_Library_add_exception_objects,libreofficekitgtk,\ $(eval $(call gb_Library_add_exception_objects,libreofficekitgtk,\
libreofficekit/source/gtk/lokdocview \ libreofficekit/source/gtk/lokdocview \
libreofficekit/source/gtk/tilebuffer \
)) ))
ifeq ($(OS),LINUX) ifeq ($(OS),LINUX)
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include <LibreOfficeKit/LibreOfficeKitGtk.h> #include <LibreOfficeKit/LibreOfficeKitGtk.h>
#include <rsc/rsc-vcl-shared-types.hxx> #include <rsc/rsc-vcl-shared-types.hxx>
#include "tilebuffer.hxx"
#if !GLIB_CHECK_VERSION(2,32,0) #if !GLIB_CHECK_VERSION(2,32,0)
#define G_SOURCE_REMOVE FALSE #define G_SOURCE_REMOVE FALSE
#define G_SOURCE_CONTINUE TRUE #define G_SOURCE_CONTINUE TRUE
...@@ -37,6 +39,8 @@ ...@@ -37,6 +39,8 @@
// We know that VirtualDevices use a DPI of 96. // We know that VirtualDevices use a DPI of 96.
static const int DPI = 96; static const int DPI = 96;
// Lets use a square of side 256 pixels.
static const int nTileSizePixels = 256;
namespace { namespace {
...@@ -62,12 +66,8 @@ void payloadToSize(const char* pPayload, long& rWidth, long& rHeight) ...@@ -62,12 +66,8 @@ void payloadToSize(const char* pPayload, long& rWidth, long& rHeight)
struct LOKDocView_Impl struct LOKDocView_Impl
{ {
LOKDocView* m_pDocView; LOKDocView* m_pDocView;
GtkWidget* m_pEventBox; GtkWidget *m_pDrawingArea;
GtkWidget* m_pTable; TileBuffer *m_pTileBuffer;
GtkWidget** m_pCanvas;
GtkWidget *darea;
TileBuffer *mTileBuffer;
float m_fZoom; float m_fZoom;
...@@ -262,10 +262,7 @@ LOKDocView_Impl::CallbackData::CallbackData(int nType, const std::string& rPaylo ...@@ -262,10 +262,7 @@ LOKDocView_Impl::CallbackData::CallbackData(int nType, const std::string& rPaylo
LOKDocView_Impl::LOKDocView_Impl(LOKDocView* pDocView) LOKDocView_Impl::LOKDocView_Impl(LOKDocView* pDocView)
: m_pDocView(pDocView), : m_pDocView(pDocView),
m_pEventBox(gtk_event_box_new()), m_pDrawingArea(gtk_drawing_area_new()),
darea(gtk_drawing_area_new()),
m_pTable(0),
m_pCanvas(0),
m_fZoom(1), m_fZoom(1),
m_pOffice(0), m_pOffice(0),
m_pDocument(0), m_pDocument(0),
...@@ -313,7 +310,7 @@ void LOKDocView_Impl::destroy(LOKDocView* pDocView, gpointer /*pData*/) ...@@ -313,7 +310,7 @@ void LOKDocView_Impl::destroy(LOKDocView* pDocView, gpointer /*pData*/)
delete pDocView->m_pImpl; 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); LOKDocView *pDocView = LOK_DOCVIEW (userdata);
pDocView->m_pImpl->renderDocument(0); pDocView->m_pImpl->renderDocument(0);
...@@ -773,7 +770,7 @@ gboolean LOKDocView_Impl::handleTimeoutImpl() ...@@ -773,7 +770,7 @@ gboolean LOKDocView_Impl::handleTimeoutImpl()
m_bCursorOverlayVisible = false; m_bCursorOverlayVisible = false;
else else
m_bCursorOverlayVisible = true; m_bCursorOverlayVisible = true;
gtk_widget_queue_draw(GTK_WIDGET(m_pEventBox)); gtk_widget_queue_draw(GTK_WIDGET(m_pDrawingArea));
} }
return G_SOURCE_CONTINUE; return G_SOURCE_CONTINUE;
...@@ -781,8 +778,6 @@ gboolean LOKDocView_Impl::handleTimeoutImpl() ...@@ -781,8 +778,6 @@ gboolean LOKDocView_Impl::handleTimeoutImpl()
void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial) void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
{ {
const int nTileSizePixels = 256;
GdkRectangle visibleArea; GdkRectangle visibleArea;
lok_docview_get_visarea (m_pDocView, &visibleArea); lok_docview_get_visarea (m_pDocView, &visibleArea);
...@@ -792,8 +787,8 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial) ...@@ -792,8 +787,8 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels); guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels); guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels);
gtk_widget_set_size_request(darea, nDocumentWidthPixels, nDocumentHeightPixels); gtk_widget_set_size_request(m_pDrawingArea, nDocumentWidthPixels, nDocumentHeightPixels);
cairo_t *pcairo = gdk_cairo_create(darea->window); cairo_t *pcairo = gdk_cairo_create(m_pDrawingArea->window);
// Render the tiles. // Render the tiles.
for (guint nRow = 0; nRow < nRows; ++nRow) for (guint nRow = 0; nRow < nRows; ++nRow)
...@@ -826,20 +821,10 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial) ...@@ -826,20 +821,10 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
if (bPaint) if (bPaint)
{ {
// Index of the current tile. g_info("gettile: (%d %d)", nRow, nColumn);
guint nTile = nRow * nColumns + nColumn;
Tile& currentTile = m_pTileBuffer->tile_buffer_get_tile(nRow, nColumn);
GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, aTileRectanglePixels.width, aTileRectanglePixels.height); 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)); gdk_cairo_set_source_pixbuf (pcairo, pPixBuf, twipToPixel(aTileRectangleTwips.x), twipToPixel(aTileRectangleTwips.y));
cairo_paint(pcairo); cairo_paint(pcairo);
...@@ -959,7 +944,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback) ...@@ -959,7 +944,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
{ {
m_aVisibleCursor = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str()); m_aVisibleCursor = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str());
m_bCursorOverlayVisible = true; m_bCursorOverlayVisible = true;
gtk_widget_queue_draw(GTK_WIDGET(m_pEventBox)); gtk_widget_queue_draw(GTK_WIDGET(m_pDrawingArea));
} }
break; break;
case LOK_CALLBACK_TEXT_SELECTION: case LOK_CALLBACK_TEXT_SELECTION:
...@@ -976,7 +961,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback) ...@@ -976,7 +961,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
} }
else else
memset(&m_aHandleMiddleRect, 0, sizeof(m_aHandleMiddleRect)); memset(&m_aHandleMiddleRect, 0, sizeof(m_aHandleMiddleRect));
gtk_widget_queue_draw(GTK_WIDGET(m_pEventBox)); gtk_widget_queue_draw(GTK_WIDGET(m_pDrawingArea));
} }
break; break;
case LOK_CALLBACK_TEXT_SELECTION_START: case LOK_CALLBACK_TEXT_SELECTION_START:
...@@ -1000,7 +985,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback) ...@@ -1000,7 +985,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
m_aGraphicSelection = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str()); m_aGraphicSelection = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str());
else else
memset(&m_aGraphicSelection, 0, sizeof(m_aGraphicSelection)); memset(&m_aGraphicSelection, 0, sizeof(m_aGraphicSelection));
gtk_widget_queue_draw(GTK_WIDGET(m_pEventBox)); gtk_widget_queue_draw(GTK_WIDGET(m_pDrawingArea));
} }
break; break;
case LOK_CALLBACK_HYPERLINK_CLICKED: case LOK_CALLBACK_HYPERLINK_CLICKED:
...@@ -1154,9 +1139,9 @@ static void lok_docview_init( GTypeInstance* pInstance, gpointer ) ...@@ -1154,9 +1139,9 @@ static void lok_docview_init( GTypeInstance* pInstance, gpointer )
pDocView->m_pImpl = new LOKDocView_Impl(pDocView); pDocView->m_pImpl = new LOKDocView_Impl(pDocView);
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(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", "expose-event",
GTK_SIGNAL_FUNC(LOKDocView_Impl::on_exposed), pDocView); GTK_SIGNAL_FUNC(LOKDocView_Impl::on_exposed), pDocView);
...@@ -1218,6 +1203,18 @@ SAL_DLLPUBLIC_EXPORT gboolean lok_docview_open_document( LOKDocView* pDocView, c ...@@ -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->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); 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); 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); pDocView->m_pImpl->renderDocument(0);
} }
...@@ -1232,6 +1229,13 @@ SAL_DLLPUBLIC_EXPORT LibreOfficeKitDocument* lok_docview_get_document(LOKDocView ...@@ -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 ) SAL_DLLPUBLIC_EXPORT void lok_docview_set_zoom ( LOKDocView* pDocView, float fZoom )
{ {
pDocView->m_pImpl->m_fZoom = 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 ) if ( pDocView->m_pImpl->m_pDocument )
pDocView->m_pImpl->renderDocument(0); pDocView->m_pImpl->renderDocument(0);
...@@ -1283,7 +1287,7 @@ SAL_DLLPUBLIC_EXPORT void lok_docview_set_edit( LOKDocView* pDocView, ...@@ -1283,7 +1287,7 @@ SAL_DLLPUBLIC_EXPORT void lok_docview_set_edit( LOKDocView* pDocView,
} }
pDocView->m_pImpl->m_bEdit = bEdit; pDocView->m_pImpl->m_bEdit = bEdit;
g_signal_emit(pDocView, docview_signals[EDIT_CHANGED], 0, bWasEdit); 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) SAL_DLLPUBLIC_EXPORT gboolean lok_docview_get_edit(LOKDocView* pDocView)
......
/* -*- 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;
}
/* -*- 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment