root/trunk/tests/PDFDocumentTest.cxx

Revision 155, 28.8 kB (checked in by jordi, 2 years ago)

The PDF document now can actually search for a text in a page and return the rectangles with the position of the found text. The rectangle is kept in a new class called DocumentRectangle? that just holds the rectangle corners' coordinates.

The DocumentLink? class has been also updated to use the new DocumentRectangle? class instead of holding the rectangles coordinates by itself.

Line 
1 // ePDFView - PDF Document Test Fixture.
2 // Copyright (C) 2006 Emma's Software.
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18 #include <epdfview.h>
19 #include "Utils.h"
20 #include "DumbDocumentObserver.h"
21 #include "PDFDocumentTest.h"
22
23 using namespace ePDFView;
24    
25 G_LOCK_EXTERN (JobRender);
26
27 // Constant for checking doubles.
28 static const double DELTA = 0.0001;
29
30 // Register the test suite into the `registry'.
31 CPPUNIT_TEST_SUITE_REGISTRATION (PDFDocumentTest);
32
33 ///
34 /// @brief Sets up the environment for each test.
35 ///
36 void
37 PDFDocumentTest::setUp ()
38 {
39     m_Document = new PDFDocument ();
40     m_Observer = new DumbDocumentObserver ();
41     m_Document->attach (m_Observer);
42     G_LOCK (JobRender);
43     JobRender::m_CanProcessJobs = TRUE;
44     G_UNLOCK (JobRender);
45 }
46
47 ///
48 /// @brief Cleans up after each test.
49 ///
50 void
51 PDFDocumentTest::tearDown ()
52 {
53     G_LOCK (JobRender);
54     JobRender::m_CanProcessJobs = FALSE;
55     IJob::clearQueue ();
56     G_UNLOCK (JobRender);
57     m_Document->detach (m_Observer);
58     delete m_Observer;
59     delete m_Document;
60 }
61
62 ///
63 /// @brief Test the data of an empty (not loaded) PDF document.
64 ///
65 /// When a document has been created but still don't have a document
66 /// loaded, then the document gives some initial data. This can happen
67 /// when the first application's window is open but no PDF has been loaded
68 /// yet.
69 ///
70 void
71 PDFDocumentTest::emptyDocument ()
72 {
73     CPPUNIT_ASSERT (!m_Document->isLoaded ());
74     CPPUNIT_ASSERT_EQUAL (0,
75             g_ascii_strcasecmp ("", m_Document->getFileName ()));
76     CPPUNIT_ASSERT_EQUAL (0, g_ascii_strcasecmp ("", m_Document->getTitle ()));
77     CPPUNIT_ASSERT_EQUAL (0, g_ascii_strcasecmp ("", m_Document->getAuthor ()));
78     CPPUNIT_ASSERT_EQUAL (0,
79             g_ascii_strcasecmp ("", m_Document->getSubject ()));
80     CPPUNIT_ASSERT_EQUAL (0,
81             g_ascii_strcasecmp ("", m_Document->getKeywords ()));
82     CPPUNIT_ASSERT_EQUAL (0,
83             g_ascii_strcasecmp ("", m_Document->getCreator ()));
84     CPPUNIT_ASSERT_EQUAL (0,
85             g_ascii_strcasecmp ("", m_Document->getProducer ()));
86     CPPUNIT_ASSERT_EQUAL (0,
87             g_ascii_strcasecmp ("", m_Document->getFormat ()));
88     CPPUNIT_ASSERT_EQUAL (0,
89             g_ascii_strcasecmp ("No", m_Document->getLinearized ()));
90     CPPUNIT_ASSERT_EQUAL (0,
91             g_ascii_strcasecmp ("", m_Document->getCreationDate ()));
92     CPPUNIT_ASSERT_EQUAL (0,
93             g_ascii_strcasecmp ("", m_Document->getModifiedDate ()));
94     CPPUNIT_ASSERT_EQUAL (PageModeUnset, m_Document->getPageMode ());
95     CPPUNIT_ASSERT_EQUAL (PageLayoutUnset, m_Document->getPageLayout ());
96     CPPUNIT_ASSERT_EQUAL (0, m_Document->getNumPages ());
97     CPPUNIT_ASSERT_EQUAL (0, m_Document->getCurrentPageNum ());
98 }
99
100 ///
101 /// @brief Tests that loading a file which does not exist fails.
102 ///
103 /// Loading a PDF can fail under three conditions: the file is not found,
104 /// the file is not a PDF (or a malformed PDF file) and the file is encrypted
105 /// but not password has been supplied.
106 ///
107 /// This test just check that loading a not existent file fails.
108 ///
109 void
110 PDFDocumentTest::fileNotFound (void)
111 {
112     gchar *testFile = getTestFile ("noFile.pdf");
113     m_Document->load (testFile, NULL);
114     while ( !m_Observer->loadFinished () ) { }
115     CPPUNIT_ASSERT (m_Observer->notifiedError ());
116     CPPUNIT_ASSERT (!m_Document->isLoaded ());
117
118     gchar *documentError = IDocument::getErrorMessage(DocumentErrorOpenFile);
119     gchar *errorMessage = g_strdup_printf (
120             "Failed to load document '%s'.\n%s\n", testFile, documentError);
121     g_free(documentError);
122     const GError *error = m_Observer->getLoadError ();
123     DocumentError errorCode = (DocumentError)error->code;
124     CPPUNIT_ASSERT_EQUAL (DocumentErrorOpenFile, errorCode);
125     CPPUNIT_ASSERT_EQUAL (0, g_ascii_strcasecmp (errorMessage,
126                                                  error->message));
127     g_free (errorMessage);
128     g_free (testFile);
129 }
130
131 ///
132 /// @brief Test that loading an invalid file fails.
133 ///
134 /// This test checks the second load failure: the file is not a PDF or
135 /// is malformed.
136 ///
137 void
138 PDFDocumentTest::invalidFile (void)
139 {
140     gchar *testFile = getTestFile ("PDFDocumentTest.cxx");
141     m_Document->load (testFile, NULL);
142     while ( !m_Observer->loadFinished () ) { }
143     CPPUNIT_ASSERT (m_Observer->notifiedError ());
144     CPPUNIT_ASSERT (!m_Document->isLoaded ());
145
146     gchar *documentError = IDocument::getErrorMessage(DocumentErrorDamaged);
147     gchar *errorMessage = g_strdup_printf (
148             "Failed to load document '%s'.\n%s\n", testFile, documentError);
149     g_free(documentError);
150     const GError *error = m_Observer->getLoadError ();
151     DocumentError errorCode = (DocumentError)error->code;
152     CPPUNIT_ASSERT_EQUAL (DocumentErrorDamaged, errorCode);
153     CPPUNIT_ASSERT_EQUAL (0, g_ascii_strcasecmp (errorMessage,
154                                                  error->message));
155     g_free (testFile);
156     g_free (errorMessage);
157 }
158
159 ///
160 /// @brief Test to load an encrypted file using invalid passwords.
161 ///
162 /// This is the last test for loading an invalid file. This test tries
163 /// to open twice the same encrypted file. The first time with a NULL password
164 /// (as unencrypted) and then using an invalid password (the real password
165 /// is 'testpasswd').
166 ///
167 void
168 PDFDocumentTest::encryptedFile (void)
169 {
170     gchar *testFile = getTestFile ("test_encrypted.pdf");
171     m_Document->load (testFile, NULL);
172     while ( !m_Observer->loadFinished () ) { }
173     CPPUNIT_ASSERT (m_Observer->notifiedPassword ());
174     CPPUNIT_ASSERT (!m_Document->isLoaded ());
175
176     gchar *documentError = IDocument::getErrorMessage(DocumentErrorEncrypted);
177     gchar *errorMessage = g_strdup_printf (
178             "Failed to load document '%s'.\n%s\n", testFile, documentError);
179     g_free(documentError);
180     const GError *error = m_Observer->getLoadError ();
181     DocumentError errorCode = (DocumentError)error->code;
182     CPPUNIT_ASSERT_EQUAL (DocumentErrorEncrypted, errorCode);
183     CPPUNIT_ASSERT_EQUAL (0, g_ascii_strcasecmp (errorMessage,
184                                                  error->message));
185     g_free (errorMessage);
186    
187     // Now try with an invalid password...
188     m_Document->load (testFile, "invalidpasswd");
189     while ( !m_Observer->loadFinished () ) { }
190     CPPUNIT_ASSERT (m_Observer->notifiedPassword ());
191     CPPUNIT_ASSERT (!m_Document->isLoaded ());
192
193     documentError = IDocument::getErrorMessage(DocumentErrorEncrypted);
194     errorMessage = g_strdup_printf (
195             "Failed to load document '%s'.\n%s\n", testFile, documentError);
196     g_free(documentError);
197     error = m_Observer->getLoadError ();
198     errorCode = (DocumentError)error->code;
199     CPPUNIT_ASSERT_EQUAL (DocumentErrorEncrypted, errorCode);
200     CPPUNIT_ASSERT_EQUAL (0, g_ascii_strcasecmp (errorMessage,
201                                                  error->message));
202     g_free (errorMessage);
203
204     // And now, just to test that it can load the pdf using the
205     // correct password.
206     m_Document->load (testFile, "testpasswd");
207     while ( !m_Observer->loadFinished () ) { }
208     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
209     CPPUNIT_ASSERT (m_Document->isLoaded ());
210     CPPUNIT_ASSERT_EQUAL (0,
211             g_ascii_strcasecmp (testFile, m_Document->getFileName ()));
212     CPPUNIT_ASSERT_EQUAL (0,
213             g_ascii_strcasecmp ("testpasswd", m_Document->getPassword ()));
214
215     g_free (testFile);
216 }
217
218 ///
219 /// @brief Test to open a valid file.
220 ///
221 /// This test will open a valid file and will try to read it's values.
222 /// Unfortunately I'm unable to produce a file with all fields, so some
223 /// of them will stay empty as in the first test.
224 ///
225 void
226 PDFDocumentTest::validFile ()
227 {
228     gchar *testFile = getTestFile ("test2.pdf");
229     m_Document->load (testFile, NULL);
230     while ( !m_Observer->loadFinished () ) { }
231     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
232     CPPUNIT_ASSERT (m_Document->isLoaded ());
233     CPPUNIT_ASSERT_EQUAL (0,
234             g_ascii_strcasecmp (testFile, m_Document->getFileName ()));
235     CPPUNIT_ASSERT_EQUAL (0,
236             g_ascii_strcasecmp ("Lorem Ipsum Dolor Site Amet",
237                                 m_Document->getTitle ()));
238     CPPUNIT_ASSERT_EQUAL (0,
239             g_ascii_strcasecmp ("Jordi Fita", m_Document->getAuthor ()));
240     CPPUNIT_ASSERT_EQUAL (0,
241             g_ascii_strcasecmp ("Test PDF File", m_Document->getSubject ()));
242     CPPUNIT_ASSERT_EQUAL (0,
243             g_ascii_strcasecmp ("Lorem Ipsum Dolor Sit Amet Consectetuer",
244                                 m_Document->getKeywords ()));
245     CPPUNIT_ASSERT_EQUAL (0,
246             g_ascii_strcasecmp ("PDFCreator Version 0.9.0",
247                                 m_Document->getCreator ()));
248     CPPUNIT_ASSERT_EQUAL (0,
249             g_ascii_strcasecmp ("AFPL Ghostscript 8.53",
250                                 m_Document->getProducer ()));
251     CPPUNIT_ASSERT_EQUAL (0,
252             g_ascii_strcasecmp ("PDF-1.3", m_Document->getFormat ()));
253     CPPUNIT_ASSERT_EQUAL (0,
254             g_ascii_strcasecmp ("No", m_Document->getLinearized ()));
255     CPPUNIT_ASSERT_EQUAL (0,
256             g_ascii_strcasecmp ("2006-10-04 23:12:27",
257                                 m_Document->getCreationDate ()));
258     CPPUNIT_ASSERT_EQUAL (0,
259             g_ascii_strcasecmp ("2006-10-04 23:12:27",
260                                 m_Document->getModifiedDate ()));
261     CPPUNIT_ASSERT_EQUAL (PageModeUnset, m_Document->getPageMode ());
262     CPPUNIT_ASSERT_EQUAL (PageLayoutUnset, m_Document->getPageLayout ());
263     CPPUNIT_ASSERT_EQUAL (2, m_Document->getNumPages ());
264     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
265
266     // Another test file.
267     g_free (testFile);
268     testFile = getTestFile ("test1.pdf");
269     m_Document->load (testFile, NULL);
270     while ( !m_Observer->loadFinished () ) { }
271     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
272     CPPUNIT_ASSERT (m_Document->isLoaded ());
273     CPPUNIT_ASSERT_EQUAL (0,
274             g_ascii_strcasecmp (testFile, m_Document->getFileName ()));
275     CPPUNIT_ASSERT_EQUAL (0, g_ascii_strcasecmp ("", m_Document->getTitle ()));
276     CPPUNIT_ASSERT_EQUAL (0, g_ascii_strcasecmp ("", m_Document->getAuthor ()));
277     CPPUNIT_ASSERT_EQUAL (0,
278             g_ascii_strcasecmp ("", m_Document->getSubject ()));
279     CPPUNIT_ASSERT_EQUAL (0,
280             g_ascii_strcasecmp ("", m_Document->getKeywords ()));
281     CPPUNIT_ASSERT_EQUAL (0,
282             g_ascii_strcasecmp ("", m_Document->getCreator ()));
283     CPPUNIT_ASSERT_EQUAL (0,
284             g_ascii_strcasecmp ("FOP 0.20.5", m_Document->getProducer ()));
285     CPPUNIT_ASSERT_EQUAL (0,
286             g_ascii_strcasecmp ("PDF-1.3", m_Document->getFormat ()));
287     CPPUNIT_ASSERT_EQUAL (0,
288             g_ascii_strcasecmp ("No", m_Document->getLinearized ()));
289     CPPUNIT_ASSERT_EQUAL (0,
290             g_ascii_strcasecmp ("", m_Document->getCreationDate ()));
291     CPPUNIT_ASSERT_EQUAL (0,
292             g_ascii_strcasecmp ("", m_Document->getModifiedDate ()));
293     CPPUNIT_ASSERT_EQUAL (PageModeOutlines, m_Document->getPageMode ());
294     CPPUNIT_ASSERT_EQUAL (PageLayoutUnset, m_Document->getPageLayout ());
295     CPPUNIT_ASSERT_EQUAL (5, m_Document->getNumPages ());
296     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
297
298     g_free (testFile);
299 }
300
301 ///
302 /// @brief Test loading a relative path filename.
303 ///
304 /// Poppler's glib wrapper needs an URI instead of just a filename, but
305 /// in order to build it I need an absolute path. This check test that
306 /// giving a relative path converts it to absolute and loads the file
307 /// properly.
308 ///
309 void
310 PDFDocumentTest::relativePath ()
311 {
312     m_Document->load (TEST_DIR "test1.pdf", NULL);
313     while ( !m_Observer->loadFinished () ) { }
314     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
315     CPPUNIT_ASSERT (m_Document->isLoaded ());
316     CPPUNIT_ASSERT_EQUAL (0,
317             g_ascii_strcasecmp (TEST_DIR "test1.pdf",
318                                 m_Document->getFileName ()));
319 }
320
321 ///
322 /// @brief Test changing pages.
323 ///
324 /// The IDocument class also has the information about the current page
325 /// that's shown, so we must change it through its methods. This test just
326 /// checks that the page is changed correctly.
327 ///
328 void
329 PDFDocumentTest::pageChange ()
330 {
331     // First try with a 2 page document.
332     gchar *testFile = getTestFile ("test2.pdf");
333     m_Document->load (testFile, NULL);
334     while ( !m_Observer->loadFinished () ) { }
335     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
336     CPPUNIT_ASSERT (m_Document->isLoaded ());
337     CPPUNIT_ASSERT_EQUAL (2, m_Document->getNumPages ());
338     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
339     CPPUNIT_ASSERT_EQUAL (1, m_Observer->getCurrentPage ());
340     m_Document->goToNextPage ();
341     CPPUNIT_ASSERT_EQUAL (2, m_Document->getCurrentPageNum ());
342     CPPUNIT_ASSERT_EQUAL (2, m_Observer->getCurrentPage ());
343     // Don't let the page go after the last page.
344     m_Document->goToNextPage ();
345     CPPUNIT_ASSERT_EQUAL (2, m_Document->getCurrentPageNum ());
346     CPPUNIT_ASSERT_EQUAL (2, m_Observer->getCurrentPage ());
347     // Now go backwards.
348     m_Document->goToPreviousPage ();
349     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
350     CPPUNIT_ASSERT_EQUAL (1, m_Observer->getCurrentPage ());
351     m_Document->goToPreviousPage ();
352     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
353     CPPUNIT_ASSERT_EQUAL (1, m_Observer->getCurrentPage ());
354     // First and last pages.
355     m_Document->goToLastPage ();
356     CPPUNIT_ASSERT_EQUAL (2, m_Document->getCurrentPageNum ());
357     CPPUNIT_ASSERT_EQUAL (2, m_Observer->getCurrentPage ());
358     m_Document->goToFirstPage ();
359     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
360     CPPUNIT_ASSERT_EQUAL (1, m_Observer->getCurrentPage ());
361     // Now, let's go to an specific page. If the page is beyond the
362     // last page or before the first page then the current page
363     // doesn't change.
364     m_Document->goToPage (2);
365     CPPUNIT_ASSERT_EQUAL (2, m_Document->getCurrentPageNum ());
366     CPPUNIT_ASSERT_EQUAL (2, m_Observer->getCurrentPage ());
367     m_Document->goToPage (1);
368     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
369     CPPUNIT_ASSERT_EQUAL (1, m_Observer->getCurrentPage ());
370     m_Document->goToPage (13);
371     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
372     CPPUNIT_ASSERT_EQUAL (1, m_Observer->getCurrentPage ());
373     m_Document->goToPage (0);
374     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
375     CPPUNIT_ASSERT_EQUAL (1, m_Observer->getCurrentPage ());
376
377     // Let's try with a 5 page document.
378     g_free (testFile);
379     testFile = getTestFile ("test1.pdf");
380     m_Document->load (testFile, NULL);
381     while ( !m_Observer->loadFinished () ) { }
382     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
383     CPPUNIT_ASSERT (m_Document->isLoaded ());
384     CPPUNIT_ASSERT_EQUAL (5, m_Document->getNumPages ());
385     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
386     CPPUNIT_ASSERT_EQUAL (1, m_Observer->getCurrentPage ());
387     m_Document->goToNextPage ();
388     CPPUNIT_ASSERT_EQUAL (2, m_Document->getCurrentPageNum ());
389     CPPUNIT_ASSERT_EQUAL (2, m_Observer->getCurrentPage ());
390     m_Document->goToNextPage ();
391     CPPUNIT_ASSERT_EQUAL (3, m_Document->getCurrentPageNum ());
392     CPPUNIT_ASSERT_EQUAL (3, m_Observer->getCurrentPage ());
393     m_Document->goToPage (5);
394     CPPUNIT_ASSERT_EQUAL (5, m_Document->getCurrentPageNum ());
395     CPPUNIT_ASSERT_EQUAL (5, m_Observer->getCurrentPage ());
396     // Don't let the page go after the last page.
397     m_Document->goToNextPage ();
398     CPPUNIT_ASSERT_EQUAL (5, m_Document->getCurrentPageNum ());
399     CPPUNIT_ASSERT_EQUAL (5, m_Observer->getCurrentPage ());
400     // Now go backwards.
401     m_Document->goToPreviousPage ();
402     CPPUNIT_ASSERT_EQUAL (4, m_Document->getCurrentPageNum ());
403     CPPUNIT_ASSERT_EQUAL (4, m_Observer->getCurrentPage ());
404     m_Document->goToPreviousPage ();
405     CPPUNIT_ASSERT_EQUAL (3, m_Document->getCurrentPageNum ());
406     CPPUNIT_ASSERT_EQUAL (3, m_Observer->getCurrentPage ());
407     m_Document->goToPage (1);
408     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
409     CPPUNIT_ASSERT_EQUAL (1, m_Observer->getCurrentPage ());
410     m_Document->goToPreviousPage ();
411     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
412     CPPUNIT_ASSERT_EQUAL (1, m_Observer->getCurrentPage ());
413     // First and last pages.
414     m_Document->goToLastPage ();
415     CPPUNIT_ASSERT_EQUAL (5, m_Document->getCurrentPageNum ());
416     CPPUNIT_ASSERT_EQUAL (5, m_Observer->getCurrentPage ());
417     m_Document->goToFirstPage ();
418     CPPUNIT_ASSERT_EQUAL (1, m_Document->getCurrentPageNum ());
419     CPPUNIT_ASSERT_EQUAL (1, m_Observer->getCurrentPage ());
420     // Now, let's go to an specific page. If the page is beyond the
421     // last page, then the current page will be the last. On the other
422     // hand, if the page is less than the first (< 1) then the current
423     // page will be the first.
424     m_Document->goToPage (3);
425     CPPUNIT_ASSERT_EQUAL (3, m_Document->getCurrentPageNum ());
426     CPPUNIT_ASSERT_EQUAL (3, m_Observer->getCurrentPage ());
427     m_Document->goToPage (2);
428     CPPUNIT_ASSERT_EQUAL (2, m_Document->getCurrentPageNum ());
429     CPPUNIT_ASSERT_EQUAL (2, m_Observer->getCurrentPage ());
430     m_Document->goToPage (13);
431     CPPUNIT_ASSERT_EQUAL (2, m_Document->getCurrentPageNum ());
432     CPPUNIT_ASSERT_EQUAL (2, m_Observer->getCurrentPage ());
433     m_Document->goToPage (0);
434     CPPUNIT_ASSERT_EQUAL (2, m_Document->getCurrentPageNum ());
435     CPPUNIT_ASSERT_EQUAL (2, m_Observer->getCurrentPage ());
436
437     g_free (testFile);
438 }
439
440 ///
441 /// @brief Test rotating a page.
442 ///
443 /// It's possible to rotate a page, but only can rotate in 90 degree
444 /// step (0, 90, 180 and 270) in either side (left or right).
445 ///
446 void
447 PDFDocumentTest::pageRotate ()
448 {
449     gchar *testFile = getTestFile ("test2.pdf");
450     m_Document->load (testFile, NULL);
451     while ( !m_Observer->loadFinished () ) { }
452     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
453     CPPUNIT_ASSERT (m_Document->isLoaded ());
454     CPPUNIT_ASSERT_EQUAL (0, m_Document->getRotation ());
455     m_Document->rotateRight ();
456     CPPUNIT_ASSERT_EQUAL (90, m_Document->getRotation ());
457     CPPUNIT_ASSERT (m_Observer->notifiedRotation ());
458     m_Document->rotateLeft ();
459     CPPUNIT_ASSERT_EQUAL (0, m_Document->getRotation ());
460     CPPUNIT_ASSERT (m_Observer->notifiedRotation ());
461     m_Document->rotateRight ();
462     CPPUNIT_ASSERT (m_Observer->notifiedRotation ());
463     m_Document->rotateRight ();
464     CPPUNIT_ASSERT_EQUAL (180, m_Document->getRotation ());
465     CPPUNIT_ASSERT (m_Observer->notifiedRotation ());
466     m_Document->rotateRight ();
467     CPPUNIT_ASSERT (m_Observer->notifiedRotation ());
468     m_Document->rotateRight ();
469     CPPUNIT_ASSERT_EQUAL (0, m_Document->getRotation ());
470     CPPUNIT_ASSERT (m_Observer->notifiedRotation ());
471     m_Document->rotateLeft ();
472     CPPUNIT_ASSERT_EQUAL (270, m_Document->getRotation ());
473     CPPUNIT_ASSERT (m_Observer->notifiedRotation ());
474    
475     g_free (testFile);
476     testFile = getTestFile ("test1.pdf");
477     m_Document->load (testFile, NULL);
478     while ( !m_Observer->loadFinished () ) { }
479     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
480     CPPUNIT_ASSERT (m_Document->isLoaded ());
481     CPPUNIT_ASSERT_EQUAL (0, m_Document->getRotation ());
482     m_Document->rotateRight ();
483     CPPUNIT_ASSERT (m_Observer->notifiedRotation ());
484     m_Document->rotateRight ();
485     CPPUNIT_ASSERT (m_Observer->notifiedRotation ());
486     m_Document->rotateLeft ();
487     CPPUNIT_ASSERT_EQUAL (90, m_Document->getRotation ());
488     CPPUNIT_ASSERT (m_Observer->notifiedRotation ());
489    
490     g_free (testFile);
491 }
492
493 ///
494 /// @brief Test the document's zoom.
495 ///
496 /// The IDocument class is also responsible of the page's zoom level. It can
497 /// Zoom In, Zoom Out, Zoom to Width and Zoom to Fit.
498 ///
499 /// Currently the Zoom In uses a factor of ~1.2 and the ZoomOut of
500 /// ~(1.0/1.2)= ~0.8333. The max scale is 4.0 and the
501 ///
502 void
503 PDFDocumentTest::pageZoom ()
504 {
505     // On this document only try Zoom In and Zoom Out.
506     gchar *testFile = getTestFile ("test2.pdf");
507     m_Document->load (testFile, NULL);
508     while ( !m_Observer->loadFinished () ) { }
509     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
510     CPPUNIT_ASSERT (m_Document->isLoaded ());
511     CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0f, m_Document->getZoom (), DELTA);
512     m_Document->zoomIn ();
513     CPPUNIT_ASSERT_DOUBLES_EQUAL (1.2f, m_Document->getZoom (), DELTA);
514     CPPUNIT_ASSERT (m_Observer->notifiedZoom ());
515     CPPUNIT_ASSERT_DOUBLES_EQUAL (1.2f, m_Observer->getZoom (), DELTA);
516     m_Document->zoomIn ();
517     CPPUNIT_ASSERT_DOUBLES_EQUAL (1.44f, m_Document->getZoom (), DELTA);
518     CPPUNIT_ASSERT (m_Observer->notifiedZoom ());
519     CPPUNIT_ASSERT_DOUBLES_EQUAL (1.44f, m_Observer->getZoom (), DELTA);
520     m_Document->zoomOut ();
521     CPPUNIT_ASSERT_DOUBLES_EQUAL (1.2f, m_Document->getZoom (), DELTA);
522     CPPUNIT_ASSERT (m_Observer->notifiedZoom ());
523     CPPUNIT_ASSERT_DOUBLES_EQUAL (1.2f, m_Observer->getZoom (), DELTA);
524     m_Document->zoomIn ();
525     m_Document->zoomIn ();
526     CPPUNIT_ASSERT_DOUBLES_EQUAL (1.728f, m_Document->getZoom (), DELTA);
527     CPPUNIT_ASSERT (m_Observer->notifiedZoom ());
528     CPPUNIT_ASSERT_DOUBLES_EQUAL (1.728f, m_Observer->getZoom (), DELTA);
529
530     // On this document we'll use the zoom to fit and zoom to width.
531     // This document is A4 in size (595 x 842).
532     g_free (testFile);
533     testFile = getTestFile ("test1.pdf");
534     m_Document->load (testFile, NULL);
535     while ( !m_Observer->loadFinished () ) { }
536     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
537     CPPUNIT_ASSERT (m_Document->isLoaded ());
538     CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0f, m_Document->getZoom (), DELTA);
539     m_Document->zoomToWidth (200);   
540     CPPUNIT_ASSERT_DOUBLES_EQUAL (0.3361f, m_Document->getZoom (), DELTA);
541     CPPUNIT_ASSERT (m_Observer->notifiedZoom ());
542     CPPUNIT_ASSERT_DOUBLES_EQUAL (0.3361f, m_Observer->getZoom (), DELTA);
543     m_Document->zoomToFit (100, 50);   
544     CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0593f, m_Document->getZoom (), DELTA);
545     CPPUNIT_ASSERT (m_Observer->notifiedZoom ());
546     CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0593f, m_Observer->getZoom (), DELTA);
547     m_Document->zoomToFit (50, 100);   
548     CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0840f, m_Document->getZoom (), DELTA);
549     CPPUNIT_ASSERT (m_Observer->notifiedZoom ());
550     CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0840f, m_Observer->getZoom (), DELTA);
551
552     g_free (testFile);
553 }
554
555 ///
556 /// @brief Test rendering a page.
557 ///
558 /// Rendering a page just means get the pixels of the page's image. Initially
559 /// I though to use a GdkPixbuf, but since I don't want to have Gtk+-2 as
560 /// a core dependence (I think it will be possible to make a Qt shell or
561 /// whatever on the future), so rendering a page gives a DocumentPage object.
562 ///
563 /// I can only test the height, width and row stride (bytes between rows)
564 /// of the DocumentPage class, as I don't know of a way to test if an image
565 /// is rendered correctly pixel by pixel. I will just test that the image is
566 /// not filled with 0x00 (initial state...)
567 ///
568 void
569 PDFDocumentTest::pageRender ()
570 {
571     gchar *testFile = getTestFile ("test2.pdf");
572     m_Document->load (testFile, NULL);
573     while ( !m_Observer->loadFinished () ) { }
574     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
575     CPPUNIT_ASSERT (m_Document->isLoaded ());
576     // Since the document is 595x842 but rotated 90 degrees,
577     // and I request a zoom to width (300) the page will have a zoom of
578     // 0.3562, which means that the final image will be 300x212 pixels.
579     // As *every* page uses 3 bytes (RGB) x 8 bits per pixel,
580     // the image is 190800 bytes long.
581     m_Document->rotateRight ();
582     CPPUNIT_ASSERT_EQUAL (90, m_Document->getRotation ());
583     m_Document->zoomToWidth (300);
584     CPPUNIT_ASSERT_DOUBLES_EQUAL (0.3562f, m_Document->getZoom (), DELTA);
585     DocumentPage *page = NULL;
586     while ( NULL == page || (DocumentPage *)0xdeadbeef == page )
587     {
588         page = m_Document->getCurrentPage ();
589     }
590     CPPUNIT_ASSERT (NULL != page);
591     CPPUNIT_ASSERT ((DocumentPage *)0xdeadbeef != page);
592     CPPUNIT_ASSERT_EQUAL (300, page->getWidth ());
593     CPPUNIT_ASSERT_EQUAL (212, page->getHeight ());
594     // The row stride is the bytes between rows in the page's pixels.
595     // 300 (Width) * 3 (RGB) in this case.
596     CPPUNIT_ASSERT_EQUAL (900, page->getRowStride ());
597     // Test only if the data is not 0x00.
598     gint imageSize = page->getRowStride () * page->getHeight ();
599     guchar *testData = new guchar[imageSize];
600     memset (testData, 0, imageSize);
601     CPPUNIT_ASSERT (0 != memcmp (testData, page->getData (), imageSize));
602     delete[] testData;
603
604     g_free (testFile);
605 }
606
607 ///
608 /// @brief Tests the document's link.
609 ///
610 /// If a page has a links, we should be able to ask the document if the
611 /// mouse pointer is over any link (to be able to change the cursor) and to
612 /// tell the document to change the current page for the page a links points
613 /// to.
614 ///
615 /// All this should happen even if the page is resized but will keep things
616 /// simple for now and only for unrotated documents.
617 ///
618 void
619 PDFDocumentTest::pageLinks ()
620 {
621     gchar *testFile = getTestFile ("test1.pdf");
622     m_Document->load (testFile, NULL);
623     g_free (testFile);
624     while ( !m_Observer->loadFinished () ) { }
625     CPPUNIT_ASSERT (m_Observer->notifiedLoaded ());
626     CPPUNIT_ASSERT (m_Document->isLoaded ());
627
628     // In this test PDF document there are two links on page 4.
629     // Both links points to page 5 and are situated at:
630     // ((72.00, 147.11), (134.50, 137.11))
631     // ((96.00, 158.11), (145.17, 148.11))
632     //
633     // First try with an unscaled document.
634     m_Document->goToPage (4);
635     DocumentPage *page = NULL;
636     while ( NULL == page || (DocumentPage *)0xdeadbeef == page )
637     {
638         page = m_Document->getCurrentPage ();
639     }
640     CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (70, 140));
641     CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (76, 40));
642     CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (136, 139));
643     CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (130, 160));
644     CPPUNIT_ASSERT (m_Document->hasLinkAtPosition (76, 139));
645     CPPUNIT_ASSERT (m_Document->hasLinkAtPosition (100, 150));
646     CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (90, 151));
647     CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (100, 130));
648     CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (110, 160));
649     CPPUNIT_ASSERT (!m_Document->hasLinkAtPosition (150, 152));
650
651     // Active a link and let see how the page is changed.
652     m_Document->activateLinkAtPosition (76, 139);
653     CPPUNIT_ASSERT_EQUAL (5, m_Document->getCurrentPageNum ());
654
655     // Now try the same but with an scaled page. (x1.2)
656     // With this scale the links are now at:
657     // ((86.40, 176.53), (160.80, 164.53))
658     // ((115.2, 189.73), (174.20, 177.73))
659     //
660     m_Document->zoomIn ();
661     m_Document->goToPage (4);
662     page = NULL;
663     while ( NULL == page || (DocumentPage *)0xdeadbeef == page )
664     {
665         page = m_Document->getCurrentPage ();
666     }
667     // Just check the first link and activate the second.
668     CPPUNIT_ASSERT (m_Document->hasLinkAtPosition (87, 175));
669     m_Document->activateLinkAtPosition (174, 177);
670     CPPUNIT_ASSERT_EQUAL (5, m_Document->getCurrentPageNum ());
671 }
672
673 ///
674 /// @brief Tests finding text in a page.
675 ///
676 void
677 PDFDocumentTest::pageFindText ()
678 {
679     gchar *testFile = getTestFile ("test1.pdf");
680     m_Document->load (testFile, NULL);
681     g_free (testFile);
682     while ( !m_Observer->loadFinished () ) { }
683
684     // If a text doesn't exist on a page the list of found text is
685     // empty.
686     CPPUNIT_ASSERT (NULL == m_Document->findTextInPage (4, "nothing"));
687     // On the other hand, if something is found the list is filled with
688     // the rectangles the text is found.
689     GList *results = m_Document->findTextInPage (4, "first");
690     CPPUNIT_ASSERT (NULL != results);
691     // In this case it should have found 2 results.
692     CPPUNIT_ASSERT_EQUAL ((guint)2, g_list_length (results));
693
694     GList *firstResult = g_list_first (results);
695     {
696         DocumentRectangle *rect = (DocumentRectangle *)firstResult->data;
697         CPPUNIT_ASSERT_DOUBLES_EQUAL (82.00, rect->getX1 (), 0.0001);
698         CPPUNIT_ASSERT_DOUBLES_EQUAL (137.11, rect->getY1 (), 0.0001);
699         CPPUNIT_ASSERT_DOUBLES_EQUAL (100.34, rect->getX2 (), 0.0001);
700         CPPUNIT_ASSERT_DOUBLES_EQUAL (146.11, rect->getY2 (), 0.0001);
701     }
702     GList *secondResult = g_list_next (firstResult);
703     {
704         DocumentRectangle *rect = (DocumentRectangle *)secondResult->data;
705         CPPUNIT_ASSERT_DOUBLES_EQUAL (96.00, rect->getX1 (), 0.0001);
706         CPPUNIT_ASSERT_DOUBLES_EQUAL (148.11, rect->getY1 (), 0.0001);
707         CPPUNIT_ASSERT_DOUBLES_EQUAL (114.34, rect->getX2 (), 0.0001);
708         CPPUNIT_ASSERT_DOUBLES_EQUAL (157.11, rect->getY2 (), 0.0001);
709     }
710     g_list_free (results);
711 }
Note: See TracBrowser for help on using the browser.