diff --git a/core/Makefile.am b/core/Makefile.am index 387607b1f..5c6aa3149 100644 --- a/core/Makefile.am +++ b/core/Makefile.am @@ -5,6 +5,6 @@ INCLUDES = -I$(srcdir)/generator_pdf -I$(srcdir)/.. -I$(srcdir)/../xpdf -I$(srcd METASOURCES = AUTO libkpdfcore_la_LIBADD = ./generator_pdf/libgeneratorpdf.la -libkpdfcore_la_SOURCES = document.cpp link.cpp page.cpp +libkpdfcore_la_SOURCES = document.cpp link.cpp page.cpp pagetransition.cpp noinst_LTLIBRARIES = libkpdfcore.la diff --git a/core/generator_pdf/generator_pdf.cpp b/core/generator_pdf/generator_pdf.cpp index 8288bd556..a83852622 100644 --- a/core/generator_pdf/generator_pdf.cpp +++ b/core/generator_pdf/generator_pdf.cpp @@ -33,6 +33,7 @@ #include "gp_outputdev.h" #include "core/observer.h" //for PAGEVIEW_ID #include "core/page.h" +#include "core/pagetransition.h" #include "conf/settings.h" // id for DATA_READY ThreadedGenerator Event @@ -118,8 +119,13 @@ bool PDFGenerator::loadDocument( const QString & fileName, QValueVectorgetNumPages(); pagesVector.resize( pageCount ); - for ( uint i = 0; i < pageCount ; i++ ) - pagesVector[i] = new KPDFPage( i, pdfdoc->getPageWidth(i+1), pdfdoc->getPageHeight(i+1), pdfdoc->getPageRotate(i+1) ); + for ( uint i = 0; i < pageCount ; i++ ) { + KPDFPage * page = new KPDFPage( i, pdfdoc->getPageWidth(i+1), + pdfdoc->getPageHeight(i+1), + pdfdoc->getPageRotate(i+1) ); + addTransition( i, page ); + pagesVector[i] = page; + } // the file has been loaded correctly return true; @@ -226,6 +232,80 @@ void PDFGenerator::addSynopsisChildren( QDomNode * parent, GList * items ) } } +void PDFGenerator::addTransition( int pageNumber, KPDFPage * page ) +{ + KPDFPageTransition *transition = new KPDFPageTransition(); + + Page *pdfPage = pdfdoc->getCatalog()->getPage( pageNumber + 1 ); + if ( pdfPage && pdfPage->getTransition() ) { + PageTransition *pdfTransition = pdfPage->getTransition(); + + switch ( pdfTransition->getType() ) { + case PageTransition::Replace: + transition->setType( KPDFPageTransition::Replace ); + break; + case PageTransition::Split: + transition->setType( KPDFPageTransition::Split ); + break; + case PageTransition::Blinds: + transition->setType( KPDFPageTransition::Blinds ); + break; + case PageTransition::Box: + transition->setType( KPDFPageTransition::Box ); + break; + case PageTransition::Wipe: + transition->setType( KPDFPageTransition::Wipe ); + break; + case PageTransition::Dissolve: + transition->setType( KPDFPageTransition::Dissolve ); + break; + case PageTransition::Glitter: + transition->setType( KPDFPageTransition::Glitter ); + break; + case PageTransition::Fly: + transition->setType( KPDFPageTransition::Fly ); + break; + case PageTransition::Push: + transition->setType( KPDFPageTransition::Push ); + break; + case PageTransition::Cover: + transition->setType( KPDFPageTransition::Cover ); + break; + case PageTransition::Uncover: + transition->setType( KPDFPageTransition::Uncover ); + break; + case PageTransition::Fade: + transition->setType( KPDFPageTransition::Fade ); + break; + } + + transition->setDuration( pdfTransition->getDuration() ); + + switch ( pdfTransition->getAlignment() ) { + case PageTransition::Horizontal: + transition->setAlignment( KPDFPageTransition::Horizontal ); + break; + case PageTransition::Vertical: + transition->setAlignment( KPDFPageTransition::Vertical ); + break; + } + + switch ( pdfTransition->getDirection() ) { + case PageTransition::Inward: + transition->setDirection( KPDFPageTransition::Inward ); + break; + case PageTransition::Outward: + transition->setDirection( KPDFPageTransition::Outward ); + break; + } + + transition->setAngle( pdfTransition->getAngle() ); + transition->setScale( pdfTransition->getScale() ); + transition->setIsRectangular( pdfTransition->isRectangular() == gTrue ); + } + + page->setTransition( transition ); +} bool PDFGenerator::print( KPrinter& printer ) { diff --git a/core/generator_pdf/generator_pdf.h b/core/generator_pdf/generator_pdf.h index c4c2964ee..a973ace37 100644 --- a/core/generator_pdf/generator_pdf.h +++ b/core/generator_pdf/generator_pdf.h @@ -75,6 +75,8 @@ class PDFGenerator : public Generator QString getDocumentDate( const QString & data ) const; // private function for creating the document synopsis hieracy void addSynopsisChildren( QDomNode * parent, GList * items ); + // private function for creating the transition information + void addTransition( int pageNumber, KPDFPage * page ); // (GT) take the first queued item from the stack and feed it to the thread void startNewThreadedGeneration(); // (GT) receive data from the generator thread diff --git a/core/page.cpp b/core/page.cpp index 27b9af997..36c1c7599 100644 --- a/core/page.cpp +++ b/core/page.cpp @@ -32,7 +32,7 @@ KPDFPage::KPDFPage( uint page, float w, float h, int r ) : m_number( page ), m_rotation( r ), m_attributes( 0 ), m_width( w ), m_height( h ), m_sLeft( 0 ), m_sTop( 0 ), - m_sRight( 0 ), m_sBottom( 0 ), m_text( 0 ) + m_sRight( 0 ), m_sBottom( 0 ), m_text( 0 ), m_transition( 0 ) { // if landscape swap width <-> height (rotate 90deg CCW) if ( r == 90 || r == 270 ) @@ -91,6 +91,11 @@ const KPDFPageRect * KPDFPage::getRect( int mouseX, int mouseY ) const return 0; } +const KPDFPageTransition * KPDFPage::getTransition() const +{ + return m_transition; +} + const QString KPDFPage::getTextInRect( const QRect & rect, double zoom ) const { if ( !m_text ) @@ -146,6 +151,11 @@ void KPDFPage::setRects( const QValueList< KPDFPageRect * > rects ) m_rects = rects; } +void KPDFPage::setTransition( const KPDFPageTransition * transition ) +{ + m_transition = transition; +} + void KPDFPage::deletePixmap( int id ) { if ( m_pixmaps.contains( id ) ) diff --git a/core/page.h b/core/page.h index 8d318b1fe..8c52cdeeb 100644 --- a/core/page.h +++ b/core/page.h @@ -15,8 +15,10 @@ class QPainter; class QPixmap; +class QRect; class TextPage; class KPDFPageRect; +class KPDFPageTransition; /** * @short Collector for all the data belonging to a page. @@ -50,6 +52,7 @@ class KPDFPage bool hasRect( int mouseX, int mouseY ) const; bool hasLink( int mouseX, int mouseY ) const; const KPDFPageRect * getRect( int mouseX, int mouseY ) const; + const KPDFPageTransition * getTransition() const; const QString getTextInRect( const QRect & rect, double zoom = 1.0 ) const; // operations (by KPDFDocument) @@ -62,6 +65,7 @@ class KPDFPage void setPixmap( int id, QPixmap * pixmap ); void setSearchPage( TextPage * text ); void setRects( const QValueList< KPDFPageRect * > rects ); + void setTransition( const KPDFPageTransition * transition ); void deletePixmap( int id ); void deletePixmapsAndRects(); @@ -74,6 +78,7 @@ class KPDFPage QMap< int, QPixmap * > m_pixmaps; TextPage * m_text; QValueList< KPDFPageRect * > m_rects; + const KPDFPageTransition * m_transition; }; diff --git a/core/pagetransition.cpp b/core/pagetransition.cpp new file mode 100644 index 000000000..969b4b0b8 --- /dev/null +++ b/core/pagetransition.cpp @@ -0,0 +1,28 @@ +/*************************************************************************** + * Copyright (C) 2005 by Tobias Koenig * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +// local includes +#include "pagetransition.h" + +/** class KPDFPageTransition **/ + +KPDFPageTransition::KPDFPageTransition() + : m_type( Replace ), + m_duration( 1 ), + m_alignment( Horizontal ), + m_direction( Inward ), + m_angle( 0 ), + m_scale( 1.0 ), + m_rectangular( false ) +{ +} + +KPDFPageTransition::~KPDFPageTransition() +{ +} diff --git a/core/pagetransition.h b/core/pagetransition.h new file mode 100644 index 000000000..30ef835b0 --- /dev/null +++ b/core/pagetransition.h @@ -0,0 +1,86 @@ +/*************************************************************************** + * Copyright (C) 2005 by Tobias Koenig * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef _KPDF_PAGE_TRANSITION_H_ +#define _KPDF_PAGE_TRANSITION_H_ + +/** + * @short Information object for the transition effect of a page. + */ +class KPDFPageTransition +{ + public: + KPDFPageTransition(); + ~KPDFPageTransition(); + + enum Type { + Replace, + Split, + Blinds, + Box, + Wipe, + Dissolve, + Glitter, + Fly, + Push, + Cover, + Uncover, + Fade + }; + + enum Alignment { + Horizontal, + Vertical + }; + + enum Direction { + Inward, + Outward + }; + + // Get type of the transition. + inline Type type() const { return m_type; } + + // Get duration of the transition in seconds. + inline int duration() const { return m_duration; } + + // Get dimension in which the transition effect occurs. + inline Alignment alignment() const { return m_alignment; } + + // Get direction of motion of the transition effect. + inline Direction direction() const { return m_direction; } + + // Get direction in which the transition effect moves. + inline int angle() const { return m_angle; } + + // Get starting or ending scale. + inline double scale() const { return m_scale; } + + // Returns true if the area to be flown is rectangular and opaque. + inline bool isRectangular() const { return m_rectangular; } + + inline void setType( Type type ) { m_type = type; } + inline void setDuration( int duration ) { m_duration = duration; } + inline void setAlignment( Alignment alignment ) { m_alignment = alignment; } + inline void setDirection( Direction direction ) { m_direction = direction; } + inline void setAngle( int angle ) { m_angle = angle; } + inline void setScale( double scale ) { m_scale = scale; } + inline void setIsRectangular( bool rectangular ) { m_rectangular = rectangular; } + + private: + Type m_type; + int m_duration; + Alignment m_alignment; + Direction m_direction; + int m_angle; + double m_scale; + bool m_rectangular; +}; + +#endif diff --git a/ui/presentationwidget.cpp b/ui/presentationwidget.cpp index 3d47e7394..32c5c0000 100644 --- a/ui/presentationwidget.cpp +++ b/ui/presentationwidget.cpp @@ -41,8 +41,6 @@ struct PresentationFrame { const KPDFPage * page; QRect geometry; - PresentationWidget::TransitionType transType; - PresentationWidget::TransitionDirection transDir; }; @@ -122,9 +120,6 @@ void PresentationWidget::pageSetup( const QValueVector & pageSet, boo { PresentationFrame * frame = new PresentationFrame(); frame->page = *setIt; - //TODO get transition from the document - frame->transType = Settings::slidesGlitterTrans() ? Glitter : NoTrans; - frame->transDir = Left; // calculate frame geometry keeping constant aspect ratio float pageRatio = frame->page->ratio(); int pageWidth = m_width, @@ -287,8 +282,7 @@ void PresentationWidget::generatePage() #endif // start transition or immediately update viewport - TransitionType type = m_frameIndex != -1 ? m_frames[ m_frameIndex ]->transType : NoTrans; - initTransition( type ); + initTransition( m_frames[ m_frameIndex ]->page->getTransition() ); } void PresentationWidget::generateIntroPage( QPainter & p ) @@ -554,14 +548,33 @@ void PresentationWidget::slotTransitionStep() /** ONLY the TRANSITIONS GENERATION function from here on **/ -void PresentationWidget::initTransition( TransitionType type ) +void PresentationWidget::initTransition( const KPDFPageTransition *transition ) { m_transitionRects.clear(); const int gridXstep = 50; const int gridYstep = 38; - switch( type ) + switch( transition->type() ) { - case Glitter: { + // TODO: implement missing transitions + case KPDFPageTransition::Replace: + update(); + return; + case KPDFPageTransition::Split: + update(); + return; + case KPDFPageTransition::Blinds: + update(); + return; + case KPDFPageTransition::Box: + update(); + return; + case KPDFPageTransition::Wipe: + update(); + return; + case KPDFPageTransition::Dissolve: + update(); + return; + case KPDFPageTransition::Glitter: { int oldX = 0, oldY = 0; // create a grid of gridXstep by gridYstep QRects @@ -595,15 +608,19 @@ void PresentationWidget::initTransition( TransitionType type ) m_transitionMul = 40; m_transitionDelay = (m_transitionMul * 500) / steps; } break; - - // TODO: implement missing transitions - case NoTrans: - case BoxIn: - case BoxOut: - case GlitterDir: - case FuseDir: - case SplitDir: - case WipeDir: + case KPDFPageTransition::Fly: + update(); + return; + case KPDFPageTransition::Push: + update(); + return; + case KPDFPageTransition::Cover: + update(); + return; + case KPDFPageTransition::Uncover: + update(); + return; + case KPDFPageTransition::Fade: update(); return; } diff --git a/ui/presentationwidget.h b/ui/presentationwidget.h index 211df139b..e978162a7 100644 --- a/ui/presentationwidget.h +++ b/ui/presentationwidget.h @@ -15,6 +15,7 @@ #include #include #include "core/observer.h" +#include "core/pagetransition.h" class KToolBar; class QTimer; @@ -35,11 +36,6 @@ class PresentationWidget : public QWidget, public KPDFDocumentObserver PresentationWidget( KPDFDocument * doc ); ~PresentationWidget(); - // define type of transitions used by presentation frames - enum TransitionType { NoTrans, BoxIn, BoxOut, Glitter, GlitterDir, - FuseDir, SplitDir, WipeDir }; - enum TransitionDirection { Left, Top, Right, Bottom }; - // inherited from KPDFDocumentObserver uint observerId() const { return PRESENTATION_ID; } void pageSetup( const QValueVector & pages, bool documentChanged ); @@ -59,7 +55,7 @@ class PresentationWidget : public QWidget, public KPDFDocumentObserver void generateIntroPage( QPainter & p ); void generateContentsPage( int page, QPainter & p ); void generateOverlay(); - void initTransition( TransitionType type ); + void initTransition( const KPDFPageTransition *transition ); // cache stuff int m_width; diff --git a/xpdf/xpdf/Page.cc b/xpdf/xpdf/Page.cc index f0253a906..c21adae02 100644 --- a/xpdf/xpdf/Page.cc +++ b/xpdf/xpdf/Page.cc @@ -172,6 +172,105 @@ GBool PageAttrs::readBox(Dict *dict, const char *key, PDFRectangle *box) { return ok; } +//------------------------------------------------------------------------ +// PageTransition +//------------------------------------------------------------------------ + +PageTransition::PageTransition(Dict *dict) + : type(Replace), + duration(1), + alignment(Horizontal), + direction(Inward), + angle(0), + scale(1.0), + rectangular(false) +{ + Object dictObj; + Object obj; + + dict->lookup("Trans", &dictObj); + if (dictObj.isDict()) { + Dict *transDict = dictObj.getDict(); + + if (transDict->lookup("S", &obj)->isName()) { + const char *s = obj.getName(); + if (strcmp("R", s) == 0) + type = Replace; + else if (strcmp("Split", s) == 0) + type = Split; + else if (strcmp("Blinds", s) == 0) + type = Blinds; + else if (strcmp("Box", s) == 0) + type = Box; + else if (strcmp("Wipe", s) == 0) + type = Wipe; + else if (strcmp("Dissolve", s) == 0) + type = Dissolve; + else if (strcmp("Glitter", s) == 0) + type = Glitter; + else if (strcmp("Fly", s) == 0) + type = Fly; + else if (strcmp("Push", s) == 0) + type = Push; + else if (strcmp("Cover", s) == 0) + type = Cover; + else if (strcmp("Uncover", s) == 0) + type = Push; + else if (strcmp("Fade", s) == 0) + type = Cover; + } + obj.free(); + + if (transDict->lookup("D", &obj)->isInt()) { + duration = obj.getInt(); + } + obj.free(); + + if (transDict->lookup("Dm", &obj)->isName()) { + const char *dm = obj.getName(); + if ( strcmp( "H", dm ) == 0 ) + alignment = Horizontal; + else if ( strcmp( "V", dm ) == 0 ) + alignment = Vertical; + } + obj.free(); + + if (transDict->lookup("M", &obj)->isName()) { + const char *m = obj.getName(); + if ( strcmp( "I", m ) == 0 ) + direction = Inward; + else if ( strcmp( "O", m ) == 0 ) + direction = Outward; + } + obj.free(); + + if (transDict->lookup("Di", &obj)->isInt()) { + angle = obj.getInt(); + } + obj.free(); + + if (transDict->lookup("Di", &obj)->isName()) { + if ( strcmp( "None", obj.getName() ) == 0 ) + angle = 0; + } + obj.free(); + + if (transDict->lookup("SS", &obj)->isReal()) { + scale = obj.getReal(); + } + obj.free(); + + if (transDict->lookup("B", &obj)->isBool()) { + rectangular = obj.getBool(); + } + obj.free(); + } + dictObj.free(); +} + +PageTransition::~PageTransition() { +} + //------------------------------------------------------------------------ // Page //------------------------------------------------------------------------ @@ -184,6 +283,9 @@ Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) { // get attributes attrs = attrsA; + // get transition + transition = new PageTransition( pageDict ); + // annotations pageDict->lookupNF("Annots", &annots); if (!(annots.isRef() || annots.isArray() || annots.isNull())) { @@ -214,6 +316,7 @@ Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) { Page::~Page() { delete attrs; + delete transition; annots.free(); contents.free(); } diff --git a/xpdf/xpdf/Page.h b/xpdf/xpdf/Page.h index 3cb318d9f..5a527f1b9 100644 --- a/xpdf/xpdf/Page.h +++ b/xpdf/xpdf/Page.h @@ -97,6 +97,74 @@ private: Object resources; }; +//------------------------------------------------------------------------ +// PageTransition +//------------------------------------------------------------------------ +class PageTransition { +public: + enum Type { + Replace, + Split, + Blinds, + Box, + Wipe, + Dissolve, + Glitter, + Fly, + Push, + Cover, + Uncover, + Fade + }; + + enum Alignment { + Horizontal, + Vertical + }; + + enum Direction { + Inward, + Outward + }; + + // Construct a new PageTransition object from a page dictionary. + PageTransition( Dict *dict ); + + // Destructor + ~PageTransition(); + + // Get type of the transition. + Type getType() const { return type; } + + // Get duration of the transition in seconds. + int getDuration() const { return duration; } + + // Get dimension in which the transition effect + // occurs. + Alignment getAlignment() const { return alignment; } + + // Get direction of motion of the transition effect. + Direction getDirection() const { return direction; } + + // Get direction in which the transition effect moves. + int getAngle() const { return angle; } + + // Get starting or ending scale. + double getScale() const { return scale; } + + // Returns true if the area to be flown is rectangular and + // opaque. + GBool isRectangular() const { return rectangular; } +private: + Type type; + int duration; + Alignment alignment; + Direction direction; + int angle; + double scale; + GBool rectangular; +}; + //------------------------------------------------------------------------ // Page //------------------------------------------------------------------------ @@ -140,6 +208,9 @@ public: // Get contents. Object *getContents(Object *obj) { return contents.fetch(xref, obj); } + // Get transition information. + PageTransition *getTransition() const { return transition; } + // Display a page. void display(OutputDev *out, double hDPI, double vDPI, int rotate, GBool crop, @@ -160,6 +231,7 @@ private: XRef *xref; // the xref table for this PDF file int num; // page number PageAttrs *attrs; // page attributes + PageTransition *transition; // page transition Object annots; // annotations array Object contents; // page contents GBool ok; // true if page is valid