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

Last change on this file since 213 was 213, checked in by Eugene Romanenko, 14 years ago

Opening external files from links in document

File size: 48.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 long find_dest_r_page( LinkDest *link_dest )
578{
579    long page_num = 0;
580
581    if ( link_dest == NULL ) {
582        return page_num;
583    }
584
585    if ( !link_dest->isPageRef() ) {
586        page_num = link_dest->getPageNum() - 1;
587    }
588
589    return page_num;
590}
591
592static void build_goto_dest( PDFDoc *doc, LuLink *evlink, LinkGoTo *link )
593{
594    LinkDest *link_dest;
595    UGooString *named_dest;
596
597    if ( !link->isOk() ) {
598        return;
599    }
600
601    link_dest = link->getDest();
602    named_dest = link->getNamedDest();
603
604    if ( link_dest != NULL ) {
605        evlink->page = find_dest_page( doc, link_dest );
606    } else if ( named_dest != NULL ) {
607        link_dest = doc->findDest( named_dest );
608        evlink->page = find_dest_page( doc, link_dest );
609        delete link_dest;
610    } else {
611        evlink->page = 0;
612    }
613}
614
615static void build_goto_r_dest( LuLink *evlink, LinkGoToR *link )
616{
617    LinkDest *link_dest;
618    UGooString *named_dest;
619
620    if ( !link->isOk() ) {
621        return;
622    }
623
624    link_dest  = link->getDest();
625    named_dest = link->getNamedDest();
626
627    char *file = link->getFileName()->getCString();
628    if ( file != NULL ) {
629        evlink->uri = somstrdup( file );
630    }
631    evlink->page = find_dest_r_page( link_dest );
632}
633
634static void build_link( PDFDoc *doc, LuLink *evlink,
635                        const char *title, LinkAction *link_action )
636{
637    evlink->title = somstrdup( title );
638    evlink->uri   = NULL;
639    evlink->type  = LU_LINK_TYPE_TITLE;
640    evlink->page  = 0;
641
642    if ( link_action == NULL ) {
643        return;
644    }
645
646    switch ( link_action->getKind() )
647    {
648        case actionGoTo:
649            {
650                evlink->type = LU_LINK_TYPE_PAGE;
651                LinkGoTo *lgt = dynamic_cast <LinkGoTo *> (link_action);
652                build_goto_dest( doc, evlink, lgt );
653            }
654            break;
655
656        case actionGoToR:
657            {
658                evlink->type = LU_LINK_TYPE_EXTERNAL_FILE;
659                LinkGoToR *lgt = dynamic_cast <LinkGoToR *> (link_action);
660                build_goto_r_dest( evlink, lgt );
661            }
662            break;
663
664        case actionURI:
665            {
666                evlink->type = LU_LINK_TYPE_EXTERNAL_URI;
667                LinkURI *lu = dynamic_cast <LinkURI *> (link_action);
668                char *uri = lu->getURI()->getCString();
669                if ( uri != NULL ) {
670                    evlink->uri = somstrdup( uri );
671                }
672            }
673            break;
674    }
675}
676
677SOM_Scope LuDocument_LuLinkMapSequence*  SOMLINK getLinkMapping(LuPopplerDocument *somSelf,
678                                                                 Environment *ev,
679                                                                long pagenum)
680{
681    LuDocument_LuLinkMapSequence *mapping = NULL;
682    mapping = (LuDocument_LuLinkMapSequence *)SOMMalloc( sizeof( LuDocument_LuLinkMapSequence ) );
683    mapping->_maximum = 0;
684    mapping->_length = 0;
685    mapping->_buffer = NULL;
686
687    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
688    PopplerDocument *document = (PopplerDocument *)somThis->data;
689    PopplerPage *page = &( document->pages[ pagenum ] );
690
691    Object obj;
692    Links *links = new Links( page->page->getAnnots( &obj ),
693                            document->doc->getCatalog()->getBaseURI() );
694    obj.free();
695
696    if ( links == NULL ) {  // No links, return empty LuLinkMapSequence
697        return mapping;
698    }
699
700    double height = 0;
701    getPageSize( somSelf, ev, pagenum, NULL, &height );
702
703    int len = links->getNumLinks();
704
705    mapping->_maximum = len;
706    mapping->_length = len;
707    if ( len != 0 ) {
708        mapping->_buffer = (LuLinkMapping *)SOMMalloc( sizeof( LuLinkMapping ) * len );
709    }
710
711    for ( int i = 0; i < len; i++ )
712    {
713        Link *link = links->getLink( i );
714        LinkAction *link_action = link->getAction();
715        build_link( document->doc, &(mapping->_buffer[ i ].link), NULL, link_action );
716
717        link->getRect( &(mapping->_buffer[ i ].area.x1),
718                       &(mapping->_buffer[ i ].area.y1),
719                       &(mapping->_buffer[ i ].area.x2),
720                       &(mapping->_buffer[ i ].area.y2) );
721
722        mapping->_buffer[ i ].area.x1 -= page->page->getCropBox()->x1;
723        mapping->_buffer[ i ].area.x2 -= page->page->getCropBox()->x1;
724        mapping->_buffer[ i ].area.y1 -= page->page->getCropBox()->y1;
725        mapping->_buffer[ i ].area.y2 -= page->page->getCropBox()->y1;
726
727        double y1 = mapping->_buffer[ i ].area.y1;
728        double y2 = mapping->_buffer[ i ].area.y2;
729        mapping->_buffer[ i ].area.y1 = height - y2;
730        mapping->_buffer[ i ].area.y2 = height - y1;
731    }
732
733    return mapping;
734}
735
736
737SOM_Scope boolean  SOMLINK isSaveable(LuPopplerDocument *somSelf,
738                                       Environment *ev)
739{
740    return TRUE;
741}
742
743
744SOM_Scope boolean  SOMLINK saveAs(LuPopplerDocument *somSelf,
745                                   Environment *ev, string filename)
746{
747    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
748    PopplerDocument *document = (PopplerDocument *)somThis->data;
749
750    boolean retval = FALSE;
751
752    if ( filename != NULL ) {
753        retval = document->doc->saveAs( new GooString( filename ) );
754    }
755
756    return retval;
757}
758
759
760SOM_Scope boolean  SOMLINK isPostScriptExportable(LuPopplerDocument *somSelf,
761                                           Environment *ev)
762{
763    return TRUE;
764}
765
766
767SOM_Scope boolean SOMLINK exportToPostScript(LuPopplerDocument *somSelf,
768                                    Environment *ev, string filename,
769                                    long first_page, long last_page,
770                                    double width, double height,
771                                    boolean* brkExport)
772{
773    if ( filename == NULL ) {
774        return FALSE;
775    }
776
777    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
778    PDFDoc *doc = ((PopplerDocument *)somThis->data)->doc;
779
780    PSOutputDev *out = new PSOutputDev( filename, doc->getXRef(), doc->getCatalog(),
781                                (first_page <= last_page) ? (first_page + 1) : (last_page + 1),
782                                (first_page <= last_page) ? (last_page + 1) : (first_page + 1),
783                                        psModePS, (int)width, (int)height,
784                                        gFalse, 0, 0, 0, 0, gFalse );
785
786    if ( !out->isOk() ) {
787        delete out;
788        return FALSE;
789    }
790
791    if ( *brkExport ) {
792        delete out;
793        return TRUE;
794    }
795
796    long pagestoprint = abs( last_page - first_page ) + 1;
797    long pg = first_page;
798    for ( long i = 0; (i < pagestoprint) && !(*brkExport); i++ ) {
799        doc->displayPage( out, pg + 1, 72.0, 72.0, 0, gFalse, gTrue, gFalse );
800        pg += ( first_page <= last_page ) ? 1 : -1;
801    }
802
803    delete out;
804    return TRUE;
805}
806
807
808SOM_Scope boolean  SOMLINK isHaveFontInfo(LuPopplerDocument *somSelf,
809                                           Environment *ev)
810{
811    return TRUE;
812}
813
814
815SOM_Scope LuDocument_LuFontInfoSequence*  SOMLINK getFontInfo(LuPopplerDocument *somSelf,
816                                                               Environment *ev)
817{
818    LuDocument_LuFontInfoSequence *fonts = NULL;
819
820    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
821    PopplerDocument *document = (PopplerDocument *)somThis->data;
822    PDFDoc *doc = document->doc;
823
824    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
825    FontInfoScanner *scanner = new FontInfoScanner( doc );
826    GooList *items = scanner->scan( doc->getNumPages() );
827    delete scanner;
828    DosReleaseMutexSem( document->mutex );
829
830    if ( items == NULL ) {
831        return NULL;
832    }
833
834    int len = items->getLength();
835
836    if ( len == 0 ) {
837        delete items;
838        return NULL;
839    }
840
841    fonts = (LuDocument_LuFontInfoSequence *)SOMMalloc( sizeof( LuDocument_LuFontInfoSequence ) );
842    fonts->_maximum = len;
843    fonts->_length = len;
844    fonts->_buffer = (LuFontInfo *)SOMMalloc( sizeof( LuFontInfo ) * len );
845
846    for ( int i = 0; i < len; i++ )
847    {
848        fonts->_buffer[i].name = NULL;
849        fonts->_buffer[i].type = NULL;
850        fonts->_buffer[i].embedded = NULL;
851
852        FontInfo *info = (FontInfo *)items->get( i );
853
854        // name
855        GooString *gnm = info->getName();
856        if ( gnm != NULL )
857        {
858            char *nm = gnm->getCString();
859            if ( info->getSubset() && ( nm != NULL ) )
860            {
861                while ( *nm && ( *nm != '+' ) ) {
862                    nm++;
863                }
864                if ( *nm ) {
865                    nm++;
866                }
867            }
868            if ( nm != NULL ) {
869                if ( *nm ) {
870                    fonts->_buffer[i].name = somstrdup( nm );
871                }
872            }
873        }
874
875        // type
876        char *t = "Unknown font type";
877        switch ( info->getType() )
878        {
879            case FontInfo::Type1:        t = "Type 1";          break;
880            case FontInfo::Type1C:       t = "Type 1C";         break;
881            case FontInfo::Type3:        t = "Type 3";          break;
882            case FontInfo::TrueType:     t = "TrueType";        break;
883            case FontInfo::CIDType0:     t = "Type 1 (CID)";    break;
884            case FontInfo::CIDType0C:    t = "Type 1C (CID)";   break;
885            case FontInfo::CIDTrueType:  t = "TrueType (CID)";  break;
886        }
887        fonts->_buffer[i].type = somstrdup( t );
888
889        // embedded
890        if ( info->getEmbedded() ) {
891            if ( info->getSubset() ) {
892                fonts->_buffer[i].embedded = LU_FONTEMBED_EMBEDDED_SUBSET;
893            } else {
894                fonts->_buffer[i].embedded = LU_FONTEMBED_EMBEDDED;
895            }
896        } else {
897            fonts->_buffer[i].embedded = LU_FONTEMBED_NOT_EMBEDDED;
898        }
899    }
900
901    return fonts;
902}
903
904
905SOM_Scope boolean  SOMLINK isHaveIndex(LuPopplerDocument *somSelf,
906                                        Environment *ev)
907{
908    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
909    PDFDoc *doc = ((PopplerDocument *)somThis->data)->doc;
910
911    Outline *outline = doc->getOutline();
912    if ( outline == NULL ) {
913        return FALSE;
914    }
915
916    GooList *items = outline->getItems();
917    if ( items == NULL ) {
918        return FALSE;
919    }
920
921    return TRUE;
922}
923
924static char *unicode_to_char( Unicode *unicode, int len )
925{
926    static UnicodeMap *uMap = NULL;
927    if ( uMap == NULL )
928    {
929        GooString *enc = new GooString( "UTF-8" );
930        uMap = globalParams->getUnicodeMap( enc );
931        uMap->incRefCnt();
932        delete enc;
933    }
934
935    GooString gstr;
936    char buf[8]; // 8 is enough for mapping an unicode char to a string
937    int i, n;
938
939    for ( i = 0; i < len; ++i ) {
940        n = uMap->mapUnicode( unicode[i], buf, sizeof( buf ) );
941        gstr.append( buf, n );
942    }
943
944    return newstrdup( gstr.getCString() );
945}
946
947static char *newstrFromUTF8( const char *s, void *objUtf8, void *objSys )
948{
949    size_t cSubs = 0;
950    size_t len = strlen( s ) + 1;
951    size_t unilen = len + 2;
952    UniChar *unibuf = new UniChar[ unilen ];
953    UniChar *tmpuni = unibuf;
954    UniUconvToUcs( objUtf8, (void **)&s, &len, &tmpuni, &unilen, &cSubs );
955    unilen = UniStrlen( unibuf );
956
957    int liglen = uniLigaturesLength( unibuf );
958    if ( liglen > 0 )  // string contain ligature(s)
959    {
960        unsigned ulen_tmp = ( unilen + liglen + 1 ) * sizeof( UniChar );
961        char *uni_tmp = new char[ ulen_tmp ];
962        uniReplaceLigatures( unibuf, (UniChar *)uni_tmp );
963        delete unibuf;
964        unibuf = (UniChar *)uni_tmp;
965        unilen = UniStrlen( unibuf );
966    }
967    uniConvertSpChars( unibuf );
968
969    size_t blen = ( unilen + 1 ) * 2;
970    char *b = new char[ blen ];
971    memset( b, 0, blen );
972    char *bsav = b;
973    tmpuni = unibuf;
974    cSubs = 0;
975    UniUconvFromUcs( objSys, &tmpuni, &unilen, (void **)&b, &blen, &cSubs );
976    delete unibuf;
977    return bsav;
978}
979
980static void add_item( Environment *ev, PDFDoc *doc, LuIndexNode *n, GooList *items,
981                      void *objUtf8, void *objSys )
982{
983    if ( items == NULL ) {
984        return;
985    }
986
987    int len = items->getLength();
988
989    for ( int i = 0; i < len; i++ )
990    {
991        OutlineItem *item = (OutlineItem *)items->get( i );
992        LinkAction *link_action = item->getAction();
993        LuLink evlink;
994        char *t1 = unicode_to_char( item->getTitle(), item->getTitleLength() );
995        char *t2 = newstrFromUTF8( t1, objUtf8, objSys );
996        build_link( doc, &evlink, t2, link_action );
997        delete t2;
998        delete t1;
999        LuIndexNode *cn = new LuIndexNode( ev, &evlink );
1000        n->addChild( ev, cn );
1001
1002        item->open();
1003        if ( item->hasKids() )
1004        {
1005            GooList *citems = item->getKids();
1006            add_item( ev, doc, cn, citems, objUtf8, objSys );
1007        }
1008    }
1009}
1010
1011SOM_Scope LuIndexNode*  SOMLINK getIndex(LuPopplerDocument *somSelf,
1012                                          Environment *ev)
1013{
1014    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1015    PopplerDocument *document = (PopplerDocument *)somThis->data;
1016    PDFDoc *doc = document->doc;
1017
1018    Outline *outline = doc->getOutline();
1019    if ( outline == NULL ) {
1020        return NULL;
1021    }
1022
1023    GooList *items = outline->getItems();
1024    if ( items == NULL ) {
1025        return NULL;
1026    }
1027
1028    LuIndexNode *root = new LuIndexNode( ev, NULL );
1029    add_item( ev, doc, root, items, document->objUtf8, document->objSys );
1030
1031    return root;
1032}
1033
1034
1035static bool has_unicode_marker( GooString *string )
1036{
1037    return ( ( (string->getChar(0) & 0xff) == 0xfe ) &&
1038             ( (string->getChar(1) & 0xff) == 0xff ) );
1039}
1040
1041// return SOMMalloc'ed string
1042static char *propcnv( GooString *s, void *objUniBe, void *objSys )
1043{
1044    if ( has_unicode_marker( s ) )
1045    {
1046        size_t cSubs = 0;
1047        size_t unilen = s->getLength() + 1;
1048        UniChar *unibuf = new UniChar[ unilen ];
1049        memset( unibuf, 0, unilen * sizeof( UniChar ) );
1050        UniChar *tmpuni = unibuf;
1051        const char *from = s->getCString() + 2;
1052        size_t fromlen = s->getLength() - 2;
1053        UniUconvToUcs( objUniBe, (void **)&from, &fromlen, &tmpuni, &unilen, &cSubs );
1054        unilen = UniStrlen( unibuf );
1055
1056        int liglen = uniLigaturesLength( unibuf );
1057        if ( liglen > 0 )  // string contain ligature(s)
1058        {
1059            unsigned ulen_tmp = ( unilen + liglen + 1 ) * sizeof( UniChar );
1060            char *uni_tmp = new char[ ulen_tmp ];
1061            uniReplaceLigatures( unibuf, (UniChar *)uni_tmp );
1062            delete unibuf;
1063            unibuf = (UniChar *)uni_tmp;
1064            unilen = UniStrlen( unibuf );
1065        }
1066        uniConvertSpChars( unibuf );
1067
1068        size_t blen = ( unilen + 1 ) * 2;
1069        char *b = (char *)SOMMalloc( blen );
1070        memset( b, 0, blen );
1071        char *bsav = b;
1072        tmpuni = unibuf;
1073        cSubs = 0;
1074        UniUconvFromUcs( objSys, &tmpuni, &unilen, (void **)&b, &blen, &cSubs );
1075        delete unibuf;
1076        return bsav;
1077    }
1078
1079    return somstrdup( s->getCString() );
1080}
1081
1082static time_t propToDate( const char *date_string )
1083{
1084    int year, mon, day, hour, min, sec;
1085    int scanned_items;
1086
1087    // See PDF Reference 1.3, Section 3.8.2 for PDF Date representation
1088    if ( ( date_string[0] == 'D' ) && ( date_string[1] == ':' ) ) {
1089        date_string += 2;
1090    }
1091
1092    // FIXME only year is mandatory; parse optional timezone offset
1093    scanned_items = sscanf( date_string, "%4d%2d%2d%2d%2d%2d",
1094                            &year, &mon, &day, &hour, &min, &sec);
1095
1096    if ( scanned_items != 6 ) {
1097        return (time_t)(-1);
1098    }
1099
1100    // Workaround for y2k bug in Distiller 3, hoping that it won't
1101    // be used after y2.2k
1102    if ( ( year < 1930 ) && ( strlen( date_string ) > 14 ) )
1103    {
1104        int century, years_since_1900;
1105        scanned_items = sscanf( date_string, "%2d%3d%2d%2d%2d%2d%2d",
1106                &century, &years_since_1900, &mon, &day, &hour, &min, &sec );
1107
1108        if ( scanned_items != 7 ) {
1109            return (time_t)(-1);
1110        }
1111
1112        year = century * 100 + years_since_1900;
1113    }
1114
1115    struct tm time = { 0 };
1116    time.tm_year  = year - 1900;
1117    time.tm_mon   = mon - 1;
1118    time.tm_mday  = day;
1119    time.tm_hour  = hour;
1120    time.tm_min   = min;
1121    time.tm_sec   = sec;
1122    time.tm_wday  = -1;
1123    time.tm_yday  = -1;
1124    time.tm_isdst = -1; // 0 = DST off, 1 = DST on, -1 = don't know
1125
1126    return mktime( &time );
1127}
1128
1129static long convPageMode( Catalog::PageMode pageMode )
1130{
1131    switch ( pageMode )
1132    {
1133        case Catalog::pageModeThumbs:
1134            return LU_DOCUMENT_MODE_USE_THUMBS;
1135        case Catalog::pageModeFullScreen:
1136            return LU_DOCUMENT_MODE_FULL_SCREEN;
1137        case Catalog::pageModeOC:
1138            return LU_DOCUMENT_MODE_USE_OC;
1139        case Catalog::pageModeAttach:
1140            return LU_DOCUMENT_MODE_USE_ATTACHMENTS;
1141        case Catalog::pageModeNone:
1142            return LU_DOCUMENT_MODE_NONE;
1143    }
1144
1145    return -1;
1146}
1147
1148static long convLayout( Catalog::PageLayout pageLayout )
1149{
1150    switch ( pageLayout )
1151    {
1152        case Catalog::pageLayoutSinglePage:
1153            return LU_DOCUMENT_LAYOUT_SINGLE_PAGE;
1154        case Catalog::pageLayoutOneColumn:
1155            return LU_DOCUMENT_LAYOUT_ONE_COLUMN;
1156        case Catalog::pageLayoutTwoColumnLeft:
1157            return LU_DOCUMENT_LAYOUT_TWO_COLUMN_LEFT;
1158        case Catalog::pageLayoutTwoColumnRight:
1159            return LU_DOCUMENT_LAYOUT_TWO_COLUMN_RIGHT;
1160        case Catalog::pageLayoutTwoPageLeft:
1161            return LU_DOCUMENT_LAYOUT_TWO_PAGE_LEFT;
1162        case Catalog::pageLayoutTwoPageRight:
1163            return LU_DOCUMENT_LAYOUT_TWO_PAGE_RIGHT;
1164    }
1165    return -1;
1166}
1167
1168SOM_Scope LuDocumentInfo*  SOMLINK getDocumentInfo(LuPopplerDocument *somSelf,
1169                                                    Environment *ev)
1170{
1171    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1172    PopplerDocument *document = (PopplerDocument *)somThis->data;
1173    PDFDoc *doc = document->doc;
1174
1175    LuDocumentInfo *info = (LuDocumentInfo *)SOMMalloc( sizeof( LuDocumentInfo ) );
1176    memset( info, 0, sizeof( LuDocumentInfo ) );
1177
1178    Object objdict;
1179    doc->getDocInfo( &objdict );
1180    if ( objdict.isDict() )
1181    {
1182        Dict *d = objdict.getDict();
1183        Object obj;
1184
1185        if ( d->lookup( "Title", &obj )->isString() ) {
1186            info->title = propcnv( obj.getString(), document->objUniBe, document->objSys );
1187            info->fields_mask |= LU_DOCUMENT_INFO_TITLE;
1188        }
1189        obj.free();
1190        if ( d->lookup( "Author", &obj )->isString() ) {
1191            info->author = propcnv( obj.getString(), document->objUniBe, document->objSys );
1192            info->fields_mask |= LU_DOCUMENT_INFO_AUTHOR;
1193        }
1194        obj.free();
1195        if ( d->lookup( "Subject", &obj )->isString() ) {
1196            info->subject = propcnv( obj.getString(), document->objUniBe, document->objSys );
1197            info->fields_mask |= LU_DOCUMENT_INFO_SUBJECT;
1198        }
1199        obj.free();
1200        if ( d->lookup( "Keywords", &obj )->isString() ) {
1201            info->keywords = propcnv( obj.getString(), document->objUniBe, document->objSys );
1202            info->fields_mask |= LU_DOCUMENT_INFO_KEYWORDS;
1203        }
1204        obj.free();
1205        if ( d->lookup( "Creator", &obj )->isString() ) {
1206            info->creator = propcnv( obj.getString(), document->objUniBe, document->objSys );
1207            info->fields_mask |= LU_DOCUMENT_INFO_CREATOR;
1208        }
1209        obj.free();
1210        if ( d->lookup( "Producer", &obj )->isString() ) {
1211            info->producer = propcnv( obj.getString(), document->objUniBe, document->objSys );
1212            info->fields_mask |= LU_DOCUMENT_INFO_PRODUCER;
1213        }
1214        obj.free();
1215        if ( d->lookup( "CreationDate", &obj )->isString() ) {
1216            char *d = propcnv( obj.getString(), document->objUniBe, document->objSys );
1217            info->creation_date = propToDate( d );
1218            if ( (long)info->creation_date != -1 ) {
1219                info->fields_mask |= LU_DOCUMENT_INFO_CREATION_DATE;
1220            }
1221            SOMFree( d );
1222        }
1223        obj.free();
1224        if ( d->lookup( "ModDate", &obj )->isString() ) {
1225            char *d = propcnv( obj.getString(), document->objUniBe, document->objSys );
1226            info->modified_date = propToDate( d );
1227            if ( (long)info->modified_date != -1 ) {
1228                info->fields_mask |= LU_DOCUMENT_INFO_MOD_DATE;
1229            }
1230            SOMFree( d );
1231        }
1232        obj.free();
1233    }
1234
1235    char *format = (char *)SOMMalloc( 16 );
1236    snprintf( format, 16, "PDF-%.2f", doc->getPDFVersion() );
1237    info->format = format;
1238    info->fields_mask |= LU_DOCUMENT_INFO_FORMAT;
1239
1240    info->linearized = doc->isLinearized();
1241    info->fields_mask |= LU_DOCUMENT_INFO_LINEARIZED;
1242
1243    Catalog *catalog = doc->getCatalog();
1244
1245    if ( ( catalog != NULL ) && catalog->isOk() )
1246    {
1247        info->layout = convLayout( catalog->getPageLayout() );
1248        if ( info->layout != -1 ) {
1249            info->fields_mask |= LU_DOCUMENT_INFO_LAYOUT;
1250        }
1251
1252        info->mode = convPageMode( catalog->getPageMode() );
1253        if ( info->mode != -1 ) {
1254            info->fields_mask |= LU_DOCUMENT_INFO_START_MODE;
1255        }
1256    }
1257
1258    info->fields_mask |= LU_DOCUMENT_INFO_PERMISSIONS;
1259    if ( doc->okToPrint() ) {
1260        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_PRINT;
1261    }
1262    if ( doc->okToChange() ) {
1263        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_MODIFY;
1264    }
1265    if ( doc->okToCopy() ) {
1266        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_COPY;
1267    }
1268    if ( doc->okToAddNotes() ) {
1269        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES;
1270    }
1271
1272    info->n_pages = doc->getNumPages();
1273    info->fields_mask |= LU_DOCUMENT_INFO_N_PAGES;
1274
1275    return info;
1276}
1277
1278
1279SOM_Scope boolean  SOMLINK getThumbnailSize(LuPopplerDocument *somSelf,
1280                                             Environment *ev,
1281                                            long pagenum,
1282                                            short suggested_width,
1283                                            short* width, short* height)
1284{
1285    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1286    Page *page = ((PopplerDocument *)somThis->data)->pages[ pagenum ].page;
1287
1288    Object thumb;
1289    Dict *dict;
1290    boolean retval = FALSE;
1291
1292    page->getThumb( &thumb );
1293    if ( thumb.isNull() )
1294    {
1295        thumb.free();
1296        return FALSE;
1297    }
1298
1299    dict = thumb.streamGetDict();
1300
1301    // Theoretically, this could succeed and you would still fail when
1302    // loading the thumb
1303    int w = 0, h = 0;
1304    if ( dict->lookupInt( "Width", "W", &w ) && dict->lookupInt( "Height", "H", &h ) )
1305    {
1306        if ( width != NULL ) {
1307            *width = w;
1308        }
1309        if ( height != NULL ) {
1310            *height = h;
1311        }
1312
1313        retval = TRUE;
1314    }
1315
1316    thumb.free();
1317
1318    return retval;
1319}
1320
1321SOM_Scope LuPixbuf*  SOMLINK getThumbnail(LuPopplerDocument *somSelf,
1322                                           Environment *ev, long pagenum,
1323                                          short suggested_width)
1324{
1325    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1326    Page *page = ((PopplerDocument *)somThis->data)->pages[ pagenum ].page;
1327
1328    unsigned char *data;
1329    int width, height, rowstride;
1330
1331    if ( !page->loadThumb( &data, &width, &height, &rowstride ) ) {
1332        return NULL;
1333    }
1334
1335    short bpp = getBpp( somSelf, ev );
1336    LuPixbuf *pixbuf = new LuPixbuf( ev, width, height, bpp );
1337    char *pixbuf_data = (char *)pixbuf->getDataPtr( ev );
1338    int pixbuf_rowstride = pixbuf->getRowSize( ev );
1339    char *src, *dst;
1340    int i, j;
1341    for ( i = 0, j = ( height - 1 ); i < height; i++, j-- )
1342    {
1343        src = data + ( j * rowstride );
1344        dst = pixbuf_data + (i * pixbuf_rowstride);
1345        for ( int k = 0; k < pixbuf_rowstride; k += bpp )
1346        {
1347            dst[ k ]     = src[ k + 2 ];
1348            dst[ k + 1 ] = src[ k + 1 ];
1349            dst[ k + 2 ] = src[ k ];
1350        }
1351    }
1352    gfree( data );
1353
1354    return pixbuf;
1355}
1356
1357
1358SOM_Scope LuDocument_LuRectSequence*  SOMLINK searchText(LuPopplerDocument *somSelf,
1359                                                          Environment *ev,
1360                                                         long pagenum,
1361                                                         string text,
1362                                                         boolean caseSensitive)
1363{
1364    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1365    PopplerDocument *document = (PopplerDocument *)somThis->data;
1366    Page *page = document->pages[ pagenum ].page;
1367
1368    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
1369    TextOutputDev *output_dev = new TextOutputDev( NULL, gTrue, gFalse, gFalse );
1370    page->display( output_dev, 72, 72, 0, gFalse,
1371                   gTrue, NULL, document->doc->getCatalog() );
1372    DosReleaseMutexSem( document->mutex );
1373
1374
1375    // Convert string from system encoding to UCS-4
1376    // first, convert to UCS-2
1377    size_t cSubs = 0;
1378    size_t text_len = strlen( text );
1379    size_t text_len_sav = text_len;
1380    size_t ucs2_len = ( text_len + 1 ) * 2;
1381    char *ucs2 = new char[ ucs2_len ];
1382    memset( ucs2, 0, ucs2_len );
1383    char *ucs2sav = ucs2;
1384    UniUconvToUcs( document->objSys, (void **)&text, &text_len,
1385                   (UniChar **)&ucs2, &ucs2_len, &cSubs );
1386    // second, convert UCS-2 to UCS-4
1387    short *uucs2 = (short *)ucs2sav;
1388    unsigned ucs4_len = ( text_len_sav + 1 ) * 2;
1389    unsigned *ucs4 = new unsigned[ ucs4_len ];
1390    memset( ucs4, 0, ucs4_len * sizeof( unsigned ) );
1391    int real_ucs4_len = 0;
1392    for ( real_ucs4_len = 0; *uucs2; real_ucs4_len++ ) {
1393        ucs4[ real_ucs4_len ] = *uucs2++;
1394    }
1395    delete ucs2sav;
1396    // conversion end
1397
1398    RectList *rl = new RectList;
1399    double xMin, yMin, xMax, yMax;
1400    xMin = 0;
1401    yMin = 0;
1402    while ( output_dev->findText( ucs4, real_ucs4_len,
1403                   gFalse, gTrue, // startAtTop, stopAtBottom
1404                   gTrue, gFalse, // startAtLast, stopAtLast
1405                   caseSensitive, gFalse, // caseSensitive, backwards
1406                   &xMin, &yMin, &xMax, &yMax ) )
1407    {
1408        LuRectangle r;
1409        r.x1 = xMin;
1410        r.y1 = yMin;
1411        r.x2 = xMax;
1412        r.y2 = yMax;
1413        rl->push_back( r );
1414    }
1415    delete ucs4;
1416    delete output_dev;
1417
1418    LuDocument_LuRectSequence *rectangles = NULL;
1419    int len = rl->size();
1420    if ( len > 0 )
1421    {
1422        rectangles = (LuDocument_LuRectSequence *)SOMMalloc( sizeof( LuDocument_LuRectSequence ) );
1423        rectangles->_maximum = len;
1424        rectangles->_length = len;
1425        rectangles->_buffer = (LuRectangle *)SOMMalloc( sizeof( LuRectangle ) * len );
1426
1427        for ( int i = 0; i < len; i++ )
1428        {
1429            rectangles->_buffer[ i ].x1 = (*rl)[i].x1;
1430            rectangles->_buffer[ i ].y1 = (*rl)[i].y1;
1431            rectangles->_buffer[ i ].x2 = (*rl)[i].x2;
1432            rectangles->_buffer[ i ].y2 = (*rl)[i].y2;
1433        }
1434    }
1435    delete rl;
1436
1437    return rectangles;
1438}
1439
1440
1441SOM_Scope boolean  SOMLINK isFixedImage(LuPopplerDocument *somSelf,
1442                                         Environment *ev)
1443{
1444    return FALSE;
1445}
1446
1447
1448SOM_Scope boolean  SOMLINK isCreateFileThumbnail(LuPopplerDocument *somSelf,
1449                                                  Environment *ev)
1450{
1451    return TRUE;
1452}
1453
1454
1455SOM_Scope void SOMLINK somDefaultInit(LuPopplerDocument *somSelf,
1456                                      som3InitCtrl* ctrl)
1457{
1458    // generated section - do not modify
1459    LuPopplerDocumentData *somThis;
1460    somInitCtrl globalCtrl;
1461    somBooleanVector myMask;
1462    LuPopplerDocument_BeginInitializer_somDefaultInit;
1463    LuPopplerDocument_Init_LuDocument_somDefaultInit(somSelf, ctrl);
1464    // end of generated section
1465
1466    // local LuPopplerDocument initialization code
1467    PopplerDocument *d = new PopplerDocument;
1468    somThis->data = d;
1469}
1470
1471
1472static void set_error( char **error, const char *fmt, ... )
1473{
1474    if ( error == NULL ) {
1475        return;
1476    }
1477
1478    va_list argptr;
1479    va_start( argptr, fmt );
1480    char *msg = new char[ 1000 ];
1481    vsnprintf( msg, 1000, fmt, argptr );
1482    *error = somstrdup( msg );
1483    delete msg;
1484}
1485
1486
1487SOM_Scope boolean  SOMLINK loadFile(LuPopplerDocument *somSelf,
1488                                     Environment *ev, string filename,
1489                                    string password, long* errorCode,
1490                                    string* error)
1491{
1492    if ( errorCode != NULL ) {
1493        *errorCode = LU_LDERR_NO_ERROR;
1494    }
1495
1496    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData( somSelf );
1497
1498    PDFDoc *newDoc;
1499    GooString *filename_g;
1500    GooString *password_g;
1501    int err;
1502
1503    if ( !globalParams ) {
1504        globalParams = new GlobalParams( NULL );
1505    }
1506
1507    filename_g = new GooString(filename);
1508
1509    password_g = NULL;
1510    if (password != NULL) {
1511        password_g = new GooString(password);
1512    }
1513
1514    newDoc = new PDFDoc(filename_g, password_g, password_g);
1515    if (password_g) {
1516        delete password_g;
1517    }
1518
1519    if (!newDoc->isOk()) {
1520        err = newDoc->getErrorCode();
1521        delete newDoc;
1522
1523        if ( errorCode != NULL )
1524        {
1525            switch ( err )
1526            {
1527                case errOpenFile:
1528                    *errorCode = LU_LDERR_OPEN_ERROR;
1529                    break;
1530                case errBadCatalog:
1531                case errDamaged:
1532                    *errorCode = LU_LDERR_DAMAGED;
1533                    break;
1534                case errEncrypted:
1535                    *errorCode = LU_LDERR_ENCRYPTED;
1536                    break;
1537                case errFileIO:
1538                    *errorCode = LU_LDERR_READ_ERROR;
1539                    break;
1540                default:
1541                    *errorCode = LU_LDERR_CUSTOM;
1542                    set_error( error, "(error %d)", err );
1543                    break;
1544            }
1545        }
1546
1547        return FALSE;
1548    }
1549
1550    PopplerDocument *document = (PopplerDocument *)somThis->data;
1551
1552    document->doc = newDoc;
1553    SplashColor white;
1554    white[0] = 255;
1555    white[1] = 255;
1556    white[2] = 255;
1557    document->output_dev = new SplashOutputDev( splashModeBGR8, 4, gFalse, white );
1558    document->output_dev->startDoc( document->doc->getXRef() );
1559
1560    long numpages = document->doc->getNumPages();
1561    document->pages = new PopplerPage[ numpages ];
1562    for ( long pagenum = 0; pagenum < numpages; pagenum++ ) {
1563        document->pages[ pagenum ].page =
1564            document->doc->getCatalog()->getPage( pagenum + 1 );
1565    }
1566
1567    return TRUE;
1568}
1569
1570
1571SOM_Scope void SOMLINK somDestruct(LuPopplerDocument *somSelf,
1572                                   octet doFree, som3DestructCtrl* ctrl)
1573{
1574    LuPopplerDocumentData *somThis;
1575    somDestructCtrl globalCtrl;
1576    somBooleanVector myMask;
1577    LuPopplerDocument_BeginDestructor;
1578
1579    // local LuPopplerDocument deinitialization code
1580    PopplerDocument *document = (PopplerDocument *)somThis->data;
1581    delete document;
1582    // end of local LuPopplerDocument deinitialization code
1583
1584    LuPopplerDocument_EndDestructor;
1585}
1586
1587
Note: See TracBrowser for help on using the repository browser.