source: trunk/Lucide/SOURCE/plugins/lupoppler/lupoppler.cpp @ 183

Last change on this file since 183 was 183, checked in by Eugene Romanenko, 15 years ago

Odd/Even? printing for 'As Image' printing, pdf plugin: fix document title

File size: 47.2 KB
Line 
1
2/*
3 *  This file was generated by the SOM Compiler.
4 *  Generated using:
5 *     SOM incremental update: 2.24
6 */
7
8
9/*
10 * Copyright (c) 2006, Eugene Romanenko, netlabs.org
11 *
12 *----------------------------------------------------------------------
13 * This file is part of poppler plugin for Lucide (lupoppler).
14 *
15 *  lupoppler is free software; you can redistribute it and/or modify
16 *  it under the terms of the GNU General Public License as published by
17 *  the Free Software Foundation; either version 2 of the License, or
18 *  (at your option) any later version.
19 *
20 *  lupoppler is distributed in the hope that it will be useful,
21 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 *  GNU General Public License for more details.
24 *----------------------------------------------------------------------
25 */
26
27/*
28 *  This file was generated by the SOM Compiler and Emitter Framework.
29 *  Generated using template emitter:
30 *      SOM Emitter emitxtm: 2.23.1.9
31 */
32
33#ifndef SOM_Module_lupoppler_Source
34#define SOM_Module_lupoppler_Source
35#endif
36#define LuPopplerDocument_Class_Source
37
38#include "lupoppler.xih"
39
40#include <goo\GooString.h>
41#include <goo\GooList.h>
42#include <splash\SplashBitmap.h>
43#include <UGooString.h>
44#include <GlobalParams.h>
45#include <ErrorCodes.h>
46#include <PDFDoc.h>
47#include <SplashOutputDev.h>
48#include <TextOutputDev.h>
49#include <PSOutputDev.h>
50#include <FontInfo.h>
51#include <Outline.h>
52#include <UnicodeMap.h>
53#include <Gfx.h>
54#include <Link.h>
55
56#define INCL_DOS
57#include <os2.h>
58
59#include <vector>
60using namespace std;
61#include <time.h>
62#include <uconv.h>
63#include "cpconv.h"
64
65typedef vector<LuRectangle> RectList;
66
67
68unsigned _System LibMain( unsigned hmod, unsigned termination )
69{
70    if ( termination ) {
71        /* DLL is detaching from process */
72    } else {
73        /* DLL is attaching to process */
74    }
75    return( 1 );
76}
77
78
79extern "C" LuDocument * _System createObject()
80{
81    return new LuPopplerDocument;
82}
83
84extern "C" char * _System getSupportedExtensions()
85{
86    return "PDF";
87}
88
89extern "C" char * _System getDescription()
90{
91    return "PDF plugin, based on poppler library v0.5.4";
92}
93
94
95class PopplerPage
96{
97    public:
98
99        Page *page;
100        TextOutputDev *text_dev;
101        Gfx *gfx;
102
103        PopplerPage();
104        ~PopplerPage();
105};
106
107PopplerPage::PopplerPage()
108{
109    page = NULL;
110    text_dev = NULL;
111    gfx = NULL;
112}
113
114PopplerPage::~PopplerPage()
115{
116    delete text_dev;
117    delete gfx;
118}
119
120
121class PopplerDocument
122{
123    public:
124
125        PDFDoc *doc;
126        SplashOutputDev *output_dev;
127        PopplerPage *pages;
128        char *text;
129        HMTX mutex;
130
131        void *objUtf8;
132        void *objUniBe;
133        void *objSys;
134
135        PopplerDocument();
136        ~PopplerDocument();
137};
138
139PopplerDocument::PopplerDocument()
140{
141    doc        = NULL;
142    output_dev = NULL;
143    pages      = NULL;
144    text       = NULL;
145    mutex      = NULLHANDLE;
146    DosCreateMutexSem( NULL, &mutex, 0, FALSE );
147
148    uconv_attribute_t attr;
149    UniCreateUconvObject( (UniChar *)L"UTF-8", &objUtf8 );
150    UniQueryUconvObject( objUtf8, &attr, sizeof(attr), NULL, NULL, NULL );
151    attr.converttype &= ~(CVTTYPE_CTRL7F | CVTTYPE_PATH);
152    UniSetUconvObject( objUtf8, &attr );
153
154    UniCreateUconvObject( (UniChar *)L"UCS-2@endian=big", &objUniBe );
155    UniQueryUconvObject( objUniBe, &attr, sizeof(attr), NULL, NULL, NULL );
156    attr.converttype &= ~(CVTTYPE_CTRL7F | CVTTYPE_PATH);
157    UniSetUconvObject( objUniBe, &attr );
158
159    UniCreateUconvObject( (UniChar *)L"", &objSys );
160    UniQueryUconvObject( objSys, &attr, sizeof(attr), NULL, NULL, NULL );
161    attr.converttype &= ~(CVTTYPE_CTRL7F | CVTTYPE_PATH);
162    attr.options = UCONV_OPTION_SUBSTITUTE_BOTH;
163    UniSetUconvObject( objSys, &attr );
164}
165
166PopplerDocument::~PopplerDocument()
167{
168    delete [] pages;
169    delete doc;
170    delete output_dev;
171    delete text;
172    DosCloseMutexSem( mutex );
173
174    UniFreeUconvObject( objUtf8 );
175    UniFreeUconvObject( objUniBe );
176    UniFreeUconvObject( objSys );
177}
178
179
180static char *newstrdup( const char *s )
181{
182    if ( s == NULL ) {
183        return NULL;
184    }
185    char *temp = new char[ strlen( s ) + 1 ];
186    strcpy( temp, s );
187    return temp;
188}
189
190static char *somstrdup( const char *s )
191{
192    if ( s == NULL ) {
193        return NULL;
194    }
195    char *temp = (char *)SOMMalloc( strlen( s ) + 1 );
196    strcpy( temp, s );
197    return temp;
198}
199
200
201SOM_Scope short  SOMLINK getBpp(LuPopplerDocument *somSelf,  Environment *ev)
202{
203    return 3;
204}
205
206SOM_Scope boolean  SOMLINK isScalable(LuPopplerDocument *somSelf,
207                                       Environment *ev)
208{
209    return TRUE;
210}
211
212
213SOM_Scope boolean  SOMLINK isRotable(LuPopplerDocument *somSelf,
214                                      Environment *ev)
215{
216    return TRUE;
217}
218
219
220SOM_Scope long  SOMLINK getPageCount(LuPopplerDocument *somSelf,
221                                      Environment *ev)
222{
223    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
224    return ((PopplerDocument *)somThis->data)->doc->getNumPages();
225}
226
227
228SOM_Scope void  SOMLINK getPageSize(LuPopplerDocument *somSelf,
229                                    Environment *ev, long pagenum,
230                                    double* width, double* height)
231{
232    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
233
234    Page *page = ((PopplerDocument *)somThis->data)->pages[ pagenum ].page;
235
236    double page_width, page_height;
237    int rotate = page->getRotate();
238    if ( rotate == 90 || rotate == 270 ) {
239        page_height = page->getCropWidth();
240        page_width = page->getCropHeight();
241    } else {
242        page_width = page->getCropWidth();
243        page_height = page->getCropHeight();
244    }
245
246    if ( width != NULL ) {
247        *width = page_width;
248    }
249    if ( height != NULL ) {
250        *height = page_height;
251    }
252}
253
254
255static void copy_page_to_pixbuf( Environment *ev, SplashBitmap *bitmap, LuPixbuf *pixbuf )
256{
257    int splash_width, splash_height, splash_rowstride;
258    int pixbuf_rowstride, pixbuf_height, pixbuf_width;
259    int height, width, rowstride;
260    char *pixbuf_data, *dst, *src;
261
262    SplashColorPtr color_ptr = bitmap->getDataPtr();
263
264    splash_width = bitmap->getWidth();
265    splash_height = bitmap->getHeight();
266    splash_rowstride = bitmap->getRowSize();
267
268    //somPrintf( "splash_width: %d   splash_height: %d   splash_rowstride: %d\n",
269    //            splash_width, splash_height, splash_rowstride );
270
271    pixbuf_data = (char *)pixbuf->getDataPtr( ev );
272    pixbuf_width = pixbuf->getWidth( ev );
273    pixbuf_height = pixbuf->getHeight( ev );
274    pixbuf_rowstride = pixbuf->getRowSize( ev );
275
276    width = __min( splash_width, pixbuf_width );
277    height = __min( splash_height, pixbuf_height );
278    rowstride = __min( splash_rowstride, pixbuf_rowstride );
279
280    int i, j;
281    for ( i = 0, j = ( height - 1 ); i < height; i++, j-- )
282    {
283        dst = pixbuf_data + i * pixbuf_rowstride;
284        src = ((char *)color_ptr) + j * splash_rowstride;
285        memcpy( dst, src, rowstride );
286    }
287
288    // test
289    //memcpy( pixbuf_data, color_ptr, pixbuf->getDataLen( ev ) );
290}
291
292
293SOM_Scope boolean  SOMLINK renderPageToPixbuf(LuPopplerDocument *somSelf,
294                                               Environment *ev,
295                                              long pagenum, long src_x,
296                                              long src_y, long src_width,
297                                              long src_height,
298                                              double scale, long rotation,
299                                              LuPixbuf* pixbuf,
300                                              long* errorCode,
301                                              string* error)
302{
303    if ( errorCode != NULL ) {
304        *errorCode = LU_RERR_NO_ERROR;
305    }
306
307    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
308    PopplerDocument *document = (PopplerDocument *)somThis->data;
309    Page *page = document->pages[ pagenum ].page;
310
311    if ( ( scale < 0.0 ) || ( pixbuf == NULL ) ) {
312        return FALSE;
313    }
314
315    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
316
317    page->displaySlice( document->output_dev,
318                72.0 * scale, 72.0 * scale,
319                rotation,
320                gFalse, /* useMediaBox */
321                gTrue, /* Crop */
322                src_x, src_y,
323                src_width, src_height,
324                NULL, /* links */
325                document->doc->getCatalog() );
326
327    DosReleaseMutexSem( document->mutex );
328
329    copy_page_to_pixbuf( ev, document->output_dev->getBitmap(), pixbuf );
330
331    return TRUE;
332}
333
334
335SOM_Scope boolean  SOMLINK isAsynchRenderingSupported(LuPopplerDocument *somSelf,
336                                                       Environment *ev)
337{
338    return TRUE;
339}
340
341
342struct asynchCallbackData
343{
344    Environment      *ev;
345    LuPixbuf         *pixbuf;
346    SplashOutputDev  *out;
347    void             *fndata;
348    _asynchCallbackFn fnd;
349    _asynchCallbackFn fna;
350    long              tmr;
351    bool              forceDraw;
352    long              delay;
353};
354
355static GBool abortCheckCbk( void *data )
356{
357    long now;
358    asynchCallbackData *cd = (asynchCallbackData *)data;
359    DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &now, sizeof( long ) );
360    long dist = ( now - cd->tmr );
361    if ( ( dist > cd->delay ) || cd->forceDraw )
362    {
363        // Note: we use out->getBitmap() on each iteration instead
364        //       of remembering pointer to bitmap before call
365        //       page->displaySlice() because OutputDev may change
366        //       bitmap during page->displaySlice() processing.
367        copy_page_to_pixbuf( cd->ev, cd->out->getBitmap(), cd->pixbuf );
368        cd->fnd( cd->fndata );
369        cd->tmr = now;
370        cd->delay += 100;
371    }
372    return (GBool)cd->fna( cd->fndata );
373}
374
375
376SOM_Scope void  SOMLINK renderPageToPixbufAsynch(LuPopplerDocument *somSelf,
377                                                  Environment *ev,
378                                                 long pagenum,
379                                                 long src_x,
380                                                 long src_y,
381                                                 long src_width,
382                                                 long src_height,
383                                                 double scale,
384                                                 long rotation,
385                                                 LuPixbuf* pixbuf,
386                                                 LuDocument_asynchCallbackFn fnd,
387                                                 LuDocument_asynchCallbackFn fna,
388                                                 somToken fndata,
389                                                 long* errorCode,
390                                                 string* error)
391{
392    if ( errorCode != NULL ) {
393        *errorCode = LU_RERR_NO_ERROR;
394    }
395
396    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
397    PopplerDocument *document = (PopplerDocument *)somThis->data;
398    Page *page = document->pages[ pagenum ].page;
399
400    if ( ( scale < 0.0 ) || ( pixbuf == NULL ) ) {
401        return;
402    }
403
404    asynchCallbackData acd;
405    acd.ev        = ev;
406    acd.pixbuf    = pixbuf;
407    acd.out       = document->output_dev;
408    acd.fndata    = fndata;
409    acd.fnd       = (_asynchCallbackFn)fnd;
410    acd.fna       = (_asynchCallbackFn)fna;
411    acd.forceDraw = false;
412    acd.delay     = 200;
413    DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &acd.tmr, sizeof( long ) );
414
415    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
416
417    //somPrintf( "src_x: %d, src_y: %d, src_width: %d, src_height: %d\n",
418    //           src_x, src_y, src_width, src_height );
419
420    page->displaySlice( document->output_dev,
421                72.0 * scale, 72.0 * scale,
422                rotation,
423                gFalse, /* useMediaBox */
424                gTrue, /* Crop */
425                src_x, src_y,
426                src_width, src_height,
427                NULL, /* links */
428                document->doc->getCatalog(),
429                abortCheckCbk, &acd );
430    DosReleaseMutexSem( document->mutex );
431
432    acd.forceDraw = true;
433    abortCheckCbk( &acd );
434}
435
436static TextOutputDev *get_text_output_dev( PopplerPage *page,
437                                           PopplerDocument *document )
438{
439    if ( page->text_dev == NULL )
440    {
441        DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
442        page->text_dev = new TextOutputDev( NULL, gTrue, gFalse, gFalse );
443
444        page->gfx = page->page->createGfx(page->text_dev,
445                          72.0, 72.0, 0,
446                          gFalse, /* useMediaBox */
447                          gTrue, /* Crop */
448                          -1, -1, -1, -1,
449                          NULL, /* links */
450                          document->doc->getCatalog(),
451                          NULL, NULL, NULL, NULL);
452
453        page->page->display( page->gfx );
454        page->text_dev->endPage();
455        DosReleaseMutexSem( document->mutex );
456    }
457
458    return page->text_dev;
459}
460
461
462SOM_Scope LuDocument_LuRectSequence*  SOMLINK getSelectionRectangles(LuPopplerDocument *somSelf,
463                                                                    Environment *ev,
464                                                                   long pagenum,
465                                                                   LuRectangle* selection)
466{
467    LuDocument_LuRectSequence *rectangles = NULL;
468
469    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
470    PopplerDocument *document = (PopplerDocument *)somThis->data;
471    PopplerPage *page = &( document->pages[ pagenum ] );
472
473    TextOutputDev *text_dev = get_text_output_dev( page, document );
474
475    PDFRectangle poppler_selection;
476    poppler_selection.x1 = selection->x1;
477    poppler_selection.y1 = selection->y1;
478    poppler_selection.x2 = selection->x2;
479    poppler_selection.y2 = selection->y2;
480
481    GooList *list = text_dev->getSelectionRegion( &poppler_selection, 1.0 );
482    int len = list->getLength();
483
484    if ( len > 0 )
485    {
486        rectangles = (LuDocument_LuRectSequence *)SOMMalloc( sizeof( LuDocument_LuRectSequence ) );
487        rectangles->_maximum = len;
488        rectangles->_length = len;
489        rectangles->_buffer = (LuRectangle *)SOMMalloc( sizeof( LuRectangle ) * len );
490
491        for ( int i = 0; i < len; i++ )
492        {
493            PDFRectangle *selection_rect = (PDFRectangle *)list->get( i );
494            rectangles->_buffer[ i ].x1 = selection_rect->x1;
495            rectangles->_buffer[ i ].y1 = selection_rect->y1;
496            rectangles->_buffer[ i ].x2 = selection_rect->x2;
497            rectangles->_buffer[ i ].y2 = selection_rect->y2;
498            delete selection_rect;
499        }
500    }
501    delete list;
502
503    return rectangles;
504}
505
506
507SOM_Scope boolean  SOMLINK isHaveText(LuPopplerDocument *somSelf,
508                                      Environment *ev)
509{
510    return TRUE;
511}
512
513
514SOM_Scope string  SOMLINK getText(LuPopplerDocument *somSelf,
515                                   Environment *ev, long pagenum,
516                                  LuRectangle* selection)
517{
518    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
519
520    if ( selection == NULL ) {
521        return NULL;
522    }
523
524    PopplerDocument *document = (PopplerDocument *)somThis->data;
525    PopplerPage *page = &( document->pages[ pagenum ] );
526
527    TextOutputDev *text_dev = get_text_output_dev( page, document );
528
529    GooString *sel_text = new GooString;
530    char *result;
531    PDFRectangle pdf_selection;
532
533    pdf_selection.x1 = selection->x1;
534    pdf_selection.y1 = selection->y1;
535    pdf_selection.x2 = selection->x2;
536    pdf_selection.y2 = selection->y2;
537
538    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
539    sel_text = text_dev->getSelectionText( &pdf_selection );
540
541    delete document->text;
542    document->text = newstrdup( sel_text->getCString() );
543    delete sel_text;
544    DosReleaseMutexSem( document->mutex );
545
546    return document->text;
547}
548
549
550SOM_Scope boolean  SOMLINK isHaveLinks(LuPopplerDocument *somSelf,
551                                        Environment *ev)
552{
553    return TRUE;
554}
555
556
557static long find_dest_page( PDFDoc *doc, LinkDest *link_dest )
558{
559    long page_num = 0;
560
561    if ( link_dest == NULL ) {
562        return page_num;
563    }
564
565    if ( link_dest->isPageRef() )
566    {
567        Ref page_ref = link_dest->getPageRef();
568        page_num = doc->findPage( page_ref.num, page_ref.gen ) - 1;
569    }
570    else {
571        page_num = link_dest->getPageNum() - 1;
572    }
573
574    return page_num;
575}
576
577static void build_goto_dest( PDFDoc *doc, LuLink *evlink, LinkGoTo *link )
578{
579    LinkDest *link_dest;
580    UGooString *named_dest;
581
582    if ( !link->isOk() ) {
583        return;
584    }
585
586    link_dest = link->getDest();
587    named_dest = link->getNamedDest();
588
589    if ( link_dest != NULL ) {
590        evlink->page = find_dest_page( doc, link_dest );
591    } else if ( named_dest != NULL ) {
592        link_dest = doc->findDest( named_dest );
593        evlink->page = find_dest_page( doc, link_dest );
594        delete link_dest;
595    } else {
596        evlink->page = 0;
597    }
598}
599
600static void build_link( PDFDoc *doc, LuLink *evlink,
601                        const char *title, LinkAction *link_action )
602{
603    evlink->title = somstrdup( title );
604    evlink->uri = NULL;
605    evlink->type = LU_LINK_TYPE_TITLE;
606    evlink->page = 0;
607
608    if ( link_action == NULL ) {
609        return;
610    }
611
612    switch ( link_action->getKind() )
613    {
614        case actionGoTo:
615            {
616                evlink->type = LU_LINK_TYPE_PAGE;
617                LinkGoTo *lgt = dynamic_cast <LinkGoTo *> (link_action);
618                build_goto_dest( doc, evlink, lgt );
619            }
620            break;
621
622        case actionURI:
623            {
624                evlink->type = LU_LINK_TYPE_EXTERNAL_URI;
625                LinkURI *lu = dynamic_cast <LinkURI *> (link_action);
626                char *uri = lu->getURI()->getCString();
627                if ( uri != NULL ) {
628                    evlink->uri = somstrdup( uri );
629                }
630            }
631            break;
632    }
633}
634
635SOM_Scope LuDocument_LuLinkMapSequence*  SOMLINK getLinkMapping(LuPopplerDocument *somSelf,
636                                                                 Environment *ev,
637                                                                long pagenum)
638{
639    LuDocument_LuLinkMapSequence *mapping = NULL;
640    mapping = (LuDocument_LuLinkMapSequence *)SOMMalloc( sizeof( LuDocument_LuLinkMapSequence ) );
641    mapping->_maximum = 0;
642    mapping->_length = 0;
643    mapping->_buffer = NULL;
644
645    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
646    PopplerDocument *document = (PopplerDocument *)somThis->data;
647    PopplerPage *page = &( document->pages[ pagenum ] );
648
649    Object obj;
650    Links *links = new Links( page->page->getAnnots( &obj ),
651                            document->doc->getCatalog()->getBaseURI() );
652    obj.free();
653
654    if ( links == NULL ) {  // No links, return empty LuLinkMapSequence
655        return mapping;
656    }
657
658    double height = 0;
659    getPageSize( somSelf, ev, pagenum, NULL, &height );
660
661    int len = links->getNumLinks();
662
663    mapping->_maximum = len;
664    mapping->_length = len;
665    if ( len != 0 ) {
666        mapping->_buffer = (LuLinkMapping *)SOMMalloc( sizeof( LuLinkMapping ) * len );
667    }
668
669    for ( int i = 0; i < len; i++ )
670    {
671        Link *link = links->getLink( i );
672        LinkAction *link_action = link->getAction();
673        build_link( document->doc, &(mapping->_buffer[ i ].link), NULL, link_action );
674
675        link->getRect( &(mapping->_buffer[ i ].area.x1),
676                       &(mapping->_buffer[ i ].area.y1),
677                       &(mapping->_buffer[ i ].area.x2),
678                       &(mapping->_buffer[ i ].area.y2) );
679
680        mapping->_buffer[ i ].area.x1 -= page->page->getCropBox()->x1;
681        mapping->_buffer[ i ].area.x2 -= page->page->getCropBox()->x1;
682        mapping->_buffer[ i ].area.y1 -= page->page->getCropBox()->y1;
683        mapping->_buffer[ i ].area.y2 -= page->page->getCropBox()->y1;
684
685        double y1 = mapping->_buffer[ i ].area.y1;
686        double y2 = mapping->_buffer[ i ].area.y2;
687        mapping->_buffer[ i ].area.y1 = height - y2;
688        mapping->_buffer[ i ].area.y2 = height - y1;
689    }
690
691    return mapping;
692}
693
694
695SOM_Scope boolean  SOMLINK isSaveable(LuPopplerDocument *somSelf,
696                                       Environment *ev)
697{
698    return TRUE;
699}
700
701
702SOM_Scope boolean  SOMLINK saveAs(LuPopplerDocument *somSelf,
703                                   Environment *ev, string filename)
704{
705    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
706    PopplerDocument *document = (PopplerDocument *)somThis->data;
707
708    boolean retval = FALSE;
709
710    if ( filename != NULL ) {
711        retval = document->doc->saveAs( new GooString( filename ) );
712    }
713
714    return retval;
715}
716
717
718SOM_Scope boolean  SOMLINK isPostScriptExportable(LuPopplerDocument *somSelf,
719                                           Environment *ev)
720{
721    return TRUE;
722}
723
724
725SOM_Scope boolean SOMLINK exportToPostScript(LuPopplerDocument *somSelf,
726                                    Environment *ev, string filename,
727                                    long first_page, long last_page,
728                                    double width, double height,
729                                    boolean* brkExport)
730{
731    if ( filename == NULL ) {
732        return FALSE;
733    }
734
735    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
736    PDFDoc *doc = ((PopplerDocument *)somThis->data)->doc;
737
738    PSOutputDev *out = new PSOutputDev( filename, doc->getXRef(), doc->getCatalog(),
739                                (first_page <= last_page) ? (first_page + 1) : (last_page + 1),
740                                (first_page <= last_page) ? (last_page + 1) : (first_page + 1),
741                                        psModePS, (int)width, (int)height,
742                                        gFalse, 0, 0, 0, 0, gFalse );
743
744    if ( !out->isOk() ) {
745        delete out;
746        return FALSE;
747    }
748
749    if ( *brkExport ) {
750        delete out;
751        return TRUE;
752    }
753
754    long pagestoprint = abs( last_page - first_page ) + 1;
755    long pg = first_page;
756    for ( long i = 0; (i < pagestoprint) && !(*brkExport); i++ ) {
757        doc->displayPage( out, pg + 1, 72.0, 72.0, 0, gFalse, gTrue, gFalse );
758        pg += ( first_page <= last_page ) ? 1 : -1;
759    }
760
761    delete out;
762    return TRUE;
763}
764
765
766SOM_Scope boolean  SOMLINK isHaveFontInfo(LuPopplerDocument *somSelf,
767                                           Environment *ev)
768{
769    return TRUE;
770}
771
772
773SOM_Scope LuDocument_LuFontInfoSequence*  SOMLINK getFontInfo(LuPopplerDocument *somSelf,
774                                                               Environment *ev)
775{
776    LuDocument_LuFontInfoSequence *fonts = NULL;
777
778    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
779    PopplerDocument *document = (PopplerDocument *)somThis->data;
780    PDFDoc *doc = document->doc;
781
782    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
783    FontInfoScanner *scanner = new FontInfoScanner( doc );
784    GooList *items = scanner->scan( doc->getNumPages() );
785    delete scanner;
786    DosReleaseMutexSem( document->mutex );
787
788    if ( items == NULL ) {
789        return NULL;
790    }
791
792    int len = items->getLength();
793
794    if ( len == 0 ) {
795        delete items;
796        return NULL;
797    }
798
799    fonts = (LuDocument_LuFontInfoSequence *)SOMMalloc( sizeof( LuDocument_LuFontInfoSequence ) );
800    fonts->_maximum = len;
801    fonts->_length = len;
802    fonts->_buffer = (LuFontInfo *)SOMMalloc( sizeof( LuFontInfo ) * len );
803
804    for ( int i = 0; i < len; i++ )
805    {
806        fonts->_buffer[i].name = NULL;
807        fonts->_buffer[i].type = NULL;
808        fonts->_buffer[i].embedded = NULL;
809
810        FontInfo *info = (FontInfo *)items->get( i );
811
812        // name
813        GooString *gnm = info->getName();
814        if ( gnm != NULL )
815        {
816            char *nm = gnm->getCString();
817            if ( info->getSubset() && ( nm != NULL ) )
818            {
819                while ( *nm && ( *nm != '+' ) ) {
820                    nm++;
821                }
822                if ( *nm ) {
823                    nm++;
824                }
825            }
826            if ( nm != NULL ) {
827                if ( *nm ) {
828                    fonts->_buffer[i].name = somstrdup( nm );
829                }
830            }
831        }
832
833        // type
834        char *t = "Unknown font type";
835        switch ( info->getType() )
836        {
837            case FontInfo::Type1:        t = "Type 1";          break;
838            case FontInfo::Type1C:       t = "Type 1C";         break;
839            case FontInfo::Type3:        t = "Type 3";          break;
840            case FontInfo::TrueType:     t = "TrueType";        break;
841            case FontInfo::CIDType0:     t = "Type 1 (CID)";    break;
842            case FontInfo::CIDType0C:    t = "Type 1C (CID)";   break;
843            case FontInfo::CIDTrueType:  t = "TrueType (CID)";  break;
844        }
845        fonts->_buffer[i].type = somstrdup( t );
846
847        // embedded
848        if ( info->getEmbedded() ) {
849            if ( info->getSubset() ) {
850                fonts->_buffer[i].embedded = LU_FONTEMBED_EMBEDDED_SUBSET;
851            } else {
852                fonts->_buffer[i].embedded = LU_FONTEMBED_EMBEDDED;
853            }
854        } else {
855            fonts->_buffer[i].embedded = LU_FONTEMBED_NOT_EMBEDDED;
856        }
857    }
858
859    return fonts;
860}
861
862
863SOM_Scope boolean  SOMLINK isHaveIndex(LuPopplerDocument *somSelf,
864                                        Environment *ev)
865{
866    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
867    PDFDoc *doc = ((PopplerDocument *)somThis->data)->doc;
868
869    Outline *outline = doc->getOutline();
870    if ( outline == NULL ) {
871        return FALSE;
872    }
873
874    GooList *items = outline->getItems();
875    if ( items == NULL ) {
876        return FALSE;
877    }
878
879    return TRUE;
880}
881
882static char *unicode_to_char( Unicode *unicode, int len )
883{
884    static UnicodeMap *uMap = NULL;
885    if ( uMap == NULL )
886    {
887        GooString *enc = new GooString( "UTF-8" );
888        uMap = globalParams->getUnicodeMap( enc );
889        uMap->incRefCnt();
890        delete enc;
891    }
892
893    GooString gstr;
894    char buf[8]; // 8 is enough for mapping an unicode char to a string
895    int i, n;
896
897    for ( i = 0; i < len; ++i ) {
898        n = uMap->mapUnicode( unicode[i], buf, sizeof( buf ) );
899        gstr.append( buf, n );
900    }
901
902    return newstrdup( gstr.getCString() );
903}
904
905static char *newstrFromUTF8( const char *s, void *objUtf8, void *objSys )
906{
907    size_t cSubs = 0;
908    size_t len = strlen( s ) + 1;
909    size_t unilen = len + 2;
910    UniChar *unibuf = new UniChar[ unilen ];
911    UniChar *tmpuni = unibuf;
912    UniUconvToUcs( objUtf8, (void **)&s, &len, &tmpuni, &unilen, &cSubs );
913    unilen = UniStrlen( unibuf );
914
915    int liglen = uniLigaturesLength( unibuf );
916    if ( liglen > 0 )  // string contain ligature(s)
917    {
918        unsigned ulen_tmp = ( unilen + liglen + 1 ) * sizeof( UniChar );
919        char *uni_tmp = new char[ ulen_tmp ];
920        uniReplaceLigatures( unibuf, (UniChar *)uni_tmp );
921        delete unibuf;
922        unibuf = (UniChar *)uni_tmp;
923        unilen = UniStrlen( unibuf );
924    }
925    uniConvertSpChars( unibuf );
926
927    size_t blen = ( unilen + 1 ) * 2;
928    char *b = new char[ blen ];
929    memset( b, 0, blen );
930    char *bsav = b;
931    tmpuni = unibuf;
932    cSubs = 0;
933    UniUconvFromUcs( objSys, &tmpuni, &unilen, (void **)&b, &blen, &cSubs );
934    delete unibuf;
935    return bsav;
936}
937
938static void add_item( Environment *ev, PDFDoc *doc, LuIndexNode *n, GooList *items,
939                      void *objUtf8, void *objSys )
940{
941    if ( items == NULL ) {
942        return;
943    }
944
945    int len = items->getLength();
946
947    for ( int i = 0; i < len; i++ )
948    {
949        OutlineItem *item = (OutlineItem *)items->get( i );
950        LinkAction *link_action = item->getAction();
951        LuLink evlink;
952        char *t1 = unicode_to_char( item->getTitle(), item->getTitleLength() );
953        char *t2 = newstrFromUTF8( t1, objUtf8, objSys );
954        build_link( doc, &evlink, t2, link_action );
955        delete t2;
956        delete t1;
957        LuIndexNode *cn = new LuIndexNode( ev, &evlink );
958        n->addChild( ev, cn );
959
960        item->open();
961        if ( item->hasKids() )
962        {
963            GooList *citems = item->getKids();
964            add_item( ev, doc, cn, citems, objUtf8, objSys );
965        }
966    }
967}
968
969SOM_Scope LuIndexNode*  SOMLINK getIndex(LuPopplerDocument *somSelf,
970                                          Environment *ev)
971{
972    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
973    PopplerDocument *document = (PopplerDocument *)somThis->data;
974    PDFDoc *doc = document->doc;
975
976    Outline *outline = doc->getOutline();
977    if ( outline == NULL ) {
978        return NULL;
979    }
980
981    GooList *items = outline->getItems();
982    if ( items == NULL ) {
983        return NULL;
984    }
985
986    LuIndexNode *root = new LuIndexNode( ev, NULL );
987    add_item( ev, doc, root, items, document->objUtf8, document->objSys );
988
989    return root;
990}
991
992
993static bool has_unicode_marker( GooString *string )
994{
995    return ( ( (string->getChar(0) & 0xff) == 0xfe ) &&
996             ( (string->getChar(1) & 0xff) == 0xff ) );
997}
998
999// return SOMMalloc'ed string
1000static char *propcnv( GooString *s, void *objUniBe, void *objSys )
1001{
1002    if ( has_unicode_marker( s ) )
1003    {
1004        size_t cSubs = 0;
1005        size_t unilen = s->getLength() + 1;
1006        UniChar *unibuf = new UniChar[ unilen ];
1007        memset( unibuf, 0, unilen * sizeof( UniChar ) );
1008        UniChar *tmpuni = unibuf;
1009        const char *from = s->getCString() + 2;
1010        size_t fromlen = s->getLength() - 2;
1011        UniUconvToUcs( objUniBe, (void **)&from, &fromlen, &tmpuni, &unilen, &cSubs );
1012        unilen = UniStrlen( unibuf );
1013
1014        int liglen = uniLigaturesLength( unibuf );
1015        if ( liglen > 0 )  // string contain ligature(s)
1016        {
1017            unsigned ulen_tmp = ( unilen + liglen + 1 ) * sizeof( UniChar );
1018            char *uni_tmp = new char[ ulen_tmp ];
1019            uniReplaceLigatures( unibuf, (UniChar *)uni_tmp );
1020            delete unibuf;
1021            unibuf = (UniChar *)uni_tmp;
1022            unilen = UniStrlen( unibuf );
1023        }
1024        uniConvertSpChars( unibuf );
1025
1026        size_t blen = ( unilen + 1 ) * 2;
1027        char *b = (char *)SOMMalloc( blen );
1028        memset( b, 0, blen );
1029        char *bsav = b;
1030        tmpuni = unibuf;
1031        cSubs = 0;
1032        UniUconvFromUcs( objSys, &tmpuni, &unilen, (void **)&b, &blen, &cSubs );
1033        delete unibuf;
1034        return bsav;
1035    }
1036
1037    return somstrdup( s->getCString() );
1038}
1039
1040static time_t propToDate( const char *date_string )
1041{
1042    int year, mon, day, hour, min, sec;
1043    int scanned_items;
1044
1045    // See PDF Reference 1.3, Section 3.8.2 for PDF Date representation
1046    if ( ( date_string[0] == 'D' ) && ( date_string[1] == ':' ) ) {
1047        date_string += 2;
1048    }
1049
1050    // FIXME only year is mandatory; parse optional timezone offset
1051    scanned_items = sscanf( date_string, "%4d%2d%2d%2d%2d%2d",
1052                            &year, &mon, &day, &hour, &min, &sec);
1053
1054    if ( scanned_items != 6 ) {
1055        return (time_t)(-1);
1056    }
1057
1058    // Workaround for y2k bug in Distiller 3, hoping that it won't
1059    // be used after y2.2k
1060    if ( ( year < 1930 ) && ( strlen( date_string ) > 14 ) )
1061    {
1062        int century, years_since_1900;
1063        scanned_items = sscanf( date_string, "%2d%3d%2d%2d%2d%2d%2d",
1064                &century, &years_since_1900, &mon, &day, &hour, &min, &sec );
1065
1066        if ( scanned_items != 7 ) {
1067            return (time_t)(-1);
1068        }
1069
1070        year = century * 100 + years_since_1900;
1071    }
1072
1073    struct tm time = { 0 };
1074    time.tm_year  = year - 1900;
1075    time.tm_mon   = mon - 1;
1076    time.tm_mday  = day;
1077    time.tm_hour  = hour;
1078    time.tm_min   = min;
1079    time.tm_sec   = sec;
1080    time.tm_wday  = -1;
1081    time.tm_yday  = -1;
1082    time.tm_isdst = -1; // 0 = DST off, 1 = DST on, -1 = don't know
1083
1084    return mktime( &time );
1085}
1086
1087static long convPageMode( Catalog::PageMode pageMode )
1088{
1089    switch ( pageMode )
1090    {
1091        case Catalog::pageModeThumbs:
1092            return LU_DOCUMENT_MODE_USE_THUMBS;
1093        case Catalog::pageModeFullScreen:
1094            return LU_DOCUMENT_MODE_FULL_SCREEN;
1095        case Catalog::pageModeOC:
1096            return LU_DOCUMENT_MODE_USE_OC;
1097        case Catalog::pageModeAttach:
1098            return LU_DOCUMENT_MODE_USE_ATTACHMENTS;
1099        case Catalog::pageModeNone:
1100            return LU_DOCUMENT_MODE_NONE;
1101    }
1102
1103    return -1;
1104}
1105
1106static long convLayout( Catalog::PageLayout pageLayout )
1107{
1108    switch ( pageLayout )
1109    {
1110        case Catalog::pageLayoutSinglePage:
1111            return LU_DOCUMENT_LAYOUT_SINGLE_PAGE;
1112        case Catalog::pageLayoutOneColumn:
1113            return LU_DOCUMENT_LAYOUT_ONE_COLUMN;
1114        case Catalog::pageLayoutTwoColumnLeft:
1115            return LU_DOCUMENT_LAYOUT_TWO_COLUMN_LEFT;
1116        case Catalog::pageLayoutTwoColumnRight:
1117            return LU_DOCUMENT_LAYOUT_TWO_COLUMN_RIGHT;
1118        case Catalog::pageLayoutTwoPageLeft:
1119            return LU_DOCUMENT_LAYOUT_TWO_PAGE_LEFT;
1120        case Catalog::pageLayoutTwoPageRight:
1121            return LU_DOCUMENT_LAYOUT_TWO_PAGE_RIGHT;
1122    }
1123    return -1;
1124}
1125
1126SOM_Scope LuDocumentInfo*  SOMLINK getDocumentInfo(LuPopplerDocument *somSelf,
1127                                                    Environment *ev)
1128{
1129    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1130    PopplerDocument *document = (PopplerDocument *)somThis->data;
1131    PDFDoc *doc = document->doc;
1132
1133    LuDocumentInfo *info = (LuDocumentInfo *)SOMMalloc( sizeof( LuDocumentInfo ) );
1134    memset( info, 0, sizeof( LuDocumentInfo ) );
1135
1136    Object objdict;
1137    doc->getDocInfo( &objdict );
1138    if ( objdict.isDict() )
1139    {
1140        Dict *d = objdict.getDict();
1141        Object obj;
1142
1143        if ( d->lookup( "Title", &obj )->isString() ) {
1144            info->title = propcnv( obj.getString(), document->objUniBe, document->objSys );
1145            info->fields_mask |= LU_DOCUMENT_INFO_TITLE;
1146        }
1147        obj.free();
1148        if ( d->lookup( "Author", &obj )->isString() ) {
1149            info->author = propcnv( obj.getString(), document->objUniBe, document->objSys );
1150            info->fields_mask |= LU_DOCUMENT_INFO_AUTHOR;
1151        }
1152        obj.free();
1153        if ( d->lookup( "Subject", &obj )->isString() ) {
1154            info->subject = propcnv( obj.getString(), document->objUniBe, document->objSys );
1155            info->fields_mask |= LU_DOCUMENT_INFO_SUBJECT;
1156        }
1157        obj.free();
1158        if ( d->lookup( "Keywords", &obj )->isString() ) {
1159            info->keywords = propcnv( obj.getString(), document->objUniBe, document->objSys );
1160            info->fields_mask |= LU_DOCUMENT_INFO_KEYWORDS;
1161        }
1162        obj.free();
1163        if ( d->lookup( "Creator", &obj )->isString() ) {
1164            info->creator = propcnv( obj.getString(), document->objUniBe, document->objSys );
1165            info->fields_mask |= LU_DOCUMENT_INFO_CREATOR;
1166        }
1167        obj.free();
1168        if ( d->lookup( "Producer", &obj )->isString() ) {
1169            info->producer = propcnv( obj.getString(), document->objUniBe, document->objSys );
1170            info->fields_mask |= LU_DOCUMENT_INFO_PRODUCER;
1171        }
1172        obj.free();
1173        if ( d->lookup( "CreationDate", &obj )->isString() ) {
1174            char *d = propcnv( obj.getString(), document->objUniBe, document->objSys );
1175            info->creation_date = propToDate( d );
1176            if ( (long)info->creation_date != -1 ) {
1177                info->fields_mask |= LU_DOCUMENT_INFO_CREATION_DATE;
1178            }
1179            SOMFree( d );
1180        }
1181        obj.free();
1182        if ( d->lookup( "ModDate", &obj )->isString() ) {
1183            char *d = propcnv( obj.getString(), document->objUniBe, document->objSys );
1184            info->modified_date = propToDate( d );
1185            if ( (long)info->modified_date != -1 ) {
1186                info->fields_mask |= LU_DOCUMENT_INFO_MOD_DATE;
1187            }
1188            SOMFree( d );
1189        }
1190        obj.free();
1191    }
1192
1193    char *format = (char *)SOMMalloc( 16 );
1194    snprintf( format, 16, "PDF-%.2f", doc->getPDFVersion() );
1195    info->format = format;
1196    info->fields_mask |= LU_DOCUMENT_INFO_FORMAT;
1197
1198    info->linearized = doc->isLinearized();
1199    info->fields_mask |= LU_DOCUMENT_INFO_LINEARIZED;
1200
1201    Catalog *catalog = doc->getCatalog();
1202
1203    if ( ( catalog != NULL ) && catalog->isOk() )
1204    {
1205        info->layout = convLayout( catalog->getPageLayout() );
1206        if ( info->layout != -1 ) {
1207            info->fields_mask |= LU_DOCUMENT_INFO_LAYOUT;
1208        }
1209
1210        info->mode = convPageMode( catalog->getPageMode() );
1211        if ( info->mode != -1 ) {
1212            info->fields_mask |= LU_DOCUMENT_INFO_START_MODE;
1213        }
1214    }
1215
1216    info->fields_mask |= LU_DOCUMENT_INFO_PERMISSIONS;
1217    if ( doc->okToPrint() ) {
1218        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_PRINT;
1219    }
1220    if ( doc->okToChange() ) {
1221        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_MODIFY;
1222    }
1223    if ( doc->okToCopy() ) {
1224        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_COPY;
1225    }
1226    if ( doc->okToAddNotes() ) {
1227        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES;
1228    }
1229
1230    info->n_pages = doc->getNumPages();
1231    info->fields_mask |= LU_DOCUMENT_INFO_N_PAGES;
1232
1233    return info;
1234}
1235
1236
1237SOM_Scope boolean  SOMLINK getThumbnailSize(LuPopplerDocument *somSelf,
1238                                             Environment *ev,
1239                                            long pagenum,
1240                                            short suggested_width,
1241                                            short* width, short* height)
1242{
1243    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1244    Page *page = ((PopplerDocument *)somThis->data)->pages[ pagenum ].page;
1245
1246    Object thumb;
1247    Dict *dict;
1248    boolean retval = FALSE;
1249
1250    page->getThumb( &thumb );
1251    if ( thumb.isNull() )
1252    {
1253        thumb.free();
1254        return FALSE;
1255    }
1256
1257    dict = thumb.streamGetDict();
1258
1259    // Theoretically, this could succeed and you would still fail when
1260    // loading the thumb
1261    int w = 0, h = 0;
1262    if ( dict->lookupInt( "Width", "W", &w ) && dict->lookupInt( "Height", "H", &h ) )
1263    {
1264        if ( width != NULL ) {
1265            *width = w;
1266        }
1267        if ( height != NULL ) {
1268            *height = h;
1269        }
1270
1271        retval = TRUE;
1272    }
1273
1274    thumb.free();
1275
1276    return retval;
1277}
1278
1279SOM_Scope LuPixbuf*  SOMLINK getThumbnail(LuPopplerDocument *somSelf,
1280                                           Environment *ev, long pagenum,
1281                                          short suggested_width)
1282{
1283    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1284    Page *page = ((PopplerDocument *)somThis->data)->pages[ pagenum ].page;
1285
1286    unsigned char *data;
1287    int width, height, rowstride;
1288
1289    if ( !page->loadThumb( &data, &width, &height, &rowstride ) ) {
1290        return NULL;
1291    }
1292
1293    short bpp = getBpp( somSelf, ev );
1294    LuPixbuf *pixbuf = new LuPixbuf( ev, width, height, bpp );
1295    char *pixbuf_data = (char *)pixbuf->getDataPtr( ev );
1296    int pixbuf_rowstride = pixbuf->getRowSize( ev );
1297    char *src, *dst;
1298    int i, j;
1299    for ( i = 0, j = ( height - 1 ); i < height; i++, j-- )
1300    {
1301        src = data + ( j * rowstride );
1302        dst = pixbuf_data + (i * pixbuf_rowstride);
1303        for ( int k = 0; k < pixbuf_rowstride; k += bpp )
1304        {
1305            dst[ k ]     = src[ k + 2 ];
1306            dst[ k + 1 ] = src[ k + 1 ];
1307            dst[ k + 2 ] = src[ k ];
1308        }
1309    }
1310    gfree( data );
1311
1312    return pixbuf;
1313}
1314
1315
1316SOM_Scope LuDocument_LuRectSequence*  SOMLINK searchText(LuPopplerDocument *somSelf,
1317                                                          Environment *ev,
1318                                                         long pagenum,
1319                                                         string text,
1320                                                         boolean caseSensitive)
1321{
1322    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1323    PopplerDocument *document = (PopplerDocument *)somThis->data;
1324    Page *page = document->pages[ pagenum ].page;
1325
1326    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
1327    TextOutputDev *output_dev = new TextOutputDev( NULL, gTrue, gFalse, gFalse );
1328    page->display( output_dev, 72, 72, 0, gFalse,
1329                   gTrue, NULL, document->doc->getCatalog() );
1330    DosReleaseMutexSem( document->mutex );
1331
1332
1333    // Convert string from system encoding to UCS-4
1334    // first, convert to UCS-2
1335    size_t cSubs = 0;
1336    size_t text_len = strlen( text );
1337    size_t text_len_sav = text_len;
1338    size_t ucs2_len = ( text_len + 1 ) * 2;
1339    char *ucs2 = new char[ ucs2_len ];
1340    memset( ucs2, 0, ucs2_len );
1341    char *ucs2sav = ucs2;
1342    UniUconvToUcs( document->objSys, (void **)&text, &text_len,
1343                   (UniChar **)&ucs2, &ucs2_len, &cSubs );
1344    // second, convert UCS-2 to UCS-4
1345    short *uucs2 = (short *)ucs2sav;
1346    unsigned ucs4_len = ( text_len_sav + 1 ) * 2;
1347    unsigned *ucs4 = new unsigned[ ucs4_len ];
1348    memset( ucs4, 0, ucs4_len * sizeof( unsigned ) );
1349    int real_ucs4_len = 0;
1350    for ( real_ucs4_len = 0; *uucs2; real_ucs4_len++ ) {
1351        ucs4[ real_ucs4_len ] = *uucs2++;
1352    }
1353    delete ucs2sav;
1354    // conversion end
1355
1356    RectList *rl = new RectList;
1357    double xMin, yMin, xMax, yMax;
1358    xMin = 0;
1359    yMin = 0;
1360    while ( output_dev->findText( ucs4, real_ucs4_len,
1361                   gFalse, gTrue, // startAtTop, stopAtBottom
1362                   gTrue, gFalse, // startAtLast, stopAtLast
1363                   caseSensitive, gFalse, // caseSensitive, backwards
1364                   &xMin, &yMin, &xMax, &yMax ) )
1365    {
1366        LuRectangle r;
1367        r.x1 = xMin;
1368        r.y1 = yMin;
1369        r.x2 = xMax;
1370        r.y2 = yMax;
1371        rl->push_back( r );
1372    }
1373    delete ucs4;
1374    delete output_dev;
1375
1376    LuDocument_LuRectSequence *rectangles = NULL;
1377    int len = rl->size();
1378    if ( len > 0 )
1379    {
1380        rectangles = (LuDocument_LuRectSequence *)SOMMalloc( sizeof( LuDocument_LuRectSequence ) );
1381        rectangles->_maximum = len;
1382        rectangles->_length = len;
1383        rectangles->_buffer = (LuRectangle *)SOMMalloc( sizeof( LuRectangle ) * len );
1384
1385        for ( int i = 0; i < len; i++ )
1386        {
1387            rectangles->_buffer[ i ].x1 = (*rl)[i].x1;
1388            rectangles->_buffer[ i ].y1 = (*rl)[i].y1;
1389            rectangles->_buffer[ i ].x2 = (*rl)[i].x2;
1390            rectangles->_buffer[ i ].y2 = (*rl)[i].y2;
1391        }
1392    }
1393    delete rl;
1394
1395    return rectangles;
1396}
1397
1398
1399SOM_Scope boolean  SOMLINK isFixedImage(LuPopplerDocument *somSelf,
1400                                         Environment *ev)
1401{
1402    return FALSE;
1403}
1404
1405
1406SOM_Scope boolean  SOMLINK isCreateFileThumbnail(LuPopplerDocument *somSelf,
1407                                                  Environment *ev)
1408{
1409    return TRUE;
1410}
1411
1412
1413SOM_Scope void SOMLINK somDefaultInit(LuPopplerDocument *somSelf,
1414                                      som3InitCtrl* ctrl)
1415{
1416    // generated section - do not modify
1417    LuPopplerDocumentData *somThis;
1418    somInitCtrl globalCtrl;
1419    somBooleanVector myMask;
1420    LuPopplerDocument_BeginInitializer_somDefaultInit;
1421    LuPopplerDocument_Init_LuDocument_somDefaultInit(somSelf, ctrl);
1422    // end of generated section
1423
1424    // local LuPopplerDocument initialization code
1425    PopplerDocument *d = new PopplerDocument;
1426    somThis->data = d;
1427}
1428
1429
1430static void set_error( char **error, const char *fmt, ... )
1431{
1432    if ( error == NULL ) {
1433        return;
1434    }
1435
1436    va_list argptr;
1437    va_start( argptr, fmt );
1438    char *msg = new char[ 1000 ];
1439    vsnprintf( msg, 1000, fmt, argptr );
1440    *error = somstrdup( msg );
1441    delete msg;
1442}
1443
1444
1445SOM_Scope boolean  SOMLINK loadFile(LuPopplerDocument *somSelf,
1446                                     Environment *ev, string filename,
1447                                    string password, long* errorCode,
1448                                    string* error)
1449{
1450    if ( errorCode != NULL ) {
1451        *errorCode = LU_LDERR_NO_ERROR;
1452    }
1453
1454    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData( somSelf );
1455
1456    PDFDoc *newDoc;
1457    GooString *filename_g;
1458    GooString *password_g;
1459    int err;
1460
1461    if ( !globalParams ) {
1462        globalParams = new GlobalParams( NULL );
1463    }
1464
1465    filename_g = new GooString(filename);
1466
1467    password_g = NULL;
1468    if (password != NULL) {
1469        password_g = new GooString(password);
1470    }
1471
1472    newDoc = new PDFDoc(filename_g, password_g, password_g);
1473    if (password_g) {
1474        delete password_g;
1475    }
1476
1477    if (!newDoc->isOk()) {
1478        err = newDoc->getErrorCode();
1479        delete newDoc;
1480
1481        if ( errorCode != NULL )
1482        {
1483            switch ( err )
1484            {
1485                case errOpenFile:
1486                    *errorCode = LU_LDERR_OPEN_ERROR;
1487                    break;
1488                case errBadCatalog:
1489                case errDamaged:
1490                    *errorCode = LU_LDERR_DAMAGED;
1491                    break;
1492                case errEncrypted:
1493                    *errorCode = LU_LDERR_ENCRYPTED;
1494                    break;
1495                case errFileIO:
1496                    *errorCode = LU_LDERR_READ_ERROR;
1497                    break;
1498                default:
1499                    *errorCode = LU_LDERR_CUSTOM;
1500                    set_error( error, "(error %d)", err );
1501                    break;
1502            }
1503        }
1504
1505        return FALSE;
1506    }
1507
1508    PopplerDocument *document = (PopplerDocument *)somThis->data;
1509
1510    document->doc = newDoc;
1511    SplashColor white;
1512    white[0] = 255;
1513    white[1] = 255;
1514    white[2] = 255;
1515    document->output_dev = new SplashOutputDev( splashModeBGR8, 4, gFalse, white );
1516    document->output_dev->startDoc( document->doc->getXRef() );
1517
1518    long numpages = document->doc->getNumPages();
1519    document->pages = new PopplerPage[ numpages ];
1520    for ( long pagenum = 0; pagenum < numpages; pagenum++ ) {
1521        document->pages[ pagenum ].page =
1522            document->doc->getCatalog()->getPage( pagenum + 1 );
1523    }
1524
1525    return TRUE;
1526}
1527
1528
1529SOM_Scope void SOMLINK somDestruct(LuPopplerDocument *somSelf,
1530                                   octet doFree, som3DestructCtrl* ctrl)
1531{
1532    LuPopplerDocumentData *somThis;
1533    somDestructCtrl globalCtrl;
1534    somBooleanVector myMask;
1535    LuPopplerDocument_BeginDestructor;
1536
1537    // local LuPopplerDocument deinitialization code
1538    PopplerDocument *document = (PopplerDocument *)somThis->data;
1539    delete document;
1540    // end of local LuPopplerDocument deinitialization code
1541
1542    LuPopplerDocument_EndDestructor;
1543}
1544
1545
Note: See TracBrowser for help on using the repository browser.