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

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

branches/kmk: Made all Lucide SOM plugins build with kmk/gcc.

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