source: trunk/Lucide/plugins/lupoppler/lupoppler.cpp @ 461

Last change on this file since 461 was 461, checked in by Silvan Scherrer, 11 years ago

poppler update to 0.14.2

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