Changeset 120
- Timestamp:
- 04/26/06 06:44:05 (2 years ago)
- Location:
- trunk
- Files:
-
- 10 modified
-
src/IDocument.cxx (modified) (11 diffs)
-
src/IDocument.h (modified) (7 diffs)
-
src/MainPter.cxx (modified) (4 diffs)
-
src/MainPter.h (modified) (1 diff)
-
src/PDFDocument.cxx (modified) (5 diffs)
-
src/PDFDocument.h (modified) (1 diff)
-
tests/DumbDocument.cxx (modified) (2 diffs)
-
tests/DumbDocument.h (modified) (1 diff)
-
tests/MainPterTest.cxx (modified) (24 diffs)
-
tests/PDFDocumentTest.cxx (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/IDocument.cxx
r85 r120 22 22 23 23 // Constants. 24 static const gdouble ZOOM_IN_FACTOR = 1.2 F;25 static const gdouble ZOOM_IN_MAX = 4.0 F;26 static const gdouble ZOOM_OUT_FACTOR = (1.0 F/ ZOOM_IN_FACTOR);24 static const gdouble ZOOM_IN_FACTOR = 1.2; 25 static const gdouble ZOOM_IN_MAX = 4.0; 26 static const gdouble ZOOM_OUT_FACTOR = (1.0 / ZOOM_IN_FACTOR); 27 27 static const gdouble ZOOM_OUT_MAX = 0.05409; 28 29 // This is the asynchronous queue for rendering. 30 static guint currentCacheAge = 0; 31 32 typedef struct 33 { 34 guint32 age; 35 gint pageNum; 36 IDocument *document; 37 DocumentPage *page; 38 gboolean done; 39 } PageRequest; 28 40 29 41 /// This is the error domain that will be used to report Document's errors. … … 114 126 115 127 /// 128 /// @brief Renders the requested pages. 129 /// 130 /// This is a working thread that waits until a request to render 131 /// a page is make. Then it renders the requested page and waits 132 /// for another. 133 /// The IDocument class is responsable to make the requests. 134 /// 135 gpointer 136 IDocument::renderPageWorker (gpointer data) 137 { 138 GAsyncQueue *renderQueue = (GAsyncQueue *)data; 139 gboolean exit = FALSE; 140 do 141 { 142 PageRequest *request = (PageRequest *)g_async_queue_pop (renderQueue); 143 if ( 0 < request->pageNum ) 144 { 145 request->page = request->document->renderPage (request->pageNum); 146 request->done = TRUE; 147 } 148 else if ( -1 == request->pageNum ) 149 { 150 delete request; 151 exit = TRUE; 152 } 153 } 154 while (!exit); 155 156 g_async_queue_unref (renderQueue); 157 renderQueue = NULL; 158 159 return NULL; 160 } 161 162 /// 116 163 /// @brief Constructs a new IDocument object. 117 164 /// … … 128 175 m_Linearized = NULL; 129 176 m_ModifiedDate = NULL; 177 m_PageCache = NULL; 130 178 m_PageLayout = PageLayoutUnset; 131 179 m_PageMode = PageModeUnset; … … 134 182 m_Producer = NULL; 135 183 m_Rotation = 0; 136 m_Scale = 0.0f;184 m_Scale = 1.0f; 137 185 m_Subject = NULL; 138 186 m_Title = NULL; 187 188 if ( !g_thread_supported () ) 189 { 190 g_thread_init (NULL); 191 } 192 m_RenderQueue = g_async_queue_new (); 193 g_async_queue_ref (m_RenderQueue); 194 g_thread_create (IDocument::renderPageWorker, (gpointer)m_RenderQueue, 195 FALSE, NULL); 139 196 } 140 197 … … 157 214 g_free (m_Subject); 158 215 g_free (m_Title); 216 217 // Create a page request with an invalid queue to let know the 218 // thread that we are done. 219 PageRequest *request = new PageRequest; 220 request->pageNum = -1; 221 g_async_queue_push (m_RenderQueue, (gpointer)request); 222 g_async_queue_unref (m_RenderQueue); 159 223 } 160 224 … … 598 662 599 663 /// 664 /// @brief Gets the document's current page image. 665 /// 666 /// @return The rendered image of the current page. 667 /// 668 DocumentPage * 669 IDocument::getCurrentPage () 670 { 671 GList *cache = g_list_first (m_PageCache); 672 PageRequest *request = NULL; 673 674 while ( NULL != cache && NULL == request ) 675 { 676 PageRequest *tmpRequest = (PageRequest *)cache->data; 677 if ( m_CurrentPage == tmpRequest->pageNum ) 678 { 679 request = tmpRequest; 680 } 681 cache = g_list_next (cache); 682 } 683 684 if ( NULL == request ) 685 return NULL; 686 687 while ( !request->done ) 688 { 689 } 690 691 return request->page; 692 } 693 694 /// 600 695 /// @brief Get the document's current page number. 601 696 /// … … 620 715 { 621 716 return m_Outline; 717 } 718 719 /// 720 /// @brief Gets the current page's unscaled size. 721 /// 722 /// Retrieves the width and height of the current page before to scale, but 723 /// after rotation. 724 /// 725 /// @param width The output pointer to save the page's width. 726 /// @param height The output pointer to save the page's height. 727 /// 728 void 729 IDocument::getPageSize (gdouble *width, gdouble *height) 730 { 731 getPageSizeForPage (getCurrentPageNum (), width, height); 622 732 } 623 733 … … 671 781 IDocument::goToPage (gint pageNum) 672 782 { 673 if ( pageNum > getNumPages () ) 674 { 675 pageNum = getNumPages (); 676 } 677 else if ( pageNum < 1 ) 678 { 679 pageNum = 1; 680 } 681 682 m_CurrentPage = pageNum; 783 m_CurrentPage = CLAMP (pageNum, 1, getNumPages ()); 784 785 if ( 1 < m_CurrentPage ) 786 { 787 scheduleToRender (m_CurrentPage - 1); 788 } 789 scheduleToRender (m_CurrentPage); 790 if ( m_CurrentPage < getNumPages () ) 791 { 792 scheduleToRender (m_CurrentPage); 793 } 683 794 } 684 795 … … 717 828 { 718 829 m_Rotation = (rotation % 360); 830 refreshCache (); 719 831 } 720 832 … … 788 900 { 789 901 m_Scale = zoom; 902 refreshCache (); 790 903 } 791 904 … … 864 977 setZoom ((gdouble)width / pageWidth); 865 978 } 979 980 void 981 IDocument::scheduleToRender (gint pageNum) 982 { 983 PageRequest *request = NULL; 984 GList *cache = g_list_first (m_PageCache); 985 986 while ( NULL != cache && NULL == request) 987 { 988 PageRequest *tmpRequest = (PageRequest *)cache->data; 989 if ( pageNum == tmpRequest->pageNum ) 990 { 991 request = tmpRequest; 992 } 993 cache = g_list_next (cache); 994 } 995 996 if ( NULL == request ) 997 { 998 request = new PageRequest; 999 request->pageNum = pageNum; 1000 request->page = NULL; 1001 request->document = this; 1002 request->done = FALSE; 1003 request->age = currentCacheAge++; 1004 1005 g_async_queue_push (m_RenderQueue, (gpointer)request); 1006 1007 // Check which cached page to drop. 1008 cache = g_list_first (m_PageCache); 1009 PageRequest *olderRequest = NULL; 1010 guint32 olderAge = G_MAXUINT32; 1011 gint numCaches = 0; 1012 while ( NULL != cache ) 1013 { 1014 numCaches++; 1015 PageRequest *tmpRequest = (PageRequest *)cache->data; 1016 if ( tmpRequest->age < olderAge ) 1017 { 1018 olderAge = tmpRequest->age; 1019 olderRequest = tmpRequest; 1020 } 1021 cache = g_list_next (cache); 1022 } 1023 1024 m_PageCache = g_list_append (m_PageCache, request); 1025 if ( 3 <= numCaches ) 1026 { 1027 m_PageCache = g_list_remove (m_PageCache, olderRequest); 1028 delete olderRequest->page; 1029 delete olderRequest; 1030 } 1031 } 1032 else 1033 { 1034 request->age = currentCacheAge++; 1035 } 1036 } 1037 1038 void 1039 IDocument::refreshCache () 1040 { 1041 GList *cache = g_list_first (m_PageCache); 1042 while ( NULL != cache ) 1043 { 1044 PageRequest *request = (PageRequest *)cache->data; 1045 /* while ( !request->done ) 1046 { 1047 }*/ 1048 request->done = FALSE; 1049 g_async_queue_push (m_RenderQueue, (gpointer)request); 1050 cache = g_list_next (cache); 1051 } 1052 } -
trunk/src/IDocument.h
r78 r120 148 148 GError **error) = 0; 149 149 /// 150 /// @brief Gets the currentpage's unscaled size.151 /// 152 /// Retrieves the width and height of the currentpage before150 /// @brief Gets a document's page's unscaled size. 151 /// 152 /// Retrieves the width and height of a document's page before 153 153 /// scaling, but after rotate it. 154 154 /// 155 /// @param pageNum The page to get its size. 155 156 /// @param width The location to save the page's width. 156 157 /// @param height The location to save the page's height. 157 158 /// 158 virtual void getPageSize (gdouble *width, gdouble *height) = 0; 159 160 /// 161 /// @brief Renders the current page. 162 /// 163 /// Rendering the current page means to get the pixels for the 164 /// current page image given the current rotation and scale level. 159 virtual void getPageSizeForPage (gint pageNum, gdouble *width, 160 gdouble *height) = 0; 161 162 /// 163 /// @brief Renders a document's page. 164 /// 165 /// Rendering a document's page means to get the pixels for the 166 /// page image given the current rotation and scale level. 167 /// 168 /// @param pageNum The page number to render. 165 169 /// 166 170 /// @return A DocumentPage with the image. The returned page must 167 171 /// be freed by calling delete when done with it. 168 172 /// 169 virtual DocumentPage *renderPage ( void) = 0;173 virtual DocumentPage *renderPage (gint pageNum) = 0; 170 174 171 175 … … 198 202 PageLayout getPageLayout (void); 199 203 void setPageLayout (PageLayout layout); 204 void getPageSize (gdouble *width, gdouble *height); 200 205 gint getNumPages (void); 201 206 void setNumPages (gint numPages); 207 DocumentPage *getCurrentPage (void); 202 208 gint getCurrentPageNum (void); 203 209 DocumentOutline *getOutline (void); … … 225 231 static GQuark getErrorQuark (void); 226 232 static gchar *getErrorMessage (DocumentError errorCode); 233 static gpointer renderPageWorker (gpointer data); 227 234 228 235 protected: … … 230 237 231 238 IDocument (void); 239 void scheduleToRender (gint pageNum); 240 void refreshCache (void); 232 241 233 242 gchar *m_Author; … … 235 244 gchar *m_Creator; 236 245 gint m_CurrentPage; 237 DocumentOutline *m_Outline;238 246 gchar *m_Format; 239 247 gchar *m_FileName; … … 241 249 gchar *m_Linearized; 242 250 gchar *m_ModifiedDate; 251 DocumentOutline *m_Outline; 252 GList *m_PageCache; 243 253 PageLayout m_PageLayout; 244 254 PageMode m_PageMode; … … 250 260 gchar *m_Subject; 251 261 gchar *m_Title; 262 GAsyncQueue *m_RenderQueue; 252 263 }; 253 264 } -
trunk/src/MainPter.cxx
r119 r120 28 28 { 29 29 m_Document = new PDFDocument (); 30 m_DocumentPage = NULL;31 30 m_View = NULL; 32 31 } … … 44 43 45 44 m_Document = document; 46 m_DocumentPage = NULL;47 45 m_View = NULL; 48 46 } … … 55 53 delete m_Document; 56 54 delete m_View; 57 delete m_DocumentPage;58 55 } 59 56 … … 662 659 view.sensitiveZoomOut (m_Document->canZoomOut ()); 663 660 664 DocumentPage *oldPage = m_DocumentPage; 665 m_DocumentPage = m_Document->renderPage (); 666 if ( NULL != m_DocumentPage ) 667 { 668 getView ().showPage (m_DocumentPage, pageScroll); 669 } 670 delete oldPage; 671 } 661 DocumentPage *documentPage = m_Document->getCurrentPage (); 662 if ( NULL != documentPage ) 663 { 664 getView ().showPage (documentPage, pageScroll); 665 } 666 } -
trunk/src/MainPter.h
r115 r120 71 71 72 72 IDocument *m_Document; 73 DocumentPage *m_DocumentPage;74 73 IMainView *m_View; 75 74 -
trunk/src/PDFDocument.cxx
r91 r120 279 279 280 280 /// 281 /// @brief Gets the currentpage's unscaled size.282 /// 283 /// Retrieves the width and height of the currentpage before to scale, but281 /// @brief Gets a document's page's unscaled size. 282 /// 283 /// Retrieves the width and height of a document's page before to scale, but 284 284 /// after rotation. 285 285 /// 286 /// @param pageNum The page to get its size. 286 287 /// @param width The output pointer to save the page's width. 287 288 /// @param height The output pointer to save the page's height. 288 289 /// 289 290 void 290 PDFDocument::getPageSize (gdouble *width, gdouble *height)291 PDFDocument::getPageSizeForPage (gint pageNum, gdouble *width, gdouble *height) 291 292 { 292 293 g_assert (NULL != m_Document && "Tried to get size of a NULL document."); … … 294 295 g_assert (NULL != height && "Tried to save the page's height to NULL."); 295 296 296 PopplerPage *page = poppler_document_get_page (m_Document, 297 getCurrentPageNum () - 1); 297 PopplerPage *page = poppler_document_get_page (m_Document, pageNum - 1); 298 298 299 299 gdouble pageWidth; … … 316 316 317 317 /// 318 /// @brief Renders the currentpage.319 /// 320 /// Rendering the current page means to get the pixels for the currentpage,318 /// @brief Renders a document's page. 319 /// 320 /// Rendering a document's page means to get the pixels for the page, 321 321 /// given the current rotation level and scale. 322 /// 323 /// @param pageNum The page to render. 322 324 /// 323 325 /// @return A DocumentPage with the image. The returned page must be freed … … 325 327 /// 326 328 DocumentPage * 327 PDFDocument::renderPage ( )329 PDFDocument::renderPage (gint pageNum) 328 330 { 329 331 // First create the document's page. 330 332 gdouble pageWidth; 331 333 gdouble pageHeight; 332 getPageSize (&pageWidth, &pageHeight);334 getPageSizeForPage (pageNum, &pageWidth, &pageHeight); 333 335 gint width = MAX((gint) ((pageWidth * getZoom ()) + 0.5), 1); 334 336 gint height = MAX((gint) ((pageHeight * getZoom ()) + 0.5), 1); … … 344 346 renderedPage->getRowStride (), 345 347 NULL, NULL); 346 PopplerPage *page = poppler_document_get_page (m_Document, 347 getCurrentPageNum () - 1); 348 PopplerPage *page = poppler_document_get_page (m_Document, pageNum - 1); 348 349 poppler_page_render_to_pixbuf (page, 0, 0, width, height, getZoom (), 349 350 getRotation (), pixbuf); -
trunk/src/PDFDocument.h
r78 r120 41 41 gboolean loadFile (const gchar *filename, const gchar *password, 42 42 GError **error); 43 void getPageSize (gdouble *width, gdouble *height); 44 DocumentPage *renderPage (void); 43 void getPageSizeForPage (gint pageNum, gdouble *width, 44 gdouble *height); 45 DocumentPage *renderPage (gint pageNum); 45 46 46 47 protected: -
trunk/tests/DumbDocument.cxx
r104 r120 75 75 76 76 void 77 DumbDocument::getPageSize (gdouble *width, gdouble *height)77 DumbDocument::getPageSizeForPage (gint pageNum, gdouble *width, gdouble *height) 78 78 { 79 79 if ( 90 == getRotation () || 270 == getRotation () ) … … 90 90 91 91 DocumentPage * 92 DumbDocument::renderPage ( )92 DumbDocument::renderPage (gint pageNum) 93 93 { 94 94 return new DocumentPage (); -
trunk/tests/DumbDocument.h
r66 r120 31 31 gboolean loadFile (const gchar *filename, const gchar *password, 32 32 GError **error); 33 void getPageSize (gdouble *width, gdouble *height); 34 DocumentPage *renderPage (void); 33 void getPageSizeForPage (gint pageNum, gdouble *width, 34 gdouble *height); 35 DocumentPage *renderPage (gint pageNum); 35 36 36 37 // Test functions. -
trunk/tests/MainPterTest.cxx
r115 r120 100 100 m_MainPter->openFileActivated (); 101 101 // Sleep to let the thread open the file. 102 sleep (1);102 usleep (500); 103 103 CPPUNIT_ASSERT_EQUAL (0, 104 104 g_ascii_strcasecmp ("/tmp/test.pdf", m_View->getTitle ())); … … 122 122 m_MainPter->openFileActivated (); 123 123 // Sleep to let the thread open the file. 124 sleep (1);124 usleep (500); 125 125 CPPUNIT_ASSERT_EQUAL (0, 126 126 g_ascii_strcasecmp ("Test PDF", m_View->getTitle ())); … … 153 153 m_MainPter->openFileActivated (); 154 154 // Sleep to let the thread open the file. 155 sleep (1);155 usleep (500); 156 156 CPPUNIT_ASSERT_EQUAL (0, 157 157 g_ascii_strcasecmp ("PDF Viewer", m_View->getTitle ())); … … 186 186 m_MainPter->openFileActivated (); 187 187 // Sleep to let the thread open the file. 188 sleep (1);188 usleep (500); 189 189 CPPUNIT_ASSERT_EQUAL (0, 190 190 g_ascii_strcasecmp ("PDF Viewer", m_View->getTitle ())); … … 221 221 m_MainPter->openFileActivated (); 222 222 // Sleep to let the thread open the file. 223 sleep (1);223 usleep (500); 224 224 CPPUNIT_ASSERT_EQUAL (0, 225 225 g_ascii_strcasecmp ("PDF Viewer", m_View->getTitle ())); … … 256 256 m_MainPter->openFileActivated (); 257 257 // Sleep to let the thread open the file. 258 sleep (1);258 usleep (500); 259 259 CPPUNIT_ASSERT_EQUAL (0, 260 260 g_ascii_strcasecmp ("PDF Viewer", m_View->getTitle ())); … … 291 291 m_MainPter->openFileActivated (); 292 292 // Sleep to let the thread open the file. 293 sleep (1);293 usleep (500); 294 294 CPPUNIT_ASSERT_EQUAL (0, 295 295 g_ascii_strcasecmp ("/tmp/test.pdf", m_View->getTitle ())); … … 324 324 m_MainPter->openFileActivated (); 325 325 // Sleep to let the thread open the file. 326 sleep (1);326 usleep (500); 327 327 CPPUNIT_ASSERT (NULL == m_View->getLastOpenFileFolder ()); 328 328 … … 331 331 m_MainPter->openFileActivated (); 332 332 // Sleep to let the thread open the file. 333 sleep (1);333 usleep (500); 334 334 CPPUNIT_ASSERT (0 == g_ascii_strcasecmp ("/tmp", 335 335 m_View->getLastOpenFileFolder ())); … … 337 337 m_MainPter->openFileActivated (); 338 338 // Sleep to let the thread open the file. 339 sleep (1);339 usleep (500); 340 340 CPPUNIT_ASSERT (0 == g_ascii_strcasecmp ("/usr", 341 341 m_View->getLastOpenFileFolder ())); … … 355 355 m_MainPter->openFileActivated (); 356 356 // Sleep to let the thread open the file. 357 sleep (1);357 usleep (500); 358 358 // Check that sets the correct number of pages and the current page. 359 359 CPPUNIT_ASSERT_EQUAL (4, m_View->getTotalPages ()); … … 437 437 m_MainPter->openFileActivated (); 438 438 // Sleep to let the thread open the file. 439 sleep (1);439 usleep (500); 440 440 // Check that sets the correct number of pages and the current page. 441 441 CPPUNIT_ASSERT_EQUAL (4, m_View->getTotalPages ()); … … 518 518 m_MainPter->openFileActivated (); 519 519 // Sleep to let the thread open the file. 520 sleep (1);520 usleep (500); 521 521 CPPUNIT_ASSERT (m_View->hasImagePageView ()); 522 522 CPPUNIT_ASSERT (!m_View->hasImagePageView ()); … … 548 548 m_MainPter->openFileActivated (); 549 549 // Sleep to let the thread open the file. 550 sleep (1);550 usleep (500); 551 551 CPPUNIT_ASSERT (m_View->hasImagePageView ()); 552 552 CPPUNIT_ASSERT (!m_View->hasImagePageView ()); … … 589 589 m_MainPter->openFileActivated (); 590 590 // Sleep to let the thread open the file. 591 sleep (1);591 usleep (500); 592 592 CPPUNIT_ASSERT (m_View->hasImagePageView ());
