Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/koreader-wtf8-and-zip-fixes'
Browse files Browse the repository at this point in the history
  • Loading branch information
plotn committed Dec 29, 2019
2 parents aa48a1c + 65719ea commit e6f64dd
Show file tree
Hide file tree
Showing 81 changed files with 2,315 additions and 1,534 deletions.
5 changes: 5 additions & 0 deletions android/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO})
set(CRENGINE_SRC_FILES
${CR3_ROOT}/crengine/src/cp_stats.cpp
${CR3_ROOT}/crengine/src/lvstring.cpp
${CR3_ROOT}/crengine/src/lvstring8collection.cpp
${CR3_ROOT}/crengine/src/lvstring16collection.cpp
${CR3_ROOT}/crengine/src/lvstring16hashedcollection.cpp
${CR3_ROOT}/crengine/src/crlog.cpp
${CR3_ROOT}/crengine/src/serialbuf.cpp
${CR3_ROOT}/crengine/src/props.cpp
${CR3_ROOT}/crengine/src/lstridmap.cpp
${CR3_ROOT}/crengine/src/rtfimp.cpp
Expand Down
5 changes: 5 additions & 0 deletions android/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ LOCAL_CFLAGS += -g -O1 -fexceptions -flto
CRENGINE_SRC_FILES := \
../../crengine/src/cp_stats.cpp \
../../crengine/src/lvstring.cpp \
../../crengine/src/lvstring8collection.cpp \
../../crengine/src/lvstring16collection.cpp \
../../crengine/src/lvstring16hashedcollection.cpp \
../../crengine/src/crlog.cpp \
../../crengine/src/serialbuf.cpp \
../../crengine/src/props.cpp \
../../crengine/src/lstridmap.cpp \
../../crengine/src/rtfimp.cpp \
Expand Down
61 changes: 56 additions & 5 deletions android/jni/cr3engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,9 @@ void cr3androidFatalErrorHandler(int errorCode, const char * errorText )
/// set fatal error handler
void crSetFatalErrorHandler( lv_FatalErrorHandler_t * handler );

jboolean initInternal(JNIEnv * penv, jclass obj, jobjectArray fontArray) {
jboolean initInternal(JNIEnv * penv, jclass obj, jobjectArray fontArray, jint sdk_int) {

CRJNIEnv::sdk_int = sdk_int;

CRJNIEnv env(penv);

Expand Down Expand Up @@ -686,13 +688,13 @@ jboolean initInternal(JNIEnv * penv, jclass obj, jobjectArray fontArray) {
/*
* Class: org_coolreader_crengine_Engine
* Method: initInternal
* Signature: ([Ljava/lang/String;)Z
* Signature: ([Ljava/lang/String;I)Z
*/
JNIEXPORT jboolean JNICALL Java_org_coolreader_crengine_Engine_initInternal
(JNIEnv * penv, jclass obj, jobjectArray fontArray)
(JNIEnv * penv, jclass obj, jobjectArray fontArray, jint sdk_int)
{
jboolean res = JNI_FALSE;
COFFEE_TRY_JNI(penv, res = initInternal(penv, obj, fontArray));
COFFEE_TRY_JNI(penv, res = initInternal(penv, obj, fontArray, sdk_int));
return res;
}

Expand Down Expand Up @@ -817,6 +819,52 @@ JNIEXPORT jboolean JNICALL Java_org_coolreader_crengine_Engine_checkFontLanguage
return res;
}

/*
* Class: org_coolreader_crengine_Engine
* Method: listFilesInternal
* Signature: (Ljava/io/File;)[Ljava/io/File;
*/
JNIEXPORT jobjectArray JNICALL Java_org_coolreader_crengine_Engine_listFilesInternal
(JNIEnv *env, jclass, jobject jdir)
{
if (NULL == jdir)
return NULL;
jclass pjcFile = env->FindClass("java/io/File");
if (NULL == pjcFile)
return NULL;
jmethodID pjmFile_GetAbsolutePath = env->GetMethodID(pjcFile, "getAbsolutePath", "()Ljava/lang/String;");
if (NULL == pjmFile_GetAbsolutePath)
return NULL;
jmethodID pjmFile_Ctor = env->GetMethodID(pjcFile, "<init>", "(Ljava/lang/String;)V");
if (NULL == pjmFile_Ctor)
return NULL;
jstring jpathname = (jstring)env->CallObjectMethod(jdir, pjmFile_GetAbsolutePath);
jboolean iscopy;
const char * s = env->GetStringUTFChars(jpathname, &iscopy);
lString16 path = (CRJNIEnv::sdk_int >= ANDROID_SDK_M) ? Utf8ToUnicode(s) : Wtf8ToUnicode(s);
env->ReleaseStringUTFChars(jpathname, s);
jobjectArray jarray = NULL;
LVContainerRef dir = LVOpenDirectory(path);
if ( !dir.isNull() ) {
jstring emptyString = env->NewStringUTF("");
jobject emptyFile = env->NewObject(pjcFile, pjmFile_Ctor, emptyString);
jarray = env->NewObjectArray(dir->GetObjectCount(), pjcFile, emptyFile);
if (NULL != jarray) {
for (int i = 0; i < dir->GetObjectCount(); i++) {
const LVContainerItemInfo *item = dir->GetObjectInfo(i);
lString16 fileName = path + "/" + item->GetName();
jstring jfilename = env->NewStringUTF(
(CRJNIEnv::sdk_int >= ANDROID_SDK_M) ? UnicodeToUtf8(fileName).c_str()
: UnicodeToWtf8(fileName).c_str());
jobject jfile = env->NewObject(pjcFile, pjmFile_Ctor, jfilename);
if (NULL != jfile)
env->SetObjectArrayElement(jarray, i, jfile);
}
}
}
return jarray;
}

/*
* Class: org_coolreader_crengine_Engine
* Method: isLink
Expand Down Expand Up @@ -885,7 +933,7 @@ JNIEXPORT jboolean JNICALL Java_org_coolreader_crengine_Engine_setKeyBacklightIn

static JNINativeMethod sEngineMethods[] = {
/* name, signature, funcPtr */
{"initInternal", "([Ljava/lang/String;)Z", (void*)Java_org_coolreader_crengine_Engine_initInternal},
{"initInternal", "([Ljava/lang/String;I)Z", (void*)Java_org_coolreader_crengine_Engine_initInternal},
{"uninitInternal", "()V", (void*)Java_org_coolreader_crengine_Engine_uninitInternal},
{"getFontFaceListInternal", "()[Ljava/lang/String;", (void*)Java_org_coolreader_crengine_Engine_getFontFaceListInternal},
{"getFontFaceAndFileNameListInternal", "()[Ljava/lang/String;", (void*)Java_org_coolreader_crengine_Engine_getFontFaceAndFileNameListInternal},
Expand All @@ -898,6 +946,9 @@ static JNINativeMethod sEngineMethods[] = {
{"setKeyBacklightInternal", "(I)Z", (void*)Java_org_coolreader_crengine_Engine_setKeyBacklightInternal},
{"scanBookCoverInternal", "(Ljava/lang/String;)[B", (void*)Java_org_coolreader_crengine_Engine_scanBookCoverInternal},
{"drawBookCoverInternal", "(Landroid/graphics/Bitmap;[BLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II)V", (void*)Java_org_coolreader_crengine_Engine_drawBookCoverInternal},
{"haveFcLangCodeInternal", "(Ljava/lang/String;)Z", (void*)Java_org_coolreader_crengine_Engine_haveFcLangCodeInternal},
{"checkFontLanguageCompatibilityInternal", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*)Java_org_coolreader_crengine_Engine_checkFontLanguageCompatibilityInternal},
{"listFilesInternal", "(Ljava/io/File;)[Ljava/io/File;", (void*)Java_org_coolreader_crengine_Engine_listFilesInternal}
};


Expand Down
17 changes: 15 additions & 2 deletions android/jni/cr3java.cpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
#include "cr3java.h"
#include "../../crengine/include/crlog.h"

#include <dlfcn.h>

uint8_t CRJNIEnv::sdk_int = 0;

lString16 CRJNIEnv::fromJavaString( jstring str )
{
if (!str)
return lString16::empty_str;
jboolean iscopy;
const char * s = env->GetStringUTFChars(str, &iscopy);
lString16 res(s);
lString16 res;
if (CRJNIEnv::sdk_int >= ANDROID_SDK_M)
res = Utf8ToUnicode(s);
else
res = Wtf8ToUnicode(s);
env->ReleaseStringUTFChars(str, s);
return res;
}

jstring CRJNIEnv::toJavaString( const lString16 & str )
{
return env->NewStringUTF(UnicodeToUtf8(str).c_str());
if (CRJNIEnv::sdk_int >= ANDROID_SDK_M)
return env->NewStringUTF(UnicodeToUtf8(str).c_str());
// To support 4-byte UTF-8 sequence on Android older that 6.0 (API 23),
// we encode characters with codes >= 0x10000 to WTF-8.
// Otherwise, we have crash with following message:
// "input is not valid Modified UTF-8: illegal start byte 0xf0"
return env->NewStringUTF(UnicodeToWtf8(str).c_str());
}

void CRJNIEnv::fromJavaStringArray( jobjectArray array, lString16Collection & dst )
Expand Down
4 changes: 4 additions & 0 deletions android/jni/cr3java.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#include "../../crengine/include/props.h"
#include "../../crengine/include/lvtinydom.h"

// M is for Marshmallow!
#define ANDROID_SDK_M 23

//====================================================================
// libjnigraphics replacement for pre-2.2 SDKs
enum AndroidBitmapFormat {
Expand Down Expand Up @@ -58,6 +61,7 @@ class BitmapAccessorInterface {
class CRJNIEnv {
public:
JNIEnv * env;
static uint8_t sdk_int;
CRJNIEnv(JNIEnv * pEnv) : env(pEnv) { }
JNIEnv * operator -> () { return env; }
lString16 fromJavaString( jstring str );
Expand Down
2 changes: 1 addition & 1 deletion android/jni/gen_jni_studio
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/sh

sdk="/opt/android-sdk-update-manager"
binclass_path=../app/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes
binclass_path=../app/build/intermediates/javac/debug/classes

export CLASSPATH="${CLASSPATH}:${sdk}/platforms/android-17/*:${binclass_path}"

Expand Down
14 changes: 11 additions & 3 deletions android/jni/org_coolreader_crengine_Engine.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions android/src/org/coolreader/crengine/Engine.java
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ public void initAgain() {
}
mFonts = findFonts();
findExternalHyphDictionaries();
if (!initInternal(mFonts)) {
if (!initInternal(mFonts, DeviceInfo.getSDKLevel())) {
log.i("Engine.initInternal failed!");
throw new RuntimeException("Cannot initialize CREngine JNI");
}
Expand All @@ -601,7 +601,7 @@ public void initAgain() {
}

// Native functions
private native static boolean initInternal(String[] fontList);
private native static boolean initInternal(String[] fontList, int sdk_int);

private native static void uninitInternal();

Expand Down Expand Up @@ -644,6 +644,8 @@ public void initAgain() {
*/
private native static boolean checkFontLanguageCompatibilityInternal(String fontFace, String langCode);

private native static File[] listFilesInternal(File dir);

public static void suspendLongOperation() {
suspendLongOperationInternal();
}
Expand All @@ -652,6 +654,10 @@ public synchronized static boolean checkFontLanguageCompatibility(String fontFac
return checkFontLanguageCompatibilityInternal(fontFace, langCode);
}

public static synchronized File[] listFiles(File dir) {
return listFilesInternal(dir);
}

/**
* Finds the corresponding language code in embedded FontConfig language orthography catalog.
*
Expand Down Expand Up @@ -2136,7 +2142,7 @@ public MountPathCorrector getPathCorrector() {
}
mFonts = findFonts();
findExternalHyphDictionaries();
if (!initInternal(mFonts)) {
if (!initInternal(mFonts, DeviceInfo.getSDKLevel())) {
log.i("Engine.initInternal failed!");
throw new RuntimeException("Cannot initialize CREngine JNI");
}
Expand Down
10 changes: 9 additions & 1 deletion android/src/org/coolreader/crengine/Scanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,15 @@ public boolean listDirectory(FileInfo baseDir)
}
try {
File dir = new File(baseDir.pathname);
File[] items = dir.listFiles();
//File[] items = dir.listFiles();
// To resolve unhandled exception
// 'JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal continuation byte 0'
// that can be produced by invalid filename (broken sdcard, etc)
// or 'JNI WARNING: input is not valid Modified UTF-8: illegal start byte 0xf0'
// that can be generated if 4-byte UTF-8 sequence found in the filename,
// we implement own directory listing method instead of File.listFiles().
// TODO: replace other occurrences of the method File.listFiles().
File[] items = Engine.listFiles(dir);
// process normal files
if ( items!=null ) {
for ( File f : items ) {
Expand Down
Loading

0 comments on commit e6f64dd

Please sign in to comment.