diff --git a/poppler/Annot.cc b/poppler/Annot.cc index dae0f62..d910832 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -6494,6 +6494,293 @@ Annot3D::Activation::Activation(Dict *dict) { } //------------------------------------------------------------------------ +// AnnotRichMedia +//------------------------------------------------------------------------ +AnnotRichMediaInstance::AnnotRichMediaInstance(Dict *dict){ + type = richMediaInstanceType; + subtype = richMediaSubTypeUnknown; + fileSpec = NULL; + Object obj1; + obj1.free(); + //Subtype name (Optional; ExtensionLevel 3) + if(dict->lookup("Subtype", &obj1)->isName()){ + const char *name = obj1.getName(); + if(strcmp(name, "3D") == 0){ + subtype = richMediaSubType3D; + }else if(strcmp(name, "Flash") == 0){ + subtype = richMediaSubTypeFlash; + }else if(strcmp(name, "Sound") == 0){ + subtype = richMediaSubTypeSound; + }else if(strcmp(name, "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(){ + if(fileSpec != NULL){ + delete fileSpec; + fileSpec = NULL; + } +} + + + +AnnotRichMediaConfiguration::AnnotRichMediaConfiguration(Dict *dict){ + instances = new GooList(); + type = richMediaConfigurationType; + subtype = richMediaSubTypeUnknown; + Object obj1; + Object obj2; + + //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() { + if(instances != NULL){ + deleteGooList(instances, AnnotRichMediaInstance); + instances = NULL; + } +} + +AnnotRichMediaContent::AnnotRichMediaContent(Dict *dict){ + Object obj1; + Object obj2; + Object obj3; + type = richMediaContentType; + configurations = new GooList(); + assets = new GooList(); + + //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){ + deleteGooList(configurations, AnnotRichMediaConfiguration); + configurations = NULL; + } + if(assets != NULL){ + deleteGooList(assets, FileSpec); + assets = NULL; + } +} + +AnnotRichMediaActivation::AnnotRichMediaActivation(Dict *dict){ + type = richMediaActivationType; + condition = activationConditionUserAction; + Object obj1; + + //Condition name (Optional; ExtensionLevel 3) + if (dict->lookup("Condition", &obj1)->isName()) { + 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) + + //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){ + type = richMediaActivationType; + condition = deactivationConditionUserAction; + Object obj1; + + //Condition name (Optional; ExtensionLevel 3) + if (dict->lookup("Condition", &obj1)->isName()) { + 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(); +} + +AnnotRichMediaDeactivation::~AnnotRichMediaDeactivation() { + +} + +AnnotRichMediaSettings::AnnotRichMediaSettings(Dict *dict){ + type = richMediaSettingsType; + Object obj1; + + //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) { + subtype = richMediaType; + Object obj1; + + //Subtype name (Required; ExtensionLevel 3) + if(dict->lookup("Subtype", &obj1)->isName()){ + subtype = richMediaType; + }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 +6926,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..b3fdb71 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,129 @@ 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); + ~AnnotRichMediaInstance(); + int getSubType(){ return subtype; } + +private: + int type; + int subtype; + FileSpec *fileSpec; +}; + +class AnnotRichMediaConfiguration { +public: + AnnotRichMediaConfiguration(Dict *dict); + ~AnnotRichMediaConfiguration(); + int getSubType(){ return subtype; } + GooList* getInstances(){ return instances; } + +private: + int type; + int subtype; + char* name; + GooList* instances; + +}; + +class AnnotRichMediaContent { +public: + AnnotRichMediaContent(Dict *dict); + ~AnnotRichMediaContent(); + GooList* getConfigurations(){ return configurations; } + GooList* getAssets(){ return assets; } + +private: + int type; + GooList* configurations; + GooList *assets; +}; + +class AnnotRichMediaActivation { +public: + AnnotRichMediaActivation(Dict *dict); + ~AnnotRichMediaActivation(); + +private: + int type; + int condition; +}; + +class AnnotRichMediaDeactivation { +public: + AnnotRichMediaDeactivation(Dict *dict); + ~AnnotRichMediaDeactivation(); + +private: + int type; + int condition; +}; + +class AnnotRichMediaSettings { +public: + AnnotRichMediaSettings(Dict *dict); + ~AnnotRichMediaSettings(); + +private: + int 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 bac1eae..2cfd339 100644 --- a/poppler/FileSpec.cc +++ b/poppler/FileSpec.cc @@ -176,7 +176,6 @@ GooString *FileSpec::getFileNameForPlatform() if (getFileSpecNameForPlatform(&fileSpec, &obj1)) platformFileName = obj1.getString()->copy(); obj1.free(); - return platformFileName; } diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc index e4bd0b1..c4c3ab4 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); @@ -97,6 +98,7 @@ extern GBool stout; extern GBool xml; extern GBool showHidden; extern GBool noMerge; +extern GBool withMedia; extern double wordBreakThreshold; @@ -104,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--) @@ -113,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){ @@ -272,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; @@ -287,6 +299,8 @@ HtmlPage::~HtmlPage() { delete links; delete imgExt; deleteGooList(imgList, HtmlImage); + deleteGooList(movieList, HtmlMovie); + deleteGooList(soundList, HtmlSound); } void HtmlPage::updateFont(GfxState *state) { @@ -877,22 +891,88 @@ void HtmlPage::dumpComplex(FILE *file, int page){ fprintf(pageFile,"
\n", page, pageWidth, pageHeight); - if( !ignore ) + + if( !ignore && !withMedia) { fprintf(pageFile, "\"background\n", 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; + } + } + + 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,"
", + 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("

", pageFile); + fputs("
\n", pageFile); } } + + + fputs("
\n", pageFile); if( !noframes ) @@ -1273,6 +1357,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(); @@ -1463,8 +1574,7 @@ GooString *HtmlOutputDev::createImageFileName(const char *ext) 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) || (complexMode && !xml)) { OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg); return; } @@ -1486,7 +1596,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) || (complexMode && !xml)) { OutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate, maskColors, inlineImg); return; @@ -1508,8 +1618,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; @@ -1838,6 +1946,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 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