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

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

Writes into EA thumbnail of first page of document

File size: 42.8 KB
Line 
1
2/*
3 *  This file was generated by the SOM Compiler.
4 *  Generated using:
5 *     SOM incremental update: 2.24
6 */
7
8
9/*
10 * Copyright (c) 2006, Eugene Romanenko, netlabs.org
11 *
12 *----------------------------------------------------------------------
13 * This file is part of poppler plugin for Lucide (lupoppler).
14 *
15 *  lupoppler is free software; you can redistribute it and/or modify
16 *  it under the terms of the GNU General Public License as published by
17 *  the Free Software Foundation; either version 2 of the License, or
18 *  (at your option) any later version.
19 *
20 *  lupoppler is distributed in the hope that it will be useful,
21 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 *  GNU General Public License for more details.
24 *----------------------------------------------------------------------
25 */
26
27/*
28 *  This file was generated by the SOM Compiler and Emitter Framework.
29 *  Generated using template emitter:
30 *      SOM Emitter emitxtm: 2.23.1.9
31 */
32
33#ifndef SOM_Module_lupoppler_Source
34#define SOM_Module_lupoppler_Source
35#endif
36#define LuPopplerDocument_Class_Source
37
38#include "lupoppler.xih"
39
40#include <goo\GooString.h>
41#include <goo\GooList.h>
42#include <splash\SplashBitmap.h>
43#include <UGooString.h>
44#include <GlobalParams.h>
45#include <ErrorCodes.h>
46#include <PDFDoc.h>
47#include <SplashOutputDev.h>
48#include <TextOutputDev.h>
49#include <PSOutputDev.h>
50#include <FontInfo.h>
51#include <Outline.h>
52#include <UnicodeMap.h>
53#include <Gfx.h>
54#include <Link.h>
55
56#define INCL_DOS
57#include <os2.h>
58
59#include <vector>
60using namespace std;
61#include <time.h>
62#include "cpconv.h"
63
64typedef vector<LuRectangle> RectList;
65
66
67unsigned _System 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 * _System createObject()
79{
80    return new LuPopplerDocument;
81}
82
83extern "C" char * _System getSupportedExtensions()
84{
85    return "PDF";
86}
87
88extern "C" char * _System getDescription()
89{
90    return "PDF plugin, based on poppler library v0.5.4";
91}
92
93
94class PopplerPage
95{
96    public:
97
98        Page *page;
99        TextOutputDev *text_dev;
100        Gfx *gfx;
101
102        PopplerPage();
103        ~PopplerPage();
104};
105
106PopplerPage::PopplerPage()
107{
108    page = NULL;
109    text_dev = NULL;
110    gfx = NULL;
111}
112
113PopplerPage::~PopplerPage()
114{
115    delete text_dev;
116    delete gfx;
117}
118
119
120class PopplerDocument
121{
122    public:
123
124        PDFDoc *doc;
125        SplashOutputDev *output_dev;
126        PopplerPage *pages;
127        char *text;
128        HMTX mutex;
129
130        PopplerDocument();
131        ~PopplerDocument();
132};
133
134PopplerDocument::PopplerDocument()
135{
136    doc        = NULL;
137    output_dev = NULL;
138    pages      = NULL;
139    text       = NULL;
140    mutex      = NULLHANDLE;
141    DosCreateMutexSem( NULL, &mutex, 0, FALSE );
142}
143
144PopplerDocument::~PopplerDocument()
145{
146    delete [] pages;
147    delete doc;
148    delete output_dev;
149    delete text;
150    DosCloseMutexSem( mutex );
151}
152
153
154static char *newstrdup( const char *s )
155{
156    if ( s == NULL ) {
157        return NULL;
158    }
159    char *temp = new char[ strlen( s ) + 1 ];
160    strcpy( temp, s );
161    return temp;
162}
163
164static char *somstrdup( const char *s )
165{
166    if ( s == NULL ) {
167        return NULL;
168    }
169    char *temp = (char *)SOMMalloc( strlen( s ) + 1 );
170    strcpy( temp, s );
171    return temp;
172}
173
174
175SOM_Scope short  SOMLINK getBpp(LuPopplerDocument *somSelf,  Environment *ev)
176{
177    return 3;
178}
179
180SOM_Scope boolean  SOMLINK isScalable(LuPopplerDocument *somSelf,
181                                       Environment *ev)
182{
183    return TRUE;
184}
185
186
187SOM_Scope boolean  SOMLINK isRotable(LuPopplerDocument *somSelf,
188                                      Environment *ev)
189{
190    return TRUE;
191}
192
193
194SOM_Scope long  SOMLINK getPageCount(LuPopplerDocument *somSelf,
195                                      Environment *ev)
196{
197    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
198    return ((PopplerDocument *)somThis->data)->doc->getNumPages();
199}
200
201
202SOM_Scope void  SOMLINK getPageSize(LuPopplerDocument *somSelf,
203                                    Environment *ev, long pagenum,
204                                    double* width, double* height)
205{
206    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
207
208    Page *page = ((PopplerDocument *)somThis->data)->pages[ pagenum ].page;
209
210    double page_width, page_height;
211    int rotate = page->getRotate();
212    if ( rotate == 90 || rotate == 270 ) {
213        page_height = page->getCropWidth();
214        page_width = page->getCropHeight();
215    } else {
216        page_width = page->getCropWidth();
217        page_height = page->getCropHeight();
218    }
219
220    if ( width != NULL ) {
221        *width = page_width;
222    }
223    if ( height != NULL ) {
224        *height = page_height;
225    }
226}
227
228
229static void copy_page_to_pixbuf( Environment *ev, SplashBitmap *bitmap, LuPixbuf *pixbuf )
230{
231    int splash_width, splash_height, splash_rowstride;
232    int pixbuf_rowstride, pixbuf_height, pixbuf_width;
233    int height, width, rowstride;
234    char *pixbuf_data, *dst, *src;
235
236    SplashColorPtr color_ptr = bitmap->getDataPtr();
237
238    splash_width = bitmap->getWidth();
239    splash_height = bitmap->getHeight();
240    splash_rowstride = bitmap->getRowSize();
241
242    //somPrintf( "splash_width: %d   splash_height: %d   splash_rowstride: %d\n",
243    //            splash_width, splash_height, splash_rowstride );
244
245    pixbuf_data = (char *)pixbuf->getDataPtr( ev );
246    pixbuf_width = pixbuf->getWidth( ev );
247    pixbuf_height = pixbuf->getHeight( ev );
248    pixbuf_rowstride = pixbuf->getRowSize( ev );
249
250    width = __min( splash_width, pixbuf_width );
251    height = __min( splash_height, pixbuf_height );
252    rowstride = __min( splash_rowstride, pixbuf_rowstride );
253
254    int i, j;
255    for ( i = 0, j = ( height - 1 ); i < height; i++, j-- )
256    {
257        dst = pixbuf_data + i * pixbuf_rowstride;
258        src = ((char *)color_ptr) + j * splash_rowstride;
259        memcpy( dst, src, rowstride );
260    }
261
262    // test
263    //memcpy( pixbuf_data, color_ptr, pixbuf->getDataLen( ev ) );
264}
265
266
267SOM_Scope void  SOMLINK renderPageToPixbuf(LuPopplerDocument *somSelf,
268                                            Environment *ev,
269                                           long pagenum, long src_x,
270                                           long src_y, long src_width,
271                                           long src_height, double scale,
272                                           long rotation, LuPixbuf* pixbuf)
273{
274    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
275    PopplerDocument *document = (PopplerDocument *)somThis->data;
276    Page *page = document->pages[ pagenum ].page;
277
278    if ( ( scale < 0.0 ) || ( pixbuf == NULL ) ) {
279        return;
280    }
281
282    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
283
284    page->displaySlice( document->output_dev,
285                72.0 * scale, 72.0 * scale,
286                rotation,
287                gFalse, /* useMediaBox */
288                gTrue, /* Crop */
289                src_x, src_y,
290                src_width, src_height,
291                NULL, /* links */
292                document->doc->getCatalog() );
293
294    DosReleaseMutexSem( document->mutex );
295
296    copy_page_to_pixbuf( ev, document->output_dev->getBitmap(), pixbuf );
297}
298
299
300SOM_Scope boolean  SOMLINK isAsynchRenderingSupported(LuPopplerDocument *somSelf,
301                                                       Environment *ev)
302{
303    return TRUE;
304}
305
306
307struct asynchCallbackData
308{
309    Environment      *ev;
310    LuPixbuf         *pixbuf;
311    SplashOutputDev  *out;
312    void             *fndata;
313    _asynchCallbackFn fnd;
314    _asynchCallbackFn fna;
315    long              tmr;
316    bool              forceDraw;
317    long              delay;
318};
319
320static GBool abortCheckCbk( void *data )
321{
322    long now;
323    asynchCallbackData *cd = (asynchCallbackData *)data;
324    DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &now, sizeof( long ) );
325    long dist = ( now - cd->tmr );
326    if ( ( dist > cd->delay ) || cd->forceDraw )
327    {
328        // Note: we use out->getBitmap() on each iteration instead
329        //       of remembering pointer to bitmap before call
330        //       page->displaySlice() because OutputDev may change
331        //       bitmap during page->displaySlice() processing.
332        copy_page_to_pixbuf( cd->ev, cd->out->getBitmap(), cd->pixbuf );
333        cd->fnd( cd->fndata );
334        cd->tmr = now;
335        cd->delay += 100;
336    }
337    return (GBool)cd->fna( cd->fndata );
338}
339
340SOM_Scope void  SOMLINK renderPageToPixbufAsynch(LuPopplerDocument *somSelf,
341                                                  Environment *ev,
342                                                 long pagenum,
343                                                 long src_x,
344                                                 long src_y,
345                                                 long src_width,
346                                                 long src_height,
347                                                 double scale,
348                                                 long rotation,
349                                                 LuPixbuf* pixbuf,
350                                                 LuDocument_asynchCallbackFn fnd,
351                                                 LuDocument_asynchCallbackFn fna,
352                                                 somToken fndata)
353{
354    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
355    PopplerDocument *document = (PopplerDocument *)somThis->data;
356    Page *page = document->pages[ pagenum ].page;
357
358    if ( ( scale < 0.0 ) || ( pixbuf == NULL ) ) {
359        return;
360    }
361
362    asynchCallbackData acd;
363    acd.ev        = ev;
364    acd.pixbuf    = pixbuf;
365    acd.out       = document->output_dev;
366    acd.fndata    = fndata;
367    acd.fnd       = (_asynchCallbackFn)fnd;
368    acd.fna       = (_asynchCallbackFn)fna;
369    acd.forceDraw = false;
370    acd.delay     = 200;
371    DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &acd.tmr, sizeof( long ) );
372
373    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
374
375    //somPrintf( "src_x: %d, src_y: %d, src_width: %d, src_height: %d\n",
376    //           src_x, src_y, src_width, src_height );
377
378    page->displaySlice( document->output_dev,
379                72.0 * scale, 72.0 * scale,
380                rotation,
381                gFalse, /* useMediaBox */
382                gTrue, /* Crop */
383                src_x, src_y,
384                src_width, src_height,
385                NULL, /* links */
386                document->doc->getCatalog(),
387                abortCheckCbk, &acd );
388    DosReleaseMutexSem( document->mutex );
389
390    acd.forceDraw = true;
391    abortCheckCbk( &acd );
392}
393
394static TextOutputDev *get_text_output_dev( PopplerPage *page,
395                                           PopplerDocument *document )
396{
397    if ( page->text_dev == NULL )
398    {
399        DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
400        page->text_dev = new TextOutputDev( NULL, gTrue, gFalse, gFalse );
401
402        page->gfx = page->page->createGfx(page->text_dev,
403                          72.0, 72.0, 0,
404                          gFalse, /* useMediaBox */
405                          gTrue, /* Crop */
406                          -1, -1, -1, -1,
407                          NULL, /* links */
408                          document->doc->getCatalog(),
409                          NULL, NULL, NULL, NULL);
410
411        page->page->display( page->gfx );
412        page->text_dev->endPage();
413        DosReleaseMutexSem( document->mutex );
414    }
415
416    return page->text_dev;
417}
418
419
420SOM_Scope LuDocument_LuRectSequence*  SOMLINK getSelectionRectangles(LuPopplerDocument *somSelf,
421                                                                    Environment *ev,
422                                                                   long pagenum,
423                                                                   LuRectangle* selection)
424{
425    LuDocument_LuRectSequence *rectangles = NULL;
426
427    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
428    PopplerDocument *document = (PopplerDocument *)somThis->data;
429    PopplerPage *page = &( document->pages[ pagenum ] );
430
431    TextOutputDev *text_dev = get_text_output_dev( page, document );
432
433    PDFRectangle poppler_selection;
434    poppler_selection.x1 = selection->x1;
435    poppler_selection.y1 = selection->y1;
436    poppler_selection.x2 = selection->x2;
437    poppler_selection.y2 = selection->y2;
438
439    GooList *list = text_dev->getSelectionRegion( &poppler_selection, 1.0 );
440    int len = list->getLength();
441
442    if ( len > 0 )
443    {
444        rectangles = (LuDocument_LuRectSequence *)SOMMalloc( sizeof( LuDocument_LuRectSequence ) );
445        rectangles->_maximum = len;
446        rectangles->_length = len;
447        rectangles->_buffer = (LuRectangle *)SOMMalloc( sizeof( LuRectangle ) * len );
448
449        for ( int i = 0; i < len; i++ )
450        {
451            PDFRectangle *selection_rect = (PDFRectangle *)list->get( i );
452            rectangles->_buffer[ i ].x1 = selection_rect->x1;
453            rectangles->_buffer[ i ].y1 = selection_rect->y1;
454            rectangles->_buffer[ i ].x2 = selection_rect->x2;
455            rectangles->_buffer[ i ].y2 = selection_rect->y2;
456            delete selection_rect;
457        }
458    }
459    delete list;
460
461    return rectangles;
462}
463
464
465SOM_Scope boolean  SOMLINK isHaveText(LuPopplerDocument *somSelf,
466                                      Environment *ev)
467{
468    return TRUE;
469}
470
471
472SOM_Scope string  SOMLINK getText(LuPopplerDocument *somSelf,
473                                   Environment *ev, long pagenum,
474                                  LuRectangle* selection)
475{
476    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
477
478    if ( selection == NULL ) {
479        return NULL;
480    }
481
482    PopplerDocument *document = (PopplerDocument *)somThis->data;
483    PopplerPage *page = &( document->pages[ pagenum ] );
484
485    TextOutputDev *text_dev = get_text_output_dev( page, document );
486
487    GooString *sel_text = new GooString;
488    char *result;
489    PDFRectangle pdf_selection;
490
491    pdf_selection.x1 = selection->x1;
492    pdf_selection.y1 = selection->y1;
493    pdf_selection.x2 = selection->x2;
494    pdf_selection.y2 = selection->y2;
495
496    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
497    sel_text = text_dev->getSelectionText( &pdf_selection );
498
499    delete document->text;
500    document->text = newstrdup( sel_text->getCString() );
501    delete sel_text;
502    DosReleaseMutexSem( document->mutex );
503
504    return document->text;
505}
506
507
508SOM_Scope boolean  SOMLINK isHaveLinks(LuPopplerDocument *somSelf,
509                                        Environment *ev)
510{
511    return TRUE;
512}
513
514
515static long find_dest_page( PDFDoc *doc, LinkDest *link_dest )
516{
517    long page_num = 0;
518
519    if ( link_dest == NULL ) {
520        return page_num;
521    }
522
523    if ( link_dest->isPageRef() )
524    {
525        Ref page_ref = link_dest->getPageRef();
526        page_num = doc->findPage( page_ref.num, page_ref.gen ) - 1;
527    }
528    else {
529        page_num = link_dest->getPageNum() - 1;
530    }
531
532    return page_num;
533}
534
535static void build_goto_dest( PDFDoc *doc, LuLink *evlink, LinkGoTo *link )
536{
537    LinkDest *link_dest;
538    UGooString *named_dest;
539
540    if ( !link->isOk() ) {
541        return;
542    }
543
544    link_dest = link->getDest();
545    named_dest = link->getNamedDest();
546
547    if ( link_dest != NULL ) {
548        evlink->page = find_dest_page( doc, link_dest );
549    } else if ( named_dest != NULL ) {
550        link_dest = doc->findDest( named_dest );
551        evlink->page = find_dest_page( doc, link_dest );
552        delete link_dest;
553    } else {
554        evlink->page = 0;
555    }
556}
557
558static void build_link( PDFDoc *doc, LuLink *evlink,
559                        const char *title, LinkAction *link_action )
560{
561    evlink->title = somstrdup( title );
562    evlink->uri = NULL;
563    evlink->type = LU_LINK_TYPE_TITLE;
564    evlink->page = 0;
565
566    if ( link_action == NULL ) {
567        return;
568    }
569
570    switch ( link_action->getKind() )
571    {
572        case actionGoTo:
573            {
574                evlink->type = LU_LINK_TYPE_PAGE;
575                LinkGoTo *lgt = dynamic_cast <LinkGoTo *> (link_action);
576                build_goto_dest( doc, evlink, lgt );
577            }
578            break;
579
580        case actionURI:
581            {
582                evlink->type = LU_LINK_TYPE_EXTERNAL_URI;
583                LinkURI *lu = dynamic_cast <LinkURI *> (link_action);
584                char *uri = lu->getURI()->getCString();
585                if ( uri != NULL ) {
586                    evlink->uri = somstrdup( uri );
587                }
588            }
589            break;
590    }
591}
592
593SOM_Scope LuDocument_LuLinkMapSequence*  SOMLINK getLinkMapping(LuPopplerDocument *somSelf,
594                                                                 Environment *ev,
595                                                                long pagenum)
596{
597    LuDocument_LuLinkMapSequence *mapping = NULL;
598    mapping = (LuDocument_LuLinkMapSequence *)SOMMalloc( sizeof( LuDocument_LuLinkMapSequence ) );
599    mapping->_maximum = 0;
600    mapping->_length = 0;
601    mapping->_buffer = NULL;
602
603    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
604    PopplerDocument *document = (PopplerDocument *)somThis->data;
605    PopplerPage *page = &( document->pages[ pagenum ] );
606
607    Object obj;
608    Links *links = new Links( page->page->getAnnots( &obj ),
609                            document->doc->getCatalog()->getBaseURI() );
610    obj.free();
611
612    if ( links == NULL ) {  // No links, return empty LuLinkMapSequence
613        return mapping;
614    }
615
616    double height = 0;
617    getPageSize( somSelf, ev, pagenum, NULL, &height );
618
619    int len = links->getNumLinks();
620
621    mapping->_maximum = len;
622    mapping->_length = len;
623    if ( len != 0 ) {
624        mapping->_buffer = (LuLinkMapping *)SOMMalloc( sizeof( LuLinkMapping ) * len );
625    }
626
627    for ( int i = 0; i < len; i++ )
628    {
629        Link *link = links->getLink( i );
630        LinkAction *link_action = link->getAction();
631        build_link( document->doc, &(mapping->_buffer[ i ].link), NULL, link_action );
632
633        link->getRect( &(mapping->_buffer[ i ].area.x1),
634                       &(mapping->_buffer[ i ].area.y1),
635                       &(mapping->_buffer[ i ].area.x2),
636                       &(mapping->_buffer[ i ].area.y2) );
637
638        mapping->_buffer[ i ].area.x1 -= page->page->getCropBox()->x1;
639        mapping->_buffer[ i ].area.x2 -= page->page->getCropBox()->x1;
640        mapping->_buffer[ i ].area.y1 -= page->page->getCropBox()->y1;
641        mapping->_buffer[ i ].area.y2 -= page->page->getCropBox()->y1;
642
643        double y1 = mapping->_buffer[ i ].area.y1;
644        double y2 = mapping->_buffer[ i ].area.y2;
645        mapping->_buffer[ i ].area.y1 = height - y2;
646        mapping->_buffer[ i ].area.y2 = height - y1;
647    }
648
649    return mapping;
650}
651
652
653SOM_Scope boolean  SOMLINK isSaveable(LuPopplerDocument *somSelf,
654                                       Environment *ev)
655{
656    return TRUE;
657}
658
659
660SOM_Scope boolean  SOMLINK saveAs(LuPopplerDocument *somSelf,
661                                   Environment *ev, string filename)
662{
663    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
664    PopplerDocument *document = (PopplerDocument *)somThis->data;
665
666    boolean retval = FALSE;
667
668    if ( filename != NULL ) {
669        retval = document->doc->saveAs( new GooString( filename ) );
670    }
671
672    return retval;
673}
674
675
676SOM_Scope boolean  SOMLINK isPostScriptExportable(LuPopplerDocument *somSelf,
677                                           Environment *ev)
678{
679    return TRUE;
680}
681
682
683SOM_Scope boolean SOMLINK exportToPostScript(LuPopplerDocument *somSelf,
684                                    Environment *ev, string filename,
685                                    long first_page, long last_page,
686                                    double width, double height,
687                                    boolean* brkExport)
688{
689    if ( filename == NULL ) {
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(), doc->getCatalog(),
697                                (first_page <= last_page) ? (first_page + 1) : (last_page + 1),
698                                (first_page <= last_page) ? (last_page + 1) : (first_page + 1),
699                                        psModePS, (int)width, (int)height,
700                                        gFalse, 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    long pagestoprint = abs( last_page - first_page ) + 1;
713    long pg = first_page;
714    for ( long i = 0; (i < pagestoprint) && !(*brkExport); i++ ) {
715        doc->displayPage( out, pg + 1, 72.0, 72.0, 0, gFalse, gTrue, gFalse );
716        pg += ( first_page <= last_page ) ? 1 : -1;
717    }
718
719    delete out;
720    return TRUE;
721}
722
723
724SOM_Scope boolean  SOMLINK isHaveFontInfo(LuPopplerDocument *somSelf,
725                                           Environment *ev)
726{
727    return TRUE;
728}
729
730
731SOM_Scope LuDocument_LuFontInfoSequence*  SOMLINK getFontInfo(LuPopplerDocument *somSelf,
732                                                               Environment *ev)
733{
734    LuDocument_LuFontInfoSequence *fonts = NULL;
735
736    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData(somSelf);
737    PopplerDocument *document = (PopplerDocument *)somThis->data;
738    PDFDoc *doc = document->doc;
739
740    DosRequestMutexSem( document->mutex, SEM_INDEFINITE_WAIT );
741    FontInfoScanner *scanner = new FontInfoScanner( doc );
742    GooList *items = scanner->scan( doc->getNumPages() );
743    delete scanner;
744    DosReleaseMutexSem( document->mutex );
745
746    if ( items == NULL ) {
747        return NULL;
748    }
749
750    int len = items->getLength();
751
752    if ( len == 0 ) {
753        delete items;
754        return NULL;
755    }
756
757    fonts = (LuDocument_LuFontInfoSequence *)SOMMalloc( sizeof( LuDocument_LuFontInfoSequence ) );
758    fonts->_maximum = len;
759    fonts->_length = len;
760    fonts->_buffer = (LuFontInfo *)SOMMalloc( sizeof( LuFontInfo ) * len );
761
762    for ( int i = 0; i < len; i++ )
763    {
764        fonts->_buffer[i].name = NULL;
765        fonts->_buffer[i].type = NULL;
766        fonts->_buffer[i].embedded = NULL;
767
768        FontInfo *info = (FontInfo *)items->get( i );
769
770        // name
771        GooString *gnm = info->getName();
772        if ( gnm != NULL )
773        {
774            char *nm = gnm->getCString();
775            if ( info->getSubset() && ( nm != NULL ) )
776            {
777                while ( *nm && ( *nm != '+' ) ) {
778                    nm++;
779                }
780                if ( *nm ) {
781                    nm++;
782                }
783            }
784            if ( nm != NULL ) {
785                if ( *nm ) {
786                    fonts->_buffer[i].name = somstrdup( nm );
787                }
788            }
789        }
790
791        // type
792        char *t = "Unknown font type";
793        switch ( info->getType() )
794        {
795            case FontInfo::Type1:        t = "Type 1";          break;
796            case FontInfo::Type1C:       t = "Type 1C";         break;
797            case FontInfo::Type3:        t = "Type 3";          break;
798            case FontInfo::TrueType:     t = "TrueType";        break;
799            case FontInfo::CIDType0:     t = "Type 1 (CID)";    break;
800            case FontInfo::CIDType0C:    t = "Type 1C (CID)";   break;
801            case FontInfo::CIDTrueType:  t = "TrueType (CID)";  break;
802        }
803        fonts->_buffer[i].type = somstrdup( t );
804
805        // embedded
806        if ( info->getEmbedded() ) {
807            if ( info->getSubset() ) {
808                fonts->_buffer[i].embedded = LU_FONTEMBED_EMBEDDED_SUBSET;
809            } else {
810                fonts->_buffer[i].embedded = LU_FONTEMBED_EMBEDDED;
811            }
812        } else {
813            fonts->_buffer[i].embedded = LU_FONTEMBED_NOT_EMBEDDED;
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 boolean  SOMLINK isCreateFileThumbnail(LuPopplerDocument *somSelf, 
1316                                                  Environment *ev)
1317{
1318    return TRUE;
1319}
1320
1321
1322SOM_Scope void SOMLINK somDefaultInit(LuPopplerDocument *somSelf,
1323                                      som3InitCtrl* ctrl)
1324{
1325    // generated section - do not modify
1326    LuPopplerDocumentData *somThis;
1327    somInitCtrl globalCtrl;
1328    somBooleanVector myMask;
1329    LuPopplerDocument_BeginInitializer_somDefaultInit;
1330    LuPopplerDocument_Init_LuDocument_somDefaultInit(somSelf, ctrl);
1331    // end of generated section
1332
1333    // local LuPopplerDocument initialization code
1334    PopplerDocument *d = new PopplerDocument;
1335    somThis->data = d;
1336}
1337
1338
1339static void set_error( char **error, const char *fmt, ... )
1340{
1341    if ( error == NULL ) {
1342        return;
1343    }
1344
1345    va_list argptr;
1346    va_start( argptr, fmt );
1347    char *msg = new char[ 1000 ];
1348    vsnprintf( msg, 1000, fmt, argptr );
1349    *error = somstrdup( msg );
1350    delete msg;
1351}
1352
1353
1354SOM_Scope boolean  SOMLINK loadFile(LuPopplerDocument *somSelf,
1355                                    Environment *ev, string filename,
1356                                    string password, string* error)
1357{
1358    LuPopplerDocumentData *somThis = LuPopplerDocumentGetData( somSelf );
1359
1360    PDFDoc *newDoc;
1361    GooString *filename_g;
1362    GooString *password_g;
1363    int err;
1364
1365    if ( !globalParams ) {
1366        globalParams = new GlobalParams( NULL );
1367    }
1368
1369    filename_g = new GooString(filename);
1370
1371    password_g = NULL;
1372    if (password != NULL) {
1373        password_g = new GooString(password);
1374    }
1375
1376    newDoc = new PDFDoc(filename_g, password_g, password_g);
1377    if (password_g) {
1378        delete password_g;
1379    }
1380
1381    if (!newDoc->isOk()) {
1382        err = newDoc->getErrorCode();
1383        delete newDoc;
1384
1385        if (err == errEncrypted) {
1386            set_error(error, "Document is encrypted.");
1387        } else {
1388            set_error(error, "Failed to load document (error %d) '%s'\n", err, filename );
1389        }
1390
1391        return FALSE;
1392    }
1393
1394    PopplerDocument *document = (PopplerDocument *)somThis->data;
1395
1396    document->doc = newDoc;
1397    SplashColor white;
1398    white[0] = 255;
1399    white[1] = 255;
1400    white[2] = 255;
1401    document->output_dev = new SplashOutputDev( splashModeBGR8, 4, gFalse, white );
1402    document->output_dev->startDoc( document->doc->getXRef() );
1403
1404    long numpages = document->doc->getNumPages();
1405    document->pages = new PopplerPage[ numpages ];
1406    for ( long pagenum = 0; pagenum < numpages; pagenum++ ) {
1407        document->pages[ pagenum ].page =
1408            document->doc->getCatalog()->getPage( pagenum + 1 );
1409    }
1410
1411    return TRUE;
1412}
1413
1414
1415SOM_Scope void SOMLINK somDestruct(LuPopplerDocument *somSelf,
1416                                   octet doFree, som3DestructCtrl* ctrl)
1417{
1418    LuPopplerDocumentData *somThis;
1419    somDestructCtrl globalCtrl;
1420    somBooleanVector myMask;
1421    LuPopplerDocument_BeginDestructor;
1422
1423    // local LuPopplerDocument deinitialization code
1424    PopplerDocument *document = (PopplerDocument *)somThis->data;
1425    delete document;
1426    // end of local LuPopplerDocument deinitialization code
1427
1428    LuPopplerDocument_EndDestructor;
1429}
1430
1431
Note: See TracBrowser for help on using the repository browser.