[fbreader] Support for footnotes

This commit is contained in:
Slava Monich 2016-11-02 16:28:59 +03:00
parent c2558fbb3f
commit 35757ce03d
6 changed files with 77 additions and 14 deletions

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com> * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
* Copyright (C) 2016 Slava Monich <slava.monich@jolla.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -51,6 +52,11 @@ BookModel::Label BookModel::label(const std::string &id) const {
return (it != myInternalHyperlinks.end()) ? it->second : Label(0, -1); return (it != myInternalHyperlinks.end()) ? it->second : Label(0, -1);
} }
shared_ptr<ZLTextModel> BookModel::footnoteModel(const std::string &id) const {
std::map<std::string,shared_ptr<ZLTextModel> >::const_iterator it = myFootnotes.find(id);
return (it != myFootnotes.end()) ? it->second : shared_ptr<ZLTextModel>();
}
ContentsModel::ContentsModel(const std::string &language) : ZLTextTreeModel(language) { ContentsModel::ContentsModel(const std::string &language) : ZLTextTreeModel(language) {
} }

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com> * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
* Copyright (C) 2016 Slava Monich <slava.monich@jolla.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -67,6 +68,7 @@ public:
shared_ptr<ZLTextModel> bookTextModel() const; shared_ptr<ZLTextModel> bookTextModel() const;
shared_ptr<ZLTextModel> contentsModel() const; shared_ptr<ZLTextModel> contentsModel() const;
shared_ptr<ZLTextModel> footnoteModel(const std::string &id) const;
const ZLImageMap &imageMap() const; const ZLImageMap &imageMap() const;
Label label(const std::string &id) const; Label label(const std::string &id) const;

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com> * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
* Copyright (C) 2016 Slava Monich <slava.monich@jolla.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -135,9 +136,11 @@ void BookReader::addHyperlinkControl(FBTextKind kind, const std::string &label)
myHyperlinkKind = kind; myHyperlinkKind = kind;
switch (myHyperlinkKind) { switch (myHyperlinkKind) {
case INTERNAL_HYPERLINK: case INTERNAL_HYPERLINK:
case FOOTNOTE:
myHyperlinkType = "internal"; myHyperlinkType = "internal";
break; break;
case FOOTNOTE:
myHyperlinkType = "footnote";
break;
case EXTERNAL_HYPERLINK: case EXTERNAL_HYPERLINK:
myHyperlinkType = "external"; myHyperlinkType = "external";
break; break;

View file

@ -173,6 +173,14 @@ private:
FBTextKind myControl; FBTextKind myControl;
}; };
class XHTMLTagFootnoteAction : public XHTMLTagAction {
public:
XHTMLTagFootnoteAction();
void doAtStart(XHTMLReader &reader, const char **xmlattributes);
void doAtEnd(XHTMLReader &reader);
};
class XHTMLTagPreAction : public XHTMLTagAction { class XHTMLTagPreAction : public XHTMLTagAction {
public: public:
@ -327,13 +335,21 @@ void XHTMLTagControlAction::doAtStart(XHTMLReader &reader, const char**) {
void XHTMLTagHyperlinkAction::doAtStart(XHTMLReader &reader, const char **xmlattributes) { void XHTMLTagHyperlinkAction::doAtStart(XHTMLReader &reader, const char **xmlattributes) {
const char *href = reader.attributeValue(xmlattributes, "href"); const char *href = reader.attributeValue(xmlattributes, "href");
if (href != 0 && href[0] != '\0') { if (href != 0 && href[0] != '\0') {
const FBTextKind hyperlinkType = MiscUtil::referenceType(href); FBTextKind hyperlinkType;
std::string link = MiscUtil::decodeHtmlURL(href); const char *type = reader.attributeValue(xmlattributes, "epub:type");
if (hyperlinkType == INTERNAL_HYPERLINK) { std::string link;
link = (link[0] == '#') ? if (type && !strcmp(type, "noteref")) {
reader.myReferenceName + link : hyperlinkType = FOOTNOTE;
reader.myReferenceDirName + link; link = href;
link = ZLFileUtil::normalizeUnixPath(link); } else {
hyperlinkType = MiscUtil::referenceType(href);
link = MiscUtil::decodeHtmlURL(href);
if (hyperlinkType == INTERNAL_HYPERLINK) {
link = (link[0] == '#') ?
reader.myReferenceName + link :
reader.myReferenceDirName + link;
link = ZLFileUtil::normalizeUnixPath(link);
}
} }
myHyperlinkStack.push(hyperlinkType); myHyperlinkStack.push(hyperlinkType);
bookReader(reader).addHyperlinkControl(hyperlinkType, link); bookReader(reader).addHyperlinkControl(hyperlinkType, link);
@ -370,6 +386,20 @@ void XHTMLTagParagraphWithControlAction::doAtEnd(XHTMLReader &reader) {
endParagraph(reader); endParagraph(reader);
} }
XHTMLTagFootnoteAction::XHTMLTagFootnoteAction() {
}
void XHTMLTagFootnoteAction::doAtStart(XHTMLReader &reader, const char **xmlattributes) {
const char *id = reader.attributeValue(xmlattributes, "id");
if (id) {
bookReader(reader).setFootnoteTextModel(id);
}
}
void XHTMLTagFootnoteAction::doAtEnd(XHTMLReader &reader) {
bookReader(reader).setMainTextModel();
}
void XHTMLTagPreAction::doAtStart(XHTMLReader &reader, const char**) { void XHTMLTagPreAction::doAtStart(XHTMLReader &reader, const char**) {
endParagraph(reader); endParagraph(reader);
reader.myParseStack.back().kind = PREFORMATTED; reader.myParseStack.back().kind = PREFORMATTED;
@ -431,6 +461,7 @@ void XHTMLReader::fillTagTable() {
addAction("dfn", new XHTMLTagParagraphWithControlAction(DEFINITION)); addAction("dfn", new XHTMLTagParagraphWithControlAction(DEFINITION));
addAction("strike", new XHTMLTagControlAction(STRIKETHROUGH)); addAction("strike", new XHTMLTagControlAction(STRIKETHROUGH));
addAction("blockquote", new XHTMLTagParagraphWithControlAction(BLOCKQUOTE)); addAction("blockquote", new XHTMLTagParagraphWithControlAction(BLOCKQUOTE));
addAction("aside", new XHTMLTagFootnoteAction());
addAction("a", new XHTMLTagHyperlinkAction()); addAction("a", new XHTMLTagHyperlinkAction());

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com> * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
* Copyright (C) 2016 Slava Monich <slava.monich@jolla.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -28,12 +29,16 @@
#include "ZLTextLineInfo.h" #include "ZLTextLineInfo.h"
#include "ZLTextSelectionModel.h" #include "ZLTextSelectionModel.h"
ZLTextArea::ZLTextArea(ZLPaintContext &context, const Properties &properties, ZLTextParagraphCursorCache *cache) : myContext(context), myProperties(properties), myWidth(0), myHeight(0), myParagraphCursorCache(cache) { ZLTextArea::ZLTextArea(ZLPaintContext &context, const Properties &properties, ZLTextParagraphCursorCache *cache) :
myContext(context), myProperties(properties), myHOffset(0), myVOffset(0), myWidth(context.width()), myHeight(context.height()), myParagraphCursorCache(cache) {
} }
ZLTextArea::~ZLTextArea() { ZLTextArea::~ZLTextArea() {
} }
ZLTextArea::Properties::~Properties() {
}
int ZLTextArea::realX(int x) const { int ZLTextArea::realX(int x) const {
return myMirroredContext.isNull() ? x : myMirroredContext->mirroredX(x); return myMirroredContext.isNull() ? x : myMirroredContext->mirroredX(x);
} }
@ -161,7 +166,7 @@ ZLTextSelectionModel &ZLTextArea::selectionModel() {
return *mySelectionModel; return *mySelectionModel;
} }
void ZLTextArea::paint() { void ZLTextArea::paint(ZLSize *size) {
myTextElementMap.clear(); myTextElementMap.clear();
myTreeNodeMap.clear(); myTreeNodeMap.clear();
@ -188,13 +193,20 @@ void ZLTextArea::paint() {
} }
y = 0; y = 0;
int index = 0; int index = 0, w = 0, lastSpaceAfter = 0;
for (std::vector<ZLTextLineInfoPtr>::const_iterator it = myLineInfos.begin(); it != myLineInfos.end(); ++it) { for (std::vector<ZLTextLineInfoPtr>::const_iterator it = myLineInfos.begin(); it != myLineInfos.end(); ++it) {
const ZLTextLineInfo &info = **it; const ZLTextLineInfo &info = **it;
drawTextLine(style, info, y, labels[index], labels[index + 1]); drawTextLine(style, info, y, labels[index], labels[index + 1]);
y += info.Height + info.Descent + info.VSpaceAfter; y += info.Height + info.Descent + info.VSpaceAfter;
lastSpaceAfter = info.VSpaceAfter;
w = std::max(w, info.StartIndent + info.Width);
++index; ++index;
} }
if (size) {
size->myWidth = w;
size->myHeight = y - lastSpaceAfter;
}
} }
bool ZLTextArea::isVisible() const { bool ZLTextArea::isVisible() const {

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com> * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
* Copyright (C) 2016 Slava Monich <slava.monich@jolla.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -39,6 +40,13 @@ class ZLTextLineInfoPtr;
struct ZLTextTreeNodeInfo; struct ZLTextTreeNodeInfo;
class ZLTextSelectionModel; class ZLTextSelectionModel;
struct ZLSize {
int myWidth, myHeight;
ZLSize();
bool isEmpty() const;
};
class ZLTextArea { class ZLTextArea {
public: public:
@ -47,7 +55,7 @@ public:
class Properties { class Properties {
public: public:
~Properties(); virtual ~Properties();
virtual shared_ptr<ZLTextStyle> baseStyle() const = 0; virtual shared_ptr<ZLTextStyle> baseStyle() const = 0;
virtual ZLColor color(const std::string &style = std::string()) const = 0; virtual ZLColor color(const std::string &style = std::string()) const = 0;
virtual bool isSelectionEnabled() const = 0; virtual bool isSelectionEnabled() const = 0;
@ -82,7 +90,7 @@ public:
ZLTextSelectionModel &selectionModel(); ZLTextSelectionModel &selectionModel();
void paint(); void paint(ZLSize *size = 0);
private: private:
void clear(); void clear();
@ -132,7 +140,8 @@ friend class ZLTextAreaController;
friend class ZLTextSelectionModel; friend class ZLTextSelectionModel;
}; };
inline ZLTextArea::Properties::~Properties() {} inline ZLSize::ZLSize() : myWidth(0), myHeight(0) {}
inline bool ZLSize::isEmpty() const { return myWidth <= 0 || myHeight <= 0; }
inline ZLPaintContext &ZLTextArea::context() const { return myMirroredContext.isNull() ? myContext : (ZLPaintContext&)*myMirroredContext; } inline ZLPaintContext &ZLTextArea::context() const { return myMirroredContext.isNull() ? myContext : (ZLPaintContext&)*myMirroredContext; }
inline void ZLTextArea::setSize(size_t width, size_t height) { myWidth = width; myHeight = height; } inline void ZLTextArea::setSize(size_t width, size_t height) { myWidth = width; myHeight = height; }