diff options
Diffstat (limited to 'src/player/ImageNode.cpp')
-rw-r--r-- | src/player/ImageNode.cpp | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/src/player/ImageNode.cpp b/src/player/ImageNode.cpp new file mode 100644 index 0000000..18543c2 --- /dev/null +++ b/src/player/ImageNode.cpp @@ -0,0 +1,241 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "ImageNode.h" + +#include "TypeDefinition.h" +#include "OGLSurface.h" +#include "Player.h" +#include "OffscreenCanvas.h" + +#include "../base/Logger.h" +#include "../base/ScopeTimer.h" +#include "../base/XMLHelper.h" +#include "../base/Exception.h" +#include "../base/ObjectCounter.h" + +#include "../graphics/Filterfliprgb.h" + +#include <iostream> +#include <sstream> + +using namespace std; + +namespace avg { + +void ImageNode::registerType() +{ + TypeDefinition def = TypeDefinition("image", "rasternode", + ExportedObject::buildObject<ImageNode>) + .addArg(Arg<UTF8String>("href", "", false, offsetof(ImageNode, m_href))) + .addArg(Arg<string>("compression", "none")); + TypeRegistry::get()->registerType(def); +} + +ImageNode::ImageNode(const ArgList& args) + : m_Compression(Image::TEXTURECOMPRESSION_NONE) +{ + args.setMembers(this); + m_pImage = ImagePtr(new Image(getSurface(), getMaterial())); + m_Compression = Image::string2compression(args.getArgVal<string>("compression")); + setHRef(m_href); + ObjectCounter::get()->incRef(&typeid(*this)); +} + +ImageNode::~ImageNode() +{ + // XXX: The following assert checks that disconnect(true) has been called. + // However, if connect() has been called but rendering never started, + // disconnect isn't called either. +// AVG_ASSERT(!m_pImage->getCanvas()); + ObjectCounter::get()->decRef(&typeid(*this)); +} + +void ImageNode::connectDisplay() +{ + if (m_pImage->getSource() == Image::SCENE) { + checkCanvasValid(m_pImage->getCanvas()); + } + m_pImage->moveToGPU(); + RasterNode::connectDisplay(); + if (m_pImage->getSource() == Image::SCENE) { + m_pImage->getCanvas()->addDependentCanvas(getCanvas()); + } +} + +void ImageNode::connect(CanvasPtr pCanvas) +{ + RasterNode::connect(pCanvas); + checkReload(); +} + +void ImageNode::disconnect(bool bKill) +{ + OffscreenCanvasPtr pCanvas = m_pImage->getCanvas(); + if (pCanvas) { + pCanvas->removeDependentCanvas(getCanvas()); + } + if (bKill) { + RasterNode::disconnect(bKill); + m_pImage = ImagePtr(new Image(getSurface(), getMaterial())); + m_href = ""; + } else { + m_pImage->moveToCPU(); + RasterNode::disconnect(bKill); + } +} + +const UTF8String& ImageNode::getHRef() const +{ + return m_href; +} + +void ImageNode::setHRef(const UTF8String& href) +{ + m_href = href; + if (m_pImage->getSource() == Image::SCENE && getState() == Node::NS_CANRENDER) + { + m_pImage->getCanvas()->removeDependentCanvas(getCanvas()); + } + try { + if (href == "") { + m_pImage->setEmpty(); + } else { + checkReload(); + } + } catch (const Exception&) { + m_href = ""; + m_pImage->setEmpty(); + throw; + } +} + +const string ImageNode::getCompression() const +{ + return Image::compression2String(m_Compression); +} + +void ImageNode::setBitmap(BitmapPtr pBmp) +{ + if (m_pImage->getSource() == Image::SCENE && getState() == Node::NS_CANRENDER) { + m_pImage->getCanvas()->removeDependentCanvas(getCanvas()); + } + m_pImage->setBitmap(pBmp, m_Compression); + if (getState() == Node::NS_CANRENDER) { + newSurface(); + } + m_href = ""; + setViewport(-32767, -32767, -32767, -32767); +} + +static ProfilingZoneID PrerenderProfilingZone("ImageNode::prerender"); + +void ImageNode::preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity) +{ + ScopeTimer timer(PrerenderProfilingZone); + Node::preRender(pVA, bIsParentActive, parentEffectiveOpacity); + if (isVisible()) { + bool bHasCanvas = bool(m_pImage->getCanvas()); + if (m_pImage->getSource() != Image::NONE) { + renderFX(getSize(), Pixel32(255, 255, 255, 255), bHasCanvas, bHasCanvas); + } + } + calcVertexArray(pVA); +} + +static ProfilingZoneID RenderProfilingZone("ImageNode::render"); + +void ImageNode::render() +{ + ScopeTimer Timer(RenderProfilingZone); + if (m_pImage->getSource() != Image::NONE) { + blt32(getTransform(), getSize(), getEffectiveOpacity(), getBlendMode(), + bool(m_pImage->getCanvas())); + } +} + +IntPoint ImageNode::getMediaSize() +{ + return m_pImage->getSize(); +} + +void ImageNode::checkReload() +{ + if (isCanvasURL(m_href)) { + if (m_Compression != Image::TEXTURECOMPRESSION_NONE) { + throw Exception(AVG_ERR_UNSUPPORTED, + "Texture compression can't be used with canvas hrefs."); + } + OffscreenCanvasPtr pCanvas = Player::get()->getCanvasFromURL(m_href); + checkCanvasValid(pCanvas); + m_pImage->setCanvas(pCanvas); + if (getState() == NS_CANRENDER) { + pCanvas->addDependentCanvas(getCanvas()); + } + newSurface(); + } else { + bool bNewImage = Node::checkReload(m_href, m_pImage, m_Compression); + if (bNewImage) { + newSurface(); + } + } + setViewport(-32767, -32767, -32767, -32767); + RasterNode::checkReload(); +} + +void ImageNode::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements) +{ + if (reactsToMouseEvents()) { + OffscreenCanvasPtr pCanvas = m_pImage->getCanvas(); + if (pCanvas && pCanvas->getHandleEvents()) { + glm::vec2 nodeSize(getSize()); + glm::vec2 canvasSize(pCanvas->getSize()); + glm::vec2 localPos(pos.x*(canvasSize.x/nodeSize.x), + pos.y*(canvasSize.y/nodeSize.y)); + pCanvas->getRootNode()->getElementsByPos(localPos, pElements); + } else { + RasterNode::getElementsByPos(pos, pElements); + } + } +} + +BitmapPtr ImageNode::getBitmap() +{ + return m_pImage->getBitmap(); +} + +bool ImageNode::isCanvasURL(const std::string& sURL) +{ + return sURL.find("canvas:") == 0; +} + +void ImageNode::checkCanvasValid(const CanvasPtr& pCanvas) +{ + if (pCanvas == getCanvas()) { + m_href = ""; + m_pImage->setEmpty(); + throw Exception(AVG_ERR_INVALID_ARGS, + "Circular dependency between canvases."); + } +} + +} |