From 286a3d119ec95b235b09935296450ec36e640aeb Mon Sep 17 00:00:00 2001 From: Mateusz Piekos Date: Thu, 21 Jun 2012 20:05:56 +0200 Subject: Added parsing and serialization of freehand path element diff --git a/Swift/QtUI/Whiteboard/FreehandLineItem.cpp b/Swift/QtUI/Whiteboard/FreehandLineItem.cpp index af8e827..bd53843 100644 --- a/Swift/QtUI/Whiteboard/FreehandLineItem.cpp +++ b/Swift/QtUI/Whiteboard/FreehandLineItem.cpp @@ -86,7 +86,7 @@ namespace Swift { return pen_; } - QVector FreehandLineItem::points() const { + const QVector& FreehandLineItem::points() const { return points_; } diff --git a/Swift/QtUI/Whiteboard/FreehandLineItem.h b/Swift/QtUI/Whiteboard/FreehandLineItem.h index e995cab..b0be36b 100644 --- a/Swift/QtUI/Whiteboard/FreehandLineItem.h +++ b/Swift/QtUI/Whiteboard/FreehandLineItem.h @@ -24,7 +24,7 @@ namespace Swift { bool collidesWithPath(const QPainterPath& path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; void setPen(const QPen& pen); QPen pen() const; - QVector points() const; + const QVector& points() const; int type() const; private: diff --git a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp index 612e467..0a1afe3 100644 --- a/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp +++ b/Swift/QtUI/Whiteboard/QtWhiteboardWindow.cpp @@ -245,15 +245,21 @@ namespace Swift { } FreehandLineItem* freehandLineItem = qgraphicsitem_cast(item); if (freehandLineItem != 0) { - QVector points = freehandLineItem->points(); - QVector::iterator it; - std::stringstream stream; - stream << "F"; - QPoint point; - for (it = points.begin(); it != points.end(); ++it) { - stream << it->x() << "," << it->y() << ","; + WhiteboardFreehandPathElement::ref element = boost::make_shared(); + QColor color = freehandLineItem->pen().color(); + std::vector > points; + QVector::const_iterator it = freehandLineItem->points().constBegin(); + for ( ; it != freehandLineItem->points().constEnd(); ++it) { + points.push_back(std::pair(it->x(), it->y())); } - stream >> serialized; + + element->setColor(Color(color.red(), color.green(), color.blue(), color.alpha())); + element->setPenWidth(freehandLineItem->pen().width()); + element->setPoints(points); + + element->setID(freehandLineItem->data(0).toString().toStdString()); + whiteboardSession_->sendElement(element); + } } diff --git a/Swift/QtUI/Whiteboard/WhiteboardElementDrawingVisitor.h b/Swift/QtUI/Whiteboard/WhiteboardElementDrawingVisitor.h index a1715bc..3b144cc 100644 --- a/Swift/QtUI/Whiteboard/WhiteboardElementDrawingVisitor.h +++ b/Swift/QtUI/Whiteboard/WhiteboardElementDrawingVisitor.h @@ -8,6 +8,7 @@ #include #include +#include #include namespace Swift { @@ -15,16 +16,33 @@ namespace Swift { public: WhiteboardElementDrawingVisitor(GView* graphicsView) : graphicsView_(graphicsView) {} - void visit(const WhiteboardLineElement* element) { - QGraphicsLineItem *item = new QGraphicsLineItem(element->x1(), element->y1(), element->x2(), element->y2()); + void visit(WhiteboardLineElement& element) { + QGraphicsLineItem *item = new QGraphicsLineItem(element.x1(), element.y1(), element.x2(), element.y2()); QPen pen; - Color color = element->getColor(); + Color color = element.getColor(); pen.setColor(QColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha())); - pen.setWidth(element->getPenWidth()); + pen.setWidth(element.getPenWidth()); item->setPen(pen); graphicsView_->scene()->addItem(item); } + void visit(WhiteboardFreehandPathElement& element) { + FreehandLineItem *item = new FreehandLineItem; + QPen pen; + Color color = element.getColor(); + pen.setColor(QColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha())); + pen.setWidth(element.getPenWidth()); + item->setPen(pen); + + std::vector >::const_iterator it = element.getPoints().begin(); + item->setStartPoint(QPointF(it->first, it->second)); + for (++it; it != element.getPoints().end(); ++it) { + item->lineTo(QPointF(it->first, it->second)); + } + + graphicsView_->scene()->addItem(item); + } + private: GView* graphicsView_; }; diff --git a/Swiften/Base/String.cpp b/Swiften/Base/String.cpp index 7ddf614..242b8e5 100644 --- a/Swiften/Base/String.cpp +++ b/Swiften/Base/String.cpp @@ -6,6 +6,8 @@ #include #include +#include +#include #include @@ -95,4 +97,20 @@ std::vector String::split(const std::string& s, char c) { return result; } +std::string String::convertIntToHexString(int h) { + std::stringstream ss; + ss << std::setbase(16); + ss << h; + return ss.str(); +} + +int String::convertHexStringToInt(const std::string& s) { + std::stringstream ss; + int h; + ss << std::setbase(16); + ss << s; + ss >> h; + return h; +} + } diff --git a/Swiften/Base/String.h b/Swiften/Base/String.h index db6c28b..1dd303f 100644 --- a/Swiften/Base/String.h +++ b/Swiften/Base/String.h @@ -27,6 +27,9 @@ namespace Swift { inline bool endsWith(const std::string& s, char c) { return s.size() > 0 && s[s.size()-1] == c; } + + std::string convertIntToHexString(int h); + int convertHexStringToInt(const std::string& s); }; class makeString { diff --git a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp index d0fa9f9..7182a8c 100644 --- a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp +++ b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp @@ -6,9 +6,11 @@ #include #include +#include #include #include #include +#include namespace Swift { WhiteboardParser::WhiteboardParser() : level_(0) { @@ -19,24 +21,93 @@ namespace Swift { getPayloadInternal()->setType(stringToType(attributes.getAttributeValue("type").get_value_or(""))); } else if (level_ == 1) { if (element == "line") { - int x1 = std::atoi(attributes.getAttributeValue("x1").get_value_or("0").c_str()); - int y1 = std::atoi(attributes.getAttributeValue("y1").get_value_or("0").c_str()); - int x2 = std::atoi(attributes.getAttributeValue("x2").get_value_or("0").c_str()); - int y2 = std::atoi(attributes.getAttributeValue("y2").get_value_or("0").c_str()); + int x1 = 0; + int y1 = 0; + int x2 = 0; + int y2 = 0; + try { + x1 = boost::lexical_cast(attributes.getAttributeValue("x1").get_value_or("0")); + y1 = boost::lexical_cast(attributes.getAttributeValue("y1").get_value_or("0")); + x2 = boost::lexical_cast(attributes.getAttributeValue("x2").get_value_or("0")); + y2 = boost::lexical_cast(attributes.getAttributeValue("y2").get_value_or("0")); + } catch (boost::bad_lexical_cast&) { + } WhiteboardLineElement::ref whiteboardElement = boost::make_shared(x1, y1, x2, y2); - Color color(attributes.getAttributeValue("stroke").get_value_or("#00000")); + Color color(attributes.getAttributeValue("stroke").get_value_or("#000000")); std::string opacity = attributes.getAttributeValue("opacity").get_value_or("1"); if (opacity.find('.') != std::string::npos) { opacity = opacity.substr(opacity.find('.')+1, 2); - color.setAlpha(std::atoi(opacity.c_str())*255/100); + try { + color.setAlpha(boost::lexical_cast(opacity)*255/100); + } catch (boost::bad_lexical_cast&) { + } } - whiteboardElement->setColor(color); - int penWidth = std::atoi(attributes.getAttributeValue("stroke-width").get_value_or("1").c_str()); + int penWidth = 1; + try { + penWidth = boost::lexical_cast(attributes.getAttributeValue("stroke-width").get_value_or("1")); + } catch (boost::bad_lexical_cast&) { + } + whiteboardElement->setPenWidth(penWidth); + + getPayloadInternal()->setElement(whiteboardElement); + } else if (element == "path") { + WhiteboardFreehandPathElement::ref whiteboardElement = boost::make_shared(); + std::string pathData = attributes.getAttributeValue("d").get_value_or(""); + std::vector > points; + if (pathData[0] == 'M') { + int pos = 1; + int npos; + int x, y; + if (pathData[pos] == ' ') { + pos++; + } + try { + npos = pathData.find(' ', pos); + x = boost::lexical_cast(pathData.substr(pos, npos-pos)); + pos = npos+1; + npos = pathData.find('L', pos); + y = boost::lexical_cast(pathData.substr(pos, npos-pos)); + pos = npos+1; + if (pathData[pos] == ' ') { + pos++; + } + points.push_back(std::pair(x, y)); + while (pos < pathData.size()) { + npos = pathData.find(' ', pos); + x = boost::lexical_cast(pathData.substr(pos, npos-pos)); + pos = npos+1; + npos = pathData.find(' ', pos); + y = boost::lexical_cast(pathData.substr(pos, npos-pos)); + pos = npos+1; + points.push_back(std::pair(x, y)); + } + } catch (boost::bad_lexical_cast&) { + } + } + whiteboardElement->setPoints(points); + + int penWidth = 1; + try { + penWidth = boost::lexical_cast(attributes.getAttributeValue("stroke-width").get_value_or("1")); + } catch (boost::bad_lexical_cast&) { + } whiteboardElement->setPenWidth(penWidth); + Color color(attributes.getAttributeValue("stroke").get_value_or("#000000")); + + std::string opacity = attributes.getAttributeValue("opacity").get_value_or("1"); + if (opacity.find('.') != std::string::npos) { + opacity = opacity.substr(opacity.find('.')+1, 2); + try { + color.setAlpha(boost::lexical_cast(opacity)*255/100); + } catch (boost::bad_lexical_cast&) { + } + } + whiteboardElement->setColor(color); + getPayloadInternal()->setElement(whiteboardElement); } } diff --git a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp index f02791c..b5a4c49 100644 --- a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp @@ -7,24 +7,54 @@ #include #include +#include #include namespace Swift { - void WhiteboardElementSerializingVisitor::visit(const WhiteboardLineElement* line) { + void WhiteboardElementSerializingVisitor::visit(WhiteboardLineElement& line) { element = boost::make_shared("line"); - element->setAttribute("x1", intToStr(line->x1())); - element->setAttribute("y1", intToStr(line->y1())); - element->setAttribute("x2", intToStr(line->x2())); - element->setAttribute("y2", intToStr(line->y2())); - element->setAttribute("id", line->getID()); - element->setAttribute("stroke", line->getColor().toHex()); - element->setAttribute("stroke-width", intToStr(line->getPenWidth())); - int alpha = line->getColor().getAlpha(); - int opacity = 100*alpha/254; - if (opacity == 100) { - element->setAttribute("opacity", "1"); - } else { - element->setAttribute("opacity", "."+intToStr(opacity)); + try { + element->setAttribute("x1", boost::lexical_cast(line.x1())); + element->setAttribute("y1", boost::lexical_cast(line.y1())); + element->setAttribute("x2", boost::lexical_cast(line.x2())); + element->setAttribute("y2", boost::lexical_cast(line.y2())); + element->setAttribute("id", line.getID()); + element->setAttribute("stroke", line.getColor().toHex()); + element->setAttribute("stroke-width", boost::lexical_cast(line.getPenWidth())); + int alpha = line.getColor().getAlpha(); + int opacity = 100*alpha/254; + if (opacity == 100) { + element->setAttribute("opacity", "1"); + } else { + element->setAttribute("opacity", "."+boost::lexical_cast(opacity)); + } + } catch (boost::bad_lexical_cast&) { + } + } + + void WhiteboardElementSerializingVisitor::visit(WhiteboardFreehandPathElement& path) { + element = boost::make_shared("path"); + element->setAttribute("id", path.getID()); + element->setAttribute("stroke", path.getColor().toHex()); + try { + element->setAttribute("stroke-width", boost::lexical_cast(path.getPenWidth())); + int alpha = path.getColor().getAlpha(); + int opacity = 100*alpha/254; + if (opacity == 100) { + element->setAttribute("opacity", "1"); + } else { + element->setAttribute("opacity", "."+boost::lexical_cast(opacity)); + } + std::string pathData; + if (path.getPoints().size() != 0) { + std::vector >::const_iterator it = path.getPoints().begin(); + pathData = "M"+boost::lexical_cast(it->first)+" "+boost::lexical_cast(it->second)+"L"; + for (; it != path.getPoints().end(); ++it) { + pathData += boost::lexical_cast(it->first)+" "+boost::lexical_cast(it->second)+" "; + } + } + element->setAttribute("d", pathData); + } catch (boost::bad_lexical_cast&) { } } diff --git a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h index 50cf252..25642d0 100644 --- a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -15,7 +16,8 @@ namespace Swift { class WhiteboardElementSerializingVisitor : public WhiteboardElementVisitor { public: - void visit(const WhiteboardLineElement* line); + void visit(WhiteboardLineElement& line); + void visit(WhiteboardFreehandPathElement& path); XMLElement::ref getResult() const; private: diff --git a/Swiften/Whiteboard/Elements/Color.cpp b/Swiften/Whiteboard/Elements/Color.cpp index b614a2a..51b8460 100644 --- a/Swiften/Whiteboard/Elements/Color.cpp +++ b/Swiften/Whiteboard/Elements/Color.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -18,39 +19,18 @@ namespace Swift { } Color::Color(const std::string& hex) : alpha_(255) { - if (hex.size() == 7) { - char temp[3]; - hex.copy(temp, 2, 1); - temp[2] = 0; - std::sscanf(temp, "%x", &red_); - hex.copy(temp, 2, 3); - temp[2] = 0; - std::sscanf(temp, "%x", &green_); - hex.copy(temp, 2, 5); - temp[2] = 0; - std::sscanf(temp, "%x", &blue_); - } + int value = String::convertHexStringToInt(hex.substr(1)); + red_ = (value >> 16)&0xFF; + green_ = (value >> 8)&0xFF; + blue_ = value&0xFF; } std::string Color::toHex() const { - std::string result = "#"; - std::string hex; - hex = intToStr(red_, 16); - if (hex.size() == 1) { - result += "0"; - } - result += hex; - hex = intToStr(green_, 16); - if (hex.size() == 1) { - result += "0"; - } - result += hex; - hex = intToStr(blue_, 16); - if (hex.size() == 1) { - result += "0"; + std::string value = String::convertIntToHexString((red_ << 16) + (green_ << 8) + blue_); + while (value.size() < 6) { + value.insert(0, "0"); } - result += hex; - return result; + return "#"+value; } int Color::getRed() const { @@ -72,11 +52,4 @@ namespace Swift { void Color::setAlpha(int alpha) { alpha_ = alpha; } - - std::string Color::intToStr(int t, int base) const { - std::stringstream ss; - ss << std::setbase(base); - ss << t; - return ss.str(); - } } diff --git a/Swiften/Whiteboard/Elements/Color.h b/Swiften/Whiteboard/Elements/Color.h index b7cca5a..7227eca 100644 --- a/Swiften/Whiteboard/Elements/Color.h +++ b/Swiften/Whiteboard/Elements/Color.h @@ -22,8 +22,6 @@ namespace Swift { void setAlpha(int alpha); private: - std::string intToStr(int t, int base = 10) const; - int red_, green_, blue_; int alpha_; }; diff --git a/Swiften/Whiteboard/Elements/WhiteboardElementVisitor.h b/Swiften/Whiteboard/Elements/WhiteboardElementVisitor.h index b5fd546..d546e7f 100644 --- a/Swiften/Whiteboard/Elements/WhiteboardElementVisitor.h +++ b/Swiften/Whiteboard/Elements/WhiteboardElementVisitor.h @@ -8,10 +8,12 @@ namespace Swift { class WhiteboardLineElement; + class WhiteboardFreehandPathElement; class WhiteboardElementVisitor { public: virtual ~WhiteboardElementVisitor() {} - virtual void visit(const WhiteboardLineElement* /*element*/) = 0; + virtual void visit(WhiteboardLineElement& /*element*/) = 0; + virtual void visit(WhiteboardFreehandPathElement& /*element*/) = 0; }; } diff --git a/Swiften/Whiteboard/Elements/WhiteboardFreehandPathElement.h b/Swiften/Whiteboard/Elements/WhiteboardFreehandPathElement.h new file mode 100644 index 0000000..9b69dc4 --- /dev/null +++ b/Swiften/Whiteboard/Elements/WhiteboardFreehandPathElement.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include +#include + +#include +#include + +namespace Swift { + class WhiteboardFreehandPathElement : public WhiteboardElement { + typedef std::pair Point; + public: + typedef boost::shared_ptr ref; + public: + WhiteboardFreehandPathElement() { + } + + void setPoints(const std::vector& points) { + points_ = points; + } + + const std::vector& getPoints() const { + return points_; + } + + const Color& getColor() const { + return color_; + } + + void setColor(const Color& color) { + color_ = color; + } + + std::string getID() const { + return id_; + } + + void setID(const std::string& id) { + id_ = id; + } + + int getPenWidth() const { + return penWidth_; + } + + void setPenWidth(const int penWidth) { + penWidth_ = penWidth; + } + + void accept(WhiteboardElementVisitor& visitor) { + visitor.visit(*this); + } + + private: + + std::vector points_; + Color color_; + int penWidth_; + std::string id_; + }; +} diff --git a/Swiften/Whiteboard/Elements/WhiteboardLineElement.h b/Swiften/Whiteboard/Elements/WhiteboardLineElement.h index 0088189..20455b6 100644 --- a/Swiften/Whiteboard/Elements/WhiteboardLineElement.h +++ b/Swiften/Whiteboard/Elements/WhiteboardLineElement.h @@ -62,7 +62,7 @@ namespace Swift { } void accept(WhiteboardElementVisitor& visitor) { - visitor.visit(this); + visitor.visit(*this); } private: -- cgit v0.10.2-6-g49f6