[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