[Libreoffice-commits] online.git: Branch 'distro/collabora/collabora-online-4-0' - common/Session.cpp common/Session.hpp kit/ChildSession.hpp kit/Kit.cpp kit/Watermark.hpp loleaflet/src Makefile.am wsd/ClientSession.cpp wsd/DocumentBroker.cpp

Mert Tumer (via logerrit) logerrit at kemper.freedesktop.org
Sat Oct 19 18:14:27 UTC 2019


 Makefile.am                           |    3 
 common/Session.cpp                    |   16 ++
 common/Session.hpp                    |   12 +
 kit/ChildSession.hpp                  |    2 
 kit/Kit.cpp                           |  224 ++++++----------------------------
 kit/Watermark.hpp                     |  178 +++++++++++++++++++++++++++
 loleaflet/src/core/Socket.js          |    3 
 loleaflet/src/layer/tile/TileLayer.js |    2 
 wsd/ClientSession.cpp                 |    7 -
 wsd/DocumentBroker.cpp                |    4 
 10 files changed, 264 insertions(+), 187 deletions(-)

New commits:
commit ed5d304a6e17d98569a75fa9b73639ee07dbdee6
Author:     Mert Tumer <mert.tumer at collabora.com>
AuthorDate: Wed Oct 16 14:00:16 2019 +0300
Commit:     Andras Timar <andras.timar at collabora.com>
CommitDate: Sat Oct 19 20:14:08 2019 +0200

    Moved class Watermark to a seperate file
    
    Added hash method for watermarktext and
    find it from normalizedviewid for rendering
    watermarks on the correct tiles
    
    Change-Id: I4b22ae1493d2957afb93028d1ece967cf766268f
    Reviewed-on: https://gerrit.libreoffice.org/81047
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/Makefile.am b/Makefile.am
index 14d64158a..dea71963d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -220,7 +220,8 @@ kit_headers = kit/ChildSession.hpp \
               kit/Delta.hpp \
               kit/DummyLibreOfficeKit.hpp \
               kit/Kit.hpp \
-              kit/KitHelper.hpp
+              kit/KitHelper.hpp \
+              kit/Watermark.hpp
 
 noinst_HEADERS = $(wsd_headers) $(shared_headers) $(kit_headers) \
                  bundled/include/LibreOfficeKit/LibreOfficeKit.h \
diff --git a/common/Session.cpp b/common/Session.cpp
index f7ed7f33f..040bbc25e 100644
--- a/common/Session.cpp
+++ b/common/Session.cpp
@@ -250,6 +250,22 @@ void Session::getIOStats(uint64_t &sent, uint64_t &recv)
     }
 }
 
+ void Session::setHash(const std::string& text)
+ {
+     int hash = 0x811C9DC5;
+     int prime = 0x1000193;
+
+     if (!text.empty())
+     {
+        for (unsigned int i = 0; i < text.length(); ++i)
+        {
+            hash += hash ^ text[i];
+            hash *= prime;
+        }
+     }
+     _hash = abs(hash);
+ }
+
 void Session::dumpState(std::ostream& os)
 {
     WebSocketHandler::dumpState(os);
diff --git a/common/Session.hpp b/common/Session.hpp
index 49f48b2e9..1934c9465 100644
--- a/common/Session.hpp
+++ b/common/Session.hpp
@@ -122,6 +122,13 @@ public:
 
     const std::string& getJailedFilePathAnonym() const { return _jailedFilePathAnonym; }
 
+    int getHash() { return _hash; }
+
+    void setHash(const std::string& text);
+
+    void setHash(const int hash) { _hash = hash; };
+
+
 protected:
     Session(const std::string& name, const std::string& id, bool readonly);
     virtual ~Session();
@@ -212,6 +219,11 @@ private:
 
     /// Language for the document based on what the user has in the UI.
     std::string _lang;
+
+    /// Hash for normalizedViewId which is basically an identity for the tile to
+    /// choose what to render on and send it to its subscribers
+    /// it is the close-to-unique integer representation of a string like Watermarks etc.
+    int _hash;
 };
 
 #endif
diff --git a/kit/ChildSession.hpp b/kit/ChildSession.hpp
index f6bcf60a7..bbcc2c773 100644
--- a/kit/ChildSession.hpp
+++ b/kit/ChildSession.hpp
@@ -24,6 +24,7 @@
 #include "Kit.hpp"
 #include "Session.hpp"
 
+class Watermark;
 class ChildSession;
 
 enum class LokEventTargetEnum
