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

Last change on this file since 95 was 95, checked in by Eugene Romanenko, 15 years ago

more comments, new method isFixedImage(), fixed keyboard selection of printer in printer dialog

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