1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-03 17:59:33 +02:00

synchronization with native branch

This commit is contained in:
Nikolay Pultsin 2012-03-01 23:54:47 +00:00
parent a6e4699d33
commit 80ab1a798d
37 changed files with 3533 additions and 3 deletions

View file

@ -76,15 +76,27 @@ LOCAL_SRC_FILES := \
NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileInputStream.cpp \ NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileInputStream.cpp \
NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileOutputStream.cpp \ NativeFormats/zlibrary/core/src/unix/filesystem/ZLUnixFileOutputStream.cpp \
NativeFormats/zlibrary/core/src/unix/library/ZLUnixLibrary.cpp \ NativeFormats/zlibrary/core/src/unix/library/ZLUnixLibrary.cpp \
NativeFormats/zlibrary/text/src/model/ZLCachedMemoryAllocator.cpp \
NativeFormats/zlibrary/text/src/model/ZLImageMapWriter.cpp \
NativeFormats/zlibrary/text/src/model/ZLTextModel.cpp \
NativeFormats/zlibrary/text/src/model/ZLTextParagraph.cpp \
NativeFormats/zlibrary/ui/src/android/filesystem/JavaFSDir.cpp \ NativeFormats/zlibrary/ui/src/android/filesystem/JavaFSDir.cpp \
NativeFormats/zlibrary/ui/src/android/filesystem/JavaInputStream.cpp \ NativeFormats/zlibrary/ui/src/android/filesystem/JavaInputStream.cpp \
NativeFormats/zlibrary/ui/src/android/filesystem/ZLAndroidFSManager.cpp \ NativeFormats/zlibrary/ui/src/android/filesystem/ZLAndroidFSManager.cpp \
NativeFormats/zlibrary/ui/src/android/library/ZLAndroidLibraryImplementation.cpp \ NativeFormats/zlibrary/ui/src/android/library/ZLAndroidLibraryImplementation.cpp \
NativeFormats/fbreader/src/bookmodel/BookModel.cpp \
NativeFormats/fbreader/src/bookmodel/BookReader.cpp \
NativeFormats/fbreader/src/formats/EncodedTextReader.cpp \
NativeFormats/fbreader/src/formats/FormatPlugin.cpp \ NativeFormats/fbreader/src/formats/FormatPlugin.cpp \
NativeFormats/fbreader/src/formats/PluginCollection.cpp \ NativeFormats/fbreader/src/formats/PluginCollection.cpp \
NativeFormats/fbreader/src/formats/txt/PlainTextFormat.cpp \
NativeFormats/fbreader/src/formats/txt/TxtBookReader.cpp \
NativeFormats/fbreader/src/formats/txt/TxtPlugin.cpp \
NativeFormats/fbreader/src/formats/txt/TxtReader.cpp \
NativeFormats/fbreader/src/library/Author.cpp \ NativeFormats/fbreader/src/library/Author.cpp \
NativeFormats/fbreader/src/library/Book.cpp \ NativeFormats/fbreader/src/library/Book.cpp \
NativeFormats/fbreader/src/library/Comparators.cpp \ NativeFormats/fbreader/src/library/Comparators.cpp \
NativeFormats/fbreader/src/library/Library.cpp \
NativeFormats/fbreader/src/library/Tag.cpp NativeFormats/fbreader/src/library/Tag.cpp
LOCAL_C_INCLUDES := \ LOCAL_C_INCLUDES := \
@ -96,6 +108,7 @@ LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/NativeFormats/zlibrary/core/src/library \ $(LOCAL_PATH)/NativeFormats/zlibrary/core/src/library \
$(LOCAL_PATH)/NativeFormats/zlibrary/core/src/logger \ $(LOCAL_PATH)/NativeFormats/zlibrary/core/src/logger \
$(LOCAL_PATH)/NativeFormats/zlibrary/core/src/util \ $(LOCAL_PATH)/NativeFormats/zlibrary/core/src/util \
$(LOCAL_PATH)/NativeFormats/zlibrary/core/src/xml $(LOCAL_PATH)/NativeFormats/zlibrary/core/src/xml \
$(LOCAL_PATH)/NativeFormats/zlibrary/text/src/model
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

View file

@ -0,0 +1,84 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 <ZLImage.h>
#include <ZLFile.h>
#include "BookModel.h"
#include "BookReader.h"
#include "../formats/FormatPlugin.h"
#include "../library/Book.h"
#include "../library/Library.h"
BookModel::BookModel(const shared_ptr<Book> book) : myBook(book) {
const std::string cacheDirectory = Library::Instance().cacheDirectory();
myImagesWriter = new ZLImageMapWriter(131072, cacheDirectory, "nimages");
myBookTextModel = new ZLTextPlainModel(std::string(), book->language(), 131072, cacheDirectory, "ncache");
myContentsModel = new ContentsModel(book->language(), cacheDirectory, "ncontents");
/*shared_ptr<FormatPlugin> plugin = PluginCollection::Instance().plugin(book->file(), false);
if (!plugin.isNull()) {
plugin->readModel(*this);
}*/
}
BookModel::~BookModel() {
}
void BookModel::setHyperlinkMatcher(shared_ptr<HyperlinkMatcher> matcher) {
myHyperlinkMatcher = matcher;
}
BookModel::Label BookModel::label(const std::string &id) const {
if (!myHyperlinkMatcher.isNull()) {
return myHyperlinkMatcher->match(myInternalHyperlinks, id);
}
std::map<std::string,Label>::const_iterator it = myInternalHyperlinks.find(id);
return (it != myInternalHyperlinks.end()) ? it->second : Label(0, -1);
}
ContentsModel::ContentsModel(const std::string &language,
const std::string &directoryName, const std::string &fileExtension) :
ZLTextTreeModel(std::string(), language, directoryName, fileExtension) {
}
void ContentsModel::setReference(const ZLTextTreeParagraph *paragraph, int reference) {
myReferenceByParagraph[paragraph] = reference;
}
int ContentsModel::reference(const ZLTextTreeParagraph *paragraph) const {
std::map<const ZLTextTreeParagraph*,int>::const_iterator it = myReferenceByParagraph.find(paragraph);
return (it != myReferenceByParagraph.end()) ? it->second : -1;
}
const shared_ptr<Book> BookModel::book() const {
return myBook;
}
void BookModel::flush() {
myBookTextModel->flush();
myContentsModel->flush();
myImagesWriter->flush();
std::map<std::string,shared_ptr<ZLTextModel> >::const_iterator it = myFootnotes.begin();
for (; it != myFootnotes.end(); ++it) {
it->second->flush();
}
}

View file

@ -0,0 +1,99 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __BOOKMODEL_H__
#define __BOOKMODEL_H__
#include <map>
#include <string>
#include <ZLTextModel.h>
#include <ZLTextParagraph.h>
#include <ZLUserData.h>
#include <ZLImageMapWriter.h>
class ZLImage;
class Book;
class ContentsModel : public ZLTextTreeModel {
public:
ContentsModel(const std::string &language, const std::string &directoryName, const std::string &fileExtension);
void setReference(const ZLTextTreeParagraph *paragraph, int reference);
int reference(const ZLTextTreeParagraph *paragraph) const;
private:
std::map<const ZLTextTreeParagraph*,int> myReferenceByParagraph;
};
class BookModel : public ZLUserDataHolder {
public:
struct Label {
Label(shared_ptr<ZLTextModel> model, int paragraphNumber) : Model(model), ParagraphNumber(paragraphNumber) {}
const shared_ptr<ZLTextModel> Model;
const int ParagraphNumber;
};
public:
class HyperlinkMatcher {
public:
virtual Label match(const std::map<std::string,Label> &lMap, const std::string &id) const = 0;
};
public:
BookModel(const shared_ptr<Book> book);
~BookModel();
void setHyperlinkMatcher(shared_ptr<HyperlinkMatcher> matcher);
shared_ptr<ZLTextModel> bookTextModel() const;
shared_ptr<ZLTextModel> contentsModel() const;
const std::map<std::string,shared_ptr<ZLTextModel> > &footnotes() const;
shared_ptr<ZLImageMapWriter> imageMapWriter() const;
Label label(const std::string &id) const;
const std::map<std::string,Label> &internalHyperlinks() const;
const shared_ptr<Book> book() const;
void flush();
private:
const shared_ptr<Book> myBook;
shared_ptr<ZLTextModel> myBookTextModel;
shared_ptr<ZLTextModel> myContentsModel;
shared_ptr<ZLImageMapWriter> myImagesWriter;
std::map<std::string,shared_ptr<ZLTextModel> > myFootnotes;
std::map<std::string,Label> myInternalHyperlinks;
shared_ptr<HyperlinkMatcher> myHyperlinkMatcher;
friend class BookReader;
};
inline shared_ptr<ZLTextModel> BookModel::bookTextModel() const { return myBookTextModel; }
inline shared_ptr<ZLTextModel> BookModel::contentsModel() const { return myContentsModel; }
inline const std::map<std::string,shared_ptr<ZLTextModel> > &BookModel::footnotes() const { return myFootnotes; }
inline shared_ptr<ZLImageMapWriter> BookModel::imageMapWriter() const { return myImagesWriter; }
inline const std::map<std::string,BookModel::Label> &BookModel::internalHyperlinks() const { return myInternalHyperlinks; }
#endif /* __BOOKMODEL_H__ */

View file

@ -0,0 +1,284 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 <ZLImage.h>
#include <ZLLogger.h>
#include "BookReader.h"
#include "BookModel.h"
#include "../library/Book.h"
#include "../library/Library.h"
BookReader::BookReader(BookModel &model) : myModel(model) {
myCurrentTextModel = 0;
myLastTOCParagraphIsEmpty = false;
myTextParagraphExists = false;
myContentsParagraphExists = false;
myInsideTitle = false;
mySectionContainsRegularContents = false;
}
BookReader::~BookReader() {
}
void BookReader::setMainTextModel() {
myCurrentTextModel = myModel.myBookTextModel;
}
void BookReader::setFootnoteTextModel(const std::string &id) {
std::map<std::string,shared_ptr<ZLTextModel> >::iterator it = myModel.myFootnotes.find(id);
if (it != myModel.myFootnotes.end()) {
myCurrentTextModel = (*it).second;
} else {
myCurrentTextModel = new ZLTextPlainModel(id, myModel.myBookTextModel->language(), 8192,
Library::Instance().cacheDirectory(), "nfootnote_id=" + id);
myModel.myFootnotes.insert(std::make_pair(id, myCurrentTextModel));
}
}
void BookReader::unsetTextModel() {
myCurrentTextModel = 0;
}
void BookReader::pushKind(FBTextKind kind) {
myKindStack.push_back(kind);
}
bool BookReader::popKind() {
if (!myKindStack.empty()) {
myKindStack.pop_back();
return true;
}
return false;
}
bool BookReader::isKindStackEmpty() const {
return myKindStack.empty();
}
void BookReader::beginParagraph(ZLTextParagraph::Kind kind) {
if (myCurrentTextModel != 0) {
((ZLTextPlainModel&)*myCurrentTextModel).createParagraph(kind);
for (std::vector<FBTextKind>::const_iterator it = myKindStack.begin(); it != myKindStack.end(); ++it) {
myCurrentTextModel->addControl(*it, true);
}
if (!myHyperlinkReference.empty()) {
myCurrentTextModel->addHyperlinkControl(myHyperlinkKind, myHyperlinkType, myHyperlinkReference);
}
myTextParagraphExists = true;
}
}
void BookReader::endParagraph() {
if (myTextParagraphExists) {
flushTextBufferToParagraph();
myTextParagraphExists = false;
}
}
void BookReader::addControl(FBTextKind kind, bool start) {
if (myTextParagraphExists) {
flushTextBufferToParagraph();
myCurrentTextModel->addControl(kind, start);
}
if (!start && !myHyperlinkReference.empty() && (kind == myHyperlinkKind)) {
myHyperlinkReference.erase();
}
}
void BookReader::addControl(const ZLTextStyleEntry &entry) {
if (myTextParagraphExists) {
flushTextBufferToParagraph();
myCurrentTextModel->addControl(entry);
}
}
void BookReader::addFixedHSpace(unsigned char length) {
if (myTextParagraphExists) {
myCurrentTextModel->addFixedHSpace(length);
}
}
void BookReader::addHyperlinkControl(FBTextKind kind, const std::string &label) {
myHyperlinkKind = kind;
std::string type;
switch (myHyperlinkKind) {
case INTERNAL_HYPERLINK:
case FOOTNOTE:
myHyperlinkType = HYPERLINK_INTERNAL;
type = "internal";
break;
case EXTERNAL_HYPERLINK:
myHyperlinkType = HYPERLINK_EXTERNAL;
type = "external";
break;
/*case BOOK_HYPERLINK:
myHyperlinkType = HYPERLINK_BOOK;
type = "book";
break;*/
default:
myHyperlinkType = HYPERLINK_NONE;
break;
}
ZLLogger::Instance().println(
"hyperlink",
" + control (" + type + "): " + label
);
if (myTextParagraphExists) {
flushTextBufferToParagraph();
myCurrentTextModel->addHyperlinkControl(kind, myHyperlinkType, label);
}
myHyperlinkReference = label;
}
void BookReader::addHyperlinkLabel(const std::string &label) {
if (!myCurrentTextModel.isNull()) {
int paragraphNumber = myCurrentTextModel->paragraphsNumber();
if (myTextParagraphExists) {
--paragraphNumber;
}
addHyperlinkLabel(label, paragraphNumber);
}
}
void BookReader::addHyperlinkLabel(const std::string &label, int paragraphNumber) {
ZLLogger::Instance().println(
"hyperlink",
" + label: " + label
);
myModel.myInternalHyperlinks.insert(std::make_pair(
label, BookModel::Label(myCurrentTextModel, paragraphNumber)
));
}
void BookReader::addData(const std::string &data) {
if (!data.empty() && myTextParagraphExists) {
if (!myInsideTitle) {
mySectionContainsRegularContents = true;
}
myBuffer.push_back(data);
}
}
void BookReader::addContentsData(const std::string &data) {
if (!data.empty() && !myTOCStack.empty()) {
myContentsBuffer.push_back(data);
}
}
void BookReader::flushTextBufferToParagraph() {
myCurrentTextModel->addText(myBuffer);
myBuffer.clear();
}
void BookReader::addImage(const std::string &id, shared_ptr<const ZLImage> image) {
if (!image.isNull()) {
myModel.myImagesWriter->addImage(id, *image);
}
}
void BookReader::insertEndParagraph(ZLTextParagraph::Kind kind) {
if ((myCurrentTextModel != 0) && mySectionContainsRegularContents) {
size_t size = myCurrentTextModel->paragraphsNumber();
if ((size > 0) && (((*myCurrentTextModel)[(size_t)-1])->kind() != kind)) {
((ZLTextPlainModel&)*myCurrentTextModel).createParagraph(kind);
mySectionContainsRegularContents = false;
}
}
}
void BookReader::insertEndOfSectionParagraph() {
insertEndParagraph(ZLTextParagraph::END_OF_SECTION_PARAGRAPH);
}
void BookReader::insertEndOfTextParagraph() {
insertEndParagraph(ZLTextParagraph::END_OF_TEXT_PARAGRAPH);
}
void BookReader::addImageReference(const std::string &id, short vOffset) {
if (myCurrentTextModel != 0) {
mySectionContainsRegularContents = true;
if (myTextParagraphExists) {
flushTextBufferToParagraph();
myCurrentTextModel->addImage(id, vOffset);
} else {
beginParagraph();
myCurrentTextModel->addControl(IMAGE, true);
myCurrentTextModel->addImage(id, vOffset);
myCurrentTextModel->addControl(IMAGE, false);
endParagraph();
}
}
}
void BookReader::beginContentsParagraph(int referenceNumber) {
if (myCurrentTextModel == myModel.myBookTextModel) {
ContentsModel &contentsModel = (ContentsModel&)*myModel.myContentsModel;
if (referenceNumber == -1) {
referenceNumber = myCurrentTextModel->paragraphsNumber();
}
ZLTextTreeParagraph *peek = myTOCStack.empty() ? 0 : myTOCStack.top();
if (!myContentsBuffer.empty()) {
contentsModel.addText(myContentsBuffer);
myContentsBuffer.clear();
myLastTOCParagraphIsEmpty = false;
}
if (myLastTOCParagraphIsEmpty) {
contentsModel.addText("...");
}
ZLTextTreeParagraph *para = contentsModel.createParagraph(peek);
contentsModel.addControl(CONTENTS_TABLE_ENTRY, true);
contentsModel.setReference(para, referenceNumber);
myTOCStack.push(para);
myLastTOCParagraphIsEmpty = true;
myContentsParagraphExists = true;
}
}
void BookReader::endContentsParagraph() {
if (!myTOCStack.empty()) {
ContentsModel &contentsModel = (ContentsModel&)*myModel.myContentsModel;
if (!myContentsBuffer.empty()) {
contentsModel.addText(myContentsBuffer);
myContentsBuffer.clear();
myLastTOCParagraphIsEmpty = false;
}
if (myLastTOCParagraphIsEmpty) {
contentsModel.addText("...");
myLastTOCParagraphIsEmpty = false;
}
myTOCStack.pop();
}
myContentsParagraphExists = false;
}
void BookReader::setReference(size_t contentsParagraphNumber, int referenceNumber) {
ContentsModel &contentsModel = (ContentsModel&)*myModel.myContentsModel;
if (contentsParagraphNumber >= contentsModel.paragraphsNumber()) {
return;
}
contentsModel.setReference((const ZLTextTreeParagraph*)contentsModel[contentsParagraphNumber], referenceNumber);
}
void BookReader::reset() {
myKindStack.clear();
}

