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

Last change on this file since 497 was 497, checked in by Silvan Scherrer, 10 years ago

Lucide: updated fontconfig and poppler

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