[fbreader] Support for footnotes
This commit is contained in:
parent
c2558fbb3f
commit
35757ce03d
6 changed files with 77 additions and 14 deletions
|
@ -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) {
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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; }
|
||||
|
|
Loading…
Reference in a new issue