Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ tasks.register('conanProfile', Copy) {
["armv8", "armv7", "x86", "x86_64"].each { architecture ->
tasks.named("conanInstall-" + architecture) {
profile.set('build/conanprofile.txt')
deployer.set('conandeployer.py')
deployerFolder.set(outputDirectory.get().asFile.toString() + "/assets")
conanExecutable.set('/Users/andreas/odr/venv/bin/conan')
dependsOn(tasks.named('conanProfile'))
}
}
Expand Down Expand Up @@ -121,6 +124,11 @@ android {
}
}
namespace 'at.tomtasche.reader'
compileSdk 35
buildToolsVersion '34.0.0'

// TODO can and should this be architecture dependent?
sourceSets.main.assets.srcDirs += "build/conan/armv8/assets"
Comment thread
andiwand marked this conversation as resolved.
}

dependencies {
Expand Down
50 changes: 50 additions & 0 deletions app/conandeployer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import shutil


def deploy(graph, output_folder: str, **kwargs):
conanfile = graph.root.conanfile
conanfile.output.info(f"Custom deployer to {output_folder}")

symlinks = conanfile.conf.get("tools.deployer:symlinks", check_type=bool, default=True)
arch = conanfile.settings.get_safe("arch")

conanfile.output.info(f"Symlinks: {symlinks}")
conanfile.output.info(f"Arch: {arch}")

deps = {dep.ref.name: dep for dep in conanfile.dependencies.values()}

print(f"Dependencies: {list(deps.keys())}")

if "odrcore" in deps:
dep = deps["odrcore"]
conanfile.output.info(f"Deploying odrcore to {output_folder}")
# nothing to deploy so far

copytree_kwargs = {"symlinks": symlinks, "dirs_exist_ok": True}

if "pdf2htmlex" in deps:
dep = deps["pdf2htmlex"]
conanfile.output.info(f"Deploying pdf2htmlex to {output_folder}")
shutil.copytree(
f"{dep.package_folder}/share/pdf2htmlex",
f"{output_folder}/pdf2htmlex",
**copytree_kwargs,
)

if "poppler-data" in deps:
dep = deps["poppler-data"]
conanfile.output.info(f"Deploying poppler-data to {output_folder}")
shutil.copytree(
f"{dep.package_folder}/share/poppler",
f"{output_folder}/poppler",
**copytree_kwargs,
)

if "fontconfig" in deps:
dep = deps["fontconfig"]
conanfile.output.info(f"Deploying fontconfig to {output_folder}")
shutil.copytree(
f"{dep.package_folder}/res/share",
f"{output_folder}/fontconfig",
**copytree_kwargs,
)
2 changes: 1 addition & 1 deletion app/conanfile.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[requires]
odrcore/4.1.1@
odrcore/9.9.9@
Comment thread
andiwand marked this conversation as resolved.
Outdated

[generators]
CMakeToolchain
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ private static void copy(InputStream src, File dst) throws IOException {
@Test
public void test() {
CoreWrapper core = new CoreWrapper();
core.initialize();

File cacheDir = InstrumentationRegistry.getInstrumentation().getTargetContext().getCacheDir();
File htmlFile = new File(cacheDir, "html");
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
android:label="@string/app_title"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/MainTheme"
android:networkSecurityConfig="@xml/network_security_config"
Comment thread
andiwand marked this conversation as resolved.
tools:replace="android:label">

<!-- https://stackoverflow.com/a/78086604/198996 -->
Expand Down
80 changes: 68 additions & 12 deletions app/src/main/cpp/CoreWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@
#include <odr/html.hpp>
#include <odr/open_document_reader.hpp>
#include <odr/exceptions.hpp>
#include <odr/http_server.hpp>

#include <android/log.h>

#include <string>
#include <optional>
#include <filesystem>

std::optional<odr::Html> html;
std::optional<odr::Html> s_html;

JNIEXPORT jobject JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_parseNative(JNIEnv *env, jobject instance,
Java_at_tomtasche_reader_background_CoreWrapper_parseNative(JNIEnv *env, jclass clazz,
jobject options) {
jboolean isCopy;

Expand Down Expand Up @@ -119,7 +121,7 @@ Java_at_tomtasche_reader_background_CoreWrapper_parseNative(JNIEnv *env, jobject
config.text_document_margin = true;
}

html = odr::OpenDocumentReader::html(inputPathCpp, [&passwordCpp]() -> std::string {
s_html = odr::OpenDocumentReader::html(inputPathCpp, [&passwordCpp]() -> std::string {
if (passwordCpp.has_value()) {
return passwordCpp.value();
}
Expand All @@ -128,7 +130,7 @@ Java_at_tomtasche_reader_background_CoreWrapper_parseNative(JNIEnv *env, jobject

{
const auto extensionCpp = odr::OpenDocumentReader::type_to_string(
html->file_type());
s_html->file_type());
const auto extensionC = extensionCpp.c_str();
jstring extension = env->NewStringUTF(extensionC);

Expand All @@ -137,7 +139,7 @@ Java_at_tomtasche_reader_background_CoreWrapper_parseNative(JNIEnv *env, jobject
env->SetObjectField(result, extensionField, extension);
}

for (auto &&page: html->pages()) {
for (auto &&page: s_html->pages()) {
jstring pageName = env->NewStringUTF(page.name.c_str());
env->CallBooleanMethod(pageNames, addMethod, pageName);

Expand Down Expand Up @@ -167,7 +169,7 @@ Java_at_tomtasche_reader_background_CoreWrapper_parseNative(JNIEnv *env, jobject
}

JNIEXPORT jobject JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_backtranslateNative(JNIEnv *env, jobject instance,
Java_at_tomtasche_reader_background_CoreWrapper_backtranslateNative(JNIEnv *env, jclass clazz,
jobject options,
jstring htmlDiff) {
jboolean isCopy;
Expand All @@ -192,7 +194,7 @@ Java_at_tomtasche_reader_background_CoreWrapper_backtranslateNative(JNIEnv *env,

const auto htmlDiffC = env->GetStringUTFChars(htmlDiff, &isCopy);

const auto extension = odr::OpenDocumentReader::type_to_string(html->file_type());
const auto extension = odr::OpenDocumentReader::type_to_string(s_html->file_type());
const auto outputPathCpp = outputPathPrefixCpp + "." + extension;
const char *outputPathC = outputPathCpp.c_str();
jstring outputPath = env->NewStringUTF(outputPathC);
Expand All @@ -201,7 +203,7 @@ Java_at_tomtasche_reader_background_CoreWrapper_backtranslateNative(JNIEnv *env,
env->SetObjectField(result, outputPathField, outputPath);

try {
html->edit(htmlDiffC);
s_html->edit(htmlDiffC);

env->ReleaseStringUTFChars(htmlDiff, htmlDiffC);
} catch (...) {
Expand All @@ -212,7 +214,7 @@ Java_at_tomtasche_reader_background_CoreWrapper_backtranslateNative(JNIEnv *env,
}

try {
html->save(outputPathCpp);
s_html->save(outputPathCpp);
} catch (...) {
env->SetIntField(result, errorField, -7);
return result;
Expand All @@ -227,7 +229,61 @@ Java_at_tomtasche_reader_background_CoreWrapper_backtranslateNative(JNIEnv *env,
}

JNIEXPORT void JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_closeNative(JNIEnv *env, jobject instance,
Java_at_tomtasche_reader_background_CoreWrapper_closeNative(JNIEnv *env, jclass clazz,
jobject options) {
html.reset();
}
s_html.reset();
}

std::optional<odr::HttpServer> s_server;

JNIEXPORT void JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_createServerNative(JNIEnv *env, jclass clazz, jstring outputPath) {
const char* outputPathC = env->GetStringUTFChars(outputPath, nullptr);
std::string output_path = outputPathC;
env->ReleaseStringUTFChars(outputPath, outputPathC);

std::filesystem::create_directories(output_path);

odr::HttpServer::Config config;
config.output_path = output_path;
s_server = odr::HttpServer(config);
}

JNIEXPORT jstring JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_hostFileNative(JNIEnv *env, jclass clazz, jobject options) {
jboolean isCopy;

jclass optionsClass = env->GetObjectClass(options);
jfieldID inputPathField = env->GetFieldID(optionsClass, "inputPath", "Ljava/lang/String;");
auto inputPath = (jstring) env->GetObjectField(options, inputPathField);

const auto inputPathC = env->GetStringUTFChars(inputPath, &isCopy);
auto inputPathCpp = std::string(inputPathC, env->GetStringUTFLength(inputPath));
env->ReleaseStringUTFChars(inputPath, inputPathC);

odr::DecodePreference decodePreference;
decodePreference.engine_priority = {
odr::DecoderEngine::poppler, odr::DecoderEngine::wvware, odr::DecoderEngine::odr};
odr::DecodedFile file = odr::OpenDocumentReader::open(inputPathCpp, decodePreference);

__android_log_print(ANDROID_LOG_INFO, "smn", "file type %i", file.file_type());

try {
std::string id = s_server->host_file(file);
return env->NewStringUTF(id.c_str());
} catch (...) {
__android_log_print(ANDROID_LOG_ERROR, "smn", "error");
return env->NewStringUTF("error");
}
}

JNIEXPORT void JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_listenServerNative(JNIEnv *env, jclass clazz) {
s_server->listen("127.0.0.1", 29665);
Comment thread
andiwand marked this conversation as resolved.
Outdated
}

JNIEXPORT void JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_stopServerNative(JNIEnv *env, jclass clazz) {
s_server->stop();
s_server.reset();
}
18 changes: 15 additions & 3 deletions app/src/main/cpp/CoreWrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,25 @@
extern "C" {

JNIEXPORT jobject JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_parseNative(JNIEnv *env, jobject instance, jobject options);
Java_at_tomtasche_reader_background_CoreWrapper_parseNative(JNIEnv *env, jclass clazz, jobject options);

JNIEXPORT jobject JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_backtranslateNative(JNIEnv *env, jobject instance, jobject options, jstring htmlDiff);
Java_at_tomtasche_reader_background_CoreWrapper_backtranslateNative(JNIEnv *env, jclass clazz, jobject options, jstring htmlDiff);

JNIEXPORT void JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_closeNative(JNIEnv *env, jobject instance, jobject options);
Java_at_tomtasche_reader_background_CoreWrapper_closeNative(JNIEnv *env, jclass clazz, jobject options);

JNIEXPORT void JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_createServerNative(JNIEnv *env, jclass clazz, jstring outputPath);

JNIEXPORT jstring JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_hostFileNative(JNIEnv *env, jclass clazz, jobject options);

JNIEXPORT void JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_listenServerNative(JNIEnv *env, jclass clazz);

JNIEXPORT void JNICALL
Java_at_tomtasche_reader_background_CoreWrapper_stopServerNative(JNIEnv *env, jclass clazz);
}

#endif //ANDROID_CORE_WRAPPER_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package at.tomtasche.reader.background;

import android.content.Context;
import android.net.Uri;

import java.io.File;

import at.tomtasche.reader.nonfree.ConfigManager;

public class CoreHttpLoader extends FileLoader {

private final ConfigManager configManager;

private CoreWrapper lastCore;

public CoreHttpLoader(Context context, ConfigManager configManager) {
super(context, LoaderType.ODF);

this.configManager = configManager;
}

@Override
public boolean isSupported(Options options) {
return options.fileType.startsWith("application/vnd.oasis.opendocument") || options.fileType.startsWith("application/x-vnd.oasis.opendocument") || options.fileType.startsWith("application/vnd.oasis.opendocument.text-master");
}

@Override
public void loadSync(Options options) {
final Result result = new Result();
result.options = options;
result.loaderType = type;

try {
translate(options, result);

callOnSuccess(result);
} catch (Throwable e) {
if (e instanceof CoreWrapper.CoreEncryptedException) {
e = new EncryptedDocumentException();
}

callOnError(result, e);
}
}

private void translate(Options options, Result result) throws Exception {
File cachedFile = AndroidFileCache.getCacheFile(context, options.cacheUri);

if (lastCore != null) {
CoreWrapper.close();
lastCore = null;
}

CoreWrapper core = new CoreWrapper();
try {
lastCore = core;
} catch (Throwable e) {
crashManager.log(e);
}

File cacheDirectory = AndroidFileCache.getCacheDirectory(cachedFile);

CoreWrapper.CoreOptions coreOptions = new CoreWrapper.CoreOptions();
coreOptions.inputPath = cachedFile.getPath();
coreOptions.outputPath = cacheDirectory.getPath();
coreOptions.password = options.password;
coreOptions.editable = options.translatable;
coreOptions.ooxml = false;

Boolean usePaging = configManager.getBooleanConfig("use_paging");
if (usePaging == null || usePaging) {
coreOptions.paging = true;
}

String id = CoreWrapper.hostFile(coreOptions);

result.partTitles.add("document");
result.partUris.add(Uri.parse("http://localhost:29665/" + id + "/document.html"));
Comment thread
andiwand marked this conversation as resolved.
Outdated
}

@Override
public File retranslate(Options options, String htmlDiff) {
return null;
}

@Override
public void close() {
super.close();

if (lastCore != null) {
CoreWrapper.close();
lastCore = null;
}
}
}
Loading