1 //========================================================================
5 // Copyright 2004 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
19 #include "GlobalParams.h"
21 #include "SplashBitmap.h"
22 #include "SplashPattern.h"
23 #include "SplashPath.h"
25 #include "ErrorCodes.h"
27 #include "TextOutputDev.h"
28 #include "CoreOutputDev.h"
31 //------------------------------------------------------------------------
33 //------------------------------------------------------------------------
35 PDFCorePage::PDFCorePage(int pageA
, int wA
, int hA
, int tileWA
, int tileHA
) {
46 PDFCorePage::~PDFCorePage() {
47 deleteGList(tiles
, PDFCoreTile
);
56 //------------------------------------------------------------------------
58 //------------------------------------------------------------------------
60 PDFCoreTile::PDFCoreTile(int xDestA
, int yDestA
) {
70 PDFCoreTile::~PDFCoreTile() {
77 //------------------------------------------------------------------------
79 //------------------------------------------------------------------------
81 PDFCore::PDFCore(SplashColorMode colorModeA
, int bitmapRowPadA
,
82 GBool reverseVideoA
, SplashColorPtr paperColorA
) {
86 continuousMode
= globalParams
->getContinuousView();
87 drawAreaWidth
= drawAreaHeight
= 0;
88 maxPageW
= totalDocH
= 0;
91 scrollX
= scrollY
= 0;
97 selectULX
= selectLRX
= 0;
98 selectULY
= selectLRY
= 0;
100 lastDragLeft
= lastDragTop
= gTrue
;
102 historyCur
= pdfHistorySize
- 1;
103 historyBLen
= historyFLen
= 0;
104 for (i
= 0; i
< pdfHistorySize
; ++i
) {
105 history
[i
].fileName
= NULL
;
112 splashColorCopy(paperColor
, paperColorA
);
113 out
= new CoreOutputDev(colorModeA
, bitmapRowPadA
,
114 reverseVideoA
, paperColorA
, gTrue
,
119 PDFCore::~PDFCore() {
125 for (i
= 0; i
< pdfHistorySize
; ++i
) {
126 if (history
[i
].fileName
) {
127 delete history
[i
].fileName
;
131 deleteGList(pages
, PDFCorePage
);
135 int PDFCore::loadFile(GString
*fileName
, GString
*ownerPassword
,
136 GString
*userPassword
) {
139 setBusyCursor(gTrue
);
140 err
= loadFile2(new PDFDoc(fileName
->copy(), ownerPassword
, userPassword
,
142 setBusyCursor(gFalse
);
147 int PDFCore::loadFile(wchar_t *fileName
, int fileNameLen
,
148 GString
*ownerPassword
, GString
*userPassword
) {
151 setBusyCursor(gTrue
);
152 err
= loadFile2(new PDFDoc(fileName
, fileNameLen
,
153 ownerPassword
, userPassword
, this));
154 setBusyCursor(gFalse
);
159 int PDFCore::loadFile(BaseStream
*stream
, GString
*ownerPassword
,
160 GString
*userPassword
) {
163 setBusyCursor(gTrue
);
164 err
= loadFile2(new PDFDoc(stream
, ownerPassword
, userPassword
, this));
165 setBusyCursor(gFalse
);
169 int PDFCore::loadFile2(PDFDoc
*newDoc
) {
175 if (!newDoc
->isOk()) {
176 err
= newDoc
->getErrorCode();
181 // replace old document
187 out
->startDoc(doc
->getXRef());
190 // nothing displayed yet
192 while (pages
->getLength() > 0) {
193 delete (PDFCorePage
*)pages
->del(0);
196 // compute the max unscaled page size
197 maxUnscaledPageW
= maxUnscaledPageH
= 0;
198 for (i
= 1; i
<= doc
->getNumPages(); ++i
) {
199 w
= doc
->getPageCropWidth(i
);
200 h
= doc
->getPageCropHeight(i
);
201 if (doc
->getPageRotate(i
) == 90 || doc
->getPageRotate(i
) == 270) {
204 if (w
> maxUnscaledPageW
) {
205 maxUnscaledPageW
= w
;
207 if (h
> maxUnscaledPageH
) {
208 maxUnscaledPageH
= h
;
215 void PDFCore::clear() {
227 while (pages
->getLength() > 0) {
228 delete (PDFCorePage
*)pages
->del(0);
232 scrollX
= scrollY
= 0;
233 redrawWindow(0, 0, drawAreaWidth
, drawAreaHeight
, gTrue
);
237 void PDFCore::displayPage(int topPageA
, double zoomA
, int rotateA
,
238 GBool scrollToTop
, GBool addToHist
) {
239 int scrollXA
, scrollYA
;
242 if (continuousMode
) {
244 } else if (scrollToTop
) {
251 scrollYA
= continuousMode
? -1 : 0;
255 lastDragLeft
= lastDragTop
= gTrue
;
257 update(topPageA
, scrollXA
, scrollYA
, zoomA
, rotateA
, gTrue
, addToHist
);
260 void PDFCore::displayDest(LinkDest
*dest
, double zoomA
, int rotateA
,
265 int dx
, dy
, scrollXA
, scrollYA
;
267 if (dest
->isPageRef()) {
268 pageRef
= dest
->getPageRef();
269 topPageA
= doc
->findPage(pageRef
.num
, pageRef
.gen
);
271 topPageA
= dest
->getPageNum();
273 if (topPageA
<= 0 || topPageA
> doc
->getNumPages()) {
277 scrollYA
= continuousMode
? -1 : scrollY
;
278 switch (dest
->getKind()) {
280 cvtUserToDev(topPageA
, dest
->getLeft(), dest
->getTop(), &dx
, &dy
);
281 if (continuousMode
&& topPage
> 0) {
282 dy
+= pageY
[topPageA
- 1];
284 scrollXA
= dest
->getChangeLeft() ? dx
: scrollX
;
285 scrollYA
= dest
->getChangeTop() ? dy
: scrollY
;
286 //~ what is the zoom parameter?
292 scrollYA
= continuousMode
? -1 : 0;
297 cvtUserToDev(topPageA
, 0, dest
->getTop(), &dx
, &dy
);
298 if (continuousMode
&& topPage
> 0) {
299 dy
+= pageY
[topPageA
- 1];
307 cvtUserToDev(topPageA
, dest
->getLeft(), 0, &dx
, &dy
);
309 scrollYA
= continuousMode
? -1 : 0;
313 cvtUserToDev(topPageA
, dest
->getLeft(), dest
->getTop(), &dx
, &dy
);
314 if (continuousMode
&& topPage
> 0) {
315 dy
+= pageY
[topPageA
- 1];
321 update(topPageA
, scrollXA
, scrollYA
, zoom
, rotate
, gFalse
,
322 addToHist
&& topPageA
!= topPage
);
326 void PDFCore::update(int topPageA
, int scrollXA
, int scrollYA
,
327 double zoomA
, int rotateA
, GBool force
, GBool addToHist
) {
328 double hDPI
, vDPI
, dpiA
, uw
, uh
, ut
;
329 int w
, h
, t
, x0
, x1
, y0
, y1
, x
, y
;
335 SplashColor xorColor
;
339 //~ handle fullScreen
341 // check for document and valid page number
343 // save the new settings
348 if (topPageA
<= 0 || topPageA
> doc
->getNumPages()) {
354 // check for changes to the PDF file
355 if ((force
|| (!continuousMode
&& topPage
!= topPageA
)) &&
357 if (loadFile(doc
->getFileName()) == errNone
) {
358 if (topPageA
> doc
->getNumPages()) {
359 topPageA
= doc
->getNumPages();
366 if (continuousMode
) {
367 uw
= maxUnscaledPageW
;
368 uh
= maxUnscaledPageH
;
371 uw
= doc
->getPageCropWidth(topPageA
);
372 uh
= doc
->getPageCropHeight(topPageA
);
373 rot
= rotateA
+ doc
->getPageRotate(topPageA
);
376 } else if (rot
< 0) {
380 if (rot
== 90 || rot
== 270) {
381 ut
= uw
; uw
= uh
; uh
= ut
;
383 if (zoomA
== zoomPage
) {
384 hDPI
= (drawAreaWidth
/ uw
) * 72;
385 if (continuousMode
) {
386 vDPI
= ((drawAreaHeight
- continuousModePageSpacing
) / uh
) * 72;
388 vDPI
= (drawAreaHeight
/ uh
) * 72;
390 dpiA
= (hDPI
< vDPI
) ? hDPI
: vDPI
;
391 } else if (zoomA
== zoomWidth
) {
392 dpiA
= (drawAreaWidth
/ uw
) * 72;
394 dpiA
= 0.01 * zoomA
* 72;
396 // this can happen if the window hasn't been sized yet
401 // if the display properties have changed, create a new PDFCorePage
403 if (force
|| pages
->getLength() == 0 ||
404 (!continuousMode
&& topPageA
!= topPage
) ||
405 zoomA
!= zoom
|| dpiA
!= dpi
|| rotateA
!= rotate
) {
407 setSelection(0, 0, 0, 0, 0);
408 while (pages
->getLength() > 0) {
409 delete (PDFCorePage
*)pages
->del(0);
414 if (continuousMode
) {
415 maxPageW
= totalDocH
= 0;
416 pageY
= (int *)greallocn(pageY
, doc
->getNumPages(), sizeof(int));
417 for (i
= 1; i
<= doc
->getNumPages(); ++i
) {
418 pageY
[i
-1] = totalDocH
;
419 w
= (int)((doc
->getPageCropWidth(i
) * dpi
) / 72 + 0.5);
420 h
= (int)((doc
->getPageCropHeight(i
) * dpi
) / 72 + 0.5);
421 rot
= rotate
+ doc
->getPageRotate(i
);
424 } else if (rot
< 0) {
427 if (rot
== 90 || rot
== 270) {
434 if (i
< doc
->getNumPages()) {
435 totalDocH
+= continuousModePageSpacing
;
439 rot
= rotate
+ doc
->getPageRotate(topPageA
);
442 } else if (rot
< 0) {
445 addPage(topPageA
, rot
);
448 // erase the selection
449 if (selectULX
!= selectLRX
&& selectULY
!= selectLRY
) {
450 xorColor
[0] = xorColor
[1] = xorColor
[2] = 0xff;
451 xorRectangle(selectPage
, selectULX
, selectULY
, selectLRX
, selectLRY
,
452 new SplashSolidColor(xorColor
));
455 if (continuousMode
) {
456 page
= NULL
; // make gcc happy
458 page
= (PDFCorePage
*)pages
->get(0);
462 // adjust the scroll position
464 if (continuousMode
&& scrollYA
< 0) {
465 scrollY
= pageY
[topPage
- 1];
469 w
= continuousMode
? maxPageW
: page
->w
;
470 if (scrollX
> w
- drawAreaWidth
) {
471 scrollX
= w
- drawAreaWidth
;
476 h
= continuousMode
? totalDocH
: page
->h
;
477 if (scrollY
> h
- drawAreaHeight
) {
478 scrollY
= h
- drawAreaHeight
;
484 // find topPage, and the first and last pages to be rasterized
485 if (continuousMode
) {
486 //~ should use a binary search
487 for (i
= 2; i
<= doc
->getNumPages(); ++i
) {
488 if (pageY
[i
-1] > scrollY
- drawAreaHeight
/ 2) {
493 for (i
= pg0
+ 1; i
<= doc
->getNumPages(); ++i
) {
494 if (pageY
[i
-1] > scrollY
) {
499 for (i
= topPage
+ 1; i
<= doc
->getNumPages(); ++i
) {
500 if (pageY
[i
-1] > scrollY
+ drawAreaHeight
+ drawAreaHeight
/ 2) {
506 // delete pages that are no longer needed and insert new pages
507 // objects that are needed
508 while (pages
->getLength() > 0 &&
509 ((PDFCorePage
*)pages
->get(0))->page
< pg0
) {
510 delete (PDFCorePage
*)pages
->del(0);
512 i
= pages
->getLength() - 1;
513 while (i
> 0 && ((PDFCorePage
*)pages
->get(i
))->page
> pg1
) {
514 delete (PDFCorePage
*)pages
->del(i
--);
516 j
= pages
->getLength() > 0 ? ((PDFCorePage
*)pages
->get(0))->page
- 1
518 for (i
= pg0
; i
<= j
; ++i
) {
519 rot
= rotate
+ doc
->getPageRotate(i
);
522 } else if (rot
< 0) {
527 j
= ((PDFCorePage
*)pages
->get(pages
->getLength() - 1))->page
;
528 for (i
= j
+ 1; i
<= pg1
; ++i
) {
529 rot
= rotate
+ doc
->getPageRotate(i
);
532 } else if (rot
< 0) {
542 // delete tiles that are no longer needed
543 for (i
= 0; i
< pages
->getLength(); ++i
) {
544 page
= (PDFCorePage
*)pages
->get(i
);
546 while (j
< page
->tiles
->getLength()) {
547 tile
= (PDFCoreTile
*)page
->tiles
->get(j
);
548 if (continuousMode
) {
549 y0
= pageY
[page
->page
- 1] + tile
->yMin
;
550 y1
= pageY
[page
->page
- 1] + tile
->yMax
;
555 if (tile
->xMax
< scrollX
- drawAreaWidth
/ 2 ||
556 tile
->xMin
> scrollX
+ drawAreaWidth
+ drawAreaWidth
/ 2 ||
557 y1
< scrollY
- drawAreaHeight
/ 2 ||
558 y0
> scrollY
+ drawAreaHeight
+ drawAreaHeight
/ 2) {
559 delete (PDFCoreTile
*)page
->tiles
->del(j
);
566 // update page positions
567 for (i
= 0; i
< pages
->getLength(); ++i
) {
568 page
= (PDFCorePage
*)pages
->get(i
);
569 page
->xDest
= -scrollX
;
570 if (continuousMode
) {
571 page
->yDest
= pageY
[page
->page
- 1] - scrollY
;
573 page
->yDest
= -scrollY
;
575 if (continuousMode
) {
576 if (page
->w
< maxPageW
) {
577 page
->xDest
+= (maxPageW
- page
->w
) / 2;
579 if (maxPageW
< drawAreaWidth
) {
580 page
->xDest
+= (drawAreaWidth
- maxPageW
) / 2;
582 } else if (page
->w
< drawAreaWidth
) {
583 page
->xDest
+= (drawAreaWidth
- page
->w
) / 2;
585 if (continuousMode
&& totalDocH
< drawAreaHeight
) {
586 page
->yDest
+= (drawAreaHeight
- totalDocH
) / 2;
587 } else if (!continuousMode
&& page
->h
< drawAreaHeight
) {
588 page
->yDest
+= (drawAreaHeight
- page
->h
) / 2;
592 // rasterize any new tiles
593 for (i
= 0; i
< pages
->getLength(); ++i
) {
594 page
= (PDFCorePage
*)pages
->get(i
);
596 x1
= x0
+ page
->w
- 1;
597 if (x0
< -drawAreaWidth
/ 2) {
598 x0
= -drawAreaWidth
/ 2;
600 if (x1
> drawAreaWidth
+ drawAreaWidth
/ 2) {
601 x1
= drawAreaWidth
+ drawAreaWidth
/ 2;
603 x0
= ((x0
- page
->xDest
) / page
->tileW
) * page
->tileW
;
604 x1
= ((x1
- page
->xDest
) / page
->tileW
) * page
->tileW
;
606 y1
= y0
+ page
->h
- 1;
607 if (y0
< -drawAreaHeight
/ 2) {
608 y0
= -drawAreaHeight
/ 2;
610 if (y1
> drawAreaHeight
+ drawAreaHeight
/ 2) {
611 y1
= drawAreaHeight
+ drawAreaHeight
/ 2;
613 y0
= ((y0
- page
->yDest
) / page
->tileH
) * page
->tileH
;
614 y1
= ((y1
- page
->yDest
) / page
->tileH
) * page
->tileH
;
615 for (y
= y0
; y
<= y1
; y
+= page
->tileH
) {
616 for (x
= x0
; x
<= x1
; x
+= page
->tileW
) {
617 needTile(page
, x
, y
);
622 // update tile positions
623 for (i
= 0; i
< pages
->getLength(); ++i
) {
624 page
= (PDFCorePage
*)pages
->get(i
);
625 for (j
= 0; j
< page
->tiles
->getLength(); ++j
) {
626 tile
= (PDFCoreTile
*)page
->tiles
->get(j
);
627 tile
->xDest
= tile
->xMin
- scrollX
;
628 if (continuousMode
) {
629 tile
->yDest
= tile
->yMin
+ pageY
[page
->page
- 1] - scrollY
;
631 tile
->yDest
= tile
->yMin
- scrollY
;
633 if (continuousMode
) {
634 if (page
->w
< maxPageW
) {
635 tile
->xDest
+= (maxPageW
- page
->w
) / 2;
637 if (maxPageW
< drawAreaWidth
) {
638 tile
->xDest
+= (drawAreaWidth
- maxPageW
) / 2;
640 } else if (page
->w
< drawAreaWidth
) {
641 tile
->xDest
+= (drawAreaWidth
- page
->w
) / 2;
643 if (continuousMode
&& totalDocH
< drawAreaHeight
) {
644 tile
->yDest
+= (drawAreaHeight
- totalDocH
) / 2;
645 } else if (!continuousMode
&& page
->h
< drawAreaHeight
) {
646 tile
->yDest
+= (drawAreaHeight
- page
->h
) / 2;
651 // redraw the selection
652 if (selectULX
!= selectLRX
&& selectULY
!= selectLRY
) {
653 xorColor
[0] = xorColor
[1] = xorColor
[2] = 0xff;
654 xorRectangle(selectPage
, selectULX
, selectULY
, selectLRX
, selectLRY
,
655 new SplashSolidColor(xorColor
));
659 redrawWindow(0, 0, drawAreaWidth
, drawAreaHeight
, needUpdate
);
664 if (++historyCur
== pdfHistorySize
) {
667 hist
= &history
[historyCur
];
668 if (hist
->fileName
) {
669 delete hist
->fileName
;
671 if (doc
->getFileName()) {
672 hist
->fileName
= doc
->getFileName()->copy();
674 hist
->fileName
= NULL
;
676 hist
->page
= topPage
;
677 if (historyBLen
< pdfHistorySize
) {
684 void PDFCore::addPage(int pg
, int rot
) {
686 int w
, h
, t
, tileW
, tileH
, i
;
688 w
= (int)((doc
->getPageCropWidth(pg
) * dpi
) / 72 + 0.5);
689 h
= (int)((doc
->getPageCropHeight(pg
) * dpi
) / 72 + 0.5);
690 if (rot
== 90 || rot
== 270) {
693 tileW
= 2 * drawAreaWidth
;
700 tileH
= 2 * drawAreaHeight
;
707 page
= new PDFCorePage(pg
, w
, h
, tileW
, tileH
);
709 i
< pages
->getLength() && pg
> ((PDFCorePage
*)pages
->get(i
))->page
;
711 pages
->insert(i
, page
);
714 void PDFCore::needTile(PDFCorePage
*page
, int x
, int y
) {
716 TextOutputDev
*textOut
;
717 int xDest
, yDest
, sliceW
, sliceH
;
720 for (i
= 0; i
< page
->tiles
->getLength(); ++i
) {
721 tile
= (PDFCoreTile
*)page
->tiles
->get(i
);
722 if (x
== tile
->xMin
&& y
== tile
->yMin
) {
727 setBusyCursor(gTrue
);
729 sliceW
= page
->tileW
;
730 if (x
+ sliceW
> page
->w
) {
731 sliceW
= page
->w
- x
;
733 sliceH
= page
->tileH
;
734 if (y
+ sliceH
> page
->h
) {
735 sliceH
= page
->h
- y
;
739 if (continuousMode
) {
740 yDest
= y
+ pageY
[page
->page
- 1] - scrollY
;
744 if (continuousMode
) {
745 if (page
->w
< maxPageW
) {
746 xDest
+= (maxPageW
- page
->w
) / 2;
748 if (maxPageW
< drawAreaWidth
) {
749 xDest
+= (drawAreaWidth
- maxPageW
) / 2;
751 } else if (page
->w
< drawAreaWidth
) {
752 xDest
+= (drawAreaWidth
- page
->w
) / 2;
754 if (continuousMode
&& totalDocH
< drawAreaHeight
) {
755 yDest
+= (drawAreaHeight
- totalDocH
) / 2;
756 } else if (!continuousMode
&& page
->h
< drawAreaHeight
) {
757 yDest
+= (drawAreaHeight
- page
->h
) / 2;
759 curTile
= tile
= newTile(xDest
, yDest
);
762 tile
->xMax
= x
+ sliceW
;
763 tile
->yMax
= y
+ sliceH
;
765 if (tile
->xMin
== 0) {
766 tile
->edges
|= pdfCoreTileLeftEdge
;
768 if (tile
->xMax
== page
->w
) {
769 tile
->edges
|= pdfCoreTileRightEdge
;
771 if (continuousMode
) {
772 if (tile
->yMin
== 0) {
773 tile
->edges
|= pdfCoreTileTopSpace
;
774 if (page
->page
== 1) {
775 tile
->edges
|= pdfCoreTileTopEdge
;
778 if (tile
->yMax
== page
->h
) {
779 tile
->edges
|= pdfCoreTileBottomSpace
;
780 if (page
->page
== doc
->getNumPages()) {
781 tile
->edges
|= pdfCoreTileBottomEdge
;
785 if (tile
->yMin
== 0) {
786 tile
->edges
|= pdfCoreTileTopEdge
;
788 if (tile
->yMax
== page
->h
) {
789 tile
->edges
|= pdfCoreTileBottomEdge
;
792 doc
->displayPageSlice(out
, page
->page
, dpi
, dpi
, rotate
,
793 gFalse
, gTrue
, gTrue
, x
, y
, sliceW
, sliceH
);
794 tile
->bitmap
= out
->takeBitmap();
795 memcpy(tile
->ctm
, out
->getDefCTM(), 6 * sizeof(double));
796 memcpy(tile
->ictm
, out
->getDefICTM(), 6 * sizeof(double));
798 page
->links
= doc
->takeLinks();
801 if ((textOut
= new TextOutputDev(NULL
, gTrue
, gFalse
, gFalse
))) {
802 doc
->displayPage(textOut
, page
->page
, dpi
, dpi
, rotate
,
803 gFalse
, gTrue
, gFalse
);
804 page
->text
= textOut
->takeText();
808 page
->tiles
->append(tile
);
810 setBusyCursor(gFalse
);
813 GBool
PDFCore::gotoNextPage(int inc
, GBool top
) {
816 if (!doc
|| doc
->getNumPages() == 0 || topPage
>= doc
->getNumPages()) {
819 if ((pg
= topPage
+ inc
) > doc
->getNumPages()) {
820 pg
= doc
->getNumPages();
822 if (continuousMode
) {
829 update(pg
, scrollX
, scrollYA
, zoom
, rotate
, gFalse
, gTrue
);
833 GBool
PDFCore::gotoPrevPage(int dec
, GBool top
, GBool bottom
) {
836 if (!doc
|| doc
->getNumPages() == 0 || topPage
<= 1) {
839 if ((pg
= topPage
- dec
) < 1) {
842 if (continuousMode
) {
847 scrollYA
= ((PDFCorePage
*)pages
->get(0))->h
- drawAreaHeight
;
854 update(pg
, scrollX
, scrollYA
, zoom
, rotate
, gFalse
, gTrue
);
858 GBool
PDFCore::gotoNamedDestination(GString
*dest
) {
865 if (!(d
= doc
->findDest(dest
))) {
868 displayDest(d
, zoom
, rotate
, gTrue
);
876 GBool
PDFCore::goForward() {
879 if (historyFLen
== 0) {
882 if (++historyCur
== pdfHistorySize
) {
887 if (!doc
|| history
[historyCur
].fileName
->cmp(doc
->getFileName()) != 0) {
888 if (loadFile(history
[historyCur
].fileName
) != errNone
) {
892 pg
= history
[historyCur
].page
;
893 update(pg
, scrollX
, continuousMode
? -1 : scrollY
,
894 zoom
, rotate
, gFalse
, gFalse
);
898 GBool
PDFCore::goBackward() {
901 if (historyBLen
<= 1) {
904 if (--historyCur
< 0) {
905 historyCur
= pdfHistorySize
- 1;
909 if (!doc
|| history
[historyCur
].fileName
->cmp(doc
->getFileName()) != 0) {
910 if (loadFile(history
[historyCur
].fileName
) != errNone
) {
914 pg
= history
[historyCur
].page
;
915 update(pg
, scrollX
, continuousMode
? -1 : scrollY
,
916 zoom
, rotate
, gFalse
, gFalse
);
920 void PDFCore::scrollLeft(int nCols
) {
921 scrollTo(scrollX
- nCols
* 16, scrollY
);
924 void PDFCore::scrollRight(int nCols
) {
925 scrollTo(scrollX
+ nCols
* 16, scrollY
);
928 void PDFCore::scrollUp(int nLines
) {
929 scrollTo(scrollX
, scrollY
- nLines
* 16);
932 void PDFCore::scrollDown(int nLines
) {
933 scrollTo(scrollX
, scrollY
+ nLines
* 16);
936 void PDFCore::scrollPageUp() {
937 if (!continuousMode
&& scrollY
== 0) {
938 gotoPrevPage(1, gFalse
, gTrue
);
940 scrollTo(scrollX
, scrollY
- drawAreaHeight
);
944 void PDFCore::scrollPageDown() {
945 if (!continuousMode
&&
946 scrollY
>= ((PDFCorePage
*)pages
->get(0))->h
- drawAreaHeight
) {
947 gotoNextPage(1, gTrue
);
949 scrollTo(scrollX
, scrollY
+ drawAreaHeight
);
953 void PDFCore::scrollTo(int x
, int y
) {
954 update(topPage
, x
, y
< 0 ? 0 : y
, zoom
, rotate
, gFalse
, gFalse
);
957 void PDFCore::zoomToRect(int pg
, double ulx
, double uly
,
958 double lrx
, double lry
) {
959 int x0
, y0
, x1
, y1
, u
, sx
, sy
;
960 double rx
, ry
, newZoom
, t
;
963 cvtUserToDev(pg
, ulx
, uly
, &x0
, &y0
);
964 cvtUserToDev(pg
, lrx
, lry
, &x1
, &y1
);
966 u
= x0
; x0
= x1
; x1
= u
;
969 u
= y0
; y0
= y1
; y1
= u
;
971 rx
= (double)drawAreaWidth
/ (double)(x1
- x0
);
972 ry
= (double)drawAreaHeight
/ (double)(y1
- y0
);
974 newZoom
= rx
* (dpi
/ (0.01 * 72));
976 t
= (drawAreaHeight
* (x1
- x0
)) / drawAreaWidth
;
977 sy
= (int)(rx
* (y0
+ y1
- t
) / 2);
978 if (continuousMode
) {
979 if ((p
= findPage(pg
)) && p
->w
< maxPageW
) {
980 sx
+= (int)(0.5 * rx
* (maxPageW
- p
->w
));
982 u
= (pg
- 1) * continuousModePageSpacing
;
983 sy
+= (int)(rx
* (pageY
[pg
- 1] - u
)) + u
;
986 newZoom
= ry
* (dpi
/ (0.01 * 72));
987 t
= (drawAreaWidth
* (y1
- y0
)) / drawAreaHeight
;
988 sx
= (int)(ry
* (x0
+ x1
- t
) / 2);
990 if (continuousMode
) {
991 if ((p
= findPage(pg
)) && p
->w
< maxPageW
) {
992 sx
+= (int)(0.5 * rx
* (maxPageW
- p
->w
));
994 u
= (pg
- 1) * continuousModePageSpacing
;
995 sy
+= (int)(ry
* (pageY
[pg
- 1] - u
)) + u
;
998 update(pg
, sx
, sy
, newZoom
, rotate
, gFalse
, gFalse
);
1001 void PDFCore::setContinuousMode(GBool cm
) {
1002 if (continuousMode
!= cm
) {
1003 continuousMode
= cm
;
1004 update(topPage
, scrollX
, -1, zoom
, rotate
, gTrue
, gFalse
);
1008 void PDFCore::setSelection(int newSelectPage
,
1009 int newSelectULX
, int newSelectULY
,
1010 int newSelectLRX
, int newSelectLRY
) {
1011 int x0
, y0
, x1
, y1
, py
;
1012 GBool haveSel
, newHaveSel
;
1013 GBool needRedraw
, needScroll
;
1014 GBool moveLeft
, moveRight
, moveTop
, moveBottom
;
1015 SplashColor xorColor
;
1019 haveSel
= selectULX
!= selectLRX
&& selectULY
!= selectLRY
;
1020 newHaveSel
= newSelectULX
!= newSelectLRX
&& newSelectULY
!= newSelectLRY
;
1022 // erase old selection on off-screen bitmap
1023 needRedraw
= gFalse
;
1025 xorColor
[0] = xorColor
[1] = xorColor
[2] = 0xff;
1026 xorRectangle(selectPage
, selectULX
, selectULY
, selectLRX
, selectLRY
,
1027 new SplashSolidColor(xorColor
));
1031 // draw new selection on off-screen bitmap
1033 xorColor
[0] = xorColor
[1] = xorColor
[2] = 0xff;
1034 xorRectangle(newSelectPage
, newSelectULX
, newSelectULY
,
1035 newSelectLRX
, newSelectLRY
,
1036 new SplashSolidColor(xorColor
));
1040 // check which edges moved
1041 if (!haveSel
|| newSelectPage
!= selectPage
) {
1042 moveLeft
= moveTop
= moveRight
= moveBottom
= gTrue
;
1044 moveLeft
= newSelectULX
!= selectULX
;
1045 moveTop
= newSelectULY
!= selectULY
;
1046 moveRight
= newSelectLRX
!= selectLRX
;
1047 moveBottom
= newSelectLRY
!= selectLRY
;
1050 // redraw currently visible part of bitmap
1053 page
= findPage(newSelectPage
);
1058 redrawWindow(page
->xDest
+ x0
, page
->yDest
+ y0
,
1059 x1
- x0
+ 1, y1
- y0
+ 1, gFalse
);
1060 } else if (!newHaveSel
) {
1061 if ((page
= findPage(selectPage
))) {
1066 redrawWindow(page
->xDest
+ x0
, page
->yDest
+ y0
,
1067 x1
- x0
+ 1, y1
- y0
+ 1, gFalse
);
1070 page
= findPage(newSelectPage
);
1072 x0
= newSelectULX
< selectULX
? newSelectULX
: selectULX
;
1073 y0
= newSelectULY
< selectULY
? newSelectULY
: selectULY
;
1074 x1
= newSelectULX
> selectULX
? newSelectULX
: selectULX
;
1075 y1
= newSelectLRY
> selectLRY
? newSelectLRY
: selectLRY
;
1076 redrawWindow(page
->xDest
+ x0
, page
->yDest
+ y0
,
1077 x1
- x0
+ 1, y1
- y0
+ 1, gFalse
);
1080 x0
= newSelectLRX
< selectLRX
? newSelectLRX
: selectLRX
;
1081 y0
= newSelectULY
< selectULY
? newSelectULY
: selectULY
;
1082 x1
= newSelectLRX
> selectLRX
? newSelectLRX
: selectLRX
;
1083 y1
= newSelectLRY
> selectLRY
? newSelectLRY
: selectLRY
;
1084 redrawWindow(page
->xDest
+ x0
, page
->yDest
+ y0
,
1085 x1
- x0
+ 1, y1
- y0
+ 1, gFalse
);
1088 x0
= newSelectULX
< selectULX
? newSelectULX
: selectULX
;
1089 y0
= newSelectULY
< selectULY
? newSelectULY
: selectULY
;
1090 x1
= newSelectLRX
> selectLRX
? newSelectLRX
: selectLRX
;
1091 y1
= newSelectULY
> selectULY
? newSelectULY
: selectULY
;
1092 redrawWindow(page
->xDest
+ x0
, page
->yDest
+ y0
,
1093 x1
- x0
+ 1, y1
- y0
+ 1, gFalse
);
1096 x0
= newSelectULX
< selectULX
? newSelectULX
: selectULX
;
1097 y0
= newSelectLRY
< selectLRY
? newSelectLRY
: selectLRY
;
1098 x1
= newSelectLRX
> selectLRX
? newSelectLRX
: selectLRX
;
1099 y1
= newSelectLRY
> selectLRY
? newSelectLRY
: selectLRY
;
1100 redrawWindow(page
->xDest
+ x0
, page
->yDest
+ y0
,
1101 x1
- x0
+ 1, y1
- y0
+ 1, gFalse
);
1106 // switch to new selection coords
1107 selectPage
= newSelectPage
;
1108 selectULX
= newSelectULX
;
1109 selectULY
= newSelectULY
;
1110 selectLRX
= newSelectLRX
;
1111 selectLRY
= newSelectLRY
;
1113 // scroll if necessary
1120 page
= findPage(selectPage
);
1121 needScroll
= gFalse
;
1124 if (moveLeft
&& page
->xDest
+ selectULX
< 0) {
1125 x0
+= page
->xDest
+ selectULX
;
1127 } else if (moveRight
&& page
->xDest
+ selectLRX
>= drawAreaWidth
) {
1128 x0
+= page
->xDest
+ selectLRX
- drawAreaWidth
;
1130 } else if (moveLeft
&& page
->xDest
+ selectULX
>= drawAreaWidth
) {
1131 x0
+= page
->xDest
+ selectULX
- drawAreaWidth
;
1133 } else if (moveRight
&& page
->xDest
+ selectLRX
< 0) {
1134 x0
+= page
->xDest
+ selectLRX
;
1137 py
= continuousMode
? pageY
[selectPage
- 1] : 0;
1138 if (moveTop
&& py
+ selectULY
< y0
) {
1139 y0
= py
+ selectULY
;
1141 } else if (moveBottom
&& py
+ selectLRY
>= y0
+ drawAreaHeight
) {
1142 y0
= py
+ selectLRY
- drawAreaHeight
;
1144 } else if (moveTop
&& py
+ selectULY
>= y0
+ drawAreaHeight
) {
1145 y0
= py
+ selectULY
- drawAreaHeight
;
1147 } else if (moveBottom
&& py
+ selectLRY
< y0
) {
1148 y0
= py
+ selectLRY
;
1157 void PDFCore::moveSelection(int pg
, int x
, int y
) {
1158 int newSelectULX
, newSelectULY
, newSelectLRX
, newSelectLRY
;
1160 // don't allow selections to span multiple pages
1161 if (pg
!= selectPage
) {
1165 // move appropriate edges of selection
1167 if (x
< selectLRX
) {
1169 newSelectLRX
= selectLRX
;
1171 newSelectULX
= selectLRX
;
1173 lastDragLeft
= gFalse
;
1176 if (x
> selectULX
) {
1177 newSelectULX
= selectULX
;
1181 newSelectLRX
= selectULX
;
1182 lastDragLeft
= gTrue
;
1186 if (y
< selectLRY
) {
1188 newSelectLRY
= selectLRY
;
1190 newSelectULY
= selectLRY
;
1192 lastDragTop
= gFalse
;
1195 if (y
> selectULY
) {
1196 newSelectULY
= selectULY
;
1200 newSelectLRY
= selectULY
;
1201 lastDragTop
= gTrue
;
1205 // redraw the selection
1206 setSelection(selectPage
, newSelectULX
, newSelectULY
,
1207 newSelectLRX
, newSelectLRY
);
1210 void PDFCore::xorRectangle(int pg
, int x0
, int y0
, int x1
, int y1
,
1211 SplashPattern
*pattern
, PDFCoreTile
*oneTile
) {
1216 SplashCoord xx0
, yy0
, xx1
, yy1
;
1220 if ((page
= findPage(pg
))) {
1221 for (i
= 0; i
< page
->tiles
->getLength(); ++i
) {
1222 tile
= (PDFCoreTile
*)page
->tiles
->get(i
);
1223 if (!oneTile
|| tile
== oneTile
) {
1224 splash
= new Splash(tile
->bitmap
);
1225 splash
->setFillPattern(pattern
->copy());
1226 xx0
= (SplashCoord
)(x0
- tile
->xMin
);
1227 yy0
= (SplashCoord
)(y0
- tile
->yMin
);
1228 xx1
= (SplashCoord
)(x1
- tile
->xMin
);
1229 yy1
= (SplashCoord
)(y1
- tile
->yMin
);
1230 path
= new SplashPath();
1231 path
->moveTo(xx0
, yy0
);
1232 path
->lineTo(xx1
, yy0
);
1233 path
->lineTo(xx1
, yy1
);
1234 path
->lineTo(xx0
, yy1
);
1236 splash
->xorFill(path
, gTrue
);
1239 xi
= x0
- tile
->xMin
;
1245 if (xi
+ wi
> tile
->bitmap
->getWidth()) {
1246 wi
= tile
->bitmap
->getWidth() - xi
;
1248 yi
= y0
- tile
->yMin
;
1254 if (yi
+ hi
> tile
->bitmap
->getHeight()) {
1255 hi
= tile
->bitmap
->getHeight() - yi
;
1257 updateTileData(tile
, xi
, yi
, wi
, hi
);
1264 GBool
PDFCore::getSelection(int *pg
, double *ulx
, double *uly
,
1265 double *lrx
, double *lry
) {
1266 if (selectULX
== selectLRX
|| selectULY
== selectLRY
) {
1270 cvtDevToUser(selectPage
, selectULX
, selectULY
, ulx
, uly
);
1271 cvtDevToUser(selectPage
, selectLRX
, selectLRY
, lrx
, lry
);
1275 GString
*PDFCore::extractText(int pg
, double xMin
, double yMin
,
1276 double xMax
, double yMax
) {
1278 TextOutputDev
*textOut
;
1279 int x0
, y0
, x1
, y1
, t
;
1282 if (!doc
->okToCopy()) {
1285 if ((page
= findPage(pg
))) {
1286 cvtUserToDev(pg
, xMin
, yMin
, &x0
, &y0
);
1287 cvtUserToDev(pg
, xMax
, yMax
, &x1
, &y1
);
1289 t
= x0
; x0
= x1
; x1
= t
;
1292 t
= y0
; y0
= y1
; y1
= t
;
1294 s
= page
->text
->getText(x0
, y0
, x1
, y1
);
1296 textOut
= new TextOutputDev(NULL
, gTrue
, gFalse
, gFalse
);
1297 if (textOut
->isOk()) {
1298 doc
->displayPage(textOut
, pg
, dpi
, dpi
, rotate
, gFalse
, gTrue
, gFalse
);
1299 textOut
->cvtUserToDev(xMin
, yMin
, &x0
, &y0
);
1300 textOut
->cvtUserToDev(xMax
, yMax
, &x1
, &y1
);
1302 t
= x0
; x0
= x1
; x1
= t
;
1305 t
= y0
; y0
= y1
; y1
= t
;
1307 s
= textOut
->getText(x0
, y0
, x1
, y1
);
1316 GBool
PDFCore::find(char *s
, GBool caseSensitive
, GBool next
, GBool backward
,
1317 GBool onePageOnly
) {
1322 // convert to Unicode
1324 u
= (Unicode
*)gmallocn(len
, sizeof(Unicode
));
1325 for (i
= 0; i
< len
; ++i
) {
1326 u
[i
] = (Unicode
)(s
[i
] & 0xff);
1329 ret
= findU(u
, len
, caseSensitive
, next
, backward
, onePageOnly
);
1335 GBool
PDFCore::findU(Unicode
*u
, int len
, GBool caseSensitive
,
1336 GBool next
, GBool backward
, GBool onePageOnly
) {
1337 TextOutputDev
*textOut
;
1338 double xMin
, yMin
, xMax
, yMax
;
1342 GBool startAtTop
, startAtLast
, stopAtLast
;
1344 // check for zero-length string
1349 setBusyCursor(gTrue
);
1351 // search current page starting at previous result, current
1352 // selection, or top/bottom of page
1353 startAtTop
= startAtLast
= gFalse
;
1354 xMin
= yMin
= xMax
= yMax
= 0;
1357 startAtLast
= gTrue
;
1358 } else if (selectULX
!= selectLRX
&& selectULY
!= selectLRY
) {
1361 xMin
= selectULX
- 1;
1362 yMin
= selectULY
- 1;
1364 xMin
= selectULX
+ 1;
1365 yMin
= selectULY
+ 1;
1370 if (!(page
= findPage(pg
))) {
1371 displayPage(pg
, zoom
, rotate
, gTrue
, gFalse
);
1372 page
= findPage(pg
);
1374 if (page
->text
->findText(u
, len
, startAtTop
, gTrue
, startAtLast
, gFalse
,
1375 caseSensitive
, backward
,
1376 &xMin
, &yMin
, &xMax
, &yMax
)) {
1382 // search following/previous pages
1383 textOut
= new TextOutputDev(NULL
, gTrue
, gFalse
, gFalse
);
1384 if (!textOut
->isOk()) {
1388 for (pg
= backward
? pg
- 1 : pg
+ 1;
1389 backward
? pg
>= 1 : pg
<= doc
->getNumPages();
1390 pg
+= backward
? -1 : 1) {
1391 doc
->displayPage(textOut
, pg
, 72, 72, 0, gFalse
, gTrue
, gFalse
);
1392 if (textOut
->findText(u
, len
, gTrue
, gTrue
, gFalse
, gFalse
,
1393 caseSensitive
, backward
,
1394 &xMin
, &yMin
, &xMax
, &yMax
)) {
1400 // search previous/following pages
1401 for (pg
= backward
? doc
->getNumPages() : 1;
1402 backward
? pg
> topPage
: pg
< topPage
;
1403 pg
+= backward
? -1 : 1) {
1404 doc
->displayPage(textOut
, pg
, 72, 72, 0, gFalse
, gTrue
, gFalse
);
1405 if (textOut
->findText(u
, len
, gTrue
, gTrue
, gFalse
, gFalse
,
1406 caseSensitive
, backward
,
1407 &xMin
, &yMin
, &xMax
, &yMax
)) {
1416 // search current page ending at previous result, current selection,
1417 // or bottom/top of page
1419 xMin
= yMin
= xMax
= yMax
= 0;
1423 stopAtLast
= gFalse
;
1427 if (page
->text
->findText(u
, len
, gTrue
, gFalse
, gFalse
, stopAtLast
,
1428 caseSensitive
, backward
,
1429 &xMin
, &yMin
, &xMax
, &yMax
)) {
1436 setBusyCursor(gFalse
);
1439 // found on a different page
1441 update(pg
, scrollX
, continuousMode
? -1 : 0, zoom
, rotate
, gFalse
, gTrue
);
1442 page
= findPage(pg
);
1443 if (!page
->text
->findText(u
, len
, gTrue
, gTrue
, gFalse
, gFalse
,
1444 caseSensitive
, backward
,
1445 &xMin
, &yMin
, &xMax
, &yMax
)) {
1446 // this can happen if coalescing is bad
1450 // found: change the selection
1452 tile
= (PDFCoreTile
*)page
->tiles
->get(0);
1453 setSelection(pg
, (int)floor(xMin
), (int)floor(yMin
),
1454 (int)ceil(xMax
), (int)ceil(yMax
));
1456 setBusyCursor(gFalse
);
1461 GBool
PDFCore::cvtWindowToUser(int xw
, int yw
,
1462 int *pg
, double *xu
, double *yu
) {
1467 for (i
= 0; i
< pages
->getLength(); ++i
) {
1468 page
= (PDFCorePage
*)pages
->get(i
);
1469 for (j
= 0; j
< page
->tiles
->getLength(); ++j
) {
1470 tile
= (PDFCoreTile
*)page
->tiles
->get(j
);
1471 if ((xw
>= tile
->xDest
&& xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1472 yw
>= tile
->yDest
&& yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
) ||
1473 ((tile
->edges
& pdfCoreTileTopEdge
) &&
1474 (tile
->edges
& pdfCoreTileLeftEdge
) &&
1475 xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1476 yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
) ||
1477 ((tile
->edges
& pdfCoreTileTopEdge
) &&
1478 (tile
->edges
& pdfCoreTileRightEdge
) &&
1479 xw
>= tile
->xDest
&&
1480 yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
) ||
1481 ((tile
->edges
& pdfCoreTileTopEdge
) &&
1482 xw
>= tile
->xDest
&& xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1483 yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
) ||
1484 ((tile
->edges
& pdfCoreTileBottomEdge
) &&
1485 (tile
->edges
& pdfCoreTileLeftEdge
) &&
1486 xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1487 yw
>= tile
->yDest
) ||
1488 ((tile
->edges
& pdfCoreTileBottomEdge
) &&
1489 (tile
->edges
& pdfCoreTileRightEdge
) &&
1490 xw
>= tile
->xDest
&&
1491 yw
>= tile
->yDest
) ||
1492 ((tile
->edges
& pdfCoreTileBottomEdge
) &&
1493 xw
>= tile
->xDest
&& xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1494 yw
>= tile
->yDest
) ||
1495 ((tile
->edges
& pdfCoreTileLeftEdge
) &&
1496 xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1497 yw
>= tile
->yDest
&& yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
) ||
1498 ((tile
->edges
& pdfCoreTileRightEdge
) &&
1499 xw
>= tile
->xDest
&&
1500 yw
>= tile
->yDest
&& yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
)) {
1504 *xu
= tile
->ictm
[0] * xw
+ tile
->ictm
[2] * yw
+ tile
->ictm
[4];
1505 *yu
= tile
->ictm
[1] * xw
+ tile
->ictm
[3] * yw
+ tile
->ictm
[5];
1515 GBool
PDFCore::cvtWindowToDev(int xw
, int yw
, int *pg
, int *xd
, int *yd
) {
1520 for (i
= 0; i
< pages
->getLength(); ++i
) {
1521 page
= (PDFCorePage
*)pages
->get(i
);
1522 for (j
= 0; j
< page
->tiles
->getLength(); ++j
) {
1523 tile
= (PDFCoreTile
*)page
->tiles
->get(j
);
1524 if ((xw
>= tile
->xDest
&& xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1525 yw
>= tile
->yDest
&& yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
) ||
1526 ((tile
->edges
& pdfCoreTileTopEdge
) &&
1527 (tile
->edges
& pdfCoreTileLeftEdge
) &&
1528 xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1529 yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
) ||
1530 ((tile
->edges
& pdfCoreTileTopEdge
) &&
1531 (tile
->edges
& pdfCoreTileRightEdge
) &&
1532 xw
>= tile
->xDest
&&
1533 yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
) ||
1534 ((tile
->edges
& pdfCoreTileTopEdge
) &&
1535 xw
>= tile
->xDest
&& xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1536 yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
) ||
1537 ((tile
->edges
& pdfCoreTileBottomEdge
) &&
1538 (tile
->edges
& pdfCoreTileLeftEdge
) &&
1539 xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1540 yw
>= tile
->yDest
) ||
1541 ((tile
->edges
& pdfCoreTileBottomEdge
) &&
1542 (tile
->edges
& pdfCoreTileRightEdge
) &&
1543 xw
>= tile
->xDest
&&
1544 yw
>= tile
->yDest
) ||
1545 ((tile
->edges
& pdfCoreTileBottomEdge
) &&
1546 xw
>= tile
->xDest
&& xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1547 yw
>= tile
->yDest
) ||
1548 ((tile
->edges
& pdfCoreTileLeftEdge
) &&
1549 xw
< tile
->xDest
+ tile
->xMax
- tile
->xMin
&&
1550 yw
>= tile
->yDest
&& yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
) ||
1551 ((tile
->edges
& pdfCoreTileRightEdge
) &&
1552 xw
>= tile
->xDest
&&
1553 yw
>= tile
->yDest
&& yw
< tile
->yDest
+ tile
->yMax
- tile
->yMin
)) {
1555 *xd
= tile
->xMin
+ xw
- tile
->xDest
;
1556 *yd
= tile
->yMin
+ yw
- tile
->yDest
;
1566 void PDFCore::cvtUserToWindow(int pg
, double xu
, double yu
, int *xw
, int *yw
) {
1570 if ((page
= findPage(pg
))) {
1571 tile
= (PDFCoreTile
*)page
->tiles
->get(0);
1572 *xw
= tile
->xDest
+ (int)(tile
->ctm
[0] * xu
+ tile
->ctm
[2] * yu
+
1573 tile
->ctm
[4] + 0.5);
1574 *yw
= tile
->yDest
+ (int)(tile
->ctm
[1] * xu
+ tile
->ctm
[3] * yu
+
1575 tile
->ctm
[5] + 0.5);
1578 // this should never happen
1582 void PDFCore::cvtUserToDev(int pg
, double xu
, double yu
, int *xd
, int *yd
) {
1587 if ((page
= findPage(pg
))) {
1588 tile
= (PDFCoreTile
*)page
->tiles
->get(0);
1589 *xd
= (int)(tile
->xMin
+ tile
->ctm
[0] * xu
+
1590 tile
->ctm
[2] * yu
+ tile
->ctm
[4] + 0.5);
1591 *yd
= (int)(tile
->yMin
+ tile
->ctm
[1] * xu
+
1592 tile
->ctm
[3] * yu
+ tile
->ctm
[5] + 0.5);
1594 doc
->getCatalog()->getPage(pg
)->getDefaultCTM(ctm
, dpi
, dpi
, rotate
,
1596 *xd
= (int)(ctm
[0] * xu
+ ctm
[2] * yu
+ ctm
[4] + 0.5);
1597 *yd
= (int)(ctm
[1] * xu
+ ctm
[3] * yu
+ ctm
[5] + 0.5);
1601 void PDFCore::cvtDevToWindow(int pg
, int xd
, int yd
, int *xw
, int *yw
) {
1606 if ((page
= findPage(pg
))) {
1607 for (i
= 0; i
< page
->tiles
->getLength(); ++i
) {
1608 tile
= (PDFCoreTile
*)page
->tiles
->get(i
);
1609 if (xd
>= tile
->xMin
&& xd
< tile
->xMax
&&
1610 yd
>= tile
->yMin
&& yd
< tile
->yMax
) {
1611 *xw
= tile
->xDest
+ xd
- tile
->xMin
;
1612 *yw
= tile
->yDest
+ yd
- tile
->yMin
;
1617 // this should never happen
1621 void PDFCore::cvtDevToUser(int pg
, int xd
, int yd
, double *xu
, double *yu
) {
1625 if ((page
= findPage(pg
))) {
1626 tile
= (PDFCoreTile
*)page
->tiles
->get(0);
1627 *xu
= tile
->ictm
[0] * (xd
- tile
->xMin
) +
1628 tile
->ictm
[2] * (yd
- tile
->yMin
) + tile
->ictm
[4];
1629 *yu
= tile
->ictm
[1] * (xd
- tile
->xMin
) +
1630 tile
->ictm
[3] * (yd
- tile
->yMin
) + tile
->ictm
[5];
1633 // this should never happen
1637 void PDFCore::setReverseVideo(GBool reverseVideoA
) {
1638 out
->setReverseVideo(reverseVideoA
);
1639 update(topPage
, scrollX
, scrollY
, zoom
, rotate
, gTrue
, gFalse
);
1642 LinkAction
*PDFCore::findLink(int pg
, double x
, double y
) {
1646 if ((page
= findPage(pg
))) {
1647 return page
->links
? page
->links
->find(x
, y
) : (LinkAction
*)NULL
;
1653 PDFCorePage
*PDFCore::findPage(int pg
) {
1657 for (i
= 0; i
< pages
->getLength(); ++i
) {
1658 page
= (PDFCorePage
*)pages
->get(i
);
1659 if (page
->page
== pg
) {
1666 void PDFCore::redrawCbk(void *data
, int x0
, int y0
, int x1
, int y1
) {
1667 PDFCore
*core
= (PDFCore
*)data
;
1669 core
->curTile
->bitmap
= core
->out
->getBitmap();
1670 core
->clippedRedrawRect(core
->curTile
, x0
, y0
,
1671 core
->curTile
->xDest
+ x0
, core
->curTile
->yDest
+ y0
,
1672 x1
- x0
+ 1, y1
- y0
+ 1,
1673 0, 0, core
->drawAreaWidth
, core
->drawAreaHeight
,
1677 void PDFCore::redrawWindow(int x
, int y
, int width
, int height
,
1681 int xDest
, yDest
, w
, i
, j
;
1683 if (pages
->getLength() == 0) {
1684 redrawRect(NULL
, 0, 0, x
, y
, width
, height
);
1688 for (i
= 0; i
< pages
->getLength(); ++i
) {
1689 page
= (PDFCorePage
*)pages
->get(i
);
1690 for (j
= 0; j
< page
->tiles
->getLength(); ++j
) {
1691 tile
= (PDFCoreTile
*)page
->tiles
->get(j
);
1692 if (tile
->edges
& pdfCoreTileTopEdge
) {
1693 if (tile
->edges
& pdfCoreTileLeftEdge
) {
1696 xDest
= tile
->xDest
;
1698 if (tile
->edges
& pdfCoreTileRightEdge
) {
1699 w
= drawAreaWidth
- xDest
;
1701 w
= tile
->xDest
+ (tile
->xMax
- tile
->xMin
) - xDest
;
1703 clippedRedrawRect(NULL
, 0, 0,
1704 xDest
, 0, w
, tile
->yDest
,
1705 x
, y
, width
, height
, gFalse
);
1707 if (tile
->edges
& pdfCoreTileBottomEdge
) {
1708 if (tile
->edges
& pdfCoreTileLeftEdge
) {
1711 xDest
= tile
->xDest
;
1713 if (tile
->edges
& pdfCoreTileRightEdge
) {
1714 w
= drawAreaWidth
- xDest
;
1716 w
= tile
->xDest
+ (tile
->xMax
- tile
->xMin
) - xDest
;
1718 yDest
= tile
->yDest
+ (tile
->yMax
- tile
->yMin
);
1719 clippedRedrawRect(NULL
, 0, 0,
1720 xDest
, yDest
, w
, drawAreaHeight
- yDest
,
1721 x
, y
, width
, height
, gFalse
);
1722 } else if ((tile
->edges
& pdfCoreTileBottomSpace
) &&
1723 i
+1 < pages
->getLength()) {
1724 if (tile
->edges
& pdfCoreTileLeftEdge
) {
1727 xDest
= tile
->xDest
;
1729 if (tile
->edges
& pdfCoreTileRightEdge
) {
1730 w
= drawAreaWidth
- xDest
;
1732 w
= tile
->xDest
+ (tile
->xMax
- tile
->xMin
) - xDest
;
1734 yDest
= tile
->yDest
+ (tile
->yMax
- tile
->yMin
);
1735 clippedRedrawRect(NULL
, 0, 0,
1737 w
, ((PDFCorePage
*)pages
->get(i
+1))->yDest
- yDest
,
1738 x
, y
, width
, height
, gFalse
);
1740 if (tile
->edges
& pdfCoreTileLeftEdge
) {
1741 clippedRedrawRect(NULL
, 0, 0,
1743 tile
->xDest
, tile
->yMax
- tile
->yMin
,
1744 x
, y
, width
, height
, gFalse
);
1746 if (tile
->edges
& pdfCoreTileRightEdge
) {
1747 xDest
= tile
->xDest
+ (tile
->xMax
- tile
->xMin
);
1748 clippedRedrawRect(NULL
, 0, 0,
1750 drawAreaWidth
- xDest
, tile
->yMax
- tile
->yMin
,
1751 x
, y
, width
, height
, gFalse
);
1753 clippedRedrawRect(tile
, 0, 0, tile
->xDest
, tile
->yDest
,
1754 tile
->bitmap
->getWidth(), tile
->bitmap
->getHeight(),
1755 x
, y
, width
, height
, needUpdate
);
1760 PDFCoreTile
*PDFCore::newTile(int xDestA
, int yDestA
) {
1761 return new PDFCoreTile(xDestA
, yDestA
);
1764 void PDFCore::updateTileData(PDFCoreTile
*tileA
,
1765 int xSrc
, int ySrc
, int width
, int height
) {
1768 void PDFCore::clippedRedrawRect(PDFCoreTile
*tile
, int xSrc
, int ySrc
,
1769 int xDest
, int yDest
, int width
, int height
,
1770 int xClip
, int yClip
, int wClip
, int hClip
,
1772 if (tile
&& needUpdate
) {
1773 updateTileData(tile
, xSrc
, ySrc
, width
, height
);
1775 if (xDest
< xClip
) {
1776 xSrc
+= xClip
- xDest
;
1777 width
-= xClip
- xDest
;
1780 if (xDest
+ width
> xClip
+ wClip
) {
1781 width
= xClip
+ wClip
- xDest
;
1783 if (yDest
< yClip
) {
1784 ySrc
+= yClip
- yDest
;
1785 height
-= yClip
- yDest
;
1788 if (yDest
+ height
> yClip
+ hClip
) {
1789 height
= yClip
+ hClip
- yDest
;
1791 if (width
> 0 && height
> 0) {
1792 redrawRect(tile
, xSrc
, ySrc
, xDest
, yDest
, width
, height
);