2016-05-21 08:41:23 -05:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef INCLUDED_TILEDESC_HPP
|
|
|
|
#define INCLUDED_TILEDESC_HPP
|
|
|
|
|
2016-09-15 07:40:26 -05:00
|
|
|
#include <cassert>
|
2016-05-21 08:41:23 -05:00
|
|
|
#include <map>
|
|
|
|
#include <sstream>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include <Poco/StringTokenizer.h>
|
|
|
|
|
|
|
|
#include "Exceptions.hpp"
|
2016-11-24 08:56:06 -06:00
|
|
|
#include "Protocol.hpp"
|
2016-05-21 08:41:23 -05:00
|
|
|
|
|
|
|
/// Tile Descriptor
|
|
|
|
/// Represents a tile's coordinates and dimensions.
|
|
|
|
class TileDesc
|
|
|
|
{
|
|
|
|
public:
|
2016-10-07 08:07:50 -05:00
|
|
|
TileDesc(int part, int width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight, int ver, int imgSize, int id, bool broadcast) :
|
2016-05-21 08:41:23 -05:00
|
|
|
_part(part),
|
|
|
|
_width(width),
|
|
|
|
_height(height),
|
|
|
|
_tilePosX(tilePosX),
|
|
|
|
_tilePosY(tilePosY),
|
|
|
|
_tileWidth(tileWidth),
|
|
|
|
_tileHeight(tileHeight),
|
2016-05-22 13:21:05 -05:00
|
|
|
_ver(ver),
|
2016-05-22 10:35:41 -05:00
|
|
|
_imgSize(imgSize),
|
2016-10-07 08:07:50 -05:00
|
|
|
_id(id),
|
|
|
|
_broadcast(broadcast)
|
2016-05-21 08:41:23 -05:00
|
|
|
{
|
|
|
|
if (_part < 0 ||
|
|
|
|
_width <= 0 ||
|
|
|
|
_height <= 0 ||
|
|
|
|
_tilePosX < 0 ||
|
|
|
|
_tilePosY < 0 ||
|
|
|
|
_tileWidth <= 0 ||
|
2016-05-22 10:35:41 -05:00
|
|
|
_tileHeight <= 0 ||
|
|
|
|
_imgSize < 0)
|
2016-05-21 08:41:23 -05:00
|
|
|
{
|
|
|
|
throw BadArgumentException("Invalid tile descriptor.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int getPart() const { return _part; }
|
|
|
|
int getWidth() const { return _width; }
|
|
|
|
int getHeight() const { return _height; }
|
|
|
|
int getTilePosX() const { return _tilePosX; }
|
|
|
|
int getTilePosY() const { return _tilePosY; }
|
|
|
|
int getTileWidth() const { return _tileWidth; }
|
|
|
|
int getTileHeight() const { return _tileHeight; }
|
2016-05-22 13:21:05 -05:00
|
|
|
int getVersion() const { return _ver; }
|
|
|
|
void setVersion(const int ver) { _ver = ver; }
|
2016-05-22 10:35:41 -05:00
|
|
|
int getImgSize() const { return _imgSize; }
|
|
|
|
void setImgSize(const int imgSize) { _imgSize = imgSize; }
|
2016-10-04 05:20:41 -05:00
|
|
|
int getId() const { return _id; }
|
2016-10-07 08:07:50 -05:00
|
|
|
bool getBroadcast() const { return _broadcast; }
|
2016-09-15 07:40:26 -05:00
|
|
|
|
2016-09-01 15:15:13 -05:00
|
|
|
bool intersectsWithRect(int x, int y, int w, int h) const
|
|
|
|
{
|
|
|
|
return x + w >= getTilePosX() &&
|
|
|
|
x <= getTilePosX() + getTileWidth() &&
|
|
|
|
y + h >= getTilePosY() &&
|
|
|
|
y <= getTilePosY() + getTileHeight();
|
|
|
|
}
|
2016-05-21 08:41:23 -05:00
|
|
|
|
2016-09-15 07:40:26 -05:00
|
|
|
bool intersects(const TileDesc& other) const
|
|
|
|
{
|
|
|
|
return intersectsWithRect(other.getTilePosX(), other.getTilePosY(),
|
|
|
|
other.getTileWidth(), other.getTileHeight());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isAdjacent(const TileDesc& other) const
|
|
|
|
{
|
|
|
|
if (other.getPart() != getPart() ||
|
|
|
|
other.getWidth() != getWidth() ||
|
|
|
|
other.getHeight() != getHeight() ||
|
|
|
|
other.getTileWidth() != getTileWidth() ||
|
|
|
|
other.getTileHeight() != getTileHeight())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return intersects(other);
|
|
|
|
}
|
|
|
|
|
2016-09-25 20:30:56 -05:00
|
|
|
bool onSameRow(const TileDesc& other) const
|
|
|
|
{
|
|
|
|
if (other.getPart() != getPart() ||
|
|
|
|
other.getWidth() != getWidth() ||
|
|
|
|
other.getHeight() != getHeight() ||
|
|
|
|
other.getTileWidth() != getTileWidth() ||
|
|
|
|
other.getTileHeight() != getTileHeight())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-11-28 20:44:09 -06:00
|
|
|
return other.getTilePosY() + other.getTileHeight() >= getTilePosY() &&
|
|
|
|
other.getTilePosY() <= getTilePosY() + getTileHeight();
|
2016-09-25 20:30:56 -05:00
|
|
|
}
|
|
|
|
|
2016-05-21 08:41:23 -05:00
|
|
|
/// Serialize this instance into a string.
|
|
|
|
/// Optionally prepend a prefix.
|
|
|
|
std::string serialize(const std::string& prefix = "") const
|
|
|
|
{
|
|
|
|
std::ostringstream oss;
|
|
|
|
oss << prefix
|
|
|
|
<< " part=" << _part
|
|
|
|
<< " width=" << _width
|
|
|
|
<< " height=" << _height
|
|
|
|
<< " tileposx=" << _tilePosX
|
|
|
|
<< " tileposy=" << _tilePosY
|
|
|
|
<< " tilewidth=" << _tileWidth
|
2016-11-23 20:28:50 -06:00
|
|
|
<< " tileheight=" << _tileHeight;
|
2016-09-19 19:30:35 -05:00
|
|
|
|
2016-11-23 20:28:50 -06:00
|
|
|
if (_id >= 0)
|
2016-09-19 19:30:35 -05:00
|
|
|
{
|
2016-11-23 20:28:50 -06:00
|
|
|
oss << " id=" << _id;
|
2016-09-19 19:30:35 -05:00
|
|
|
}
|
|
|
|
|
2016-11-23 20:28:50 -06:00
|
|
|
// Anything after ver is optional.
|
|
|
|
oss << " ver=" << _ver;
|
|
|
|
|
|
|
|
if (_imgSize > 0)
|
2016-05-21 08:41:23 -05:00
|
|
|
{
|
2016-11-23 20:28:50 -06:00
|
|
|
oss << " imgsize=" << _imgSize;
|
2016-05-21 08:41:23 -05:00
|
|
|
}
|
|
|
|
|
2016-10-07 08:07:50 -05:00
|
|
|
if (_broadcast)
|
|
|
|
{
|
|
|
|
oss << " broadcast=yes";
|
|
|
|
}
|
|
|
|
|
2016-05-21 08:41:23 -05:00
|
|
|
return oss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Deserialize a TileDesc from a tokenized string.
|
2016-10-29 20:15:00 -05:00
|
|
|
static TileDesc parse(const Poco::StringTokenizer& tokens)
|
2016-05-21 08:41:23 -05:00
|
|
|
{
|
2016-05-21 09:40:16 -05:00
|
|
|
// We don't expect undocumented fields and
|
2016-05-21 08:41:23 -05:00
|
|
|
// assume all values to be int.
|
|
|
|
std::map<std::string, int> pairs;
|
|
|
|
|
2016-05-22 10:35:41 -05:00
|
|
|
// Optional.
|
2016-05-22 13:21:05 -05:00
|
|
|
pairs["ver"] = -1;
|
2016-05-22 10:35:41 -05:00
|
|
|
pairs["imgsize"] = 0;
|
2016-05-22 13:21:05 -05:00
|
|
|
pairs["id"] = -1;
|
2016-05-21 08:41:23 -05:00
|
|
|
|
|
|
|
for (size_t i = 0; i < tokens.count(); ++i)
|
|
|
|
{
|
|
|
|
std::string name;
|
|
|
|
int value = -1;
|
|
|
|
if (LOOLProtocol::parseNameIntegerPair(tokens[i], name, value))
|
|
|
|
{
|
|
|
|
pairs[name] = value;
|
|
|
|
}
|
|
|
|
}
|
2016-11-23 20:28:50 -06:00
|
|
|
|
2016-10-07 08:07:50 -05:00
|
|
|
std::string s;
|
2016-11-23 20:28:50 -06:00
|
|
|
const bool broadcast = (LOOLProtocol::getTokenString(tokens, "broadcast", s) &&
|
|
|
|
s == "yes");
|
2016-05-21 08:41:23 -05:00
|
|
|
|
|
|
|
return TileDesc(pairs["part"], pairs["width"], pairs["height"],
|
|
|
|
pairs["tileposx"], pairs["tileposy"],
|
|
|
|
pairs["tilewidth"], pairs["tileheight"],
|
2016-05-22 13:21:05 -05:00
|
|
|
pairs["ver"],
|
2016-10-07 08:07:50 -05:00
|
|
|
pairs["imgsize"], pairs["id"], broadcast);
|
2016-05-21 08:41:23 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Deserialize a TileDesc from a string format.
|
2016-10-29 20:15:00 -05:00
|
|
|
static TileDesc parse(const std::string& message)
|
2016-05-21 08:41:23 -05:00
|
|
|
{
|
|
|
|
Poco::StringTokenizer tokens(message, " ",
|
2016-10-29 20:15:00 -05:00
|
|
|
Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
|
2016-05-21 08:41:23 -05:00
|
|
|
return parse(tokens);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
int _part;
|
|
|
|
int _width;
|
|
|
|
int _height;
|
|
|
|
int _tilePosX;
|
|
|
|
int _tilePosY;
|
|
|
|
int _tileWidth;
|
|
|
|
int _tileHeight;
|
2016-10-29 20:15:00 -05:00
|
|
|
int _ver; //< Versioning support.
|
|
|
|
int _imgSize; //< Used for responses.
|
2016-05-21 08:41:23 -05:00
|
|
|
int _id;
|
2016-10-07 08:07:50 -05:00
|
|
|
bool _broadcast;
|
2016-05-21 08:41:23 -05:00
|
|
|
};
|
|
|
|
|
2016-08-13 23:01:13 -05:00
|
|
|
/// One or more tile header.
|
|
|
|
/// Used to request the rendering of multiple
|
|
|
|
/// tiles as well as the header of the response.
|
2016-05-22 10:31:36 -05:00
|
|
|
class TileCombined
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
TileCombined(int part, int width, int height,
|
|
|
|
const std::string& tilePositionsX, const std::string& tilePositionsY,
|
2016-05-22 13:21:05 -05:00
|
|
|
int tileWidth, int tileHeight, int ver = -1,
|
|
|
|
const std::string& imgSizes = "", int id = -1) :
|
2016-05-22 10:31:36 -05:00
|
|
|
_part(part),
|
|
|
|
_width(width),
|
|
|
|
_height(height),
|
|
|
|
_tileWidth(tileWidth),
|
|
|
|
_tileHeight(tileHeight),
|
2016-05-22 13:21:05 -05:00
|
|
|
_ver(ver),
|
2016-05-22 10:31:36 -05:00
|
|
|
_id(id)
|
|
|
|
{
|
|
|
|
if (_part < 0 ||
|
|
|
|
_width <= 0 ||
|
|
|
|
_height <= 0 ||
|
|
|
|
_tileWidth <= 0 ||
|
|
|
|
_tileHeight <= 0)
|
|
|
|
{
|
|
|
|
throw BadArgumentException("Invalid tilecombine descriptor.");
|
|
|
|
}
|
|
|
|
|
|
|
|
Poco::StringTokenizer positionXtokens(tilePositionsX, ",", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
|
|
|
|
Poco::StringTokenizer positionYtokens(tilePositionsY, ",", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
|
2016-05-22 10:35:41 -05:00
|
|
|
Poco::StringTokenizer sizeTokens(imgSizes, ",", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
|
2016-05-22 10:31:36 -05:00
|
|
|
|
|
|
|
const auto numberOfPositions = positionYtokens.count();
|
|
|
|
|
|
|
|
// check that number of positions for X and Y is the same
|
2016-05-22 10:35:41 -05:00
|
|
|
if (numberOfPositions != positionXtokens.count() || (!imgSizes.empty() && numberOfPositions != sizeTokens.count()))
|
2016-05-22 10:31:36 -05:00
|
|
|
{
|
|
|
|
throw BadArgumentException("Invalid tilecombine descriptor. Uneven number of tiles.");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < numberOfPositions; ++i)
|
|
|
|
{
|
|
|
|
int x = 0;
|
|
|
|
if (!LOOLProtocol::stringToInteger(positionXtokens[i], x))
|
|
|
|
{
|
|
|
|
throw BadArgumentException("Invalid tilecombine descriptor.");
|
|
|
|
}
|
|
|
|
|
|
|
|
int y = 0;
|
|
|
|
if (!LOOLProtocol::stringToInteger(positionYtokens[i], y))
|
|
|
|
{
|
|
|
|
throw BadArgumentException("Invalid tilecombine descriptor.");
|
|
|
|
}
|
|
|
|
|
2016-05-22 10:35:41 -05:00
|
|
|
int size = 0;
|
|
|
|
if (sizeTokens.count() && !LOOLProtocol::stringToInteger(sizeTokens[i], size))
|
|
|
|
{
|
|
|
|
throw BadArgumentException("Invalid tilecombine descriptor.");
|
|
|
|
}
|
|
|
|
|
2016-10-07 08:07:50 -05:00
|
|
|
_tiles.emplace_back(_part, _width, _height, x, y, _tileWidth, _tileHeight, ver, size, id, false);
|
2016-05-22 10:31:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
int getPart() const { return _part; }
|
|
|
|
int getWidth() const { return _width; }
|
|
|
|
int getHeight() const { return _height; }
|
|
|
|
int getTileWidth() const { return _tileWidth; }
|
|
|
|
int getTileHeight() const { return _tileHeight; }
|
2016-05-22 13:21:05 -05:00
|
|
|
int getVersion() const { return _ver; }
|
|
|
|
void setVersion(const int ver) { _ver = ver; }
|
2016-05-22 10:31:36 -05:00
|
|
|
|
|
|
|
const std::vector<TileDesc>& getTiles() const { return _tiles; }
|
|
|
|
std::vector<TileDesc>& getTiles() { return _tiles; }
|
|
|
|
|
|
|
|
/// Serialize this instance into a string.
|
|
|
|
/// Optionally prepend a prefix.
|
|
|
|
std::string serialize(const std::string& prefix = "") const
|
|
|
|
{
|
|
|
|
std::ostringstream oss;
|
|
|
|
oss << prefix
|
|
|
|
<< " part=" << _part
|
|
|
|
<< " width=" << _width
|
|
|
|
<< " height=" << _height
|
|
|
|
<< " tileposx=";
|
|
|
|
for (const auto& tile : _tiles)
|
|
|
|
{
|
|
|
|
oss << tile.getTilePosX() << ',';
|
|
|
|
}
|
|
|
|
|
|
|
|
oss.seekp(-1, std::ios_base::cur); // Remove last comma.
|
|
|
|
|
|
|
|
oss << " tileposy=";
|
|
|
|
for (const auto& tile : _tiles)
|
|
|
|
{
|
|
|
|
oss << tile.getTilePosY() << ',';
|
|
|
|
}
|
|
|
|
|
|
|
|
oss.seekp(-1, std::ios_base::cur); // Remove last comma.
|
|
|
|
|
2016-05-22 10:35:41 -05:00
|
|
|
oss << " imgsize=";
|
|
|
|
for (const auto& tile : _tiles)
|
|
|
|
{
|
|
|
|
oss << tile.getImgSize() << ',';
|
|
|
|
}
|
|
|
|
|
|
|
|
oss.seekp(-1, std::ios_base::cur); // Remove last comma.
|
|
|
|
|
2016-05-22 10:31:36 -05:00
|
|
|
oss << " tilewidth=" << _tileWidth
|
|
|
|
<< " tileheight=" << _tileHeight;
|
2016-05-22 13:21:05 -05:00
|
|
|
|
2016-05-22 10:31:36 -05:00
|
|
|
if (_id >= 0)
|
|
|
|
{
|
|
|
|
oss << " id=" << _id;
|
|
|
|
}
|
|
|
|
|
2016-11-23 20:28:50 -06:00
|
|
|
if (_ver >= 0)
|
|
|
|
{
|
|
|
|
oss << " ver=" << _ver;
|
|
|
|
}
|
|
|
|
|
2016-05-22 10:31:36 -05:00
|
|
|
return oss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Deserialize a TileDesc from a tokenized string.
|
2016-10-29 20:15:00 -05:00
|
|
|
static TileCombined parse(const Poco::StringTokenizer& tokens)
|
2016-05-22 10:31:36 -05:00
|
|
|
{
|
|
|
|
// We don't expect undocumented fields and
|
|
|
|
// assume all values to be int.
|
|
|
|
std::map<std::string, int> pairs;
|
|
|
|
|
2016-05-22 13:21:05 -05:00
|
|
|
// Optional.
|
|
|
|
pairs["ver"] = -1;
|
2016-05-22 10:31:36 -05:00
|
|
|
pairs["id"] = -1;
|
|
|
|
|
|
|
|
std::string tilePositionsX;
|
|
|
|
std::string tilePositionsY;
|
2016-05-22 10:35:41 -05:00
|
|
|
std::string imgSizes;
|
2016-05-22 10:31:36 -05:00
|
|
|
for (size_t i = 0; i < tokens.count(); ++i)
|
|
|
|
{
|
|
|
|
std::string name;
|
|
|
|
std::string value;
|
|
|
|
if (LOOLProtocol::parseNameValuePair(tokens[i], name, value))
|
|
|
|
{
|
|
|
|
if (name == "tileposx")
|
|
|
|
{
|
|
|
|
tilePositionsX = value;
|
|
|
|
}
|
|
|
|
else if (name == "tileposy")
|
|
|
|
{
|
|
|
|
tilePositionsY = value;
|
|
|
|
}
|
2016-05-22 10:35:41 -05:00
|
|
|
else if (name == "imgsize")
|
|
|
|
{
|
|
|
|
imgSizes = value;
|
|
|
|
}
|
2016-05-22 10:31:36 -05:00
|
|
|
else
|
|
|
|
{
|
|
|
|
int v = 0;
|
|
|
|
if (LOOLProtocol::stringToInteger(value, v))
|
|
|
|
{
|
|
|
|
pairs[name] = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TileCombined(pairs["part"], pairs["width"], pairs["height"],
|
|
|
|
tilePositionsX, tilePositionsY,
|
|
|
|
pairs["tilewidth"], pairs["tileheight"],
|
2016-05-22 13:21:05 -05:00
|
|
|
pairs["ver"],
|
2016-05-22 10:35:41 -05:00
|
|
|
imgSizes, pairs["id"]);
|
2016-05-22 10:31:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Deserialize a TileDesc from a string format.
|
2016-10-29 20:15:00 -05:00
|
|
|
static TileCombined parse(const std::string& message)
|
2016-05-22 10:31:36 -05:00
|
|
|
{
|
|
|
|
Poco::StringTokenizer tokens(message, " ",
|
2016-10-29 20:15:00 -05:00
|
|
|
Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
|
2016-05-22 10:31:36 -05:00
|
|
|
return parse(tokens);
|
|
|
|
}
|
|
|
|
|
2016-10-29 20:15:00 -05:00
|
|
|
static TileCombined create(const std::vector<TileDesc>& tiles)
|
2016-09-15 07:40:26 -05:00
|
|
|
{
|
|
|
|
assert(!tiles.empty());
|
|
|
|
|
|
|
|
std::ostringstream xs;
|
|
|
|
std::ostringstream ys;
|
|
|
|
int ver = -1;
|
|
|
|
|
|
|
|
for (auto& tile : tiles)
|
|
|
|
{
|
|
|
|
xs << tile.getTilePosX() << ',';
|
|
|
|
ys << tile.getTilePosY() << ',';
|
|
|
|
ver = std::max(tile.getVersion(), ver);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TileCombined(tiles[0].getPart(), tiles[0].getWidth(), tiles[0].getHeight(),
|
|
|
|
xs.str(), ys.str(), tiles[0].getTileWidth(), tiles[0].getTileHeight(), ver, "", -1);
|
|
|
|
}
|
|
|
|
|
2016-05-22 10:31:36 -05:00
|
|
|
private:
|
|
|
|
std::vector<TileDesc> _tiles;
|
|
|
|
int _part;
|
|
|
|
int _width;
|
|
|
|
int _height;
|
|
|
|
int _tileWidth;
|
|
|
|
int _tileHeight;
|
2016-10-29 20:15:00 -05:00
|
|
|
int _ver; //< Versioning support.
|
2016-05-22 10:31:36 -05:00
|
|
|
int _id;
|
|
|
|
};
|
|
|
|
|
2016-05-21 08:41:23 -05:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|