summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2019-03-22 15:49:47 +0200
committerAndras Timar <andras.timar@collabora.com>2019-05-09 13:44:53 +0200
commitfce8094f0848ee2b52998d0a61af20449aab9fc9 (patch)
treed0a98357703e1ec2e80bf413dd465cb296136d33
parentfb162606ea6e518a48bb04738235a5953d894d7f (diff)
For iOS, generate the data: URLs for the PNG tiles already in the Online codecd-4.0.4-1
(What we cache is also the textual data: URLs even if we store them using .png file names.) This avoids the current back-and-forth-encoding: First we base64-encode the complete binary "tile:" message (one text line followed by a newline and the binary PNG) to pass to WebKit, then in the JavaScript snippet passed to WebKit we decode the base64 and turn it into an ArrayBuffer, and then we unpack the ArrayBuffer and encode the PNG part to use as a data: URL.
-rw-r--r--common/Png.hpp18
-rw-r--r--ios/Mobile/Document.mm92
-rw-r--r--loleaflet/src/core/Socket.js12
3 files changed, 59 insertions, 63 deletions
diff --git a/common/Png.hpp b/common/Png.hpp
index 84861fc48..0d40a37a0 100644
--- a/common/Png.hpp
+++ b/common/Png.hpp
@@ -52,6 +52,10 @@
#include <cassert>
#include <chrono>
+#ifdef IOS
+#include <Foundation/Foundation.h>
+#endif
+
#include "Log.hpp"
#include "SpookyV2.h"
@@ -134,6 +138,10 @@ bool encodeSubBufferToPNG(unsigned char* pixmap, size_t startX, size_t startY,
png_set_compression_level(png_ptr, Z_BEST_SPEED);
#endif
+#ifdef IOS
+ auto initialSize = output.size();
+#endif
+
png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_set_write_fn(png_ptr, &output, user_write_fn, user_flush_fn);
@@ -169,6 +177,16 @@ bool encodeSubBufferToPNG(unsigned char* pixmap, size_t startX, size_t startY,
png_destroy_write_struct(&png_ptr, &info_ptr);
+#ifdef IOS
+ auto base64 = [[NSData dataWithBytesNoCopy:output.data() + initialSize length:(output.size() - initialSize) freeWhenDone:NO] base64EncodedDataWithOptions:0];
+
+ const char dataURLStart[] = "data:image/png;base64,";
+
+ output.resize(initialSize);
+ output.insert(output.end(), dataURLStart, dataURLStart + sizeof(dataURLStart)-1);
+ output.insert(output.end(), (char*)base64.bytes, (char*)base64.bytes + base64.length);
+#endif
+
return true;
}
diff --git a/ios/Mobile/Document.mm b/ios/Mobile/Document.mm
index 8550bc3e8..5473ef081 100644
--- a/ios/Mobile/Document.mm
+++ b/ios/Mobile/Document.mm
@@ -84,69 +84,39 @@
NSString *js;
- // Check if the message is binary. We say that any message that isn't just a single line is
- // "binary" even if that strictly speaking isn't the case; for instance the commandvalues:
- // message has a long bunch of non-binary JSON on multiple lines. But _onMessage() in Socket.js
- // handles it fine even if such a message, too, comes in as an ArrayBuffer. (Look for the
- // "textMsg = String.fromCharCode.apply(null, imgBytes);".)
-
- const char *newline = (const char *)memchr(buffer, '\n', length);
- if (newline != nullptr) {
- // The data needs to be an ArrayBuffer
- js = @"window.TheFakeWebSocket.onmessage({'data': Base64ToArrayBuffer('";
- js = [js stringByAppendingString: [[NSData dataWithBytes:buffer length:length] base64EncodedStringWithOptions:0]];
- js = [js stringByAppendingString:@"')});"];
- NSString *subjs = [js substringToIndex:std::min(100ul, js.length)];
- if (subjs.length < js.length)
- subjs = [subjs stringByAppendingString:@"..."];
-
- // LOG_TRC("Evaluating JavaScript: " << [subjs UTF8String]);
-
- dispatch_async(dispatch_get_main_queue(), ^{
- [self.viewController.webView evaluateJavaScript:js
- completionHandler:^(id _Nullable obj, NSError * _Nullable error)
- {
- if (error) {
- LOG_ERR("Error after " << [subjs UTF8String] << ": " << [error.localizedDescription UTF8String]);
- }
- }
- ];
- });
- } else {
- const unsigned char *ubufp = (const unsigned char *)buffer;
- std::vector<char> data;
- for (int i = 0; i < length; i++) {
- if (ubufp[i] < ' ' || ubufp[i] == '\'' || ubufp[i] == '\\') {
- data.push_back('\\');
- data.push_back('x');
- data.push_back("0123456789abcdef"[(ubufp[i] >> 4) & 0x0F]);
- data.push_back("0123456789abcdef"[ubufp[i] & 0x0F]);
- } else {
- data.push_back(ubufp[i]);
- }
+ const unsigned char *ubufp = (const unsigned char *)buffer;
+ std::vector<char> data;
+ for (int i = 0; i < length; i++) {
+ if (ubufp[i] < ' ' || ubufp[i] == '\'' || ubufp[i] == '\\') {
+ data.push_back('\\');
+ data.push_back('x');
+ data.push_back("0123456789abcdef"[(ubufp[i] >> 4) & 0x0F]);
+ data.push_back("0123456789abcdef"[ubufp[i] & 0x0F]);
+ } else {
+ data.push_back(ubufp[i]);
}
- data.push_back(0);
-
- js = @"window.TheFakeWebSocket.onmessage({'data': '";
- js = [js stringByAppendingString:[NSString stringWithUTF8String:data.data()]];
- js = [js stringByAppendingString:@"'});"];
-
- // LOG_TRC("Evaluating JavaScript: " << [js UTF8String]);
-
- dispatch_async(dispatch_get_main_queue(), ^{
- [self.viewController.webView evaluateJavaScript:js
- completionHandler:^(id _Nullable obj, NSError * _Nullable error)
- {
- if (error) {
- LOG_ERR("Error after " << [js UTF8String] << ": " << [[error localizedDescription] UTF8String]);
- NSString *jsException = error.userInfo[@"WKJavaScriptExceptionMessage"];
- if (jsException != nil)
- LOG_ERR("JavaScript exception: " << [jsException UTF8String]);
- }
- }
- ];
- });
}
+ data.push_back(0);
+
+ js = @"window.TheFakeWebSocket.onmessage({'data': '";
+ js = [js stringByAppendingString:[NSString stringWithUTF8String:data.data()]];
+ js = [js stringByAppendingString:@"'});"];
+
+ // LOG_TRC("Evaluating JavaScript: " << [js UTF8String]);
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self.viewController.webView evaluateJavaScript:js
+ completionHandler:^(id _Nullable obj, NSError * _Nullable error)
+ {
+ if (error) {
+ LOG_ERR("Error after " << [js UTF8String] << ": " << [[error localizedDescription] UTF8String]);
+ NSString *jsException = error.userInfo[@"WKJavaScriptExceptionMessage"];
+ if (jsException != nil)
+ LOG_ERR("JavaScript exception: " << [jsException UTF8String]);
+ }
+ }
+ ];
+ });
}
@end
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index f7dc49dda..78d8a00d7 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -239,7 +239,7 @@ L.Socket = L.Class.extend({
},
_onMessage: function (e) {
- var imgBytes, index, textMsg;
+ var imgBytes, index, textMsg, img;
if (typeof (e.data) === 'string') {
textMsg = e.data;
@@ -749,13 +749,21 @@ L.Socket = L.Class.extend({
textMsg = decodeURIComponent(window.escape(textMsg));
}
}
+ else if (window.ThisIsTheiOSApp) {
+ // In the iOS app, the native code sends us the PNG tile already as a data: URL after the newline
+ var newlineIndex = textMsg.indexOf('\n');
+ if (newlineIndex > 0) {
+ img = textMsg.substring(newlineIndex+1);
+ textMsg = textMsg.substring(0, newlineIndex);
+ }
+ }
else {
var data = imgBytes.subarray(index + 1);
if (data.length > 0 && data[0] == 68 /* D */)
{
console.log('Socket: got a delta !');
- var img = data;
+ img = data;
}
else
{