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; + } +}