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

lokdocview, tilebuffer: clean up

Improve documentation, style fixes

Change-Id: I5000e32e90cd8e3b75e8df2907673efc303a55fd
üst ad0a404e
/* -*- 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. * This file is part of the LibreOffice project.
* *
...@@ -177,12 +177,12 @@ struct LOKDocView_Impl ...@@ -177,12 +177,12 @@ struct LOKDocView_Impl
/// Implementation of the timeout handler, invoked by handleTimeout(). /// Implementation of the timeout handler, invoked by handleTimeout().
gboolean handleTimeoutImpl(); 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 * This method is invoked only manually, not when some Gtk signal is
* emitted. * 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. * the tiles that intersect with pPartial.
*/ */
void renderDocument(GdkRectangle* pPartial); void renderDocument(GdkRectangle* pPartial);
...@@ -665,7 +665,7 @@ void LOKDocView_Impl::setTilesInvalid(const GdkRectangle& rRectangle) ...@@ -665,7 +665,7 @@ void LOKDocView_Impl::setTilesInvalid(const GdkRectangle& rRectangle)
for (int i = aStart.x; i < aEnd.x; i++) for (int i = aStart.x; i < aEnd.x; i++)
for (int j = aStart.y; j < aEnd.y; j++) 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) void LOKDocView_Impl::renderHandle(cairo_t* pCairo, const GdkRectangle& rCursor, cairo_surface_t* pHandle, GdkRectangle& rRectangle)
...@@ -801,7 +801,8 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial) ...@@ -801,7 +801,8 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
GdkRectangle aTileRectangleTwips, aTileRectanglePixels; GdkRectangle aTileRectangleTwips, aTileRectanglePixels;
bool bPaint = true; bool bPaint = true;
// Determine size of the tile: the rightmost/bottommost tiles may be smaller and we need the size to decide if we need to repaint. // Determine size of the tile: the rightmost/bottommost tiles may
// be smaller, and we need the size to decide if we need to repaint.
if (nColumn == nColumns - 1) if (nColumn == nColumns - 1)
aTileRectanglePixels.width = nDocumentWidthPixels - nColumn * nTileSizePixels; aTileRectanglePixels.width = nDocumentWidthPixels - nColumn * nTileSizePixels;
else else
...@@ -811,7 +812,8 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial) ...@@ -811,7 +812,8 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
else else
aTileRectanglePixels.height = nTileSizePixels; 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. // 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, m_fZoom) * nColumn; aTileRectangleTwips.x = pixelToTwip(nTileSizePixels, m_fZoom) * nColumn;
aTileRectangleTwips.y = pixelToTwip(nTileSizePixels, m_fZoom) * nRow; aTileRectangleTwips.y = pixelToTwip(nTileSizePixels, m_fZoom) * nRow;
aTileRectangleTwips.width = pixelToTwip(aTileRectanglePixels.width, m_fZoom); aTileRectangleTwips.width = pixelToTwip(aTileRectanglePixels.width, m_fZoom);
...@@ -824,12 +826,14 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial) ...@@ -824,12 +826,14 @@ void LOKDocView_Impl::renderDocument(GdkRectangle* pPartial)
if (bPaint) 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); Tile& currentTile = m_pTileBuffer->getTile(nRow, nColumn);
GdkPixbuf* pPixBuf = currentTile.tile_get_buffer(); GdkPixbuf* pPixBuf = currentTile.getBuffer();
gdk_cairo_set_source_pixbuf (pcairo, pPixBuf, twipToPixel(aTileRectangleTwips.x, m_fZoom), twipToPixel(aTileRectangleTwips.y, m_fZoom)); gdk_cairo_set_source_pixbuf (pcairo, pPixBuf,
twipToPixel(aTileRectangleTwips.x, m_fZoom),
twipToPixel(aTileRectangleTwips.y, m_fZoom));
cairo_paint(pcairo); cairo_paint(pcairo);
} }
} }
...@@ -942,7 +946,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback) ...@@ -942,7 +946,7 @@ gboolean LOKDocView_Impl::callbackImpl(CallbackData* pCallback)
} }
else else
{ {
m_pTileBuffer->tile_buffer_reset_all_tiles(); m_pTileBuffer->resetAllTiles();
renderDocument(0); renderDocument(0);
} }
} }
...@@ -1148,21 +1152,28 @@ static void lok_docview_init( GTypeInstance* pInstance, gpointer ) ...@@ -1148,21 +1152,28 @@ static void lok_docview_init( GTypeInstance* pInstance, gpointer )
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(pDocView), gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(pDocView),
pDocView->m_pImpl->m_pDrawingArea ); 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", "expose-event",
GTK_SIGNAL_FUNC(LOKDocView_Impl::on_exposed), pDocView); G_CALLBACK(LOKDocView_Impl::on_exposed), pDocView);
g_signal_connect(GTK_OBJECT(pDocView->m_pImpl->m_pDrawingArea), g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea),
"expose-event", "expose-event",
GTK_SIGNAL_FUNC(LOKDocView_Impl::renderOverlay), pDocView); G_CALLBACK(LOKDocView_Impl::renderOverlay), pDocView);
gtk_widget_add_events(pDocView->m_pImpl->m_pDrawingArea, gtk_widget_add_events(pDocView->m_pImpl->m_pDrawingArea,
GDK_BUTTON_PRESS_MASK GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK |GDK_BUTTON_RELEASE_MASK
| GDK_BUTTON_MOTION_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),
g_signal_connect(G_OBJECT(pDocView->m_pImpl->m_pDrawingArea), "motion-notify-event", G_CALLBACK(LOKDocView_Impl::signalMotion), pDocView); "button-press-event",
G_CALLBACK(LOKDocView_Impl::signalButton), pDocView);
gtk_signal_connect(GTK_OBJECT(pDocView), "destroy", GTK_SIGNAL_FUNC(LOKDocView_Impl::destroy), 0); 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() SAL_DLLPUBLIC_EXPORT guint lok_docview_get_type()
...@@ -1253,7 +1264,7 @@ SAL_DLLPUBLIC_EXPORT void lok_docview_set_zoom ( LOKDocView* pDocView, float fZo ...@@ -1253,7 +1264,7 @@ SAL_DLLPUBLIC_EXPORT void lok_docview_set_zoom ( LOKDocView* pDocView, float fZo
guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels); guint nRows = ceil((double)nDocumentHeightPixels / nTileSizePixels);
guint nColumns = ceil((double)nDocumentWidthPixels / 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 ) if ( pDocView->m_pImpl->m_pDocument )
pDocView->m_pImpl->renderDocument(0); pDocView->m_pImpl->renderDocument(0);
......
/* -*- 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. * This file is part of the LibreOffice project.
* *
...@@ -9,6 +9,10 @@ ...@@ -9,6 +9,10 @@
#include "tilebuffer.hxx" #include "tilebuffer.hxx"
/* ------------------
Utility functions
------------------
*/
float pixelToTwip(float fInput, float zoom) float pixelToTwip(float fInput, float zoom)
{ {
return (fInput / DPI / zoom) * 1440.0f; return (fInput / DPI / zoom) * 1440.0f;
...@@ -19,84 +23,96 @@ float twipToPixel(float fInput, float zoom) ...@@ -19,84 +23,96 @@ float twipToPixel(float fInput, float zoom)
return fInput / 1440.0f * DPI * zoom; return fInput / 1440.0f * DPI * zoom;
} }
GdkPixbuf* Tile::tile_get_buffer() /* ----------------------------
Tile class member functions
----------------------------
*/
GdkPixbuf* Tile::getBuffer()
{ {
return m_pBuffer; return m_pBuffer;
} }
void Tile::tile_release() void Tile::release()
{ {
g_object_unref (m_pBuffer); g_object_unref (m_pBuffer);
m_pBuffer = NULL; 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; m_fZoomFactor = newZoomFactor;
tile_buffer_reset_all_tiles(); resetAllTiles();
// set new buffer width and height // set new buffer width and height
m_nWidth = columns; m_nWidth = columns;
m_nHeight = rows; m_nHeight = rows;
} }
void TileBuffer::tile_buffer_reset_all_tiles() void TileBuffer::resetAllTiles()
{ {
std::map<int, Tile>::iterator it = m_mTiles.begin(); std::map<int, Tile>::iterator it = m_mTiles.begin();
for (; it != m_mTiles.end(); it++) for (; it != m_mTiles.end(); it++)
{ {
it->second.tile_release(); it->second.release();
} }
m_mTiles.clear(); 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; int index = x * m_nWidth + y;
g_info("setting invalid : %d %d",x, y); g_info("Setting tile invalid (%d, %d)", x, y);
if (m_mTiles.find(index) != m_mTiles.end()) if (m_mTiles.find(index) != m_mTiles.end())
{ {
m_mTiles[index].valid = 0; m_mTiles[index].valid = 0;
m_mTiles[index].tile_release(); m_mTiles[index].release();
m_mTiles.erase(index); 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; int index = x * m_nWidth + y;
if(m_mTiles.find(index) == m_mTiles.end() || !m_mTiles[index].valid) 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); GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, m_nTileSize, m_nTileSize);
if (!pPixBuf){ if (!pPixBuf)
g_info ("error allocating memory to pixbuf"); {
} g_info ("Error allocating memory to pixbuf");
unsigned char* pBuffer = gdk_pixbuf_get_pixels(pPixBuf); return m_mTiles[index];
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;
} }
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]; return m_mTiles[index];
} }
void Tile::tile_set_pixbuf(GdkPixbuf *buffer)
{ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
m_pBuffer = buffer;
}
/* -*- 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. * This file is part of the LibreOffice project.
* *
...@@ -24,32 +24,60 @@ const int DPI = 96; ...@@ -24,32 +24,60 @@ const int DPI = 96;
// Lets use a square of side 256 pixels for each tile. // Lets use a square of side 256 pixels for each tile.
const int nTileSizePixels = 256; 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); 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); float twipToPixel(float fInput, float zoom);
/* /**
This class represents a single tile in the tile buffer. This class represents a single tile in the tile buffer.
TODO: Extend it to support features like double buffering It encloses a reference to GdkPixBuf containing the pixel data of the tile.
*/ */
class Tile class Tile
{ {
public: public:
Tile() : valid(0) {} Tile() : valid(0) {}
~Tile() { ~Tile() { }
}
GdkPixbuf* tile_get_buffer(); /**
void tile_release(); Tells if this tile is valid or not. Initialised to 0 (invalid) during
void tile_set_pixbuf(GdkPixbuf*); object creation.
*/
bool valid; 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; GdkPixbuf *m_pBuffer;
}; };
/* /**
TileBuffer is the buffer caching all the recently rendered tiles. This class represents the tile buffer which is responsible for managing,
The buffer is set to invalid when zoom factor changes. 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 class TileBuffer
{ {
...@@ -67,19 +95,58 @@ class TileBuffer ...@@ -67,19 +95,58 @@ class TileBuffer
~TileBuffer() {} ~TileBuffer() {}
void tile_buffer_set_zoom(float zoomFactor, int rows, int columns); /**
Tile& tile_buffer_get_tile(int x, int y); Sets the zoom factor (m_fZoomFactor) for this tile buffer. Setting the
void tile_buffer_update(); zoom factor invalidates whole of the tile buffer, destroys all tiles
void tile_buffer_reset_all_tiles(); contained within it, and sets new width, height values for tile
void tile_buffer_set_invalid(int x, int y); 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: private:
/// Contains the reference to the LOK Document that this tile buffer is for.
LibreOfficeKitDocument *m_pLOKDocument; LibreOfficeKitDocument *m_pLOKDocument;
/// The side of each squared tile in pixels.
int m_nTileSize; int m_nTileSize;
/// The zoom factor that the tile buffer is currently rendered to.
float m_fZoomFactor; float m_fZoomFactor;
/// Stores all the tiles cached by this tile buffer.
std::map<int, Tile> m_mTiles; 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; int m_nWidth;
/// Height of the current tile buffer (numbero of rows)
int m_nHeight; int m_nHeight;
}; };
#endif // INCLUDED_TILEBUFFER_HXX #endif // INCLUDED_TILEBUFFER_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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