@@ -238,6 +239,7 @@ public:
     }
 
     using Session::sendTextFrame;
+    std::shared_ptr<Watermark> _docWatermark;
 
 private:
     bool loadDocument(const char* buffer, int length, const std::vector<std::string>& tokens);
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index ad0df946e..3adb5347e 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -67,6 +67,7 @@
 #include <UserMessages.hpp>
 #include <Util.hpp>
 #include "Delta.hpp"
+#include "Watermark.hpp"
 
 #ifndef MOBILEAPP
 #include <common/SigUtil.hpp>
@@ -629,171 +630,6 @@ public:
     }
 };
 
-class Watermark
-{
-public:
-    Watermark(const std::shared_ptr<lok::Document>& loKitDoc, const std::string& text,
-    const std::shared_ptr<ChildSession> & session)
-        : _loKitDoc(loKitDoc)
-        , _text(text)
-        , _font("Liberation Sans")
-        , _width(0)
-        , _height(0)
-        , _alphaLevel(session->getWatermarkOpacity())
-    {
-    }
-
-    ~Watermark()
-    {
-    }
-
-    void blending(unsigned char* tilePixmap,
-                   int offsetX, int offsetY,
-                   int tilesPixmapWidth, int tilesPixmapHeight,
-                   int tileWidth, int tileHeight,
-                   LibreOfficeKitTileMode /*mode*/)
-    {
-        // set requested watermark size a little bit smaller than tile size
-        int width = tileWidth * 0.9;
-        int height = tileHeight * 0.9;
-
-        const std::vector<unsigned char>* pixmap = getPixmap(width, height);
-
-        if (pixmap && tilePixmap)
-        {
-            // center watermark
-            const int maxX = std::min(tileWidth, _width);
-            const int maxY = std::min(tileHeight, _height);
-            offsetX += (tileWidth - maxX) / 2;
-            offsetY += (tileHeight - maxY) / 2;
-
-            alphaBlend(*pixmap, _width, _height, offsetX, offsetY, tilePixmap, tilesPixmapWidth, tilesPixmapHeight);
-        }
-    }
-
-private:
-    /// Alpha blend pixels from 'from' over the 'to'.
-    void alphaBlend(const std::vector<unsigned char>& from, int from_width, int from_height, int from_offset_x, int from_offset_y,
-            unsigned char* to, int to_width, int to_height)
-    {
-        for (int to_y = from_offset_y, from_y = 0; (to_y < to_height) && (from_y < from_height) ; ++to_y, ++from_y)
-            for (int to_x = from_offset_x, from_x = 0; (to_x < to_width) && (from_x < from_width); ++to_x, ++from_x)
-            {
-                const unsigned char* f = from.data() + 4 * (from_y * from_width + from_x);
-                double src_r = f[0];
-                double src_g = f[1];
-                double src_b = f[2];
-                double src_a = f[3] / 255.0;
-
-                unsigned char* t = to + 4 * (to_y * to_width + to_x);
-                double dst_r = t[0];
-                double dst_g = t[1];
-                double dst_b = t[2];
-                double dst_a = t[3] / 255.0;
-
-                double out_a = src_a + dst_a * (1.0 - src_a);
-                unsigned char out_r = src_r + dst_r * (1.0 - src_a);
-                unsigned char out_g = src_g + dst_g * (1.0 - src_a);
-                unsigned char out_b = src_b + dst_b * (1.0 - src_a);
-
-                t[0] = out_r;
-                t[1] = out_g;
-                t[2] = out_b;
-                t[3] = static_cast<unsigned char>(out_a * 255.0);
-            }
-    }
-
-    /// Create bitmap that we later use as the watermark for every tile.
-    const std::vector<unsigned char>* getPixmap(int width, int height)
-    {
-        if (!_pixmap.empty() && width == _width && height == _height)
-            return &_pixmap;
-
-        _pixmap.clear();
-
-        _width = width;
-        _height = height;
-
-        if (!_loKitDoc)
-        {
-            LOG_ERR("Watermark rendering requested without a valid document.");
-            return nullptr;
-        }
-
-        // renderFont returns a buffer based on RGBA mode, where r, g, b
-        // are always set to 0 (black) and the alpha level is 0 everywhere
-        // except on the text area; the alpha level take into account of
-        // performing anti-aliasing over the text edges.
-        unsigned char* textPixels = _loKitDoc->renderFont(_font.c_str(), _text.c_str(), &_width, &_height);
-
-        if (!textPixels)
-        {
-            LOG_ERR("Watermark: rendering failed.");
-        }
-
-        const unsigned int pixel_count = width * height * 4;
-
-        std::vector<unsigned char> text(textPixels, textPixels + pixel_count);
-        // No longer needed.
-        std::free(textPixels);
-
-        _pixmap.reserve(pixel_count);
-
-        // Create the white blurred background
-        // Use box blur, it's enough for our purposes
-        const int r = 2;
-        const double weight = (r+1) * (r+1);
-        for (int y = 0; y < height; ++y)
-        {
-            for (int x = 0; x < width; ++x)
-            {
-                double t = 0;
-                for (int ky = std::max(y - r, 0); ky <= std::min(y + r, height - 1); ++ky)
-                {
-                    for (int kx = std::max(x - r, 0); kx <= std::min(x + r, width - 1); ++kx)
-                    {
-                        // Pre-multiplied alpha; the text is black, so all the
-                        // information is only in the alpha channel
-                        t += text[4 * (ky * width + kx) + 3];
-                    }
-                }
-
-                // Clamp the result.
-                double avg = t / weight;
-                if (avg > 255.0)
-                    avg = 255.0;
-
-                // Pre-multiplied alpha, but use white for the resulting color
-                const double alpha = avg / 255.0;
-                _pixmap[4 * (y * width + x) + 0] = 0xff * alpha;
-                _pixmap[4 * (y * width + x) + 1] = 0xff * alpha;
-                _pixmap[4 * (y * width + x) + 2] = 0xff * alpha;
-                _pixmap[4 * (y * width + x) + 3] = avg;
-            }
-        }
-
-        // Now copy the (black) text over the (white) blur
-        alphaBlend(text, _width, _height, 0, 0, _pixmap.data(), _width, _height);
-
-        // Make the resulting pixmap semi-transparent
-        for (unsigned char* p = _pixmap.data(); p < _pixmap.data() + pixel_count; p++)
-        {
-            *p = static_cast<unsigned char>(*p * _alphaLevel);
-        }
-
-        return &_pixmap;
-    }
-
-private:
-    std::shared_ptr<lok::Document> _loKitDoc;
-    std::string _text;
-    std::string _font;
-    int _width;
-    int _height;
-    double _alphaLevel;
-    std::vector<unsigned char> _pixmap;
-};
-
 #ifndef MOBILEAPP
 static FILE* ProcSMapsFile = nullptr;
 #endif
