From f9324b3f2bf64574bf20e37686624b8600c3ecc4 Mon Sep 17 00:00:00 2001
From: Corentin Allemand
Date: Wed, 31 Oct 2012 17:18:37 +0100
Subject: [PATCH 1/7] Add with media params
---
utils/HtmlOutputDev.cc | 4 +++-
utils/pdftohtml.cc | 7 +++++--
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc
index e4bd0b1..7d60975 100644
--- a/utils/HtmlOutputDev.cc
+++ b/utils/HtmlOutputDev.cc
@@ -97,6 +97,7 @@ extern GBool stout;
extern GBool xml;
extern GBool showHidden;
extern GBool noMerge;
+extern GBool withMedia;
extern double wordBreakThreshold;
@@ -877,7 +878,8 @@ void HtmlPage::dumpComplex(FILE *file, int page){
fprintf(pageFile,"\n",
page, pageWidth, pageHeight);
- if( !ignore )
+
+ if( !ignore && !withMedia)
{
fprintf(pageFile,
"

\n",
diff --git a/utils/pdftohtml.cc b/utils/pdftohtml.cc
index 97372be..72e784f 100644
--- a/utils/pdftohtml.cc
+++ b/utils/pdftohtml.cc
@@ -84,6 +84,7 @@ double wordBreakThreshold=10; // 10%, below converted into a coefficient - 0.1
GBool showHidden = gFalse;
GBool noMerge = gFalse;
GBool fontFullName = gFalse;
+GBool withMedia = gFalse;
static char ownerPassword[33] = "";
static char userPassword[33] = "";
static GBool printVersion = gFalse;
@@ -141,7 +142,9 @@ static const ArgDesc argDesc[] = {
{"-wbt", argFP, &wordBreakThreshold, 0,
"word break threshold (default 10 percent)"},
{"-fontfullname", argFlag, &fontFullName, 0,
- "outputs font full name"},
+ "outputs font full name"},
+ {"-withmedia", argFlag, &withMedia, 0,
+ "extract all media"},
{NULL}
};
@@ -383,7 +386,7 @@ int main(int argc, char *argv[]) {
htmlOut->dumpDocOutline(doc);
}
- if ((complexMode || singleHtml) && !xml && !ignore) {
+ if ((complexMode || singleHtml) && !xml && !ignore && !withMedia) {
#ifdef HAVE_SPLASH
GooString *imgFileName = NULL;
// White paper color
--
1.7.10.2 (Apple Git-33)
From 1d677d4f2c4106bc73e25be5294161b02bbd3810 Mon Sep 17 00:00:00 2001
From: Corentin Allemand
Date: Wed, 31 Oct 2012 18:16:19 +0100
Subject: [PATCH 2/7] Extract images with "-withMedia" parameter
---
utils/HtmlOutputDev.cc | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc
index 7d60975..916ec91 100644
--- a/utils/HtmlOutputDev.cc
+++ b/utils/HtmlOutputDev.cc
@@ -889,6 +889,26 @@ void HtmlPage::dumpComplex(FILE *file, int page){
delete tmp;
+ if(!ignore && withMedia){
+ int listlen=imgList->getLength();
+ GooString *imgfname;
+ for (int i = 0; i < listlen; i++) {
+ HtmlImage *img = (HtmlImage*)imgList->del(0);
+ imgfname=basename(img->fName);
+ fprintf(pageFile,
+ "",
+ xoutRound(img->yMin),
+ xoutRound(img->xMin),
+ xoutRound(img->xMax-img->xMin),
+ xoutRound(img->yMax-img->yMin));
+
+ fprintf(pageFile,"
![]()
xMax-img->xMin),xoutRound(img->yMax-img->yMin));
+ fprintf(pageFile,"src=\"%s\"/>",imgfname->getCString());
+ fputs("
\n", pageFile);
+ delete img;
+ }
+ }
+
for(HtmlString *tmp1=yxStrings;tmp1;tmp1=tmp1->yxNext){
if (tmp1->htext){
fprintf(pageFile,
@@ -906,6 +926,9 @@ void HtmlPage::dumpComplex(FILE *file, int page){
}
}
+
+
+
fputs(" \n", pageFile);
if( !noframes )
@@ -1466,7 +1489,7 @@ void HtmlOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool interpolate, GBool inlineImg) {
- if (ignore||(complexMode && !xml)) {
+ if (ignore|| !(complexMode && withMedia)) {
OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg);
return;
}
@@ -1488,7 +1511,7 @@ void HtmlOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap *colorMap,
GBool interpolate, int *maskColors, GBool inlineImg) {
- if (ignore||(complexMode && !xml)) {
+ if (ignore || !(complexMode && withMedia)) {
OutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate,
maskColors, inlineImg);
return;
--
1.7.10.2 (Apple Git-33)
From f2bbe496201746dd107e6147e5577e83a0c7ee75 Mon Sep 17 00:00:00 2001
From: Corentin Allemand
Date: Mon, 5 Nov 2012 13:54:50 +0100
Subject: [PATCH 3/7] Extract Video and Sound from AnnotRichMedia
---
poppler/Annot.cc | 279 ++++++++++++++++++++++++++++++++++++++++++++++++
poppler/Annot.h | 110 ++++++++++++++++++-
poppler/FileSpec.cc | 8 +-
poppler/Sound.cc | 14 +--
utils/HtmlOutputDev.cc | 184 ++++++++++++++++++++++++++++++-
utils/HtmlOutputDev.h | 64 +++++++++++
6 files changed, 642 insertions(+), 17 deletions(-)
diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index dae0f62..a9807ac 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -6494,6 +6494,283 @@ Annot3D::Activation::Activation(Dict *dict) {
}
//------------------------------------------------------------------------
+// AnnotRichMedia
+//------------------------------------------------------------------------
+AnnotRichMediaInstance::AnnotRichMediaInstance(Dict *dict){
+ subtype = richMediaSubTypeUnknown;
+ Object obj1;
+ //Type name (Optional; ExtensionLevel 3)
+ if(dict->lookup("Type", &obj1)->isName()){
+ type = obj1.getName();
+ }
+ obj1.free();
+ //Subtype name (Optional; ExtensionLevel 3)
+ if(dict->lookup("Subtype", &obj1)->isName()){
+ char *stype = obj1.getName();
+ if(strcmp(stype, "3D") == 0){
+ subtype = richMediaSubType3D;
+ }else if(strcmp(stype, "Flash") == 0){
+ subtype = richMediaSubTypeFlash;
+ }else if(strcmp(stype, "Sound") == 0){
+ subtype = richMediaSubTypeSound;
+ }else if(strcmp(stype, "Video") == 0){
+ subtype = richMediaSubTypeVideo;
+ }
+ }
+ obj1.free();
+ //Params dictionary (Optional; ExtensionLevel 3) This entry is valid only for subtype Flash.
+ if(dict->lookup("Params", &obj1)->isDict()){
+ //TODO
+ }
+ obj1.free();
+ //Asset dictionary (Optional; ExtensionLevel 3)
+ if(dict->lookup("Asset", &obj1)->isDict()){
+ fileSpec = new FileSpec(&obj1);
+ }
+ obj1.free();
+}
+
+AnnotRichMediaInstance::~AnnotRichMediaInstance(){
+}
+
+
+
+AnnotRichMediaConfiguration::AnnotRichMediaConfiguration(Dict *dict){
+ instances = new GooList();
+ subtype = richMediaSubTypeUnknown;
+ Object obj1;
+ Object obj2;
+ //Type name (Optional; ExtensionLevel 3)
+ if(dict->lookup("Type", &obj1)->isName()){
+ type = obj1.getName();
+ }
+ obj1.free();
+ //Subtype name (Optional; ExtensionLevel 3)
+ if(dict->lookup("Subtype", &obj1)->isName()){
+ char *stype = obj1.getName();
+ if(strcmp(stype, "3D") == 0){
+ subtype = richMediaSubType3D;
+ }else if(strcmp(stype, "Flash") == 0){
+ subtype = richMediaSubTypeFlash;
+ }else if(strcmp(stype, "Sound") == 0){
+ subtype = richMediaSubTypeSound;
+ }else if(strcmp(stype, "Video") == 0){
+ subtype = richMediaSubTypeVideo;
+ }
+ }
+ obj1.free();
+ //Name text tree (Optional; ExtensionLevel 3)
+ if(dict->lookup("Name", &obj1)->isName()){
+ name = obj1.getName();
+ }
+ obj1.free();
+ //Instances array (Optional; ExtensionLevel 3)
+ if(dict->lookup("Instances", &obj1)->isArray()){
+ Array* insts = obj1.getArray();
+ AnnotRichMediaInstance *instance;
+ for (int i = 0; i < insts->getLength(); ++i) {
+ if(insts->get(i, &obj2)->isDict()){
+ instance = new AnnotRichMediaInstance(obj2.getDict());
+ instances->append(instance);
+ }
+ obj2.free();
+ }
+ }
+}
+
+AnnotRichMediaConfiguration::~AnnotRichMediaConfiguration() {
+
+}
+
+AnnotRichMediaContent::AnnotRichMediaContent(Dict *dict){
+ Object obj1;
+ Object obj2;
+ Object obj3;
+ configurations = new GooList();
+ assets = new GooList();
+ //Type name (Optional; ExtensionLevel 3)
+ if (dict->lookup("Type", &obj1)->isName()) {
+ type = obj1.getName();
+ }
+ obj1.free();
+
+ //Assets name tree (Optional; ExtensionLevel 3)
+ if (dict->lookup("Assets", &obj1)) {
+ Dict* asts = obj1.getDict();
+ if(asts->lookup("Names", &obj2)->isArray()){
+ Array* names = obj2.getArray();
+ for (int iName = 0; iName < names->getLength(); iName = iName+2) {
+ if(names->get(iName, &obj3)->isString()){
+ //TODO
+ }
+ obj3.free();
+ if (names->get(iName + 1, &obj3)->isDict()) {
+ FileSpec* fSpec = new FileSpec(&obj3);
+ assets->append(fSpec);
+ }
+ obj3.free();
+ }
+ }
+ obj2.free();
+ }
+ obj1.free();
+
+ //Configurations array (Optional; ExtensionLevel 3)
+ if (dict->lookup("Configurations", &obj1)->isArray()) {
+ //Type name (Optional; ExtensionLevel 3)
+ Array* conf = obj1.getArray();
+ AnnotRichMediaConfiguration* configuration;
+ for (int i = 0; i < conf->getLength(); ++i) {
+ if(conf->get(0, &obj2)->isDict()){
+ configuration = new AnnotRichMediaConfiguration(obj2.getDict());
+ configurations->append(configuration);
+ }else{
+ //TODO error;
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+ //Views array (Optional; ExtensionLevel 3)
+}
+
+AnnotRichMediaContent::~AnnotRichMediaContent() {
+ if(configurations != NULL){
+ delete configurations;
+ configurations = NULL;
+ }
+}
+
+AnnotRichMediaActivation::AnnotRichMediaActivation(Dict *dict){
+ Object obj1;
+ //Type name (Optional; ExtensionLevel 3)
+ if (dict->lookup("Type", &obj1)->isName()) {
+ type = obj1.getName();
+ }
+ obj1.free();
+ //Condition name (Optional; ExtensionLevel 3)
+ if (dict->lookup("Condition", &obj1)->isName()) {
+ condition = obj1.getName();
+ }
+ obj1.free();
+ //Animation dictionary (Optional; ExtensionLevel 3)
+
+ //View dictionary (Optional; ExtensionLevel 3)
+
+ //Configuration dictionary (Optional; ExtensionLevel 3)
+
+ //Presentation dictionary (Optional; ExtensionLevel 3)
+
+ //Scripts array (Optional; ExtensionLevel 3)
+
+}
+
+AnnotRichMediaActivation::~AnnotRichMediaActivation() {
+
+}
+
+AnnotRichMediaDeactivation::AnnotRichMediaDeactivation(Dict *dict){
+ Object obj1;
+ //Type name (Optional; ExtensionLevel 3)
+ if (dict->lookup("Type", &obj1)->isName()) {
+ type = obj1.getName();
+ }
+ obj1.free();
+ //Condition name (Optional; ExtensionLevel 3)
+ if (dict->lookup("Condition", &obj1)->isName()) {
+ condition = obj1.getName();
+ }
+ obj1.free();
+}
+
+AnnotRichMediaDeactivation::~AnnotRichMediaDeactivation() {
+
+}
+
+AnnotRichMediaSettings::AnnotRichMediaSettings(Dict *dict){
+ Object obj1;
+ //Type name (Optional; ExtensionLevel 3)
+ if (dict->lookup("Type", &obj1)->isName()) {
+ type = obj1.getName();
+ }
+ obj1.free();
+ //Activation dictionary (Optional; ExtensionLevel 3)
+ if (dict->lookup("Activation", &obj1)->isDict()) {
+ activation = new AnnotRichMediaActivation(obj1.getDict());
+ }
+ obj1.free();
+ //Deactivation dictionary (Optional; ExtensionLevel 3)
+ if (dict->lookup("Deactivation", &obj1)->isDict()) {
+ deactivation = new AnnotRichMediaDeactivation(obj1.getDict());
+ }
+ obj1.free();
+}
+
+AnnotRichMediaSettings::~AnnotRichMediaSettings() {
+ if(activation != NULL){
+ delete activation;
+ activation = NULL;
+ }
+ if(deactivation != NULL){
+ delete deactivation;
+ deactivation = NULL;
+ }
+}
+
+
+AnnotRichMedia::AnnotRichMedia(PDFDoc *docA, Dict *dict, Object *obj) :
+ Annot(docA, dict, obj) {
+ type = typeRichMedia;
+ initialize(docA, dict);
+}
+
+AnnotRichMedia::~AnnotRichMedia() {
+ if(settings != NULL){
+ delete settings;
+ settings = NULL;
+ }
+ if(content != NULL){
+ delete content;
+ content = NULL;
+ }
+}
+
+void AnnotRichMedia::initialize(PDFDoc *docA, Dict* dict) {
+ Object obj1;
+
+ //Subtype name (Required; ExtensionLevel 3)
+ if(dict->lookup("Subtype", &obj1)->isName()){
+ char* subtype = obj1.getName();
+ }else{
+ error(errSyntaxError, -1, "Bad Annot RichMedia");
+ //ok = gFalse;
+ }
+ obj1.free();
+
+ //RichMediaSettings dictionary (Optional; ExtensionLevel 3)
+ if (dict->lookup("RichMediaSettings", &obj1)->isDict()) {
+ settings = new AnnotRichMediaSettings(obj1.getDict());
+ }
+ obj1.free();
+
+ //RichMediaContent dictionary (Required; ExtensionLevel 3)
+ if (dict->lookup("RichMediaContent", &obj1)->isDict()) {
+ content = new AnnotRichMediaContent(obj1.getDict());
+ }
+ obj1.free();
+}
+
+void AnnotRichMedia::draw(Gfx *gfx, GBool printing) {}
+
+GooList* AnnotRichMedia::getConfigurations(){
+ GooList* configurations = new GooList();
+ if(content != NULL){
+ configurations->append(content->getConfigurations());
+ }
+ return configurations;
+}
+
+//------------------------------------------------------------------------
// Annots
//------------------------------------------------------------------------
@@ -6639,6 +6916,8 @@ Annot *Annots::createAnnot(Dict* dict, Object *obj) {
annot = NULL;
obj2.free();
+ } else if (!strcmp(typeName, "RichMedia")) {
+ annot = new AnnotRichMedia(doc, dict, obj);
} else {
annot = new Annot(doc, dict, obj);
}
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 68ddeb7..7435fc4 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -54,6 +54,8 @@ class PDFRectangle;
class Movie;
class LinkAction;
class Sound;
+class GooList;
+class FileSpec;
enum AnnotLineEndingStyle {
annotLineEndingSquare, // Square
@@ -73,6 +75,11 @@ enum AnnotExternalDataType {
annotExternalDataMarkup3D // Markup3D
};
+enum AnnotRichMediaSubType {
+ subTypeMovie, // 0
+ subTypeSound // 1
+};
+
//------------------------------------------------------------------------
// AnnotCoord
//------------------------------------------------------------------------
@@ -516,7 +523,8 @@ public:
typePrinterMark, // PrinterMark 22
typeTrapNet, // TrapNet 23
typeWatermark, // Watermark 24
- type3D // 3D 25
+ type3D, // 3D 25
+ typeRichMedia // RichMedia 26
};
/**
@@ -1383,6 +1391,106 @@ private:
};
//------------------------------------------------------------------------
+// AnnotRichMedia
+//------------------------------------------------------------------------
+
+class AnnotRichMediaInstance {
+public:
+ AnnotRichMediaInstance(Dict *dict);
+ ~AnnotRichMediaInstance();
+ int getSubType(){ return subtype; }
+
+private:
+ char* type;
+ int subtype;
+ char* name;
+ FileSpec *fileSpec;
+};
+
+enum RichMediaSubType {
+ richMediaSubTypeUnknown,
+ richMediaSubType3D,
+ richMediaSubTypeFlash,
+ richMediaSubTypeSound,
+ richMediaSubTypeVideo
+};
+class AnnotRichMediaConfiguration {
+public:
+ AnnotRichMediaConfiguration(Dict *dict);
+ ~AnnotRichMediaConfiguration();
+ int getSubType(){ return subtype; }
+ GooList* getInstances(){ return instances; }
+
+private:
+ char* type;
+ int subtype;
+ char* name;
+ GooList* instances;
+
+};
+
+class AnnotRichMediaContent {
+public:
+ AnnotRichMediaContent(Dict *dict);
+ ~AnnotRichMediaContent();
+ GooList* getConfigurations(){ return configurations; }
+ GooList* getAssets(){ return assets; }
+
+private:
+ char* type;
+ GooList* configurations;
+ GooList *assets;
+};
+
+class AnnotRichMediaActivation {
+public:
+ AnnotRichMediaActivation(Dict *dict);
+ ~AnnotRichMediaActivation();
+
+private:
+ char* type;
+ char* condition;
+};
+
+class AnnotRichMediaDeactivation {
+public:
+ AnnotRichMediaDeactivation(Dict *dict);
+ ~AnnotRichMediaDeactivation();
+
+private:
+ char* type;
+ char* condition;
+};
+
+class AnnotRichMediaSettings {
+public:
+ AnnotRichMediaSettings(Dict *dict);
+ ~AnnotRichMediaSettings();
+
+private:
+ char* type;
+ AnnotRichMediaActivation* activation;
+ AnnotRichMediaDeactivation *deactivation;
+};
+
+class AnnotRichMedia: public Annot {
+public:
+ AnnotRichMedia(PDFDoc *docA, Dict *dict, Object *obj);
+ ~AnnotRichMedia();
+ virtual void draw(Gfx *gfx, GBool printing);
+ GooList* getConfigurations();
+ AnnotRichMediaContent* getContent(){ return content; }
+
+private:
+ void initialize(PDFDoc *docA, Dict *dict);
+ int subtype;
+ AnnotRichMediaContent* content;
+ AnnotRichMediaSettings* settings;
+};
+
+
+
+//------------------------------------------------------------------------
// Annots
//------------------------------------------------------------------------
diff --git a/poppler/FileSpec.cc b/poppler/FileSpec.cc
index 1adcf5b..9cb459a 100644
--- a/poppler/FileSpec.cc
+++ b/poppler/FileSpec.cc
@@ -187,12 +187,12 @@ GBool getFileSpecName (Object *fileSpec, Object *fileName)
}
if (fileSpec->isDict()) {
- fileSpec->dictLookup("UF", fileName);
+ fileSpec->dictLookup("F", fileName);
if (fileName->isString()) {
return gTrue;
}
fileName->free();
- fileSpec->dictLookup("F", fileName);
+ fileSpec->dictLookup("UF", fileName);
if (fileName->isString()) {
return gTrue;
}
@@ -224,9 +224,9 @@ GBool getFileSpecNameForPlatform (Object *fileSpec, Object *fileName)
}
if (fileSpec->isDict()) {
- if (!fileSpec->dictLookup("UF", fileName)->isString ()) {
+ if (!fileSpec->dictLookup("F", fileName)->isString ()) {
fileName->free();
- if (!fileSpec->dictLookup("F", fileName)->isString ()) {
+ if (!fileSpec->dictLookup("UF", fileName)->isString ()) {
fileName->free();
#ifdef _WIN32
char *platform = "DOS";
diff --git a/poppler/Sound.cc b/poppler/Sound.cc
index 6129fdc..5f4628c 100644
--- a/poppler/Sound.cc
+++ b/poppler/Sound.cc
@@ -66,13 +66,13 @@ Sound::Sound(Object *obj, bool readAttrs)
Dict *dict = streamObj->getStream()->getDict();
dict->lookup("F", &tmp);
if (!tmp.isNull()) {
- Object obj1;
- // valid 'F' key -> external file
- kind = soundExternal;
- if (getFileSpecNameForPlatform (&tmp, &obj1)) {
- fileName = obj1.getString()->copy();
- obj1.free();
- }
+ Object obj1;
+ // valid 'F' key -> external file
+ kind = soundExternal;
+ if (getFileSpecNameForPlatform (&tmp, &obj1)) {
+ fileName = obj1.getString()->copy();
+ obj1.free();
+ }
} else {
// no file specification, then the sound data have to be
// extracted from the stream
diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc
index 7d60975..8052a02 100644
--- a/utils/HtmlOutputDev.cc
+++ b/utils/HtmlOutputDev.cc
@@ -66,13 +66,14 @@
#include "HtmlUtils.h"
#include "Outline.h"
#include "PDFDoc.h"
+#include "FileSpec.h"
#define DEBUG __FILE__ << ": " << __LINE__ << ": DEBUG: "
class HtmlImage
{
public:
- HtmlImage(GooString *_fName, GfxState *state)
+ HtmlImage(GooString *_fName, GfxState *state)
: fName(_fName) {
state->transform(0, 0, &xMin, &yMax);
state->transform(1, 1, &xMax, &yMin);
@@ -105,7 +106,6 @@ static GBool debug = gFalse;
static GooString *gstr_buff0 = NULL; // a workspace in which I format strings
static GooString* basename(GooString* str){
-
char *p=str->getCString();
int len=str->getLength();
for (int i=len-1;i>=0;i--)
@@ -114,6 +114,15 @@ static GooString* basename(GooString* str){
return new GooString(str);
}
+static const char* extension(GooString* str) {
+ char *p=str->getCString();
+ char *dot = strrchr(p, '.');
+ if(!dot || dot == p)
+ return "";
+ return dot+1;
+}
+
+
#if 0
static GooString* Dirname(GooString* str){
@@ -273,6 +282,8 @@ HtmlPage::HtmlPage(GBool rawOrder, char *imgExtVal) {
fonts=new HtmlFontAccu();
links=new HtmlLinks();
imgList=new GooList();
+ movieList = new GooList();
+ soundList = new GooList();
pageWidth=0;
pageHeight=0;
fontsPageMarker = 0;
@@ -288,6 +299,8 @@ HtmlPage::~HtmlPage() {
delete links;
delete imgExt;
deleteGooList(imgList, HtmlImage);
+ deleteGooList(movieList, HtmlMovie);
+ deleteGooList(soundList, HtmlSound);
}
void HtmlPage::updateFont(GfxState *state) {
@@ -886,8 +899,50 @@ void HtmlPage::dumpComplex(FILE *file, int page){
pageWidth, pageHeight, tmp->getCString(),
(page-firstPage+1), imgExt->getCString());
}
-
delete tmp;
+
+ if(!ignore && withMedia){
+ int listlen=movieList->getLength();
+ GooString *moviefname;
+ for (int i = 0; i < listlen; i++) {
+ HtmlMovie *movie = (HtmlMovie*)movieList->del(0);
+ moviefname=basename(movie->fName);
+ fprintf(pageFile,
+ "",
+ xoutRound(movie->yMin),
+ xoutRound(movie->xMin),
+ xoutRound(movie->xMax-movie->xMin),
+ xoutRound(movie->yMax-movie->yMin));
+
+ fprintf(pageFile,"\n", pageFile);
+ fputs("
\n", pageFile);
+ delete movie;
+ }
+ }
+
+ if(!ignore && withMedia){
+ int listlen=soundList->getLength();
+ GooString *soundfname;
+ for (int i = 0; i < listlen; i++) {
+ HtmlSound *sound = (HtmlSound*)soundList->del(0);
+ soundfname=basename(sound->fName);
+ fprintf(pageFile,
+ "",
+ xoutRound(sound->yMin),
+ xoutRound(sound->xMin),
+ xoutRound(sound->xMax-sound->xMin),
+ xoutRound(sound->yMax-sound->yMin));
+
+ fprintf(pageFile,"
\n", pageFile);
+ fputs("
\n", pageFile);
+ delete sound;
+ }
+ }
+
for(HtmlString *tmp1=yxStrings;tmp1;tmp1=tmp1->yxNext){
if (tmp1->htext){
@@ -1275,6 +1330,33 @@ void HtmlOutputDev::endPage() {
doProcessLink(linksList->getLink(i));
}
delete linksList;
+ Annots *annotsList = docPage->getAnnots();
+ for (int i = 0; i < annotsList->getNumAnnots(); ++i) {
+ Annot *annot = annotsList->getAnnot(i);
+
+
+ if(dynamic_cast(annot) != NULL){
+ //fprintf(stderr, "IS MOVIE.\n");
+ }else if(dynamic_cast(annot) != NULL){
+ doProcessRichMedia(dynamic_cast(annot));
+ }else if(dynamic_cast(annot) != NULL){
+
+ }
+ }
+
+ /*
+ Movies *moviesList = docPage->getMovies();
+ for (int i = 0; i < moviesList->getNumMovies(); ++i) {
+ doProcessMovie(moviesList->getMovie(i));
+ }
+ delete moviesList;
+
+ RichMedias *richMediasList = docPage->getRichMedias();
+ for (int i = 0; i < richMediasList->getNumRichMedias(); ++i) {
+ doProcessRichMedia(richMediasList->getRichMedia(i));
+ }
+ delete richMediasList;
+ */
pages->conv();
pages->coalesce();
@@ -1510,8 +1592,6 @@ void HtmlOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
}
}
-
-
void HtmlOutputDev::doProcessLink(AnnotLink* link){
double _x1,_y1,_x2,_y2;
int x1,y1,x2,y2;
@@ -1840,6 +1920,100 @@ void HtmlOutputDev::newXmlOutlineLevel(FILE *output, GooList *outlines, Catalog*
#endif
}
+GooString *HtmlOutputDev::createMovieFileName(const char *ext)
+{
+ GooString *fName=new GooString(Docname);
+ fName->append("-");
+ GooString *pgNum= GooString::fromInt(pageNum);
+ GooString *imgnum= GooString::fromInt(pages->getNumMovies()+1);//TODO
+
+ fName->append(pgNum)->append("_")->append(imgnum)->append(".")->append(ext);
+ delete pgNum;
+ delete imgnum;
+
+ return fName;
+}
+
+GooString *HtmlOutputDev::createSoundFileName(const char *ext)
+{
+ GooString *fName=new GooString(Docname);
+ fName->append("-");
+ GooString *pgNum= GooString::fromInt(pageNum);
+ GooString *imgnum= GooString::fromInt(pages->getNumSounds()+1);//TODO
+
+ fName->append(pgNum)->append("_")->append(imgnum)->append(".")->append(ext);
+ delete pgNum;
+ delete imgnum;
+
+ return fName;
+}
+
+
+void HtmlOutputDev::doProcessRichMedia(AnnotRichMedia* richMedia){
+ double _x1,_y1,_x2,_y2;
+ int x1,y1,x2,y2;
+
+ richMedia->getRect(&_x1,&_y1,&_x2,&_y2);
+ cvtUserToDev(_x1,_y1,&x1,&y1);
+
+ cvtUserToDev(_x2,_y2,&x2,&y2);
+
+ GooString *fName;
+ AnnotRichMediaContent* content = richMedia->getContent();
+ GooList *assets = content->getAssets();
+
+ FileSpec* fileSpec = NULL;
+ AnnotRichMediaConfiguration* configuration = NULL;
+
+ HtmlMovie* movie;
+ HtmlSound* sound;
+
+ if(assets->getLength() > 0){
+ fileSpec = (FileSpec*) assets->get(0);
+ }
+
+ GooList *configurations = richMedia->getConfigurations();
+ if(configurations->getLength() > 0){
+ configuration = (AnnotRichMediaConfiguration*) configurations->get(0);
+ }
+
+ if(fileSpec != NULL && configuration != NULL){
+ if(configuration->getSubType() == richMediaSubTypeVideo){
+ fName = createMovieFileName(extension(fileSpec->getFileNameForPlatform()));
+ fileSpec->getEmbeddedFile()->save(fName->getCString());
+ movie = new HtmlMovie((double) x1, (double) y2, (double) x2, (double) y1, fName);
+ pages->addMovie(movie);
+ }else if(configuration->getSubType() == richMediaSubTypeSound){
+ fName = createSoundFileName(extension(fileSpec->getFileNameForPlatform()));
+ fileSpec->getEmbeddedFile()->save(fName->getCString());
+ sound = new HtmlSound((double) x1, (double) y2, (double) x2, (double) y1, fName);
+ pages->addSound(sound);
+ }
+ }
+
+
+}
+
+void HtmlOutputDev::doWriteStream(Stream* str, GooString* fileName){
+ if(str != NULL && fileName != NULL){
+ FILE *f1;
+ int c;
+ if (!(f1 = fopen(fileName->getCString(), "wb"))) {
+ error(errIO, -1, "Couldn't open file '%s'", fileName->getCString());
+ return;
+ }
+
+ // initialize stream
+ str->reset();
+
+ // copy the stream
+ while ((c = str->getChar()) != EOF)
+ fputc(c, f1);
+ fclose(f1);
+ }
+}
+
+
#ifndef DISABLE_OUTLINE
int HtmlOutputDev::getOutlinePageNum(OutlineItem *item)
{
diff --git a/utils/HtmlOutputDev.h b/utils/HtmlOutputDev.h
index 12b16bf..cac2f7e 100644
--- a/utils/HtmlOutputDev.h
+++ b/utils/HtmlOutputDev.h
@@ -62,6 +62,48 @@ class GfxState;
class GooString;
class PDFDoc;
class OutlineItem;
+
+
+//------------------------------------------------------------------------
+// HtmlMovie
+//------------------------------------------------------------------------
+class HtmlMovie
+{
+public:
+ HtmlMovie(double x1, double y1, double x2, double y2, GooString* _fName){
+ xMin = x1;
+ yMin = y1;
+ xMax = x2;
+ yMax = y2;
+ fName = _fName;
+ }
+ ~HtmlMovie() { delete fName; }
+
+ double xMin, xMax; // image x coordinates
+ double yMin, yMax; // image y coordinates
+ GooString *fName; // image file name
+};
+
+//------------------------------------------------------------------------
+// HtmlSound
+//------------------------------------------------------------------------
+class HtmlSound
+{
+public:
+ HtmlSound(double x1, double y1, double x2, double y2, GooString* _fName){
+ xMin = x1;
+ yMin = y1;
+ xMax = x2;
+ yMax = y2;
+ fName = _fName;
+ }
+ ~HtmlSound() { delete fName; }
+
+ double xMin, xMax; // image x coordinates
+ double yMin, yMax; // image y coordinates
+ GooString *fName; // image file name
+};
+
//------------------------------------------------------------------------
// HtmlString
//------------------------------------------------------------------------
@@ -160,9 +202,24 @@ public:
// add an image to the current page
void addImage(GooString *fname, GfxState *state);
+ // add an movie to the current page
+ void addMovie(HtmlMovie *movie){
+ movieList->append(movie);
+ }
+ // add an sound to the current page
+ void addSound(HtmlSound *sound){
+ soundList->append(sound);
+ }
+
// number of images on the current page
int getNumImages() { return imgList->getLength(); }
+ // number of movies on the current page
+ int getNumMovies() { return movieList->getLength(); }
+
+ // number of sounds on the current page
+ int getNumSounds() { return soundList->getLength(); }
+
void dump(FILE *f, int pageNum);
// Clear the page.
@@ -186,11 +243,14 @@ private:
void dumpComplex(FILE* f, int page);
int dumpComplexHeaders(FILE * const file, FILE *& pageFile, int page);
+
// marks the position of the fonts that belong to current page (for noframes)
int fontsPageMarker;
HtmlFontAccu *fonts;
HtmlLinks *links;
GooList *imgList;
+ GooList *movieList;
+ GooList *soundList;
GooString *DocName;
GooString *imgExt;
@@ -329,6 +389,10 @@ private:
void drawPngImage(GfxState *state, Stream *str, int width, int height,
GfxImageColorMap *colorMap, GBool isMask = gFalse);
GooString *createImageFileName(const char *ext);
+ GooString *createMovieFileName(const char *ext);
+ GooString *createSoundFileName(const char *ext);
+ void doProcessRichMedia(AnnotRichMedia* richMedia);
+ void doWriteStream(Stream* str, GooString* fileName);
FILE *fContentsFrame;
FILE *page; // html file
--
1.7.10.2 (Apple Git-33)
From d169182965f904f5ef6305e2f063c193d676a816 Mon Sep 17 00:00:00 2001
From: Corentin Allemand
Date: Mon, 5 Nov 2012 14:35:06 +0100
Subject: [PATCH 4/7] Add "div" around "'p"
---
utils/HtmlOutputDev.cc | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc
index 7d60975..6faa100 100644
--- a/utils/HtmlOutputDev.cc
+++ b/utils/HtmlOutputDev.cc
@@ -891,10 +891,13 @@ void HtmlPage::dumpComplex(FILE *file, int page){
for(HtmlString *tmp1=yxStrings;tmp1;tmp1=tmp1->yxNext){
if (tmp1->htext){
+ fprintf(pageFile,"",
+ xoutRound(tmp1->yMin),
+ xoutRound(tmp1->xMin),
+ xoutRound(tmp1->xMax-tmp1->xMin),
+ xoutRound(tmp1->yMax-tmp1->yMin));
fprintf(pageFile,
- "
yMin),
- xoutRound(tmp1->xMin));
+ "
", tmp1->fontpos);
fputs(tmp1->htext->getCString(), pageFile);
fputs("
\n", pageFile);
+ fputs("
\n", pageFile);
}
}
--
1.7.10.2 (Apple Git-33)
From a34618f3b629c0f89657cc11c648d6ec4cb6e64c Mon Sep 17 00:00:00 2001
From: Corentin Allemand
Date: Mon, 5 Nov 2012 14:58:45 +0100
Subject: [PATCH 5/7] Remove carriage return
---
utils/HtmlOutputDev.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc
index 6faa100..f433798 100644
--- a/utils/HtmlOutputDev.cc
+++ b/utils/HtmlOutputDev.cc
@@ -905,7 +905,7 @@ void HtmlPage::dumpComplex(FILE *file, int page){
}
fprintf(pageFile,"%d\">", tmp1->fontpos);
fputs(tmp1->htext->getCString(), pageFile);
- fputs("
\n", pageFile);
+ fputs("", pageFile);
fputs("\n", pageFile);
}
}
--
1.7.10.2 (Apple Git-33)
From a4103bccf0c2b1dded5a8c61ba6ba2a2fcb8c91e Mon Sep 17 00:00:00 2001
From: Corentin Allemand
Date: Mon, 5 Nov 2012 14:59:58 +0100
Subject: [PATCH 6/7] Remove "
---
utils/HtmlOutputDev.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc
index f433798..7fb234e 100644
--- a/utils/HtmlOutputDev.cc
+++ b/utils/HtmlOutputDev.cc
@@ -891,7 +891,7 @@ void HtmlPage::dumpComplex(FILE *file, int page){
for(HtmlString *tmp1=yxStrings;tmp1;tmp1=tmp1->yxNext){
if (tmp1->htext){
- fprintf(pageFile,"",
+ fprintf(pageFile,"
",
xoutRound(tmp1->yMin),
xoutRound(tmp1->xMin),
xoutRound(tmp1->xMax-tmp1->xMin),
--
1.7.10.2 (Apple Git-33)
From 1a2cef1c1a6408deaa944b9ab36369f995d9a32f Mon Sep 17 00:00:00 2001
From: Corentin Allemand
Date: Tue, 20 Nov 2012 14:11:45 +0100
Subject: [PATCH 7/7] Change char* to enum
---
poppler/Annot.cc | 86 ++++++++++++++++++++++++++++++++++++++++++++----------
poppler/Annot.h | 55 ++++++++++++++++++++++++----------
poppler/Sound.cc | 14 ++++-----
3 files changed, 117 insertions(+), 38 deletions(-)
diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index a9807ac..5ca350c 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -6497,23 +6497,28 @@ Annot3D::Activation::Activation(Dict *dict) {
// AnnotRichMedia
//------------------------------------------------------------------------
AnnotRichMediaInstance::AnnotRichMediaInstance(Dict *dict){
+ type = richMediaInstanceType;
subtype = richMediaSubTypeUnknown;
+ fileSpec = NULL;
Object obj1;
//Type name (Optional; ExtensionLevel 3)
if(dict->lookup("Type", &obj1)->isName()){
- type = obj1.getName();
+ const char *name = obj1.getName();
+ if(!strcmp("RichMediaInstance", name)){
+ type = richMediaInstanceType;
+ }
}
obj1.free();
//Subtype name (Optional; ExtensionLevel 3)
if(dict->lookup("Subtype", &obj1)->isName()){
- char *stype = obj1.getName();
- if(strcmp(stype, "3D") == 0){
+ const char *name = obj1.getName();
+ if(strcmp(name, "3D") == 0){
subtype = richMediaSubType3D;
- }else if(strcmp(stype, "Flash") == 0){
+ }else if(strcmp(name, "Flash") == 0){
subtype = richMediaSubTypeFlash;
- }else if(strcmp(stype, "Sound") == 0){
+ }else if(strcmp(name, "Sound") == 0){
subtype = richMediaSubTypeSound;
- }else if(strcmp(stype, "Video") == 0){
+ }else if(strcmp(name, "Video") == 0){
subtype = richMediaSubTypeVideo;
}
}
@@ -6531,18 +6536,26 @@ AnnotRichMediaInstance::AnnotRichMediaInstance(Dict *dict){
}
AnnotRichMediaInstance::~AnnotRichMediaInstance(){
+ if(fileSpec != NULL){
+ delete fileSpec;
+ fileSpec = NULL;
+ }
}
AnnotRichMediaConfiguration::AnnotRichMediaConfiguration(Dict *dict){
instances = new GooList();
+ type = richMediaConfigurationType;
subtype = richMediaSubTypeUnknown;
Object obj1;
Object obj2;
//Type name (Optional; ExtensionLevel 3)
if(dict->lookup("Type", &obj1)->isName()){
- type = obj1.getName();
+ const char *name = obj1.getName();
+ if(!strcmp("RichMediaConfiguration", name)){
+ type = richMediaConfigurationType;
+ }
}
obj1.free();
//Subtype name (Optional; ExtensionLevel 3)
@@ -6579,18 +6592,25 @@ AnnotRichMediaConfiguration::AnnotRichMediaConfiguration(Dict *dict){
}
AnnotRichMediaConfiguration::~AnnotRichMediaConfiguration() {
-
+ if(instances != NULL){
+ delete instances;
+ instances = NULL;
+ }
}
AnnotRichMediaContent::AnnotRichMediaContent(Dict *dict){
Object obj1;
Object obj2;
Object obj3;
+ type = richMediaContentType;
configurations = new GooList();
assets = new GooList();
//Type name (Optional; ExtensionLevel 3)
if (dict->lookup("Type", &obj1)->isName()) {
- type = obj1.getName();
+ const char *name = obj1.getName();
+ if(!strcmp("RichMediaContent", name)){
+ type = richMediaContentType;
+ }
}
obj1.free();
@@ -6639,18 +6659,34 @@ AnnotRichMediaContent::~AnnotRichMediaContent() {
delete configurations;
configurations = NULL;
}
+ if(assets != NULL){
+ delete assets;
+ assets = NULL;
+ }
}
AnnotRichMediaActivation::AnnotRichMediaActivation(Dict *dict){
+ type = richMediaActivationType;
+ condition = activationConditionUserAction;
Object obj1;
//Type name (Optional; ExtensionLevel 3)
if (dict->lookup("Type", &obj1)->isName()) {
- type = obj1.getName();
+ const char *name = obj1.getName();
+ if(!strcmp("RichMediaActivation", name)){
+ type = richMediaActivationType;
+ }
}
obj1.free();
//Condition name (Optional; ExtensionLevel 3)
if (dict->lookup("Condition", &obj1)->isName()) {
- condition = obj1.getName();
+ const char *name = obj1.getName();
+ if(!strcmp("XA", name)){
+ condition = activationConditionUserAction;
+ }else if(!strcmp("PO", name)){
+ condition = activationConditionPageOpened;
+ }else if(!strcmp("PV", name)){
+ condition = activationConditionPageVisible;
+ }
}
obj1.free();
//Animation dictionary (Optional; ExtensionLevel 3)
@@ -6670,15 +6706,27 @@ AnnotRichMediaActivation::~AnnotRichMediaActivation() {
}
AnnotRichMediaDeactivation::AnnotRichMediaDeactivation(Dict *dict){
+ type = richMediaActivationType;
+ condition = deactivationConditionUserAction;
Object obj1;
//Type name (Optional; ExtensionLevel 3)
if (dict->lookup("Type", &obj1)->isName()) {
- type = obj1.getName();
+ const char *name = obj1.getName();
+ if(!strcmp("RichMediaDeactivation", name)){
+ type = richMediaDeactivationType;
+ }
}
obj1.free();
//Condition name (Optional; ExtensionLevel 3)
if (dict->lookup("Condition", &obj1)->isName()) {
- condition = obj1.getName();
+ const char *name = obj1.getName();
+ if(!strcmp("PC", name)){
+ condition = deactivationConditionPageClosed;
+ }else if(!strcmp("PI", name)){
+ condition = deactivationConditionPageInvisible;
+ }else if(!strcmp("XD", name)){
+ condition = deactivationConditionUserAction;
+ }
}
obj1.free();
}
@@ -6688,10 +6736,14 @@ AnnotRichMediaDeactivation::~AnnotRichMediaDeactivation() {
}
AnnotRichMediaSettings::AnnotRichMediaSettings(Dict *dict){
+ type = richMediaSettingsType;
Object obj1;
//Type name (Optional; ExtensionLevel 3)
if (dict->lookup("Type", &obj1)->isName()) {
- type = obj1.getName();
+ const char *name = obj1.getName();
+ if(!strcmp("RichMediaSettings", name)){
+ type = richMediaSettingsType;
+ }
}
obj1.free();
//Activation dictionary (Optional; ExtensionLevel 3)
@@ -6736,11 +6788,15 @@ AnnotRichMedia::~AnnotRichMedia() {
}
void AnnotRichMedia::initialize(PDFDoc *docA, Dict* dict) {
+ subtype = richMediaType;
Object obj1;
//Subtype name (Required; ExtensionLevel 3)
if(dict->lookup("Subtype", &obj1)->isName()){
- char* subtype = obj1.getName();
+ const char *name = obj1.getName();
+ if(!strcmp("RichMedia", name)){
+ subtype = richMediaType;
+ }
}else{
error(errSyntaxError, -1, "Bad Annot RichMedia");
//ok = gFalse;
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 7435fc4..b3fdb71 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -1394,6 +1394,37 @@ private:
// AnnotRichMedia
//------------------------------------------------------------------------
+enum RichMediaActivationCondition{
+ activationConditionUserAction, //XA
+ activationConditionPageOpened, //PO
+ activationConditionPageVisible //PV
+};
+
+enum RichMediaDeactivationCondition {
+ deactivationConditionPageClosed, // PC
+ deactivationConditionPageInvisible, // PI
+ deactivationConditionUserAction // XD
+};
+
+enum RichMediaType{
+ richMediaInstanceType,
+ richMediaConfigurationType,
+ richMediaContentType,
+ richMediaActivationType,
+ richMediaDeactivationType,
+ richMediaSettingsType,
+ richMediaType
+};
+
+enum RichMediaSubType {
+ richMediaSubTypeUnknown,
+ richMediaSubType3D,
+ richMediaSubTypeFlash,
+ richMediaSubTypeSound,
+ richMediaSubTypeVideo
+};
+
+
class AnnotRichMediaInstance {
public:
AnnotRichMediaInstance(Dict *dict);
@@ -1401,19 +1432,11 @@ public:
int getSubType(){ return subtype; }
private:
- char* type;
+ int type;
int subtype;
- char* name;
FileSpec *fileSpec;
};
-enum RichMediaSubType {
- richMediaSubTypeUnknown,
- richMediaSubType3D,
- richMediaSubTypeFlash,
- richMediaSubTypeSound,
- richMediaSubTypeVideo
-};
class AnnotRichMediaConfiguration {
public:
AnnotRichMediaConfiguration(Dict *dict);
@@ -1422,7 +1445,7 @@ public:
GooList* getInstances(){ return instances; }
private:
- char* type;
+ int type;
int subtype;
char* name;
GooList* instances;
@@ -1437,7 +1460,7 @@ public:
GooList* getAssets(){ return assets; }
private:
- char* type;
+ int type;
GooList* configurations;
GooList *assets;
};
@@ -1448,8 +1471,8 @@ public:
~AnnotRichMediaActivation();
private:
- char* type;
- char* condition;
+ int type;
+ int condition;
};
class AnnotRichMediaDeactivation {
@@ -1458,8 +1481,8 @@ public:
~AnnotRichMediaDeactivation();
private:
- char* type;
- char* condition;
+ int type;
+ int condition;
};
class AnnotRichMediaSettings {
@@ -1468,7 +1491,7 @@ public:
~AnnotRichMediaSettings();
private:
- char* type;
+ int type;
AnnotRichMediaActivation* activation;
AnnotRichMediaDeactivation *deactivation;
};
diff --git a/poppler/Sound.cc b/poppler/Sound.cc
index 5f4628c..6129fdc 100644
--- a/poppler/Sound.cc
+++ b/poppler/Sound.cc
@@ -66,13 +66,13 @@ Sound::Sound(Object *obj, bool readAttrs)
Dict *dict = streamObj->getStream()->getDict();
dict->lookup("F", &tmp);
if (!tmp.isNull()) {
- Object obj1;
- // valid 'F' key -> external file
- kind = soundExternal;
- if (getFileSpecNameForPlatform (&tmp, &obj1)) {
- fileName = obj1.getString()->copy();
- obj1.free();
- }
+ Object obj1;
+ // valid 'F' key -> external file
+ kind = soundExternal;
+ if (getFileSpecNameForPlatform (&tmp, &obj1)) {
+ fileName = obj1.getString()->copy();
+ obj1.free();
+ }
} else {
// no file specification, then the sound data have to be
// extracted from the stream
--
1.7.10.2 (Apple Git-33)