diff --git a/poppler/Annot.cc b/poppler/Annot.cc index 18576c8..672f3c6 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -6696,6 +6696,319 @@ Annot3D::Activation::Activation(Dict *dict) { } //------------------------------------------------------------------------ +// AnnotRichMedia +//------------------------------------------------------------------------ +AnnotRichMedia::AnnotRichMedia(PDFDoc *docA, PDFRectangle *rect) : + Annot(docA, rect) { + Object obj1; + + type = typeRichMedia; + + annotObj.dictSet ("Subtype", obj1.initName ("RichMedia")); + + initialize(docA, annotObj.getDict()); +} + +AnnotRichMedia::AnnotRichMedia(PDFDoc *docA, Dict *dict, Object *obj) : + Annot(docA, dict, obj) { + type = typeRichMedia; + initialize(docA, dict); +} + +AnnotRichMedia::~AnnotRichMedia() { + delete content; + delete settings; +} + +void AnnotRichMedia::initialize(PDFDoc *docA, Dict* dict) { + Object obj1; + + if (dict->lookup("RichMediaContent", &obj1)->isDict()) { + content = new AnnotRichMedia::Content(obj1.getDict()); + } else { + content = NULL; + } + obj1.free(); + + if (dict->lookup("RichMediaSettings", &obj1)->isDict()) { + settings = new AnnotRichMedia::Settings(obj1.getDict()); + } else { + settings = NULL; + } + obj1.free(); +} + +AnnotRichMedia::Settings::Settings(Dict *dict) { + Object obj1; + + if (dict->lookup("Activation", &obj1)->isDict()) { + activation = new AnnotRichMedia::Activation(obj1.getDict()); + } else { + activation = NULL; + } + obj1.free(); + + if (dict->lookup("Deactivation", &obj1)->isDict()) { + deactivation = new AnnotRichMedia::Deactivation(obj1.getDict()); + } else { + deactivation = NULL; + } + obj1.free(); +} + +AnnotRichMedia::Settings::~Settings() { + delete activation; + delete deactivation; +} + +AnnotRichMedia::Activation::Activation(Dict *dict) { + Object obj1; + + if (dict->lookup("Condition", &obj1)->isName()) { + const char *name = obj1.getName(); + + if (!strcmp(name, "PO")) { + condition = conditionPageOpened; + } else if (!strcmp(name, "PV")) { + condition = conditionPageVisible; + } else if (!strcmp(name, "XA")) { + condition = conditionUserAction; + } + } else { + condition = conditionUserAction; + } + obj1.free(); +} + +AnnotRichMedia::Deactivation::Deactivation(Dict *dict) { + Object obj1; + + if (dict->lookup("Condition", &obj1)->isName()) { + const char *name = obj1.getName(); + + if (!strcmp(name, "PC")) { + condition = conditionPageClosed; + } else if (!strcmp(name, "PI")) { + condition = conditionPageInvisible; + } else if (!strcmp(name, "XD")) { + condition = conditionUserAction; + } + } else { + condition = conditionUserAction; + } + obj1.free(); +} + +AnnotRichMedia::Content::Content(Dict *dict) { + Object obj1; + + if (dict->lookup("Configurations", &obj1)->isArray()) { + nConfigurations = obj1.arrayGetLength(); + + configurations = (Configuration **)gmallocn(nConfigurations, sizeof(Configuration *)); + memset(configurations, 0, nConfigurations * sizeof(Configuration *)); + + for (int i = 0; i < nConfigurations; ++i) { + Object obj2; + + if (obj1.arrayGet(i, &obj2)->isDict()) { + configurations[i] = new AnnotRichMedia::Configuration(obj2.getDict()); + } + obj2.free(); + } + } else { + configurations = NULL; + } + obj1.free(); + + if (dict->lookup("Assets", &obj1)->isDict()) { + Object obj2; + + if (obj1.getDict()->lookup("Names", &obj2)->isArray()) { + nAssets = obj2.arrayGetLength() / 2; + + assets = (Asset **)gmallocn(nAssets, sizeof(Asset *)); + memset(assets, 0, nAssets * sizeof(Asset *)); + + int counter = 0; + for (int i = 0; i < obj2.arrayGetLength(); i += 2) { + Object objKey; + + assets[counter] = new AnnotRichMedia::Asset; + + obj2.arrayGet(i, &objKey); + obj2.arrayGet(i + 1, &assets[counter]->fileSpec); + + assets[counter]->name = new GooString( objKey.getString() ); + ++counter; + + objKey.free(); + } + } + obj2.free(); + + } else { + assets = NULL; + } + obj1.free(); +} + +AnnotRichMedia::Content::~Content() { + if (configurations) { + for (int i = 0; i < nConfigurations; ++i) + delete configurations[i]; + gfree(configurations); + } + + if (assets) { + for (int i = 0; i < nAssets; ++i) + delete assets[i]; + gfree(assets); + } +} + +AnnotRichMedia::Asset::Asset() + : name(NULL) +{ +} + +AnnotRichMedia::Asset::~Asset() +{ + delete name; + fileSpec.free(); +} + +AnnotRichMedia::Configuration::Configuration(Dict *dict) +{ + Object obj1; + + if (dict->lookup("Instances", &obj1)->isArray()) { + nInstances = obj1.arrayGetLength(); + + instances = (Instance **)gmallocn(nInstances, sizeof(Instance *)); + memset(instances, 0, nInstances * sizeof(Instance *)); + + for (int i = 0; i < nInstances; ++i) { + Object obj2; + + if (obj1.arrayGet(i, &obj2)->isDict()) { + instances[i] = new AnnotRichMedia::Instance(obj2.getDict()); + } + obj2.free(); + } + } else { + instances = NULL; + } + obj1.free(); + + if (dict->lookup("Name", &obj1)->isString()) { + name = new GooString(obj1.getString()); + } else { + name = NULL; + } + obj1.free(); + + if (dict->lookup("Subtype", &obj1)->isName()) { + const char *name = obj1.getName(); + + if (!strcmp(name, "3D")) { + type = type3D; + } else if (!strcmp(name, "Flash")) { + type = typeFlash; + } else if (!strcmp(name, "Sound")) { + type = typeSound; + } else if (!strcmp(name, "Video")) { + type = typeVideo; + } else { + // determine from first instance + if (instances && nInstances > 0) { + AnnotRichMedia::Instance *instance = instances[0]; + switch (instance->type) { + case AnnotRichMedia::Instance::type3D: + type = type3D; + break; + case AnnotRichMedia::Instance::typeFlash: + type = typeFlash; + break; + case AnnotRichMedia::Instance::typeSound: + type = typeSound; + break; + case AnnotRichMedia::Instance::typeVideo: + type = typeVideo; + break; + default: + type = typeFlash; + break; + } + } + } + } + obj1.free(); + +} + +AnnotRichMedia::Configuration::~Configuration() +{ + if (instances) { + for (int i = 0; i < nInstances; ++i) + delete instances[i]; + gfree(instances); + } + + delete name; +} + +AnnotRichMedia::Instance::Instance(Dict *dict) +{ + Object obj1; + + if (dict->lookup("Subtype", &obj1)->isName()) { + const char *name = obj1.getName(); + + if (!strcmp(name, "3D")) { + type = type3D; + } else if (!strcmp(name, "Flash")) { + type = typeFlash; + } else if (!strcmp(name, "Sound")) { + type = typeSound; + } else if (!strcmp(name, "Video")) { + type = typeVideo; + } else { + type = typeFlash; + } + } + obj1.free(); + + if (dict->lookup("Params", &obj1)->isDict()) { + params = new AnnotRichMedia::Params(obj1.getDict()); + } else { + params = NULL; + } +} + +AnnotRichMedia::Instance::~Instance() +{ + delete params; +} + +AnnotRichMedia::Params::Params(Dict *dict) +{ + Object obj1; + + if (dict->lookup("FlashVars", &obj1)->isString()) { + flashVars = new GooString(obj1.getString()); + } else { + flashVars = NULL; + } + obj1.free(); +} + +AnnotRichMedia::Params::~Params() +{ + delete flashVars; +} + +//------------------------------------------------------------------------ // Annots //------------------------------------------------------------------------ @@ -6828,6 +7141,8 @@ Annot *Annots::createAnnot(Dict* dict, Object *obj) { annot = new Annot(doc, dict, obj); } else if (!strcmp(typeName, "3D")) { annot = new Annot3D(doc, dict, obj); + } else if (!strcmp(typeName, "RichMedia")) { + annot = new AnnotRichMedia(doc, dict, obj); } else if (!strcmp(typeName, "Popup")) { /* Popup annots are already handled by markup annots * Here we only care about popup annots without a diff --git a/poppler/Annot.h b/poppler/Annot.h index 1e64f59..acf4848 100644 --- a/poppler/Annot.h +++ b/poppler/Annot.h @@ -56,6 +56,7 @@ class PDFRectangle; class Movie; class LinkAction; class Sound; +class FileSpec; enum AnnotLineEndingStyle { annotLineEndingSquare, // Square @@ -526,7 +527,8 @@ public: typePrinterMark, // PrinterMark 22 typeTrapNet, // TrapNet 23 typeWatermark, // Watermark 24 - type3D // 3D 25 + type3D, // 3D 25 + typeRichMedia // RichMedia 26 }; /** @@ -1409,6 +1411,132 @@ private: }; //------------------------------------------------------------------------ +// AnnotRichMedia +//------------------------------------------------------------------------ + +class AnnotRichMedia: public Annot { +public: + class Params { + public: + Params(Dict *dict); + ~Params(); + + // optional + GooString *flashVars; // FlashVars + }; + + class Instance { + public: + enum Type { + type3D, // 3D + typeFlash, // Flash + typeSound, // Sound + typeVideo // Video + }; + + Instance(Dict *dict); + ~Instance(); + + // optional + Type type; // Subtype + Params *params; // Params + }; + + class Configuration { + public: + enum Type { + type3D, // 3D + typeFlash, // Flash + typeSound, // Sound + typeVideo // Video + }; + + Configuration(Dict *dict); + ~Configuration(); + + // optional + Type type; // Subtype + GooString *name; // Name + Instance **instances; // Instances + int nInstances; + }; + + class Asset { + public: + Asset(); + ~Asset(); + + GooString *name; + Object fileSpec; + }; + + class Content { + public: + Content(Dict *dict); + ~Content(); + + // optional + Configuration **configurations; // Configurations + int nConfigurations; + + Asset **assets; // Assets + int nAssets; + }; + + class Activation { + public: + enum Condition { + conditionPageOpened, // PO + conditionPageVisible, // PV + conditionUserAction // XA + }; + + Activation(Dict *dict); + + // optional + Condition condition; + }; + + class Deactivation { + public: + enum Condition { + conditionPageClosed, // PC + conditionPageInvisible, // PI + conditionUserAction // XD + }; + + Deactivation(Dict *dict); + + // optional + Condition condition; + }; + + class Settings { + public: + Settings(Dict *dict); + ~Settings(); + + // optional + Activation *activation; + Deactivation *deactivation; + }; + + AnnotRichMedia(PDFDoc *docA, PDFRectangle *rect); + AnnotRichMedia(PDFDoc *docA, Dict *dict, Object *obj); + ~AnnotRichMedia(); + + // required + Content *content; // RichMediaContent + + // optional + Settings *settings; // RichMediaSettings + +private: + void initialize(PDFDoc *docA, Dict *dict); +}; + + +//------------------------------------------------------------------------ // Annots //------------------------------------------------------------------------