diff --git a/jni/Android.mk b/jni/Android.mk
index e7814b67f..3e21eb5f4 100644
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -133,6 +133,7 @@ LOCAL_SRC_FILES := \
NativeFormats/fbreader/src/formats/doc/OleStream.cpp \
NativeFormats/fbreader/src/formats/doc/OleStreamReader.cpp \
NativeFormats/fbreader/src/formats/doc/OleUtil.cpp \
+ NativeFormats/fbreader/src/formats/doc/DocImageDataReader.cpp \
NativeFormats/fbreader/src/library/Author.cpp \
NativeFormats/fbreader/src/library/Book.cpp \
NativeFormats/fbreader/src/library/Comparators.cpp \
diff --git a/jni/NativeFormats/NativeFormats.pro b/jni/NativeFormats/NativeFormats.pro
new file mode 100644
index 000000000..805cb889b
--- /dev/null
+++ b/jni/NativeFormats/NativeFormats.pro
@@ -0,0 +1,298 @@
+######################################################################
+# Automatically generated by qmake (2.01a) ?? ???? 14 23:55:58 2012
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += . \
+ util \
+ fbreader/src/bookmodel \
+ fbreader/src/formats \
+ fbreader/src/library \
+ fbreader/src/formats/css \
+ fbreader/src/formats/doc \
+ fbreader/src/formats/fb2 \
+ fbreader/src/formats/html \
+ fbreader/src/formats/oeb \
+ fbreader/src/formats/rtf \
+ fbreader/src/formats/txt \
+ fbreader/src/formats/util \
+ fbreader/src/formats/xhtml \
+ zlibrary/core/src/constants \
+ zlibrary/core/src/encoding \
+ zlibrary/core/src/filesystem \
+ zlibrary/core/src/image \
+ zlibrary/core/src/language \
+ zlibrary/core/src/library \
+ zlibrary/core/src/logger \
+ zlibrary/core/src/util \
+ zlibrary/core/src/xml \
+ zlibrary/text/src/model \
+ zlibrary/core/src/filesystem/zip \
+ zlibrary/core/src/unix/filesystem \
+ zlibrary/core/src/unix/library \
+ zlibrary/core/src/xml/expat \
+ zlibrary/ui/src/android/filesystem \
+ zlibrary/ui/src/android/library
+INCLUDEPATH += . \
+ util \
+ zlibrary/core/src/util \
+ zlibrary/core/src/image \
+ zlibrary/core/src/filesystem \
+ fbreader/src/bookmodel \
+ zlibrary/text/src/model \
+ fbreader/src/formats \
+ fbreader/src/library \
+ zlibrary/core/src/library \
+ zlibrary/core/src/logger \
+ zlibrary/core/src/encoding \
+ zlibrary/core/src/language \
+ fbreader/src/formats/fb2 \
+ fbreader/src/formats/html \
+ fbreader/src/formats/txt \
+ fbreader/src/formats/oeb \
+ fbreader/src/formats/rtf \
+ fbreader/src/formats/doc \
+ fbreader/src/formats/css \
+ zlibrary/core/src/xml \
+ zlibrary/core/src/constants \
+ fbreader/src/formats/util \
+ fbreader/src/formats/xhtml \
+ zlibrary/core/src/filesystem/zip \
+ zlibrary/core/src/xml/expat \
+ zlibrary/core/src/unix/filesystem \
+ zlibrary/core/src/unix/library \
+ zlibrary/ui/src/android/filesystem \
+ /usr/include
+
+
+# Input
+HEADERS += util/AndroidUtil.h \
+ util/JniEnvelope.h \
+ fbreader/src/bookmodel/BookModel.h \
+ fbreader/src/bookmodel/BookReader.h \
+ fbreader/src/bookmodel/FBHyperlinkType.h \
+ fbreader/src/bookmodel/FBTextKind.h \
+ fbreader/src/formats/EncodedTextReader.h \
+ fbreader/src/formats/FormatPlugin.h \
+ fbreader/src/library/Author.h \
+ fbreader/src/library/Book.h \
+ fbreader/src/library/Library.h \
+ fbreader/src/library/Lists.h \
+ fbreader/src/library/Tag.h \
+ fbreader/src/formats/css/StyleSheetParser.h \
+ fbreader/src/formats/css/StyleSheetTable.h \
+ fbreader/src/formats/doc/DocBookReader.h \
+ fbreader/src/formats/doc/DocMetaInfoReader.h \
+ fbreader/src/formats/doc/DocPlugin.h \
+ fbreader/src/formats/doc/OleMainStream.h \
+ fbreader/src/formats/doc/OleStorage.h \
+ fbreader/src/formats/doc/OleStream.h \
+ fbreader/src/formats/doc/OleStreamReader.h \
+ fbreader/src/formats/doc/OleUtil.h \
+ fbreader/src/formats/fb2/FB2BookReader.h \
+ fbreader/src/formats/fb2/FB2CoverReader.h \
+ fbreader/src/formats/fb2/FB2MetaInfoReader.h \
+ fbreader/src/formats/fb2/FB2Plugin.h \
+ fbreader/src/formats/fb2/FB2Reader.h \
+ fbreader/src/formats/fb2/FB2TagManager.h \
+ fbreader/src/formats/html/HtmlBookReader.h \
+ fbreader/src/formats/html/HtmlDescriptionReader.h \
+ fbreader/src/formats/html/HtmlEntityCollection.h \
+ fbreader/src/formats/html/HtmlPlugin.h \
+ fbreader/src/formats/html/HtmlReader.h \
+ fbreader/src/formats/html/HtmlReaderStream.h \
+ fbreader/src/formats/html/HtmlTagActions.h \
+ fbreader/src/formats/oeb/NCXReader.h \
+ fbreader/src/formats/oeb/OEBBookReader.h \
+ fbreader/src/formats/oeb/OEBCoverReader.h \
+ fbreader/src/formats/oeb/OEBMetaInfoReader.h \
+ fbreader/src/formats/oeb/OEBPlugin.h \
+ fbreader/src/formats/oeb/OEBTextStream.h \
+ fbreader/src/formats/oeb/XHTMLImageFinder.h \
+ fbreader/src/formats/rtf/RtfBookReader.h \
+ fbreader/src/formats/rtf/RtfDescriptionReader.h \
+ fbreader/src/formats/rtf/RtfPlugin.h \
+ fbreader/src/formats/rtf/RtfReader.h \
+ fbreader/src/formats/rtf/RtfReaderStream.h \
+ fbreader/src/formats/txt/PlainTextFormat.h \
+ fbreader/src/formats/txt/TxtBookReader.h \
+ fbreader/src/formats/txt/TxtPlugin.h \
+ fbreader/src/formats/txt/TxtReader.h \
+ fbreader/src/formats/util/EntityFilesCollector.h \
+ fbreader/src/formats/util/MergedStream.h \
+ fbreader/src/formats/util/MiscUtil.h \
+ fbreader/src/formats/util/XMLTextStream.h \
+ fbreader/src/formats/xhtml/XHTMLReader.h \
+ zlibrary/core/src/constants/ZLXMLNamespace.h \
+ zlibrary/core/src/encoding/DummyEncodingConverter.h \
+ zlibrary/core/src/encoding/JavaEncodingConverter.h \
+ zlibrary/core/src/encoding/Utf16EncodingConverters.h \
+ zlibrary/core/src/encoding/ZLEncodingConverter.h \
+ zlibrary/core/src/encoding/ZLEncodingConverterProvider.h \
+ zlibrary/core/src/filesystem/ZLDir.h \
+ zlibrary/core/src/filesystem/ZLFile.h \
+ zlibrary/core/src/filesystem/ZLFileInfo.h \
+ zlibrary/core/src/filesystem/ZLFSDir.h \
+ zlibrary/core/src/filesystem/ZLFSManager.h \
+ zlibrary/core/src/filesystem/ZLInputStream.h \
+ zlibrary/core/src/filesystem/ZLOutputStream.h \
+ zlibrary/core/src/image/ZLFileImage.h \
+ zlibrary/core/src/image/ZLImage.h \
+ zlibrary/core/src/image/ZLStreamImage.h \
+ zlibrary/core/src/language/ZLCharSequence.h \
+ zlibrary/core/src/language/ZLLanguageDetector.h \
+ zlibrary/core/src/language/ZLLanguageList.h \
+ zlibrary/core/src/language/ZLLanguageMatcher.h \
+ zlibrary/core/src/language/ZLStatistics.h \
+ zlibrary/core/src/language/ZLStatisticsGenerator.h \
+ zlibrary/core/src/language/ZLStatisticsItem.h \
+ zlibrary/core/src/language/ZLStatisticsXMLReader.h \
+ zlibrary/core/src/library/ZLibrary.h \
+ zlibrary/core/src/logger/ZLLogger.h \
+ zlibrary/core/src/util/shared_ptr.h \
+ zlibrary/core/src/util/ZLBoolean3.h \
+ zlibrary/core/src/util/ZLFileUtil.h \
+ zlibrary/core/src/util/ZLStringUtil.h \
+ zlibrary/core/src/util/ZLUnicodeUtil.h \
+ zlibrary/core/src/xml/ZLAsynchronousInputStream.h \
+ zlibrary/core/src/xml/ZLPlainAsynchronousInputStream.h \
+ zlibrary/core/src/xml/ZLXMLReader.h \
+ zlibrary/text/src/model/ZLCachedMemoryAllocator.h \
+ zlibrary/text/src/model/ZLHyperlinkType.h \
+ zlibrary/text/src/model/ZLTextAlignmentType.h \
+ zlibrary/text/src/model/ZLTextKind.h \
+ zlibrary/text/src/model/ZLTextModel.h \
+ zlibrary/text/src/model/ZLTextParagraph.h \
+ zlibrary/text/src/model/ZLTextStyleEntry.h \
+ zlibrary/core/src/filesystem/zip/ZLZDecompressor.h \
+ zlibrary/core/src/filesystem/zip/ZLZip.h \
+ zlibrary/core/src/filesystem/zip/ZLZipHeader.h \
+ zlibrary/core/src/unix/filesystem/ZLUnixFileInputStream.h \
+ zlibrary/core/src/unix/filesystem/ZLUnixFileOutputStream.h \
+ zlibrary/core/src/unix/filesystem/ZLUnixFSDir.h \
+ zlibrary/core/src/unix/filesystem/ZLUnixFSManager.h \
+ zlibrary/core/src/unix/library/ZLibraryImplementation.h \
+ zlibrary/core/src/xml/expat/ZLXMLReaderInternal.h \
+ zlibrary/ui/src/android/filesystem/JavaFSDir.h \
+ zlibrary/ui/src/android/filesystem/JavaInputStream.h \
+ zlibrary/ui/src/android/filesystem/ZLAndroidFSManager.h \
+ zlibrary/text/src/model/ZLTextStyleEntry.h \
+ fbreader/src/formats/html/HtmlTagActions.h \
+ fbreader/src/formats/html/HtmlReaderStream.h \
+ fbreader/src/formats/html/HtmlReader.h \
+ fbreader/src/formats/html/HtmlPlugin.h \
+ fbreader/src/formats/html/HtmlEntityCollection.h \
+ fbreader/src/formats/html/HtmlDescriptionReader.h \
+ fbreader/src/formats/html/HtmlBookReader.h \
+ fbreader/src/formats/doc/OleUtil.h \
+ fbreader/src/formats/doc/OleStreamReader.h \
+ fbreader/src/formats/doc/OleStream.h \
+ fbreader/src/formats/doc/OleStorage.h \
+ fbreader/src/formats/doc/OleMainStream.h \
+ fbreader/src/formats/doc/DocPlugin.h \
+ fbreader/src/formats/doc/DocMetaInfoReader.h \
+ fbreader/src/formats/doc/DocBookReader.h
+SOURCES += JavaNativeFormatPlugin.cpp \
+ JavaPluginCollection.cpp \
+ main.cpp \
+ util/AndroidUtil.cpp \
+ util/JniEnvelope.cpp \
+ fbreader/src/bookmodel/BookModel.cpp \
+ fbreader/src/bookmodel/BookReader.cpp \
+ fbreader/src/formats/EncodedTextReader.cpp \
+ fbreader/src/formats/FormatPlugin.cpp \
+ fbreader/src/formats/PluginCollection.cpp \
+ fbreader/src/library/Author.cpp \
+ fbreader/src/library/Book.cpp \
+ fbreader/src/library/Comparators.cpp \
+ fbreader/src/library/Library.cpp \
+ fbreader/src/library/Tag.cpp \
+ fbreader/src/formats/css/StyleSheetParser.cpp \
+ fbreader/src/formats/css/StyleSheetTable.cpp \
+ fbreader/src/formats/doc/DocBookReader.cpp \
+ fbreader/src/formats/doc/DocMetaInfoReader.cpp \
+ fbreader/src/formats/doc/DocPlugin.cpp \
+ fbreader/src/formats/doc/OleMainStream.cpp \
+ fbreader/src/formats/doc/OleStorage.cpp \
+ fbreader/src/formats/doc/OleStream.cpp \
+ fbreader/src/formats/doc/OleStreamReader.cpp \
+ fbreader/src/formats/doc/OleUtil.cpp \
+ fbreader/src/formats/fb2/FB2BookReader.cpp \
+ fbreader/src/formats/fb2/FB2CoverReader.cpp \
+ fbreader/src/formats/fb2/FB2MetaInfoReader.cpp \
+ fbreader/src/formats/fb2/FB2Plugin.cpp \
+ fbreader/src/formats/fb2/FB2Reader.cpp \
+ fbreader/src/formats/fb2/FB2TagManager.cpp \
+ fbreader/src/formats/html/HtmlBookReader.cpp \
+ fbreader/src/formats/html/HtmlDescriptionReader.cpp \
+ fbreader/src/formats/html/HtmlEntityCollection.cpp \
+ fbreader/src/formats/html/HtmlPlugin.cpp \
+ fbreader/src/formats/html/HtmlReader.cpp \
+ fbreader/src/formats/html/HtmlReaderStream.cpp \
+ fbreader/src/formats/oeb/NCXReader.cpp \
+ fbreader/src/formats/oeb/OEBBookReader.cpp \
+ fbreader/src/formats/oeb/OEBCoverReader.cpp \
+ fbreader/src/formats/oeb/OEBMetaInfoReader.cpp \
+ fbreader/src/formats/oeb/OEBPlugin.cpp \
+ fbreader/src/formats/oeb/OEBTextStream.cpp \
+ fbreader/src/formats/oeb/XHTMLImageFinder.cpp \
+ fbreader/src/formats/rtf/RtfBookReader.cpp \
+ fbreader/src/formats/rtf/RtfDescriptionReader.cpp \
+ fbreader/src/formats/rtf/RtfPlugin.cpp \
+ fbreader/src/formats/rtf/RtfReader.cpp \
+ fbreader/src/formats/rtf/RtfReaderStream.cpp \
+ fbreader/src/formats/txt/PlainTextFormat.cpp \
+ fbreader/src/formats/txt/TxtBookReader.cpp \
+ fbreader/src/formats/txt/TxtPlugin.cpp \
+ fbreader/src/formats/txt/TxtReader.cpp \
+ fbreader/src/formats/util/EntityFilesCollector.cpp \
+ fbreader/src/formats/util/MergedStream.cpp \
+ fbreader/src/formats/util/MiscUtil.cpp \
+ fbreader/src/formats/util/XMLTextStream.cpp \
+ fbreader/src/formats/xhtml/XHTMLReader.cpp \
+ zlibrary/core/src/constants/ZLXMLNamespace.cpp \
+ zlibrary/core/src/encoding/DummyEncodingConverter.cpp \
+ zlibrary/core/src/encoding/JavaEncodingConverter.cpp \
+ zlibrary/core/src/encoding/Utf16EncodingConverters.cpp \
+ zlibrary/core/src/encoding/ZLEncodingCollection.cpp \
+ zlibrary/core/src/encoding/ZLEncodingConverter.cpp \
+ zlibrary/core/src/filesystem/ZLDir.cpp \
+ zlibrary/core/src/filesystem/ZLFile.cpp \
+ zlibrary/core/src/filesystem/ZLFSManager.cpp \
+ zlibrary/core/src/filesystem/ZLInputStreamDecorator.cpp \
+ zlibrary/core/src/language/ZLCharSequence.cpp \
+ zlibrary/core/src/language/ZLLanguageDetector.cpp \
+ zlibrary/core/src/language/ZLLanguageList.cpp \
+ zlibrary/core/src/language/ZLLanguageMatcher.cpp \
+ zlibrary/core/src/language/ZLStatistics.cpp \
+ zlibrary/core/src/language/ZLStatisticsGenerator.cpp \
+ zlibrary/core/src/language/ZLStatisticsItem.cpp \
+ zlibrary/core/src/language/ZLStatisticsXMLReader.cpp \
+ zlibrary/core/src/library/ZLibrary.cpp \
+ zlibrary/core/src/logger/ZLLogger.cpp \
+ zlibrary/core/src/util/ZLFileUtil.cpp \
+ zlibrary/core/src/util/ZLStringUtil.cpp \
+ zlibrary/core/src/util/ZLUnicodeUtil.cpp \
+ zlibrary/core/src/xml/ZLAsynchronousInputStream.cpp \
+ zlibrary/core/src/xml/ZLPlainAsynchronousInputStream.cpp \
+ zlibrary/core/src/xml/ZLXMLReader.cpp \
+ zlibrary/text/src/model/ZLCachedMemoryAllocator.cpp \
+ zlibrary/text/src/model/ZLTextModel.cpp \
+ zlibrary/text/src/model/ZLTextParagraph.cpp \
+ zlibrary/core/src/filesystem/zip/ZLGzipInputStream.cpp \
+ zlibrary/core/src/filesystem/zip/ZLZDecompressor.cpp \
+ zlibrary/core/src/filesystem/zip/ZLZipDir.cpp \
+ zlibrary/core/src/filesystem/zip/ZLZipEntryCache.cpp \
+ zlibrary/core/src/filesystem/zip/ZLZipHeader.cpp \
+ zlibrary/core/src/filesystem/zip/ZLZipInputStream.cpp \
+ zlibrary/core/src/unix/filesystem/ZLUnixFileInputStream.cpp \
+ zlibrary/core/src/unix/filesystem/ZLUnixFileOutputStream.cpp \
+ zlibrary/core/src/unix/filesystem/ZLUnixFSDir.cpp \
+ zlibrary/core/src/unix/filesystem/ZLUnixFSManager.cpp \
+ zlibrary/core/src/unix/library/ZLUnixLibrary.cpp \
+ zlibrary/core/src/xml/expat/ZLXMLReaderInternal.cpp \
+ zlibrary/ui/src/android/filesystem/JavaFSDir.cpp \
+ zlibrary/ui/src/android/filesystem/JavaInputStream.cpp \
+ zlibrary/ui/src/android/filesystem/ZLAndroidFSManager.cpp \
+ zlibrary/ui/src/android/library/ZLAndroidLibraryImplementation.cpp
diff --git a/jni/NativeFormats/NativeFormats.pro.user b/jni/NativeFormats/NativeFormats.pro.user
new file mode 100644
index 000000000..caffc36aa
--- /dev/null
+++ b/jni/NativeFormats/NativeFormats.pro.user
@@ -0,0 +1,365 @@
+
+
+
+
+
+ ProjectExplorer.Project.ActiveTarget
+ 0
+
+
+ ProjectExplorer.Project.EditorSettings
+
+ true
+ false
+
+ Cpp
+
+ CppGlobal
+
+
+
+ QmlJS
+
+ QmlJSGlobal
+
+
+ 2
+ System
+ false
+ 4
+ true
+ 1
+ true
+ 0
+ true
+ 0
+ 8
+ true
+ 1
+ true
+ true
+ true
+ true
+
+
+
+ ProjectExplorer.Project.PluginSettings
+
+
+
+ ProjectExplorer.Project.Target.0
+
+ Desktop
+ Desktop
+ Qt4ProjectManager.Target.DesktopTarget
+ 0
+ 0
+ 0
+
+ ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-32bit./opt/QtSDK/debugger/Desktop/bin/gdb
+
+
+ qmake
+
+ QtProjectManager.QMakeBuildStep
+ false
+ true
+
+ false
+
+
+ Сборка
+
+ Qt4ProjectManager.MakeStep
+ false
+
+
+
+ 2
+ Сборка
+
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ Сборка
+
+ Qt4ProjectManager.MakeStep
+ true
+ clean
+
+
+ 1
+ Очистка
+
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Qt в PATH Релиз
+
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 0
+ /home/snowwlex/ws/FBReaderJ/jni/NativeFormats
+ 2
+ false
+
+
+ ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-32bit./opt/QtSDK/debugger/Desktop/bin/gdb
+
+
+ qmake
+
+ QtProjectManager.QMakeBuildStep
+ false
+ true
+
+ false
+
+
+ Сборка
+
+ Qt4ProjectManager.MakeStep
+ false
+
+
+
+ 2
+ Сборка
+
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ Сборка
+
+ Qt4ProjectManager.MakeStep
+ true
+ clean
+
+
+ 1
+ Очистка
+
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Qt в PATH Отладка
+
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 2
+ /home/snowwlex/ws/FBReaderJ/jni/NativeFormats
+ 2
+ false
+
+
+ ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-32bit./opt/QtSDK/debugger/Desktop/bin/gdb
+
+
+ qmake
+
+ QtProjectManager.QMakeBuildStep
+ false
+ true
+
+ false
+
+
+ Сборка
+
+ Qt4ProjectManager.MakeStep
+ false
+
+
+
+ 2
+ Сборка
+
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ Сборка
+
+ Qt4ProjectManager.MakeStep
+ true
+ clean
+
+
+ 1
+ Очистка
+
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Qt 4.6.2 (Системная) Релиз
+
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 0
+ /home/snowwlex/ws/FBReaderJ/jni/NativeFormats
+ 5
+ false
+
+
+ ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-32bit./opt/QtSDK/debugger/Desktop/bin/gdb
+
+
+ qmake
+
+ QtProjectManager.QMakeBuildStep
+ false
+ true
+
+ false
+
+
+ Сборка
+
+ Qt4ProjectManager.MakeStep
+ false
+
+
+
+ 2
+ Сборка
+
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ Сборка
+
+ Qt4ProjectManager.MakeStep
+ true
+ clean
+
+
+ 1
+ Очистка
+
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Qt 4.6.2 (Системная) Отладка
+
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 2
+ /home/snowwlex/ws/FBReaderJ/jni/NativeFormats
+ 5
+ false
+
+ 4
+
+
+ 0
+ Установка
+
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+ Без установки
+
+ ProjectExplorer.DefaultDeployConfiguration
+
+ 1
+
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+ true
+ 0.01
+ 0.01
+ 10
+ 10
+ true
+ true
+ 25
+ 25
+
+
+ true
+ true
+ valgrind
+ valgrind
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+
+ NativeFormats
+
+ Qt4ProjectManager.Qt4RunConfiguration
+ 2
+
+ NativeFormats.pro
+ false
+ false
+
+
+ 3768
+ true
+ false
+ false
+
+ 1
+
+
+
+ ProjectExplorer.Project.TargetCount
+ 1
+
+
+ ProjectExplorer.Project.Updater.EnvironmentId
+ {bce7c847-fb35-41bd-9485-843f1b18eb8e}
+
+
+ ProjectExplorer.Project.Updater.FileVersion
+ 10
+
+
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.cpp b/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.cpp
index a83c7ca57..fac0068d6 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.cpp
+++ b/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Geometer Plus
+ * Copyright (C) 2004-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
@@ -21,10 +21,11 @@
#include
#include
-#include
#include
#include
#include
+#include
+#include
#include "DocBookReader.h"
#include "../../bookmodel/BookModel.h"
@@ -35,7 +36,8 @@
DocBookReader::DocBookReader(BookModel &model, const std::string &encoding) :
OleStreamReader(encoding),
- myModelReader(model) {
+ myModelReader(model),
+ myPictureCounter(0) {
myReadState = READ_TEXT;
}
@@ -160,6 +162,7 @@ void DocBookReader::handleStartField() {
void DocBookReader::handleSeparatorField() {
static const std::string HYPERLINK = "HYPERLINK";
+ static const std::string SEQUENCE = "SEQ";
// static const std::string PAGE = "PAGE";
// static const std::string PAGEREF = "PAGEREF";
// static const std::string SHAPE = "SHAPE";
@@ -185,6 +188,12 @@ void DocBookReader::handleSeparatorField() {
}
}
+ if (!splitted.empty() && splitted.at(0) == SEQUENCE) {
+ myReadFieldState = READ_FIELD_TEXT;
+ myHyperlinkTypeState = NO_HYPERLINK;
+ return;
+ }
+
if (splitted.size() < 2 || splitted.at(0) != HYPERLINK) {
myReadFieldState = DONT_READ_FIELD_TEXT;
//to remove pagination from TOC and not hyperlink fields
@@ -221,9 +230,12 @@ void DocBookReader::handleEndField() {
}
-void DocBookReader::handleStartOfHeading() {
- //heading can be, for example, a picture
- //TODO implement
+void DocBookReader::handlePicture(const ZLFileImage::Blocks &blocks) {
+ std::string number;
+ ZLStringUtil::appendNumber(number, myPictureCounter++);
+ myModelReader.addImageReference(number, 0, false);
+ ZLFile file(myModelReader.model().book()->file().path(), "image/auto");
+ myModelReader.addImage(number, new ZLFileImage(file, "", blocks));
}
void DocBookReader::handleOtherControlChar(ZLUnicodeUtil::Ucs2Char ucs2char) {
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.h b/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.h
index 0fbadcbfb..976249499 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.h
+++ b/jni/NativeFormats/fbreader/src/formats/doc/DocBookReader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Geometer Plus
+ * Copyright (C) 2004-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
@@ -51,7 +51,7 @@ private:
void handleStartField();
void handleSeparatorField();
void handleEndField();
- void handleStartOfHeading();
+ void handlePicture(const ZLFileImage::Blocks &blocks);
void handleOtherControlChar(ZLUnicodeUtil::Ucs2Char ucs2char);
//formatting:
@@ -89,6 +89,7 @@ private:
std::vector myKindStack;
shared_ptr myCurStyleEntry;
OleMainStream::Style myCurStyleInfo;
+ unsigned int myPictureCounter;
};
inline DocBookReader::~DocBookReader() {}
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/DocImageDataReader.cpp b/jni/NativeFormats/fbreader/src/formats/doc/DocImageDataReader.cpp
new file mode 100644
index 000000000..6b80d604d
--- /dev/null
+++ b/jni/NativeFormats/fbreader/src/formats/doc/DocImageDataReader.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2004-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.
+ */
+
+#include "OleUtil.h"
+
+#include "DocImageDataReader.h"
+
+DocImageDataReader::DocImageDataReader(shared_ptr dataStream) :
+ myDataStream(dataStream) {
+}
+
+ZLFileImage::Blocks DocImageDataReader::getImagePieceInfo(unsigned int dataPos) {
+ if (myDataStream.isNull()) {
+ return ZLFileImage::Blocks();
+ }
+ if (!myDataStream->seek(dataPos, true)) {
+ return ZLFileImage::Blocks();
+ }
+
+ //reading PICF structure (see p. 421 [MS-DOC])
+ unsigned int picfHeaderSize = 4 + 2 + 8; //record length, headerLength and storage format
+ char headerBuffer[picfHeaderSize];
+ if (myDataStream->read(headerBuffer, picfHeaderSize) != picfHeaderSize) {
+ return ZLFileImage::Blocks();
+ }
+ unsigned int length = OleUtil::getU4Bytes(headerBuffer, 0);
+ unsigned int headerLength = OleUtil::getU2Bytes(headerBuffer, 4);
+ unsigned int formatType = OleUtil::getU2Bytes(headerBuffer, 6);
+
+ if (formatType != 0x0064) { //external link to some file; see p.394 [MS-DOC]
+ //TODO implement
+ return ZLFileImage::Blocks();
+ }
+ if (headerLength >= length) {
+ return ZLFileImage::Blocks();
+ }
+
+ //reading OfficeArtInlineSpContainer structure; see p.421 [MS-DOC] and p.56 [MS-ODRAW]
+ if (!myDataStream->seek(headerLength - picfHeaderSize, false)) { //skip header
+ return ZLFileImage::Blocks();
+ }
+
+ char buffer[8]; //for OfficeArtRecordHeader structure; see p.69 [MS-ODRAW]
+ bool found = false;
+ unsigned int curOffset = 0;
+ for (curOffset = headerLength; !found && curOffset + 8 <= length; curOffset += 8) {
+ if (myDataStream->read(buffer, 8) != 8) {
+ return ZLFileImage::Blocks();
+ }
+ unsigned int recordInstance = OleUtil::getU2Bytes(buffer, 0) >> 4;
+ unsigned int recordType = OleUtil::getU2Bytes(buffer, 2);
+ unsigned int recordLen = OleUtil::getU4Bytes(buffer, 4);
+
+ switch (recordType) {
+ case 0xF000: case 0xF001: case 0xF002: case 0xF003: case 0xF004: case 0xF005:
+ break;
+ case 0xF007:
+ {
+ myDataStream->seek(33, false);
+ char tmpBuf[1];
+ myDataStream->read(tmpBuf, 1);
+ unsigned int nameLength = OleUtil::getU1Byte(tmpBuf, 0);
+ myDataStream->seek(nameLength * 2 + 2, false);
+ curOffset += 33 + 1 + nameLength * 2 + 2;
+ }
+ break;
+ case 0xF008:
+ myDataStream->seek(8, false);
+ curOffset += 8;
+ break;
+ case 0xF009:
+ myDataStream->seek(16, false);
+ curOffset += 16;
+ break;
+ case 0xF006: case 0xF00A: case 0xF00B: case 0xF00D: case 0xF00E: case 0xF00F: case 0xF010: case 0xF011: case 0xF122:
+ myDataStream->seek(recordLen, false);
+ curOffset += recordLen;
+ break;
+ case 0xF01A: //EMF
+ case 0xF01B: //WMF
+ case 0xF01C: //PICT
+ //TODO implement
+ return ZLFileImage::Blocks();
+ case 0xF01D: //JPEG
+ myDataStream->seek(17, false);
+ curOffset += 17;
+ if (recordInstance == 0x46B || recordInstance == 0x6E3) {
+ myDataStream->seek(16, false);
+ curOffset += 16;
+ }
+ found = true;
+ break;
+ case 0xF01E: //PNG
+ myDataStream->seek(17, false);
+ curOffset += 17;
+ if (recordInstance == 0x6E1) {
+ myDataStream->seek(16, false);
+ curOffset += 16;
+ }
+ found = true;
+ break;
+ case 0xF01F: //DIB (BMP without 14-bytes header)
+ myDataStream->seek(17, false);
+ curOffset += 17;
+ if (recordInstance == 0x7A9) {
+ myDataStream->seek(16, false);
+ curOffset += 16;
+ }
+ found = true;
+ break;
+ case 0xF020: //TIFF
+ myDataStream->seek(17, false);
+ curOffset += 17;
+ if (recordInstance == 0x6E5) {
+ myDataStream->seek(16, false);
+ curOffset += 16;
+ }
+ found = true;
+ break;
+ case 0xF00C:
+ default:
+ return ZLFileImage::Blocks();
+ }
+ }
+
+ if (!found) {
+ return ZLFileImage::Blocks();
+ }
+ return myDataStream->getBlockPieceInfoList(dataPos + curOffset, length - curOffset);
+}
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/DocImageDataReader.h b/jni/NativeFormats/fbreader/src/formats/doc/DocImageDataReader.h
new file mode 100644
index 000000000..35bad85df
--- /dev/null
+++ b/jni/NativeFormats/fbreader/src/formats/doc/DocImageDataReader.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004-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.
+ */
+
+#ifndef __DOCIMAGEDATAREADER_H__
+#define __DOCIMAGEDATAREADER_H__
+
+#include
+
+#include "OleStream.h"
+
+class DocImageDataReader {
+
+public:
+ DocImageDataReader(shared_ptr dataStream);
+ ZLFileImage::Blocks getImagePieceInfo(unsigned int dataPos);
+
+private:
+ shared_ptr myDataStream;
+};
+
+#endif /* __DOCIMAGEDATAREADER_H__ */
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/DocMetaInfoReader.cpp b/jni/NativeFormats/fbreader/src/formats/doc/DocMetaInfoReader.cpp
index 6f3f14750..0ddcb4230 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/DocMetaInfoReader.cpp
+++ b/jni/NativeFormats/fbreader/src/formats/doc/DocMetaInfoReader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Geometer Plus
+ * Copyright (C) 2004-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
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/DocMetaInfoReader.h b/jni/NativeFormats/fbreader/src/formats/doc/DocMetaInfoReader.h
index ea75cd903..30e9ec020 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/DocMetaInfoReader.h
+++ b/jni/NativeFormats/fbreader/src/formats/doc/DocMetaInfoReader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Geometer Plus
+ * Copyright (C) 2004-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
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/DocPlugin.cpp b/jni/NativeFormats/fbreader/src/formats/doc/DocPlugin.cpp
index 00cdd015d..2afdf9241 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/DocPlugin.cpp
+++ b/jni/NativeFormats/fbreader/src/formats/doc/DocPlugin.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Geometer Plus
+ * Copyright (C) 2004-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
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/DocPlugin.h b/jni/NativeFormats/fbreader/src/formats/doc/DocPlugin.h
index cb8665548..93b18035a 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/DocPlugin.h
+++ b/jni/NativeFormats/fbreader/src/formats/doc/DocPlugin.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Geometer Plus
+ * Copyright (C) 2004-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
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/OleMainStream.cpp b/jni/NativeFormats/fbreader/src/formats/doc/OleMainStream.cpp
index 01f69cc08..e903118f2 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/OleMainStream.cpp
+++ b/jni/NativeFormats/fbreader/src/formats/doc/OleMainStream.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 Geometer Plus
+ * Copyright (C) 2004-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
@@ -47,6 +47,10 @@ OleMainStream::SectionInfo::SectionInfo() :
newPage(true) {
}
+OleMainStream::PictureInfo::PictureInfo() :
+ dataPos(0) {
+}
+
OleMainStream::OleMainStream(shared_ptr storage, OleEntry oleEntry, shared_ptr stream) :
OleStream(storage, oleEntry, stream) {
}
@@ -90,6 +94,11 @@ bool OleMainStream::open() {
return false;
}
+ OleEntry dataEntry;
+ if (myStorage->getEntryByName("Data", dataEntry)) {
+ myDataStream = new OleStream(myStorage, dataEntry, myBaseStream);
+ }
+
//result of reading following structures doesn't check, because all these
//problems can be ignored, and document can be showed anyway, maybe with wrong formatting
readBookmarks(headerBuffer, tableEntry);
@@ -116,6 +125,14 @@ const OleMainStream::Bookmarks &OleMainStream::getBookmarks() const {
return myBookmarks;
}
+const OleMainStream::PictureInfoList &OleMainStream::getPictureInfoList() const {
+ return myPictureInfoList;
+}
+
+shared_ptr OleMainStream::dataStream() const {
+ return myDataStream;
+}
+
bool OleMainStream::readFIB(const char *headerBuffer) {
int flags = OleUtil::getU2Bytes(headerBuffer, 0xA); //offset for flags
@@ -314,7 +331,6 @@ bool OleMainStream::readBookmarks(const char *headerBuffer, const OleEntry &tabl
return true; //there's no bookmarks
}
-
OleStream tableStream(myStorage, tableEntry, myBaseStream);
std::string buffer;
if (!readToBuffer(buffer, beginNamesInfo, namesInfoLength, tableStream)) {
@@ -352,7 +368,8 @@ bool OleMainStream::readBookmarks(const char *headerBuffer, const OleEntry &tabl
return false;
}
- size_t size = (charPosInfoLen / 4 - 1) / 2;
+ static const unsigned int BKF_SIZE = 4;
+ size_t size = calcCountOfPLC(charPosInfoLen, BKF_SIZE);
std::vector charPage;
for (size_t index = 0, offset = 0; index < size; ++index, offset += 4) {
charPage.push_back(OleUtil::getU4Bytes(buffer.c_str(), offset));
@@ -479,9 +496,9 @@ bool OleMainStream::readStylesheet(const char *headerBuffer, const OleEntry &tab
}
bool OleMainStream::readCharInfoTable(const char *headerBuffer, const OleEntry &tableEntry) {
- //fcPlcfbteChpx structure is table with formatting for particular run of text
- unsigned int beginCharInfo = OleUtil::getU4Bytes(headerBuffer, 0xfa); // address of fcPlcfbteChpx structure
- size_t charInfoLength = (size_t)OleUtil::getU4Bytes(headerBuffer, 0xfe); // length of fcPlcfbteChpx structure
+ //PlcfbteChpx structure is table with formatting for particular run of text
+ unsigned int beginCharInfo = OleUtil::getU4Bytes(headerBuffer, 0xfa); // address of PlcfbteChpx structure
+ size_t charInfoLength = (size_t)OleUtil::getU4Bytes(headerBuffer, 0xfe); // length of PlcfbteChpx structure
if (charInfoLength < 4) {
return false;
}
@@ -492,9 +509,10 @@ bool OleMainStream::readCharInfoTable(const char *headerBuffer, const OleEntry &
return false;
}
- size_t size = (charInfoLength / 4 - 1) / 2;
+ static const unsigned int CHPX_SIZE = 4;
+ size_t size = calcCountOfPLC(charInfoLength, CHPX_SIZE);
std::vector charBlocks;
- for (size_t index = 0, offset = (size + 1) * 4; index < size; ++index, offset += 4) {
+ for (size_t index = 0, offset = (size + 1) * 4; index < size; ++index, offset += CHPX_SIZE) {
charBlocks.push_back(OleUtil::getU4Bytes(buffer.c_str(), offset));
}
@@ -520,6 +538,14 @@ bool OleMainStream::readCharInfoTable(const char *headerBuffer, const OleEntry &
getCharInfo(chpxOffset, istd, formatPageBuffer + 1, len - 1, charInfo);
}
myCharInfoList.push_back(CharPosToCharInfo(charPos, charInfo));
+
+ if (chpxOffset != 0) {
+ PictureInfo pictureInfo;
+ if (getPictureInfo(chpxOffset, formatPageBuffer + 1, len - 1, pictureInfo)) {
+ myPictureInfoList.push_back(CharPosToPictureInfo(charPos, pictureInfo));
+ }
+ }
+
}
}
delete[] formatPageBuffer;
@@ -540,10 +566,11 @@ bool OleMainStream::readParagraphStyleTable(const char *headerBuffer, const OleE
return false;
}
- size_t size = (paragraphInfoLength / 4 - 1) / 2;
+ static const unsigned int PAPX_SIZE = 4;
+ size_t size = calcCountOfPLC(paragraphInfoLength, PAPX_SIZE);
std::vector paragraphBlocks;
- for (size_t index = 0, tOffset = (size + 1) * 4; index < size; ++index, tOffset += 4) {
+ for (size_t index = 0, tOffset = (size + 1) * 4; index < size; ++index, tOffset += PAPX_SIZE) {
paragraphBlocks.push_back(OleUtil::getU4Bytes(buffer.c_str(), tOffset));
}
@@ -600,7 +627,8 @@ bool OleMainStream::readSectionsInfoTable(const char *headerBuffer, const OleEnt
return false;
}
- size_t decriptorsCount = (sectInfoLen - 4) / 16;
+ static const unsigned int SED_SIZE = 12;
+ size_t decriptorsCount = calcCountOfPLC(sectInfoLen, SED_SIZE);
//saving the section offsets (in character positions)
std::vector charPos;
@@ -611,7 +639,7 @@ bool OleMainStream::readSectionsInfoTable(const char *headerBuffer, const OleEnt
//saving sepx offsets
std::vector sectPage;
- for (size_t index = 0, tOffset = (decriptorsCount + 1) * 4; index < decriptorsCount; ++index, tOffset += 12) {
+ for (size_t index = 0, tOffset = (decriptorsCount + 1) * 4; index < decriptorsCount; ++index, tOffset += SED_SIZE) {
sectPage.push_back(OleUtil::getU4Bytes(buffer.c_str(), tOffset + 2));
}
@@ -780,6 +808,39 @@ void OleMainStream::getSectionInfo(const char *grpprlBuffer, size_t bytes, Secti
}
}
+bool OleMainStream::getPictureInfo(unsigned int chpxOffset, const char *grpprlBuffer, unsigned int bytes, PictureInfo &pictureInfo) {
+ //p. 105 of [MS-DOC] documentation
+ unsigned int offset = 0;
+ bool isFound = false;
+ while (bytes >= offset + 2) {
+ switch (OleUtil::getU2Bytes(grpprlBuffer, chpxOffset + offset)) {
+ case 0x080a: // ole object, p.107 [MS-DOC]
+ if (OleUtil::getU1Byte(grpprlBuffer, chpxOffset + offset + 2) == 0x01) {
+ return false;
+ }
+ break;
+ case 0x0806: // is not a picture, but a binary data? (sprmCFData, p.106 [MS-DOC])
+ if (OleUtil::getU4Bytes(grpprlBuffer, chpxOffset + offset + 2) == 0x01) {
+ return false;
+ }
+ break;
+// case 0x0855: // sprmCFSpec, p.117 [MS-DOC], MUST BE applied with a value of 1 (see p.105 [MS-DOC])
+// if (OleUtil::getU1Byte(grpprlBuffer, chpxOffset + offset + 2) != 0x01) {
+// return false;
+// }
+// break;
+ case 0x6a03: // location p.105 [MS-DOC]
+ pictureInfo.dataPos = OleUtil::getU4Bytes(grpprlBuffer, chpxOffset + offset + 2);
+ isFound = true;
+ break;
+ default:
+ break;
+ }
+ offset += getPrlLength(grpprlBuffer, chpxOffset + offset);
+ }
+ return isFound;
+}
+
OleMainStream::Style OleMainStream::getStyleFromStylesheet(unsigned int istd, const StyleSheet &stylesheet) {
//TODO optimize it: StyleSheet can be map structure with istd key
Style style;
@@ -831,7 +892,8 @@ bool OleMainStream::offsetToCharPos(unsigned int offset, unsigned int &charPos,
return false;
}
if ((unsigned int)pieces.front().offset > offset) {
- return false;
+ charPos = 0;
+ return true;
}
if ((unsigned int)(pieces.back().offset + pieces.back().length) <= offset) {
return false;
@@ -871,6 +933,11 @@ bool OleMainStream::readToBuffer(std::string &result, unsigned int offset, size_
return true;
}
+unsigned int OleMainStream::calcCountOfPLC(unsigned int totalSize, unsigned int elementSize) {
+ //calculates count of elements in PLC structure, formula from p.30 [MS-DOC]
+ return (totalSize - 4) / (4 + elementSize);
+}
+
unsigned int OleMainStream::getPrlLength(const char *grpprlBuffer, unsigned int byteNumber) {
unsigned int tmp;
unsigned int opCode = OleUtil::getU2Bytes(grpprlBuffer, byteNumber);
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/OleMainStream.h b/jni/NativeFormats/fbreader/src/formats/doc/OleMainStream.h
index 0a4dca8a2..4712f917e 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/OleMainStream.h
+++ b/jni/NativeFormats/fbreader/src/formats/doc/OleMainStream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 Geometer Plus
+ * Copyright (C) 2004-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
@@ -106,16 +106,22 @@ public:
bool newPage;
SectionInfo();
};
-
typedef std::vector SectionInfoList;
struct Bookmark {
unsigned int charPos;
std::string name;
};
-
typedef std::vector Bookmarks;
+ struct PictureInfo {
+ unsigned int dataPos;
+
+ PictureInfo();
+ };
+ typedef std::pair CharPosToPictureInfo;
+ typedef std::vector PictureInfoList;
+
public:
OleMainStream(shared_ptr storage, OleEntry oleEntry, shared_ptr stream);
@@ -125,6 +131,8 @@ public:
const CharInfoList &getCharInfoList() const;
const StyleInfoList &getStyleInfoList() const;
const Bookmarks &getBookmarks() const;
+ const PictureInfoList &getPictureInfoList() const;
+ shared_ptr dataStream() const;
private:
bool readFIB(const char *headerBuffer);
@@ -144,6 +152,7 @@ private: //formatting reader helpers methods
static void getCharInfo(unsigned int chpxOffset, unsigned int istd, const char *grpprlBuffer, unsigned int bytes, CharInfo &charInfo);
static void getStyleInfo(unsigned int papxOffset, const char *grpprlBuffer, unsigned int bytes, Style &styleInfo);
static void getSectionInfo(const char *grpprlBuffer, size_t bytes, SectionInfo §ionInfo);
+ static bool getPictureInfo(unsigned int chpxOffset, const char *grpprlBuffer, unsigned int bytes, PictureInfo &pictureInfo);
static Style getStyleFromStylesheet(unsigned int istd, const StyleSheet &stylesheet);
static int getStyleIndex(unsigned int istd, const std::vector &isFilled, const StyleSheet &stylesheet);
@@ -152,6 +161,8 @@ private: //formatting reader helpers methods
static bool offsetToCharPos(unsigned int offset, unsigned int &charPos, const Pieces &pieces);
static bool readToBuffer(std::string &result, unsigned int offset, size_t length, OleStream &stream);
+ static unsigned int calcCountOfPLC(unsigned int totalSize, unsigned int elementSize);
+
private:
enum PrlFlag {
UNSET = 0,
@@ -171,8 +182,11 @@ private:
CharInfoList myCharInfoList;
StyleInfoList myStyleInfoList;
SectionInfoList mySectionInfoList;
+ PictureInfoList myPictureInfoList;
Bookmarks myBookmarks;
+
+ shared_ptr myDataStream;
};
#endif /* __OLEMAINSTREAM_H__ */
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/OleStorage.cpp b/jni/NativeFormats/fbreader/src/formats/doc/OleStorage.cpp
index c1f5ea0fc..fbdb13513 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/OleStorage.cpp
+++ b/jni/NativeFormats/fbreader/src/formats/doc/OleStorage.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 Geometer Plus
+ * Copyright (C) 2004-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
@@ -259,11 +259,11 @@ bool OleStorage::readOleEntry(int propNumber, OleEntry &e) {
chainCur < (int)(e.isBigBlock ? myBBD.size() : mySBD.size()) &&
e.blocks.size() <= e.length / (e.isBigBlock ? mySectorSize : myShortSectorSize));
}
- e.length = std::min(e.length, (unsigned int)(e.isBigBlock ? mySectorSize : myShortSectorSize) * e.blocks.size());
+ e.length = std::min(e.length, (unsigned int)((e.isBigBlock ? mySectorSize : myShortSectorSize) * e.blocks.size()));
return true;
}
-unsigned int OleStorage::getFileOffsetOfBlock(OleEntry &e, unsigned int blockNumber) {
+unsigned int OleStorage::getFileOffsetOfBlock(const OleEntry &e, unsigned int blockNumber) const {
unsigned int res;
if (e.isBigBlock) {
res = BBD_BLOCK_SIZE + e.blocks.at(blockNumber) * mySectorSize;
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/OleStorage.h b/jni/NativeFormats/fbreader/src/formats/doc/OleStorage.h
index 099cb26bd..715ffa50c 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/OleStorage.h
+++ b/jni/NativeFormats/fbreader/src/formats/doc/OleStorage.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 Geometer Plus
+ * Copyright (C) 2004-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
@@ -55,11 +55,11 @@ public:
const std::vector &getEntries() const;
bool getEntryByName(std::string name, OleEntry &entry) const;
- unsigned int getSectorSize();
- unsigned int getShortSectorSize();
+ unsigned int getSectorSize() const;
+ unsigned int getShortSectorSize() const;
public: //TODO make private
- unsigned int getFileOffsetOfBlock(OleEntry &e, unsigned int blockNumber);
+ unsigned int getFileOffsetOfBlock(const OleEntry &e, unsigned int blockNumber) const;
private:
bool readDIFAT(char *oleBuf);
@@ -86,7 +86,7 @@ private:
};
inline const std::vector &OleStorage::getEntries() const { return myEntries; }
-inline unsigned int OleStorage::getSectorSize() { return mySectorSize; }
-inline unsigned int OleStorage::getShortSectorSize() { return myShortSectorSize; }
+inline unsigned int OleStorage::getSectorSize() const { return mySectorSize; }
+inline unsigned int OleStorage::getShortSectorSize() const { return myShortSectorSize; }
#endif /* __OLESTORAGE_H__ */
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/OleStream.cpp b/jni/NativeFormats/fbreader/src/formats/doc/OleStream.cpp
index 126be646a..5838a62ab 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/OleStream.cpp
+++ b/jni/NativeFormats/fbreader/src/formats/doc/OleStream.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 Geometer Plus
+ * Copyright (C) 2004-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
@@ -70,20 +70,17 @@ size_t OleStream::read(char *buffer, size_t maxSize) {
readedBytes = myBaseStream->read(buffer, std::min(length, bytesLeftInCurBlock));
for (size_t i = 0; i < toReadBlocks; ++i) {
- size_t readbytes;
- ++curBlockNumber;
+ if (++curBlockNumber >= myOleEntry.blocks.size()) {
+ break;
+ }
newFileOffset = myStorage->getFileOffsetOfBlock(myOleEntry, curBlockNumber);
myBaseStream->seek(newFileOffset, true);
- readbytes = myBaseStream->read(buffer + readedBytes, std::min(length - readedBytes, sectorSize));
- readedBytes += readbytes;
+ readedBytes += myBaseStream->read(buffer + readedBytes, std::min(length - readedBytes, sectorSize));
}
- if (toReadBytes > 0) {
- size_t readbytes;
- ++curBlockNumber;
+ if (toReadBytes > 0 && ++curBlockNumber < myOleEntry.blocks.size()) {
newFileOffset = myStorage->getFileOffsetOfBlock(myOleEntry, curBlockNumber);
myBaseStream->seek(newFileOffset, true);
- readbytes = myBaseStream->read(buffer + readedBytes, toReadBytes);
- readedBytes += readbytes;
+ readedBytes += myBaseStream->read(buffer + readedBytes, toReadBytes);
}
myOleOffset += readedBytes;
return readedBytes;
@@ -125,3 +122,74 @@ bool OleStream::seek(unsigned int offset, bool absoluteOffset) {
size_t OleStream::offset() {
return myOleOffset;
}
+
+ZLFileImage::Blocks OleStream::getBlockPieceInfoList(unsigned int offset, unsigned int size) const {
+ ZLFileImage::Blocks list;
+ unsigned int sectorSize = (myOleEntry.isBigBlock ? myStorage->getSectorSize() : myStorage->getShortSectorSize());
+ unsigned int curBlockNumber = offset / sectorSize;
+ if (curBlockNumber >= myOleEntry.blocks.size()) {
+ return list;
+ }
+ unsigned int modBlock = offset % sectorSize;
+ unsigned int startFileOffset = myStorage->getFileOffsetOfBlock(myOleEntry, curBlockNumber) + modBlock;
+
+ unsigned int bytesLeftInCurBlock = sectorSize - modBlock;
+ unsigned int toReadBlocks = 0, toReadBytes = 0;
+ if (bytesLeftInCurBlock < size) {
+ toReadBlocks = (size - bytesLeftInCurBlock) / sectorSize;
+ toReadBytes = (size - bytesLeftInCurBlock) % sectorSize;
+ }
+
+ unsigned int readedBytes = std::min(size, bytesLeftInCurBlock);
+ list.push_back(ZLFileImage::Block(startFileOffset, readedBytes));
+
+ for (unsigned int i = 0; i < toReadBlocks; ++i) {
+ if (++curBlockNumber >= myOleEntry.blocks.size()) {
+ break;
+ }
+ unsigned int newFileOffset = myStorage->getFileOffsetOfBlock(myOleEntry, curBlockNumber);
+ unsigned int readbytes = std::min(size - readedBytes, sectorSize);
+ list.push_back(ZLFileImage::Block(newFileOffset, readbytes));
+ readedBytes += readbytes;
+ }
+ if (toReadBytes > 0 && ++curBlockNumber < myOleEntry.blocks.size()) {
+ unsigned int newFileOffset = myStorage->getFileOffsetOfBlock(myOleEntry, curBlockNumber);
+ unsigned int readbytes = toReadBytes;
+ list.push_back(ZLFileImage::Block(newFileOffset, readbytes));
+ readedBytes += readbytes;
+ }
+
+ return concatBlocks(list);
+}
+
+ZLFileImage::Blocks OleStream::concatBlocks(const ZLFileImage::Blocks &blocks) {
+ if (blocks.size() < 2) {
+ return blocks;
+ }
+ ZLFileImage::Blocks optList;
+ ZLFileImage::Block curBlock = blocks.at(0);
+ unsigned int nextOffset = curBlock.offset + curBlock.size;
+ for (size_t i = 1; i < blocks.size(); ++i) {
+ ZLFileImage::Block b = blocks.at(i);
+ if (b.offset == nextOffset) {
+ curBlock.size += b.size;
+ nextOffset += b.size;
+ } else {
+ optList.push_back(curBlock);
+ curBlock = b;
+ nextOffset = curBlock.offset + curBlock.size;
+ }
+ }
+ optList.push_back(curBlock);
+ return optList;
+}
+
+size_t OleStream::fileOffset() {
+ size_t sectorSize = (size_t)(myOleEntry.isBigBlock ? myStorage->getSectorSize() : myStorage->getShortSectorSize());
+ unsigned int curBlockNumber = myOleOffset / sectorSize;
+ if (curBlockNumber >= myOleEntry.blocks.size()) {
+ return 0;
+ }
+ unsigned int modBlock = myOleOffset % sectorSize;
+ return myStorage->getFileOffsetOfBlock(myOleEntry, curBlockNumber) + modBlock;
+}
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/OleStream.h b/jni/NativeFormats/fbreader/src/formats/doc/OleStream.h
index 1859b3b47..2108fa295 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/OleStream.h
+++ b/jni/NativeFormats/fbreader/src/formats/doc/OleStream.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 Geometer Plus
+ * Copyright (C) 2004-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
@@ -20,6 +20,8 @@
#ifndef __OLESTREAM_H__
#define __OLESTREAM_H__
+#include
+
#include "OleStorage.h"
class OleStream {
@@ -36,6 +38,11 @@ public:
bool seek(unsigned int offset, bool absoluteOffset);
size_t offset();
+public:
+ ZLFileImage::Blocks getBlockPieceInfoList(unsigned int offset, unsigned int size) const;
+ static ZLFileImage::Blocks concatBlocks(const ZLFileImage::Blocks &blocks);
+ size_t fileOffset();
+
public:
bool eof() const;
@@ -48,6 +55,4 @@ protected:
unsigned int myOleOffset;
};
-
-
#endif /* __OLESTREAM_H__ */
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/OleStreamReader.cpp b/jni/NativeFormats/fbreader/src/formats/doc/OleStreamReader.cpp
index efafce8c6..d792071f0 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/OleStreamReader.cpp
+++ b/jni/NativeFormats/fbreader/src/formats/doc/OleStreamReader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 Geometer Plus
+ * Copyright (C) 2004-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
@@ -26,6 +26,7 @@
#include "OleMainStream.h"
#include "DocBookReader.h"
#include "OleUtil.h"
+#include "DocImageDataReader.h"
#include "OleStreamReader.h"
@@ -42,13 +43,14 @@ const ZLUnicodeUtil::Ucs2Char OleStreamReader::WORD_START_FIELD = 0x0013;
const ZLUnicodeUtil::Ucs2Char OleStreamReader::WORD_SEPARATOR_FIELD = 0x0014;
const ZLUnicodeUtil::Ucs2Char OleStreamReader::WORD_END_FIELD = 0x0015;
const ZLUnicodeUtil::Ucs2Char OleStreamReader::WORD_ZERO_WIDTH_UNBREAKABLE_SPACE = 0xfeff;
+const ZLUnicodeUtil::Ucs2Char OleStreamReader::PICTURE = 0x0001;
+const ZLUnicodeUtil::Ucs2Char OleStreamReader::DRAWN_OBJECT = 0x0008;
//unicode values:
const ZLUnicodeUtil::Ucs2Char OleStreamReader::NULL_SYMBOL = 0x0;
const ZLUnicodeUtil::Ucs2Char OleStreamReader::FILE_SEPARATOR = 0x1c;
const ZLUnicodeUtil::Ucs2Char OleStreamReader::LINE_FEED = 0x000a;
const ZLUnicodeUtil::Ucs2Char OleStreamReader::SOFT_HYPHEN = 0xad;
-const ZLUnicodeUtil::Ucs2Char OleStreamReader::START_OF_HEADING = 0x0001;
const ZLUnicodeUtil::Ucs2Char OleStreamReader::SPACE = 0x20;
const ZLUnicodeUtil::Ucs2Char OleStreamReader::SHORT_DEFIS = 0x2D;
const ZLUnicodeUtil::Ucs2Char OleStreamReader::VERTICAL_LINE = 0x7C;
@@ -67,6 +69,7 @@ void OleStreamReader::clear() {
myNextStyleInfoIndex = 0;
myNextCharInfoIndex = 0;
myNextBookmarkIndex = 0;
+ myNextPictureInfoIndex = 0;
}
bool OleStreamReader::readStream(OleMainStream &oleMainStream) {
@@ -122,8 +125,8 @@ bool OleStreamReader::readStream(OleMainStream &oleMainStream) {
case WORD_END_FIELD:
handleEndField();
break;
- case START_OF_HEADING:
- handleStartOfHeading();
+ case PICTURE:
+ //pictures handle method is called from processPicture()
break;
default:
handleOtherControlChar(ucs2char);
@@ -133,11 +136,11 @@ bool OleStreamReader::readStream(OleMainStream &oleMainStream) {
continue; //skip
} else {
//debug output
- //std::string utf8String;
- //ZLUnicodeUtil::Ucs2String ucs2String;
- //ucs2String.push_back(ucs2char);
- //ZLUnicodeUtil::ucs2ToUtf8(utf8String, ucs2String);
- //printf("%s", utf8String.c_str());
+// std::string utf8String;
+// ZLUnicodeUtil::Ucs2String ucs2String;
+// ucs2String.push_back(ucs2char);
+// ZLUnicodeUtil::ucs2ToUtf8(utf8String, ucs2String);
+// printf("%s", utf8String.c_str());
handleChar(ucs2char);
}
@@ -152,7 +155,40 @@ bool OleStreamReader::getUcs2Char(OleMainStream &stream, ZLUnicodeUtil::Ucs2Char
return false;
}
}
+ ucs2char = myBuffer.at(myCurBufferPosition++);
+ processStyles(stream);
+ if (ucs2char == PICTURE) {
+ processPicture(stream);
+ }
+ ++myCurCharPos;
+ return true;
+}
+void OleStreamReader::processPicture(OleMainStream &stream) {
+ shared_ptr dataStream = stream.dataStream();
+ if (dataStream.isNull()) {
+ return;
+ }
+ const OleMainStream::PictureInfoList &pictureInfoList = stream.getPictureInfoList();
+ if (pictureInfoList.empty()) {
+ return;
+ }
+ //seek to curCharPos, because not all entries in PictureInfo are real pictures
+ while(myNextPictureInfoIndex < pictureInfoList.size() && pictureInfoList.at(myNextPictureInfoIndex).first < myCurCharPos) {
+ ++myNextPictureInfoIndex;
+ }
+ while (myNextPictureInfoIndex < pictureInfoList.size() && pictureInfoList.at(myNextPictureInfoIndex).first == myCurCharPos) {
+ OleMainStream::PictureInfo info = pictureInfoList.at(myNextPictureInfoIndex).second;
+ DocImageDataReader imageReader(dataStream);
+ ZLFileImage::Blocks list = imageReader.getImagePieceInfo(info.dataPos);
+ if (!list.empty()) {
+ handlePicture(list);
+ }
+ ++myNextPictureInfoIndex;
+ }
+}
+
+void OleStreamReader::processStyles(OleMainStream &stream) {
const OleMainStream::StyleInfoList &styleInfoList = stream.getStyleInfoList();
if (!styleInfoList.empty()) {
while (myNextStyleInfoIndex < styleInfoList.size() && styleInfoList.at(myNextStyleInfoIndex).first == myCurCharPos) {
@@ -179,10 +215,6 @@ bool OleStreamReader::getUcs2Char(OleMainStream &stream, ZLUnicodeUtil::Ucs2Char
++myNextBookmarkIndex;
}
}
-
- ucs2char = myBuffer.at(myCurBufferPosition++);
- ++myCurCharPos;
- return true;
}
bool OleStreamReader::fillBuffer(OleMainStream &stream) {
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/OleStreamReader.h b/jni/NativeFormats/fbreader/src/formats/doc/OleStreamReader.h
index d36fb31dd..a5b46bf7f 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/OleStreamReader.h
+++ b/jni/NativeFormats/fbreader/src/formats/doc/OleStreamReader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 Geometer Plus
+ * Copyright (C) 2004-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
@@ -41,13 +41,14 @@ public:
static const ZLUnicodeUtil::Ucs2Char WORD_SEPARATOR_FIELD;
static const ZLUnicodeUtil::Ucs2Char WORD_END_FIELD;
static const ZLUnicodeUtil::Ucs2Char WORD_ZERO_WIDTH_UNBREAKABLE_SPACE;
+ static const ZLUnicodeUtil::Ucs2Char PICTURE;
+ static const ZLUnicodeUtil::Ucs2Char DRAWN_OBJECT;
//unicode values:
static const ZLUnicodeUtil::Ucs2Char NULL_SYMBOL;
static const ZLUnicodeUtil::Ucs2Char FILE_SEPARATOR;
static const ZLUnicodeUtil::Ucs2Char LINE_FEED;
static const ZLUnicodeUtil::Ucs2Char SOFT_HYPHEN;
- static const ZLUnicodeUtil::Ucs2Char START_OF_HEADING;
static const ZLUnicodeUtil::Ucs2Char SPACE;
static const ZLUnicodeUtil::Ucs2Char SHORT_DEFIS;
static const ZLUnicodeUtil::Ucs2Char VERTICAL_LINE;
@@ -70,7 +71,7 @@ protected:
virtual void handleStartField() = 0;
virtual void handleSeparatorField() = 0;
virtual void handleEndField() = 0;
- virtual void handleStartOfHeading() = 0;
+ virtual void handlePicture(const ZLFileImage::Blocks &blocks) = 0;
virtual void handleOtherControlChar(ZLUnicodeUtil::Ucs2Char ucs2char) = 0;
virtual void handleFontStyle(unsigned int fontStyle) = 0;
@@ -79,6 +80,8 @@ protected:
private:
bool getUcs2Char(OleMainStream &stream, ZLUnicodeUtil::Ucs2Char &ucs2char);
+ void processPicture(OleMainStream &stream);
+ void processStyles(OleMainStream &stream);
bool fillBuffer(OleMainStream &stream);
private:
@@ -94,6 +97,7 @@ private:
size_t myNextStyleInfoIndex;
size_t myNextCharInfoIndex;
size_t myNextBookmarkIndex;
+ size_t myNextPictureInfoIndex;
};
#endif /* __OLESTREAMREADER_H__ */
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/OleUtil.cpp b/jni/NativeFormats/fbreader/src/formats/doc/OleUtil.cpp
index 39ff75d13..2e8f68502 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/OleUtil.cpp
+++ b/jni/NativeFormats/fbreader/src/formats/doc/OleUtil.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 Geometer Plus
+ * Copyright (C) 2004-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
diff --git a/jni/NativeFormats/fbreader/src/formats/doc/OleUtil.h b/jni/NativeFormats/fbreader/src/formats/doc/OleUtil.h
index d74903236..531c76918 100644
--- a/jni/NativeFormats/fbreader/src/formats/doc/OleUtil.h
+++ b/jni/NativeFormats/fbreader/src/formats/doc/OleUtil.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 Geometer Plus
+ * Copyright (C) 2004-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
diff --git a/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.cpp b/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.cpp
index 8b526295a..582c35c1a 100644
--- a/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.cpp
+++ b/jni/NativeFormats/fbreader/src/formats/xhtml/XHTMLReader.cpp
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
#include "XHTMLReader.h"
diff --git a/jni/NativeFormats/util/AndroidUtil.cpp b/jni/NativeFormats/util/AndroidUtil.cpp
index 84e582d4e..529bb00e3 100644
--- a/jni/NativeFormats/util/AndroidUtil.cpp
+++ b/jni/NativeFormats/util/AndroidUtil.cpp
@@ -166,7 +166,7 @@ bool AndroidUtil::init(JavaVM* jvm) {
Method_ZLFile_getPath = new StringMethod(Class_ZLFile, "getPath", "()");
Method_ZLFile_size = new LongMethod(Class_ZLFile, "size", "()");
- Constructor_ZLFileImage = new Constructor(Class_ZLFileImage, "(Ljava/lang/String;Lorg/geometerplus/zlibrary/core/filesystem/ZLFile;Ljava/lang/String;II)V");
+ Constructor_ZLFileImage = new Constructor(Class_ZLFileImage, "(Ljava/lang/String;Lorg/geometerplus/zlibrary/core/filesystem/ZLFile;Ljava/lang/String;[I[I)V");
StaticMethod_Paths_cacheDirectory = new StaticObjectMethod(Class_Paths, "cacheDirectory", Class_java_lang_String, "()");
@@ -213,14 +213,25 @@ jobject AndroidUtil::createJavaImage(JNIEnv *env, const ZLFileImage &image) {
jobject javaFile = createJavaFile(env, image.file().path());
jstring javaEncoding = createJavaString(env, image.encoding());
+ std::vector offsets, sizes;
+ const ZLFileImage::Blocks &blocks = image.blocks();
+ for (size_t i = 0; i < blocks.size(); ++i) {
+ offsets.push_back((jint)blocks.at(i).offset);
+ sizes.push_back((jint)blocks.at(i).size);
+ }
+ jintArray javaOffsets = createJavaIntArray(env, offsets);
+ jintArray javaSizes = createJavaIntArray(env, sizes);
+
jobject javaImage = Constructor_ZLFileImage->call(
javaMimeType, javaFile, javaEncoding,
- image.offset(), image.size()
+ javaOffsets, javaSizes
);
env->DeleteLocalRef(javaEncoding);
env->DeleteLocalRef(javaFile);
env->DeleteLocalRef(javaMimeType);
+ env->DeleteLocalRef(javaOffsets);
+ env->DeleteLocalRef(javaSizes);
return javaImage;
}
diff --git a/jni/NativeFormats/zlibrary/core/src/image/ZLFileImage.h b/jni/NativeFormats/zlibrary/core/src/image/ZLFileImage.h
index e92f5aeb2..25e55effa 100644
--- a/jni/NativeFormats/zlibrary/core/src/image/ZLFileImage.h
+++ b/jni/NativeFormats/zlibrary/core/src/image/ZLFileImage.h
@@ -20,28 +20,53 @@
#ifndef __ZLFILEIMAGE_H__
#define __ZLFILEIMAGE_H__
+#include
+
#include
-#include "ZLStreamImage.h"
+#include "ZLImage.h"
-class ZLFileImage : public ZLStreamImage {
+class ZLFileImage : public ZLSingleImage {
+
+public:
+ struct Block {
+ unsigned int offset;
+ unsigned int size;
+
+ Block(unsigned int off, unsigned int s);
+ };
+ typedef std::vector Blocks;
public:
ZLFileImage(const ZLFile &file, const std::string &encoding, size_t offset, size_t size = 0);
+ ZLFileImage(const ZLFile &file, const std::string &encoding, const Blocks &blocks);
//Kind kind() const;
const ZLFile &file() const;
+ const std::string &encoding() const;
+ const ZLFileImage::Blocks& blocks() const;
protected:
//shared_ptr inputStream() const;
private:
const ZLFile myFile;
+ const std::string myEncoding;
+ Blocks myBlocks;
};
-inline ZLFileImage::ZLFileImage(const ZLFile &file, const std::string &encoding, size_t offset, size_t size) : ZLStreamImage(file.mimeType(), encoding, offset, size), myFile(file) {}
+inline ZLFileImage::Block::Block(unsigned int off, unsigned int s) : offset(off), size(s) {}
+
+inline ZLFileImage::ZLFileImage(const ZLFile &file, const std::string &encoding, size_t offset, size_t size) : ZLSingleImage(file.mimeType()), myFile(file), myEncoding(encoding) {
+ myBlocks.push_back(Block(offset, size));
+}
+
+inline ZLFileImage::ZLFileImage(const ZLFile &file, const std::string &encoding, const ZLFileImage::Blocks &blocks) : ZLSingleImage(file.mimeType()), myFile(file), myEncoding(encoding), myBlocks(blocks) { }
+
//inline ZLSingleImage::Kind ZLFileImage::kind() const { return FILE_IMAGE; }
inline const ZLFile &ZLFileImage::file() const { return myFile; }
+inline const std::string &ZLFileImage::encoding() const { return myEncoding; }
+inline const ZLFileImage::Blocks &ZLFileImage::blocks() const { return myBlocks; }
//inline shared_ptr ZLFileImage::inputStream() const { return myFile.inputStream(); }
#endif /* __ZLFILEIMAGE_H__ */
diff --git a/src/org/geometerplus/zlibrary/core/image/ZLFileImage.java b/src/org/geometerplus/zlibrary/core/image/ZLFileImage.java
index 8fc3082e0..317b52caf 100644
--- a/src/org/geometerplus/zlibrary/core/image/ZLFileImage.java
+++ b/src/org/geometerplus/zlibrary/core/image/ZLFileImage.java
@@ -34,12 +34,19 @@ public class ZLFileImage extends ZLSingleImage {
public static ZLFileImage byUrlPath(String urlPath) {
try {
final String[] data = urlPath.split("\000");
+ int count = Integer.parseInt(data[2]);
+ int[] offsets = new int[count];
+ int[] lengths = new int[count];
+ for (int i = 0; i < count; ++i) {
+ offsets[i] = Integer.parseInt(data[3 + i]);
+ lengths[i] = Integer.parseInt(data[3 + count + i]);
+ }
return new ZLFileImage(
MimeType.IMAGE_AUTO,
ZLFile.createFileByPath(data[0]),
data[1],
- Integer.parseInt(data[2]),
- Integer.parseInt(data[3])
+ offsets,
+ lengths
);
} catch (Exception e) {
e.printStackTrace();
@@ -49,19 +56,33 @@ public class ZLFileImage extends ZLSingleImage {
private final ZLFile myFile;
private final String myEncoding;
- private final int myOffset;
- private final int myLength;
+ private final int[] myOffsets;
+ private final int[] myLengths;
+
+ public ZLFileImage(String mimeType, ZLFile file, String encoding, int[] offsets, int[] lengths) {
+ this(MimeType.get(mimeType), file, encoding, offsets, lengths);
+ }
+
+ public ZLFileImage(MimeType mimeType, ZLFile file, String encoding, int[] offsets, int[] lengths) {
+ super(mimeType);
+ myFile = file;
+ myEncoding = encoding != null ? encoding : ENCODING_NONE;
+ myOffsets = offsets;
+ myLengths = lengths;
+ }
public ZLFileImage(String mimeType, ZLFile file, String encoding, int offset, int length) {
this(MimeType.get(mimeType), file, encoding, offset, length);
}
public ZLFileImage(MimeType mimeType, ZLFile file, String encoding, int offset, int length) {
- super(mimeType);
- myFile = file;
- myEncoding = encoding != null ? encoding : ENCODING_NONE;
- myOffset = offset;
- myLength = length;
+ super(mimeType);
+ myFile = file;
+ myEncoding = encoding != null ? encoding : ENCODING_NONE;
+ myOffsets = new int[1];
+ myLengths = new int[1];
+ myOffsets[0] = offset;
+ myLengths[0] = length;
}
public ZLFileImage(MimeType mimeType, ZLFile file) {
@@ -69,15 +90,34 @@ public class ZLFileImage extends ZLSingleImage {
}
public String getURI() {
- return SCHEME + "://" + myFile.getPath() + "\000" + myEncoding + "\000" + myOffset + "\000" + myLength;
+ String result = SCHEME + "://" + myFile.getPath() + "\000" + myEncoding + "\000" + myOffsets.length;
+ for (int offset : myOffsets) {
+ result += "\000" + offset;
+ }
+ for (int length : myLengths) {
+ result += "\000" + length;
+ }
+ return result;
}
@Override
public InputStream inputStream() {
try {
- final InputStream stream =
- new SliceInputStream(myFile.getInputStream(), myOffset, myLength != 0 ? myLength : Integer.MAX_VALUE);
- if (ENCODING_NONE.equals(myEncoding)) {
+ final InputStream stream;
+ if (myOffsets.length == 1) {
+ final int offset = myOffsets[0];
+ final int length = myLengths[0];
+ stream = new SliceInputStream(myFile.getInputStream(), offset, length != 0 ? length : Integer.MAX_VALUE);
+ } else {
+ final InputStream[] streams = new InputStream[myOffsets.length];
+ for (int i = 0; i < myOffsets.length; ++i) {
+ final int offset = myOffsets[i];
+ final int length = myLengths[i];
+ streams[i] = new SliceInputStream(myFile.getInputStream(), offset, length != 0 ? length : Integer.MAX_VALUE);
+ }
+ stream = new MergedInputStream(streams);
+ }
+ if (ENCODING_NONE.equals(myEncoding)) {
return stream;
} else if (ENCODING_HEX.equals(myEncoding)) {
return new HexInputStream(stream);
diff --git a/src/org/geometerplus/zlibrary/core/util/MergedInputStream.java b/src/org/geometerplus/zlibrary/core/util/MergedInputStream.java
new file mode 100644
index 000000000..f7185f190
--- /dev/null
+++ b/src/org/geometerplus/zlibrary/core/util/MergedInputStream.java
@@ -0,0 +1,107 @@
+/*
+ * 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.zlibrary.core.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class MergedInputStream extends InputStream {
+ private final InputStream[] myStreams;
+ private InputStream myCurrentStream;
+ private int myCurrentStreamNumber;
+
+ public MergedInputStream(InputStream[] streams) throws IOException {
+ myStreams = streams;
+ myCurrentStream = streams[0];
+ myCurrentStreamNumber = 0;
+ }
+
+ @Override
+ public int read() throws IOException {
+ int readed = -1;
+ boolean streamIsAvailable = true;
+ while (readed == -1 && streamIsAvailable) {
+ readed = myCurrentStream.read();
+ if (readed == -1) {
+ streamIsAvailable = nextStream();
+ }
+ }
+ return readed;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ int bytesToRead = len;
+ int bytesReaded = 0;
+ boolean streamIsAvailable = true;
+ while (bytesToRead > 0 && streamIsAvailable) {
+ int readed = myCurrentStream.read(b, off, bytesToRead);
+ if (readed != -1) {
+ bytesToRead -= readed;
+ off += readed;
+ bytesReaded += readed;
+ }
+ if (bytesToRead != 0) {
+ streamIsAvailable = nextStream();
+ }
+ }
+ return bytesReaded == 0 ? -1 : bytesReaded;
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ long skipped = myCurrentStream.skip(n);
+ boolean streamIsAvailable = true;
+ while (skipped < n && streamIsAvailable) {
+ streamIsAvailable = nextStream();
+ if (streamIsAvailable) {
+ skipped += myCurrentStream.skip(n - skipped);
+ }
+ }
+ return skipped;
+ }
+
+ @Override
+ public int available() throws IOException {
+ int total = 0;
+ for (int i = myCurrentStreamNumber; i < myStreams.length; ++i) {
+ total += myStreams[i].available();
+ }
+ return total;
+ }
+
+ @Override
+ public void reset() throws IOException {
+ myCurrentStream = myStreams[0];
+ myCurrentStreamNumber = 0;
+ for (InputStream stream : myStreams) {
+ stream.reset();
+ }
+ }
+
+ private boolean nextStream() {
+ if (myCurrentStreamNumber + 1 >= myStreams.length) {
+ return false;
+ }
+ ++myCurrentStreamNumber;
+ myCurrentStream = myStreams[myCurrentStreamNumber];
+ return true;
+ }
+}