summaryrefslogtreecommitdiffstats
path: root/libreofficekit/source/gtk/tilebuffer.hxx
blob: 239482e34625fe5655e086b196a9e950ce6ad008 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/* -*- 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 <cairo.h>
#include <gio/gio.h>
#include <glib.h>

#include <map>

#define LOK_TILEBUFFER_ERROR (LOKTileBufferErrorQuark())

// 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);

/**
   Gets GQuark identifying this tile buffer errors
*/
GQuark LOKTileBufferErrorQuark(void);

/**
   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(false)
        , m_pBuffer(nullptr)
    {
    }
    ~Tile()
    {
        if (m_pBuffer)
            cairo_surface_destroy(m_pBuffer);
    }

    /**
       Tells if this tile is valid or not. Initialised to 0 (invalid) during
       object creation.
    */
    bool valid;

    /// Function to get the pointer to enclosing cairo_surface_t
    cairo_surface_t* getBuffer();
    /// Used to set the pixel buffer of this object
    void setSurface(cairo_surface_t*);

private:
    /// Pixel buffer data for this tile
    cairo_surface_t* m_pBuffer;
};

/**
   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
{
public:
    TileBuffer(int columns = 0, int scale = 1)
        : m_nWidth(columns)
    {
        cairo_surface_t* pSurface = cairo_image_surface_create(
            CAIRO_FORMAT_ARGB32, nTileSizePixels * scale, nTileSizePixels * scale);
        m_DummyTile.setSurface(pSurface);
        cairo_surface_destroy(pSurface);
    }

    /**
       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
       @param task GTask object containing the necessary data
       @param pool GThreadPool managed by the widget instance used for all the
       LOK calls made by widget. It is needed here because getTile invokes one
       of the LOK call : paintTile.

       @return the tile at the mentioned position (x, y)
     */
    Tile& getTile(int x, int y, GTask* task, GThreadPool* pool);

    /*
      Takes ownership of the surface and sets it on a tile at a given location
    */
    void setTile(int x, int y, cairo_surface_t* surface);

    /// Returns true if a valid tile exists at this location
    bool hasValidTile(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
       @param zoom zoom factor of the document
       @param task GTask object containing the necessary data
       @param pool GThreadPool managed by the widget instance used for all the
       LOK calls made by widget. It is needed here because setInvalid() invokes one
       of the LOK call : paintTile.
     */
    void setInvalid(int x, int y, float zoom, GTask* task, GThreadPool*);

private:
    /// Stores all the tiles cached by this tile buffer.
    std::map<int, Tile> m_mTiles;
    /// Width of the current tile buffer (number of columns)
    int m_nWidth;
    /// Dummy tile
    Tile m_DummyTile;
};

enum
{
    LOK_LOAD_DOC,
    LOK_POST_COMMAND,
    LOK_SET_EDIT,
    LOK_SET_PARTMODE,
    LOK_SET_PART,
    LOK_POST_KEY,
    LOK_PAINT_TILE,
    LOK_POST_MOUSE_EVENT,
    LOK_SET_GRAPHIC_SELECTION,
    LOK_SET_CLIENT_ZOOM
};

enum
{
    LOK_TILEBUFFER_CHANGED,
    LOK_TILEBUFFER_MEMORY
};

/**
   A struct that we use to store the data about the LOK call.

   Object of this type is passed with all the LOK calls,
   so that they can be identified. Additionally, it also contains
   the data that LOK call needs.
*/
struct LOEvent
{
    /// To identify the type of LOK call
    int m_nType;

    /// @name post_command parameters
    ///@{
    const gchar* m_pCommand;
    gchar* m_pArguments;
    gboolean m_bNotifyWhenFinished;
    ///@}

    /// set_edit parameter
    gboolean m_bEdit;

    /// set_partmode parameter
    int m_nPartMode;

    /// set_part parameter
    int m_nPart;

    /// @name postKeyEvent parameters
    ///@{
    int m_nKeyEvent;
    int m_nCharCode;
    int m_nKeyCode;
    ///@}

    /// @name paintTile parameters
    ///@{
    int m_nPaintTileX;
    int m_nPaintTileY;
    float m_fPaintTileZoom;
    TileBuffer* m_pTileBuffer;
    ///@}

    /// @name postMouseEvent parameters
    ///@{
    int m_nPostMouseEventType;
    int m_nPostMouseEventX;
    int m_nPostMouseEventY;
    int m_nPostMouseEventCount;
    int m_nPostMouseEventButton;
    int m_nPostMouseEventModifier;
    ///@}

    /// @name setGraphicSelection parameters
    ///@{
    int m_nSetGraphicSelectionType;
    int m_nSetGraphicSelectionX;
    int m_nSetGraphicSelectionY;
    ///@}

    /// @name setClientView parameters
    ///@{
    int m_nTilePixelWidth;
    int m_nTilePixelHeight;
    int m_nTileTwipWidth;
    int m_nTileTwipHeight;
    ///@}

    /// Constructor to instantiate an object of type `type`.
    explicit LOEvent(int type)
        : m_nType(type)
        , m_pCommand(nullptr)
        , m_pArguments(nullptr)
        , m_bNotifyWhenFinished(false)
        , m_bEdit(false)
        , m_nPartMode(0)
        , m_nPart(0)
        , m_nKeyEvent(0)
        , m_nCharCode(0)
        , m_nKeyCode(0)
        , m_nPaintTileX(0)
        , m_nPaintTileY(0)
        , m_fPaintTileZoom(0)
        , m_pTileBuffer(nullptr)
        , m_nPostMouseEventType(0)
        , m_nPostMouseEventX(0)
        , m_nPostMouseEventY(0)
        , m_nPostMouseEventCount(0)
        , m_nPostMouseEventButton(0)
        , m_nPostMouseEventModifier(0)
        , m_nSetGraphicSelectionType(0)
        , m_nSetGraphicSelectionX(0)
        , m_nSetGraphicSelectionY(0)
        , m_nTilePixelWidth(0)
        , m_nTilePixelHeight(0)
        , m_nTileTwipWidth(0)
        , m_nTileTwipHeight(0)
    {
    }

    /// Wrapper around delete to help GLib.
    static void destroy(void* pMemory);
};

#endif // INCLUDED_TILEBUFFER_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */