Changeset 78

Show
Ignore:
Timestamp:
04/17/06 07:28:50 (2 years ago)
Author:
jordi
Message:

Since version 0.5.0 and up doesn't support the old Xpdf header files and because the CairoOutputDev?.h file is not installed on version 0.5.1, I now use Poppler's glib wrapper for PDF loading.

The glib wrapper needs an URI instead of a filename (why?), so the path to the file must be specified as an absolute path to be able to convert it to an URI (file:///dir1/dir2/file.pdf). This also means that the tests files had to be changed to use absolute paths. I added a function (that I'll change to a common utils source) that transform the filename to an absolute path.

Location:
trunk
Files:
9 modified

Legend:

Unmodified
Added
Removed
  • trunk/configure.ac

    r54 r78  
    11dnl Process this file with autoconf to produce a configure script. 
    2 AC_INIT([ePDFView], [0.1.1], [jordi@emma-soft.com]) 
     2AC_INIT([ePDFView], [0.1.2], [jordi@emma-soft.com]) 
    33AC_PREREQ([2.13]) 
    44AC_CONFIG_HEADER([config.h]) 
     
    3030GLIB_REQUIRED=2.6.0 
    3131GTK2_REQUIRED=2.6.0 
    32 FREETYPE2_REQUIRED=2.1.9 
    3332 
    3433PKG_CHECK_MODULES([GLIB], [glib-2.0 >= $GLIB_REQUIRED]) 
     
    3837AC_SUBST([GTK2_CFLAGS]) 
    3938AC_SUBST([GTK2_LIBS]) 
    40 PKG_CHECK_MODULES([POPPLER], [poppler-cairo >= $POPPLER_REQUIRED freetype2 >= $FREETYPE2_REQUIRED]) 
     39PKG_CHECK_MODULES([POPPLER], [poppler-glib >= $POPPLER_REQUIRED gdk-2.0 >= $GTK2_REQUIRED pango]) 
    4140AC_SUBST([POPPLER_CFLAGS]) 
    4241AC_SUBST([POPPLER_LIBS]) 
  • trunk/src/IDocument.cxx

    r73 r78  
    131131    m_Format = NULL; 
    132132    m_Keywords = NULL; 
    133     m_Linearized = FALSE; 
     133    m_Linearized = NULL; 
    134134    m_ModifiedDate = NULL; 
    135135    m_PageLayout = PageLayoutUnset; 
     
    156156    g_free (m_Format); 
    157157    g_free (m_Keywords); 
     158    g_free (m_Linearized); 
    158159    g_free (m_ModifiedDate); 
    159160    g_free (m_Password); 
     
    182183/// @brief Sets the document's title. 
    183184/// 
    184 /// @param title The title of the document. 
    185 /// 
    186 void 
    187 IDocument::setTitle (const gchar *title) 
     185/// @param title The title of the document. IDocument will free it. 
     186/// 
     187void 
     188IDocument::setTitle (gchar *title) 
    188189{ 
    189190    g_free (m_Title); 
    190     m_Title = g_strdup (title); 
     191    m_Title = title; 
    191192} 
    192193 
     
    210211/// @brief Sets the document's author. 
    211212/// 
    212 /// @param author The name of the document's author. 
    213 /// 
    214 void 
    215 IDocument::setAuthor (const gchar *author) 
     213/// @param author The name of the document's author. IDocument will free it. 
     214/// 
     215void 
     216IDocument::setAuthor (gchar *author) 
    216217{ 
    217218    g_free (m_Author); 
    218     m_Author = g_strdup (author); 
     219    m_Author = author; 
    219220} 
    220221 
     
    238239/// @brief Sets the document's subject. 
    239240/// 
    240 /// @param subject The subject of the document. 
    241 /// 
    242 void 
    243 IDocument::setSubject (const gchar *subject) 
     241/// @param subject The subject of the document. IDocument will free it. 
     242/// 
     243void 
     244IDocument::setSubject (gchar *subject) 
    244245{ 
    245246    g_free (m_Subject); 
    246     m_Subject = g_strdup (subject); 
     247    m_Subject = subject; 
    247248} 
    248249 
     
    266267/// @brief Sets the document's keywords. 
    267268/// 
    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/// 
     272void 
     273IDocument::setKeywords (gchar *keywords) 
    272274{ 
    273275    g_free (m_Keywords); 
    274     m_Keywords = g_strdup (keywords); 
     276    m_Keywords = keywords; 
    275277} 
    276278 
     
    295297/// 
    296298/// @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/// 
     301void 
     302IDocument::setCreator (gchar *creator) 
    300303{ 
    301304    g_free (m_Creator); 
    302     m_Creator = g_strdup (creator); 
     305    m_Creator = creator; 
    303306} 
    304307/// 
     
    322325/// 
    323326/// @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/// 
     329void 
     330IDocument::setProducer (gchar *producer) 
    327331{ 
    328332    g_free (m_Producer); 
    329     m_Producer = g_strdup (producer); 
     333    m_Producer = producer; 
    330334} 
    331335 
     
    350354/// @brief Sets the document's format. 
    351355/// 
    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/// 
     359void 
     360IDocument::setFormat (gchar *format) 
    356361{ 
    357362    g_free (m_Format); 
    358     m_Format = g_strdup (format); 
     363    m_Format = format; 
    359364} 
    360365 
     
    369374IDocument::getLinearized () 
    370375{ 
    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; 
    376381} 
    377382 
     
    379384/// @brief Sets if the document is linearised. 
    380385/// 
    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/// 
     389void 
     390IDocument::setLinearized (gchar *linearized) 
     391{ 
     392    g_free (m_Linearized); 
    387393    m_Linearized = linearized; 
    388394} 
     
    408414/// 
    409415/// @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 (const gchar *date) 
     416///             'Y-M-D H:M:s'. IDocument will free it. 
     417/// 
     418void 
     419IDocument::setCreationDate (gchar *date) 
    414420{ 
    415421    g_free (m_CreationDate); 
    416     m_CreationDate = g_strdup (date); 
     422    m_CreationDate = date; 
    417423} 
    418424 
     
    437443/// 
    438444/// @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 (const gchar *date) 
     445///             'Y-M-D H:M:s'. IDocument will free it. 
     446/// 
     447void 
     448IDocument::setModifiedDate (gchar *date) 
    443449{ 
    444450    g_free (m_ModifiedDate); 
    445     m_ModifiedDate = g_strdup (date); 
    446      
     451    m_ModifiedDate = date; 
    447452} 
    448453 
  • trunk/src/IDocument.h

    r65 r78  
    171171             
    172172            const gchar *getTitle (void); 
    173             void setTitle (const gchar *title); 
     173            void setTitle (gchar *title); 
    174174            const gchar *getAuthor (void); 
    175             void setAuthor (const gchar *author); 
     175            void setAuthor (gchar *author); 
    176176            const gchar *getSubject (void); 
    177             void setSubject (const gchar *subject); 
     177            void setSubject (gchar *subject); 
    178178            const gchar *getKeywords (void); 
    179             void setKeywords (const gchar *keywords); 
     179            void setKeywords (gchar *keywords); 
    180180            const gchar *getCreator (void); 
    181             void setCreator (const gchar *creator); 
     181            void setCreator (gchar *creator); 
    182182            const gchar *getPassword (void); 
    183183            void setPassword (const gchar *password); 
    184184            const gchar *getProducer (void); 
    185             void setProducer (const gchar *producer); 
     185            void setProducer (gchar *producer); 
    186186            const gchar *getFileName (void); 
    187187            void setFileName (const gchar *fileName); 
    188188            const gchar *getFormat (void); 
    189             void setFormat (const gchar *format); 
     189            void setFormat (gchar *format); 
    190190            const gchar *getLinearized (void); 
    191             void setLinearized (gboolean linearized); 
     191            void setLinearized (gchar *linearized); 
    192192            const gchar *getCreationDate (void); 
    193             void setCreationDate (const gchar *date); 
     193            void setCreationDate (gchar *date); 
    194194            const gchar *getModifiedDate (void); 
    195             void setModifiedDate (const gchar *date); 
     195            void setModifiedDate (gchar *date); 
    196196            PageMode getPageMode (void); 
    197197            void setPageMode (PageMode mode); 
     
    239239            gchar *m_FileName; 
    240240            gchar *m_Keywords; 
    241             gboolean m_Linearized; 
     241            gchar *m_Linearized; 
    242242            gchar *m_ModifiedDate; 
    243243            PageLayout m_PageLayout; 
  • trunk/src/PDFDocument.cxx

    r73 r78  
    1717 
    1818#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> 
    3021#include "epdfview.h" 
    3122 
     
    3324 
    3425// Constants. 
    35 static const gint CAIRO_BYTES_PER_PIXEL = 4; 
     26static const gint PIXBUF_BITS_PER_SAMPLE = 8; 
     27static const gint DATE_LENGTH = 100; 
    3628 
    3729// 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); 
     30static PageLayout convertPageLayout (gint pageLayout); 
     31static PageMode convertPageMode (gint pageMode); 
    4332 
    4433/// 
     
    4938{ 
    5039    m_Document = NULL; 
    51     m_OutputDevice = NULL; 
    5240} 
    5341 
     
    5745PDFDocument::~PDFDocument () 
    5846{ 
    59     delete m_Document; 
    60     delete m_OutputDevice; 
     47    if ( NULL != m_Document ) 
     48    { 
     49        g_object_unref (G_OBJECT (m_Document)); 
     50    } 
    6151} 
    6252 
     
    6959PDFDocument::isLoaded () 
    7060{ 
    71     return (NULL != m_Document && m_Document->isOk ()); 
     61    return (NULL != m_Document); 
    7262} 
    7363 
     
    7767/// Tries to open the PDF file @a filename using the password in @a password. 
    7868/// 
    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. 
    8071/// @param password The password to use to open @a filename. 
    8172/// @param error Location to store the error occurring or NULL to ignore  
     
    9081    g_assert (NULL != filename && "Tried to load a NULL file name"); 
    9182 
    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; 
    10487    } 
    10588    // 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); 
    11193    // 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. 
    116116        gchar *errorMessage = IDocument::getErrorMessage (errorCode); 
    117117        g_set_error (error,  
     
    124124    } 
    125125    
    126     setFileName (filename); 
     126    // Set the used filename and password to let the user reload the 
     127    // document. 
     128    setFileName (filename);     
    127129    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    } 
    129135    m_Document = newDocument; 
    130136    // Load the document's information and outline. 
    131137    loadMetadata (); 
    132     Outline *outline = m_Document->getOutline (); 
     138    PopplerIndexIter *outline = poppler_index_iter_new (m_Document); 
    133139    m_Outline = new DocumentOutline (); 
    134     setOutline (m_Outline, outline->getItems ()); 
     140    setOutline (m_Outline, outline); 
    135141    // Set the current rotation angle and zoom level. 
    136142    setRotation (0); 
    137143    setZoom (1.0f); 
    138     // Set the output device. 
    139     delete m_OutputDevice; 
    140     m_OutputDevice = new CairoOutputDev (); 
    141     m_OutputDevice->startDoc (m_Document->getXRef ()); 
    142144 
    143145    return TRUE; 
     
    158160    g_assert (NULL != m_Document && "The document has not been loaded."); 
    159161 
    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)); 
    209228 
    210229    // 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)); 
    212231    goToFirstPage (); 
    213232} 
     
    222241///                call must be set to the root DocumentOutline. 
    223242/// @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(). 
    226245/// 
    227246void 
    228 PDFDocument::setOutline (DocumentOutline *outline, GooList *childrenList) 
     247PDFDocument::setOutline (DocumentOutline *outline,  
     248                         PopplerIndexIter *childrenList) 
    229249{ 
    230250    if ( NULL != childrenList ) 
    231251    { 
    232         int numChildren = childrenList->getLength (); 
    233         for ( int childIndex = 0 ; childIndex < numChildren ; childIndex++ ) 
     252        do 
    234253        { 
    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 ) 
    250257            { 
    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); 
     266