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

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 16 years ago

First import

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