Commit 25568706 authored by Victor Yacovlev's avatar Victor Yacovlev

DocBookViewer: PNG + SVG inline image support

parent f7acb00b
......@@ -13,7 +13,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(QT_USE_QTMAIN 1)
find_package(Qt4 4.7.0 COMPONENTS QtCore QtGui QtXml REQUIRED)
find_package(Qt4 4.7.0 COMPONENTS QtCore QtGui QtXml QtSvg REQUIRED)
include (${QT_USE_FILE})
if(NOT MSVC)
......@@ -75,4 +75,4 @@ else()
add_executable(DocBookViewerApp ${APP_SOURCES} ${APP_MOC_SOURCES} ${APP_UI_SOURCES})
target_link_libraries(DocBookViewerApp ${QT_LIBRARIES} DocBookViewer)
endif()
\ No newline at end of file
endif()
......@@ -154,6 +154,12 @@ QString ContentView::renderElement(ModelPtr data) const
else if (data->modelType() == DocBookModel::Entry) {
return renderEntry(data);
}
else if (data->modelType() == DocBookModel::InlineMediaObject) {
return renderInlineMediaObject(data);
}
else if (data->modelType() == DocBookModel::ImageObject) {
return renderImageObject(data);
}
else {
return "";
}
......@@ -297,10 +303,10 @@ QString ContentView::renderRow(ModelPtr data) const
}
QString result;
if (inTableHead) {
result += "<tr bgcolor='lightgray'>\n";
result += "<tr valign='center' bgcolor='lightgray'>\n";
}
else {
result += "<tr>\n";
result += "<tr valign='center'>\n";
}
result += renderChilds(data);
result += "</tr>\n";
......@@ -324,7 +330,7 @@ QString ContentView::renderEntry(ModelPtr data) const
parent = parent->parent();
}
QString result;
result += "<td align='center'>\n";
result += "<td align='center' valign='center'>\n";
if (inTableHead) {
result += "<b>";
}
......@@ -425,6 +431,60 @@ QString ContentView::renderParagraph(ModelPtr data) const
return result;
}
QString ContentView::renderInlineMediaObject(ModelPtr data) const
{
QString result;
ModelPtr mediaObject = findImageData(data);
if (mediaObject) {
result += renderElement(mediaObject);
}
return result;
}
QString ContentView::renderImageObject(ModelPtr data) const
{
QString result;
ModelPtr imageData;
foreach (ModelPtr child, data->children()) {
if (child->modelType() == DocBookModel::ImageData) {
imageData = child;
break;
}
}
result += "<img src='model_ptr:"+modelToLink(imageData)+"'>";
return result;
}
QVariant ContentView::loadResource(int type, const QUrl &name)
{
QVariant result;
bool ignore = true;
if (type == QTextDocument::ImageResource) {
const QString link = name.toString();
if (link.startsWith("model_ptr:")) {
ignore = false;
QByteArray linkPtr = QByteArray::fromHex(link.toAscii().mid(10));
QDataStream ds(linkPtr);
quintptr rawPointer = 0;
ds >> rawPointer;
if (rawPointer) {
DocBookModel * model =
reinterpret_cast<DocBookModel*>(rawPointer);
if (model->modelType() == DocBookModel::ImageData) {
const QImage & image = model->imageData();
result = image;
}
}
}
}
if (ignore) {
return QTextBrowser::loadResource(type, name);
}
else {
return result;
}
}
QString ContentView::normalizeText(QString textData) const
{
static QMap<QString,QString> replacements;
......@@ -600,6 +660,26 @@ bool ContentView::hasChild(ModelPtr who, ModelPtr childToFind) const
return false;
}
ModelPtr ContentView::findImageData(ModelPtr parent) const
{
ModelPtr svgChild;
ModelPtr pngChild;
foreach (ModelPtr child, parent->children()) {
if (child->modelType()==DocBookModel::ImageObject) {
foreach (ModelPtr childChild, child->children()) {
if (childChild->modelType()==DocBookModel::ImageData) {
if (childChild->format() == "svg") {
svgChild = child;
}
else if (childChild->format() == "png") {
pngChild = child;
}
}
}
}
}
return pngChild ? pngChild : svgChild;
}
QString ContentView::renderTOC(ModelPtr data) const
......
......@@ -58,13 +58,18 @@ private:
QString renderRow(ModelPtr data) const;
QString renderEntry(ModelPtr data) const;
QString renderInlineMediaObject(ModelPtr data) const;
QString renderImageObject(ModelPtr data) const;
bool isPlainPage(ModelPtr data) const;
ModelPtr topLevelModel(ModelPtr data) const;
ModelPtr onePageParentModel(ModelPtr data) const;
ModelPtr findModelById(ModelPtr top, const QString & modelId) const;
ModelPtr findImageData(ModelPtr parent) const;
QString modelToLink(ModelPtr data) const;
bool hasModelOnThisPage(ModelPtr data) const;
bool hasChild(ModelPtr who, ModelPtr child) const;
......@@ -79,6 +84,8 @@ private:
static QString programTextForLanguage(const QString &source,
const QString &language);
QVariant loadResource(int type, const QUrl &name);
private /*fields*/:
QList<ModelPtr> loadedModels_;
mutable struct Counters {
......
......@@ -63,6 +63,8 @@ ModelPtr DocBookFactory::parseDocument(QIODevice *stream,
void DocBookFactory::filterByOs(ModelPtr root) const
{
if (!root)
return;
QString pattern;
#ifdef Q_WS_MAC
pattern = "mac";
......@@ -182,6 +184,15 @@ bool DocBookFactory::startElement(
else if (element == "entry") {
model = new DocBookModel(root_, DocBookModel::Entry);
}
else if (element == "inlinemediaobject") {
model = new DocBookModel(root_, DocBookModel::InlineMediaObject);
}
else if (element == "imageobject") {
model = new DocBookModel(root_, DocBookModel::ImageObject);
}
else if (element == "imagedata") {
model = new DocBookModel(root_, DocBookModel::ImageData);
}
else if (element == "xref") {
model = new DocBookModel(root_, DocBookModel::Xref);
model->xrefLinkEnd_ = atts.value("linkend");
......@@ -204,6 +215,21 @@ bool DocBookFactory::startElement(
model->role_ = atts.value("language");
}
}
if (model->modelType() == DocBookModel::ImageData) {
model->format_ = atts.value("format");
const QString href = atts.value("fileref");
if (href.length() > 0) {
model->href_ = url_.resolved(href);
if (model->format()=="png") {
model->cachedImage_ = QImage(model->href().toLocalFile());
}
else if (model->format()=="svg") {
model->svgRenderer_ = SvgRendererPtr(
new QSvgRenderer(model->href().toLocalFile())
);
}
}
}
root_ = ModelPtr(model);
}
else if (element == "include") {
......@@ -265,6 +291,7 @@ bool DocBookFactory::endElement(const QString &namespaceURI,
<< "example" << "programlisting" << "code"
<< "preface" << "abstract" << "reference"
<< "informaltable" << "table" << "thead" << "tbody" << "row" << "entry"
<< "inlinemediaobject" << "imageobject" << "imagedata"
<< "emphasis" << "xref" << "keycombo" << "keysym";
const QString element = localName.toLower();
if (root_ && element == "title") {
......
#include "docbookmodel.h"
#include "contentrenderer.h"
#include <QImage>
#include <QPainter>
namespace DocBookViewer {
DocBookModel::DocBookModel(ModelPtr parent, const ModelType modelType)
......@@ -57,6 +60,16 @@ const QString& DocBookModel::xrefEndTerm() const
return xrefEndTerm_;
}
const QString DocBookModel::format() const
{
return format_.toLower().trimmed();
}
const QUrl& DocBookModel::href() const
{
return href_;
}
ModelPtr DocBookModel::parent() const
{
return parent_;
......@@ -126,4 +139,16 @@ void DocBookModel::updateSectionLevel()
}
}
const QImage& DocBookModel::imageData() const
{
if (svgRenderer_ && cachedImage_.isNull()) {
const QSize size = svgRenderer_->defaultSize();
QImage img(size, QImage::Format_ARGB32);
QPainter painter(&img);
svgRenderer_->render(&painter);
cachedImage_ = img;
}
return cachedImage_;
}
}
......@@ -4,14 +4,18 @@
// Qt includes
#include <QtGlobal>
#include <QString>
#include <QUrl>
#include <QObject>
#include <QSharedPointer>
#include <QSvgRenderer>
#include <QImage>
namespace DocBookViewer {
static const quint8 MAX_SECTION_LEVEL_IN_TOC = 2u;
typedef QSharedPointer<class DocBookModel> ModelPtr;
typedef QList<ModelPtr>::iterator ModelIterator;
typedef QSharedPointer<QSvgRenderer> SvgRendererPtr;
class DocBookModel
{
......@@ -47,7 +51,10 @@ public:
THead,
TBody,
Row,
Entry
Entry,
InlineMediaObject,
ImageObject,
ImageData
};
quint8 sectionLevel() const;
......@@ -59,11 +66,16 @@ public:
const QString & role() const;
const QString & xrefLinkEnd() const;
const QString & xrefEndTerm() const;
const QUrl & href() const;
const QString format() const;
ModelPtr parent() const;
const QList<ModelPtr>& children() const;
void setParent(ModelPtr parent);
bool isSectioningNode() const;
const QImage& imageData() const;
protected /*methods*/:
explicit DocBookModel(ModelPtr parent, const ModelType modelType);
void updateSectionLevel();
......@@ -81,6 +93,10 @@ protected /*fields*/:
QString xrefLinkEnd_;
QString xrefEndTerm_;
QString role_;
QUrl href_;
QString format_;
mutable SvgRendererPtr svgRenderer_;
mutable QImage cachedImage_;
};
}
......
......@@ -2,7 +2,7 @@
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"
[]>
<chapter xmlns="http://www.oasis-open.org/docbook/xml/4.5/">
<chapter xmlns="http://www.oasis-open.org/docbook/xml/4.5/" xmlns:xi="http://www.w3.org/2001/XInclude">
<title>Имена, величины и выражения</title>
<section>
<title>Имена</title>
......@@ -535,47 +535,113 @@
</thead>
<tbody>
<row>
<entry>TODO</entry>
<entry>
<inlinemediaobject>
<imageobject>
<imagedata format="PNG" fileref="table_of_expressions/sample01.png"/>
</imageobject>
</inlinemediaobject>
</entry>
<entry><code>-1/x**2</code></entry>
</row>
<row>
<entry>TODO</entry>
<entry>
<inlinemediaobject>
<imageobject>
<imagedata format="PNG" fileref="table_of_expressions/sample02.png"/>
</imageobject>
</inlinemediaobject>
</entry>
<entry><code>a/(b*c)</code></entry>
</row>
<row>
<entry>TODO</entry>
<entry>
<inlinemediaobject>
<imageobject>
<imagedata format="PNG" fileref="table_of_expressions/sample03.png"/>
</imageobject>
</inlinemediaobject>
</entry>
<entry><code>a/b*c</code> или <code>(a/b)*c</code></entry>
</row>
<row>
<entry>TODO</entry>
<entry><code>2**(2**(2**n))</code></entry>
<entry>
<inlinemediaobject>
<imageobject>
<imagedata format="PNG" fileref="table_of_expressions/sample04.png"/>
</imageobject>
</inlinemediaobject>
</entry>
<entry><code>2**(2**n)</code></entry>
</row>
<row>
<entry>TODO</entry>
<entry>
<inlinemediaobject>
<imageobject>
<imagedata format="PNG" fileref="table_of_expressions/sample05.png"/>
</imageobject>
</inlinemediaobject>
</entry>
<entry><code>x**(y**z)</code></entry>
</row>
<row>
<entry>TODO</entry>
<entry>
<inlinemediaobject>
<imageobject>
<imagedata format="PNG" fileref="table_of_expressions/sample06.png"/>
</imageobject>
</inlinemediaobject>
</entry>
<entry><code>(-b+sqrt(b**2-4*a*c))/(2*a)</code></entry>
</row>
<row>
<entry>TODO</entry>
<entry>
<inlinemediaobject>
<imageobject>
<imagedata format="PNG" fileref="table_of_expressions/sample07.png"/>
</imageobject>
</inlinemediaobject>
</entry>
<entry><code>sqrt(p*(p-a)*(p-b)*(p-c))</code></entry>
</row>
<row>
<entry>TODO</entry>
<entry>
<inlinemediaobject>
<imageobject>
<imagedata format="PNG" fileref="table_of_expressions/sample08.png"/>
</imageobject>
</inlinemediaobject>
</entry>
<entry><code>(a+b+c)/2</code></entry>
</row>
<row>
<entry>TODO</entry>
<entry>
<inlinemediaobject>
<imageobject>
<imagedata format="PNG" fileref="table_of_expressions/sample09.png"/>
</imageobject>
</inlinemediaobject>
</entry>
<entry><code>sqrt(a**2+b**2-2*a*b*cos(gamma))</code></entry>
</row>
<row>
<entry>TODO</entry>
<entry>
<inlinemediaobject>
<imageobject>
<imagedata format="PNG" fileref="table_of_expressions/sample10.png"/>
</imageobject>
</inlinemediaobject>
</entry>
<entry><code>(a*d+b*c)/(b*d)</code></entry>
</row>
<row>
<entry>TODO</entry>
<entry>
<inlinemediaobject>
<imageobject>
<imagedata format="PNG" fileref="table_of_expressions/sample11.png"/>
</imageobject>
</inlinemediaobject>
</entry>
<entry><code>sin(alpha)*cos(beta)+cos(alpha)*sin(beta)</code></entry>
</row>
</tbody>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment