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

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

PDF plugin: poppler library updated to version 0.8.3

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.3";
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(), "",
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,
804                                        gFalse, 0, 0, 0, 0, gFalse );
805
806    if ( !out->isOk() ) {
807        delete out;
808        return FALSE;
809    }
810
811    if ( *brkExport ) {
812        delete out;
813        return TRUE;
814    }
815
816    long pagestoprint = abs( last_page - first_page ) + 1;
817    long pg = first_page;
818    for ( long i = 0; (i < pagestoprint) && !(*brkExport); i++ ) {
819        doc->displayPage( out, pg + 1, 72.0, 72.0, 0, gFalse, gTrue, gFalse );
820        pg += ( first_page <= last_page ) ? 1 : -1;
821    }
822
823    delete out;
824    return TRUE;
825}
826
827
828SOM_Scope boolean  SOMLINK isHaveFontInfo(LuPopplerDocument *somSelf,
829                                           Environment *ev)
830{
831    return TRUE;
832}
833
834
835SOM_Scope LuDocument_LuFontInfoSequence*  SOMLINK getFontInfo(LuPopplerDocument *somSelf,
836                                                               Environment *ev)
837{
838    LuDocument_LuFontInfoSequence *fonts = NULL;
839
840    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
841    PopplerDocument *document = (PopplerDocument *)somThis->data;
842    PDFDoc *doc = document->doc;
843
844    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
845    FontInfoScanner *scanner = new FontInfoScanner( doc );
846    GooList *items = scanner->scan( doc->getNumPages() );
847    delete scanner;
848    DosReleaseMutexSem( document->mutex );
849
850    if ( items == NULL ) {
851        return NULL;
852    }
853
854    int len = items->getLength();
855
856    if ( len == 0 ) {
857        delete items;
858        return NULL;
859    }
860
861    fonts = (LuDocument_LuFontInfoSequence *)SOMMalloc( sizeof( LuDocument_LuFontInfoSequence ) );
862    fonts->_maximum = len;
863    fonts->_length = len;
864    fonts->_buffer = (LuFontInfo *)SOMMalloc( sizeof( LuFontInfo ) * len );
865
866    for ( int i = 0; i < len; i++ )
867    {
868        fonts->_buffer[i].name = NULL;
869        fonts->_buffer[i].type = NULL;
870        fonts->_buffer[i].embedded = NULL;
871
872        FontInfo *info = (FontInfo *)items->get( i );
873
874        // name
875        GooString *gnm = info->getName();
876        if ( gnm != NULL )
877        {
878            char *nm = gnm->getCString();
879            if ( info->getSubset() && ( nm != NULL ) )
880            {
881                while ( *nm && ( *nm != '+' ) ) {
882                    nm++;
883                }
884                if ( *nm ) {
885                    nm++;
886                }
887            }
888            if ( nm != NULL ) {
889                if ( *nm ) {
890                    fonts->_buffer[i].name = somstrdup( nm );
891                }
892            }
893        }
894
895        // type
896        char *t = "Unknown font type";
897        switch ( info->getType() )
898        {
899            case FontInfo::Type1:        t = "Type 1";          break;
900            case FontInfo::Type1C:       t = "Type 1C";         break;
901            case FontInfo::Type3:        t = "Type 3";          break;
902            case FontInfo::TrueType:     t = "TrueType";        break;
903            case FontInfo::CIDType0:     t = "Type 1 (CID)";    break;
904            case FontInfo::CIDType0C:    t = "Type 1C (CID)";   break;
905            case FontInfo::CIDTrueType:  t = "TrueType (CID)";  break;
906        }
907        fonts->_buffer[i].type = somstrdup( t );
908
909        // embedded
910        if ( info->getEmbedded() ) {
911            if ( info->getSubset() ) {
912                fonts->_buffer[i].embedded = LU_FONTEMBED_EMBEDDED_SUBSET;
913            } else {
914                fonts->_buffer[i].embedded = LU_FONTEMBED_EMBEDDED;
915            }
916        } else {
917            fonts->_buffer[i].embedded = LU_FONTEMBED_NOT_EMBEDDED;
918        }
919    }
920
921    return fonts;
922}
923
924
925SOM_Scope boolean  SOMLINK isHaveIndex(LuPopplerDocument *somSelf,
926                                        Environment *ev)
927{
928    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
929    PDFDoc *doc = ((PopplerDocument *)somThis->data)->doc;
930
931    Outline *outline = doc->getOutline();
932    if ( outline == NULL ) {
933        return FALSE;
934    }
935
936    GooList *items = outline->getItems();
937    if ( items == NULL ) {
938        return FALSE;
939    }
940
941    return TRUE;
942}
943
944static char *unicode_to_char( Unicode *unicode, int len )
945{
946    static UnicodeMap *uMap = NULL;
947    if ( uMap == NULL )
948    {
949        GooString *enc = new GooString( "UTF-8" );
950        uMap = globalParams->getUnicodeMap( enc );
951        uMap->incRefCnt();
952        delete enc;
953    }
954
955    GooString gstr;
956    char buf[8]; // 8 is enough for mapping an unicode char to a string
957    int i, n;
958
959    for ( i = 0; i < len; ++i ) {
960        n = uMap->mapUnicode( unicode[i], buf, sizeof( buf ) );
961        gstr.append( buf, n );
962    }
963
964    return newstrdup( gstr.getCString() );
965}
966
967static char *newstrFromUTF8( const char *s, void *objUtf8, void *objSys )
968{
969    size_t cSubs = 0;
970    size_t len = strlen( s ) + 1;
971    size_t unilen = len + 2;
972    UniChar *unibuf = new UniChar[ unilen ];
973    UniChar *tmpuni = unibuf;
974    UniUconvToUcs( objUtf8, (void **)&s, &len, &tmpuni, &unilen, &cSubs );
975    unilen = UniStrlen( unibuf );
976
977    int liglen = uniLigaturesLength( unibuf );
978    if ( liglen > 0 )  // string contain ligature(s)
979    {
980        unsigned ulen_tmp = ( unilen + liglen + 1 ) * sizeof( UniChar );
981        char *uni_tmp = new char[ ulen_tmp ];
982        uniReplaceLigatures( unibuf, (UniChar *)uni_tmp );
983        delete unibuf;
984        unibuf = (UniChar *)uni_tmp;
985        unilen = UniStrlen( unibuf );
986    }
987    uniConvertSpChars( unibuf );
988
989    size_t blen = ( unilen + 1 ) * 2;
990    char *b = new char[ blen ];
991    memset( b, 0, blen );
992    char *bsav = b;
993    tmpuni = unibuf;
994    cSubs = 0;
995    UniUconvFromUcs( objSys, &tmpuni, &unilen, (void **)&b, &blen, &cSubs );
996    delete unibuf;
997    return bsav;
998}
999
1000static void add_item( Environment *ev, PDFDoc *doc, LuIndexNode *n, GooList *items,
1001                      void *objUtf8, void *objSys )
1002{
1003    if ( items == NULL ) {
1004        return;
1005    }
1006
1007    int len = items->getLength();
1008
1009    for ( int i = 0; i < len; i++ )
1010    {
1011        OutlineItem *item = (OutlineItem *)items->get( i );
1012        LinkAction *link_action = item->getAction();
1013        LuLink evlink;
1014        char *t1 = unicode_to_char( item->getTitle(), item->getTitleLength() );
1015        char *t2 = newstrFromUTF8( t1, objUtf8, objSys );
1016        build_link( doc, &evlink, t2, link_action );
1017        delete t2;
1018        delete t1;
1019        LuIndexNode *cn = new LuIndexNode( ev, &evlink );
1020        n->addChild( ev, cn );
1021
1022        item->open();
1023        if ( item->hasKids() )
1024        {
1025            GooList *citems = item->getKids();
1026            add_item( ev, doc, cn, citems, objUtf8, objSys );
1027        }
1028    }
1029}
1030
1031SOM_Scope LuIndexNode*  SOMLINK getIndex(LuPopplerDocument *somSelf,
1032                                          Environment *ev)
1033{
1034    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1035    PopplerDocument *document = (PopplerDocument *)somThis->data;
1036    PDFDoc *doc = document->doc;
1037
1038    Outline *outline = doc->getOutline();
1039    if ( outline == NULL ) {
1040        return NULL;
1041    }
1042
1043    GooList *items = outline->getItems();
1044    if ( items == NULL ) {
1045        return NULL;
1046    }
1047
1048    LuIndexNode *root = new LuIndexNode( ev, NULL );
1049    add_item( ev, doc, root, items, document->objUtf8, document->objSys );
1050
1051    return root;
1052}
1053
1054
1055static bool has_unicode_marker( GooString *string )
1056{
1057    return ( ( (string->getChar(0) & 0xff) == 0xfe ) &&
1058             ( (string->getChar(1) & 0xff) == 0xff ) );
1059}
1060
1061// return SOMMalloc'ed string
1062static char *propcnv( GooString *s, void *objUniBe, void *objSys )
1063{
1064    if ( has_unicode_marker( s ) )
1065    {
1066        size_t cSubs = 0;
1067        size_t unilen = s->getLength() + 1;
1068        UniChar *unibuf = new UniChar[ unilen ];
1069        memset( unibuf, 0, unilen * sizeof( UniChar ) );
1070        UniChar *tmpuni = unibuf;
1071        const char *from = s->getCString() + 2;
1072        size_t fromlen = s->getLength() - 2;
1073        UniUconvToUcs( objUniBe, (void **)&from, &fromlen, &tmpuni, &unilen, &cSubs );
1074        unilen = UniStrlen( unibuf );
1075
1076        int liglen = uniLigaturesLength( unibuf );
1077        if ( liglen > 0 )  // string contain ligature(s)
1078        {
1079            unsigned ulen_tmp = ( unilen + liglen + 1 ) * sizeof( UniChar );
1080            char *uni_tmp = new char[ ulen_tmp ];
1081            uniReplaceLigatures( unibuf, (UniChar *)uni_tmp );
1082            delete unibuf;
1083            unibuf = (UniChar *)uni_tmp;
1084            unilen = UniStrlen( unibuf );
1085        }
1086        uniConvertSpChars( unibuf );
1087
1088        size_t blen = ( unilen + 1 ) * 2;
1089        char *b = (char *)SOMMalloc( blen );
1090        memset( b, 0, blen );
1091        char *bsav = b;
1092        tmpuni = unibuf;
1093        cSubs = 0;
1094        UniUconvFromUcs( objSys, &tmpuni, &unilen, (void **)&b, &blen, &cSubs );
1095        delete unibuf;
1096        return bsav;
1097    }
1098
1099    return somstrdup( s->getCString() );
1100}
1101
1102static time_t propToDate( const char *date_string )
1103{
1104    int year, mon, day, hour, min, sec;
1105    int scanned_items;
1106
1107    // See PDF Reference 1.3, Section 3.8.2 for PDF Date representation
1108    if ( ( date_string[0] == 'D' ) && ( date_string[1] == ':' ) ) {
1109        date_string += 2;
1110    }
1111
1112    // FIXME only year is mandatory; parse optional timezone offset
1113    scanned_items = sscanf( date_string, "%4d%2d%2d%2d%2d%2d",
1114                            &year, &mon, &day, &hour, &min, &sec);
1115
1116    if ( scanned_items != 6 ) {
1117        return (time_t)(-1);
1118    }
1119
1120    // Workaround for y2k bug in Distiller 3, hoping that it won't
1121    // be used after y2.2k
1122    if ( ( year < 1930 ) && ( strlen( date_string ) > 14 ) )
1123    {
1124        int century, years_since_1900;
1125        scanned_items = sscanf( date_string, "%2d%3d%2d%2d%2d%2d%2d",
1126                &century, &years_since_1900, &mon, &day, &hour, &min, &sec );
1127
1128        if ( scanned_items != 7 ) {
1129            return (time_t)(-1);
1130        }
1131
1132        year = century * 100 + years_since_1900;
1133    }
1134
1135    struct tm time = { 0 };
1136    time.tm_year  = year - 1900;
1137    time.tm_mon   = mon - 1;
1138    time.tm_mday  = day;
1139    time.tm_hour  = hour;
1140    time.tm_min   = min;
1141    time.tm_sec   = sec;
1142    time.tm_wday  = -1;
1143    time.tm_yday  = -1;
1144    time.tm_isdst = -1; // 0 = DST off, 1 = DST on, -1 = don't know
1145
1146    return mktime( &time );
1147}
1148
1149static long convPageMode( Catalog::PageMode pageMode )
1150{
1151    switch ( pageMode )
1152    {
1153        case Catalog::pageModeThumbs:
1154            return LU_DOCUMENT_MODE_USE_THUMBS;
1155        case Catalog::pageModeFullScreen:
1156            return LU_DOCUMENT_MODE_FULL_SCREEN;
1157        case Catalog::pageModeOC:
1158            return LU_DOCUMENT_MODE_USE_OC;
1159        case Catalog::pageModeAttach:
1160            return LU_DOCUMENT_MODE_USE_ATTACHMENTS;
1161        case Catalog::pageModeNone:
1162            return LU_DOCUMENT_MODE_NONE;
1163    }
1164
1165    return -1;
1166}
1167
1168static long convLayout( Catalog::PageLayout pageLayout )
1169{
1170    switch ( pageLayout )
1171    {
1172        case Catalog::pageLayoutSinglePage:
1173            return LU_DOCUMENT_LAYOUT_SINGLE_PAGE;
1174        case Catalog::pageLayoutOneColumn:
1175            return LU_DOCUMENT_LAYOUT_ONE_COLUMN;
1176        case Catalog::pageLayoutTwoColumnLeft:
1177            return LU_DOCUMENT_LAYOUT_TWO_COLUMN_LEFT;
1178        case Catalog::pageLayoutTwoColumnRight:
1179            return LU_DOCUMENT_LAYOUT_TWO_COLUMN_RIGHT;
1180        case Catalog::pageLayoutTwoPageLeft:
1181            return LU_DOCUMENT_LAYOUT_TWO_PAGE_LEFT;
1182        case Catalog::pageLayoutTwoPageRight:
1183            return LU_DOCUMENT_LAYOUT_TWO_PAGE_RIGHT;
1184    }
1185    return -1;
1186}
1187
1188SOM_Scope LuDocumentInfo*  SOMLINK getDocumentInfo(LuPopplerDocument *somSelf,
1189                                                    Environment *ev)
1190{
1191    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1192    PopplerDocument *document = (PopplerDocument *)somThis->data;
1193    PDFDoc *doc = document->doc;
1194
1195    LuDocumentInfo *info = (LuDocumentInfo *)SOMMalloc( sizeof( LuDocumentInfo ) );
1196    memset( info, 0, sizeof( LuDocumentInfo ) );
1197
1198    Object objdict;
1199    doc->getDocInfo( &objdict );
1200    if ( objdict.isDict() )
1201    {
1202        Dict *d = objdict.getDict();
1203        Object obj;
1204
1205        if ( d->lookup( "Title", &obj )->isString() ) {
1206            info->title = propcnv( obj.getString(), document->objUniBe, document->objSys );
1207            info->fields_mask |= LU_DOCUMENT_INFO_TITLE;
1208        }
1209        obj.free();
1210        if ( d->lookup( "Author", &obj )->isString() ) {
1211            info->author = propcnv( obj.getString(), document->objUniBe, document->objSys );
1212            info->fields_mask |= LU_DOCUMENT_INFO_AUTHOR;
1213        }
1214        obj.free();
1215        if ( d->lookup( "Subject", &obj )->isString() ) {
1216            info->subject = propcnv( obj.getString(), document->objUniBe, document->objSys );
1217            info->fields_mask |= LU_DOCUMENT_INFO_SUBJECT;
1218        }
1219        obj.free();
1220        if ( d->lookup( "Keywords", &obj )->isString() ) {
1221            info->keywords = propcnv( obj.getString(), document->objUniBe, document->objSys );
1222            info->fields_mask |= LU_DOCUMENT_INFO_KEYWORDS;
1223        }
1224        obj.free();
1225        if ( d->lookup( "Creator", &obj )->isString() ) {
1226            info->creator = propcnv( obj.getString(), document->objUniBe, document->objSys );
1227            info->fields_mask |= LU_DOCUMENT_INFO_CREATOR;
1228        }
1229        obj.free();
1230        if ( d->lookup( "Producer", &obj )->isString() ) {
1231            info->producer = propcnv( obj.getString(), document->objUniBe, document->objSys );
1232            info->fields_mask |= LU_DOCUMENT_INFO_PRODUCER;
1233        }
1234        obj.free();
1235        if ( d->lookup( "CreationDate", &obj )->isString() ) {
1236            char *d = propcnv( obj.getString(), document->objUniBe, document->objSys );
1237            info->creation_date = propToDate( d );
1238            if ( (long)info->creation_date != -1 ) {
1239                info->fields_mask |= LU_DOCUMENT_INFO_CREATION_DATE;
1240            }
1241            SOMFree( d );
1242        }
1243        obj.free();
1244        if ( d->lookup( "ModDate", &obj )->isString() ) {
1245            char *d = propcnv( obj.getString(), document->objUniBe, document->objSys );
1246            info->modified_date = propToDate( d );
1247            if ( (long)info->modified_date != -1 ) {
1248                info->fields_mask |= LU_DOCUMENT_INFO_MOD_DATE;
1249            }
1250            SOMFree( d );
1251        }
1252        obj.free();
1253    }
1254
1255    char *format = (char *)SOMMalloc( 16 );
1256    snprintf( format, 16, "PDF-%.2f", doc->getPDFVersion() );
1257    info->format = format;
1258    info->fields_mask |= LU_DOCUMENT_INFO_FORMAT;
1259
1260    info->linearized = doc->isLinearized();
1261    info->fields_mask |= LU_DOCUMENT_INFO_LINEARIZED;
1262
1263    Catalog *catalog = doc->getCatalog();
1264
1265    if ( ( catalog != NULL ) && catalog->isOk() )
1266    {
1267        info->layout = convLayout( catalog->getPageLayout() );
1268        if ( info->layout != -1 ) {
1269            info->fields_mask |= LU_DOCUMENT_INFO_LAYOUT;
1270        }
1271
1272        info->mode = convPageMode( catalog->getPageMode() );
1273        if ( info->mode != -1 ) {
1274            info->fields_mask |= LU_DOCUMENT_INFO_START_MODE;
1275        }
1276    }
1277
1278    info->fields_mask |= LU_DOCUMENT_INFO_PERMISSIONS;
1279    if ( doc->okToPrint() ) {
1280        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_PRINT;
1281    }
1282    if ( doc->okToChange() ) {
1283        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_MODIFY;
1284    }
1285    if ( doc->okToCopy() ) {
1286        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_COPY;
1287    }
1288    if ( doc->okToAddNotes() ) {
1289        info->permissions |= LU_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES;
1290    }
1291
1292    info->n_pages = doc->getNumPages();
1293    info->fields_mask |= LU_DOCUMENT_INFO_N_PAGES;
1294
1295    return info;
1296}
1297
1298
1299SOM_Scope boolean  SOMLINK getThumbnailSize(LuPopplerDocument *somSelf,
1300                                             Environment *ev,
1301                                            long pagenum,
1302                                            short suggested_width,
1303                                            short* width, short* height)
1304{
1305    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1306    Page *page = ((PopplerDocument *)somThis->data)->pages[ pagenum ].page;
1307
1308    Object thumb;
1309    Dict *dict;
1310    boolean retval = FALSE;
1311
1312    page->getThumb( &thumb );
1313    if ( thumb.isNull() )
1314    {
1315        thumb.free();
1316        return FALSE;
1317    }
1318
1319    dict = thumb.streamGetDict();
1320
1321    // Theoretically, this could succeed and you would still fail when
1322    // loading the thumb
1323    int w = 0, h = 0;
1324    if ( dict->lookupInt( "Width", "W", &w ) && dict->lookupInt( "Height", "H", &h ) )
1325    {
1326        if ( width != NULL ) {
1327            *width = w;
1328        }
1329        if ( height != NULL ) {
1330            *height = h;
1331        }
1332
1333        retval = TRUE;
1334    }
1335
1336    thumb.free();
1337
1338    return retval;
1339}
1340
1341SOM_Scope LuPixbuf*  SOMLINK getThumbnail(LuPopplerDocument *somSelf,
1342                                           Environment *ev, long pagenum,
1343                                          short suggested_width)
1344{
1345    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1346    Page *page = ((PopplerDocument *)somThis->data)->pages[ pagenum ].page;
1347
1348    unsigned char *data;
1349    int width, height, rowstride;
1350
1351    if ( !page->loadThumb( &data, &width, &height, &rowstride ) ) {
1352        return NULL;
1353    }
1354
1355    short bpp = getBpp( somSelf, ev );
1356    LuPixbuf *pixbuf = new LuPixbuf( ev, width, height, bpp );
1357    char *pixbuf_data = (char *)pixbuf->getDataPtr( ev );
1358    int pixbuf_rowstride = pixbuf->getRowSize( ev );
1359    char *src, *dst;
1360    int i, j;
1361    for ( i = 0, j = ( height - 1 ); i < height; i++, j-- )
1362    {
1363        src = (char*)(data + ( j * rowstride ));
1364        dst = pixbuf_data + (i * pixbuf_rowstride);
1365        for ( int k = 0; k < pixbuf_rowstride; k += bpp )
1366        {
1367            dst[ k ]     = src[ k + 2 ];
1368            dst[ k + 1 ] = src[ k + 1 ];
1369            dst[ k + 2 ] = src[ k ];
1370        }
1371    }
1372    gfree( data );
1373
1374    return pixbuf;
1375}
1376
1377
1378SOM_Scope LuDocument_LuRectSequence*  SOMLINK searchText(LuPopplerDocument *somSelf,
1379                                                          Environment *ev,
1380                                                         long pagenum,
1381                                                         string text,
1382                                                         boolean caseSensitive)
1383{
1384    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
1385    PopplerDocument *document = (PopplerDocument *)somThis->data;
1386    Page *page = document->pages[ pagenum ].page;
1387
1388    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
1389    TextOutputDev *output_dev = new TextOutputDev( NULL, gTrue, gFalse, gFalse );
1390    page->display( output_dev, 72, 72, 0, gFalse,
1391                   gTrue, NULL, document->doc->getCatalog() );
1392    DosReleaseMutexSem( document->mutex );
1393
1394
1395    // Convert string from system encoding to UCS-4
1396    // first, convert to UCS-2
1397    size_t cSubs = 0;
1398    size_t text_len = strlen( text );
1399    size_t text_len_sav = text_len;
1400    size_t ucs2_len = ( text_len + 1 ) * 2;
1401    char *ucs2 = new char[ ucs2_len ];
1402    memset( ucs2, 0, ucs2_len );
1403    char *ucs2sav = ucs2;
1404    UniUconvToUcs( document->objSys, (void **)&text, &text_len,
1405                   (UniChar **)&ucs2, &ucs2_len, &cSubs );
1406    // second, convert UCS-2 to UCS-4
1407    short *uucs2 = (short *)ucs2sav;
1408    unsigned ucs4_len = ( text_len_sav + 1 ) * 2;
1409    unsigned *ucs4 = new unsigned[ ucs4_len ];
1410    memset( ucs4, 0, ucs4_len * sizeof( unsigned ) );
1411    int real_ucs4_len = 0;
1412    for ( real_ucs4_len = 0; *uucs2; real_ucs4_len++ ) {
1413        ucs4[ real_ucs4_len ] = *uucs2++;
1414    }
1415    delete ucs2sav;
1416    // conversion end
1417
1418    RectList *rl = new RectList;
1419    double xMin, yMin, xMax, yMax;
1420    xMin = 0;
1421    yMin = 0;
1422    while ( output_dev->findText( ucs4, real_ucs4_len,
1423                   gFalse, gTrue, // startAtTop, stopAtBottom
1424                   gTrue, gFalse, // startAtLast, stopAtLast
1425                   caseSensitive, gFalse, // caseSensitive, backwards
1426                   &xMin, &yMin, &xMax, &yMax ) )
1427    {
1428        LuRectangle r;
1429        r.x1 = xMin;
1430        r.y1 = yMin;
1431        r.x2 = xMax;
1432        r.y2 = yMax;
1433        rl->push_back( r );
1434    }
1435    delete ucs4;
1436    delete output_dev;
1437
1438    LuDocument_LuRectSequence *rectangles = NULL;
1439    int len = rl->size();
1440    if ( len > 0 )
1441    {
1442        rectangles = (LuDocument_LuRectSequence *)SOMMalloc( sizeof( LuDocument_LuRectSequence ) );
1443        rectangles->_maximum = len;
1444        rectangles->_length = len;
1445        rectangles->_buffer = (LuRectangle *)SOMMalloc( sizeof( LuRectangle ) * len );
1446
1447        for ( int i = 0; i < len; i++ )
1448        {
1449            rectangles->_buffer[ i ].x1 = (*rl)[i].x1;
1450            rectangles->_buffer[ i ].y1 = (*rl)[i].y1;
1451            rectangles->_buffer[ i ].x2 = (*rl)[i].x2;
1452            rectangles->_buffer[ i ].y2 = (*rl)[i].y2;
1453        }
1454    }
1455    delete rl;
1456
1457    return rectangles;
1458}
1459
1460
1461SOM_Scope boolean  SOMLINK isFixedImage(LuPopplerDocument *somSelf,
1462                                         Environment *ev)
1463{
1464    return FALSE;
1465}
1466
1467
1468SOM_Scope boolean  SOMLINK isCreateFileThumbnail(LuPopplerDocument *somSelf,
1469                                                  Environment *ev)
1470{
1471    return TRUE;
1472}
1473
1474
1475SOM_Scope void SOMLINK somDefaultInit(LuPopplerDocument *somSelf,
1476                                      som3InitCtrl* ctrl)
1477{
1478    // generated section - do not modify
1479    LuPopplerDocumentData *somThis;
1480    somInitCtrl globalCtrl;
1481    somBooleanVector myMask;
1482    LuPopplerDocument_BeginInitializer_somDefaultInit;
1483    LuPopplerDocument_Init_LuDocument_somDefaultInit(somSelf, ctrl);
1484    // end of generated section
1485
1486    // local LuPopplerDocument initialization code
1487    PopplerDocument *d = new PopplerDocument;
1488    somThis->data = d;
1489}
1490
1491
1492static void set_error( char **error, const char *fmt, ... )
1493{
1494    if ( error == NULL ) {
1495        return;
1496    }
1497
1498    va_list argptr;
1499    va_start( argptr, fmt );
1500    char *msg = new char[ 1000 ];
1501    vsnprintf( msg, 1000, fmt, argptr );
1502    *error = somstrdup( msg );
1503    delete msg;
1504}
1505
1506
1507SOM_Scope boolean  SOMLINK loadFile(LuPopplerDocument *somSelf,
1508                                     Environment *ev, string filename,
1509                                    string password, long* errorCode,
1510                                    string* error)
1511{
1512    if ( errorCode != NULL ) {
1513        *errorCode = LU_LDERR_NO_ERROR;
1514    }
1515
1516    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData( somSelf );
1517
1518    PDFDoc *newDoc;
1519    GooString *filename_g;
1520    GooString *password_g;
1521    int err;
1522
1523    if ( !globalParams ) {
1524        globalParams = new GlobalParams();
1525    }
1526
1527    filename_g = new GooString(filename);
1528
1529    password_g = NULL;
1530    if (password != NULL) {
1531        password_g = new GooString(password);
1532    }
1533
1534    newDoc = new PDFDoc(filename_g, password_g, password_g);
1535    if (password_g) {
1536        delete password_g;
1537    }
1538
1539    if (!newDoc->isOk()) {
1540        err = newDoc->getErrorCode();
1541        delete newDoc;
1542
1543        if ( errorCode != NULL )
1544        {
1545            switch ( err )
1546            {
1547                case errOpenFile:
1548                    *errorCode = LU_LDERR_OPEN_ERROR;
1549                    break;
1550                case errBadCatalog:
1551                case errDamaged:
1552                    *errorCode = LU_LDERR_DAMAGED;
1553                    break;
1554                case errEncrypted:
1555                    *errorCode = LU_LDERR_ENCRYPTED;
1556                    break;
1557                case errFileIO:
1558                    *errorCode = LU_LDERR_READ_ERROR;
1559                    break;
1560                default:
1561                    *errorCode = LU_LDERR_CUSTOM;
1562                    set_error( error, "(error %d)", err );
1563                    break;
1564            }
1565        }
1566
1567        return FALSE;
1568    }
1569
1570    PopplerDocument *document = (PopplerDocument *)somThis->data;
1571
1572    document->doc = newDoc;
1573    SplashColor white;
1574    white[0] = 255;
1575    white[1] = 255;
1576    white[2] = 255;
1577    document->output_dev = new SplashOutputDev( splashModeXBGR8, 4, gFalse, white );
1578    document->output_dev->startDoc( document->doc->getXRef() );
1579
1580    long numpages = document->doc->getNumPages();
1581    document->pages = new PopplerPage[ numpages ];
1582    for ( long pagenum = 0; pagenum < numpages; pagenum++ ) {
1583        document->pages[ pagenum ].page =
1584            document->doc->getCatalog()->getPage( pagenum + 1 );
1585    }
1586
1587    return TRUE;
1588}
1589
1590
1591SOM_Scope void SOMLINK somDestruct(LuPopplerDocument *somSelf,
1592                                   octet doFree, som3DestructCtrl* ctrl)
1593{
1594    LuPopplerDocumentData *somThis;
1595    somDestructCtrl globalCtrl;
1596    somBooleanVector myMask;
1597    LuPopplerDocument_BeginDestructor;
1598
1599    // local LuPopplerDocument deinitialization code
1600    PopplerDocument *document = (PopplerDocument *)somThis->data;
1601    delete document;
1602    // end of local LuPopplerDocument deinitialization code
1603
1604    LuPopplerDocument_EndDestructor;
1605}
1606
1607
Note: See TracBrowser for help on using the repository browser.