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

Last change on this file since 515 was 515, checked in by Silvan Scherrer, 9 years ago

updated poppler to 0.20.3

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