@@ -1030,6 +866,22 @@ public:
                 " ms (" << area / elapsed << " MP/s).");
         const auto mode = static_cast<LibreOfficeKitTileMode>(_loKitDocument->getTileMode());
 
+        int nViewId = tile.getNormalizedViewId();
+        const auto it = std::find_if(_sessions.begin(), _sessions.end(), [nViewId](const std::pair<std::string, std::shared_ptr<ChildSession>>& val){ return (val.second)->getHash() == nViewId; });
+        const auto& session = it->second;
+
+        if (it == _sessions.end())
+        {
+            LOG_ERR("Session is not found. Maybe exited after rendering request.");
+            return;
+        }
+
+        int pixelWidth = tile.getWidth();
+        int pixelHeight = tile.getHeight();
+
+        if (session->_docWatermark)
+            session->_docWatermark->blending(pixmap.data(), 0, 0, pixelWidth, pixelHeight, pixelWidth, pixelHeight, mode);
+
         const TileBinaryHash hash = Png::hashBuffer(pixmap.data(), tile.getWidth(), tile.getHeight());
         TileWireId wid = _pngCache.hashToWireId(hash);
         TileWireId oldWireId = tile.getOldWireId();
@@ -1046,12 +898,6 @@ public:
         // Send back the request with all optional parameters given in the request.
         std::string response = ADD_DEBUG_RENDERID(tile.serialize("tile:")) + "\n";
 
-        int pixelWidth = tile.getWidth();
-        int pixelHeight = tile.getHeight();
-
-        if (_docWatermark)
-            _docWatermark->blending(pixmap.data(), 0, 0, pixelWidth, pixelHeight, pixelWidth, pixelHeight, mode);
-
         std::shared_ptr<std::vector<char>> output = std::make_shared<std::vector<char>>();
         output->reserve(response.size() + pixmapDataSize);
         output->resize(response.size());
@@ -1134,6 +980,16 @@ public:
                 " rendered in " << (elapsed/1000.) << " ms (" << area / elapsed << " MP/s).");
         const auto mode = static_cast<LibreOfficeKitTileMode>(_loKitDocument->getTileMode());
 
