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

Last change on this file since 227 was 227, checked in by Eugene Romanenko, 14 years ago

comment

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