[Libreoffice-commits] core.git: Branch 'feature/gsoc-tiled-rendering' - 8 commits - libreofficekit/Library_libreofficekitgtk.mk libreofficekit/source
Pranav Kant
pranavk at gnome.org
Thu Jun 4 10:06:53 PDT 2015
Rebased ref, commits from common ancestor:
commit 9e5b792642fe39b9558c26f9d76b8ed9b6752942
Author: Pranav Kant <pranavk at gnome.org>
Date: Thu Jun 4 22:09:57 2015 +0530
lokdocview, tilebuffer: clean up
Improve documentation, style fixes
Change-Id: I5000e32e90cd8e3b75e8df2907673efc303a55fd
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 50ddc76..4191fa1 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
@@ -177,12 +177,12 @@ struct LOKDocView_Impl
/// Implementation of the timeout handler, invoked by handleTimeout().
gboolean handleTimeoutImpl();
/**
- * Renders the document to a number of tiles.
+ * Renders the document to a number of visible tiles.
*
* This method is invoked only manually, not when some Gtk signal is
* emitted.
*
- * @param pPartial if 0, then the full document is rendered, otherwise only
+ * @param pPartial if 0, then the full visible document is rendered, otherwise only
* the tiles that intersect with pPartial.
*/
void renderDocument(GdkRectangle* pPartial);
@@ -665,7 +665,7 @@ void LOKDocView_Impl::setTilesInvalid(const GdkRectangle& rRectangle)
for (int i = aStart.x; i < aEnd.x; i++)
for (int j = aStart.y; j < aEnd.y; j++)
- m_pTileBuffer->tile_buffer_set_invalid(i, j);
+ m_pTileBuffer->setInvalid(i, j);
}
void LOKDocView_Impl::renderHandle(cairo_t* pCairo, const GdkRectangle& rCursor, cairo_surface_t* pHandle, GdkRectangle& rRectangle)
@@ -824,10 +824,10 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
if (bPaint)
{
- // g_info("gettile: (%d %d)", nRow, nColumn);
+ g_info("tile_buffer_get_tile (%d, %d)", nRow, nColumn);
- Tile& currentTile = m_pTileBuffer->tile_buffer_get_tile(nRow, nColumn);
- GdkPixbuf* pPixBuf = currentTile.tile_get_buffer();
+ Tile& currentTile = m_pTileBuffer->getTile(nRow, nColumn);
+ GdkPixbuf* pPixBuf = currentTile.getBuffer();
gdk_cairo_set_source_pixbuf (pcairo, pPixBuf, twipToPixel(aTileRectangleTwips.x, m_fZoom), twipToPixel(aTileRectangleTwips.y, m_fZoom));
cairo_paint(pcairo);
@@ -942,7 +942,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
}
else
{
- m_pTileBuffer->tile_buffer_reset_all_tiles();
+ m_pTileBuffer->resetAllTiles();
renderDocument(0);
}
}
@@ -1148,21 +1148,28 @@ static void lok_docview_init( GTypeInstance* pInstance, gpointer )
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(pDocView),
pDocView->m_pImpl->m_pDrawingArea );
- g_signal_connect(GTK_OBJECT(pDocView->m_pImpl->m_pDrawingArea),
+ g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea),
"expose-event",
- GTK_SIGNAL_FUNC(LOKDocView_Impl::on_exposed), pDocView);
- g_signal_connect(GTK_OBJECT(pDocView->m_pImpl->m_pDrawingArea),
+ G_CALLBACK(LOKDocView_Impl::on_exposed), pDocView);
+ g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea),
"expose-event",
- GTK_SIGNAL_FUNC(LOKDocView_Impl::renderOverlay), pDocView);
+ G_CALLBACK(LOKDocView_Impl::renderOverlay), pDocView);
gtk_widget_add_events(pDocView->m_pImpl->m_pDrawingArea,
- GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK
- | GDK_BUTTON_MOTION_MASK);
- g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea), "button-press-event", G_CALLBACK(LOKDocView_Impl::signalButton), pDocView);
- g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea), "button-release-event", G_CALLBACK(LOKDocView_Impl::signalButton), pDocView);
- g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea), "motion-notify-event", G_CALLBACK(LOKDocView_Impl::signalMotion), pDocView);
-
- gtk_signal_connect(GTK_OBJECT(pDocView), "destroy", GTK_SIGNAL_FUNC(LOKDocView_Impl::destroy), 0);
+ GDK_BUTTON_PRESS_MASK
+ |GDK_BUTTON_RELEASE_MASK
+ |GDK_BUTTON_MOTION_MASK);
+
+ g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea),
+ "button-press-event",
+ G_CALLBACK(LOKDocView_Impl::signalButton), pDocView);
+ g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea),
+ "button-release-event",
+ G_CALLBACK(LOKDocView_Impl::signalButton), pDocView);
+ g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea),
+ "motion-notify-event",
+ G_CALLBACK(LOKDocView_Impl::signalMotion), pDocView);
+
+ g_signal_connect(G_OBJECT(pDocView), "destroy", G_CALLBACK(LOKDocView_Impl::destroy), 0);
}
SAL_DLLPUBLIC_EXPORT guint lok_docview_get_type()
@@ -1253,7 +1260,7 @@ SAL_DLLPUBLIC_EXPORT void lok_docview_set_zoom ( LOKDocView* pDocView, float fZo
guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels);
- pDocView->m_pImpl->m_pTileBuffer->tile_buffer_set_zoom(fZoom, nRows, nColumns);
+ pDocView->m_pImpl->m_pTileBuffer->setZoom(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
index 3e5e01f..936d472 100644
--- a/libreofficekit/source/gtk/tilebuffer.cxx
+++ b/libreofficekit/source/gtk/tilebuffer.cxx
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
@@ -9,6 +9,10 @@
#include "tilebuffer.hxx"
+/* ------------------
+ Utility functions
+ ------------------
+*/
float pixelToTwip(float fInput, float zoom)
{
return (fInput / DPI / zoom) * 1440.0f;
@@ -19,84 +23,94 @@ float twipToPixel(float fInput, float zoom)
return fInput / 1440.0f * DPI * zoom;
}
-GdkPixbuf* Tile::tile_get_buffer()
+/* ----------------------------
+ Tile class member functions
+ ----------------------------
+*/
+GdkPixbuf* Tile::getBuffer()
{
return m_pBuffer;
}
-void Tile::tile_release()
+void Tile::release()
{
g_object_unref (m_pBuffer);
m_pBuffer = NULL;
}
-void TileBuffer::tile_buffer_set_zoom(float newZoomFactor, int rows, int columns)
+void Tile::setPixbuf(GdkPixbuf *buffer)
+{
+ m_pBuffer = buffer;
+}
+
+/* ----------------------------------
+ TileBuffer class member functions
+ ----------------------------------
+*/
+void TileBuffer::setZoom(float newZoomFactor, int rows, int columns)
{
m_fZoomFactor = newZoomFactor;
- tile_buffer_reset_all_tiles();
+ resetAllTiles();
// set new buffer width and height
m_nWidth = columns;
m_nHeight = rows;
}
-void TileBuffer::tile_buffer_reset_all_tiles()
+void TileBuffer::resetAllTiles()
{
std::map<int, Tile>::iterator it = m_mTiles.begin();
for (; it != m_mTiles.end(); it++)
{
- it->second.tile_release();
+ it->second.release();
}
m_mTiles.clear();
}
-void TileBuffer::tile_buffer_set_invalid(int x, int y)
+void TileBuffer::setInvalid(int x, int y)
{
int index = x * m_nWidth + y;
g_info("setting invalid : %d %d",x, y);
if (m_mTiles.find(index) != m_mTiles.end())
{
m_mTiles[index].valid = 0;
- m_mTiles[index].tile_release();
+ m_mTiles[index].release();
m_mTiles.erase(index);
}
}
-Tile& TileBuffer::tile_buffer_get_tile(int x, int y)
+Tile& TileBuffer::getTile(int x, int y)
{
int index = x * m_nWidth + y;
if(m_mTiles.find(index) == m_mTiles.end() || !m_mTiles[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));
-
- //create a mapping for it
- m_mTiles[index].tile_set_pixbuf(pPixBuf);
- m_mTiles[index].valid = 1;
+ 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,
+ pBuffer,
+ m_nTileSize, m_nTileSize,
+ aTileRectangle.x, aTileRectangle.y,
+ pixelToTwip(m_nTileSize, m_fZoomFactor),
+ pixelToTwip(m_nTileSize, m_fZoomFactor));
+
+ //create a mapping for it
+ m_mTiles[index].setPixbuf(pPixBuf);
+ m_mTiles[index].valid = 1;
+ }
return m_mTiles[index];
}
-void Tile::tile_set_pixbuf(GdkPixbuf *buffer)
-{
- m_pBuffer = buffer;
-}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx
index 15b276f..7e2132f 100644
--- a/libreofficekit/source/gtk/tilebuffer.hxx
+++ b/libreofficekit/source/gtk/tilebuffer.hxx
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
@@ -24,32 +24,60 @@ const int DPI = 96;
// Lets use a square of side 256 pixels for each tile.
const int nTileSizePixels = 256;
+/**
+ Converts the pixel value to zoom independent twip value.
+
+ @param fInput value to convert
+ @param zoom the current zoom level
+
+ @return the pixels value corresponding to given twip value
+*/
float pixelToTwip(float fInput, float zoom);
+/**
+ Converts the zoom independent twip value pixel value.
+
+ @param fInput value to convert
+ @param zoom the current zoom level
+
+ @return the twip value corresponding to given pixel value
+*/
float twipToPixel(float fInput, float zoom);
-/*
- This class represents a single tile in the tile buffer.
- TODO: Extend it to support features like double buffering
+/**
+ This class represents a single tile in the tile buffer.
+ It encloses a reference to GdkPixBuf containing the pixel data of the tile.
*/
class Tile
{
public:
- Tile() : valid(0) {}
- ~Tile() {
- }
+ Tile() : valid(0) {}
+ ~Tile() { }
- GdkPixbuf* tile_get_buffer();
- void tile_release();
- void tile_set_pixbuf(GdkPixbuf*);
+ /**
+ Tells if this tile is valid or not. Initialised to 0 (invalid) during
+ object creation.
+ */
bool valid;
- private:
+
+ /// Function to get the pointer to enclosing GdkPixbuf
+ GdkPixbuf* getBuffer();
+ /// Destroys the enclosing GdkPixbuf object pointed to by m_pBuffer
+ void release();
+ /// Used to set the pixel buffer of this object
+ void setPixbuf(GdkPixbuf*);
+
+private:
+ /// Pixel buffer data for this tile
GdkPixbuf *m_pBuffer;
};
-/*
- TileBuffer is the buffer caching all the recently rendered tiles.
- The buffer is set to invalid when zoom factor changes.
+/**
+ This class represents the tile buffer which is responsible for managing,
+ reusing and caching all the already rendered tiles. If the given tile is not
+ present in the buffer, call to LOK Document's (m_pLOKDocument) paintTile
+ method is made which fetches the rendered tile from LO core and store it in
+ buffer for future reuse.
*/
class TileBuffer
{
@@ -67,19 +95,58 @@ class TileBuffer
~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();
- void tile_buffer_set_invalid(int x, int y);
+ /**
+ Sets the zoom factor (m_fZoomFactor) for this tile buffer. Setting the
+ zoom factor invalidates whole of the tile buffer, destroys all tiles
+ contained within it, and sets new width, height values for tile
+ buffer. The width, height value of tile buffer is the width and height of
+ the table containing all possible tiles (rendered and non-rendered) that
+ this buffer can have.
+
+ @param zoomFactor the new zoom factor value to set
+ */
+ void setZoom(float zoomFactor, int rows, int columns);
+ /**
+ Gets the underlying Tile object for given position. The position (0, 0)
+ points to the left top most tile of the buffer.
+
+ If the tile is not cached by the tile buffer, it makes a paintTile call
+ to LO core asking to render the given tile. It then stores the tile for
+ future reuse.
+
+ @param x the tile along the x-axis of the buffer
+ @param y the tile along the y-axis of the buffer
+
+ @return the tile at the mentioned position (x, y)
+ */
+ Tile& getTile(int x, int y);
+ /// Destroys all the tiles in the tile buffer; also frees the memory allocated
+ /// for all the Tile objects.
+ void resetAllTiles();
+ /**
+ Marks the tile as invalid. The tile (0, 0) is the left topmost tile in
+ the tile buffer.
+
+ @param x the position of tile along x-axis
+ @param y the position of tile along y-axis
+ */
+ void setInvalid(int x, int y);
+
private:
+ /// Contains the reference to the LOK Document that this tile buffer is for.
LibreOfficeKitDocument *m_pLOKDocument;
+ /// The side of each squared tile in pixels.
int m_nTileSize;
+ /// The zoom factor that the tile buffer is currently rendered to.
float m_fZoomFactor;
+ /// Stores all the tiles cached by this tile buffer.
std::map<int, Tile> m_mTiles;
- //TODO: Also set width and height when document size changes
+ /// Width of the current tile buffer (number of columns)
int m_nWidth;
+ /// Height of the current tile buffer (numbero of rows)
int m_nHeight;
};
#endif // INCLUDED_TILEBUFFER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 34e44f5509c474a590b747fa1bc39cb69a4349bd
Author: Pranav Kant <pranavk at gnome.org>
Date: Thu Jun 4 14:15:58 2015 +0530
lokdocview: wrap a functionality inside a member function
Lets use a member function to set invalid tiles that come under the
given GdkRectangle.
Change-Id: I440336ddf3c5fd9094f35bb89479aa76a42477fa
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 478375d..50ddc76 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -212,6 +212,8 @@ struct LOKDocView_Impl
void searchNotFound(const std::string& rPayload);
/// LOK decided to change parts, need to update UI.
void setPart(const std::string& rPayload);
+ /// Sets the tiles enclosed by rRectangle as invalid in m_pTileBuffer
+ void setTilesInvalid(const GdkRectangle& rRectangle);
};
namespace {
@@ -646,6 +648,26 @@ bool LOKDocView_Impl::isEmptyRectangle(const GdkRectangle& rRectangle)
return rRectangle.x == 0 && rRectangle.y == 0 && rRectangle.width == 0 && rRectangle.height == 0;
}
+void LOKDocView_Impl::setTilesInvalid(const GdkRectangle& rRectangle)
+{
+ GdkRectangle aRectanglePixels;
+ GdkPoint aStart, aEnd;
+
+ aRectanglePixels.x = twipToPixel(rRectangle.x, m_fZoom);
+ aRectanglePixels.y = twipToPixel(rRectangle.y, m_fZoom);
+ aRectanglePixels.width = twipToPixel(rRectangle.width, m_fZoom);
+ aRectanglePixels.height = twipToPixel(rRectangle.height, m_fZoom);
+
+ aStart.x = aRectanglePixels.y / nTileSizePixels;
+ aStart.y = aRectanglePixels.x / nTileSizePixels;
+ aEnd.x = (aRectanglePixels.y + aRectanglePixels.height + nTileSizePixels) / nTileSizePixels;
+ aEnd.y = (aRectanglePixels.x + aRectanglePixels.width + nTileSizePixels) / nTileSizePixels;
+
+ for (int i = aStart.x; i < aEnd.x; i++)
+ for (int j = aStart.y; j < aEnd.y; j++)
+ m_pTileBuffer->tile_buffer_set_invalid(i, j);
+}
+
void LOKDocView_Impl::renderHandle(cairo_t* pCairo, const GdkRectangle& rCursor, cairo_surface_t* pHandle, GdkRectangle& rRectangle)
{
GdkPoint aCursorBottom;
@@ -915,21 +937,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
if (pCallback->m_aPayload != "EMPTY")
{
GdkRectangle aRectangle = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str());
- GdkRectangle aRectanglePixels;
- aRectanglePixels.x = twipToPixel(aRectangle.x, m_fZoom);
- aRectanglePixels.y = twipToPixel(aRectangle.y, m_fZoom);
- aRectanglePixels.width = twipToPixel(aRectangle.width, m_fZoom);
- aRectanglePixels.height = twipToPixel(aRectangle.height, m_fZoom);
- int rowStart = aRectanglePixels.y / nTileSizePixels;
- int colStart = aRectanglePixels.x / nTileSizePixels;
- int rowEnd = (aRectanglePixels.y + aRectanglePixels.height + nTileSizePixels) / nTileSizePixels;
- int colEnd = (aRectanglePixels.x + aRectanglePixels.width + nTileSizePixels) / nTileSizePixels;
- int i,j;
- for (i = rowStart; i < rowEnd; i++) {
- for (j = colStart; j < colEnd; j++) {
- m_pTileBuffer->tile_buffer_set_invalid(i, j);
- }
- }
+ setTilesInvalid(aRectangle);
renderDocument(0);
}
else
@@ -943,21 +951,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
{
m_aVisibleCursor = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str());
m_bCursorOverlayVisible = true;
- GdkRectangle aRectanglePixels;
- aRectanglePixels.x = twipToPixel(m_aVisibleCursor.x, m_fZoom);
- aRectanglePixels.y = twipToPixel(m_aVisibleCursor.y, m_fZoom);
- aRectanglePixels.width = twipToPixel(m_aVisibleCursor.width, m_fZoom);
- aRectanglePixels.height = twipToPixel(m_aVisibleCursor.height, m_fZoom);
- int rowStart = aRectanglePixels.y / nTileSizePixels;
- int colStart = aRectanglePixels.x / nTileSizePixels;
- int rowEnd = (aRectanglePixels.y + aRectanglePixels.height + nTileSizePixels) / nTileSizePixels;
- int colEnd = (aRectanglePixels.x + aRectanglePixels.width + nTileSizePixels) / nTileSizePixels;
- int i,j;
- for (i = rowStart; i < rowEnd; i++) {
- for (j = colStart; j < colEnd; j++) {
- m_pTileBuffer->tile_buffer_set_invalid(i, j);
- }
- }
+ setTilesInvalid(m_aVisibleCursor);
renderDocument(0);
}
break;
commit 3021e56a81142af59e455ca4f7bb38f5facadf7d
Author: Pranav Kant <pranavk at gnome.org>
Date: Thu Jun 4 13:56:46 2015 +0530
lokdocview: move commonly used functions and variables to common header
twipToPixel and pixelToTwip are also being used by the new TileBuffer
clsas. Lets move these utility functions to a common header,
tilebuffer.hxx
The variables for DPI and tileSize are also moved to tilebuffer.hxx
Change-Id: I9d0bec7f2aefe412df232040a7a9abc6db3e4ccb
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index d3f0820..478375d 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -37,11 +37,6 @@
// Number of handles around a graphic selection.
#define GRAPHIC_HANDLE_COUNT 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 {
/// Sets rWidth and rHeight from a "width, height" string.
@@ -145,10 +140,6 @@ struct LOKDocView_Impl
static void destroy(LOKDocView* pDocView, gpointer pData);
/// Connected to the expose-event of the GtkDrawingArea
static void on_exposed(GtkWidget *widget, GdkEvent *event, gpointer user_data);
- /// Converts from screen pixels to document coordinates.
- float pixelToTwip(float fInput);
- /// Converts from document coordinates to screen pixels.
- float twipToPixel(float fInput);
/// Receives a key press or release event.
void signalKey(GdkEventKey* pEvent);
/**
@@ -316,16 +307,6 @@ void LOKDocView_Impl::on_exposed(GtkWidget* /*widget*/, GdkEvent* /*event*/, gpo
pDocView->m_pImpl->renderDocument(0);
}
-float LOKDocView_Impl::pixelToTwip(float fInput)
-{
- return (fInput / DPI / m_fZoom) * 1440.0f;
-}
-
-float LOKDocView_Impl::twipToPixel(float fInput)
-{
- return fInput / 1440.0f * DPI * m_fZoom;
-}
-
void LOKDocView_Impl::signalKey(GdkEventKey* pEvent)
{
int nCharCode = 0;
@@ -390,7 +371,7 @@ gboolean LOKDocView_Impl::signalButton(GtkWidget* /*pEventBox*/, GdkEventButton*
/// Receives a button press event.
gboolean LOKDocView_Impl::signalButtonImpl(GdkEventButton* pEvent)
{
- g_info("LOKDocView_Impl::signalButton: %d, %d (in twips: %d, %d)", (int)pEvent->x, (int)pEvent->y, (int)pixelToTwip(pEvent->x), (int)pixelToTwip(pEvent->y));
+ g_info("LOKDocView_Impl::signalButton: %d, %d (in twips: %d, %d)", (int)pEvent->x, (int)pEvent->y, (int)pixelToTwip(pEvent->x, m_fZoom), (int)pixelToTwip(pEvent->y, m_fZoom));
if (pEvent->type == GDK_BUTTON_RELEASE)
{
@@ -419,7 +400,7 @@ gboolean LOKDocView_Impl::signalButtonImpl(GdkEventButton* pEvent)
{
g_info("LOKDocView_Impl::signalButton: end of drag graphic handle #%d", i);
m_bInDragGraphicHandles[i] = false;
- m_pDocument->pClass->setGraphicSelection(m_pDocument, LOK_SETGRAPHICSELECTION_END, pixelToTwip(pEvent->x), pixelToTwip(pEvent->y));
+ m_pDocument->pClass->setGraphicSelection(m_pDocument, LOK_SETGRAPHICSELECTION_END, pixelToTwip(pEvent->x, m_fZoom), pixelToTwip(pEvent->y, m_fZoom));
return FALSE;
}
}
@@ -428,7 +409,7 @@ gboolean LOKDocView_Impl::signalButtonImpl(GdkEventButton* pEvent)
{
g_info("LOKDocView_Impl::signalButton: end of drag graphic selection");
m_bInDragGraphicSelection = false;
- m_pDocument->pClass->setGraphicSelection(m_pDocument, LOK_SETGRAPHICSELECTION_END, pixelToTwip(pEvent->x), pixelToTwip(pEvent->y));
+ m_pDocument->pClass->setGraphicSelection(m_pDocument, LOK_SETGRAPHICSELECTION_END, pixelToTwip(pEvent->x, m_fZoom), pixelToTwip(pEvent->y, m_fZoom));
return FALSE;
}
}
@@ -469,8 +450,8 @@ gboolean LOKDocView_Impl::signalButtonImpl(GdkEventButton* pEvent)
m_bInDragGraphicHandles[i] = true;
m_pDocument->pClass->setGraphicSelection(m_pDocument,
LOK_SETGRAPHICSELECTION_START,
- pixelToTwip(m_aGraphicHandleRects[i].x + m_aGraphicHandleRects[i].width / 2),
- pixelToTwip(m_aGraphicHandleRects[i].y + m_aGraphicHandleRects[i].height / 2));
+ pixelToTwip(m_aGraphicHandleRects[i].x + m_aGraphicHandleRects[i].width / 2, m_fZoom),
+ pixelToTwip(m_aGraphicHandleRects[i].y + m_aGraphicHandleRects[i].height / 2, m_fZoom));
return FALSE;
}
}
@@ -488,7 +469,7 @@ gboolean LOKDocView_Impl::signalButtonImpl(GdkEventButton* pEvent)
if ((pEvent->time - m_nLastButtonPressTime) < 250)
nCount++;
m_nLastButtonPressTime = pEvent->time;
- m_pDocument->pClass->postMouseEvent(m_pDocument, LOK_MOUSEEVENT_MOUSEBUTTONDOWN, pixelToTwip(pEvent->x), pixelToTwip(pEvent->y), nCount);
+ m_pDocument->pClass->postMouseEvent(m_pDocument, LOK_MOUSEEVENT_MOUSEBUTTONDOWN, pixelToTwip(pEvent->x, m_fZoom), pixelToTwip(pEvent->y, m_fZoom), nCount);
break;
}
case GDK_BUTTON_RELEASE:
@@ -497,7 +478,7 @@ gboolean LOKDocView_Impl::signalButtonImpl(GdkEventButton* pEvent)
if ((pEvent->time - m_nLastButtonReleaseTime) < 250)
nCount++;
m_nLastButtonReleaseTime = pEvent->time;
- m_pDocument->pClass->postMouseEvent(m_pDocument, LOK_MOUSEEVENT_MOUSEBUTTONUP, pixelToTwip(pEvent->x), pixelToTwip(pEvent->y), nCount);
+ m_pDocument->pClass->postMouseEvent(m_pDocument, LOK_MOUSEEVENT_MOUSEBUTTONUP, pixelToTwip(pEvent->x, m_fZoom), pixelToTwip(pEvent->y, m_fZoom), nCount);
break;
}
default:
@@ -534,21 +515,21 @@ gboolean LOKDocView_Impl::signalMotionImpl(GdkEventButton* pEvent)
{
g_info("lcl_signalMotion: dragging the middle handle");
LOKDocView_Impl::getDragPoint(&m_aHandleMiddleRect, pEvent, &aPoint);
- m_pDocument->pClass->setTextSelection(m_pDocument, LOK_SETTEXTSELECTION_RESET, pixelToTwip(aPoint.x), pixelToTwip(aPoint.y));
+ m_pDocument->pClass->setTextSelection(m_pDocument, LOK_SETTEXTSELECTION_RESET, pixelToTwip(aPoint.x, m_fZoom), pixelToTwip(aPoint.y, m_fZoom));
return FALSE;
}
if (m_bInDragStartHandle)
{
g_info("lcl_signalMotion: dragging the start handle");
LOKDocView_Impl::getDragPoint(&m_aHandleStartRect, pEvent, &aPoint);
- m_pDocument->pClass->setTextSelection(m_pDocument, LOK_SETTEXTSELECTION_START, pixelToTwip(aPoint.x), pixelToTwip(aPoint.y));
+ m_pDocument->pClass->setTextSelection(m_pDocument, LOK_SETTEXTSELECTION_START, pixelToTwip(aPoint.x, m_fZoom), pixelToTwip(aPoint.y, m_fZoom));
return FALSE;
}
if (m_bInDragEndHandle)
{
g_info("lcl_signalMotion: dragging the end handle");
LOKDocView_Impl::getDragPoint(&m_aHandleEndRect, pEvent, &aPoint);
- m_pDocument->pClass->setTextSelection(m_pDocument, LOK_SETTEXTSELECTION_END, pixelToTwip(aPoint.x), pixelToTwip(aPoint.y));
+ m_pDocument->pClass->setTextSelection(m_pDocument, LOK_SETTEXTSELECTION_END, pixelToTwip(aPoint.x, m_fZoom), pixelToTwip(aPoint.y, m_fZoom));
return FALSE;
}
for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
@@ -566,20 +547,20 @@ gboolean LOKDocView_Impl::signalMotionImpl(GdkEventButton* pEvent)
}
GdkRectangle aMotionInTwipsInTwips;
- aMotionInTwipsInTwips.x = pixelToTwip(pEvent->x);
- aMotionInTwipsInTwips.y = pixelToTwip(pEvent->y);
+ aMotionInTwipsInTwips.x = pixelToTwip(pEvent->x, m_fZoom);
+ aMotionInTwipsInTwips.y = pixelToTwip(pEvent->y, m_fZoom);
aMotionInTwipsInTwips.width = 1;
aMotionInTwipsInTwips.height = 1;
if (gdk_rectangle_intersect(&aMotionInTwipsInTwips, &m_aGraphicSelection, 0))
{
g_info("lcl_signalMotion: start of drag graphic selection");
m_bInDragGraphicSelection = true;
- m_pDocument->pClass->setGraphicSelection(m_pDocument, LOK_SETGRAPHICSELECTION_START, pixelToTwip(pEvent->x), pixelToTwip(pEvent->y));
+ m_pDocument->pClass->setGraphicSelection(m_pDocument, LOK_SETGRAPHICSELECTION_START, pixelToTwip(pEvent->x, m_fZoom), pixelToTwip(pEvent->y, m_fZoom));
return FALSE;
}
// Otherwise a mouse move, as on the desktop.
- m_pDocument->pClass->postMouseEvent(m_pDocument, LOK_MOUSEEVENT_MOUSEMOVE, pixelToTwip(pEvent->x), pixelToTwip(pEvent->y), 1);
+ m_pDocument->pClass->postMouseEvent(m_pDocument, LOK_MOUSEEVENT_MOUSEMOVE, pixelToTwip(pEvent->x, m_fZoom), pixelToTwip(pEvent->y, m_fZoom), 1);
return FALSE;
}
@@ -602,10 +583,10 @@ gboolean LOKDocView_Impl::renderOverlayImpl(GtkWidget* pWidget)
cairo_set_source_rgb(pCairo, 0, 0, 0);
cairo_rectangle(pCairo,
- twipToPixel(m_aVisibleCursor.x),
- twipToPixel(m_aVisibleCursor.y),
- twipToPixel(m_aVisibleCursor.width),
- twipToPixel(m_aVisibleCursor.height));
+ twipToPixel(m_aVisibleCursor.x, m_fZoom),
+ twipToPixel(m_aVisibleCursor.y, m_fZoom),
+ twipToPixel(m_aVisibleCursor.width, m_fZoom),
+ twipToPixel(m_aVisibleCursor.height, m_fZoom));
cairo_fill(pCairo);
}
@@ -624,10 +605,10 @@ gboolean LOKDocView_Impl::renderOverlayImpl(GtkWidget* pWidget)
// Blue with 75% transparency.
cairo_set_source_rgba(pCairo, ((double)0x43)/255, ((double)0xac)/255, ((double)0xe8)/255, 0.25);
cairo_rectangle(pCairo,
- twipToPixel(rRectangle.x),
- twipToPixel(rRectangle.y),
- twipToPixel(rRectangle.width),
- twipToPixel(rRectangle.height));
+ twipToPixel(rRectangle.x, m_fZoom),
+ twipToPixel(rRectangle.y, m_fZoom),
+ twipToPixel(rRectangle.width, m_fZoom),
+ twipToPixel(rRectangle.height, m_fZoom));
cairo_fill(pCairo);
}
@@ -674,10 +655,10 @@ void LOKDocView_Impl::renderHandle(cairo_t* pCairo, const GdkRectangle& rCursor,
nHandleWidth = cairo_image_surface_get_width(pHandle);
nHandleHeight = cairo_image_surface_get_height(pHandle);
// We want to scale down the handle, so that its height is the same as the cursor caret.
- fHandleScale = twipToPixel(rCursor.height) / nHandleHeight;
+ fHandleScale = twipToPixel(rCursor.height, m_fZoom) / nHandleHeight;
// We want the top center of the handle bitmap to be at the bottom center of the cursor rectangle.
- aCursorBottom.x = twipToPixel(rCursor.x) + twipToPixel(rCursor.width) / 2 - (nHandleWidth * fHandleScale) / 2;
- aCursorBottom.y = twipToPixel(rCursor.y) + twipToPixel(rCursor.height);
+ aCursorBottom.x = twipToPixel(rCursor.x, m_fZoom) + twipToPixel(rCursor.width, m_fZoom) / 2 - (nHandleWidth * fHandleScale) / 2;
+ aCursorBottom.y = twipToPixel(rCursor.y, m_fZoom) + twipToPixel(rCursor.height, m_fZoom);
cairo_save(pCairo);
cairo_translate(pCairo, aCursorBottom.x, aCursorBottom.y);
cairo_scale(pCairo, fHandleScale, fHandleScale);
@@ -700,10 +681,10 @@ void LOKDocView_Impl::renderGraphicHandle(cairo_t* pCairo, const GdkRectangle& r
nHandleWidth = cairo_image_surface_get_width(pHandle);
nHandleHeight = cairo_image_surface_get_height(pHandle);
- aSelection.x = twipToPixel(rSelection.x);
- aSelection.y = twipToPixel(rSelection.y);
- aSelection.width = twipToPixel(rSelection.width);
- aSelection.height = twipToPixel(rSelection.height);
+ aSelection.x = twipToPixel(rSelection.x, m_fZoom);
+ aSelection.y = twipToPixel(rSelection.y, m_fZoom);
+ aSelection.width = twipToPixel(rSelection.width, m_fZoom);
+ aSelection.height = twipToPixel(rSelection.height, m_fZoom);
for (int i = 0; i < GRAPHIC_HANDLE_COUNT; ++i)
{
@@ -781,8 +762,8 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
GdkRectangle visibleArea;
lok_docview_get_visarea (m_pDocView, &visibleArea);
- long nDocumentWidthPixels = twipToPixel(m_nDocumentWidthTwips);
- long nDocumentHeightPixels = twipToPixel(m_nDocumentHeightTwips);
+ long nDocumentWidthPixels = twipToPixel(m_nDocumentWidthTwips, m_fZoom);
+ long nDocumentHeightPixels = twipToPixel(m_nDocumentHeightTwips, m_fZoom);
// Total number of rows / columns in this document.
guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels);
@@ -809,10 +790,10 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
aTileRectanglePixels.height = nTileSizePixels;
// Determine size and position of the tile in document coordinates, so we can decide if we can skip painting for partial rendering.
- aTileRectangleTwips.x = pixelToTwip(nTileSizePixels) * nColumn;
- aTileRectangleTwips.y = pixelToTwip(nTileSizePixels) * nRow;
- aTileRectangleTwips.width = pixelToTwip(aTileRectanglePixels.width);
- aTileRectangleTwips.height = pixelToTwip(aTileRectanglePixels.height);
+ aTileRectangleTwips.x = pixelToTwip(nTileSizePixels, m_fZoom) * nColumn;
+ aTileRectangleTwips.y = pixelToTwip(nTileSizePixels, m_fZoom) * nRow;
+ aTileRectangleTwips.width = pixelToTwip(aTileRectanglePixels.width, m_fZoom);
+ aTileRectangleTwips.height = pixelToTwip(aTileRectanglePixels.height, m_fZoom);
if (pPartial && !gdk_rectangle_intersect(pPartial, &aTileRectangleTwips, 0))
bPaint = false;
@@ -826,7 +807,7 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
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));
+ gdk_cairo_set_source_pixbuf (pcairo, pPixBuf, twipToPixel(aTileRectangleTwips.x, m_fZoom), twipToPixel(aTileRectangleTwips.y, m_fZoom));
cairo_paint(pcairo);
}
}
@@ -935,10 +916,10 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
{
GdkRectangle aRectangle = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str());
GdkRectangle aRectanglePixels;
- aRectanglePixels.x = twipToPixel(aRectangle.x);
- aRectanglePixels.y = twipToPixel(aRectangle.y);
- aRectanglePixels.width = twipToPixel(aRectangle.width);
- aRectanglePixels.height = twipToPixel(aRectangle.height);
+ aRectanglePixels.x = twipToPixel(aRectangle.x, m_fZoom);
+ aRectanglePixels.y = twipToPixel(aRectangle.y, m_fZoom);
+ aRectanglePixels.width = twipToPixel(aRectangle.width, m_fZoom);
+ aRectanglePixels.height = twipToPixel(aRectangle.height, m_fZoom);
int rowStart = aRectanglePixels.y / nTileSizePixels;
int colStart = aRectanglePixels.x / nTileSizePixels;
int rowEnd = (aRectanglePixels.y + aRectanglePixels.height + nTileSizePixels) / nTileSizePixels;
@@ -963,10 +944,10 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
m_aVisibleCursor = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str());
m_bCursorOverlayVisible = true;
GdkRectangle aRectanglePixels;
- aRectanglePixels.x = twipToPixel(m_aVisibleCursor.x);
- aRectanglePixels.y = twipToPixel(m_aVisibleCursor.y);
- aRectanglePixels.width = twipToPixel(m_aVisibleCursor.width);
- aRectanglePixels.height = twipToPixel(m_aVisibleCursor.height);
+ aRectanglePixels.x = twipToPixel(m_aVisibleCursor.x, m_fZoom);
+ aRectanglePixels.y = twipToPixel(m_aVisibleCursor.y, m_fZoom);
+ aRectanglePixels.width = twipToPixel(m_aVisibleCursor.width, m_fZoom);
+ aRectanglePixels.height = twipToPixel(m_aVisibleCursor.height, m_fZoom);
int rowStart = aRectanglePixels.y / nTileSizePixels;
int colStart = aRectanglePixels.x / nTileSizePixels;
int rowEnd = (aRectanglePixels.y + aRectanglePixels.height + nTileSizePixels) / nTileSizePixels;
@@ -1246,10 +1227,11 @@ SAL_DLLPUBLIC_EXPORT gboolean lok_docview_open_document( LOKDocView* pDocView, c
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);
+ float zoom = pDocView->m_pImpl->m_fZoom;
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);
+ long nDocumentWidthPixels = twipToPixel(nDocumentWidthTwips, zoom);
+ long nDocumentHeightPixels = twipToPixel(nDocumentHeightTwips, zoom);
// Total number of rows / columns in this document.
guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels);
@@ -1271,8 +1253,8 @@ 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);
+ long nDocumentWidthPixels = twipToPixel(pDocView->m_pImpl->m_nDocumentWidthTwips, fZoom);
+ long nDocumentHeightPixels = twipToPixel(pDocView->m_pImpl->m_nDocumentHeightTwips, fZoom);
// Total number of rows / columns in this document.
guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels);
@@ -1350,12 +1332,13 @@ SAL_DLLPUBLIC_EXPORT void lok_docview_post_key(GtkWidget* /*pWidget*/, GdkEventK
SAL_DLLPUBLIC_EXPORT void lok_docview_get_visarea(LOKDocView* pThis, GdkRectangle* pArea)
{
+ float zoom = pThis->m_pImpl->m_fZoom;
GtkAdjustment* pHAdjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(pThis));
- pArea->x = pThis->m_pImpl->pixelToTwip(gtk_adjustment_get_value(pHAdjustment));
- pArea->width = pThis->m_pImpl->pixelToTwip(gtk_adjustment_get_page_size(pHAdjustment));
+ pArea->x = pixelToTwip(gtk_adjustment_get_value(pHAdjustment),zoom);
+ pArea->width = pixelToTwip(gtk_adjustment_get_page_size(pHAdjustment), zoom);
GtkAdjustment* pVAdjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(pThis));
- pArea->y = pThis->m_pImpl->pixelToTwip(gtk_adjustment_get_value(pVAdjustment));
- pArea->height = pThis->m_pImpl->pixelToTwip(gtk_adjustment_get_page_size(pVAdjustment));
+ pArea->y = pixelToTwip(gtk_adjustment_get_value(pVAdjustment), zoom);
+ pArea->height = pixelToTwip(gtk_adjustment_get_page_size(pVAdjustment), zoom);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/libreofficekit/source/gtk/tilebuffer.cxx b/libreofficekit/source/gtk/tilebuffer.cxx
index e13f5b0..3e5e01f 100644
--- a/libreofficekit/source/gtk/tilebuffer.cxx
+++ b/libreofficekit/source/gtk/tilebuffer.cxx
@@ -9,14 +9,12 @@
#include "tilebuffer.hxx"
-static const int DPI = 96;
-
-static float pixelToTwip(float fInput, float zoom)
+float pixelToTwip(float fInput, float zoom)
{
return (fInput / DPI / zoom) * 1440.0f;
}
-static float twipToPixel(float fInput, float zoom)
+float twipToPixel(float fInput, float zoom)
{
return fInput / 1440.0f * DPI * zoom;
}
diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx
index 088df93..15b276f 100644
--- a/libreofficekit/source/gtk/tilebuffer.hxx
+++ b/libreofficekit/source/gtk/tilebuffer.hxx
@@ -19,6 +19,15 @@
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <LibreOfficeKit/LibreOfficeKitGtk.h>
+// We know that VirtualDevices use a DPI of 96.
+const int DPI = 96;
+// Lets use a square of side 256 pixels for each tile.
+const int nTileSizePixels = 256;
+
+float pixelToTwip(float fInput, float zoom);
+
+float twipToPixel(float fInput, float zoom);
+
/*
This class represents a single tile in the tile buffer.
TODO: Extend it to support features like double buffering
commit 4d6c2b7197502da85bd7cbfce57d62c412f8ebd4
Author: Pranav Kant <pranavk at gnome.org>
Date: Thu Jun 4 03:32:18 2015 +0530
lokdocview: Add support for editing documents
Change-Id: I8637d99e6fa59129af207e667bcdf03dc212efeb
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index f476a23..d3f0820 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -821,7 +821,7 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
if (bPaint)
{
- g_info("gettile: (%d %d)", nRow, nColumn);
+ // g_info("gettile: (%d %d)", nRow, nColumn);
Tile& currentTile = m_pTileBuffer->tile_buffer_get_tile(nRow, nColumn);
GdkPixbuf* pPixBuf = currentTile.tile_get_buffer();
@@ -934,17 +934,50 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
if (pCallback->m_aPayload != "EMPTY")
{
GdkRectangle aRectangle = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str());
- renderDocument(&aRectangle);
+ GdkRectangle aRectanglePixels;
+ aRectanglePixels.x = twipToPixel(aRectangle.x);
+ aRectanglePixels.y = twipToPixel(aRectangle.y);
+ aRectanglePixels.width = twipToPixel(aRectangle.width);
+ aRectanglePixels.height = twipToPixel(aRectangle.height);
+ int rowStart = aRectanglePixels.y / nTileSizePixels;
+ int colStart = aRectanglePixels.x / nTileSizePixels;
+ int rowEnd = (aRectanglePixels.y + aRectanglePixels.height + nTileSizePixels) / nTileSizePixels;
+ int colEnd = (aRectanglePixels.x + aRectanglePixels.width + nTileSizePixels) / nTileSizePixels;
+ int i,j;
+ for (i = rowStart; i < rowEnd; i++) {
+ for (j = colStart; j < colEnd; j++) {
+ m_pTileBuffer->tile_buffer_set_invalid(i, j);
+ }
+ }
+ renderDocument(0);
}
else
+ {
+ m_pTileBuffer->tile_buffer_reset_all_tiles();
renderDocument(0);
+ }
}
break;
case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
{
m_aVisibleCursor = LOKDocView_Impl::payloadToRectangle(pCallback->m_aPayload.c_str());
m_bCursorOverlayVisible = true;
- gtk_widget_queue_draw(GTK_WIDGET(m_pDrawingArea));
+ GdkRectangle aRectanglePixels;
+ aRectanglePixels.x = twipToPixel(m_aVisibleCursor.x);
+ aRectanglePixels.y = twipToPixel(m_aVisibleCursor.y);
+ aRectanglePixels.width = twipToPixel(m_aVisibleCursor.width);
+ aRectanglePixels.height = twipToPixel(m_aVisibleCursor.height);
+ int rowStart = aRectanglePixels.y / nTileSizePixels;
+ int colStart = aRectanglePixels.x / nTileSizePixels;
+ int rowEnd = (aRectanglePixels.y + aRectanglePixels.height + nTileSizePixels) / nTileSizePixels;
+ int colEnd = (aRectanglePixels.x + aRectanglePixels.width + nTileSizePixels) / nTileSizePixels;
+ int i,j;
+ for (i = rowStart; i < rowEnd; i++) {
+ for (j = colStart; j < colEnd; j++) {
+ m_pTileBuffer->tile_buffer_set_invalid(i, j);
+ }
+ }
+ renderDocument(0);
}
break;
case LOK_CALLBACK_TEXT_SELECTION:
@@ -961,7 +994,6 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
}
else
memset(&m_aHandleMiddleRect, 0, sizeof(m_aHandleMiddleRect));
- gtk_widget_queue_draw(GTK_WIDGET(m_pDrawingArea));
}
break;
case LOK_CALLBACK_TEXT_SELECTION_START:
@@ -1144,6 +1176,16 @@ static void lok_docview_init( GTypeInstance* pInstance, gpointer )
g_signal_connect(GTK_OBJECT(pDocView->m_pImpl->m_pDrawingArea),
"expose-event",
GTK_SIGNAL_FUNC(LOKDocView_Impl::on_exposed), pDocView);
+ g_signal_connect(GTK_OBJECT(pDocView->m_pImpl->m_pDrawingArea),
+ "expose-event",
+ GTK_SIGNAL_FUNC(LOKDocView_Impl::renderOverlay), pDocView);
+ gtk_widget_add_events(pDocView->m_pImpl->m_pDrawingArea,
+ GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_BUTTON_MOTION_MASK);
+ g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea), "button-press-event", G_CALLBACK(LOKDocView_Impl::signalButton), pDocView);
+ g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea), "button-release-event", G_CALLBACK(LOKDocView_Impl::signalButton), pDocView);
+ g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea), "motion-notify-event", G_CALLBACK(LOKDocView_Impl::signalMotion), pDocView);
gtk_signal_connect(GTK_OBJECT(pDocView), "destroy", GTK_SIGNAL_FUNC(LOKDocView_Impl::destroy), 0);
}
diff --git a/libreofficekit/source/gtk/tilebuffer.cxx b/libreofficekit/source/gtk/tilebuffer.cxx
index e1b5b32..e13f5b0 100644
--- a/libreofficekit/source/gtk/tilebuffer.cxx
+++ b/libreofficekit/source/gtk/tilebuffer.cxx
@@ -23,69 +23,82 @@ static float twipToPixel(float fInput, float zoom)
GdkPixbuf* Tile::tile_get_buffer()
{
- return m_pBuffer;
+ return m_pBuffer;
}
void Tile::tile_release()
{
- gdk_pixbuf_unref(m_pBuffer);
- m_pBuffer = NULL;
+ g_object_unref (m_pBuffer);
+ m_pBuffer = NULL;
}
void TileBuffer::tile_buffer_set_zoom(float newZoomFactor, int rows, int columns)
{
- m_fZoomFactor = newZoomFactor;
+ m_fZoomFactor = newZoomFactor;
- tile_buffer_reset_all_tiles();
+ tile_buffer_reset_all_tiles();
- // set new buffer width and height
- m_nWidth = columns;
- m_nHeight = rows;
+ // set new buffer width and height
+ m_nWidth = columns;
+ m_nHeight = rows;
}
void TileBuffer::tile_buffer_reset_all_tiles()
{
- std::map<int, Tile>::iterator it = m_mTiles.begin();
- for (; it != m_mTiles.end(); it++)
- {
- it->second.tile_release();
- }
- m_mTiles.clear();
+ std::map<int, Tile>::iterator it = m_mTiles.begin();
+ for (; it != m_mTiles.end(); it++)
+ {
+ it->second.tile_release();
+ }
+ m_mTiles.clear();
+}
+
+void TileBuffer::tile_buffer_set_invalid(int x, int y)
+{
+ int index = x * m_nWidth + y;
+ g_info("setting invalid : %d %d",x, y);
+ if (m_mTiles.find(index) != m_mTiles.end())
+ {
+ m_mTiles[index].valid = 0;
+ m_mTiles[index].tile_release();
+ m_mTiles.erase(index);
+ }
}
Tile& TileBuffer::tile_buffer_get_tile(int x, int y)
{
- int index = x * m_nWidth + y;
- if(m_mTiles.find(index) == m_mTiles.end())
- {
- 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));
-
- //create a mapping for it
- m_mTiles[index].tile_set_pixbuf(pPixBuf);
- m_mTiles[index].valid = 1;
- }
-
- return m_mTiles[index];
+ int index = x * m_nWidth + y;
+ if(m_mTiles.find(index) == m_mTiles.end() || !m_mTiles[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));
+
+ //create a mapping for it
+ m_mTiles[index].tile_set_pixbuf(pPixBuf);
+ m_mTiles[index].valid = 1;
+ }
+
+ return m_mTiles[index];
}
void Tile::tile_set_pixbuf(GdkPixbuf *buffer)
{
- m_pBuffer = buffer;
+ m_pBuffer = buffer;
}
diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx
index 0bc2d38..088df93 100644
--- a/libreofficekit/source/gtk/tilebuffer.hxx
+++ b/libreofficekit/source/gtk/tilebuffer.hxx
@@ -25,18 +25,17 @@
*/
class Tile
{
-public:
- Tile() : valid(0) {}
- ~Tile() {
- tile_release();
- }
+ public:
+ Tile() : valid(0) {}
+ ~Tile() {
+ }
- GdkPixbuf* tile_get_buffer();
- void tile_release();
- void tile_set_pixbuf(GdkPixbuf*);
- bool valid;
-private:
- GdkPixbuf *m_pBuffer;
+ GdkPixbuf* tile_get_buffer();
+ void tile_release();
+ void tile_set_pixbuf(GdkPixbuf*);
+ bool valid;
+ private:
+ GdkPixbuf *m_pBuffer;
};
/*
@@ -45,32 +44,33 @@ private:
*/
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)
+ 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)
{ }
- ~TileBuffer() {}
+ ~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::map<int, Tile> m_mTiles;
- //TODO: Also set width and height when document size changes
- int m_nWidth;
- int m_nHeight;
+ 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();
+ void tile_buffer_set_invalid(int x, int y);
+ private:
+ LibreOfficeKitDocument *m_pLOKDocument;
+ int m_nTileSize;
+ float m_fZoomFactor;
+ std::map<int, Tile> m_mTiles;
+ //TODO: Also set width and height when document size changes
+ int m_nWidth;
+ int m_nHeight;
};
#endif // INCLUDED_TILEBUFFER_HXX
commit 5415bd512768de45df93e292b33beeedf128388b
Author: Pranav Kant <pranavk at gnome.org>
Date: Thu Jun 4 01:44:47 2015 +0530
lokdocview: Use maps instead of vector
Using vector each tile needs to be allocated memory irrespective of
whether tile is required or not. This approach fails when we zoom in to
a very high level to have thousands of tiles due to lot of memory
required. Using maps instead of vector takes care of this, and only
allocates Tiles when required.
Change-Id: I523f815618451a7f014e28258e0de7b1c0693370
diff --git a/libreofficekit/source/gtk/tilebuffer.cxx b/libreofficekit/source/gtk/tilebuffer.cxx
index ca66ae90..e1b5b32 100644
--- a/libreofficekit/source/gtk/tilebuffer.cxx
+++ b/libreofficekit/source/gtk/tilebuffer.cxx
@@ -41,22 +41,22 @@ void TileBuffer::tile_buffer_set_zoom(float newZoomFactor, int rows, int columns
// 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++)
+ std::map<int, Tile>::iterator it = m_mTiles.begin();
+ for (; it != m_mTiles.end(); it++)
{
- m_aTiles[i].tile_release();
+ it->second.tile_release();
}
- m_aTiles.clear();
+ m_mTiles.clear();
}
Tile& TileBuffer::tile_buffer_get_tile(int x, int y)
{
int index = x * m_nWidth + y;
- if(!m_aTiles[index].valid)
+ if(m_mTiles.find(index) == m_mTiles.end())
{
GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, m_nTileSize, m_nTileSize);
if (!pPixBuf){
@@ -77,11 +77,12 @@ Tile& TileBuffer::tile_buffer_get_tile(int x, int 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;
+ //create a mapping for it
+ m_mTiles[index].tile_set_pixbuf(pPixBuf);
+ m_mTiles[index].valid = 1;
}
- return m_aTiles[index];
+ return m_mTiles[index];
}
void Tile::tile_set_pixbuf(GdkPixbuf *buffer)
diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx
index a5ed0dc..0bc2d38 100644
--- a/libreofficekit/source/gtk/tilebuffer.hxx
+++ b/libreofficekit/source/gtk/tilebuffer.hxx
@@ -12,7 +12,7 @@
#include <gdk/gdkkeysyms.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <vector>
+#include <map>
#define LOK_USE_UNSTABLE_API
#include <LibreOfficeKit/LibreOfficeKit.h>
@@ -55,9 +55,7 @@ public:
, m_fZoomFactor(1)
, m_nWidth(columns)
, m_nHeight(rows)
- {
- m_aTiles.resize(rows * columns);
- }
+ { }
~TileBuffer() {}
@@ -69,7 +67,7 @@ private:
LibreOfficeKitDocument *m_pLOKDocument;
int m_nTileSize;
float m_fZoomFactor;
- std::vector<Tile> m_aTiles;
+ std::map<int, Tile> m_mTiles;
//TODO: Also set width and height when document size changes
int m_nWidth;
int m_nHeight;
commit fef9bc9c0b172f9b4393b59686515deaf2f47ad2
Author: Pranav Kant <pranavk at gnome.org>
Date: Thu Jun 4 00:06:46 2015 +0530
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
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..f476a23 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 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..a5ed0dc
--- /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
commit 1d0edaaeec96fc04cf2c9f45eb50621a458fbe45
Author: Pranav Kant <pranavk at gnome.org>
Date: Wed Jun 3 20:52:49 2015 +0530
lokdocview: use GtkDrawingArea for drawing tiles
Change-Id: I1a3d8a9229f416418f0f3e9c720b78af09b35978
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index a766b8a..676952c 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -65,6 +65,9 @@ struct LOKDocView_Impl
GtkWidget* m_pEventBox;
GtkWidget* m_pTable;
GtkWidget** m_pCanvas;
+ GtkWidget *darea;
+
+ TileBuffer *mTileBuffer;
float m_fZoom;
@@ -140,6 +143,8 @@ struct LOKDocView_Impl
~LOKDocView_Impl();
/// Connected to the destroy signal of LOKDocView, deletes its LOKDocView_Impl.
static void destroy(LOKDocView* pDocView, gpointer pData);
+ /// Connected to the expose-event of the GtkDrawingArea
+ static void on_exposed(GtkWidget *widget, GdkEvent *event, gpointer user_data);
/// Converts from screen pixels to document coordinates.
float pixelToTwip(float fInput);
/// Converts from document coordinates to screen pixels.
@@ -258,6 +263,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_fZoom(1),
@@ -307,6 +313,12 @@ void LOKDocView_Impl::destroy(LOKDocView* pDocView, gpointer /*pData*/)
delete pDocView->m_pImpl;
}
+void LOKDocView_Impl::on_exposed(GtkWidget *widget, GdkEvent *event, gpointer userdata)
+{
+ LOKDocView *pDocView = LOK_DOCVIEW (userdata);
+ pDocView->m_pImpl->renderDocument(0);
+}
+
float LOKDocView_Impl::pixelToTwip(float fInput)
{
return (fInput / DPI / m_fZoom) * 1440.0f;
@@ -771,40 +783,17 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
{
const int nTileSizePixels = 256;
+ GdkRectangle visibleArea;
+ lok_docview_get_visarea (m_pDocView, &visibleArea);
+
long nDocumentWidthPixels = twipToPixel(m_nDocumentWidthTwips);
long nDocumentHeightPixels = twipToPixel(m_nDocumentHeightTwips);
// Total number of rows / columns in this document.
guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
guint nColumns = ceil((double)nDocumentWidthPixels / nTileSizePixels);
- // Set up our table and the tile pointers.
- if (!m_pTable)
- pPartial = 0;
- if (pPartial)
- {
- // Same as nRows / nColumns, but from the previous renderDocument() call.
- guint nOldRows, nOldColumns;
-
-#if GTK_CHECK_VERSION(2,22,0)
- gtk_table_get_size(GTK_TABLE(m_pTable), &nOldRows, &nOldColumns);
- if (nOldRows != nRows || nOldColumns != nColumns)
- // Can't do partial rendering, document size changed.
- pPartial = 0;
-#else
- pPartial = 0;
-#endif
- }
- if (!pPartial)
- {
- if (m_pTable)
- gtk_container_remove(GTK_CONTAINER(m_pEventBox), m_pTable);
- m_pTable = gtk_table_new(nRows, nColumns, FALSE);
- gtk_container_add(GTK_CONTAINER(m_pEventBox), m_pTable);
- gtk_widget_show(m_pTable);
- if (m_pCanvas)
- g_free(m_pCanvas);
- m_pCanvas = static_cast<GtkWidget**>(g_malloc0(sizeof(GtkWidget*) * nRows * nColumns));
- }
+ gtk_widget_set_size_request(darea, nDocumentWidthPixels, nDocumentHeightPixels);
+ cairo_t *pcairo = gdk_cairo_create(darea->window);
// Render the tiles.
for (guint nRow = 0; nRow < nRows; ++nRow)
@@ -830,7 +819,10 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
aTileRectangleTwips.width = pixelToTwip(aTileRectanglePixels.width);
aTileRectangleTwips.height = pixelToTwip(aTileRectanglePixels.height);
if (pPartial && !gdk_rectangle_intersect(pPartial, &aTileRectangleTwips, 0))
- bPaint = false;
+ bPaint = false;
+
+ if (!gdk_rectangle_intersect(&visibleArea, &aTileRectangleTwips, 0))
+ bPaint = false;
if (bPaint)
{
@@ -849,21 +841,16 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
// Size of the tile, depends on the zoom factor and the tile position only.
aTileRectangleTwips.width, aTileRectangleTwips.height);
- if (m_pCanvas[nTile])
- gtk_widget_destroy(GTK_WIDGET(m_pCanvas[nTile]));
- m_pCanvas[nTile] = gtk_image_new();
- gtk_image_set_from_pixbuf(GTK_IMAGE(m_pCanvas[nTile]), pPixBuf);
- g_object_unref(G_OBJECT(pPixBuf));
- gtk_widget_show(m_pCanvas[nTile]);
- gtk_table_attach(GTK_TABLE(m_pTable),
- m_pCanvas[nTile],
- nColumn, nColumn + 1, nRow, nRow + 1,
- GTK_SHRINK, GTK_SHRINK, 0, 0);
+ gdk_cairo_set_source_pixbuf (pcairo, pPixBuf, twipToPixel(aTileRectangleTwips.x), twipToPixel(aTileRectangleTwips.y));
+ cairo_paint(pcairo);
}
}
}
+
+ cairo_destroy(pcairo);
}
+
GdkRectangle LOKDocView_Impl::payloadToRectangle(const char* pPayload)
{
GdkRectangle aRet;
@@ -1167,17 +1154,13 @@ 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->m_pEventBox );
-
- gtk_widget_set_events(pDocView->m_pImpl->m_pEventBox, GDK_BUTTON_PRESS_MASK); // So that drag doesn't try to move the whole window.
- gtk_signal_connect(GTK_OBJECT(pDocView->m_pImpl->m_pEventBox), "button-press-event", GTK_SIGNAL_FUNC(LOKDocView_Impl::signalButton), pDocView);
- gtk_signal_connect(GTK_OBJECT(pDocView->m_pImpl->m_pEventBox), "button-release-event", GTK_SIGNAL_FUNC(LOKDocView_Impl::signalButton), pDocView);
- gtk_signal_connect(GTK_OBJECT(pDocView->m_pImpl->m_pEventBox), "motion-notify-event", GTK_SIGNAL_FUNC(LOKDocView_Impl::signalMotion), pDocView);
+ pDocView->m_pImpl->darea );
- gtk_widget_show( pDocView->m_pImpl->m_pEventBox );
+ g_signal_connect(GTK_OBJECT(pDocView->m_pImpl->darea),
+ "expose-event",
+ GTK_SIGNAL_FUNC(LOKDocView_Impl::on_exposed), pDocView);
gtk_signal_connect(GTK_OBJECT(pDocView), "destroy", GTK_SIGNAL_FUNC(LOKDocView_Impl::destroy), 0);
- g_signal_connect_after(pDocView->m_pImpl->m_pEventBox, "expose-event", G_CALLBACK(LOKDocView_Impl::renderOverlay), pDocView);
}
SAL_DLLPUBLIC_EXPORT guint lok_docview_get_type()
commit 9fc51dc5f5f4e108a21127abf5e03fc01bb6ddc0
Author: Pranav Kant <pranavk at gnome.org>
Date: Tue Jun 2 18:26:12 2015 +0530
lokdocview: add width and height to the visible rectangle
Change-Id: I64212113750893f33f8a859ba52ecd8815a820f4
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 064e534..a766b8a 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -1323,8 +1323,10 @@ SAL_DLLPUBLIC_EXPORT void lok_docview_get_visarea(LOKDocView* pThis, GdkRectangl
{
GtkAdjustment* pHAdjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(pThis));
pArea->x = pThis->m_pImpl->pixelToTwip(gtk_adjustment_get_value(pHAdjustment));
+ pArea->width = pThis->m_pImpl->pixelToTwip(gtk_adjustment_get_page_size(pHAdjustment));
GtkAdjustment* pVAdjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(pThis));
pArea->y = pThis->m_pImpl->pixelToTwip(gtk_adjustment_get_value(pVAdjustment));
+ pArea->height = pThis->m_pImpl->pixelToTwip(gtk_adjustment_get_page_size(pVAdjustment));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list