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

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

branches/kmk: Implemented LuPopplerDocument::getInputFields() and LuPopplerInputField?.

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