[Libreoffice-commits] online.git: 7 commits - loleaflet/reference.html loleaflet/src loolwsd/bundled loolwsd/LOOLSession.cpp loolwsd/LOOLSession.hpp loolwsd/protocol.txt loolwsd/TileCache.cpp loolwsd/TileCache.hpp

Mihai Varga mihai.varga at collabora.com
Mon Nov 30 02:59:59 PST 2015


 loleaflet/reference.html                                |   47 ++++++++
 loleaflet/src/control/Toolbar.js                        |    8 +
 loleaflet/src/core/Socket.js                            |    5 
 loleaflet/src/layer/tile/TileLayer.js                   |   11 +
 loolwsd/LOOLSession.cpp                                 |   93 ++++++++++++++++
 loolwsd/LOOLSession.hpp                                 |    6 +
 loolwsd/TileCache.cpp                                   |   29 ++++
 loolwsd/TileCache.hpp                                   |    6 +
 loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h |    6 +
 loolwsd/protocol.txt                                    |    5 
 10 files changed, 213 insertions(+), 3 deletions(-)

New commits:
commit 5b1471aaf05d60164bc0016955cca1c1063c6427
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Mon Nov 30 12:59:37 2015 +0200

    loolwsd: update the bundled headers

diff --git a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
index 5189cca..a78c0aa 100644
--- a/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/loolwsd/bundled/include/LibreOfficeKit/LibreOfficeKit.h
@@ -202,6 +202,12 @@ struct _LibreOfficeKitDocumentClass
     int (*getView) (LibreOfficeKitDocument* pThis);
     /// @see lok::Document::getViews().
     int (*getViews) (LibreOfficeKitDocument* pThis);
+
+    /// @see lok::Document::renderFont().
+    unsigned char* (*renderFont) (LibreOfficeKitDocument* pThis,
+                       const char* pFontName,
+                       int* pFontWidth,
+                       int* pFontHeight);
 #endif // LOK_USE_UNSTABLE_API
 };
 
commit e1b0e3dce92d66a258570c011ed171454119e4b3
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Mon Nov 30 12:58:41 2015 +0200

    loolwsd: update renderFont png encoding

diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index b0ef846..9708131 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -1117,17 +1117,16 @@ void ChildProcessSession::sendFontRendering(const char* /*buffer*/, int /*length
     pixmap = _loKitDocument->pClass->renderFont(_loKitDocument, decodedFont.c_str(), &width, &height);
     std::cout << Util::logPrefix() << "renderFont called, font[" << font << "] rendered in " << double(timestamp.elapsed())/1000 <<  "ms" << std::endl;
 
-    if (pixmap != NULL) {
-        if (!Util::encodePNGAndAppendToBuffer(pixmap, width, height, output))
+    if (pixmap != nullptr) {
+        if (!Util::encodePNGAndAppendToBuffer(pixmap, width, height, output, LOK_TILEMODE_RGBA))
         {
             sendTextFrame("error: cmd=renderfont kind=failure");
             delete[] pixmap;
             return;
         }
+        delete[] pixmap;
     }
 
-    delete[] pixmap;
-
     sendBinaryFrame(output.data(), output.size());
 }
 
commit b78fd2c68a635250db44c636220854a7b1bfdf68
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Fri Nov 27 16:16:27 2015 +0200

    loleaflet: renderfont command handler

diff --git a/loleaflet/reference.html b/loleaflet/reference.html
index 9996b4c..9c80699 100644
--- a/loleaflet/reference.html
+++ b/loleaflet/reference.html
@@ -1636,6 +1636,12 @@ var map = L.map('map', {
 		<td><code>undefined</code></td>
         <td>Applies a style from a style family.</td>
 	</tr>
+	<tr>
+		<td><code><b>renderFont</b>(
+            <nobr><String><i>fontName</i>)</nobr>
+		<td><code>undefined</code></td>
+        <td>Renders the given font in the smallest rectangle it can fit in.</td>
+	</tr>
 </table>
 
 <h2 id="loleaflet-page">Page oriented</h2>
@@ -1752,6 +1758,11 @@ var map = L.map('map', {
 		<td>Fired when the url for the pdf export is ready.</td>
 	</tr>
 	<tr>
+		<td><code><b>renderfont</b></code></td>
+		<td><code><a href="#renderfont-event">RenderFontEvent</a></code></td>
+		<td>Fired when the font rendering is ready.</td>
+	</tr>
+	<tr>
 		<td><code><b>search</b></code></td>
 		<td><code><a href="#search-event">SearchEvent</a></code></td>
 		<td>Fired when the search result is ready.</td>
@@ -1976,6 +1987,26 @@ var map = L.map('map', {
 	</tr>
 </table>
 
+<h3 id="renderfont-event">RenderFontEvent</h3>
+
+<table data-id='events'>
+	<tr>
+		<th class="width100">property</th>
+		<th>type</th>
+		<th>description</th>
+	</tr>
+	<tr>
+		<td><code><b>font</b></code></td>
+        <td><code>String</code></td>
+		<td>Font name.</td>
+	</tr>
+	<tr>
+		<td><code><b>img</b></code></td>
+        <td><code>String</code></td>
+		<td>The image data URL.</td>
+	</tr>
+</table>
+
 <h3 id="search-event">SearchEvent</h3>
 
 <table data-id='events'>
diff --git a/loleaflet/src/control/Toolbar.js b/loleaflet/src/control/Toolbar.js
index 4ff4d17..4f05b43 100644
--- a/loleaflet/src/control/Toolbar.js
+++ b/loleaflet/src/control/Toolbar.js
@@ -104,5 +104,9 @@ L.Map.include({
 			}
 		};
 		L.Socket.sendMessage('uno .uno:EnterString ' + JSON.stringify(command));
+	},
+
+	renderFont: function (fontName) {
+		L.Socket.sendMessage('renderfont font=' + window.encodeURIComponent(fontName));
 	}
 });
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index fe47c65..744ca6f 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -85,7 +85,7 @@ L.Socket = {
 			textMsg = String.fromCharCode.apply(null, imgBytes.subarray(0, index));
 		}
 
-		if (!textMsg.startsWith('tile:')) {
+		if (!textMsg.startsWith('tile:') && !textMsg.startsWith('renderfont:')) {
 			// log the tile msg separately as we need the tile coordinates
 			L.Log.log(textMsg, L.INCOMING);
 			if (imgBytes !== undefined) {
@@ -222,6 +222,9 @@ L.Socket = {
 			else if (tokens[i].substring(0, 5) === 'port=') {
 				command.port = tokens[i].substring(5);
 			}
+			else if (tokens[i].substring(0, 5) === 'font=') {
+				command.font = window.decodeURIComponent(tokens[i].substring(5));
+			}
 		}
 		if (command.tileWidth && command.tileHeight && this._map._docLayer) {
 			var scale = command.tileWidth / this._map._docLayer.options.tileWidthTwips;
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 94f32bb..1810ca3 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -257,6 +257,9 @@ L.TileLayer = L.GridLayer.extend({
 		else if (textMsg.startsWith('partpagerectangles:')) {
 			this._onPartPageRectanglesMsg(textMsg);
 		}
+		else if (textMsg.startsWith('renderfont:')) {
+			this._onRenderFontMsg(textMsg, img);
+		}
 		else if (textMsg.startsWith('searchnotfound:')) {
 			this._onSearchNotFoundMsg(textMsg);
 		}
@@ -445,6 +448,14 @@ L.TileLayer = L.GridLayer.extend({
 		this._onCurrentPageUpdate();
 	},
 
+	_onRenderFontMsg: function (textMsg, img) {
+		var command = L.Socket.parseServerCmd(textMsg);
+		this._map.fire('renderfont', {
+			font: command.font,
+			img: img
+		});
+	},
+
 	_onSearchNotFoundMsg: function (textMsg) {
 		var originalPhrase = textMsg.substring(16);
 		this._map.fire('search', {originalPhrase: originalPhrase, count: 0});
commit 862cfe29a021f653b3292d9b78deb6be2345d78a
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Fri Nov 27 16:13:25 2015 +0200

    loolwsd: `renderfont` command handler
    
    Renders the requested font and sends it back to the client as a png
    image

diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index 1bac381..b0ef846 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -295,6 +295,16 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
                 assert(firstLine.size() == static_cast<std::string::size_type>(length));
                 peer->_tileCache->invalidateTiles(firstLine);
             }
+            else if (tokens[0] == "renderfont:")
+            {
+                std::string font;
+                if (tokens.count() < 2 ||
+                    !getTokenString(tokens[1], "font", font))
+                    assert(false);
+
+                assert(firstLine.size() < static_cast<std::string::size_type>(length));
+                peer->_tileCache->saveRendering(font, "font", buffer + firstLine.size() + 1, length - firstLine.size() - 1);
+            }
         }
 
         forwardToPeer(buffer, length);
@@ -365,6 +375,7 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
              tokens[0] != "key" &&
              tokens[0] != "mouse" &&
              tokens[0] != "partpagerectangles" &&
+             tokens[0] != "renderfont" &&
              tokens[0] != "requestloksession" &&
              tokens[0] != "resetselection" &&
              tokens[0] != "saveas" &&
@@ -401,6 +412,10 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
     {
         return invalidateTiles(buffer, length, tokens);
     }
+    else if (tokens[0] == "renderfont")
+    {
+        sendFontRendering(buffer, length, tokens);
+    }
     else if (tokens[0] == "status")
     {
         return getStatus(buffer, length);
@@ -548,6 +563,43 @@ std::string MasterProcessSession::getSaveAs()
     return _saveAsQueue.get();
 }
 
+void MasterProcessSession::sendFontRendering(const char *buffer, int length, StringTokenizer& tokens)
+{
+    std::string font;
+
+    if (tokens.count() < 2 ||
+        !getTokenString(tokens[1], "font", font))
+    {
+        sendTextFrame("error: cmd=renderfont kind=syntax");
+        return;
+    }
+
+    std::string response = "renderfont: " + Poco::cat(std::string(" "), tokens.begin() + 1, tokens.end()) + "\n";
+
+    std::vector<char> output;
+    output.resize(response.size());
+    std::memcpy(output.data(), response.data(), response.size());
+
+    std::unique_ptr<std::fstream> cachedRendering = _tileCache->lookupRendering(font, "font");
+    if (cachedRendering && cachedRendering->is_open())
+    {
+        cachedRendering->seekg(0, std::ios_base::end);
+        size_t pos = output.size();
+        std::streamsize size = cachedRendering->tellg();
+        output.resize(pos + size);
+        cachedRendering->seekg(0, std::ios_base::beg);
+        cachedRendering->read(output.data() + pos, size);
+        cachedRendering->close();
+
+        sendBinaryFrame(output.data(), output.size());
+        return;
+    }
+
+    if (_peer.expired())
+        dispatchChild();
+    forwardToPeer(buffer, length);
+}
+
 void MasterProcessSession::sendTile(const char *buffer, int length, StringTokenizer& tokens)
 {
     int part, width, height, tilePosX, tilePosY, tileWidth, tileHeight;
@@ -756,6 +808,10 @@ bool ChildProcessSession::handleInput(const char *buffer, int length)
         sendTextFrame("error: cmd=" + tokens[0] + " kind=nodocloaded");
         return false;
     }
+    else if (tokens[0] == "renderfont")
+    {
+        sendFontRendering(buffer, length, tokens);
+    }
     else if (tokens[0] == "setclientpart")
     {
         return setClientPart(buffer, length, tokens);
@@ -1037,6 +1093,44 @@ bool ChildProcessSession::loadDocument(const char *buffer, int length, StringTok
     return true;
 }
 
+void ChildProcessSession::sendFontRendering(const char* /*buffer*/, int /*length*/, StringTokenizer& tokens)
+{
+    std::string font, decodedFont;
+    int width, height;
+    unsigned char *pixmap;
+
+    if (tokens.count() < 2 ||
+        !getTokenString(tokens[1], "font", font))
+    {
+        sendTextFrame("error: cmd=renderfont kind=syntax");
+        return;
+    }
+
+    URI::decode(font, decodedFont);
+    std::string response = "renderfont: " + Poco::cat(std::string(" "), tokens.begin() + 1, tokens.end()) + "\n";
+
+    std::vector<char> output;
+    output.resize(response.size());
+    std::memcpy(output.data(), response.data(), response.size());
+
+    Poco::Timestamp timestamp;
+    pixmap = _loKitDocument->pClass->renderFont(_loKitDocument, decodedFont.c_str(), &width, &height);
+    std::cout << Util::logPrefix() << "renderFont called, font[" << font << "] rendered in " << double(timestamp.elapsed())/1000 <<  "ms" << std::endl;
+
+    if (pixmap != NULL) {
+        if (!Util::encodePNGAndAppendToBuffer(pixmap, width, height, output))
+        {
+            sendTextFrame("error: cmd=renderfont kind=failure");
+            delete[] pixmap;
+            return;
+        }
+    }
+
+    delete[] pixmap;
+
+    sendBinaryFrame(output.data(), output.size());
+}
+
 bool ChildProcessSession::getStatus(const char* /*buffer*/, int /*length*/)
 {
     std::string status = "status: " + LOKitHelper::documentStatus(_loKitDocument);
diff --git a/loolwsd/LOOLSession.hpp b/loolwsd/LOOLSession.hpp
index b807cab..3fe471a 100644
--- a/loolwsd/LOOLSession.hpp
+++ b/loolwsd/LOOLSession.hpp
@@ -71,6 +71,8 @@ protected:
 
     virtual void sendTile(const char *buffer, int length, Poco::StringTokenizer& tokens) = 0;
 
+    virtual void sendFontRendering(const char *buffer, int length, Poco::StringTokenizer& tokens) = 0;
+
     // Fields common to sessions in master and jailed processes:
 
     // In the master process, the websocket to the LOOL client or the jailed child process. In a
@@ -137,6 +139,8 @@ public:
 
     virtual void sendTile(const char *buffer, int length, Poco::StringTokenizer& tokens);
 
+    virtual void sendFontRendering(const char *buffer, int length, Poco::StringTokenizer& tokens);
+
     void dispatchChild();
     void forwardToPeer(const char *buffer, int length);
 
@@ -190,6 +194,8 @@ public:
 
     virtual void sendTile(const char *buffer, int length, Poco::StringTokenizer& tokens);
 
+    virtual void sendFontRendering(const char *buffer, int length, Poco::StringTokenizer& tokens);
+
     bool clientZoom(const char *buffer, int length, Poco::StringTokenizer& tokens);
     bool downloadAs(const char *buffer, int length, Poco::StringTokenizer& tokens);
     bool getChildId();
diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt
index 2f98f31..e9cce86 100644
--- a/loolwsd/protocol.txt
+++ b/loolwsd/protocol.txt
@@ -65,6 +65,11 @@ mouse type=<type> x=<x> y=<y> count=<count>
 
     <type> is 'buttondown', 'buttonup' or 'move', others are numbers.
 
+renderfont font=<font>
+
+    requests the rendering of the given font.
+    The font parameter is URL encoded
+
 requestloksession
 
     requests the initialization of a LOK process in an attempt to predict the user's
commit aa405d383691f72b748dbcea5390412497927c8f
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Fri Nov 27 16:12:44 2015 +0200

    loolwsd: cache rendered fonts

diff --git a/loolwsd/TileCache.cpp b/loolwsd/TileCache.cpp
index cbd0278..d978bd2 100644
--- a/loolwsd/TileCache.cpp
+++ b/loolwsd/TileCache.cpp
@@ -188,6 +188,35 @@ void TileCache::saveTextFile(const std::string& text, std::string fileName)
     textStream.close();
 }
 