+        int nViewId = tileCombined.getNormalizedViewId();
+        const auto it = std::find_if(_sessions.begin(), _sessions.end(), [nViewId](const std::pair<std::string, std::shared_ptr<ChildSession>>& val){ return (val.second)->getHash() == nViewId; });
+        const auto& session = it->second;
+
+        if (it == _sessions.end())
+        {
+            LOG_ERR("Session is not found. Maybe exited after rendering request.");
+            return;
+        }
+
         std::vector<char> output;
         output.reserve(pixmapSize);
 
@@ -1150,6 +1006,12 @@ public:
             const int offsetX = positionX * pixelWidth;
             const int offsetY = positionY * pixelHeight;
 
+            if (session->_docWatermark)
+                session->_docWatermark->blending(pixmap.data(), offsetX, offsetY,
+                                        pixmapWidth, pixmapHeight,
+                                        pixelWidth, pixelHeight,
+                                        mode);
+
             const uint64_t hash = Png::hashSubBuffer(pixmap.data(), offsetX, offsetY,
                                                      pixelWidth, pixelHeight, pixmapWidth, pixmapHeight);
 
@@ -1164,12 +1026,6 @@ public:
                 continue;
             }
 
-            if (_docWatermark)
-                _docWatermark->blending(pixmap.data(), offsetX, offsetY,
-                                        pixmapWidth, pixmapHeight,
-                                        pixelWidth, pixelHeight,
-                                        mode);
-
             if (!_pngCache.encodeSubBufferToPNG(pixmap.data(), offsetX, offsetY,
                                                 pixelWidth, pixelHeight, pixmapWidth, pixmapHeight, output, mode,
                                                 hash, wireId, oldWireId))
@@ -1738,9 +1594,6 @@ private:
             // Only save the options on opening the document.
             // No support for changing them after opening a document.
             _renderOpts = renderOpts;
-
-            if (!watermarkText.empty())
-                _docWatermark.reset(new Watermark(_loKitDocument, watermarkText, session));
         }
         else
         {
@@ -1796,6 +1649,14 @@ private:
                 sessionId << "] loaded view [" << viewId << "]. Have " <<
                 viewCount << " view" << (viewCount != 1 ? "s." : "."));
 
+        if (!watermarkText.empty())
+        {
+            session->_docWatermark.reset(new Watermark(_loKitDocument, watermarkText, session));
+            session->setHash(watermarkText);
+        }
+        else
+            session->setHash(0);
+
         return _loKitDocument;
     }
 
@@ -2107,9 +1968,6 @@ private:
     // Whether password is required to view the document, or modify it
     PasswordType _docPasswordType;
 
-    // Document watermark
-    std::unique_ptr<Watermark> _docWatermark;
-
     std::atomic<bool> _stop;
     mutable std::mutex _mutex;
 