View file

@ -0,0 +1,115 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __BOOKREADER_H__
#define __BOOKREADER_H__
#include <vector>
#include <stack>
#include <string>
#include <ZLTextParagraph.h>
#include "FBHyperlinkType.h"
#include "FBTextKind.h"
class BookModel;
class ZLTextModel;
class ZLInputStream;
class BookReader {
public:
BookReader(BookModel &model);
virtual ~BookReader();
void setMainTextModel();
void setFootnoteTextModel(const std::string &id);
void unsetTextModel();
void insertEndOfSectionParagraph();
void insertEndOfTextParagraph();
void pushKind(FBTextKind kind);
bool popKind();
bool isKindStackEmpty() const;
void beginParagraph(ZLTextParagraph::Kind kind = ZLTextParagraph::TEXT_PARAGRAPH);
void endParagraph();
bool paragraphIsOpen() const;
void addControl(FBTextKind kind, bool start);
void addControl(const ZLTextStyleEntry &entry);
void addHyperlinkControl(FBTextKind kind, const std::string &label);
void addHyperlinkLabel(const std::string &label);
void addHyperlinkLabel(const std::string &label, int paragraphNumber);
void addFixedHSpace(unsigned char length);
void addImageReference(const std::string &id, short vOffset = 0);
void addImage(const std::string &id, shared_ptr<const ZLImage> image);
void beginContentsParagraph(int referenceNumber = -1);
void endContentsParagraph();
bool contentsParagraphIsOpen() const;
void setReference(size_t contentsParagraphNumber, int referenceNumber);
void addData(const std::string &data);
void addContentsData(const std::string &data);
void enterTitle() { myInsideTitle = true; }
void exitTitle() { myInsideTitle = false; }
const BookModel &model() const { return myModel; }
void reset();
private:
void insertEndParagraph(ZLTextParagraph::Kind kind);
void flushTextBufferToParagraph();
private:
BookModel &myModel;
shared_ptr<ZLTextModel> myCurrentTextModel;
std::vector<FBTextKind> myKindStack;
bool myTextParagraphExists;
bool myContentsParagraphExists;
std::stack<ZLTextTreeParagraph*> myTOCStack;
bool myLastTOCParagraphIsEmpty;
bool mySectionContainsRegularContents;
bool myInsideTitle;
std::vector<std::string> myBuffer;
std::vector<std::string> myContentsBuffer;
std::string myHyperlinkReference;
FBHyperlinkType myHyperlinkType;
FBTextKind myHyperlinkKind;
};
inline bool BookReader::paragraphIsOpen() const {
return myTextParagraphExists;
}
inline bool BookReader::contentsParagraphIsOpen() const {
return myContentsParagraphExists;
}
#endif /* __BOOKREADER_H__ */

View file

@ -0,0 +1,30 @@
/*
* Copyright (C) 2011-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __FBHYPERLINKTYPE_H__
#define __FBHYPERLINKTYPE_H__
enum FBHyperlinkType {
HYPERLINK_NONE = 0,
HYPERLINK_INTERNAL = 1,
HYPERLINK_EXTERNAL = 2,
//HYPERLINK_BOOK = 3,
};
#endif /* __FBHYPERLINKTYPE_H__ */

View file

@ -0,0 +1,70 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __FBTEXTKIND_H__
#define __FBTEXTKIND_H__
enum FBTextKind {
// please, don't change these numbers
// add new text kinds at end of this enumeration
//
// all the values MUST be in the range 0..127
REGULAR = 0,
TITLE = 1,
SECTION_TITLE = 2,
POEM_TITLE = 3,
SUBTITLE = 4,
ANNOTATION = 5,
EPIGRAPH = 6,
STANZA = 7,
VERSE = 8,
PREFORMATTED = 9,
IMAGE = 10,
END_OF_SECTION = 11,
CITE = 12,
AUTHOR = 13,
DATEKIND = 14,
INTERNAL_HYPERLINK = 15,
FOOTNOTE = 16,
EMPHASIS = 17,
STRONG = 18,
SUB = 19,
SUP = 20,
CODE = 21,
STRIKETHROUGH = 22,
CONTENTS_TABLE_ENTRY = 23,
//LIBRARY_AUTHOR_ENTRY = 24,
//LIBRARY_BOOK_ENTRY = 25,
LIBRARY_ENTRY = 25,
//RECENT_BOOK_LIST = 26,
ITALIC = 27,
BOLD = 28,
DEFINITION = 29,
DEFINITION_DESCRIPTION = 30,
H1 = 31,
H2 = 32,
H3 = 33,
H4 = 34,
H5 = 35,
H6 = 36,
EXTERNAL_HYPERLINK = 37,
//BOOK_HYPERLINK = 38,
};
#endif /* __FBTEXTKIND_H__ */

View file

@ -0,0 +1,29 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 "EncodedTextReader.h"
EncodedTextReader::EncodedTextReader(const std::string &encoding) {
ZLEncodingCollection &collection = ZLEncodingCollection::Instance();
ZLEncodingConverterInfoPtr info = collection.info(encoding);
myConverter = (!info.isNull()) ? info->createConverter() : collection.defaultConverter();
}
EncodedTextReader::~EncodedTextReader() {
}

View file

@ -0,0 +1,37 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __ENCODEDTEXTREADER_H__
#define __ENCODEDTEXTREADER_H__
#include <string>
#include <ZLEncodingConverter.h>
class EncodedTextReader {
protected:
EncodedTextReader(const std::string &encoding);
virtual ~EncodedTextReader();
protected:
shared_ptr<ZLEncodingConverter> myConverter;
};
#endif /* __ENCODEDTEXTREADER_H__ */

View file

