diff --git a/jni/NativeFormats/util/AndroidUtil.cpp b/jni/NativeFormats/util/AndroidUtil.cpp index 16d339970..e09d5234c 100644 --- a/jni/NativeFormats/util/AndroidUtil.cpp +++ b/jni/NativeFormats/util/AndroidUtil.cpp @@ -29,6 +29,7 @@ const char * const AndroidUtil::Class_java_io_PrintStream = "java/io/PrintStream const char * const AndroidUtil::Class_ZLibrary = "org/geometerplus/zlibrary/core/library/ZLibrary"; const char * const AndroidUtil::Class_NativeFormatPlugin = "org/geometerplus/fbreader/formats/NativeFormatPlugin"; const char * const AndroidUtil::Class_PluginCollection = "org/geometerplus/fbreader/formats/PluginCollection"; +const char * const AndroidUtil::Class_JavaEncodingCollection = "org/geometerplus/fbreader/formats/JavaEncodingCollection"; const char * const AndroidUtil::Class_Paths = "org/geometerplus/fbreader/Paths"; const char * const AndroidUtil::Class_ZLFile = "org/geometerplus/zlibrary/core/filesystem/ZLFile"; const char * const AndroidUtil::Class_Book = "org/geometerplus/fbreader/library/Book"; @@ -57,6 +58,11 @@ jmethodID AndroidUtil::MID_NativeFormatPlugin_supportedFileType; jmethodID AndroidUtil::SMID_PluginCollection_Instance; +jmethodID AndroidUtil::SMID_JavaEncodingCollection_Instance; +jmethodID AndroidUtil::MID_JavaEncodingCollection_getEncoding_int; +jmethodID AndroidUtil::MID_JavaEncodingCollection_getEncoding_String; +jmethodID AndroidUtil::MID_JavaEncodingCollection_isEncodingSupported; + jmethodID AndroidUtil::SMID_ZLFile_createFileByPath; jmethodID AndroidUtil::MID_ZLFile_children; jmethodID AndroidUtil::MID_ZLFile_exists; @@ -142,6 +148,13 @@ bool AndroidUtil::init(JavaVM* jvm) { CHECK_NULL( SMID_PluginCollection_Instance = env->GetStaticMethodID(cls, "Instance", "()Lorg/geometerplus/fbreader/formats/PluginCollection;") ); env->DeleteLocalRef(cls); + CHECK_NULL( cls = env->FindClass(Class_JavaEncodingCollection) ); + CHECK_NULL( SMID_JavaEncodingCollection_Instance = env->GetStaticMethodID(cls, "Instance", "()Lorg/geometerplus/fbreader/formats/JavaEncodingCollection;") ); + CHECK_NULL( MID_JavaEncodingCollection_getEncoding_String = env->GetMethodID(cls, "getEncoding", "(Ljava/lang/String;)Lorg/geometerplus/fbreader/formats/Encoding;") ); + CHECK_NULL( MID_JavaEncodingCollection_getEncoding_int = env->GetMethodID(cls, "getEncoding", "(I)Lorg/geometerplus/fbreader/formats/Encoding;") ); + CHECK_NULL( MID_JavaEncodingCollection_isEncodingSupported = env->GetMethodID(cls, "isEncodingSupported", "()Z") ); + env->DeleteLocalRef(cls); + CHECK_NULL( cls = env->FindClass(Class_ZLFile) ); CHECK_NULL( SMID_ZLFile_createFileByPath = env->GetStaticMethodID(cls, "createFileByPath", "(Ljava/lang/String;)Lorg/geometerplus/zlibrary/core/filesystem/ZLFile;") ); CHECK_NULL( MID_ZLFile_children = env->GetMethodID(cls, "children", "()Ljava/util/List;") ); diff --git a/jni/NativeFormats/util/AndroidUtil.h b/jni/NativeFormats/util/AndroidUtil.h index 75f871c9d..7336802ce 100644 --- a/jni/NativeFormats/util/AndroidUtil.h +++ b/jni/NativeFormats/util/AndroidUtil.h @@ -40,6 +40,7 @@ public: static const char * const Class_ZLFile; static const char * const Class_NativeFormatPlugin; static const char * const Class_PluginCollection; + static const char * const Class_JavaEncodingCollection; static const char * const Class_Paths; static const char * const Class_Book; static const char * const Class_Tag; @@ -75,6 +76,11 @@ public: static jmethodID SMID_PluginCollection_Instance; + static jmethodID SMID_JavaEncodingCollection_Instance; + static jmethodID MID_JavaEncodingCollection_getEncoding_String; + static jmethodID MID_JavaEncodingCollection_getEncoding_int; + static jmethodID MID_JavaEncodingCollection_isEncodingSupported; + static jmethodID SMID_Paths_cacheDirectory; static jfieldID FID_Book_File; diff --git a/jni/NativeFormats/zlibrary/core/src/encoding/JavaEncodingConverter.cpp b/jni/NativeFormats/zlibrary/core/src/encoding/JavaEncodingConverter.cpp index 4677a23a5..e599efca8 100644 --- a/jni/NativeFormats/zlibrary/core/src/encoding/JavaEncodingConverter.cpp +++ b/jni/NativeFormats/zlibrary/core/src/encoding/JavaEncodingConverter.cpp @@ -17,6 +17,7 @@ * 02110-1301, USA. */ +#include #include #include "JavaEncodingConverter.h" @@ -32,12 +33,20 @@ public: void reset(); bool fillTable(int *map); +private: + jobject myJavaConverter; + friend class JavaEncodingConverterProvider; }; bool JavaEncodingConverterProvider::providesConverter(const std::string &encoding) { - // TODO: implement - return false; + JNIEnv *env = AndroidUtil::getEnv(); + jclass cls = env->FindClass(AndroidUtil::Class_JavaEncodingCollection); + jobject collection = env->CallStaticObjectMethod(cls, AndroidUtil::SMID_JavaEncodingCollection_Instance); + jboolean result = env->CallBooleanMethod(collection, AndroidUtil::MID_JavaEncodingCollection_isEncodingSupported); + env->DeleteLocalRef(collection); + env->DeleteLocalRef(cls); + return result != 0; } shared_ptr JavaEncodingConverterProvider::createConverter(const std::string &encoding) { diff --git a/proguard.cfg b/proguard.cfg index 52c34322b..d6b26ef33 100755 --- a/proguard.cfg +++ b/proguard.cfg @@ -35,6 +35,14 @@ -keepclassmembers class org.geometerplus.fbreader.formats.FormatPlugin { public ** supportedFileType(); } +-keep class org.geometerplus.fbreader.formats.Encoding +-keep class org.geometerplus.fbreader.formats.JavaEncodingCollection +-keepclassmembers class org.geometerplus.fbreader.formats.JavaEncodingCollection { + public static ** Instance(); + public ** getEncoding(java.lang.String); + public ** getEncoding(int); + public boolean isEncodingSupported(java.lang.String); +} -keep class org.geometerplus.fbreader.Paths -keepclassmembers class org.geometerplus.fbreader.Paths { public static ** cacheDirectory(); diff --git a/src/org/geometerplus/fbreader/formats/EncodingConverter.java b/src/org/geometerplus/fbreader/formats/EncodingConverter.java new file mode 100644 index 000000000..2643d380b --- /dev/null +++ b/src/org/geometerplus/fbreader/formats/EncodingConverter.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007-2012 Geometer Plus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package org.geometerplus.fbreader.formats; + +import java.nio.*; +import java.nio.charset.*; + +public class EncodingConverter { + private CharsetDecoder myDecoder; + private CharsetEncoder myEncoder; + + EncodingConverter(String encoding) { + myDecoder = Charset.forName(encoding).newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + myEncoder = Charset.forName("utf-8").newEncoder(); + } + + // we assume out is large enough for this conversion + // returns number of filled bytes in out buffer + int convert(byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { + final ByteBuffer inBuffer = ByteBuffer.wrap(in, inOffset, inLength); + final ByteBuffer outBuffer = ByteBuffer.wrap(out, outOffset, out.length - outOffset); + try { + final CharBuffer charBuffer = myDecoder.decode(inBuffer); + myEncoder.encode(charBuffer, outBuffer, true); + return charBuffer.length(); + } catch (CharacterCodingException e) { + return 0; + } + } + + void reset() { + myDecoder.reset(); + myEncoder.reset(); + } +} diff --git a/src/org/geometerplus/fbreader/formats/FilteredEncodingCollection.java b/src/org/geometerplus/fbreader/formats/FilteredEncodingCollection.java index 508e9d390..26912f462 100644 --- a/src/org/geometerplus/fbreader/formats/FilteredEncodingCollection.java +++ b/src/org/geometerplus/fbreader/formats/FilteredEncodingCollection.java @@ -35,7 +35,7 @@ abstract class FilteredEncodingCollection extends EncodingCollection { ); } - protected abstract boolean isEncodingSupported(String name); + public abstract boolean isEncodingSupported(String name); @Override public List encodings() { diff --git a/src/org/geometerplus/fbreader/formats/JavaEncodingCollection.java b/src/org/geometerplus/fbreader/formats/JavaEncodingCollection.java index ced66ca17..d560e8bb0 100644 --- a/src/org/geometerplus/fbreader/formats/JavaEncodingCollection.java +++ b/src/org/geometerplus/fbreader/formats/JavaEncodingCollection.java @@ -22,12 +22,21 @@ package org.geometerplus.fbreader.formats; import java.nio.charset.Charset; public final class JavaEncodingCollection extends FilteredEncodingCollection { - public JavaEncodingCollection() { + private volatile static JavaEncodingCollection ourInstance; + + public static JavaEncodingCollection Instance() { + if (ourInstance == null) { + ourInstance = new JavaEncodingCollection(); + } + return ourInstance; + } + + private JavaEncodingCollection() { super(); } @Override - protected boolean isEncodingSupported(String name) { + public boolean isEncodingSupported(String name) { try { return Charset.forName(name) != null; } catch (Exception e) { diff --git a/src/org/geometerplus/fbreader/formats/NativeFormatPlugin.java b/src/org/geometerplus/fbreader/formats/NativeFormatPlugin.java index a56c82ba5..326fb35c5 100644 --- a/src/org/geometerplus/fbreader/formats/NativeFormatPlugin.java +++ b/src/org/geometerplus/fbreader/formats/NativeFormatPlugin.java @@ -105,6 +105,6 @@ public class NativeFormatPlugin extends FormatPlugin { @Override public EncodingCollection supportedEncodings() { // TODO: implement - return new JavaEncodingCollection(); + return JavaEncodingCollection.Instance(); } } diff --git a/src/org/geometerplus/fbreader/formats/pdb/MobipocketPlugin.java b/src/org/geometerplus/fbreader/formats/pdb/MobipocketPlugin.java index ccfa0a3c7..b92458f21 100644 --- a/src/org/geometerplus/fbreader/formats/pdb/MobipocketPlugin.java +++ b/src/org/geometerplus/fbreader/formats/pdb/MobipocketPlugin.java @@ -246,6 +246,6 @@ public class MobipocketPlugin extends JavaFormatPlugin { @Override public EncodingCollection supportedEncodings() { - return new JavaEncodingCollection(); + return JavaEncodingCollection.Instance(); } }