[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) 2016 Slava Monich <slava.monich@jolla.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
@ -51,6 +52,11 @@ BookModel::Label BookModel::label(const std::string &id) const {
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) {
}

View file

@ -1,5 +1,6 @@
/*
* 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
* 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> contentsModel() const;
shared_ptr<ZLTextModel> footnoteModel(const std::string &id) const;
const ZLImageMap &imageMap() 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) 2016 Slava Monich <slava.monich@jolla.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
@ -135,9 +136,11 @@ void BookReader::addHyperlinkControl(FBTextKind kind, const std::string &label)
myHyperlinkKind = kind;
switch (myHyperlinkKind) {
case INTERNAL_HYPERLINK:
case FOOTNOTE:
myHyperlinkType = "internal";
break;
case FOOTNOTE:
myHyperlinkType = "footnote";
break;
case EXTERNAL_HYPERLINK:
myHyperlinkType = "external";
break;

View file

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

View file

@ -1,5 +1,6 @@
/*
* 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
* it under the terms of the GNU General Public License as published by
@ -28,12 +29,16 @@
#include "ZLTextLineInfo.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::Properties::~Properties() {
}
int ZLTextArea::realX(int x) const {
return myMirroredContext.isNull() ? x : myMirroredContext->mirroredX(x);
}
@ -161,7 +166,7 @@ ZLTextSelectionModel &ZLTextArea::selectionModel() {
return *mySelectionModel;
}
void ZLTextArea::paint() {
void ZLTextArea::paint(ZLSize *size) {
myTextElementMap.clear();
myTreeNodeMap.clear();
@ -188,13 +193,20 @@ void ZLTextArea::paint() {
}
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) {
const ZLTextLineInfo &info = **it;
drawTextLine(style, info, y, labels[index], labels[index + 1]);
y += info.Height + info.Descent + info.VSpaceAfter;
lastSpaceAfter = info.VSpaceAfter;
w = std::max(w, info.StartIndent + info.Width);
++index;
}
if (size) {
size->myWidth = w;
size->myHeight = y - lastSpaceAfter;
}
}
bool ZLTextArea::isVisible() const {

View file

@ -1,5 +1,6 @@
/*
* 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
* it under the terms of the GNU General Public License as published by
@ -39,6 +40,13 @@ class ZLTextLineInfoPtr;
struct ZLTextTreeNodeInfo;
class ZLTextSelectionModel;
struct ZLSize {
int myWidth, myHeight;
ZLSize();
bool isEmpty() const;
};
class ZLTextArea {
public:
@ -47,7 +55,7 @@ public:
class Properties {
public:
~Properties();
virtual ~Properties();
virtual shared_ptr<ZLTextStyle> baseStyle() const = 0;
virtual ZLColor color(const std::string &style = std::string()) const = 0;
virtual bool isSelectionEnabled() const = 0;
@ -82,7 +90,7 @@ public:
ZLTextSelectionModel &selectionModel();
void paint();
void paint(ZLSize *size = 0);
private:
void clear();
@ -132,7 +140,8 @@ friend class ZLTextAreaController;
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 void ZLTextArea::setSize(size_t width, size_t height) { myWidth = width; myHeight = height; }