//********************************************************************************* // Rendition.cc //--------------------------------------------------------------------------------- // //--------------------------------------------------------------------------------- // Hugo Mercier (c) 2008 // Pino Toscano (c) 2008 // Carlos Garcia Campos (c) 2010 // Tobias Koenig (c) 2012 // // 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. // // 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 #include "Rendition.h" #include "FileSpec.h" MediaWindowParameters::MediaWindowParameters() { // default values type = windowEmbedded; width = -1; height = -1; relativeTo = windowRelativeToDocument; XPosition = 0.5; YPosition = 0.5; hasTitleBar = gTrue; hasCloseButton = gTrue; isResizeable = gTrue; } MediaWindowParameters::~MediaWindowParameters() { } void MediaWindowParameters::parseFWParams(Object* obj) { Object tmp; if (obj->dictLookup("D", &tmp)->isArray()) { Array * dim = tmp.getArray(); if (dim->getLength() >= 2) { Object dd; if (dim->get(0, &dd)->isInt()) { width = dd.getInt(); } dd.free(); if (dim->get(1, &dd)->isInt()) { height = dd.getInt(); } dd.free(); } } tmp.free(); if (obj->dictLookup("RT", &tmp)->isInt()) { int t = tmp.getInt(); switch(t) { case 0: relativeTo = windowRelativeToDocument; break; case 1: relativeTo = windowRelativeToApplication; break; case 2: relativeTo = windowRelativeToDesktop; break; } } tmp.free(); if (obj->dictLookup("P",&tmp)->isInt()) { int t = tmp.getInt(); switch(t) { case 0: // Upper left XPosition = 0.0; YPosition = 0.0; break; case 1: // Upper Center XPosition = 0.5; YPosition = 0.0; break; case 2: // Upper Right XPosition = 1.0; YPosition = 0.0; break; case 3: // Center Left XPosition = 0.0; YPosition = 0.5; break; case 4: // Center XPosition = 0.5; YPosition = 0.5; break; case 5: // Center Right XPosition = 1.0; YPosition = 0.5; break; case 6: // Lower Left XPosition = 0.0; YPosition = 1.0; break; case 7: // Lower Center XPosition = 0.5; YPosition = 1.0; break; case 8: // Lower Right XPosition = 1.0; YPosition = 1.0; break; } } tmp.free(); if (obj->dictLookup("T", &tmp)->isBool()) { hasTitleBar = tmp.getBool(); } tmp.free(); if (obj->dictLookup("UC", &tmp)->isBool()) { hasCloseButton = tmp.getBool(); } tmp.free(); if (obj->dictLookup("R", &tmp)->isInt()) { isResizeable = (tmp.getInt() != 0); } tmp.free(); } MediaParameters::MediaParameters() { // instanciate to default values volume = 100; fittingPolicy = fittingUndefined; autoPlay = gTrue; repeatCount = 1.0; opacity = 1.0; showControls = gFalse; duration = 0; } MediaParameters::~MediaParameters() { } void MediaParameters::parseMediaPlayParameters(Object* obj) { Object tmp; if (obj->dictLookup("V", &tmp)->isInt()) { volume = tmp.getInt(); } tmp.free(); if (obj->dictLookup("C", &tmp)->isBool()) { showControls = tmp.getBool(); } tmp.free(); if (obj->dictLookup("F", &tmp)->isInt()) { int t = tmp.getInt(); switch(t) { case 0: fittingPolicy = fittingMeet; break; case 1: fittingPolicy = fittingSlice; break; case 2: fittingPolicy = fittingFill; break; case 3: fittingPolicy = fittingScroll; break; case 4: fittingPolicy = fittingHidden; break; case 5: fittingPolicy = fittingUndefined; break; } } tmp.free(); // duration parsing // duration's default value is set to 0, which means : intrinsinc media duration if (obj->dictLookup("D", &tmp)->isDict()) { Object oname, ddict, tmp2; if (tmp.dictLookup("S", &oname)->isName()) { char* name = oname.getName(); if (!strcmp(name, "F")) duration = -1; // infinity else if (!strcmp(name, "T")) { if (tmp.dictLookup("T", &ddict)->isDict()) { if (ddict.dictLookup("V", &tmp2)->isNum()) { duration = Gulong(tmp2.getNum()); } tmp2.free(); } ddict.free(); } } oname.free(); } tmp.free(); if (obj->dictLookup("A", &tmp)->isBool()) { autoPlay = tmp.getBool(); } tmp.free(); if (obj->dictLookup("RC", &tmp)->isNum()) { repeatCount = tmp.getNum(); } tmp.free(); } void MediaParameters::parseMediaScreenParameters(Object* obj) { Object tmp; if (obj->dictLookup("W", &tmp)->isInt()) { int t = tmp.getInt(); switch(t) { case 0: windowParams.type = MediaWindowParameters::windowFloating; break; case 1: windowParams.type = MediaWindowParameters::windowFullscreen; break; case 2: windowParams.type = MediaWindowParameters::windowHidden; break; case 3: windowParams.type = MediaWindowParameters::windowEmbedded; break; } } tmp.free(); // background color if (obj->dictLookup("B", &tmp)->isArray()) { Array* color = tmp.getArray(); Object component; color->get(0, &component); bgColor.r = component.getNum(); component.free(); color->get(1, &component); bgColor.g = component.getNum(); component.free(); color->get(2, &component); bgColor.b = component.getNum(); component.free(); } tmp.free(); // opacity if (obj->dictLookup("O", &tmp)->isNum()) { opacity = tmp.getNum(); } tmp.free(); if (windowParams.type == MediaWindowParameters::windowFloating) { Object winDict; if (obj->dictLookup("F",&winDict)->isDict()) { windowParams.parseFWParams(&winDict); } winDict.free(); } } MediaRendition::~MediaRendition() { if (fileName) delete fileName; if (contentType) delete contentType; if (embeddedStream && (!embeddedStream->decRef())) { delete embeddedStream; } } MediaRendition::MediaRendition(Object* obj) { Object tmp, tmp2; GBool hasClip = gFalse; ok = gTrue; fileName = NULL; contentType = NULL; isEmbedded = gFalse; embeddedStream = NULL; // // Parse media clip data // if (obj->dictLookup("C", &tmp2)->isDict()) { // media clip hasClip = gTrue; if (tmp2.dictLookup("S", &tmp)->isName()) { if (!strcmp(tmp.getName(), "MCD")) { // media clip data Object obj1, obj2; if (tmp2.dictLookup("D", &obj1)->isDict()) { if (obj1.dictLookup("F", &obj2)->isString()) { fileName = obj2.getString()->copy(); } obj2.free(); if (obj1.dictLookup("EF", &obj2)->isDict()) { Object embedded; if (obj2.dictLookup("F", &embedded)->isStream()) { isEmbedded = gTrue; embeddedStream = embedded.getStream(); // "copy" stream embeddedStream->incRef(); } embedded.free(); } obj2.free(); // TODO: D might be a form XObject too } else { error (errSyntaxError, -1, "Invalid Media Clip Data"); ok = gFalse; } obj1.free(); // FIXME: ignore CT if D is a form XObject if (tmp2.dictLookup("CT", &obj1)->isString()) { contentType = obj1.getString()->copy(); } obj1.free(); } else if (!strcmp(tmp.getName(), "MCS")) { // media clip data // TODO } } else { error (errSyntaxError, -1, "Invalid Media Clip"); ok = gFalse; } tmp.free(); } tmp2.free(); if (!ok) return; // // parse Media Play Parameters if (obj->dictLookup("P", &tmp2)->isDict()) { // media play parameters Object params; if (tmp2.dictLookup("MH", ¶ms)->isDict()) { MH.parseMediaPlayParameters(¶ms); } params.free(); if (tmp2.dictLookup("BE", ¶ms)->isDict()) { BE.parseMediaPlayParameters(¶ms); } params.free(); } else if (!hasClip) { error (errSyntaxError, -1, "Invalid Media Rendition"); ok = gFalse; } tmp2.free(); // // parse Media Screen Parameters if (obj->dictLookup("SP", &tmp2)->isDict()) { // media screen parameters Object params; if (tmp2.dictLookup("MH", ¶ms)->isDict()) { MH.parseMediaScreenParameters(¶ms); } params.free(); if (tmp2.dictLookup("BE", ¶ms)->isDict()) { BE.parseMediaScreenParameters(¶ms); } params.free(); } tmp2.free(); } void MediaRendition::outputToFile(FILE* fp) { if (!isEmbedded) return; embeddedStream->reset(); while (1) { int c = embeddedStream->getChar(); if (c == EOF) break; fwrite(&c, 1, 1, fp); } } MediaRendition *MediaRendition::copy() { // call default copy constructor MediaRendition* new_media = new MediaRendition(*this); if (contentType) new_media->contentType = contentType->copy(); if (fileName) new_media->fileName = fileName->copy(); if (new_media->embeddedStream) new_media->embeddedStream->incRef(); return new_media; } // TODO: SelectorRendition