diff --git a/kit/Watermark.hpp b/kit/Watermark.hpp
new file mode 100644
index 000000000..063db0385
--- /dev/null
+++ b/kit/Watermark.hpp
@@ -0,0 +1,178 @@
+#ifndef INCLUDED_WATERMARK_HPP
+#define INCLUDED_WATERMARK_HPP
+
+#define LOK_USE_UNSTABLE_API
+#include <LibreOfficeKit/LibreOfficeKitInit.h>
+#include <LibreOfficeKit/LibreOfficeKit.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <vector>
+#include <Log.hpp>
+#include <cstdlib>
+#include <string>
+#include "ChildSession.hpp"
+
+class Watermark
+{
+public:
+    Watermark(const std::shared_ptr<lok::Document>& loKitDoc, const std::string& text,
+    const std::shared_ptr<ChildSession> & session)
+        : _loKitDoc(loKitDoc)
+        , _text(text)
+        , _font("Liberation Sans")
+        , _width(0)
+        , _height(0)
+        , _alphaLevel(session->getWatermarkOpacity())
+    {
+    }
+
+    ~Watermark()
+    {
+    }
+
+    void blending(unsigned char* tilePixmap,
+                   int offsetX, int offsetY,
+                   int tilesPixmapWidth, int tilesPixmapHeight,
+                   int tileWidth, int tileHeight,
+                   LibreOfficeKitTileMode /*mode*/)
+    {
+        // set requested watermark size a little bit smaller than tile size
+        int width = tileWidth * 0.9;
+        int height = tileHeight * 0.9;
+
+        const std::vector<unsigned char>* pixmap = getPixmap(width, height);
+
+        if (pixmap && tilePixmap)
+        {
+            // center watermark
+            const int maxX = std::min(tileWidth, _width);
+            const int maxY = std::min(tileHeight, _height);
+            offsetX += (tileWidth - maxX) / 2;
+            offsetY += (tileHeight - maxY) / 2;
+
+            alphaBlend(*pixmap, _width, _height, offsetX, offsetY, tilePixmap, tilesPixmapWidth, tilesPixmapHeight);
+        }
+    }
+
+private:
+    /// Alpha blend pixels from 'from' over the 'to'.
+    void alphaBlend(const std::vector<unsigned char>& from, int from_width, int from_height, int from_offset_x, int from_offset_y,
+            unsigned char* to, int to_width, int to_height)
+    {
+        for (int to_y = from_offset_y, from_y = 0; (to_y < to_height) && (from_y < from_height) ; ++to_y, ++from_y)
+            for (int to_x = from_offset_x, from_x = 0; (to_x < to_width) && (from_x < from_width); ++to_x, ++from_x)
+            {
+                const unsigned char* f = from.data() + 4 * (from_y * from_width + from_x);
+                double src_r = f[0];
+                double src_g = f[1];
+                double src_b = f[2];
+                double src_a = f[3] / 255.0;
+
+                unsigned char* t = to + 4 * (to_y * to_width + to_x);
+                double dst_r = t[0];
+                double dst_g = t[1];
+                double dst_b = t[2];
+                double dst_a = t[3] / 255.0;
+
+                double out_a = src_a + dst_a * (1.0 - src_a);
+                unsigned char out_r = src_r + dst_r * (1.0 - src_a);
+                unsigned char out_g = src_g + dst_g * (1.0 - src_a);
+                unsigned char out_b = src_b + dst_b * (1.0 - src_a);
+
+                t[0] = out_r;
+                t[1] = out_g;
+                t[2] = out_b;
+                t[3] = static_cast<unsigned char>(out_a * 255.0);
+            }
+    }
+
+    /// Create bitmap that we later use as the watermark for every tile.
+    const std::vector<unsigned char>* getPixmap(int width, int height)
+    {
+        if (!_pixmap.empty() && width == _width && height == _height)
+            return &_pixmap;
+
+        _pixmap.clear();
+
+        _width = width;
+        _height = height;
+
+        if (!_loKitDoc)
+        {
+            LOG_ERR("Watermark rendering requested without a valid document.");
+            return nullptr;
+        }
+
+        // renderFont returns a buffer based on RGBA mode, where r, g, b
+        // are always set to 0 (black) and the alpha level is 0 everywhere
+        // except on the text area; the alpha level take into account of
+        // performing anti-aliasing over the text edges.
+        unsigned char* textPixels = _loKitDoc->renderFont(_font.c_str(), _text.c_str(), &_width, &_height);
+
+        if (!textPixels)
+        {
+            LOG_ERR("Watermark: rendering failed.");
+        }
+
+        const unsigned int pixel_count = width * height * 4;
+
+        std::vector<unsigned char> text(textPixels, textPixels + pixel_count);
+        // No longer needed.
+        std::free(textPixels);
+
+        _pixmap.reserve(pixel_count);
+
+        // Create the white blurred background
+        // Use box blur, it's enough for our purposes
+        const int r = 2;
+        const double weight = (r+1) * (r+1);
+        for (int y = 0; y < height; ++y)
+        {
+            for (int x = 0; x < width; ++x)
+            {
+                double t = 0;
+                for (int ky = std::max(y - r, 0); ky <= std::min(y + r, height - 1); ++ky)
+                {
+                    for (int kx = std::max(x - r, 0); kx <= std::min(x + r, width - 1); ++kx)
+                    {
+                        // Pre-multiplied alpha; the text is black, so all the
+                        // information is only in the alpha channel
+                        t += text[4 * (ky * width + kx) + 3];
+                    }
+                }
+
+                // Clamp the result.
+                double avg = t / weight;
+                if (avg > 255.0)
+                    avg = 255.0;
+
+                // Pre-multiplied alpha, but use white for the resulting color
+                const double alpha = avg / 255.0;
+                _pixmap[4 * (y * width + x) + 0] = 0xff * alpha;
+                _pixmap[4 * (y * width + x) + 1] = 0xff * alpha;
+                _pixmap[4 * (y * width + x) + 2] = 0xff * alpha;
+                _pixmap[4 * (y * width + x) + 3] = avg;
+            }
+        }
+
+        // Now copy the (black) text over the (white) blur
+        alphaBlend(text, _width, _height, 0, 0, _pixmap.data(), _width, _height);
+
+        // Make the resulting pixmap semi-transparent
+        for (unsigned char* p = _pixmap.data(); p < _pixmap.data() + pixel_count; p++)
+        {
+            *p = static_cast<unsigned char>(*p * _alphaLevel);
+        }
+
+        return &_pixmap;
+    }
+
+private:
+    std::shared_ptr<lok::Document> _loKitDoc;
+    std::string _text;
+    std::string _font;
+    int _width;
+    int _height;
+    double _alphaLevel;
+    std::vector<unsigned char> _pixmap;
+};
+#endif
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index ffe478d81..b6c8101d5 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -969,6 +969,9 @@ L.Socket = L.Class.extend({
 			else if (tokens[i].substring(0, 7) === 'viewid=') {
 				command.viewid = tokens[i].substring(7);
 			}
+			else if (tokens[i].substring(0, 8) === 'nviewid=') {
+				command.nviewid = tokens[i].substring(8);
+			}
 			else if (tokens[i].substring(0, 7) === 'params=') {
 				command.params = tokens[i].substring(7).split(',');
 			}
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 57acac5f6..2fb2cb859 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -1476,7 +1476,7 @@ L.TileLayer = L.GridLayer.extend({
 		L.Log.log(textMsg, L.INCOMING, key);
 
 		// Send acknowledgment, that the tile message arrived
-		var tileID = command.part + ':' + command.x + ':' + command.y + ':' + command.tileWidth + ':' + command.tileHeight;
+		var tileID = command.part + ':' + command.x + ':' + command.y + ':' + command.tileWidth + ':' + command.tileHeight + ':' + command.nviewid;
 		this._map._socket.sendMessage('tileprocessed tile=' + tileID);
 	},
 
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index c5182616d..86a79754e 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -591,6 +591,7 @@ bool ClientSession::sendTile(const char * /*buffer*/, int /*length*/, const std:
     try
     {
         TileDesc tileDesc = TileDesc::parse(tokens);
+        tileDesc.setNormalizedViewId(getHash());
         docBroker->handleTileRequest(tileDesc, shared_from_this());
     }
     catch (const std::exception& exc)
@@ -608,6 +609,7 @@ bool ClientSession::sendCombinedTiles(const char* /*buffer*/, int /*length*/, co
     try
     {
         TileCombined tileCombined = TileCombined::parse(tokens);
+        tileCombined.setNormalizedViewId(getHash());
         docBroker->handleTileCombinedRequest(tileCombined, shared_from_this());
     }
     catch (const std::exception& exc)
@@ -1322,7 +1324,7 @@ void ClientSession::handleTileInvalidation(const std::string& message,
     if( part == -1 ) // If no part is specifed we use the part used by the client
         part = _clientSelectedPart;
 
-    int normalizedViewId=0;
+    int normalizedViewId=getHash();
 
     std::vector<TileDesc> invalidTiles;
     if(part == _clientSelectedPart || _isTextDocument)
@@ -1355,6 +1357,7 @@ void ClientSession::handleTileInvalidation(const std::string& message,
     if(!invalidTiles.empty())
     {
         TileCombined tileCombined = TileCombined::create(invalidTiles);
+        tileCombined.setNormalizedViewId(getHash());
         docBroker->handleTileCombinedRequest(tileCombined, shared_from_this());
     }
 }
@@ -1429,7 +1432,7 @@ std::string ClientSession::generateTileID(const TileDesc& tile) const
 {
     std::ostringstream tileID;
     tileID << tile.getPart() << ":" << tile.getTilePosX() << ":" << tile.getTilePosY() << ":"
-           << tile.getTileWidth() << ":" << tile.getTileHeight();
+           << tile.getTileWidth() << ":" << tile.getTileHeight() << ":" << tile.getNormalizedViewId();
     return tileID.str();
 }
 
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 5e89ee736..3119a14c1 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -623,6 +623,10 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
     session->setUserName(username);
     session->setUserExtraInfo(userExtraInfo);
     session->setWatermarkText(watermarkText);
+    if(!watermarkText.empty())
+        session->setHash(watermarkText);
+    else
+        session->setHash(0);
 
     // Basic file information was stored by the above getWOPIFileInfo() or getLocalFileInfo() calls
     const StorageBase::FileInfo fileInfo = _storage->getFileInfo();


More information about the Libreoffice-commits mailing list