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

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

PDF plugin: Poppler library updated to version 0.8.6

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