- Timestamp:
- 04/17/06 07:28:50 (3 years ago)
- Location:
- trunk
- Files:
-
- 9 modified
-
configure.ac (modified) (3 diffs)
-
src/IDocument.cxx (modified) (13 diffs)
-
src/IDocument.h (modified) (2 diffs)
-
src/PDFDocument.cxx (modified) (14 diffs)
-
src/PDFDocument.h (modified) (2 diffs)
-
tests/DocumentOutlineTest.cxx (modified) (5 diffs)
-
tests/Makefile.am (modified) (1 diff)
-
tests/PDFDocumentTest.cxx (modified) (22 diffs)
-
tests/main.cxx (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/configure.ac
r54 r78 1 1 dnl Process this file with autoconf to produce a configure script. 2 AC_INIT([ePDFView], [0.1. 1], [jordi@emma-soft.com])2 AC_INIT([ePDFView], [0.1.2], [jordi@emma-soft.com]) 3 3 AC_PREREQ([2.13]) 4 4 AC_CONFIG_HEADER([config.h]) … … 30 30 GLIB_REQUIRED=2.6.0 31 31 GTK2_REQUIRED=2.6.0 32 FREETYPE2_REQUIRED=2.1.933 32 34 33 PKG_CHECK_MODULES([GLIB], [glib-2.0 >= $GLIB_REQUIRED]) … … 38 37 AC_SUBST([GTK2_CFLAGS]) 39 38 AC_SUBST([GTK2_LIBS]) 40 PKG_CHECK_MODULES([POPPLER], [poppler- cairo >= $POPPLER_REQUIRED freetype2 >= $FREETYPE2_REQUIRED])39 PKG_CHECK_MODULES([POPPLER], [poppler-glib >= $POPPLER_REQUIRED gdk-2.0 >= $GTK2_REQUIRED pango]) 41 40 AC_SUBST([POPPLER_CFLAGS]) 42 41 AC_SUBST([POPPLER_LIBS]) -
trunk/src/IDocument.cxx
r73 r78 131 131 m_Format = NULL; 132 132 m_Keywords = NULL; 133 m_Linearized = FALSE;133 m_Linearized = NULL; 134 134 m_ModifiedDate = NULL; 135 135 m_PageLayout = PageLayoutUnset; … … 156 156 g_free (m_Format); 157 157 g_free (m_Keywords); 158 g_free (m_Linearized); 158 159 g_free (m_ModifiedDate); 159 160 g_free (m_Password); … … 182 183 /// @brief Sets the document's title. 183 184 /// 184 /// @param title The title of the document. 185 /// 186 void 187 IDocument::setTitle ( constgchar *title)185 /// @param title The title of the document. IDocument will free it. 186 /// 187 void 188 IDocument::setTitle (gchar *title) 188 189 { 189 190 g_free (m_Title); 190 m_Title = g_strdup (title);191 m_Title = title; 191 192 } 192 193 … … 210 211 /// @brief Sets the document's author. 211 212 /// 212 /// @param author The name of the document's author. 213 /// 214 void 215 IDocument::setAuthor ( constgchar *author)213 /// @param author The name of the document's author. IDocument will free it. 214 /// 215 void 216 IDocument::setAuthor (gchar *author) 216 217 { 217 218 g_free (m_Author); 218 m_Author = g_strdup (author);219 m_Author = author; 219 220 } 220 221 … … 238 239 /// @brief Sets the document's subject. 239 240 /// 240 /// @param subject The subject of the document. 241 /// 242 void 243 IDocument::setSubject ( constgchar *subject)241 /// @param subject The subject of the document. IDocument will free it. 242 /// 243 void 244 IDocument::setSubject (gchar *subject) 244 245 { 245 246 g_free (m_Subject); 246 m_Subject = g_strdup (subject);247 m_Subject = subject; 247 248 } 248 249 … … 266 267 /// @brief Sets the document's keywords. 267 268 /// 268 /// @param keywords A white space separated list of keywords. 269 /// 270 void 271 IDocument::setKeywords (const gchar *keywords) 269 /// @param keywords A white space separated list of keywords. IDocument will 270 /// free it. 271 /// 272 void 273 IDocument::setKeywords (gchar *keywords) 272 274 { 273 275 g_free (m_Keywords); 274 m_Keywords = g_strdup (keywords);276 m_Keywords = keywords; 275 277 } 276 278 … … 295 297 /// 296 298 /// @param creator The name of the software that created the document. 297 /// 298 void 299 IDocument::setCreator (const gchar *creator) 299 /// IDocument will free it. 300 /// 301 void 302 IDocument::setCreator (gchar *creator) 300 303 { 301 304 g_free (m_Creator); 302 m_Creator = g_strdup (creator);305 m_Creator = creator; 303 306 } 304 307 /// … … 322 325 /// 323 326 /// @param producer The name of the software that converted the document. 324 /// 325 void 326 IDocument::setProducer (const gchar *producer) 327 /// IDocument will free it. 328 /// 329 void 330 IDocument::setProducer (gchar *producer) 327 331 { 328 332 g_free (m_Producer); 329 m_Producer = g_strdup (producer);333 m_Producer = producer; 330 334 } 331 335 … … 350 354 /// @brief Sets the document's format. 351 355 /// 352 /// @param format Set the format in which the document is. 353 /// 354 void 355 IDocument::setFormat (const gchar *format) 356 /// @param format Set the format in which the document is. IDocument will free 357 /// it. 358 /// 359 void 360 IDocument::setFormat (gchar *format) 356 361 { 357 362 g_free (m_Format); 358 m_Format = g_strdup (format);363 m_Format = format; 359 364 } 360 365 … … 369 374 IDocument::getLinearized () 370 375 { 371 if ( m_Linearized )372 { 373 return " Yes";374 } 375 return "No";376 if ( NULL == m_Linearized ) 377 { 378 return "No"; 379 } 380 return m_Linearized; 376 381 } 377 382 … … 379 384 /// @brief Sets if the document is linearised. 380 385 /// 381 /// @param linearized Set to TRUE if the document is linearized. 382 /// FALSE otherwise. 383 /// 384 void 385 IDocument::setLinearized (gboolean linearized) 386 { 386 /// @param linearized Set to "Yes" if the document is linearized. "No" 387 /// otherwise. IDocument will free it. 388 /// 389 void 390 IDocument::setLinearized (gchar *linearized) 391 { 392 g_free (m_Linearized); 387 393 m_Linearized = linearized; 388 394 } … … 408 414 /// 409 415 /// @param date The date and time the document was created in format 410 /// 'Y-M-D H:M:s'. 411 /// 412 void 413 IDocument::setCreationDate ( constgchar *date)416 /// 'Y-M-D H:M:s'. IDocument will free it. 417 /// 418 void 419 IDocument::setCreationDate (gchar *date) 414 420 { 415 421 g_free (m_CreationDate); 416 m_CreationDate = g_strdup (date);422 m_CreationDate = date; 417 423 } 418 424 … … 437 443 /// 438 444 /// @param date The date and time the document was modified in format 439 /// 'Y-M-D H:M:s'. 440 /// 441 void 442 IDocument::setModifiedDate ( constgchar *date)445 /// 'Y-M-D H:M:s'. IDocument will free it. 446 /// 447 void 448 IDocument::setModifiedDate (gchar *date) 443 449 { 444 450 g_free (m_ModifiedDate); 445 m_ModifiedDate = g_strdup (date); 446 451 m_ModifiedDate = date; 447 452 } 448 453 -
trunk/src/IDocument.h
r65 r78 171 171 172 172 const gchar *getTitle (void); 173 void setTitle ( constgchar *title);173 void setTitle (gchar *title); 174 174 const gchar *getAuthor (void); 175 void setAuthor ( constgchar *author);175 void setAuthor (gchar *author); 176 176 const gchar *getSubject (void); 177 void setSubject ( constgchar *subject);177 void setSubject (gchar *subject); 178 178 const gchar *getKeywords (void); 179 void setKeywords ( constgchar *keywords);179 void setKeywords (gchar *keywords); 180 180 const gchar *getCreator (void); 181 void setCreator ( constgchar *creator);181 void setCreator (gchar *creator); 182 182 const gchar *getPassword (void); 183 183 void setPassword (const gchar *password); 184 184 const gchar *getProducer (void); 185 void setProducer ( constgchar *producer);185 void setProducer (gchar *producer); 186 186 const gchar *getFileName (void); 187 187 void setFileName (const gchar *fileName); 188 188 const gchar *getFormat (void); 189 void setFormat ( constgchar *format);189 void setFormat (gchar *format); 190 190 const gchar *getLinearized (void); 191 void setLinearized (g booleanlinearized);191 void setLinearized (gchar *linearized); 192 192 const gchar *getCreationDate (void); 193 void setCreationDate ( constgchar *date);193 void setCreationDate (gchar *date); 194 194 const gchar *getModifiedDate (void); 195 void setModifiedDate ( constgchar *date);195 void setModifiedDate (gchar *date); 196 196 PageMode getPageMode (void); 197 197 void setPageMode (PageMode mode); … … 239 239 gchar *m_FileName; 240 240 gchar *m_Keywords; 241 g booleanm_Linearized;241 gchar *m_Linearized; 242 242 gchar *m_ModifiedDate; 243 243 PageLayout m_PageLayout; -
trunk/src/PDFDocument.cxx
r73 r78 17 17 18 18 #include <config.h> 19 20 // Poppler headers. 21 #include <goo/GooList.h> 22 #include <PDFDoc.h> 23 #include <CairoOutputDev.h> 24 #include <ErrorCodes.h> 25 #include <GlobalParams.h> 26 #include <PDFDocEncoding.h> 27 #include <Outline.h> 28 #include <Link.h> 29 19 #include <time.h> 20 #include <glib/poppler.h> 30 21 #include "epdfview.h" 31 22 … … 33 24 34 25 // Constants. 35 static const gint CAIRO_BYTES_PER_PIXEL = 4; 26 static const gint PIXBUF_BITS_PER_SAMPLE = 8; 27 static const gint DATE_LENGTH = 100; 36 28 37 29 // Forward declarations. 38 static gchar *getDictionaryString (Object &object, const gchar *key); 39 static gchar *getDictionaryDate (Object &object, const gchar *key); 40 static gboolean hasUnicodeMarker (GooString *string); 41 static PageLayout convertPageLayout (Catalog::PageLayout pageLayout); 42 static PageMode convertPageMode (Catalog::PageMode pageMode); 30 static PageLayout convertPageLayout (gint pageLayout); 31 static PageMode convertPageMode (gint pageMode); 43 32 44 33 /// … … 49 38 { 50 39 m_Document = NULL; 51 m_OutputDevice = NULL;52 40 } 53 41 … … 57 45 PDFDocument::~PDFDocument () 58 46 { 59 delete m_Document; 60 delete m_OutputDevice; 47 if ( NULL != m_Document ) 48 { 49 g_object_unref (G_OBJECT (m_Document)); 50 } 61 51 } 62 52 … … 69 59 PDFDocument::isLoaded () 70 60 { 71 return (NULL != m_Document && m_Document->isOk ());61 return (NULL != m_Document); 72 62 } 73 63 … … 77 67 /// Tries to open the PDF file @a filename using the password in @a password. 78 68 /// 79 /// @param filename The name of the file name to open. 69 /// @param filename The name of the file name to open. It must be an absolute 70 /// path. 80 71 /// @param password The password to use to open @a filename. 81 72 /// @param error Location to store the error occurring or NULL to ignore … … 90 81 g_assert (NULL != filename && "Tried to load a NULL file name"); 91 82 92 // The Poppler library has a GLOBAL file for parameters. 93 // If this file isn't loaded then weird error happens. 94 if ( NULL == globalParams ) 95 { 96 globalParams = new GlobalParams ("/etc/xpdfrc"); 97 } 98 99 GooString *filename_g = new GooString (filename); 100 GooString *password_g = NULL; 101 if (NULL != password ) 102 { 103 password_g = new GooString (password); 83 gchar *filename_uri = g_filename_to_uri (filename, NULL, error); 84 if ( NULL == filename_uri ) 85 { 86 return FALSE; 104 87 } 105 88 // Try to open the PDF document. 106 PDFDoc *newDocument = new PDFDoc (filename_g, password_g, password_g); 107 delete password_g; 108 // The filename_g can't be deleted as PDFDoc saves the reference. 109 // deleting it will cause trouble when deleting the newDocument. 110 89 GError *loadError = NULL; 90 PopplerDocument *newDocument = 91 poppler_document_new_from_file (filename_uri, password, &loadError); 92 g_free (filename_uri); 111 93 // Check if the document couldn't be opened successfully and why. 112 if ( !newDocument->isOk() ) 113 { 114 DocumentError errorCode = (DocumentError)newDocument->getErrorCode (); 115 delete newDocument; 94 if ( NULL == newDocument ) 95 { 96 // Popller's glib wrapper passes the Poppler error code unless the 97 // error is that the file is encrypted. We want to set our own 98 // error code in this case. 99 DocumentError errorCode = DocumentErrorNone; 100 if ( POPPLER_ERROR == loadError->domain ) 101 { 102 errorCode = DocumentErrorEncrypted; 103 } 104 else 105 { 106 // OK, the glib's wrapper don't pass the error code directly 107 // from Poppler. Instead returns G_FILE_ERROR_FAILED and a 108 // non translated string. 109 // Maybe I'm wrong (very probable) but that's a wrong way. 110 // So I'm reading the error code from the error string... 111 sscanf (loadError->message, "Failed to load document (error %d)", 112 (gint *)&errorCode); 113 } 114 g_error_free (loadError); 115 // Get our error message. 116 116 gchar *errorMessage = IDocument::getErrorMessage (errorCode); 117 117 g_set_error (error, … … 124 124 } 125 125 126 setFileName (filename); 126 // Set the used filename and password to let the user reload the 127 // document. 128 setFileName (filename); 127 129 setPassword (password); 128 delete m_Document; 130 if ( NULL != m_Document ) 131 { 132 g_object_unref (G_OBJECT (m_Document)); 133 m_Document = NULL; 134 } 129 135 m_Document = newDocument; 130 136 // Load the document's information and outline. 131 137 loadMetadata (); 132 Outline *outline = m_Document->getOutline ();138 PopplerIndexIter *outline = poppler_index_iter_new (m_Document); 133 139 m_Outline = new DocumentOutline (); 134 setOutline (m_Outline, outline ->getItems ());140 setOutline (m_Outline, outline); 135 141 // Set the current rotation angle and zoom level. 136 142 setRotation (0); 137 143 setZoom (1.0f); 138 // Set the output device.139 delete m_OutputDevice;140 m_OutputDevice = new CairoOutputDev ();141 m_OutputDevice->startDoc (m_Document->getXRef ());142 144 143 145 return TRUE; … … 158 160 g_assert (NULL != m_Document && "The document has not been loaded."); 159 161 160 // Retrieve the document's meta data dictionary. 161 Object dictionary; 162 m_Document->getDocInfo (&dictionary); 163 164 gchar *value = NULL; 165 // Author 166 value = getDictionaryString (dictionary, "Author"); 167 setAuthor (value); 168 g_free (value); 169 // Creation date. 170 value = getDictionaryDate (dictionary, "CreationDate"); 171 setCreationDate (value); 172 g_free (value); 173 // Creator 174 value = getDictionaryString (dictionary, "Creator"); 175 setCreator (value); 176 g_free (value); 177 // PDF Format 178 value = g_strdup_printf ("PDF-%.2g", m_Document->getPDFVersion ()); 179 setFormat (value); 180 g_free (value); 181 // Keywords 182 value = getDictionaryString (dictionary, "Keywords"); 183 setKeywords (value); 184 g_free (value); 185 // Is linearised 186 setLinearized (m_Document->isLinearized ()); 187 // Modified date 188 value = getDictionaryDate (dictionary, "ModDate"); 189 setModifiedDate (value); 190 g_free (value); 191 // Producer 192 value = getDictionaryString (dictionary, "Producer"); 193 setProducer (value); 194 g_free (value); 195 // Subject 196 value = getDictionaryString (dictionary, "Subject"); 197 setSubject (value); 198 g_free (value); 199 // Title 200 value = getDictionaryString (dictionary, "Title"); 201 setTitle (value); 202 g_free (value); 203 204 // For the page mode and layout we need the catalog, not the 205 // dictionary. 206 Catalog *catalog = m_Document->getCatalog (); 207 setPageLayout (convertPageLayout (catalog->getPageLayout ())); 208 setPageMode (convertPageMode (catalog->getPageMode ())); 162 163 gchar *author = NULL; 164 GTime creationDate; 165 gchar *creator = NULL; 166 gchar *format = NULL; 167 gchar *keywords = NULL; 168 PopplerPageLayout layout = POPPLER_PAGE_LAYOUT_UNSET; 169 gchar *linearized = NULL; 170 GTime modDate; 171 PopplerPageMode mode = POPPLER_PAGE_MODE_UNSET; 172 gchar *producer = NULL; 173 gchar *subject = NULL; 174 gchar *title = NULL; 175 176 g_object_get (m_Document, 177 "author", &author, 178 "creation-date", &creationDate, 179 "creator", &creator, 180 "format", &format, 181 "keywords", &keywords, 182 "page-layout", &layout, 183 "linearized", &linearized, 184 "mod-date", &modDate, 185 "page-mode", &mode, 186 "producer", &producer, 187 "subject", &subject, 188 "title", &title, 189 NULL); 190 setAuthor (author); 191 if ( 0 < creationDate ) 192 { 193 struct tm *tmpTime = localtime ((const time_t *)&creationDate); 194 gchar *date = g_strnfill (DATE_LENGTH + 1, 0); 195 strftime (date, DATE_LENGTH, "%Y-%m-%d %H:%M:%S", tmpTime); 196 setCreationDate (date); 197 } 198 else 199 { 200 setCreationDate (NULL); 201 } 202 setCreator (creator); 203 setFormat (format); 204 setKeywords (keywords); 205 setLinearized (linearized); 206 if ( 0 < modDate ) 207 { 208 struct tm *tmpTime = localtime ((const time_t *)&modDate); 209 gchar *date = g_strnfill (DATE_LENGTH + 1, 0); 210 strftime (date, DATE_LENGTH, "%Y-%m-%d %H:%M:%S", tmpTime); 211 setModifiedDate (date); 212 } 213 else 214 { 215 setModifiedDate (NULL); 216 } 217 setProducer (producer); 218 setSubject (subject); 219 setTitle (title); 220 221 // For the page mode and layout we need the enumerator value 222 GEnumValue *pageLayout = g_enum_get_value ( 223 (GEnumClass *)g_type_class_peek (POPPLER_TYPE_PAGE_LAYOUT), layout); 224 setPageLayout (convertPageLayout (pageLayout->value)); 225 GEnumValue *pageMode = g_enum_get_value ( 226 (GEnumClass *)g_type_class_peek (POPPLER_TYPE_PAGE_MODE), mode); 227 setPageMode (convertPageMode (pageMode->value)); 209 228 210 229 // Get the number of pages and set the current to the first. 211 setNumPages ( m_Document->getNumPages ());230 setNumPages (poppler_document_get_n_pages (m_Document)); 212 231 goToFirstPage (); 213 232 } … … 222 241 /// call must be set to the root DocumentOutline. 223 242 /// @param childrenList The list of children for to set to @a outline. 224 /// The first line must be a call to the getItems()225 /// function from the PDF's outline.243 /// The first line must be the returned valued of 244 /// poppler_index_iter_new(). 226 245 /// 227 246 void 228 PDFDocument::setOutline (DocumentOutline *outline, GooList *childrenList) 247 PDFDocument::setOutline (DocumentOutline *outline, 248 PopplerIndexIter *childrenList) 229 249 { 230 250 if ( NULL != childrenList ) 231 251 { 232 int numChildren = childrenList->getLength (); 233 for ( int childIndex = 0 ; childIndex < numChildren ; childIndex++ ) 252 do 234 253 { 235 OutlineItem *item = (OutlineItem *)childrenList->get (childIndex); 236 // Get the title, create the new child outline and set the 237 // title to it. 238 gchar *title = g_ucs4_to_utf8 (item->getTitle (), 239 item->getTitleLength (), 240 NULL, NULL, NULL); 241 DocumentOutline *child = new DocumentOutline (); 242 child->setParent (outline); 243 child->setTitle (title); 244 g_free (title); 245 /// Get the page destination. 246 gint destination = 1; 247 LinkAction *action = item->getAction (); 248 if ( NULL != action && actionGoTo == action->getKind () && 249 action->isOk () ) 254 PopplerAction *action = 255 poppler_index_iter_get_action (childrenList); 256 if ( POPPLER_ACTION_GOTO_DEST == action->type ) 250 257 { 251 LinkDest *linkDestination = NULL; 252 GooString *namedDest = ((LinkGoTo *)action)->getNamedDest (); 253 // getNamedDest() or getDest() will return NULL, just need to 254 // find which one. 255 if ( NULL != namedDest ) 256 { 257 linkDestination = m_Document->findDest (namedDest); 258 } 259 else 260 { 261 linkDestination = ((LinkGoTo *)action)->getDest (); 262 } 263 if ( NULL != linkDestination && linkDestination->isOk () ) 264 { 265 if ( linkDestination->isPageRef () ) 266 { 267 Ref pageReference = linkDestination->getPageRef (); 268 destination = m_Document->findPage (pageReference.num, 269 pageReference.gen); 270 } 271 else 272 { 273 destination = linkDestination->getPageNum (); 274 } 275 } // if ( linkDestination->isOk () ) 276 } // if ( NULL != action ... ) 277 child->setDestination (destination); 278 outline->addChild (child); 279 // Add the child's children, if any. 280 if ( item->hasKids () ) 281 { 282 // I need to open the outline because if it's not 283 // open then the getKids() function would return NULL. 284 item->open (); 285 setOutline (child, item->getKids ()); 258 PopplerActionGotoDest *actionGoTo = 259 (PopplerActionGotoDest *)action; 260 DocumentOutline *child = new DocumentOutline (); 261 child->setParent (outline); 262 child->setTitle (actionGoTo->title); 263 PopplerDest *destination = actionGoTo->dest; 264 child->setDestination (destination->page_num); 265 outline->addChild (child);