+void TileCache::saveRendering(const std::string& name, const std::string& dir, const char *data, size_t size)
+{
+    // can fonts be invalidated?
+    std::string dirName = cacheDirName(false) + "/" + dir;
+
+    File(dirName).createDirectories();
+
+    std::string fileName = dirName + "/" + name;
+
+    std::fstream outStream(fileName, std::ios::out);
+    outStream.write(data, size);
+    outStream.close();
+}
+
+std::unique_ptr<std::fstream> TileCache::lookupRendering(const std::string& name, const std::string& dir)
+{
+    std::string dirName = cacheDirName(false) + "/" + dir;
+    std::string fileName = dirName + "/" + name;
+    File directory(dirName);
+
+    if (directory.exists() && directory.isDirectory() && File(fileName).exists())
+    {
+        std::unique_ptr<std::fstream> result(new std::fstream(fileName, std::ios::in));
+        return result;
+    }
+
+    return nullptr;
+}
+
 void TileCache::invalidateTiles(int part, int x, int y, int width, int height)
 {
     // in the Editing cache, remove immediately
diff --git a/loolwsd/TileCache.hpp b/loolwsd/TileCache.hpp
index 8294784..316f85f 100644
--- a/loolwsd/TileCache.hpp
+++ b/loolwsd/TileCache.hpp
@@ -51,6 +51,12 @@ public:
     // The parameter is a message
     void saveTextFile(const std::string& text, std::string fileName);
 
+    // Saves a font / style / etc rendering
+    // The dir parameter should be the type of rendering, like "font", "style", etc
+    void saveRendering(const std::string& name, const std::string& dir, const char *data, size_t size);
+
+    std::unique_ptr<std::fstream> lookupRendering(const std::string& name, const std::string& dir);
+
     // The tiles parameter is an invalidatetiles: message as sent by the child process
     void invalidateTiles(const std::string& tiles);
 
commit 46a726c22e68640bad8ea6dffc38fc8d0efd762e
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Mon Nov 23 20:08:04 2015 +0200

    loleaflet: tested and document .uno:SetHyperlink'

diff --git a/loleaflet/reference.html b/loleaflet/reference.html
index f8ad51f..9996b4c 100644
--- a/loleaflet/reference.html
+++ b/loleaflet/reference.html
@@ -8140,6 +8140,22 @@ var unoCommands = [
 },
 
 {
+    uno: '.uno:SetHyperlink',
+    parameter: {
+        'Hyperlink.Text': {
+            type: 'string',
+            value: 'some text'
+        },
+        'Hyperlink.URL': {
+            type: 'string',
+            value: 'url'
+        }
+    },
+    description: 'Creates a hyperlink. If Hyperlink.Text is not specified, the hyperlink will be set for the current ' +
+                     'selection. Hyperlink.URL can be a web URL or a bookmark from the document.'
+},
+
+{
     uno: '.uno:Shadowed',
     parameter: null,
     description: 'Shadowed.'
commit 4aafd56654e94ca660ec20d0b310e2c0a028537a
Author: Mihai Varga <mihai.varga at collabora.com>
Date:   Mon Nov 23 19:57:27 2015 +0200

    loleaflet: add a JSON parameter to sendUnoCommand()

diff --git a/loleaflet/src/control/Toolbar.js b/loleaflet/src/control/Toolbar.js
index 1644947..4ff4d17 100644
--- a/loleaflet/src/control/Toolbar.js
+++ b/loleaflet/src/control/Toolbar.js
@@ -77,9 +77,9 @@ L.Map.include({
 		}
 	},
 
-	sendUnoCommand: function (command) {
+	sendUnoCommand: function (command, json) {
 		if (this._docLayer._permission === 'edit') {
-			L.Socket.sendMessage('uno ' + command);
+			L.Socket.sendMessage('uno ' + command + (json ? ' ' + JSON.stringify(json) : ''));
 		}
 	},
 


More information about the Libreoffice-commits mailing list