summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMateusz Piekos <mateuszpiekos@gmail.com>2012-05-30 12:40:27 (GMT)
committerRemko Tronçon <git@el-tramo.be>2012-09-08 16:14:27 (GMT)
commitfe8a8aa031da734f3112184420b372021d9e10c7 (patch)
tree9f8e0b7d11d7612eb25a8682cf940fa647ca67f2 /Swiften/Parser
parent0174723efbc1f612433d45c6916a2ad4596b96ba (diff)
downloadswift-fe8a8aa031da734f3112184420b372021d9e10c7.zip
swift-fe8a8aa031da734f3112184420b372021d9e10c7.tar.bz2
Support whiteboarding.
License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php
Diffstat (limited to 'Swiften/Parser')
-rw-r--r--Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp2
-rw-r--r--Swiften/Parser/PayloadParsers/WhiteboardParser.cpp315
-rw-r--r--Swiften/Parser/PayloadParsers/WhiteboardParser.h34
-rw-r--r--Swiften/Parser/SConscript1
4 files changed, 352 insertions, 0 deletions
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
index 217f278..a40e8f6 100644
--- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
@@ -66,6 +66,7 @@
#include <Swiften/Parser/PayloadParsers/JingleFileTransferDescriptionParser.h>
#include <Swiften/Parser/PayloadParsers/DeliveryReceiptParserFactory.h>
#include <Swiften/Parser/PayloadParsers/DeliveryReceiptRequestParserFactory.h>
+#include <Swiften/Parser/PayloadParsers/WhiteboardParser.h>
using namespace boost;
@@ -124,6 +125,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleFileTransferReceivedParser> >("received", "urn:xmpp:jingle:apps:file-transfer:3"));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<JingleFileTransferHashParser> >("checksum"));
factories_.push_back(boost::make_shared<GenericPayloadParserFactory<S5BProxyRequestParser> >("query", "http://jabber.org/protocol/bytestreams"));
+ factories_.push_back(boost::make_shared<GenericPayloadParserFactory<WhiteboardParser> >("wb", "http://swift.im/whiteboard"));
factories_.push_back(boost::make_shared<DeliveryReceiptParserFactory>());
factories_.push_back(boost::make_shared<DeliveryReceiptRequestParserFactory>());
diff --git a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp
new file mode 100644
index 0000000..09d8de9
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2012 Mateusz Piękos
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/WhiteboardParser.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardLineElement.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardRectElement.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardTextElement.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardPolygonElement.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardEllipseElement.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardFreehandPathElement.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardColor.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardInsertOperation.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardUpdateOperation.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardDeleteOperation.h>
+#include <boost/optional.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace Swift {
+ WhiteboardParser::WhiteboardParser() : actualIsText(false), level_(0) {
+ }
+
+ void WhiteboardParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) {
+ if (level_ == 0) {
+ getPayloadInternal()->setType(stringToType(attributes.getAttributeValue("type").get_value_or("")));
+ } else if (level_ == 1) {
+ std::string type = attributes.getAttributeValue("type").get_value_or("");
+ if (type == "insert") {
+ WhiteboardInsertOperation::ref insertOp = boost::make_shared<WhiteboardInsertOperation>();
+ operation = insertOp;
+ } else if (type == "update") {
+ WhiteboardUpdateOperation::ref updateOp = boost::make_shared<WhiteboardUpdateOperation>();
+ std::string move = attributes.getAttributeValue("newpos").get_value_or("0");
+ updateOp->setNewPos(boost::lexical_cast<int>(attributes.getAttributeValue("newpos").get_value_or("0")));
+ operation = updateOp;
+ } else if (type == "delete") {
+ WhiteboardDeleteOperation::ref deleteOp = boost::make_shared<WhiteboardDeleteOperation>();
+ deleteOp->setElementID(attributes.getAttributeValue("elementid").get_value_or(""));
+ operation = deleteOp;
+ }
+ if (operation) {
+ try {
+ operation->setID(attributes.getAttributeValue("id").get_value_or(""));
+ operation->setParentID(attributes.getAttributeValue("parentid").get_value_or(""));
+ operation->setPos(boost::lexical_cast<int>(attributes.getAttributeValue("pos").get_value_or("0")));
+ } catch (boost::bad_lexical_cast&) {
+ }
+ }
+
+ } else if (level_ == 2) {
+ if (element == "line") {
+ int x1 = 0;
+ int y1 = 0;
+ int x2 = 0;
+ int y2 = 0;
+ try {
+ x1 = boost::lexical_cast<int>(attributes.getAttributeValue("x1").get_value_or("0"));
+ y1 = boost::lexical_cast<int>(attributes.getAttributeValue("y1").get_value_or("0"));
+ x2 = boost::lexical_cast<int>(attributes.getAttributeValue("x2").get_value_or("0"));
+ y2 = boost::lexical_cast<int>(attributes.getAttributeValue("y2").get_value_or("0"));
+ } catch (boost::bad_lexical_cast&) {
+ }
+ WhiteboardLineElement::ref whiteboardElement = boost::make_shared<WhiteboardLineElement>(x1, y1, x2, y2);
+
+ WhiteboardColor color(attributes.getAttributeValue("stroke").get_value_or("#000000"));
+ color.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1")));
+ whiteboardElement->setColor(color);
+
+ int penWidth = 1;
+ try {
+ penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1"));
+ } catch (boost::bad_lexical_cast&) {
+ }
+ whiteboardElement->setPenWidth(penWidth);
+ whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or(""));
+ getPayloadInternal()->setElement(whiteboardElement);
+ wbElement = whiteboardElement;
+ } else if (element == "path") {
+ WhiteboardFreehandPathElement::ref whiteboardElement = boost::make_shared<WhiteboardFreehandPathElement>();
+ std::string pathData = attributes.getAttributeValue("d").get_value_or("");
+ std::vector<std::pair<int, int> > points;
+ if (pathData[0] == 'M') {
+ unsigned int pos = 1;
+ unsigned int npos;
+ int x, y;
+ if (pathData[pos] == ' ') {
+ pos++;
+ }
+ try {
+ npos = pathData.find(' ', pos);
+ x = boost::lexical_cast<int>(pathData.substr(pos, npos-pos));
+ pos = npos+1;
+ npos = pathData.find('L', pos);
+ y = boost::lexical_cast<int>(pathData.substr(pos, npos-pos));
+ pos = npos+1;
+ if (pathData[pos] == ' ') {
+ pos++;
+ }
+ points.push_back(std::pair<int, int>(x, y));
+ while (pos < pathData.size()) {
+ npos = pathData.find(' ', pos);
+ x = boost::lexical_cast<int>(pathData.substr(pos, npos-pos));
+ pos = npos+1;
+ npos = pathData.find(' ', pos);
+ y = boost::lexical_cast<int>(pathData.substr(pos, npos-pos));
+ pos = npos+1;
+ points.push_back(std::pair<int, int>(x, y));
+ }
+ } catch (boost::bad_lexical_cast&) {
+ }
+ }
+ whiteboardElement->setPoints(points);
+
+ int penWidth = 1;
+ try {
+ penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1"));
+ } catch (boost::bad_lexical_cast&) {
+ }
+ whiteboardElement->setPenWidth(penWidth);
+
+ WhiteboardColor color(attributes.getAttributeValue("stroke").get_value_or("#000000"));
+ color.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1")));
+ whiteboardElement->setColor(color);
+ whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or(""));
+ getPayloadInternal()->setElement(whiteboardElement);
+ wbElement = whiteboardElement;
+ } else if (element == "rect") {
+ int x = 0;
+ int y = 0;
+ int width = 0;
+ int height = 0;
+ try {
+ x = boost::lexical_cast<int>(attributes.getAttributeValue("x").get_value_or("0"));
+ y = boost::lexical_cast<int>(attributes.getAttributeValue("y").get_value_or("0"));
+ width = boost::lexical_cast<int>(attributes.getAttributeValue("width").get_value_or("0"));
+ height = boost::lexical_cast<int>(attributes.getAttributeValue("height").get_value_or("0"));
+ } catch (boost::bad_lexical_cast&) {
+ }
+
+ WhiteboardRectElement::ref whiteboardElement = boost::make_shared<WhiteboardRectElement>(x, y, width, height);
+
+ int penWidth = 1;
+ try {
+ penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1"));
+ } catch (boost::bad_lexical_cast&) {
+ }
+ whiteboardElement->setPenWidth(penWidth);
+
+ WhiteboardColor penColor(attributes.getAttributeValue("stroke").get_value_or("#000000"));
+ WhiteboardColor brushColor(attributes.getAttributeValue("fill").get_value_or("#000000"));
+ penColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1")));
+ brushColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("fill-opacity").get_value_or("1")));
+ whiteboardElement->setPenColor(penColor);
+ whiteboardElement->setBrushColor(brushColor);
+ whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or(""));
+ getPayloadInternal()->setElement(whiteboardElement);
+ wbElement = whiteboardElement;
+ } else if (element == "polygon") {
+ WhiteboardPolygonElement::ref whiteboardElement = boost::make_shared<WhiteboardPolygonElement>();
+
+ std::string pointsData = attributes.getAttributeValue("points").get_value_or("");
+ std::vector<std::pair<int, int> > points;
+ unsigned int pos = 0;
+ unsigned int npos;
+ int x, y;
+ try {
+ while (pos < pointsData.size()) {
+ npos = pointsData.find(',', pos);
+ x = boost::lexical_cast<int>(pointsData.substr(pos, npos-pos));
+ pos = npos+1;
+ npos = pointsData.find(' ', pos);
+ y = boost::lexical_cast<int>(pointsData.substr(pos, npos-pos));
+ pos = npos+1;
+ points.push_back(std::pair<int, int>(x, y));
+ }
+ } catch (boost::bad_lexical_cast&) {
+ }
+
+ whiteboardElement->setPoints(points);
+
+ int penWidth = 1;
+ try {
+ penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1"));
+ } catch (boost::bad_lexical_cast&) {
+ }
+ whiteboardElement->setPenWidth(penWidth);
+
+ WhiteboardColor penColor(attributes.getAttributeValue("stroke").get_value_or("#000000"));
+ WhiteboardColor brushColor(attributes.getAttributeValue("fill").get_value_or("#000000"));
+ penColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1")));
+ brushColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("fill-opacity").get_value_or("1")));
+ whiteboardElement->setPenColor(penColor);
+ whiteboardElement->setBrushColor(brushColor);
+ whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or(""));
+ getPayloadInternal()->setElement(whiteboardElement);
+ wbElement = whiteboardElement;
+ } else if (element == "text") {
+ int x = 0;
+ int y = 0;
+ try {
+ x = boost::lexical_cast<int>(attributes.getAttributeValue("x").get_value_or("0"));
+ y = boost::lexical_cast<int>(attributes.getAttributeValue("y").get_value_or("0"));
+ } catch (boost::bad_lexical_cast&) {
+ }
+
+ WhiteboardTextElement::ref whiteboardElement = boost::make_shared<WhiteboardTextElement>(x, y);
+
+ actualIsText = true;
+ WhiteboardColor color(attributes.getAttributeValue("fill").get_value_or("#000000"));
+ color.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1")));
+ whiteboardElement->setColor(color);
+
+ int fontSize = 1;
+ try {
+ fontSize = boost::lexical_cast<int>(attributes.getAttributeValue("font-size").get_value_or("12"));
+ } catch (boost::bad_lexical_cast&) {
+ }
+ whiteboardElement->setSize(fontSize);
+ whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or(""));
+ getPayloadInternal()->setElement(whiteboardElement);
+ wbElement = whiteboardElement;
+ } else if (element == "ellipse") {
+ int cx = 0;
+ int cy = 0;
+ int rx = 0;
+ int ry = 0;
+ try {
+ cx = boost::lexical_cast<int>(attributes.getAttributeValue("cx").get_value_or("0"));
+ cy = boost::lexical_cast<int>(attributes.getAttributeValue("cy").get_value_or("0"));
+ rx = boost::lexical_cast<int>(attributes.getAttributeValue("rx").get_value_or("0"));
+ ry = boost::lexical_cast<int>(attributes.getAttributeValue("ry").get_value_or("0"));
+ } catch (boost::bad_lexical_cast&) {
+ }
+
+ WhiteboardEllipseElement::ref whiteboardElement = boost::make_shared<WhiteboardEllipseElement>(cx, cy, rx, ry);
+
+ int penWidth = 1;
+ try {
+ penWidth = boost::lexical_cast<int>(attributes.getAttributeValue("stroke-width").get_value_or("1"));
+ } catch (boost::bad_lexical_cast&) {
+ }
+ whiteboardElement->setPenWidth(penWidth);
+
+ WhiteboardColor penColor(attributes.getAttributeValue("stroke").get_value_or("#000000"));
+ WhiteboardColor brushColor(attributes.getAttributeValue("fill").get_value_or("#000000"));
+ penColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1")));
+ brushColor.setAlpha(opacityToAlpha(attributes.getAttributeValue("fill-opacity").get_value_or("1")));
+ whiteboardElement->setPenColor(penColor);
+ whiteboardElement->setBrushColor(brushColor);
+ whiteboardElement->setID(attributes.getAttributeValue("id").get_value_or(""));
+ getPayloadInternal()->setElement(whiteboardElement);
+ wbElement = whiteboardElement;
+ }
+ }
+ ++level_;
+ }
+
+ void WhiteboardParser::handleEndElement(const std::string& element, const std::string&) {
+ --level_;
+ if (level_ == 0) {
+ getPayloadInternal()->setData(data_);
+ } else if (level_ == 1) {
+ WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast<WhiteboardInsertOperation>(operation);
+ if (insertOp) {
+ insertOp->setElement(wbElement);
+ }
+
+ WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast<WhiteboardUpdateOperation>(operation);
+ if (updateOp) {
+ updateOp->setElement(wbElement);
+ }
+ getPayloadInternal()->setOperation(operation);
+ } else if (level_ == 2) {
+ if (element == "text") {
+ actualIsText = false;
+ }
+ }
+ }
+
+ void WhiteboardParser::handleCharacterData(const std::string& data) {
+ if (level_ == 3 && actualIsText) {
+ WhiteboardTextElement::ref element = boost::dynamic_pointer_cast<WhiteboardTextElement>(getPayloadInternal()->getElement());
+ element->setText(data);
+ }
+ }
+
+ WhiteboardPayload::Type WhiteboardParser::stringToType(const std::string& type) const {
+ if (type == "data") {
+ return WhiteboardPayload::Data;
+ } else if (type == "session-request") {
+ return WhiteboardPayload::SessionRequest;
+ } else if (type == "session-accept") {
+ return WhiteboardPayload::SessionAccept;
+ } else if (type == "session-terminate") {
+ return WhiteboardPayload::SessionTerminate;
+ } else {
+ return WhiteboardPayload::UnknownType;
+ }
+ }
+
+ int WhiteboardParser::opacityToAlpha(std::string opacity) const {
+ int value = 255;
+ if (opacity.find('.') != std::string::npos) {
+ opacity = opacity.substr(opacity.find('.')+1, 2);
+ try {
+ value = boost::lexical_cast<int>(opacity)*255/100;
+ } catch (boost::bad_lexical_cast&) {
+ }
+ }
+ return value;
+ }
+}
diff --git a/Swiften/Parser/PayloadParsers/WhiteboardParser.h b/Swiften/Parser/PayloadParsers/WhiteboardParser.h
new file mode 100644
index 0000000..0368c7c
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/WhiteboardParser.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012 Mateusz Piękos
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Elements/WhiteboardPayload.h>
+#include <Swiften/Parser/GenericPayloadParser.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardElement.h>
+#include <Swiften/Elements/Whiteboard/WhiteboardOperation.h>
+
+namespace Swift {
+ class WhiteboardParser : public Swift::GenericPayloadParser<WhiteboardPayload> {
+ public:
+ WhiteboardParser();
+
+ virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);
+ virtual void handleEndElement(const std::string& element, const std::string&);
+ virtual void handleCharacterData(const std::string& data);
+
+ private:
+ WhiteboardPayload::Type stringToType(const std::string& type) const;
+ int opacityToAlpha(std::string opacity) const;
+
+ private:
+ bool actualIsText;
+ int level_;
+ std::string data_;
+ WhiteboardElement::ref wbElement;
+ WhiteboardOperation::ref operation;
+ };
+}
diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript
index e4c2778..64e9eb9 100644
--- a/Swiften/Parser/SConscript
+++ b/Swiften/Parser/SConscript
@@ -72,6 +72,7 @@ sources = [
"PayloadParsers/S5BProxyRequestParser.cpp",
"PayloadParsers/DeliveryReceiptParser.cpp",
"PayloadParsers/DeliveryReceiptRequestParser.cpp",
+ "PayloadParsers/WhiteboardParser.cpp",
"PlatformXMLParserFactory.cpp",
"PresenceParser.cpp",
"SerializingParser.cpp",