File indexing completed on 2024-04-28 04:32:47

0001 /*
0002     SPDX-FileCopyrightText: 2012 Mailson Menezes <mailson@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #ifndef _OKULAR_TILES_MANAGER_P_H_
0007 #define _OKULAR_TILES_MANAGER_P_H_
0008 
0009 #include "area.h"
0010 #include "okularcore_export.h"
0011 
0012 class QPixmap;
0013 
0014 namespace Okular
0015 {
0016 class Tile;
0017 
0018 /**
0019  * Node in the quadtree structure used by the tiles manager to store tiles.
0020  *
0021  * Except for the first level, the tiles manager stores tiles in a quadtree
0022  * structure.
0023  * Each node stores the pixmap of a tile and its location on the page.
0024  * There's a limit on the size of the pixmaps (TILES_MAXSIZE, defined in
0025  * tilesmanager.cpp), and tiles that are bigger than that value are split into
0026  * four children tiles, which are stored as children of the original tile.
0027  * If children tiles are still too big, they are recursively split again.
0028  * If the zoom level changes and a big tile goes below the limit, it is merged
0029  * back into a leaf tile.
0030  */
0031 class TileNode
0032 {
0033 public:
0034     TileNode();
0035 
0036     bool isValid() const;
0037 
0038     /**
0039      * Location on the page in normalized coords
0040      */
0041     NormalizedRect rect;
0042 
0043     /**
0044      * Associated pixmap or NULL if not present
0045      *
0046      * For each node, it is guaranteed that there's no more than one pixmap
0047      * along the path from the root to the node itself.
0048      * In fact, it is very frequent that a leaf node has no pixmap and one
0049      * of its ancestors has. Such a situation shows, for example, when the
0050      * parent tile still has a dirty tile from a previous lower zoom level.
0051      */
0052     QPixmap *pixmap;
0053 
0054     /**
0055      * Rotation of this individual tile.
0056      *
0057      * A rotation to the page does not immediately rotates the pixmaps in
0058      * cache. This operation happens when pixmaps are going to be used.
0059      */
0060     Rotation rotation;
0061 
0062     /**
0063      * Whether the tile needs to be repainted (after a zoom or rotation)
0064      * If a tile doesn't have a pixmap but all its children are updated
0065      * (dirty = false), the parent tile is also considered updated.
0066      */
0067     bool dirty;
0068 
0069     /**
0070     Whether the tile contains a partially rendered pixmap.
0071     Some backends, such as PDF, can send partial updates that contain
0072     only some of the page's elements (e.g. only a background image) drawn.
0073     */
0074     bool partial;
0075 
0076     /**
0077      * Distance between the tile and the viewport.
0078      * This is used by the evicting algorithm.
0079      */
0080     double distance;
0081 
0082     /**
0083      * Children tiles
0084      * When a tile is split into multiple tiles, they're added as children.
0085      * nTiles can be either 0 (in leaf tiles) or 4 (in split tiles).
0086      */
0087     TileNode *tiles;
0088     int nTiles;
0089     TileNode *parent;
0090 };
0091 
0092 /**
0093  * @short Tiles management
0094  *
0095  * This class has direct access to all tiles and handles how they should be
0096  * stored, deleted and retrieved. Each tiles manager only handles one page.
0097  *
0098  * The tiles manager is a tree of tiles. At first the page is divided in a 4x4
0099  * grid of 16 tiles. Then each of these tiles can be recursively split in 4
0100  * subtiles so that we keep the size of each pixmap inside a safe interval.
0101  */
0102 class TilesManager
0103 {
0104 public:
0105     enum TileLeaf {
0106         TerminalTile, ///< Return tiles without children
0107         PixmapTile    ///< Return only tiles with pixmap
0108     };
0109 
0110     TilesManager(int pageNumber, int width, int height, Rotation rotation = Rotation0);
0111     ~TilesManager();
0112 
0113     TilesManager(const TilesManager &) = delete;
0114     TilesManager &operator=(const TilesManager &) = delete;
0115 
0116     /**
0117      * Sets the pixmap of the tiles covered by @p rect (which represents
0118      * the location of @p pixmap on the page).
0119      * @p pixmap may cover an area which contains multiple tiles. So each
0120      * tile we get a cropped part of the @p pixmap.
0121      *
0122      * Also it checks the dimensions of the given parameters against the
0123      * current request as to avoid setting pixmaps of late requests.
0124      */
0125     void setPixmap(const QPixmap *pixmap, const NormalizedRect &rect, bool isPartialPixmap);
0126 
0127     /**
0128      * Checks whether all tiles intersecting with @p rect are available.
0129      * Returns false if at least one tile needs to be repainted (the tile
0130      * is dirty).
0131      */
0132     bool hasPixmap(const NormalizedRect &rect);
0133 
0134     /**
0135      * Returns a list of all tiles intersecting with @p rect.
0136      *
0137      * As to avoid requests of big areas, each traversed tile is checked
0138      * for its size and split if necessary.
0139      *
0140      * @param rect The normalized rectangular area
0141      * @param tileLeaf Indicate the type of tile to return
0142      */
0143     QList<Tile> tilesAt(const NormalizedRect &rect, TileLeaf tileLeaf);
0144 
0145     /**
0146      * The total memory consumed by the tiles manager
0147      */
0148     qulonglong totalMemory() const;
0149 
0150     /**
0151      * Removes at least @p numberOfBytes bytes worth of tiles (least ranked
0152      * tiles are removed first).
0153      * Set @p visibleRect to the visible region of the page. Set a
0154      * @p visiblePageNumber if the current page is not visible.
0155      * Visible tiles are not discarded.
0156      */
0157     void cleanupPixmapMemory(qulonglong numberOfBytes, const NormalizedRect &visibleRect, int visiblePageNumber);
0158 
0159     /**
0160      * Checks whether a given region has already been requested
0161      */
0162     bool isRequesting(const NormalizedRect &rect, int pageWidth, int pageHeight) const;
0163 
0164     /**
0165      * Sets a region to be requested so the tiles manager knows which
0166      * pixmaps to expect and discard those not useful anymore (late pixmaps)
0167      */
0168     void setRequest(const NormalizedRect &rect, int pageWidth, int pageHeight);
0169 
0170     /**
0171      * Inform the new size of the page and mark all tiles to repaint
0172      */
0173     void setSize(int width, int height);
0174 
0175     /**
0176      * Gets the width of the page in tiles manager
0177      */
0178     int width() const;
0179 
0180     /**
0181      * Gets the height of the page in tiles manager
0182      */
0183     int height() const;
0184 
0185     /**
0186      * Inform the new rotation of the page
0187      */
0188     void setRotation(Rotation rotation);
0189     Rotation rotation() const;
0190 
0191     /**
0192      * Mark all tiles as dirty
0193      */
0194     void markDirty();
0195 
0196     /**
0197      * Returns a rotated NormalizedRect given a @p rotation
0198      */
0199     static NormalizedRect toRotatedRect(const NormalizedRect &rect, Rotation rotation);
0200 
0201     /**
0202      * Returns a non rotated version of @p rect, which is rotated by @p rotation
0203      */
0204     static NormalizedRect fromRotatedRect(const NormalizedRect &rect, Rotation rotation);
0205 
0206 private:
0207     class Private;
0208     Private *const d;
0209     friend class Private;
0210 };
0211 
0212 }
0213 
0214 #endif // _OKULAR_TILES_MANAGER_P_H_