summaryrefslogtreecommitdiff
path: root/src/player/ImageNode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/player/ImageNode.cpp')
-rw-r--r--src/player/ImageNode.cpp241
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.");
+ }
+}
+
+}