@ -29,7 +29,7 @@
//#include "fb2/FB2Plugin.h" //#include "fb2/FB2Plugin.h"
////#include "docbook/DocBookPlugin.h" ////#include "docbook/DocBookPlugin.h"
//#include "html/HtmlPlugin.h" //#include "html/HtmlPlugin.h"
//#include "txt/TxtPlugin.h" #include "txt/TxtPlugin.h"
//#include "pdb/PdbPlugin.h" //#include "pdb/PdbPlugin.h"
//#include "tcr/TcrPlugin.h" //#include "tcr/TcrPlugin.h"
//#include "oeb/OEBPlugin.h" //#include "oeb/OEBPlugin.h"
@ -46,7 +46,7 @@ PluginCollection &PluginCollection::Instance() {
//ourInstance->myPlugins.push_back(new FB2Plugin()); //ourInstance->myPlugins.push_back(new FB2Plugin());
// //ourInstance->myPlugins.push_back(new DocBookPlugin()); // //ourInstance->myPlugins.push_back(new DocBookPlugin());
//ourInstance->myPlugins.push_back(new HtmlPlugin()); //ourInstance->myPlugins.push_back(new HtmlPlugin());
//ourInstance->myPlugins.push_back(new TxtPlugin()); ourInstance->myPlugins.push_back(new TxtPlugin());
// ourInstance->myPlugins.push_back(new PluckerPlugin()); // ourInstance->myPlugins.push_back(new PluckerPlugin());
// ourInstance->myPlugins.push_back(new PalmDocPlugin()); // ourInstance->myPlugins.push_back(new PalmDocPlugin());
// ourInstance->myPlugins.push_back(new MobipocketPlugin()); // ourInstance->myPlugins.push_back(new MobipocketPlugin());

View file

@ -0,0 +1,258 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 <cctype>
#include <algorithm>
//#include <ZLOptions.h>
//#include <ZLOptionsDialog.h>
//#include <ZLOptionEntry.h>
#include <ZLFile.h>
#include "PlainTextFormat.h"
//#include "../../options/FBCategoryKey.h"
const std::string OPTION_Initialized = "Initialized";
const std::string OPTION_BreakType = "BreakType";
const std::string OPTION_IgnoredIndent = "IgnoredIndent";
const std::string OPTION_EmptyLinesBeforeNewSection = "EmptyLinesBeforeNewSection";
const std::string OPTION_CreateContentsTable = "CreateContentsTable";
PlainTextFormat::PlainTextFormat(const ZLFile &file) :
// InitializedOption(FBCategoryKey::BOOKS, file.path(), OPTION_Initialized, false),
// BreakTypeOption(FBCategoryKey::BOOKS, file.path(), OPTION_BreakType, 1),
// IgnoredIndentOption(FBCategoryKey::BOOKS, file.path(), OPTION_IgnoredIndent, 1, 100, 1),
// EmptyLinesBeforeNewSectionOption(FBCategoryKey::BOOKS, file.path(), OPTION_EmptyLinesBeforeNewSection, 1, 100, 1),
// CreateContentsTableOption(FBCategoryKey::BOOKS, file.path(), OPTION_CreateContentsTable, false) {
myInitialized(false),
myBreakType(1),
myIgnoredIndent(1),
myEmptyLinesBeforeNewSection(1),
myCreateContentsTable(false) {
}
/*PlainTextInfoPage::PlainTextInfoPage(ZLOptionsDialog &dialog, const ZLFile &file, const ZLResourceKey &key, bool showContentsEntry) : myFormat(file) {
if (!myFormat.initialized()) {
PlainTextFormatDetector detector;
shared_ptr<ZLInputStream> stream = file.inputStream();
if (!stream.isNull()) {
detector.detect(*stream, myFormat);
}
}
ZLDialogContent &tab = dialog.createTab(key);
BreakTypeOptionEntry *breakEntry = new BreakTypeOptionEntry(*this, myFormat.BreakTypeOption);
myIgnoredIndentEntry = new ZLSimpleSpinOptionEntry(myFormat.IgnoredIndentOption, 1);
tab.addOption(ZLResourceKey("breakType"), breakEntry);
tab.addOption(ZLResourceKey("ignoreIndent"), myIgnoredIndentEntry);
breakEntry->onValueSelected(breakEntry->initialIndex());
if (showContentsEntry) {
CreateContentsTableOptionEntry *contentsTableEntry = new CreateContentsTableOptionEntry(*this, myFormat.CreateContentsTableOption);
myEmptyLinesBeforeNewSectionEntry = new ZLSimpleSpinOptionEntry(myFormat.EmptyLinesBeforeNewSectionOption, 1);
tab.addOption(ZLResourceKey("buildTOC"), contentsTableEntry);
tab.addOption(ZLResourceKey("emptyLines"), myEmptyLinesBeforeNewSectionEntry);
contentsTableEntry->onStateChanged(contentsTableEntry->initialState());
}
}*/
/*PlainTextInfoPage::~PlainTextInfoPage() {
}*/
const int BUFFER_SIZE = 4096;
void PlainTextFormatDetector::detect(ZLInputStream &stream, PlainTextFormat &format) {
if (!stream.open()) {
return;
}
const unsigned int tableSize = 10;
unsigned int lineCounter = 0;
int emptyLineCounter = -1;
unsigned int stringsWithLengthLessThan81Counter = 0;
unsigned int stringIndentTable[tableSize] = { 0 };
unsigned int emptyLinesTable[tableSize] = { 0 };
unsigned int emptyLinesBeforeShortStringTable[tableSize] = { 0 };
bool currentLineIsEmpty = true;
unsigned int currentLineLength = 0;
unsigned int currentLineIndent = 0;
int currentNumberOfEmptyLines = -1;
char *buffer = new char[BUFFER_SIZE];
int length;
char previous = 0;
do {
length = stream.read(buffer, BUFFER_SIZE);
const char *end = buffer + length;
for (const char *ptr = buffer; ptr != end; ++ptr) {
++currentLineLength;
if (*ptr == '\n') {
++lineCounter;
if (currentLineIsEmpty) {
++emptyLineCounter;
++currentNumberOfEmptyLines;
} else {
if (currentNumberOfEmptyLines >= 0) {
int index = std::min(currentNumberOfEmptyLines, (int)tableSize - 1);
emptyLinesTable[index]++;
if (currentLineLength < 51) {
emptyLinesBeforeShortStringTable[index]++;
}
}
currentNumberOfEmptyLines = -1;
}
if (currentLineLength < 81) {
++stringsWithLengthLessThan81Counter;
}
if (!currentLineIsEmpty) {
stringIndentTable[std::min(currentLineIndent, tableSize - 1)]++;
}
currentLineIsEmpty = true;
currentLineLength = 0;
currentLineIndent = 0;
} else if (*ptr == '\r') {
continue;
} else if (isspace((unsigned char)*ptr)) {
if (currentLineIsEmpty) {
++currentLineIndent;
}
} else {
currentLineIsEmpty = false;
}
previous = *ptr;
}
} while (length == BUFFER_SIZE);
delete[] buffer;
unsigned int nonEmptyLineCounter = lineCounter - emptyLineCounter;
{
unsigned int indent = 0;
unsigned int lineWithIndent = 0;
for (; indent < tableSize; ++indent) {
lineWithIndent += stringIndentTable[indent];
if (lineWithIndent > 0.1 * nonEmptyLineCounter) {
break;
}
}
format.myIgnoredIndent = (indent + 1);
}
{
int breakType = 0;
breakType |= PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE;
if (stringsWithLengthLessThan81Counter < 0.3 * nonEmptyLineCounter) {
breakType |= PlainTextFormat::BREAK_PARAGRAPH_AT_NEW_LINE;
} else {
breakType |= PlainTextFormat::BREAK_PARAGRAPH_AT_LINE_WITH_INDENT;
}
format.myBreakType = (breakType);
}
{
unsigned int max = 0;
unsigned index;
int emptyLinesBeforeNewSection = -1;
for (index = 2; index < tableSize; ++index) {
if (max < emptyLinesBeforeShortStringTable[index]) {
max = emptyLinesBeforeShortStringTable[index];
emptyLinesBeforeNewSection = index;
}
}
if (emptyLinesBeforeNewSection > 0) {
for (index = tableSize - 1; index > 0; --index) {
emptyLinesTable[index - 1] += emptyLinesTable[index];
emptyLinesBeforeShortStringTable[index - 1] += emptyLinesBeforeShortStringTable[index];
}
for (index = emptyLinesBeforeNewSection; index < tableSize; ++index) {
if ((emptyLinesBeforeShortStringTable[index] > 2) &&
(emptyLinesBeforeShortStringTable[index] > 0.7 * emptyLinesTable[index])) {
break;
}
}
emptyLinesBeforeNewSection = (index == tableSize) ? -1 : (int)index;
}
format.myEmptyLinesBeforeNewSection = (emptyLinesBeforeNewSection);
format.myCreateContentsTable = (emptyLinesBeforeNewSection > 0);
}
format.myInitialized = (true);
}
/*BreakTypeOptionEntry::BreakTypeOptionEntry(PlainTextInfoPage &page, ZLIntegerOption &breakTypeOption) : myPage(page), myBreakTypeOption(breakTypeOption) {
}
BreakTypeOptionEntry::~BreakTypeOptionEntry() {
}
static std::vector<std::string> BREAK_TYPE_VALUES_VECTOR;
int BreakTypeOptionEntry::initialIndex() const {
switch (myBreakTypeOption.value()) {
case PlainTextFormat::BREAK_PARAGRAPH_AT_NEW_LINE:
return 0;
case PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE:
return 1;
case PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE | PlainTextFormat::BREAK_PARAGRAPH_AT_LINE_WITH_INDENT:
default:
return 2;
}
}
const std::string &BreakTypeOptionEntry::initialValue() const {
return values()[initialIndex()];
}
const std::vector<std::string> &BreakTypeOptionEntry::values() const {
if (BREAK_TYPE_VALUES_VECTOR.empty()) {
BREAK_TYPE_VALUES_VECTOR.push_back("New Line");
BREAK_TYPE_VALUES_VECTOR.push_back("Empty Line");
BREAK_TYPE_VALUES_VECTOR.push_back("Line With Indent");
}
return BREAK_TYPE_VALUES_VECTOR;
}
void BreakTypeOptionEntry::onAccept(const std::string &value) {
if (value == values()[0]) {
myBreakTypeOption.setValue(PlainTextFormat::BREAK_PARAGRAPH_AT_NEW_LINE);
} else if (value == values()[1]) {
myBreakTypeOption.setValue(PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE);
} else if (value == values()[2]) {
myBreakTypeOption.setValue(PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE | PlainTextFormat::BREAK_PARAGRAPH_AT_LINE_WITH_INDENT);
}
}
void BreakTypeOptionEntry::onValueSelected(int index) {
myPage.myIgnoredIndentEntry->setVisible(index == 2);
}*/
/*CreateContentsTableOptionEntry::CreateContentsTableOptionEntry(PlainTextInfoPage &page, ZLBooleanOption &option) : ZLSimpleBooleanOptionEntry(option), myPage(page) {
}
CreateContentsTableOptionEntry::~CreateContentsTableOptionEntry() {
}
void CreateContentsTableOptionEntry::onStateChanged(bool state) {
myPage.myEmptyLinesBeforeNewSectionEntry->setVisible(state);
}*/

View file

@ -0,0 +1,118 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __PLAINTEXTFORMAT_H__
#define __PLAINTEXTFORMAT_H__
#include <ZLInputStream.h>
//#include <ZLOptions.h>
//#include <optionEntries/ZLSimpleOptionEntry.h>
//#include <ZLResource.h>
#include "../FormatPlugin.h"
class PlainTextFormat {
public:
enum ParagraphBreakType {
BREAK_PARAGRAPH_AT_NEW_LINE = 1,
BREAK_PARAGRAPH_AT_EMPTY_LINE = 2,
BREAK_PARAGRAPH_AT_LINE_WITH_INDENT = 4,
};
PlainTextFormat(const ZLFile &file);
~PlainTextFormat() {}
bool initialized() const { return myInitialized; }
int breakType() const { return myBreakType; }
int ignoredIndent() const { return myIgnoredIndent; }
int emptyLinesBeforeNewSection() const { return myEmptyLinesBeforeNewSection; }
bool createContentsTable() const { return myCreateContentsTable; }
private:
bool myInitialized;
int myBreakType;
int myIgnoredIndent;
int myEmptyLinesBeforeNewSection;
bool myCreateContentsTable;
// ZLBooleanOption InitializedOption;
// ZLIntegerOption BreakTypeOption;
// ZLIntegerRangeOption IgnoredIndentOption;
// ZLIntegerRangeOption EmptyLinesBeforeNewSectionOption;
// ZLBooleanOption CreateContentsTableOption;
friend class PlainTextInfoPage;
friend class PlainTextFormatDetector;
};
/*class PlainTextInfoPage : public FormatInfoPage {
public:
PlainTextInfoPage(ZLOptionsDialog &dialog, const ZLFile &file, const ZLResourceKey &key, bool showContentsEntry);
~PlainTextInfoPage();
private:
PlainTextFormat myFormat;
ZLSimpleSpinOptionEntry *myIgnoredIndentEntry;
ZLSimpleSpinOptionEntry *myEmptyLinesBeforeNewSectionEntry;
friend class BreakTypeOptionEntry;
friend class CreateContentsTableOptionEntry;
};*/
class PlainTextFormatDetector {
public:
PlainTextFormatDetector() {}
~PlainTextFormatDetector() {}
void detect(ZLInputStream &stream, PlainTextFormat &format);
};
/*class BreakTypeOptionEntry : public ZLComboOptionEntry {
public:
BreakTypeOptionEntry(PlainTextInfoPage &page, ZLIntegerOption &breakTypeOption);
~BreakTypeOptionEntry();
int initialIndex() const;
const std::string &initialValue() const;
const std::vector<std::string> &values() const;
void onAccept(const std::string &value);
void onValueSelected(int index);
private:
PlainTextInfoPage &myPage;
ZLIntegerOption &myBreakTypeOption;
};*/
/*class CreateContentsTableOptionEntry : public ZLSimpleBooleanOptionEntry {
public:
CreateContentsTableOptionEntry(PlainTextInfoPage &page, ZLBooleanOption &option);
~CreateContentsTableOptionEntry();
void onStateChanged(bool state);
private:
PlainTextInfoPage &myPage;
};*/
#endif /* __PLAINTEXTFORMAT_H__ */

View file

@ -0,0 +1,124 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 <cctype>
#include "TxtBookReader.h"
#include "../../bookmodel/BookModel.h"
TxtBookReader::TxtBookReader(BookModel &model, const PlainTextFormat &format, const std::string &encoding) : TxtReader(encoding), BookReader(model), myFormat(format) {
}
void TxtBookReader::internalEndParagraph() {
if (!myLastLineIsEmpty) {
//myLineFeedCounter = 0;
myLineFeedCounter = -1; /* Fixed by Hatred: zero value was break LINE INDENT formater -
second line print with indent like new paragraf */
}
myLastLineIsEmpty = true;
endParagraph();
}
bool TxtBookReader::characterDataHandler(std::string &str) {
const char *ptr = str.data();
const char *end = ptr + str.length();
for (; ptr != end; ++ptr) {
if (isspace((unsigned char)*ptr)) {
if (*ptr != '\t') {
++mySpaceCounter;
} else {
mySpaceCounter += myFormat.ignoredIndent() + 1; // TODO: implement single option in PlainTextFormat
}
} else {
myLastLineIsEmpty = false;
break;
}
}
if (ptr != end) {
if ((myFormat.breakType() & PlainTextFormat::BREAK_PARAGRAPH_AT_LINE_WITH_INDENT) &&
myNewLine && (mySpaceCounter > myFormat.ignoredIndent())) {
internalEndParagraph();
beginParagraph();
}
addData(str);
if (myInsideContentsParagraph) {
addContentsData(str);
}
myNewLine = false;
}
return true;
}
bool TxtBookReader::newLineHandler() {
if (!myLastLineIsEmpty) {
myLineFeedCounter = -1;
}
myLastLineIsEmpty = true;
++myLineFeedCounter;
myNewLine = true;
mySpaceCounter = 0;
bool paragraphBreak =
(myFormat.breakType() & PlainTextFormat::BREAK_PARAGRAPH_AT_NEW_LINE) ||
((myFormat.breakType() & PlainTextFormat::BREAK_PARAGRAPH_AT_EMPTY_LINE) && (myLineFeedCounter > 0));
if (myFormat.createContentsTable()) {
// if (!myInsideContentsParagraph && (myLineFeedCounter == myFormat.emptyLinesBeforeNewSection() + 1)) {
/* Fixed by Hatred: remove '+ 1' for emptyLinesBeforeNewSection, it looks like very strange
when we should point count of empty string decrised by 1 in settings dialog */
if (!myInsideContentsParagraph && (myLineFeedCounter == myFormat.emptyLinesBeforeNewSection())) {
myInsideContentsParagraph = true;
internalEndParagraph();
insertEndOfSectionParagraph();
beginContentsParagraph();
enterTitle();
pushKind(SECTION_TITLE);
beginParagraph();
paragraphBreak = false;
}
if (myInsideContentsParagraph && (myLineFeedCounter == 1)) {
exitTitle();
endContentsParagraph();
popKind();
myInsideContentsParagraph = false;
paragraphBreak = true;
}
}
if (paragraphBreak) {
internalEndParagraph();
beginParagraph();
}
return true;
}
void TxtBookReader::startDocumentHandler() {
setMainTextModel();
pushKind(REGULAR);
beginParagraph();
myLineFeedCounter = 0;
myInsideContentsParagraph = false;
enterTitle();
myLastLineIsEmpty = true;
myNewLine = true;
mySpaceCounter = 0;
}
void TxtBookReader::endDocumentHandler() {
internalEndParagraph();
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __TXTBOOKREADER_H__
#define __TXTBOOKREADER_H__
#include <stack>
#include "TxtReader.h"
#include "PlainTextFormat.h"
#include "../../bookmodel/BookReader.h"
class BookModel;
class TxtBookReader : public TxtReader, public BookReader {
public:
TxtBookReader(BookModel &model, const PlainTextFormat &format, const std::string &encoding);
~TxtBookReader();
protected:
void startDocumentHandler();
void endDocumentHandler();
bool characterDataHandler(std::string &str);
bool newLineHandler();
private:
void internalEndParagraph();
private:
const PlainTextFormat &myFormat;
int myLineFeedCounter;
bool myInsideContentsParagraph;
bool myLastLineIsEmpty;
bool myNewLine;
int mySpaceCounter;
};
inline TxtBookReader::~TxtBookReader() {}
#endif /* __TXTBOOKREADER_H__ */

View file

@ -0,0 +1,74 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 <ZLFile.h>
#include <ZLInputStream.h>
#include "TxtPlugin.h"
#include "TxtBookReader.h"
#include "PlainTextFormat.h"
#include "../../bookmodel/BookModel.h"
#include "../../library/Book.h"
TxtPlugin::~TxtPlugin() {
}
bool TxtPlugin::providesMetaInfo() const {
return false;
}
const std::string TxtPlugin::supportedFileType() const {
return "plain text";
}
bool TxtPlugin::readMetaInfo(Book &book) const {
return true;
}
bool TxtPlugin::readModel(BookModel &model) const {
const Book &book = *model.book();
const ZLFile &file = book.file();
shared_ptr<ZLInputStream> stream = file.inputStream();
if (stream.isNull()) {
return false;
}
PlainTextFormat format(file);
if (!format.initialized()) {
PlainTextFormatDetector detector;
detector.detect(*stream, format);
}
TxtBookReader(model, format, book.encoding()).readDocument(*stream);
return true;
}
//FormatInfoPage *TxtPlugin::createInfoPage(ZLOptionsDialog &dialog, const ZLFile &file) {
// return new PlainTextInfoPage(dialog, file, ZLResourceKey("Text"), true);
//}
bool TxtPlugin::readLanguageAndEncoding(Book &book) const {
shared_ptr<ZLInputStream> stream = book.file().inputStream();
if (stream.isNull()) {
return false;
}
detectEncodingAndLanguage(book, *stream);
return !book.encoding().empty();
}

View file

@ -0,0 +1,37 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __TXTPLUGIN_H__
#define __TXTPLUGIN_H__
#include "../FormatPlugin.h"
class TxtPlugin : public FormatPlugin {
public:
~TxtPlugin();
bool providesMetaInfo() const;
const std::string supportedFileType() const;
bool readMetaInfo(Book &book) const;
bool readLanguageAndEncoding(Book &book) const;
bool readModel(BookModel &model) const;
// FormatInfoPage *createInfoPage(ZLOptionsDialog &dialog, const ZLFile &file);
};
#endif /* __TXTPLUGIN_H__ */

View file

@ -0,0 +1,82 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 <cctype>
#include <ZLInputStream.h>
#include "TxtReader.h"
TxtReader::TxtReader(const std::string &encoding) : EncodedTextReader(encoding) {
}
TxtReader::~TxtReader() {
}
void TxtReader::readDocument(ZLInputStream &stream) {
if (!stream.open()) {
return;
}
startDocumentHandler();
const size_t BUFSIZE = 2048;
char *buffer = new char[BUFSIZE];
std::string str;
size_t length;
do {
length = stream.read(buffer, BUFSIZE);
char *start = buffer;
const char *end = buffer + length;
for (char *ptr = start; ptr != end; ++ptr) {
if (*ptr == '\n' || *ptr == '\r') {
bool skipNewLine = false;
if (*ptr == '\r' && (ptr + 1) != end && *(ptr + 1) == '\n') {
skipNewLine = true;
*ptr = '\n';
}
if (start != ptr) {
str.erase();
myConverter->convert(str, start, ptr + 1);
characterDataHandler(str);
}
if (skipNewLine) {
++ptr;
}
start = ptr + 1;
newLineHandler();
} else if (isspace((unsigned char)*ptr)) {
if (*ptr != '\t') {
*ptr = ' ';
}
} else {
}
}
if (start != end) {
str.erase();
myConverter->convert(str, start, end);
characterDataHandler(str);
}
} while (length == BUFSIZE);
delete[] buffer;
endDocumentHandler();
stream.close();
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __TXTREADER_H__
#define __TXTREADER_H__
#include <string>
#include <ZLEncodingConverter.h>
#include "../EncodedTextReader.h"
class ZLInputStream;
class TxtReader : public EncodedTextReader {
public:
void readDocument(ZLInputStream &stream);
protected:
TxtReader(const std::string &encoding);
virtual ~TxtReader();
protected:
virtual void startDocumentHandler() = 0;
virtual void endDocumentHandler() = 0;
virtual bool characterDataHandler(std::string &str) = 0;
virtual bool newLineHandler() = 0;
};
#endif /* __TXTREADER_H__ */

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 <AndroidUtil.h>
#include "Library.h"
shared_ptr<Library> Library::ourInstance;
Library &Library::Instance() {
if (ourInstance.isNull()) {
ourInstance = new Library();
}
return *ourInstance;
}
Library::Library() {
JNIEnv *env = AndroidUtil::getEnv();
jclass paths = env->FindClass(AndroidUtil::Class_Paths);
myPathsClass = (jclass)env->NewGlobalRef(paths);
env->DeleteLocalRef(paths);
}
Library::~Library() {
JNIEnv *env = AndroidUtil::getEnv();
env->DeleteGlobalRef(myPathsClass);
}
std::string Library::cacheDirectory() const {
JNIEnv *env = AndroidUtil::getEnv();
jstring res = (jstring)env->CallStaticObjectMethod(myPathsClass, AndroidUtil::SMID_Paths_cacheDirectory);
const char *data = env->GetStringUTFChars(res, 0);
std::string str(data);
env->ReleaseStringUTFChars(res, data);
env->DeleteLocalRef(res);
return str;
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __LIBRARY_H__
#define __LIBRARY_H__
#include <jni.h>
#include <string>
#include <shared_ptr.h>
class Library {
public:
static Library &Instance();
private:
static shared_ptr<Library> ourInstance;
private:
Library();
public:
~Library();
std::string cacheDirectory() const;
private:
jclass myPathsClass;
};
#endif /* __LIBRARY_H__ */

View file

@ -27,6 +27,7 @@ const char * const AndroidUtil::Class_java_io_InputStream = "java/io/InputStream
const char * const AndroidUtil::Class_ZLibrary = "org/geometerplus/zlibrary/core/library/ZLibrary"; const char * const AndroidUtil::Class_ZLibrary = "org/geometerplus/zlibrary/core/library/ZLibrary";
const char * const AndroidUtil::Class_NativeFormatPlugin = "org/geometerplus/fbreader/formats/NativeFormatPlugin"; const char * const AndroidUtil::Class_NativeFormatPlugin = "org/geometerplus/fbreader/formats/NativeFormatPlugin";
const char * const AndroidUtil::Class_PluginCollection = "org/geometerplus/fbreader/formats/PluginCollection"; const char * const AndroidUtil::Class_PluginCollection = "org/geometerplus/fbreader/formats/PluginCollection";
const char * const AndroidUtil::Class_Paths = "org/geometerplus/fbreader/Paths";
const char * const AndroidUtil::Class_ZLFile = "org/geometerplus/zlibrary/core/filesystem/ZLFile"; const char * const AndroidUtil::Class_ZLFile = "org/geometerplus/zlibrary/core/filesystem/ZLFile";
const char * const AndroidUtil::Class_Book = "org/geometerplus/fbreader/library/Book"; const char * const AndroidUtil::Class_Book = "org/geometerplus/fbreader/library/Book";
const char * const AndroidUtil::Class_Tag = "org/geometerplus/fbreader/library/Tag"; const char * const AndroidUtil::Class_Tag = "org/geometerplus/fbreader/library/Tag";
@ -53,6 +54,8 @@ jmethodID AndroidUtil::MID_ZLFile_getPath;
jmethodID AndroidUtil::MID_ZLFile_isDirectory; jmethodID AndroidUtil::MID_ZLFile_isDirectory;
jmethodID AndroidUtil::MID_ZLFile_size; jmethodID AndroidUtil::MID_ZLFile_size;
jmethodID AndroidUtil::SMID_Paths_cacheDirectory;
jfieldID AndroidUtil::FID_Book_File; jfieldID AndroidUtil::FID_Book_File;
jmethodID AndroidUtil::MID_Book_getTitle; jmethodID AndroidUtil::MID_Book_getTitle;
jmethodID AndroidUtil::MID_Book_getLanguage; jmethodID AndroidUtil::MID_Book_getLanguage;
@ -109,6 +112,10 @@ bool AndroidUtil::init(JavaVM* jvm) {
CHECK_NULL( MID_ZLFile_size = env->GetMethodID(cls, "size", "()J") ); CHECK_NULL( MID_ZLFile_size = env->GetMethodID(cls, "size", "()J") );
env->DeleteLocalRef(cls); env->DeleteLocalRef(cls);
CHECK_NULL( cls = env->FindClass(Class_Paths) );
CHECK_NULL( SMID_Paths_cacheDirectory = env->GetStaticMethodID(cls, "cacheDirectory", "()Ljava/lang/String;") );
env->DeleteLocalRef(cls);
CHECK_NULL( cls = env->FindClass(Class_Book) ); CHECK_NULL( cls = env->FindClass(Class_Book) );
CHECK_NULL( FID_Book_File = env->GetFieldID(cls, "File", "Lorg/geometerplus/zlibrary/core/filesystem/ZLFile;") ); CHECK_NULL( FID_Book_File = env->GetFieldID(cls, "File", "Lorg/geometerplus/zlibrary/core/filesystem/ZLFile;") );
CHECK_NULL( MID_Book_getTitle = env->GetMethodID(cls, "getTitle", "()Ljava/lang/String;") ); CHECK_NULL( MID_Book_getTitle = env->GetMethodID(cls, "getTitle", "()Ljava/lang/String;") );

View file

@ -37,6 +37,7 @@ public:
static const char * const Class_ZLFile; static const char * const Class_ZLFile;
static const char * const Class_NativeFormatPlugin; static const char * const Class_NativeFormatPlugin;
static const char * const Class_PluginCollection; static const char * const Class_PluginCollection;
static const char * const Class_Paths;
static const char * const Class_Book; static const char * const Class_Book;
static const char * const Class_Tag; static const char * const Class_Tag;
@ -62,6 +63,8 @@ public:
static jmethodID SMID_PluginCollection_Instance; static jmethodID SMID_PluginCollection_Instance;
static jmethodID SMID_Paths_cacheDirectory;
static jfieldID FID_Book_File; static jfieldID FID_Book_File;
static jmethodID MID_Book_getTitle; static jmethodID MID_Book_getTitle;
static jmethodID MID_Book_getLanguage; static jmethodID MID_Book_getLanguage;

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __ZLFILEIMAGE_H__
#define __ZLFILEIMAGE_H__
#include <ZLFile.h>
#include "ZLStreamImage.h"
class ZLFileImage : public ZLStreamImage {
public:
ZLFileImage(const ZLFile &file, size_t offset, size_t size = 0);
Kind kind() const;
const ZLFile &file() const;
protected:
shared_ptr<ZLInputStream> inputStream() const;
private:
const ZLFile myFile;
};
inline ZLFileImage::ZLFileImage(const ZLFile &file, size_t offset, size_t size) : ZLStreamImage(file.mimeType(), offset, size), myFile(file) {}
inline ZLSingleImage::Kind ZLFileImage::kind() const { return FILE_IMAGE; }
inline const ZLFile &ZLFileImage::file() const { return myFile; }
#endif /* __ZLFILEIMAGE_H__ */

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __ZLSTREAMIMAGE_H__
#define __ZLSTREAMIMAGE_H__
#include <string>
#include <ZLImage.h>
#include <ZLInputStream.h>
class ZLStreamImage : public ZLSingleImage {
public:
ZLStreamImage(const std::string &mimeType, size_t offset, size_t size = 0);
const shared_ptr<std::string> stringData() const;
size_t offset() const;
size_t size() const;
private:
virtual shared_ptr<ZLInputStream> inputStream() const = 0;
private:
const size_t myOffset;
mutable size_t mySize;
};
inline ZLStreamImage::ZLStreamImage(const std::string &mimeType, size_t offset, size_t size) : ZLSingleImage(mimeType), myOffset(offset), mySize(size) {}
inline size_t ZLStreamImage::offset() const { return myOffset; }
inline size_t ZLStreamImage::size() const { return mySize; }
#endif /* __ZLSTREAMIMAGE_H__ */

View file

@ -0,0 +1,125 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 <cstdint>
#include <cstring>
#include <algorithm>
#include <ZLFile.h>
#include <ZLDir.h>
#include <ZLOutputStream.h>
#include <ZLStringUtil.h>
#include "ZLCachedMemoryAllocator.h"
ZLCachedMemoryAllocator::ZLCachedMemoryAllocator(const size_t rowSize,
const std::string &directoryName, const std::string &fileExtension) :
myRowSize(rowSize),
myCurrentRowSize(0),
myOffset(0),
myHasChanges(false),
myDirectoryName(directoryName),
myFileExtension(fileExtension) {
ZLFile(directoryName).directory(true);
}
ZLCachedMemoryAllocator::~ZLCachedMemoryAllocator() {
flush();
for (std::vector<char*>::const_iterator it = myPool.begin(); it != myPool.end(); ++it) {
delete[] *it;
}
}
void ZLCachedMemoryAllocator::flush() {
if (!myHasChanges) {
return;
}
char *ptr = myPool.back() + myOffset;
*ptr++ = 0;
*ptr = 0;
writeCache(myOffset + 2);
myHasChanges = false;
}
std::string ZLCachedMemoryAllocator::makeFileName(size_t index) {
std::string name(myDirectoryName);
name.append("/");
ZLStringUtil::appendNumber(name, index);
return name.append(".").append(myFileExtension);
}
void ZLCachedMemoryAllocator::writeCache(size_t blockLength) {
if (myPool.size() == 0) {
return;
}
const size_t index = myPool.size() - 1;
const std::string fileName = makeFileName(index);
ZLFile file(fileName);
shared_ptr<ZLOutputStream> stream = file.outputStream();
stream->open();
stream->write(myPool[index], blockLength);
stream->close();
}
char *ZLCachedMemoryAllocator::allocate(size_t size) {
myHasChanges = true;
if (myPool.empty()) {
myCurrentRowSize = std::max(myRowSize, size + 2 + sizeof(char*));
myPool.push_back(new char[myCurrentRowSize]);
} else if (myOffset + size + 2 + sizeof(char*) > myCurrentRowSize) {
myCurrentRowSize = std::max(myRowSize, size + 2 + sizeof(char*));
char *row = new char[myCurrentRowSize];
char *ptr = myPool.back() + myOffset;
*ptr++ = 0;
*ptr++ = 0;
memcpy(ptr, &row, sizeof(char*));
writeCache(myOffset + 2);
myPool.push_back(row);
myOffset = 0;
}
char *ptr = myPool.back() + myOffset;
myOffset += size;
return ptr;
}
char *ZLCachedMemoryAllocator::reallocateLast(char *ptr, size_t newSize) {
myHasChanges = true;
const size_t oldOffset = ptr - myPool.back();
if (oldOffset + newSize + 2 + sizeof(char*) <= myCurrentRowSize) {
myOffset = oldOffset + newSize;
return ptr;
} else {
myCurrentRowSize = std::max(myRowSize, newSize + 2 + sizeof(char*));
char *row = new char[myCurrentRowSize];
memcpy(row, ptr, myOffset - oldOffset);
*ptr++ = 0;
*ptr++ = 0;
memcpy(ptr, &row, sizeof(char*));
writeCache(oldOffset + 2);
myPool.push_back(row);
myOffset = newSize;
return row;
}
}

View file

@ -0,0 +1,96 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __ZLCACHEDMEMORYALLOCATOR_H__
#define __ZLCACHEDMEMORYALLOCATOR_H__
#include <vector>
class ZLCachedMemoryAllocator {
public:
ZLCachedMemoryAllocator(const size_t rowSize, const std::string &directoryName, const std::string &fileExtension);
~ZLCachedMemoryAllocator();
char *allocate(size_t size);
char *reallocateLast(char *ptr, size_t newSize);
void flush();
static void writeUInt16(char *ptr, uint16_t value);
static void writeUInt32(char *ptr, uint32_t value);
static uint16_t readUInt16(const char *ptr);
static uint32_t readUInt32(const char *ptr);
public:
const std::string &directoryName() const;
const std::string &fileExtension() const;
size_t blocksNumber() const;
size_t currentBytesOffset() const;
private:
std::string makeFileName(size_t index);
void writeCache(size_t blockLength);
private:
const size_t myRowSize;
size_t myCurrentRowSize;
std::vector<char*> myPool;
size_t myOffset;
bool myHasChanges;
const std::string myDirectoryName;
const std::string myFileExtension;
private: // disable copying
ZLCachedMemoryAllocator(const ZLCachedMemoryAllocator&);
const ZLCachedMemoryAllocator &operator = (const ZLCachedMemoryAllocator&);
};
inline const std::string &ZLCachedMemoryAllocator::directoryName() const { return myDirectoryName; }
inline const std::string &ZLCachedMemoryAllocator::fileExtension() const { return myFileExtension; }
inline size_t ZLCachedMemoryAllocator::blocksNumber() const { return myPool.size(); }
inline size_t ZLCachedMemoryAllocator::currentBytesOffset() const { return myOffset; }
inline void ZLCachedMemoryAllocator::writeUInt16(char *ptr, uint16_t value) {
*ptr++ = value;
*ptr = value >> 8;
}
inline void ZLCachedMemoryAllocator::writeUInt32(char *ptr, uint32_t value) {
*ptr++ = value;
value >>= 8;
*ptr++ = value;
value >>= 8;
*ptr++ = value;
*ptr = value >> 8;
}
inline uint16_t ZLCachedMemoryAllocator::readUInt16(const char *ptr) {
const uint8_t *tmp = (const uint8_t*)ptr;
return *tmp + ((uint16_t)*(tmp + 1) << 8);
}
inline uint32_t ZLCachedMemoryAllocator::readUInt32(const char *ptr) {
const uint8_t *tmp = (const uint8_t*)ptr;
return *tmp
+ ((uint32_t)*(tmp + 1) << 8)
+ ((uint32_t)*(tmp + 2) << 16)
+ ((uint32_t)*(tmp + 3) << 24);
}
#endif /* __ZLCACHEDMEMORYALLOCATOR_H__ */

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2011-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __ZLHYPERLINKTYPE_H__
#define __ZLHYPERLINKTYPE_H__
typedef unsigned char ZLHyperlinkType;
#endif /* __ZLHYPERLINKTYPE_H__ */

View file

@ -0,0 +1,122 @@
/*
* Copyright (C) 2011-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 <ZLFileImage.h>
#include <ZLUnicodeUtil.h>
#include "ZLImageMapWriter.h"
ZLImageMapWriter::ZLImageMapWriter(const size_t rowSize,
const std::string &directoryName, const std::string &fileExtension) :
myAllocator(rowSize, directoryName, fileExtension) {
}
void ZLImageMapWriter::addImage(const std::string &id, const ZLImage &image) {
const size_t dataSize = myAllocator.blocksNumber();
const size_t bytesOffset = myAllocator.currentBytesOffset();
myIds.push_back(id);
myIndices.push_back((dataSize == 0) ? 0 : (dataSize - 1));
myOffsets.push_back(bytesOffset / 2); // offset in words for future use in Java
if (image.isSingle()) {
addSingleImageEntry((const ZLSingleImage&)image);
} else {
addMultiImageEntry((const ZLMultiImage&)image);
}
}
void ZLImageMapWriter::addSingleImageEntry(const ZLSingleImage &image) {
ZLUnicodeUtil::Ucs2String ucs2mime;
ZLUnicodeUtil::utf8ToUcs2(ucs2mime, image.mimeType());
const size_t mimeSize = ucs2mime.size() * 2;
const size_t len = 4 + mimeSize;
char *address = myAllocator.allocate(len);
char *ptr = address;
*ptr++ = image.kind();
*ptr++ = 0; // multi ? 1 : 0
ZLCachedMemoryAllocator::writeUInt16(ptr, ucs2mime.size());
memcpy(ptr + 2, &ucs2mime.front(), mimeSize);
switch (image.kind()) {
case ZLSingleImage::BASE64_ENCODED_IMAGE:
case ZLSingleImage::REGULAR_IMAGE:
{
const shared_ptr<std::string> data = image.stringData();
size_t length = data.isNull() ? 0 : data->length();
size_t dataSize = (length + 1) / 2;
const size_t newlen = len + 4 + dataSize * 2;
address = myAllocator.reallocateLast(address, newlen);
ptr = address + len;
ZLCachedMemoryAllocator::writeUInt32(ptr, dataSize);
ptr += 4;
if (length > 0) {
memcpy(ptr, data->data(), length);
ptr += length;
if (length % 2) {
*ptr++ = 0;
}
}
break;
}
case ZLSingleImage::FILE_IMAGE:
{
const ZLFileImage &fileImage = (const ZLFileImage&)image;
ZLUnicodeUtil::Ucs2String ucs2path;
ZLUnicodeUtil::utf8ToUcs2(ucs2path, fileImage.file().path());
const size_t pathSize = ucs2path.size() * 2;
const size_t newlen = len + 10 + pathSize;
address = myAllocator.reallocateLast(address, newlen);
ptr = address + len;
ZLCachedMemoryAllocator::writeUInt32(ptr, fileImage.offset());
ptr += 4;
ZLCachedMemoryAllocator::writeUInt32(ptr, fileImage.size());
ptr += 4;
ZLCachedMemoryAllocator::writeUInt16(ptr, ucs2path.size());
ptr += 2;
memcpy(ptr, &ucs2path.front(), pathSize);
ptr += pathSize;
break;
}
}
}
void ZLImageMapWriter::addMultiImageEntry(const ZLMultiImage &image) {
const size_t len = 2;
char *address = myAllocator.allocate(len);
char *ptr = address;
*ptr++ = 0; // kind -- N/A for multi images
*ptr++ = 1; // multi ? 1 : 0
// TODO: implement
}
void ZLImageMapWriter::flush() {
myAllocator.flush();
}

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2011-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __ZLIMAGEMAPWRITER_H__
#define __ZLIMAGEMAPWRITER_H__
#include <jni.h>
#include <ZLImage.h>
#include <ZLUnicodeUtil.h>
#include <ZLTextParagraph.h>
#include <ZLCachedMemoryAllocator.h>
class ZLImageMapWriter {
public:
ZLImageMapWriter(const size_t rowSize, const std::string &directoryName, const std::string &fileExtension);
void addImage(const std::string &id, const ZLImage &image);
void flush();
const std::vector<std::string> identifiers() const;
const std::vector<jint> indices() const;
const std::vector<jint> offsets() const;
const ZLCachedMemoryAllocator &allocator() const;
private:
void addSingleImageEntry(const ZLSingleImage &image);
void addMultiImageEntry(const ZLMultiImage &image);
private:
ZLCachedMemoryAllocator myAllocator;
std::vector<std::string> myIds;
std::vector<jint> myIndices;
std::vector<jint> myOffsets;
private:
ZLImageMapWriter(const ZLImageMapWriter &);
const ZLImageMapWriter &operator = (const ZLImageMapWriter &);
};
inline const std::vector<std::string> ZLImageMapWriter::identifiers() const { return myIds; }
inline const std::vector<jint> ZLImageMapWriter::indices() const { return myIndices; }
inline const std::vector<jint> ZLImageMapWriter::offsets() const { return myOffsets; }
inline const ZLCachedMemoryAllocator &ZLImageMapWriter::allocator() const { return myAllocator; }
#endif /* __ZLIMAGEMAPWRITER_H__ */

View file

@ -0,0 +1,32 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __ZLTEXTALIGNMENTTYPE_H__
#define __ZLTEXTALIGNMENTTYPE_H__
enum ZLTextAlignmentType {
ALIGN_UNDEFINED = 0,
ALIGN_LEFT = 1,
ALIGN_RIGHT = 2,
ALIGN_CENTER = 3,
ALIGN_JUSTIFY = 4,
ALIGN_LINESTART = 5 // left for LTR languages and right for RTL
};
#endif /* __ZLTEXTALIGNMENTTYPE_H__ */

View file

@ -0,0 +1,30 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __ZLTEXTFONTMODIFIER_H__
#define __ZLTEXTFONTMODIFIER_H__
enum ZLTextFontModifier {
FONT_MODIFIER_DEFAULT = 0,
FONT_MODIFIER_BOLD = 1 << 0,
FONT_MODIFIER_ITALIC = 1 << 1,
FONT_MODIFIER_SMALLCAPS = 1 << 2,
};
#endif /* __ZLTEXTFONTMODIFIER_H__ */

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __ZLTEXTKIND_H__
#define __ZLTEXTKIND_H__
typedef unsigned char ZLTextKind;
#endif /* __ZLTEXTKIND_H__ */

View file

@ -0,0 +1,379 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 <cstdint>
#include <cstring>
#include <algorithm>
#include <ZLibrary.h>
//#include <ZLSearchUtil.h>
//#include <ZLLanguageUtil.h>
#include <ZLUnicodeUtil.h>
#include "ZLTextModel.h"
#include "ZLTextParagraph.h"
ZLTextModel::ZLTextModel(const std::string &id, const std::string &language, const size_t rowSize,
const std::string &directoryName, const std::string &fileExtension) :
myId(id),
myLanguage(language.empty() ? ZLibrary::Language() : language),
myAllocator(rowSize, directoryName, fileExtension),
myLastEntryStart(0) {
}
ZLTextModel::~ZLTextModel() {
for (std::vector<ZLTextParagraph*>::const_iterator it = myParagraphs.begin(); it != myParagraphs.end(); ++it) {
delete *it;
}
}
/*
bool ZLTextModel::isRtl() const {
return ZLLanguageUtil::isRTLLanguage(myLanguage);
}
void ZLTextModel::search(const std::string &text, size_t startIndex, size_t endIndex, bool ignoreCase) const {
ZLSearchPattern pattern(text, ignoreCase);
myMarks.clear();
std::vector<ZLTextParagraph*>::const_iterator start =
(startIndex < myParagraphs.size()) ? myParagraphs.begin() + startIndex : myParagraphs.end();
std::vector<ZLTextParagraph*>::const_iterator end =
(endIndex < myParagraphs.size()) ? myParagraphs.begin() + endIndex : myParagraphs.end();
for (std::vector<ZLTextParagraph*>::const_iterator it = start; it < end; ++it) {
int offset = 0;
for (ZLTextParagraph::Iterator jt = **it; !jt.isEnd(); jt.next()) {
if (jt.entryKind() == ZLTextParagraphEntry::TEXT_ENTRY) {
const ZLTextEntry& textEntry = (ZLTextEntry&)*jt.entry();
const char *str = textEntry.data();
const size_t len = textEntry.dataLength();
for (int pos = ZLSearchUtil::find(str, len, pattern); pos != -1; pos = ZLSearchUtil::find(str, len, pattern, pos + 1)) {
myMarks.push_back(ZLTextMark(it - myParagraphs.begin(), offset + pos, pattern.length()));
}
offset += len;
}
}
}
}
void ZLTextModel::selectParagraph(size_t index) const {
if (index < paragraphsNumber()) {
myMarks.push_back(ZLTextMark(index, 0, (*this)[index]->textDataLength()));
}
}
ZLTextMark ZLTextModel::firstMark() const {
return marks().empty() ? ZLTextMark() : marks().front();
}
ZLTextMark ZLTextModel::lastMark() const {
return marks().empty() ? ZLTextMark() : marks().back();
}
ZLTextMark ZLTextModel::nextMark(ZLTextMark position) const {
std::vector<ZLTextMark>::const_iterator it = std::upper_bound(marks().begin(), marks().end(), position);
return (it != marks().end()) ? *it : ZLTextMark();
}
ZLTextMark ZLTextModel::previousMark(ZLTextMark position) const {
if (marks().empty()) {
return ZLTextMark();
}
std::vector<ZLTextMark>::const_iterator it = std::lower_bound(marks().begin(), marks().end(), position);
if (it == marks().end()) {
--it;
}
if (*it >= position) {
if (it == marks().begin()) {
return ZLTextMark();
}
--it;
}
return *it;
}
*/
void ZLTextModel::addParagraphInternal(ZLTextParagraph *paragraph) {
checkUtf8Text();
const size_t dataSize = myAllocator.blocksNumber();
const size_t bytesOffset = myAllocator.currentBytesOffset();
myStartEntryIndices.push_back((dataSize == 0) ? 0 : (dataSize - 1));
myStartEntryOffsets.push_back(bytesOffset / 2); // offset in words for future use in Java
myParagraphLengths.push_back(0);
myTextSizes.push_back(myTextSizes.empty() ? 0 : myTextSizes.back());
myParagraphKinds.push_back(paragraph->kind());
myParagraphs.push_back(paragraph);
myLastEntryStart = 0;
}
ZLTextTreeModel::ZLTextTreeModel(const std::string &id, const std::string &language,
const std::string &directoryName, const std::string &fileExtension) :
ZLTextModel(id, language, 8192, directoryName, fileExtension) {
myRoot = new ZLTextTreeParagraph();
myRoot->open(true);
}
ZLTextTreeModel::~ZLTextTreeModel() {
delete myRoot;
}
ZLTextTreeParagraph *ZLTextTreeModel::createParagraph(ZLTextTreeParagraph *parent) {
if (parent == 0) {
parent = myRoot;
}
ZLTextTreeParagraph *tp = new ZLTextTreeParagraph(parent);
addParagraphInternal(tp);
return tp;
}
/*
void ZLTextTreeModel::search(const std::string &text, size_t startIndex, size_t endIndex, bool ignoreCase) const {
ZLTextModel::search(text, startIndex, endIndex, ignoreCase);
for (std::vector<ZLTextMark>::const_iterator it = marks().begin(); it != marks().end(); ++it) {
((ZLTextTreeParagraph*)(*this)[it->ParagraphIndex])->openTree();
}
}
void ZLTextTreeModel::selectParagraph(size_t index) const {
if (index < paragraphsNumber()) {
ZLTextModel::selectParagraph(index);
((ZLTextTreeParagraph*)(*this)[index])->openTree();
}
}
*/
ZLTextPlainModel::ZLTextPlainModel(const std::string &id, const std::string &language, const size_t rowSize,
const std::string &directoryName, const std::string &fileExtension) :
ZLTextModel(id, language, rowSize, directoryName, fileExtension) {
}
void ZLTextPlainModel::createParagraph(ZLTextParagraph::Kind kind) {
ZLTextParagraph *paragraph = (kind == ZLTextParagraph::TEXT_PARAGRAPH) ? new ZLTextParagraph() : new ZLTextSpecialParagraph(kind);
addParagraphInternal(paragraph);
}
void ZLTextModel::checkUtf8Text() {
if (myLastEntryStart == 0 || *myLastEntryStart != ZLTextParagraphEntry::TEXT_ENTRY
|| *(myLastEntryStart + 1) == 0) {
return;
}
const size_t utf8Len = ZLCachedMemoryAllocator::readUInt32(myLastEntryStart + 2);
ZLUnicodeUtil::Ucs2String ucs2str;
ZLUnicodeUtil::utf8ToUcs2(ucs2str, myLastEntryStart + 6, utf8Len);
const size_t newLen = ucs2str.size() * 2;
myLastEntryStart = myAllocator.reallocateLast(myLastEntryStart, newLen + 6);
*(myLastEntryStart + 1) = 0;
ZLCachedMemoryAllocator::writeUInt32(myLastEntryStart + 2, ucs2str.size());
memcpy(myLastEntryStart + 6, &ucs2str.front(), newLen);
myTextSizes.back() += ucs2str.size();
}
void ZLTextModel::addText(const std::string &text) {
const size_t len = text.length();
if (myLastEntryStart != 0 && *myLastEntryStart == ZLTextParagraphEntry::TEXT_ENTRY
&& *(myLastEntryStart + 1) != 0) {
const size_t oldLen = ZLCachedMemoryAllocator::readUInt32(myLastEntryStart + 2);
const size_t newLen = oldLen + len;
myLastEntryStart = myAllocator.reallocateLast(myLastEntryStart, newLen + 6);
ZLCachedMemoryAllocator::writeUInt32(myLastEntryStart + 2, newLen);
memcpy(myLastEntryStart + 6 + oldLen, text.data(), len);
} else {
myLastEntryStart = myAllocator.allocate(len + 6);
*myLastEntryStart = ZLTextParagraphEntry::TEXT_ENTRY;
*(myLastEntryStart + 1) = 1;
ZLCachedMemoryAllocator::writeUInt32(myLastEntryStart + 2, len);
memcpy(myLastEntryStart + 6, text.data(), len);
myParagraphs.back()->addEntry(myLastEntryStart);
++myParagraphLengths.back();
}
}
void ZLTextModel::addText(const std::vector<std::string> &text) {
if (text.size() == 0) {
return;
}
size_t len = 0;
for (std::vector<std::string>::const_iterator it = text.begin(); it != text.end(); ++it) {
len += it->length();
}
if (myLastEntryStart != 0 && *myLastEntryStart == ZLTextParagraphEntry::TEXT_ENTRY
&& *(myLastEntryStart + 1) != 0) {
const size_t oldLen = ZLCachedMemoryAllocator::readUInt32(myLastEntryStart + 2);
const size_t newLen = oldLen + len;
myLastEntryStart = myAllocator.reallocateLast(myLastEntryStart, newLen + 6);
ZLCachedMemoryAllocator::writeUInt32(myLastEntryStart + 2, newLen);
size_t offset = 6 + oldLen;
for (std::vector<std::string>::const_iterator it = text.begin(); it != text.end(); ++it) {
memcpy(myLastEntryStart + offset, it->data(), it->length());
offset += it->length();
}
} else {
myLastEntryStart = myAllocator.allocate(len + 6);
*myLastEntryStart = ZLTextParagraphEntry::TEXT_ENTRY;
*(myLastEntryStart + 1) = 1;
ZLCachedMemoryAllocator::writeUInt32(myLastEntryStart + 2, len);
size_t offset = 6;
for (std::vector<std::string>::const_iterator it = text.begin(); it != text.end(); ++it) {
memcpy(myLastEntryStart + offset, it->data(), it->length());
offset += it->length();
}
myParagraphs.back()->addEntry(myLastEntryStart);
++myParagraphLengths.back();
}
}
void ZLTextModel::addFixedHSpace(unsigned char length) {
checkUtf8Text();
myLastEntryStart = myAllocator.allocate(4);
*myLastEntryStart = ZLTextParagraphEntry::FIXED_HSPACE_ENTRY;
*(myLastEntryStart + 1) = 0;
*(myLastEntryStart + 2) = length;
*(myLastEntryStart + 3) = 0;
myParagraphs.back()->addEntry(myLastEntryStart);
++myParagraphLengths.back();
}
void ZLTextModel::addControl(ZLTextKind textKind, bool isStart) {
checkUtf8Text();
myLastEntryStart = myAllocator.allocate(4);
*myLastEntryStart = ZLTextParagraphEntry::CONTROL_ENTRY;
*(myLastEntryStart + 1) = 0;
*(myLastEntryStart + 2) = textKind;
*(myLastEntryStart + 3) = isStart ? 1 : 0;
myParagraphs.back()->addEntry(myLastEntryStart);
++myParagraphLengths.back();
}
void ZLTextModel::addControl(const ZLTextStyleEntry &entry) {
/*checkUtf8Text();
size_t len = 10 + 2 * (ZLTextStyleEntry::NUMBER_OF_LENGTHS +
(ZLTextStyleEntry::NUMBER_OF_LENGTHS + 1) / 2);
ZLUnicodeUtil::Ucs2String fontFamily;
size_t fontFamilyLen = 0;
if (entry.fontFamilySupported()) {
ZLUnicodeUtil::utf8ToUcs2(fontFamily, entry.fontFamily());
fontFamilyLen = fontFamily.size() * 2;
len += 2 + fontFamilyLen;
}
myLastEntryStart = myAllocator.allocate(len);
char *address = myLastEntryStart;
*address++ = ZLTextParagraphEntry::STYLE_ENTRY;
*address++ = 0;
ZLCachedMemoryAllocator::writeUInt32(address, entry.myMask);
address += 4;*/
// Pack myLengths array so:
//
// 1) for every two elements there is a word with those Units (two Units
// in two bytes) followed by two words with those Sizes;
//
// 2) if there is one last element (without a pair) => then another one
// word is appended with only one Unit (in the first byte) followed by
// a word containing corresponding Size.
//
/*const int lengthMinusOne = ZLTextStyleEntry::NUMBER_OF_LENGTHS - 1;
for (int i = 0; i < lengthMinusOne; i += 2) {
const ZLTextStyleEntry::LengthType &l0 = entry.myLengths[i];
const ZLTextStyleEntry::LengthType &l1 = entry.myLengths[i + 1];
*address++ = l0.Unit;
*address++ = l1.Unit;
ZLCachedMemoryAllocator::writeUInt16(address, l0.Size);
address += 2;
ZLCachedMemoryAllocator::writeUInt16(address, l1.Size);
address += 2;
}
if (ZLTextStyleEntry::NUMBER_OF_LENGTHS % 2) {
const ZLTextStyleEntry::LengthType &l0 = entry.myLengths[lengthMinusOne];
*address++ = l0.Unit;
*address++ = 0;
ZLCachedMemoryAllocator::writeUInt16(address, l0.Size);
address += 2;
}
*address++ = entry.mySupportedFontModifier;
*address++ = entry.myFontModifier;
*address++ = entry.myAlignmentType;
*address++ = entry.myFontSizeMag;
if (entry.fontFamilySupported()) {
ZLCachedMemoryAllocator::writeUInt16(address, fontFamily.size());
memcpy(address + 2, &fontFamily.front(), fontFamilyLen);
}
myParagraphs.back()->addEntry(myLastEntryStart);
++myParagraphLengths.back();*/
}
void ZLTextModel::addHyperlinkControl(ZLTextKind textKind, ZLHyperlinkType hyperlinkType, const std::string &label) {
checkUtf8Text();
ZLUnicodeUtil::Ucs2String ucs2label;
ZLUnicodeUtil::utf8ToUcs2(ucs2label, label);
const size_t len = ucs2label.size() * 2;
myLastEntryStart = myAllocator.allocate(len + 6);
*myLastEntryStart = ZLTextParagraphEntry::HYPERLINK_CONTROL_ENTRY;
*(myLastEntryStart + 1) = 0;
*(myLastEntryStart + 2) = textKind;
*(myLastEntryStart + 3) = hyperlinkType;
ZLCachedMemoryAllocator::writeUInt16(myLastEntryStart + 4, ucs2label.size());
memcpy(myLastEntryStart + 6, &ucs2label.front(), len);
myParagraphs.back()->addEntry(myLastEntryStart);
++myParagraphLengths.back();
}
void ZLTextModel::addImage(const std::string &id, short vOffset) {
checkUtf8Text();
ZLUnicodeUtil::Ucs2String ucs2id;
ZLUnicodeUtil::utf8ToUcs2(ucs2id, id);
const size_t len = ucs2id.size() * 2;
myLastEntryStart = myAllocator.allocate(len + 6);
*myLastEntryStart = ZLTextParagraphEntry::IMAGE_ENTRY;
*(myLastEntryStart + 1) = 0;
ZLCachedMemoryAllocator::writeUInt16(myLastEntryStart + 2, vOffset);
ZLCachedMemoryAllocator::writeUInt16(myLastEntryStart + 4, ucs2id.size());
memcpy(myLastEntryStart + 6, &ucs2id.front(), len);
myParagraphs.back()->addEntry(myLastEntryStart);
++myParagraphLengths.back();
}
void ZLTextModel::addBidiReset() {
checkUtf8Text();
myLastEntryStart = myAllocator.allocate(2);
*myLastEntryStart = ZLTextParagraphEntry::RESET_BIDI_ENTRY;
*(myLastEntryStart + 1) = 0;
myParagraphs.back()->addEntry(myLastEntryStart);
++myParagraphLengths.back();
}
void ZLTextModel::flush() {
checkUtf8Text();
myAllocator.flush();
}

View file

@ -0,0 +1,167 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __ZLTEXTMODEL_H__
#define __ZLTEXTMODEL_H__
#include <jni.h>
#include <vector>
#include <string>
#include <algorithm>
#include <ZLHyperlinkType.h>
#include <ZLTextParagraph.h>
#include <ZLTextKind.h>
//#include <ZLTextMark.h>
#include <ZLCachedMemoryAllocator.h>
class ZLTextParagraph;
class ZLTextTreeParagraph;
class ZLTextModel {
public:
enum Kind {
PLAIN_TEXT_MODEL,
TREE_MODEL,
};
protected:
ZLTextModel(const std::string &id, const std::string &language, const size_t rowSize,
const std::string &directoryName, const std::string &fileExtension);
public:
virtual ~ZLTextModel();
virtual Kind kind() const = 0;
const std::string &id() const;
const std::string &language() const;
//bool isRtl() const;
size_t paragraphsNumber() const;
ZLTextParagraph *operator [] (size_t index);
const ZLTextParagraph *operator [] (size_t index) const;
/*
const std::vector<ZLTextMark> &marks() const;
virtual void search(const std::string &text, size_t startIndex, size_t endIndex, bool ignoreCase) const;
virtual void selectParagraph(size_t index) const;
void removeAllMarks();
ZLTextMark firstMark() const;
ZLTextMark lastMark() const;
ZLTextMark nextMark(ZLTextMark position) const;
ZLTextMark previousMark(ZLTextMark position) const;
*/
void addControl(ZLTextKind textKind, bool isStart);
void addControl(const ZLTextStyleEntry &entry);
void addHyperlinkControl(ZLTextKind textKind, ZLHyperlinkType hyperlinkType, const std::string &label);
void addText(const std::string &text);
void addText(const std::vector<std::string> &text);
void addImage(const std::string &id, short vOffset);
void addFixedHSpace(unsigned char length);
void addBidiReset();
void flush();
const ZLCachedMemoryAllocator &allocator() const;
const std::vector<jint> &startEntryIndices() const;
const std::vector<jint> &startEntryOffsets() const;
const std::vector<jint> &paragraphLengths() const;
const std::vector<jint> &textSizes() const;
const std::vector<jbyte> &paragraphKinds() const;
protected:
void addParagraphInternal(ZLTextParagraph *paragraph);
void checkUtf8Text();
private:
const std::string myId;
const std::string myLanguage;
std::vector<ZLTextParagraph*> myParagraphs;
//mutable std::vector<ZLTextMark> myMarks;
mutable ZLCachedMemoryAllocator myAllocator;
char *myLastEntryStart;
std::vector<jint> myStartEntryIndices;
std::vector<jint> myStartEntryOffsets;
std::vector<jint> myParagraphLengths;
std::vector<jint> myTextSizes;
std::vector<jbyte> myParagraphKinds;
private:
ZLTextModel(const ZLTextModel&);
const ZLTextModel &operator = (const ZLTextModel&);
};
class ZLTextPlainModel : public ZLTextModel {
public:
ZLTextPlainModel(const std::string &id, const std::string &language, const size_t rowSize,
const std::string &directoryName, const std::string &fileExtension);
Kind kind() const;
void createParagraph(ZLTextParagraph::Kind kind);
};
class ZLTextTreeModel : public ZLTextModel {
public:
ZLTextTreeModel(const std::string &id, const std::string &language,
const std::string &directoryName, const std::string &fileExtension);
~ZLTextTreeModel();
Kind kind() const;
ZLTextTreeParagraph *createParagraph(ZLTextTreeParagraph *parent = 0);
void search(const std::string &text, size_t startIndex, size_t endIndex, bool ignoreCase) const;
void selectParagraph(size_t index) const;
private:
ZLTextTreeParagraph *myRoot;
};
inline const std::string &ZLTextModel::id() const { return myId; }
inline const std::string &ZLTextModel::language() const { return myLanguage; }
inline size_t ZLTextModel::paragraphsNumber() const { return myParagraphs.size(); }
//inline const std::vector<ZLTextMark> &ZLTextModel::marks() const { return myMarks; }
//inline void ZLTextModel::removeAllMarks() { myMarks.clear(); }
inline const ZLCachedMemoryAllocator &ZLTextModel::allocator() const { return myAllocator; }
inline const std::vector<jint> &ZLTextModel::startEntryIndices() const { return myStartEntryIndices; }
inline const std::vector<jint> &ZLTextModel::startEntryOffsets() const { return myStartEntryOffsets; }
inline const std::vector<jint> &ZLTextModel::paragraphLengths() const { return myParagraphLengths; };
inline const std::vector<jint> &ZLTextModel::textSizes() const { return myTextSizes; };
inline const std::vector<jbyte> &ZLTextModel::paragraphKinds() const { return myParagraphKinds; };
inline ZLTextParagraph *ZLTextModel::operator [] (size_t index) {
return myParagraphs[std::min(myParagraphs.size() - 1, index)];
}
inline const ZLTextParagraph *ZLTextModel::operator [] (size_t index) const {
return myParagraphs[std::min(myParagraphs.size() - 1, index)];
}
inline ZLTextModel::Kind ZLTextPlainModel::kind() const { return PLAIN_TEXT_MODEL; }
inline ZLTextModel::Kind ZLTextTreeModel::kind() const { return TREE_MODEL; }
#endif /* __ZLTEXTMODEL_H__ */

View file

@ -0,0 +1,266 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 <string.h>
#include <algorithm>
#include <ZLUnicodeUtil.h>
#include <ZLImage.h>
#include "ZLCachedMemoryAllocator.h"
#include "ZLTextParagraph.h"
const shared_ptr<ZLTextParagraphEntry> ResetBidiEntry::Instance = new ResetBidiEntry();
short ZLTextStyleEntry::length(Length name, const Metrics &metrics) const {
switch (myLengths[name].Unit) {
default:
case SIZE_UNIT_PIXEL:
return myLengths[name].Size;
case SIZE_UNIT_EM_100:
return (myLengths[name].Size * metrics.FontSize + 50) / 100;
case SIZE_UNIT_EX_100:
return (myLengths[name].Size * metrics.FontXHeight + 50) / 100;
case SIZE_UNIT_PERCENT:
switch (name) {
default:
case LENGTH_LEFT_INDENT:
case LENGTH_RIGHT_INDENT:
case LENGTH_FIRST_LINE_INDENT_DELTA:
return (myLengths[name].Size * metrics.FullWidth + 50) / 100;
case LENGTH_SPACE_BEFORE:
case LENGTH_SPACE_AFTER:
return (myLengths[name].Size * metrics.FullHeight + 50) / 100;
}
}
}
ZLTextStyleEntry::ZLTextStyleEntry(char *address) {
myMask = ZLCachedMemoryAllocator::readUInt32(address);
address += 4;
const int lengthMinusOne = ZLTextStyleEntry::NUMBER_OF_LENGTHS - 1;
for (int i = 0; i < lengthMinusOne; i += 2) {
ZLTextStyleEntry::LengthType &l0 = myLengths[i];
ZLTextStyleEntry::LengthType &l1 = myLengths[i + 1];
l0.Unit = (SizeUnit)*address++;
l1.Unit = (SizeUnit)*address++;
l0.Size = ZLCachedMemoryAllocator::readUInt16(address);
address += 2;
l1.Size = ZLCachedMemoryAllocator::readUInt16(address);
address += 2;
}
if (ZLTextStyleEntry::NUMBER_OF_LENGTHS % 2) {
ZLTextStyleEntry::LengthType &l0 = myLengths[lengthMinusOne];
l0.Unit = (SizeUnit)*address;
address += 2;
l0.Size = ZLCachedMemoryAllocator::readUInt16(address);
address += 2;
}
mySupportedFontModifier = *address++;
myFontModifier = *address++;
myAlignmentType = (ZLTextAlignmentType)*address++;
myFontSizeMag = *address++;
if (fontFamilySupported()) {
const size_t len = ZLCachedMemoryAllocator::readUInt16(address);
ZLUnicodeUtil::Ucs2Char *ucs2data = (ZLUnicodeUtil::Ucs2Char *)(address + 2);
ZLUnicodeUtil::Ucs2String ucs2str(ucs2data, ucs2data + len);
ZLUnicodeUtil::ucs2ToUtf8(myFontFamily, ucs2str);
}
}
ZLTextControlEntryPool ZLTextControlEntryPool::Pool;
shared_ptr<ZLTextParagraphEntry> ZLTextControlEntryPool::controlEntry(ZLTextKind kind, bool isStart) {
std::map<ZLTextKind, shared_ptr<ZLTextParagraphEntry> > &entries = isStart ? myStartEntries : myEndEntries;
std::map<ZLTextKind, shared_ptr<ZLTextParagraphEntry> >::iterator it = entries.find(kind);
if (it != entries.end()) {
return it->second;
}
shared_ptr<ZLTextParagraphEntry> entry = new ZLTextControlEntry(kind, isStart);
entries[kind] = entry;
return entry;
}
ZLTextHyperlinkControlEntry::ZLTextHyperlinkControlEntry(const char *address) : ZLTextControlEntry((ZLTextKind)*address, true), myHyperlinkType((ZLHyperlinkType)*(address + 1)) {
const size_t len = ZLCachedMemoryAllocator::readUInt16(address + 2);
ZLUnicodeUtil::Ucs2Char *ucs2data = (ZLUnicodeUtil::Ucs2Char *)(address + 4);
ZLUnicodeUtil::Ucs2String ucs2str(ucs2data, ucs2data + len);
ZLUnicodeUtil::ucs2ToUtf8(myLabel, ucs2str);
}
ZLTextEntry::ZLTextEntry(const char *address) {
const size_t len = ZLCachedMemoryAllocator::readUInt32(address);
ZLUnicodeUtil::Ucs2Char *ucs2data = (ZLUnicodeUtil::Ucs2Char *)(address + 4);
ZLUnicodeUtil::Ucs2String ucs2str(ucs2data, ucs2data + len);
ZLUnicodeUtil::ucs2ToUtf8(myText, ucs2str);
}
ImageEntry::ImageEntry(const char *address) {
myVOffset = ZLCachedMemoryAllocator::readUInt16(address);
const size_t len = ZLCachedMemoryAllocator::readUInt16(address + 2);
ZLUnicodeUtil::Ucs2Char *ucs2data = (ZLUnicodeUtil::Ucs2Char *)(address + 4);
ZLUnicodeUtil::Ucs2String ucs2str(ucs2data, ucs2data + len);
ZLUnicodeUtil::ucs2ToUtf8(myId, ucs2str);
}
const shared_ptr<ZLTextParagraphEntry> ZLTextParagraph::Iterator::entry() const {
if (myEntry.isNull()) {
switch (*myPointer) {
case ZLTextParagraphEntry::TEXT_ENTRY:
myEntry = new ZLTextEntry(myPointer + 2);
break;
case ZLTextParagraphEntry::CONTROL_ENTRY:
myEntry = ZLTextControlEntryPool::Pool.controlEntry(
(ZLTextKind)*(myPointer + 2), *(myPointer + 3) != 0);
break;
case ZLTextParagraphEntry::HYPERLINK_CONTROL_ENTRY:
myEntry = new ZLTextHyperlinkControlEntry(myPointer + 2);
break;
case ZLTextParagraphEntry::IMAGE_ENTRY:
myEntry = new ImageEntry(myPointer + 2);
break;
case ZLTextParagraphEntry::STYLE_ENTRY:
myEntry = new ZLTextStyleEntry(myPointer + 2);
break;
case ZLTextParagraphEntry::FIXED_HSPACE_ENTRY:
myEntry = new ZLTextFixedHSpaceEntry(*(myPointer + 2));
break;
case ZLTextParagraphEntry::RESET_BIDI_ENTRY:
myEntry = ResetBidiEntry::Instance;
break;
}
}
return myEntry;
}
void ZLTextParagraph::Iterator::next() {
++myIndex;
myEntry = 0;
if (myIndex != myEndIndex) {
switch (*myPointer) {
case ZLTextParagraphEntry::TEXT_ENTRY:
{
const size_t len = ZLCachedMemoryAllocator::readUInt32(myPointer + 2);
myPointer += len * 2 + 6;
break;
}
case ZLTextParagraphEntry::CONTROL_ENTRY:
myPointer += 4;
break;
case ZLTextParagraphEntry::HYPERLINK_CONTROL_ENTRY:
{
const size_t len = ZLCachedMemoryAllocator::readUInt16(myPointer + 4);
myPointer += len * 2 + 6;
break;
}
case ZLTextParagraphEntry::IMAGE_ENTRY:
{
const size_t len = ZLCachedMemoryAllocator::readUInt16(myPointer + 4);
myPointer += len * 2 + 6;
break;
}
case ZLTextParagraphEntry::STYLE_ENTRY:
{
unsigned int mask = ZLCachedMemoryAllocator::readUInt32(myPointer + 2);
bool withFontFamily = (mask & ZLTextStyleEntry::SUPPORT_FONT_FAMILY) == ZLTextStyleEntry::SUPPORT_FONT_FAMILY;
myPointer += 10 + 2 * (ZLTextStyleEntry::NUMBER_OF_LENGTHS +
(ZLTextStyleEntry::NUMBER_OF_LENGTHS + 1) / 2);
if (withFontFamily) {
const size_t len = ZLCachedMemoryAllocator::readUInt16(myPointer);
myPointer += 2 + 2 * len;
}
break;
}
case ZLTextParagraphEntry::FIXED_HSPACE_ENTRY:
myPointer += 4;
break;
case ZLTextParagraphEntry::RESET_BIDI_ENTRY:
myPointer += 2;
break;
}
if (*myPointer == 0) {
memcpy(&myPointer, myPointer + 1, sizeof(char*));
}
}
}
size_t ZLTextParagraph::textDataLength() const {
size_t len = 0;
for (Iterator it = *this; !it.isEnd(); it.next()) {
if (it.entryKind() == ZLTextParagraphEntry::TEXT_ENTRY) {
len += ((ZLTextEntry&)*it.entry()).dataLength();
}
}
return len;
}
size_t ZLTextParagraph::characterNumber() const {
size_t len = 0;
for (Iterator it = *this; !it.isEnd(); it.next()) {
switch (it.entryKind()) {
case ZLTextParagraphEntry::TEXT_ENTRY:
{
const ZLTextEntry &entry = (ZLTextEntry&)*it.entry();
len += ZLUnicodeUtil::utf8Length(entry.data(), entry.dataLength());
break;
}
case ZLTextParagraphEntry::IMAGE_ENTRY:
len += 100;
break;
default:
break;
}
}
return len;
}
ZLTextTreeParagraph::ZLTextTreeParagraph(ZLTextTreeParagraph *parent) : myIsOpen(false), myParent(parent) {
if (parent != 0) {
parent->addChild(this);
myDepth = parent->myDepth + 1;
} else {
myDepth = 0;
}
}
void ZLTextTreeParagraph::openTree() {
for (ZLTextTreeParagraph *p = parent(); p != 0; p = p->parent()) {
p->open(true);
}
}
void ZLTextTreeParagraph::removeFromParent() {
if (myParent != 0) {
myParent->myChildren.erase(std::find(myParent->myChildren.begin(), myParent->myChildren.end(), this));
}
}
int ZLTextTreeParagraph::fullSize() const {
int size = 1;
for (std::vector<ZLTextTreeParagraph*>::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it) {
size += (*it)->fullSize();
}
return size;
}

View file

@ -0,0 +1,422 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* 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 __ZLTEXTPARAGRAPH_H__
#define __ZLTEXTPARAGRAPH_H__
#include <map>
#include <vector>
#include <string>
#include <shared_ptr.h>
#include <ZLHyperlinkType.h>
#include <ZLTextKind.h>
#include <ZLTextAlignmentType.h>
#include <ZLTextFontModifier.h>
class ZLImage;
typedef std::map<std::string,shared_ptr<const ZLImage> > ZLImageMap;
class ZLTextParagraphEntry {
public:
enum Kind {
TEXT_ENTRY = 1,
IMAGE_ENTRY = 2,
CONTROL_ENTRY = 3,
HYPERLINK_CONTROL_ENTRY = 4,
STYLE_ENTRY = 5,
FIXED_HSPACE_ENTRY = 6,
RESET_BIDI_ENTRY = 7,
};
protected:
ZLTextParagraphEntry();
public:
virtual ~ZLTextParagraphEntry();
private: // disable copying
ZLTextParagraphEntry(const ZLTextParagraphEntry &entry);
const ZLTextParagraphEntry &operator = (const ZLTextParagraphEntry &entry);
};
class ZLTextStyleEntry : public ZLTextParagraphEntry {
public:
enum SizeUnit {
SIZE_UNIT_PIXEL,
SIZE_UNIT_EM_100,
SIZE_UNIT_EX_100,
SIZE_UNIT_PERCENT
};
struct Metrics {
Metrics(int fontSize, int fontXHeight, int fullWidth, int fullHeight);
int FontSize;
int FontXHeight;
int FullWidth;
int FullHeight;
};
enum Length {
LENGTH_LEFT_INDENT = 0,
LENGTH_RIGHT_INDENT = 1,
LENGTH_FIRST_LINE_INDENT_DELTA = 2,
LENGTH_SPACE_BEFORE = 3,
LENGTH_SPACE_AFTER = 4,
NUMBER_OF_LENGTHS = 5,
};
private:
struct LengthType {
SizeUnit Unit;
short Size;
};
public:
ZLTextStyleEntry();
ZLTextStyleEntry(char *address);
~ZLTextStyleEntry();
bool isEmpty() const;
bool lengthSupported(Length name) const;
short length(Length name, const Metrics &metrics) const;
void setLength(Length name, short length, SizeUnit unit);
bool alignmentTypeSupported() const;
ZLTextAlignmentType alignmentType() const;
void setAlignmentType(ZLTextAlignmentType alignmentType);
unsigned char supportedFontModifier() const;
unsigned char fontModifier() const;
void setFontModifier(ZLTextFontModifier style, bool set);
bool fontSizeSupported() const;
signed char fontSizeMag() const;
void setFontSizeMag(signed char fontSizeMag);
bool fontFamilySupported() const;
const std::string &fontFamily() const;
void setFontFamily(const std::string &fontFamily);
static const unsigned int SUPPORT_ALIGNMENT_TYPE = 1U << NUMBER_OF_LENGTHS;
static const unsigned int SUPPORT_FONT_SIZE = 1U << (NUMBER_OF_LENGTHS + 1);
static const unsigned int SUPPORT_FONT_FAMILY = 1U << (NUMBER_OF_LENGTHS + 2);
private:
unsigned int myMask;
LengthType myLengths[NUMBER_OF_LENGTHS];
ZLTextAlignmentType myAlignmentType;
unsigned char mySupportedFontModifier;
unsigned char myFontModifier;
signed char myFontSizeMag;
std::string myFontFamily;
friend class ZLTextModel;
};
class ZLTextControlEntry : public ZLTextParagraphEntry {
protected:
ZLTextControlEntry(ZLTextKind kind, bool isStart);
public:
virtual ~ZLTextControlEntry();
ZLTextKind kind() const;
bool isStart() const;
virtual bool isHyperlink() const;
private:
ZLTextKind myKind;
bool myStart;
friend class ZLTextControlEntryPool;
};
class ZLTextControlEntryPool {
public:
static ZLTextControlEntryPool Pool;
public:
ZLTextControlEntryPool();
~ZLTextControlEntryPool();
shared_ptr<ZLTextParagraphEntry> controlEntry(ZLTextKind kind, bool isStart);
private:
std::map<ZLTextKind, shared_ptr<ZLTextParagraphEntry> > myStartEntries;
std::map<ZLTextKind, shared_ptr<ZLTextParagraphEntry> > myEndEntries;
};
class ZLTextFixedHSpaceEntry : public ZLTextParagraphEntry {
public:
ZLTextFixedHSpaceEntry(unsigned char length);
unsigned char length() const;
private:
const unsigned char myLength;
};
class ZLTextHyperlinkControlEntry : public ZLTextControlEntry {
public:
ZLTextHyperlinkControlEntry(const char *address);
~ZLTextHyperlinkControlEntry();
const std::string &label() const;
ZLHyperlinkType hyperlinkType() const;
bool isHyperlink() const;
private:
std::string myLabel;
ZLHyperlinkType myHyperlinkType;
};
class ZLTextEntry : public ZLTextParagraphEntry {
public:
ZLTextEntry(const char *address);
~ZLTextEntry();
size_t dataLength() const;
const char *data() const;
private:
std::string myText;
};
class ImageEntry : public ZLTextParagraphEntry {
public:
ImageEntry(const char *address);
~ImageEntry();
const std::string &id() const;
short vOffset() const;
private:
std::string myId;
short myVOffset;
};
class ResetBidiEntry : public ZLTextParagraphEntry {
public:
static const shared_ptr<ZLTextParagraphEntry> Instance;
private:
ResetBidiEntry();
};
class ZLTextParagraph {
public:
class Iterator {
public:
Iterator(const ZLTextParagraph &paragraph);
~Iterator();
bool isEnd() const;
void next();
const shared_ptr<ZLTextParagraphEntry> entry() const;
ZLTextParagraphEntry::Kind entryKind() const;
private:
char *myPointer;
size_t myIndex;
size_t myEndIndex;
mutable shared_ptr<ZLTextParagraphEntry> myEntry;
};
enum Kind {
TEXT_PARAGRAPH,
TREE_PARAGRAPH,
EMPTY_LINE_PARAGRAPH,
BEFORE_SKIP_PARAGRAPH,
AFTER_SKIP_PARAGRAPH,
END_OF_SECTION_PARAGRAPH,
END_OF_TEXT_PARAGRAPH,
};
protected:
ZLTextParagraph();
public:
virtual ~ZLTextParagraph();
virtual Kind kind() const;
size_t entryNumber() const;
size_t textDataLength() const;
size_t characterNumber() const;
private:
void addEntry(char *address);
private:
char *myFirstEntryAddress;
size_t myEntryNumber;
friend class Iterator;
friend class ZLTextModel;
friend class ZLTextPlainModel;
};
class ZLTextSpecialParagraph : public ZLTextParagraph {
private:
ZLTextSpecialParagraph(Kind kind);
public:
~ZLTextSpecialParagraph();
Kind kind() const;
private:
Kind myKind;
friend class ZLTextPlainModel;
};
class ZLTextTreeParagraph : public ZLTextParagraph {
public:
ZLTextTreeParagraph(ZLTextTreeParagraph *parent = 0);
~ZLTextTreeParagraph();
Kind kind() const;
bool isOpen() const;
void open(bool o);
void openTree();
int depth() const;
ZLTextTreeParagraph *parent();
const ZLTextTreeParagraph *parent() const;
const std::vector<ZLTextTreeParagraph*> &children() const;
int fullSize() const;
void removeFromParent();
private:
void addChild(ZLTextTreeParagraph *child);
private:
bool myIsOpen;
int myDepth;
ZLTextTreeParagraph *myParent;
std::vector<ZLTextTreeParagraph*> myChildren;
};
inline ZLTextParagraphEntry::ZLTextParagraphEntry() {}
inline ZLTextParagraphEntry::~ZLTextParagraphEntry() {}
inline ZLTextStyleEntry::ZLTextStyleEntry() : myMask(0), myAlignmentType(ALIGN_UNDEFINED), mySupportedFontModifier(0), myFontModifier(0), myFontSizeMag(0) {}
inline ZLTextStyleEntry::~ZLTextStyleEntry() {}
inline ZLTextStyleEntry::Metrics::Metrics(int fontSize, int fontXHeight, int fullWidth, int fullHeight) : FontSize(fontSize), FontXHeight(fontXHeight), FullWidth(fullWidth), FullHeight(fullHeight) {}
inline bool ZLTextStyleEntry::isEmpty() const { return myMask == 0; }
inline bool ZLTextStyleEntry::lengthSupported(Length name) const { return (myMask & (1U << name)) != 0; }
inline void ZLTextStyleEntry::setLength(Length name, short length, SizeUnit unit) {
myLengths[name].Size = length;
myLengths[name].Unit = unit;
myMask |= 1U << name;
}
inline bool ZLTextStyleEntry::alignmentTypeSupported() const { return (myMask & SUPPORT_ALIGNMENT_TYPE) == SUPPORT_ALIGNMENT_TYPE; }
inline ZLTextAlignmentType ZLTextStyleEntry::alignmentType() const { return myAlignmentType; }
inline void ZLTextStyleEntry::setAlignmentType(ZLTextAlignmentType alignmentType) { myAlignmentType = alignmentType; myMask |= SUPPORT_ALIGNMENT_TYPE; }
inline unsigned char ZLTextStyleEntry::supportedFontModifier() const { return mySupportedFontModifier; }
inline unsigned char ZLTextStyleEntry::fontModifier() const { return myFontModifier; }
inline void ZLTextStyleEntry::setFontModifier(ZLTextFontModifier style, bool set) {
if (set) {
myFontModifier |= style;
} else {
myFontModifier &= ~style;
}
mySupportedFontModifier |= style;
}
inline bool ZLTextStyleEntry::fontSizeSupported() const { return (myMask & SUPPORT_FONT_SIZE) == SUPPORT_FONT_SIZE; }
inline signed char ZLTextStyleEntry::fontSizeMag() const { return myFontSizeMag; }
inline void ZLTextStyleEntry::setFontSizeMag(signed char fontSizeMag) { myFontSizeMag = fontSizeMag; myMask |= SUPPORT_FONT_SIZE; }
inline bool ZLTextStyleEntry::fontFamilySupported() const { return (myMask & SUPPORT_FONT_FAMILY) == SUPPORT_FONT_FAMILY; }
inline const std::string &ZLTextStyleEntry::fontFamily() const { return myFontFamily; }
inline void ZLTextStyleEntry::setFontFamily(const std::string &fontFamily) { myFontFamily = fontFamily; myMask |= SUPPORT_FONT_FAMILY; }
inline ZLTextControlEntry::ZLTextControlEntry(ZLTextKind kind, bool isStart) : myKind(kind), myStart(isStart) {}
inline ZLTextControlEntry::~ZLTextControlEntry() {}
inline ZLTextKind ZLTextControlEntry::kind() const { return myKind; }
inline bool ZLTextControlEntry::isStart() const { return myStart; }
inline bool ZLTextControlEntry::isHyperlink() const { return false; }
inline ZLTextFixedHSpaceEntry::ZLTextFixedHSpaceEntry(unsigned char length) : myLength(length) {}
inline unsigned char ZLTextFixedHSpaceEntry::length() const { return myLength; }
inline ZLTextControlEntryPool::ZLTextControlEntryPool() {}
inline ZLTextControlEntryPool::~ZLTextControlEntryPool() {}
inline ZLTextHyperlinkControlEntry::~ZLTextHyperlinkControlEntry() {}
inline const std::string &ZLTextHyperlinkControlEntry::label() const { return myLabel; }
inline ZLHyperlinkType ZLTextHyperlinkControlEntry::hyperlinkType() const { return myHyperlinkType; }
inline bool ZLTextHyperlinkControlEntry::isHyperlink() const { return true; }
inline ZLTextEntry::~ZLTextEntry() {}
inline const char *ZLTextEntry::data() const { return myText.data(); }
inline size_t ZLTextEntry::dataLength() const { return myText.length(); }
inline ImageEntry::~ImageEntry() {}
inline const std::string &ImageEntry::id() const { return myId; }
inline short ImageEntry::vOffset() const { return myVOffset; }
inline ResetBidiEntry::ResetBidiEntry() {}
inline ZLTextParagraph::ZLTextParagraph() : myEntryNumber(0) {}
inline ZLTextParagraph::~ZLTextParagraph() {}
inline ZLTextParagraph::Kind ZLTextParagraph::kind() const { return TEXT_PARAGRAPH; }
inline size_t ZLTextParagraph::entryNumber() const { return myEntryNumber; }
inline void ZLTextParagraph::addEntry(char *address) { if (myEntryNumber == 0) myFirstEntryAddress = address; ++myEntryNumber; }
inline ZLTextParagraph::Iterator::Iterator(const ZLTextParagraph &paragraph) : myPointer(paragraph.myFirstEntryAddress), myIndex(0), myEndIndex(paragraph.entryNumber()) {}
inline ZLTextParagraph::Iterator::~Iterator() {}
inline bool ZLTextParagraph::Iterator::isEnd() const { return myIndex == myEndIndex; }
inline ZLTextParagraphEntry::Kind ZLTextParagraph::Iterator::entryKind() const { return (ZLTextParagraphEntry::Kind)*myPointer; }
inline ZLTextSpecialParagraph::ZLTextSpecialParagraph(Kind kind) : myKind(kind) {}
inline ZLTextSpecialParagraph::~ZLTextSpecialParagraph() {}
inline ZLTextParagraph::Kind ZLTextSpecialParagraph::kind() const { return myKind; }
inline ZLTextTreeParagraph::~ZLTextTreeParagraph() {}
inline ZLTextParagraph::Kind ZLTextTreeParagraph::kind() const { return TREE_PARAGRAPH; }
inline bool ZLTextTreeParagraph::isOpen() const { return myIsOpen; }
inline void ZLTextTreeParagraph::open(bool o) { myIsOpen = o; }
inline int ZLTextTreeParagraph::depth() const { return myDepth; }
inline ZLTextTreeParagraph *ZLTextTreeParagraph::parent() { return myParent; }
inline const ZLTextTreeParagraph *ZLTextTreeParagraph::parent() const { return myParent; }
inline const std::vector<ZLTextTreeParagraph*> &ZLTextTreeParagraph::children() const { return myChildren; }
inline void ZLTextTreeParagraph::addChild(ZLTextTreeParagraph *child) { myChildren.push_back(child); }
#endif /* __ZLTEXTPARAGRAPH_H__ */

View file

@ -31,6 +31,10 @@
-keepclassmembers class org.geometerplus.fbreader.formats.PluginCollection { -keepclassmembers class org.geometerplus.fbreader.formats.PluginCollection {
public static ** Instance(); public static ** Instance();
} }
-keep class org.geometerplus.fbreader.Paths
-keepclassmembers class org.geometerplus.fbreader.Paths {
public static ** cacheDirectory();
}
-keep class org.geometerplus.fbreader.library.Book -keep class org.geometerplus.fbreader.library.Book
-keepclassmembers class org.geometerplus.fbreader.library.Book { -keepclassmembers class org.geometerplus.fbreader.library.Book {
public ** File; public ** File;