source: trunk/Lucide/SOURCE/plugins/lupoppler/lupoppler.cpp @ 215

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