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

Last change on this file since 263 was 263, checked in by Eugene Romanenko, 13 years ago

PDF plugin: Poppler library updated to version 0.10.3

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