source: branches/kmk/Lucide/plugins/lupoppler/lupoppler.cpp @ 337

Last change on this file since 337 was 337, checked in by dmik, 12 years ago

branches/kmk: Added a bunch of unicode conversion helpers based on the original propcnv() from lupoppler.cpp.

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