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

Last change on this file since 555 was 555, checked in by Gregg Young, 4 years ago

Andy's fix for an include file name conflict

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