[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) 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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
Loading…
Reference in a new issue