Commit 42c016c6 authored by Albert Astals Cid's avatar Albert Astals Cid
Browse files

* poppler/Link.cc:

        * poppler/Link.h:
        * poppler/Makefile.am:
        * poppler/Page.cc:
        * poppler/Page.h:
        * poppler/Sound.cc:
        * poppler/Sound.h: Make poppler able to read Sound objects, Sound
        actions and Opening/Closing page actions. Patch by Pino Toscano.

        * qt4/src/Makefile.am:
        * qt4/src/poppler-link.cc:
        * qt4/src/poppler-link.h:
        * qt4/src/poppler-qt4.h:
        * qt4/src/poppler-page.cc:
        * qt4/src/poppler-sound.cc: Support for sounds, sound links and page
        actions in the Qt4 backend. Patch by Pino Toscano.
parent 1da064d7
2006-10-08 Albert Astals Cid <aacid@kde.org>
* poppler/Link.cc:
* poppler/Link.h:
* poppler/Makefile.am:
* poppler/Page.cc:
* poppler/Page.h:
* poppler/Sound.cc:
* poppler/Sound.h: Make poppler able to read Sound objects, Sound
actions and Opening/Closing page actions. Patch by Pino Toscano.
* qt4/src/Makefile.am:
* qt4/src/poppler-link.cc:
* qt4/src/poppler-link.h:
* qt4/src/poppler-qt4.h:
* qt4/src/poppler-page.cc:
* qt4/src/poppler-sound.cc: Support for sounds, sound links and page
actions in the Qt4 backend. Patch by Pino Toscano.
2006-09-30 Albert Astals Cid <aacid@kde.org> 2006-09-30 Albert Astals Cid <aacid@kde.org>
* qt4/src/poppler-page.cc: PA is optional, H is a name not a string * qt4/src/poppler-page.cc: PA is optional, H is a name not a string
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "Array.h" #include "Array.h"
#include "Dict.h" #include "Dict.h"
#include "Link.h" #include "Link.h"
#include "Sound.h"
#include "UGooString.h" #include "UGooString.h"
//------------------------------------------------------------------------ //------------------------------------------------------------------------
...@@ -88,6 +89,10 @@ LinkAction *LinkAction::parseAction(Object *obj, GooString *baseURI) { ...@@ -88,6 +89,10 @@ LinkAction *LinkAction::parseAction(Object *obj, GooString *baseURI) {
obj3.free(); obj3.free();
obj4.free(); obj4.free();
// Sound action
} else if (obj2.isName("Sound")) {
action = new LinkSound(obj);
// unknown action // unknown action
} else if (obj2.isName()) { } else if (obj2.isName()) {
action = new LinkUnknown(obj2.getName()); action = new LinkUnknown(obj2.getName());
...@@ -625,6 +630,54 @@ LinkMovie::~LinkMovie() { ...@@ -625,6 +630,54 @@ LinkMovie::~LinkMovie() {
} }
} }
//------------------------------------------------------------------------
// LinkSound
//------------------------------------------------------------------------
LinkSound::LinkSound(Object *soundObj) {
volume = 1.0;
sync = gFalse;
repeat = gFalse;
mix = gFalse;
sound = NULL;
if (soundObj->isDict())
{
Object tmp;
// volume
soundObj->dictLookup("Volume", &tmp);
if (tmp.isNum()) {
volume = tmp.getNum();
}
tmp.free();
// sync
soundObj->dictLookup("Synchronous", &tmp);
if (tmp.isBool()) {
sync = tmp.getBool();
}
tmp.free();
// repeat
soundObj->dictLookup("Repeat", &tmp);
if (tmp.isBool()) {
repeat = tmp.getBool();
}
tmp.free();
// mix
soundObj->dictLookup("Mix", &tmp);
if (tmp.isBool()) {
mix = tmp.getBool();
}
tmp.free();
// 'Sound' object
soundObj->dictLookup("Sound", &tmp);
sound = Sound::parseSound(&tmp);
tmp.free();
}
}
LinkSound::~LinkSound() {
delete sound;
}
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// LinkUnknown // LinkUnknown
//------------------------------------------------------------------------ //------------------------------------------------------------------------
......
...@@ -19,6 +19,7 @@ class GooString; ...@@ -19,6 +19,7 @@ class GooString;
class UGooString; class UGooString;
class Array; class Array;
class Dict; class Dict;
class Sound;
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// LinkAction // LinkAction
...@@ -31,6 +32,7 @@ enum LinkActionKind { ...@@ -31,6 +32,7 @@ enum LinkActionKind {
actionURI, // URI actionURI, // URI
actionNamed, // named action actionNamed, // named action
actionMovie, // movie action actionMovie, // movie action
actionSound, // sound action
actionUnknown // anything else actionUnknown // anything else
}; };
...@@ -275,6 +277,36 @@ private: ...@@ -275,6 +277,36 @@ private:
GooString *title; GooString *title;
}; };
//------------------------------------------------------------------------
// LinkSound
//------------------------------------------------------------------------
class LinkSound: public LinkAction {
public:
LinkSound(Object *soundObj);
virtual ~LinkSound();
virtual GBool isOk() { return sound != NULL; }
virtual LinkActionKind getKind() { return actionSound; }
double getVolume() { return volume; }
GBool getSynchronous() { return sync; }
GBool getRepeat() { return repeat; }
GBool getMix() { return mix; }
Sound *getSound() { return sound; }
private:
double volume;
GBool sync;
GBool repeat;
GBool mix;
Sound *sound;
};
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// LinkUnknown // LinkUnknown
//------------------------------------------------------------------------ //------------------------------------------------------------------------
......
...@@ -156,6 +156,7 @@ poppler_include_HEADERS = \ ...@@ -156,6 +156,7 @@ poppler_include_HEADERS = \
UGooString.h \ UGooString.h \
UTF8.h \ UTF8.h \
XpdfPluginAPI.h \ XpdfPluginAPI.h \
Sound.h \
poppler-config.h poppler-config.h
endif endif
...@@ -208,6 +209,7 @@ libpoppler_la_SOURCES = \ ...@@ -208,6 +209,7 @@ libpoppler_la_SOURCES = \
PageLabelInfo.cc \ PageLabelInfo.cc \
SecurityHandler.cc \ SecurityHandler.cc \
UGooString.cc \ UGooString.cc \
Sound.cc \
XpdfPluginAPI.cc XpdfPluginAPI.cc
EXTRA_DIST = gen-unicode-tables.py EXTRA_DIST = gen-unicode-tables.py
...@@ -230,6 +230,14 @@ Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) { ...@@ -230,6 +230,14 @@ Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) {
num, thumb.getTypeName()); num, thumb.getTypeName());
thumb.initNull(); thumb.initNull();
} }
// actions
pageDict->lookupNF("AA", &actions);
if (!(actions.isDict() || actions.isNull())) {
error(-1, "Page additional action object (page %d) is wrong type (%s)",
num, actions.getTypeName());
actions.initNull();
}
return; return;
......
...@@ -151,6 +151,9 @@ public: ...@@ -151,6 +151,9 @@ public:
// Get transition. // Get transition.
Object *getTrans(Object *obj) { return trans.fetch(xref, obj); } Object *getTrans(Object *obj) { return trans.fetch(xref, obj); }
// Get actions
Object *getActions(Object *obj) { return actions.fetch(xref, obj); }
Gfx *createGfx(OutputDev *out, double hDPI, double vDPI, Gfx *createGfx(OutputDev *out, double hDPI, double vDPI,
int rotate, GBool useMediaBox, GBool crop, int rotate, GBool useMediaBox, GBool crop,
int sliceX, int sliceY, int sliceW, int sliceH, int sliceX, int sliceY, int sliceW, int sliceH,
...@@ -194,6 +197,7 @@ private: ...@@ -194,6 +197,7 @@ private:
Object contents; // page contents Object contents; // page contents
Object thumb; // page thumbnail Object thumb; // page thumbnail
Object trans; // page transition Object trans; // page transition
Object actions; // page addiction actions
GBool ok; // true if page is valid GBool ok; // true if page is valid
}; };
......
/* Sound.cc - an object that holds the sound structure
* Copyright (C) 2006, Pino Toscano <pino@kde.org>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include "GooString.h"
#include "Object.h"
#include "Sound.h"
#include "Stream.h"
Sound *Sound::parseSound(Object *obj)
{
// let's try to see if this Object is a Sound, according to the PDF specs
// (section 9.2)
Stream *str = NULL;
// the Object must be a Stream
if (obj->isStream()) {
str = obj->getStream();
} else {
return NULL;
}
// the Stream must have a Dict
Dict *dict = str->getDict();
if (dict == NULL)
return NULL;
Object tmp;
// the Dict must have the 'R' key of type num
dict->lookup("R", &tmp);
if (tmp.isNum()) {
return new Sound(obj);
} else {
return NULL;
}
}
Sound::Sound(Object *obj)
{
streamObj = new Object();
streamObj->initNull();
obj->copy(streamObj);
}
Sound::~Sound()
{
streamObj->free();
}
Stream *Sound::getStream()
{
return streamObj->getStream();
}
/* Sound.h - an object that holds the sound structure
* Copyright (C) 2006, Pino Toscano <pino@kde.org>
*
* 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, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef Sound_H
#define Sound_H
class Object;
class Stream;
//------------------------------------------------------------------------
class Sound
{
public:
// Try to parse the Object s
static Sound *parseSound(Object *s);
// Destructor
~Sound();
Object *getObject() { return streamObj; }
Stream *getStream();
private:
// Create a sound. The Object obj is ensured to be a Stream with a Dict
Sound(Object *obj);
Object *streamObj;
};
#endif
...@@ -25,6 +25,7 @@ libpoppler_qt4_la_SOURCES = \ ...@@ -25,6 +25,7 @@ libpoppler_qt4_la_SOURCES = \
poppler-link.cc \ poppler-link.cc \
poppler-annotation.cc \ poppler-annotation.cc \
../../qt/poppler-page-transition.cc \ ../../qt/poppler-page-transition.cc \
poppler-sound.cc \
poppler-annotation-helper.h \ poppler-annotation-helper.h \
poppler-private.h poppler-private.h
......
...@@ -247,6 +247,41 @@ namespace Poppler { ...@@ -247,6 +247,41 @@ namespace Poppler {
return Action; return Action;
} }
// LinkSound
LinkSound::LinkSound( const QRectF &linkArea, double volume, bool sync, bool repeat, bool mix, SoundObject *sound ) : Link(linkArea), m_volume(volume), m_sync(sync), m_repeat(repeat), m_mix(mix), m_sound(sound)
{
}
Link::LinkType LinkSound::linkType() const
{
return Sound;
}
double LinkSound::volume() const
{
return m_volume;
}
bool LinkSound::synchronous() const
{
return m_sync;
}
bool LinkSound::repeat() const
{
return m_repeat;
}
bool LinkSound::mix() const
{
return m_mix;
}
SoundObject *LinkSound::sound() const
{
return m_sound;
}
// LinkMovie // LinkMovie
LinkMovie::LinkMovie( const QRectF &linkArea ) : Link(linkArea) LinkMovie::LinkMovie( const QRectF &linkArea ) : Link(linkArea)
{ {
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
namespace Poppler { namespace Poppler {
class LinkDestinationData; class LinkDestinationData;
class SoundObject;
class LinkDestination class LinkDestination
{ {
...@@ -83,7 +84,7 @@ class Link ...@@ -83,7 +84,7 @@ class Link
Link( const QRectF &linkArea ); Link( const QRectF &linkArea );
// get link type (inherited classes mustreturn an unique identifier) // get link type (inherited classes mustreturn an unique identifier)
enum LinkType { None, Goto, Execute, Browse, Action, Movie }; enum LinkType { None, Goto, Execute, Browse, Action, Sound, Movie };
virtual LinkType linkType() const; virtual LinkType linkType() const;
// virtual destructor // virtual destructor
...@@ -174,6 +175,29 @@ class LinkAction : public Link ...@@ -174,6 +175,29 @@ class LinkAction : public Link
ActionType m_type; ActionType m_type;
}; };
/** Sound: a sound to be played **/
class LinkSound : public Link
{
public:
// create a Link_Sound
LinkSound( const QRectF &linkArea, double volume, bool sync, bool repeat, bool mix, SoundObject *sound );
LinkType linkType() const;
double volume() const;
bool synchronous() const;
bool repeat() const;
bool mix() const;
SoundObject *sound() const;
private:
double m_volume;
bool m_sync;
bool m_repeat;
bool m_mix;
SoundObject *m_sound;
};
/** Movie: Not yet defined -> think renaming to 'Media' link **/ /** Movie: Not yet defined -> think renaming to 'Media' link **/
class LinkMovie : public Link class LinkMovie : public Link
// TODO this (Movie link) // TODO this (Movie link)
......
...@@ -123,6 +123,12 @@ Link* PageData::convertLinkActionToLink(::LinkAction * a, const QRectF &linkArea ...@@ -123,6 +123,12 @@ Link* PageData::convertLinkActionToLink(::LinkAction * a, const QRectF &linkArea
} }
break; break;
case actionSound:
{
::LinkSound *ls = (::LinkSound *)a;
popplerLink = new LinkSound( linkArea, ls->getVolume(), ls->getSynchronous(), ls->getRepeat(), ls->getMix(), new SoundObject( ls->getSound() ) );
}
case actionMovie: case actionMovie:
/* TODO this (Movie link) /* TODO this (Movie link)
m_type = Movie; m_type = Movie;
...@@ -366,6 +372,32 @@ PageTransition *Page::transition() const ...@@ -366,6 +372,32 @@ PageTransition *Page::transition() const
return m_page->transition; return m_page->transition;
} }
Link *Page::action( PageAction act ) const
{
if ( act == Page::Opening || act == Page::Closing )
{
::Page *p = m_page->parentDoc->m_doc->doc.getCatalog()->getPage(m_page->index + 1);
Object o;
p->getActions(&o);
if (!o.isDict())
{
o.free();
return 0;
}
Dict *dict = o.getDict();
Object o2;
const char *key = act == Page::Opening ? "O" : "C";
dict->lookup(key, &o2);
::LinkAction *act = ::LinkAction::parseAction(&o2, m_page->parentDoc->m_doc->doc.getCatalog()->getBaseURI() );
o2.free();
Link *popplerLink = NULL;
if (act != NULL)
popplerLink = m_page->convertLinkActionToLink(act, QRectF(), m_page->parentDoc->m_doc);
return popplerLink;
}
return 0;
}
QSizeF Page::pageSizeF() const QSizeF Page::pageSizeF() const
{ {
::Page *p; ::Page *p;
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <poppler-page-transition.h> #include <poppler-page-transition.h>
class EmbFile; class EmbFile;
class Sound;
/** /**
The Poppler Qt bindings The Poppler Qt bindings
...@@ -224,6 +225,14 @@ namespace Poppler { ...@@ -224,6 +225,14 @@ namespace Poppler {
enum Rotation { Rotate0 = 0, Rotate90 = 1, Rotate180 = 2, Rotate270 = 3 }; enum Rotation { Rotate0 = 0, Rotate90 = 1, Rotate180 = 2, Rotate270 = 3 };
/**
The kinds of page actions
*/
enum PageAction {
Opening, ///< The action when a page is "opened"
Closing ///< The action when a page is "closed"
};
/** /**
Render the page to a QImage using the Splash renderer Render the page to a QImage using the Splash renderer
...@@ -375,6 +384,11 @@ delete pixmap; ...@@ -375,6 +384,11 @@ delete pixmap;
**/ **/
PageTransition *transition() const; PageTransition *transition() const;
/**
Gets the page action specified, or NULL if there is no action
**/
Link *action( PageAction act ) const;
/** /**
Types of orientations that are possible Types of orientations that are possible
*/ */
...@@ -710,6 +724,79 @@ delete pixmap; ...@@ -710,6 +724,79 @@ delete pixmap;
*/ */
QDateTime convertDate( char *dateString ); QDateTime convertDate( char *dateString );
class SoundData;
/**
Container class for a sound file in a PDF document.
A sound can be either External (in that case should be loaded the file
whose url is represented by url() ), or Embedded, and the player has to
play the data contained in data().
*/
class SoundObject {
public:
/**
The type of sound
*/
enum SoundType {
External, ///< The real sound file is external
Embedded ///< The sound is contained in the data
};
/**
The encoding format used for the sound
*/
enum SoundEncoding {
Raw, ///< Raw encoding, with unspecified or unsigned values in the range [ 0, 2^B − 1 ]
Signed, ///< Twos-complement values
muLaw, ///< mu-law-encoded samples
ALaw ///< A-law-encoded samples
};
SoundObject(Sound *popplersound);
SoundObject(const SoundObject &s);
~SoundObject();
/**
Is the sound embedded (@ref Embedded ) or external (@ref External )?
*/