//********************************************************************************* // Rendition.cc //--------------------------------------------------------------------------------- // //--------------------------------------------------------------------------------- // Hugo Mercier (c) 2008 // Pino Toscano (c) 2008 // Carlos Garcia Campos (c) 2010 // Tobias Koenig (c) 2012 // Albert Astals Cid (C) 2017, 2018 // // 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 = true; hasCloseButton = true; isResizeable = true; } MediaWindowParameters::~MediaWindowParameters() { } void MediaWindowParameters::parseFWParams(Object *obj) { Object tmp = obj->dictLookup("D"); if (tmp.isArray()) { Array *dim = tmp.getArray(); if (dim->getLength() >= 2) { Object dd = dim->get(0); if (dd.isInt()) { width = dd.getInt(); } dd = dim->get(1); if (dd.isInt()) { height = dd.getInt(); } } } tmp = obj->dictLookup("RT"); if (tmp.isInt()) { int t = tmp.getInt(); switch (t) { case 0: relativeTo = windowRelativeToDocument; break; case 1: relativeTo = windowRelativeToApplication; break; case 2: relativeTo = windowRelativeToDesktop; break; } } tmp = obj->dictLookup("P"); if (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 = obj->dictLookup("T"); if (tmp.isBool()) { hasTitleBar = tmp.getBool(); } tmp = obj->dictLookup("UC"); if (tmp.isBool()) { hasCloseButton = tmp.getBool(); } tmp = obj->dictLookup("R"); if (tmp.isInt()) { isResizeable = (tmp.getInt() != 0); } } MediaParameters::MediaParameters() { // instanciate to default values volume = 100; fittingPolicy = fittingUndefined; autoPlay = true; repeatCount = 1.0; opacity = 1.0; showControls = false; duration = 0; } MediaParameters::~MediaParameters() { } void MediaParameters::parseMediaPlayParameters(Object *obj) { Object tmp = obj->dictLookup("V"); if (tmp.isInt()) { volume = tmp.getInt(); } tmp = obj->dictLookup("C"); if (tmp.isBool()) { showControls = tmp.getBool(); } tmp = obj->dictLookup("F"); if (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; } } // duration parsing // duration's default value is set to 0, which means : intrinsinc media duration tmp = obj->dictLookup("D"); if (tmp.isDict()) { Object oname = tmp.dictLookup("S"); if (oname.isName()) { const char *name = oname.getName(); if (!strcmp(name, "F")) duration = -1; // infinity else if (!strcmp(name, "T")) { Object ddict = tmp.dictLookup("T"); if (ddict.isDict()) { Object tmp2 = ddict.dictLookup("V"); if (tmp2.isNum()) { duration = (unsigned long)(tmp2.getNum()); } } } } } tmp = obj->dictLookup("A"); if (tmp.isBool()) { autoPlay = tmp.getBool(); } tmp = obj->dictLookup("RC"); if (tmp.isNum()) { repeatCount = tmp.getNum(); } } void MediaParameters::parseMediaScreenParameters(Object *obj) { Object tmp = obj->dictLookup("W"); if (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; } } // background color tmp = obj->dictLookup("B"); if (tmp.isArray()) { Array *color = tmp.getArray(); Object component = color->get(0); bgColor.r = component.getNum(); component = color->get(1); bgColor.g = component.getNum(); component = color->get(2); bgColor.b = component.getNum(); } // opacity tmp = obj->dictLookup("O"); if (tmp.isNum()) { opacity = tmp.getNum(); } if (windowParams.type == MediaWindowParameters::windowFloating) { Object winDict = obj->dictLookup("F"); if (winDict.isDict()) { windowParams.parseFWParams(&winDict); } } } MediaRendition::~MediaRendition() { delete fileName; delete contentType; } MediaRendition::MediaRendition(Object *obj) { bool hasClip = false; ok = true; fileName = nullptr; contentType = nullptr; isEmbedded = false; // // Parse media clip data // Object tmp2 = obj->dictLookup("C"); if (tmp2.isDict()) { // media clip hasClip = true; Object tmp = tmp2.dictLookup("S"); if (tmp.isName()) { if (!strcmp(tmp.getName(), "MCD")) { // media clip data Object obj1 = tmp2.dictLookup("D"); if (obj1.isDict()) { Object obj2 = obj1.dictLookup("F"); if (obj2.isString()) { fileName = obj2.getString()->copy(); } obj2 = obj1.dictLookup("EF"); if (obj2.isDict()) { Object embedded = obj2.dictLookup("F"); if (embedded.isStream()) { isEmbedded = true; embeddedStreamObject = embedded.copy(); } } // TODO: D might be a form XObject too } else { error(errSyntaxError, -1, "Invalid Media Clip Data"); ok = false; } // FIXME: ignore CT if D is a form XObject obj1 = tmp2.dictLookup("CT"); if (obj1.isString()) { contentType = obj1.getString()->copy(); } } else if (!strcmp(tmp.getName(), "MCS")) { // media clip data // TODO } } else { error(errSyntaxError, -1, "Invalid Media Clip"); ok = false; } } if (!ok) return; // // parse Media Play Parameters tmp2 = obj->dictLookup("P"); if (tmp2.isDict()) { // media play parameters Object params = tmp2.dictLookup("MH"); if (params.isDict()) { MH.parseMediaPlayParameters(¶ms); } params = tmp2.dictLookup("BE"); if (params.isDict()) { BE.parseMediaPlayParameters(¶ms); } } else if (!hasClip) { error(errSyntaxError, -1, "Invalid Media Rendition"); ok = false; } // // parse Media Screen Parameters tmp2 = obj->dictLookup("SP"); if (tmp2.isDict()) { // media screen parameters Object params = tmp2.dictLookup("MH"); if (params.isDict()) { MH.parseMediaScreenParameters(¶ms); } params = tmp2.dictLookup("BE"); if (params.isDict()) { BE.parseMediaScreenParameters(¶ms); } } } MediaRendition::MediaRendition(const MediaRendition &other) { ok = other.ok; MH = other.MH; BE = other.BE; isEmbedded = other.isEmbedded; embeddedStreamObject = other.embeddedStreamObject.copy(); if (other.contentType) contentType = other.contentType->copy(); else contentType = nullptr; if (other.fileName) fileName = other.fileName->copy(); else fileName = nullptr; } void MediaRendition::outputToFile(FILE *fp) { if (!isEmbedded) return; embeddedStreamObject.streamReset(); while (true) { int c = embeddedStreamObject.streamGetChar(); if (c == EOF) break; fwrite(&c, 1, 1, fp); } } MediaRendition *MediaRendition::copy() const { return new MediaRendition(*this); } // TODO: SelectorRendition