displaymodel.h.svn-base
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 381 行
SVN-BASE
381 行
/* Copyright Krzysztof Kowalczyk 2006-2007
License: GPLv2 */
#ifndef _DISPLAY_MODEL_H_
#define _DISPLAY_MODEL_H_
#include "base_util.h"
#include "geom_util.h"
#include "DisplayState.h"
#include "PdfEngine.h"
#include "PdfSearch.h"
#define INVALID_ZOOM -99
#define INVALID_BIG_ZOOM 999999.0 /* arbitrary but big */
typedef struct DisplaySettings {
int paddingPageBorderTop;
int paddingPageBorderBottom;
int paddingPageBorderLeft;
int paddingPageBorderRight;
int paddingBetweenPagesX;
int paddingBetweenPagesY;
} DisplaySettings;
/* the default distance between a page and window border edges, in pixels */
#ifdef _WIN32
#define PADDING_PAGE_BORDER_TOP_DEF 6
#else
#define PADDING_PAGE_BORDER_TOP_DEF 4
#endif
#define PADDING_PAGE_BORDER_BOTTOM_DEF PADDING_PAGE_BORDER_TOP_DEF
#define PADDING_PAGE_BORDER_LEFT_DEF 2
#define PADDING_PAGE_BORDER_RIGHT_DEF 2
/* the distance between pages in x axis, in pixels. Only applicable if
columns > 1 */
#define PADDING_BETWEEN_PAGES_X_DEF 4
/* the distance between pages in y axis, in pixels. Only applicable if
more than one page in y axis (continuous mode) */
#define PADDING_BETWEEN_PAGES_Y_DEF PADDING_PAGE_BORDER_TOP_DEF * 2
#define PADDING_PAGE_BORDER_TOP gDisplaySettings.paddingPageBorderTop
#define PADDING_PAGE_BORDER_BOTTOM gDisplaySettings.paddingPageBorderBottom
#define PADDING_PAGE_BORDER_LEFT gDisplaySettings.paddingPageBorderLeft
#define PADDING_PAGE_BORDER_RIGHT gDisplaySettings.paddingPageBorderRight
#define PADDING_BETWEEN_PAGES_X gDisplaySettings.paddingBetweenPagesX
#define PADDING_BETWEEN_PAGES_Y gDisplaySettings.paddingBetweenPagesY
#define POINT_OUT_OF_PAGE 0
/* Describes many attributes of one page in one, convenient place */
typedef struct PdfPageInfo {
/* data that is constant for a given page. page size and rotation
recorded in PDF file */
double pageDx; // TODO: consider SizeD instead of pageDx/pageDy
double pageDy;
int rotation;
/* data that needs to be set before DisplayModel_relayout().
Determines whether a given page should be shown on the screen. */
bool shown;
/* data that changes when zoom and rotation changes */
/* position and size within total area after applying zoom and rotation.
Represents display rectangle for a given page.
Calculated in DisplayModel_relayout() */
/* TODO: change it to RectD ?*/
double currDx;
double currDy;
double currPosX;
double currPosY;
/* data that changes due to scrolling. Calculated in DisplayModel_RecalcVisibleParts() */
bool visible; /* is currently visible on the page ? */
/* part of the image that should be shown */
int bitmapX, bitmapY, bitmapDx, bitmapDy;
/* where it should be blitted on the screen */
int screenX, screenY;
} PdfPageInfo;
/* When searching, we can be in one of those states. The state determines what
will happen after searching for next or previous term.
*/
enum SearchState {
/* Search hasn't started yet. 'Next' will start searching from the top
of current page, searching forward. 'Previous' will start searching from
the top of current page, searching backward. */
eSsNone,
/* We searched the whole document and didn't find the search term at all. 'Next'
and 'prev' do nothing. */
eSsNotFound,
/* Previous 'next' search found the term, without wrapping. 'Next' will
continue searching forward from the current position. 'Previous' will
search backward from the current position.*/
eSsFoundNext,
/* Like eSsFoundNext but we wrapped past last page. In that case we show
a message about being wrapped and continuing from top. */
eSsFoundNextWrapped,
/* Previous 'prev' search found the term, without wrapping. 'Next' will
search forward from the current position. 'Prev' will continue searching
backward */
eSsFoundPrev,
/* Like eSsFoundPrev, but wrapped around first page. */
eSsFoundPrevWrapped,
/* TODO: add eSsFoundOnlyOne as optimization i.e. if the hit is the same
as previous hit, 'next' and 'previous' will do nothing, to avoid (possibly
long) no-op search.
eSsFoundOnlyOne */
};
/* The current state of searching */
typedef struct SearchStateData {
/* String we search for, both regular and unicode versions */
//TODO: make it not depend on poppler
// GooString * str;
// UGooString * strU;
/* The page on which we started the search */
int startPage;
/* did we wrap (crossed last page when searching forward or first page
when searching backwards) */
BOOL wrapped;
SearchState searchState;
BOOL caseSensitive;
int currPage; /* page for the last hit */
} SearchStateData;
/* Information needed to drive the display of a given PDF document on a screen.
You can think of it as a model in the MVC pardigm.
All the display changes should be done through changing this model via
API and re-displaying things based on new display information */
class DisplayModel
{
public:
DisplayModel(DisplayMode displayMode);
~DisplayModel();
RenderedBitmap *renderBitmap(int pageNo, double zoomReal, int rotation,
BOOL (*abortCheckCbkA)(void *data),
void *abortCheckCbkDataA) {
if (!pdfEngine) return NULL;
return pdfEngine->renderBitmap(pageNo, zoomReal, rotation, abortCheckCbkA, abortCheckCbkDataA);
}
/* number of pages in PDF document */
int pageCount() const { return pdfEngine->pageCount(); }
bool load(const WCHAR *fileName, int startPage, WindowInfo *win, bool tryrepair);
bool validPageNo(int pageNo) const { return pdfEngine->validPageNo(pageNo); }
bool hasTocTree() { return pdfEngine->hasTocTree(); }
PdfTocItem *getTocTree() { return pdfEngine->getTocTree(); }
/* current rotation selected by user */
int rotation(void) const { return _rotation; }
void setRotation(int rotation) { _rotation = rotation; }
DisplayMode displayMode() const { return _displayMode; }
void changeDisplayMode(DisplayMode displayMode);
const WCHAR *fileName(void) const { return pdfEngine->fileName(); }
/* a "virtual" zoom level. Can be either a real zoom level in percent
(i.e. 100.0 is original size) or one of virtual values ZOOM_FIT_PAGE
or ZOOM_FIT_WIDTH, whose real value depends on draw area size */
double zoomVirtual(void) const { return _zoomVirtual; }
void setZoomVirtual(double zoomVirtual);
double zoomReal(void) const { return _zoomReal; }
int startPage(void) const { return _startPage; }
int currentPageNo(void) const;
PdfEngine * pdfEngine;
/* an arbitrary pointer that can be used by an app e.g. a multi-window GUI
could link this to a data describing window displaying this document */
void * appData() const { return _appData; }
void setAppData(void *appData) { _appData = appData; }
/* TODO: rename to pageInfo() */
PdfPageInfo * getPageInfo(int pageNo) const;
/* an array of PdfPageInfo, len of array is pageCount */
PdfPageInfo * _pagesInfo;
/* areaOffset is "polymorphic". If drawAreaSize.dx > totalAreSize.dx then
areaOffset.x is offset of total area rect inside draw area, otherwise
an offset of draw area inside total area.
The same for areaOff.y, except it's for dy */
PointD areaOffset;
/* size of draw area i.e. _totalDrawAreaSize minus scrollbarsSize (if
they're shown) */
SizeD drawAreaSize;
SearchStateData searchState;
int searchHitPageNo;
RectD searchHitRectPage;
RectI searchHitRectCanvas;
void setScrollbarsSize(int scrollbarXDy, int scrollbarYDx) {
_scrollbarXDy = scrollbarXDy;
_scrollbarYDx = scrollbarYDx;
}
void setTotalDrawAreaSize(SizeD size) {
_totalDrawAreaSize = size;
drawAreaSize = SizeD(size.dx() - _scrollbarYDx, size.dy() - _scrollbarXDy);
}
bool needHScroll() { return drawAreaSize.dxI() < _canvasSize.dxI(); }
bool needVScroll() { return drawAreaSize.dyI() < _canvasSize.dyI(); }
void changeTotalDrawAreaSize(SizeD totalDrawAreaSize);
bool pageShown(int pageNo);
bool pageVisible(int pageNo);
bool pageVisibleNearby(int pageNo);
void relayout(double zoomVirtual, int rotation);
void goToPage(int pageNo, int scrollY, int scrollX=-1);
bool goToPrevPage(int scrollY);
bool goToNextPage(int scrollY);
bool goToFirstPage(void);
bool goToLastPage(void);
void goToTocLink(void *link);
void scrollXTo(int xOff);
void scrollXBy(int dx);
void scrollYTo(int yOff);
void scrollYBy(int dy, bool changePage);
void scrollYByAreaDy(bool forward, bool changePage);
void zoomTo(double zoomVirtual);
void zoomBy(double zoomFactor);
void rotateBy(int rotation);
int getTextInRegion(int pageNo, RectD *region, unsigned short *buf, int buflen);
void clearSearchHit(void);
void setSearchHit(int pageNo, RectD *hitRect);
void recalcLinksCanvasPos(void);
int getLinkCount(void);
PdfLink * linkAtPosition(int x, int y);
void handleLink(PdfLink *pdfLink);
void goToNamedDest(const char *name);
bool cvtUserToScreen(int pageNo, double *x, double *y);
bool cvtScreenToUser(int *pageNo, double *x, double *y);
bool rectCvtUserToScreen(int pageNo, RectD *r);
bool rectCvtScreenToUser(int *pageNo, RectD *r);
void SetFindMatchCase(bool match) { _pdfSearch->SetSensitive(match); }
PdfSearchResult *Find(PdfSearchDirection direction = FIND_FORWARD, wchar_t *text = NULL);
BOOL bFoundText;
BOOL _showToc;
BOOL _fullScreen;
BOOL _tocBeforeFullScreen;
int getPageNoByPoint (double x, double y);
void MapResultRectToScreen(PdfSearchResult *rect);
void rebuildLinks();
void handleLink2(pdf_link* link);
protected:
void startRenderingPage(int pageNo);
bool buildPagesInfo(void);
double zoomRealFromFirtualForPage(double zoomVirtual, int pageNo);
int firstVisiblePageNo(void) const;
void changeStartPage(int startPage);
void recalcVisibleParts(void);
void recalcSearchHitCanvasPos(void);
void renderVisibleParts(void);
/* Those need to be implemented somewhere else by the GUI */
void setScrollbarsState(void);
/* called when a page number changes */
void pageChanged(void);
/* called when we decide that the display needs to be redrawn */
void repaintDisplay(bool delayed);
void showBusyCursor();
void showNormalCursor();
PdfSearch * _pdfSearch;
DisplayMode _displayMode; /* TODO: not used yet */
/* In non-continuous mode is the first page from a PDF file that we're
displaying.
No meaning in continous mode. */
int _startPage;
void * _appData;
/* size of scrollbars */
int _scrollbarXDy;
int _scrollbarYDx;
/* size of total draw area (i.e. window size) */
SizeD _totalDrawAreaSize;
/* size of virtual canvas containing all rendered pages.
TODO: re-consider, 32 signed number should be large enough for everything. */
SizeD _canvasSize;
/* real zoom value calculated from zoomVirtual. Same as zoomVirtual except
for ZOOM_FIT_PAGE and ZOOM_FIT_WIDTH */
double _zoomReal;
double _zoomVirtual;
int _rotation;
public:
/* an array of 'totalLinksCount' size, each entry describing a link */
PdfLink * _links;
int _linksCount;
};
bool validZoomReal(double zoomReal);
bool displayModeContinuous(DisplayMode displayMode);
bool displayModeFacing(DisplayMode displayMode);
DisplaySettings * globalDisplaySettings(void);
int columnsFromDisplayMode(DisplayMode displayMode);
void pageSizeAfterRotation(PdfPageInfo *pageInfo, int rotation, double *pageDxOut, double *pageDyOut);
bool displayStateFromDisplayModel(DisplayState *ds, DisplayModel *dm);
DisplayModel *DisplayModel_CreateFromFileName(
const WCHAR *fileName,
SizeD totalDrawAreaSize,
int scrollbarXDy, int scrollbarYDx,
DisplayMode displayMode, int startPage,
WindowInfo *win, bool tryrepair);
extern DisplaySettings gDisplaySettings;
/* must be implemented somewhere else */
extern void LaunchBrowser(const char *uri);
/* We keep a cache of rendered bitmaps. BitmapCacheEntry keeps data
that uniquely identifies rendered page (dm, pageNo, rotation, zoomReal)
and corresponding rendered bitmap.
*/
typedef struct {
DisplayModel * dm;
int pageNo;
int rotation;
double zoomLevel;
RenderedBitmap *bitmap;
double renderTime;
} BitmapCacheEntry;
typedef struct {
DisplayModel * dm;
int pageNo;
double zoomLevel;
int rotation;
int abort;
} PageRenderRequest;
/* Lock protecting both bitmap cache and page render queue */
void LockCache();
void UnlockCache();
void RenderQueue_Add(DisplayModel *dm, int pageNo);
extern void RenderQueue_RemoveForDisplayModel(DisplayModel *dm);
extern void cancelRenderingForDisplayModel(DisplayModel *dm);
BitmapCacheEntry *BitmapCache_Find(DisplayModel *dm, int pageNo, double zoomLevel, int rotation);
BitmapCacheEntry *BitmapCache_Find(DisplayModel *dm, int pageNo);
bool BitmapCache_Exists(DisplayModel *dm, int pageNo, double zoomLevel, int rotation);
void BitmapCache_Add(DisplayModel *dm, int pageNo, double zoomLevel, int rotation,
RenderedBitmap *bitmap, double renderTime);
void BitmapCache_FreeAll(void);
bool BitmapCache_FreeForDisplayModel(DisplayModel *dm);
bool BitmapCache_FreeNotVisible(void);
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?