diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
index 7ce898dda..334b8eadf 100644
--- a/autotests/CMakeLists.txt
+++ b/autotests/CMakeLists.txt
@@ -106,3 +106,12 @@ ecm_add_test(signatureformtest.cpp
TEST_NAME "signatureformtest"
LINK_LIBRARIES Qt5::Test okularcore
)
+
+find_package(Discount "2")
+
+if(discount_FOUND)
+ ecm_add_test(markdowntest.cpp ../generators/markdown/converter.cpp
+ TEST_NAME "markdowntest"
+ LINK_LIBRARIES Qt5::Test okularcore KF5::I18n discount::Lib
+ )
+endif()
diff --git a/autotests/data/1500x300.png b/autotests/data/1500x300.png
new file mode 100644
index 000000000..d6e26b995
Binary files /dev/null and b/autotests/data/1500x300.png differ
diff --git a/autotests/data/300x1500.png b/autotests/data/300x1500.png
new file mode 100644
index 000000000..e10cda14f
Binary files /dev/null and b/autotests/data/300x1500.png differ
diff --git a/autotests/data/imageSizes.md b/autotests/data/imageSizes.md
new file mode 100644
index 000000000..abda7fad2
--- /dev/null
+++ b/autotests/data/imageSizes.md
@@ -0,0 +1,77 @@
+# Test for specifying image sizes in markdown
+
+(c)
+
+## small image
+
+* no explicit size:
+
+
+
+* only width specified `=100x`:
+
+
+
+* only height specified `=x100`:
+
+
+
+* both specified `=100x100`:
+
+
+
+* only width, using html `4200x`:
+
+
+
+* both specified, using html `4200x4200`:
+
+
+
+## wide image
+
+* no explicit size:
+
+
+
+* only width specified `=100x`:
+
+
+
+* only height specified `=x100`:
+
+
+
+* both specified `=100x100`:
+
+
+
+* only height specified, using html `x4200`:
+
+
+
+* both specified, using html `4200x4200`:
+
+
+
+## tall image
+
+* no explicit size:
+
+
+
+* only width specified `=100x`:
+
+
+
+* only height specified `=x100`:
+
+
+
+* both specified `=100x100`:
+
+
+
+* both specified, using html `4200x4200`:
+
+
diff --git a/autotests/markdowntest.cpp b/autotests/markdowntest.cpp
new file mode 100644
index 000000000..57128a981
--- /dev/null
+++ b/autotests/markdowntest.cpp
@@ -0,0 +1,128 @@
+/***************************************************************************
+ * Copyright (C) 2020 by Markus Brenneis *
+ * *
+ * 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 *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include
+
+#include "../settings_core.h"
+#include "core/document.h"
+#include "generators/markdown/converter.h"
+#include
+#include
+#include
+
+class MarkdownTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+
+ void testFancyPantsEnabled();
+ void testFancyPantsDisabled();
+ void testImageSizes();
+
+private:
+ void findImages(QTextFrame *parent, QVector &images);
+ void findImages(const QTextBlock &parent, QVector &images);
+};
+
+void MarkdownTest::initTestCase()
+{
+ Okular::SettingsCore::instance(QStringLiteral("markdowntest"));
+}
+
+void MarkdownTest::testFancyPantsEnabled()
+{
+ Markdown::Converter converter;
+ converter.setFancyPantsEnabled(true);
+ QTextDocument *document = converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md"));
+
+ QTextFrame::iterator secondFrame = ++(document->rootFrame()->begin());
+ QVERIFY(secondFrame.currentBlock().text().startsWith(QStringLiteral("©")));
+}
+
+void MarkdownTest::testFancyPantsDisabled()
+{
+ Markdown::Converter converter;
+ converter.setFancyPantsEnabled(false);
+ QTextDocument *document = converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md"));
+
+ QTextFrame::iterator secondFrame = ++(document->rootFrame()->begin());
+ QVERIFY(secondFrame.currentBlock().text().startsWith(QStringLiteral("(c)")));
+}
+
+void MarkdownTest::testImageSizes()
+{
+ Markdown::Converter converter;
+ QTextDocument *document = converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md"));
+
+ QTextFrame *parent = document->rootFrame();
+
+ QVector images;
+ findImages(parent, images);
+
+ QCOMPARE(images.size(), 17);
+
+ qreal expectedSizes[][2] = {// width, height
+ // small image
+ {412, 349},
+ {100, 84.70873786407767},
+ {118.0515759312321, 100},
+ {100, 100},
+ {890, 753.9077669902913},
+ {890, 890},
+ // wide image
+ {890, 178},
+ {100, 20},
+ {500, 100},
+ {100, 100},
+ {890, 178},
+ {890, 890},
+ // tall image
+ {300, 1500},
+ {100, 500},
+ {20, 100},
+ {100, 100},
+ {890, 890}};
+
+ for (int i = 0; i < images.size(); i++) {
+ QCOMPARE(images[i].width(), expectedSizes[i][0]);
+ QCOMPARE(images[i].height(), expectedSizes[i][1]);
+ }
+}
+
+void MarkdownTest::findImages(QTextFrame *parent, QVector &images)
+{
+ for (QTextFrame::iterator it = parent->begin(); !it.atEnd(); ++it) {
+ QTextFrame *textFrame = it.currentFrame();
+ const QTextBlock textBlock = it.currentBlock();
+
+ if (textFrame) {
+ findImages(textFrame, images);
+ } else if (textBlock.isValid()) {
+ findImages(textBlock, images);
+ }
+ }
+}
+
+void MarkdownTest::findImages(const QTextBlock &parent, QVector &images)
+{
+ for (QTextBlock::iterator it = parent.begin(); !it.atEnd(); ++it) {
+ const QTextFragment textFragment = it.fragment();
+ if (textFragment.isValid()) {
+ const QTextCharFormat textCharFormat = textFragment.charFormat();
+ if (textCharFormat.isImageFormat()) {
+ images.append(textCharFormat.toImageFormat());
+ }
+ }
+ }
+}
+
+QTEST_MAIN(MarkdownTest)
+#include "markdowntest.moc"
diff --git a/generators/markdown/converter.cpp b/generators/markdown/converter.cpp
index 715842ee0..18a1a9ea7 100644
--- a/generators/markdown/converter.cpp
+++ b/generators/markdown/converter.cpp
@@ -9,8 +9,6 @@
#include "converter.h"
-#include "generator_md.h"
-
#include
#include
@@ -41,10 +39,16 @@ extern "C" {
#define MKD_AUTOLINK 0
#endif
+#define PAGE_WIDTH 980
+#define PAGE_HEIGHT 1307
+#define PAGE_MARGIN 45
+#define CONTENT_WIDTH (PAGE_WIDTH - 2 * PAGE_MARGIN)
+
using namespace Markdown;
Converter::Converter()
: m_markdownFile(nullptr)
+ , m_isFancyPantsEnabled(true)
{
}
@@ -96,7 +100,7 @@ QTextDocument *Converter::convertOpenFile()
MMIOT *markdownHandle = mkd_in(m_markdownFile, 0);
int flags = MKD_FENCEDCODE | MKD_GITHUBTAGS | MKD_AUTOLINK | MKD_TOC | MKD_IDANCHOR;
- if (!MarkdownGenerator::isFancyPantsEnabled())
+ if (!m_isFancyPantsEnabled)
flags |= MKD_NOPANTS;
if (!mkd_compile(markdownHandle, flags)) {
emit error(i18n("Failed to compile the Markdown document."), -1);
@@ -109,14 +113,15 @@ QTextDocument *Converter::convertOpenFile()
const QString html = QString::fromUtf8(htmlDocument, size);
QTextDocument *textDocument = new QTextDocument;
- textDocument->setPageSize(QSizeF(980, 1307));
+ textDocument->setPageSize(QSizeF(PAGE_WIDTH, PAGE_HEIGHT));
textDocument->setHtml(html);
- textDocument->setDefaultFont(generator()->generalSettings()->font());
+ if (generator())
+ textDocument->setDefaultFont(generator()->generalSettings()->font());
mkd_cleanup(markdownHandle);
QTextFrameFormat frameFormat;
- frameFormat.setMargin(45);
+ frameFormat.setMargin(PAGE_MARGIN);
QTextFrame *rootFrame = textDocument->rootFrame();
rootFrame->setFrameFormat(frameFormat);
@@ -189,16 +194,13 @@ void Converter::convertImages(const QTextBlock &parent, const QDir &dir, QTextDo
QTextImageFormat format;
+ const qreal specifiedHeight = textCharFormat.toImageFormat().height();
+ const qreal specifiedWidth = textCharFormat.toImageFormat().width();
+
format.setName(QDir::cleanPath(dir.absoluteFilePath(textCharFormat.toImageFormat().name())));
const QImage img = QImage(format.name());
- if (img.width() > 890) {
- format.setWidth(890);
- format.setHeight(img.height() * 890. / img.width());
- } else {
- format.setWidth(img.width());
- format.setHeight(img.height());
- }
+ setImageSize(format, specifiedWidth, specifiedHeight, img.width(), img.height());
QTextCursor cursor(textDocument);
cursor.setPosition(textFragment.position(), QTextCursor::MoveAnchor);
@@ -209,3 +211,30 @@ void Converter::convertImages(const QTextBlock &parent, const QDir &dir, QTextDo
}
}
}
+
+void Converter::setImageSize(QTextImageFormat &format, const qreal specifiedWidth, const qreal specifiedHeight, const qreal originalWidth, const qreal originalHeight)
+{
+ qreal width = 0;
+ qreal height = 0;
+
+ const bool hasSpecifiedSize = specifiedHeight > 0 || specifiedWidth > 0;
+ if (hasSpecifiedSize) {
+ width = specifiedWidth;
+ height = specifiedHeight;
+ if (width == 0 && originalHeight > 0) {
+ width = originalWidth * height / originalHeight;
+ } else if (height == 0 && originalWidth > 0) {
+ height = originalHeight * width / originalWidth;
+ }
+ } else {
+ width = originalWidth;
+ height = originalHeight;
+ }
+
+ if (width > CONTENT_WIDTH) {
+ height = height * CONTENT_WIDTH / width;
+ width = CONTENT_WIDTH;
+ }
+ format.setWidth(width);
+ format.setHeight(height);
+}
diff --git a/generators/markdown/converter.h b/generators/markdown/converter.h
index 6bfb21279..a4e1e2dd2 100644
--- a/generators/markdown/converter.h
+++ b/generators/markdown/converter.h
@@ -32,6 +32,15 @@ public:
void convertAgain();
+ void setFancyPantsEnabled(bool b)
+ {
+ m_isFancyPantsEnabled = b;
+ }
+ bool isFancyPantsEnabled() const
+ {
+ return m_isFancyPantsEnabled;
+ }
+
QTextDocument *convertOpenFile();
private:
@@ -39,9 +48,11 @@ private:
void extractLinks(const QTextBlock &parent, QHash &internalLinks, QHash &documentAnchors);
void convertImages(QTextFrame *parent, const QDir &dir, QTextDocument *textDocument);
void convertImages(const QTextBlock &parent, const QDir &dir, QTextDocument *textDocument);
+ void setImageSize(QTextImageFormat &format, const qreal specifiedWidth, const qreal specifiedHeight, const qreal originalWidth, const qreal originalHeight);
FILE *m_markdownFile;
QDir m_fileDir;
+ bool m_isFancyPantsEnabled;
};
}
diff --git a/generators/markdown/generator_md.cpp b/generators/markdown/generator_md.cpp
index e7dce4e6c..0431bbe15 100644
--- a/generators/markdown/generator_md.cpp
+++ b/generators/markdown/generator_md.cpp
@@ -20,27 +20,27 @@
OKULAR_EXPORT_PLUGIN(MarkdownGenerator, "libokularGenerator_md.json")
-bool MarkdownGenerator::s_isFancyPantsEnabled = true;
-bool MarkdownGenerator::s_wasFancyPantsEnabled = true;
-
MarkdownGenerator::MarkdownGenerator(QObject *parent, const QVariantList &args)
: Okular::TextDocumentGenerator(new Markdown::Converter, QStringLiteral("okular_markdown_generator_settings"), parent, args)
{
Okular::TextDocumentSettings *mdSettings = generalSettings();
- mdSettings->addItemBool(QStringLiteral("SmartyPants"), s_isFancyPantsEnabled, true);
+ mdSettings->addItemBool(QStringLiteral("SmartyPants"), m_isFancyPantsConfigEnabled, true);
mdSettings->load();
- s_wasFancyPantsEnabled = s_isFancyPantsEnabled;
+ m_wasFancyPantsConfigEnabled = m_isFancyPantsConfigEnabled;
+ Markdown::Converter *c = static_cast(converter());
+ c->setFancyPantsEnabled(m_isFancyPantsConfigEnabled);
}
bool MarkdownGenerator::reparseConfig()
{
const bool textDocumentGeneratorChangedConfig = Okular::TextDocumentGenerator::reparseConfig();
- if (s_wasFancyPantsEnabled != s_isFancyPantsEnabled) {
- s_wasFancyPantsEnabled = s_isFancyPantsEnabled;
+ if (m_wasFancyPantsConfigEnabled != m_isFancyPantsConfigEnabled) {
+ m_wasFancyPantsConfigEnabled = m_isFancyPantsConfigEnabled;
Markdown::Converter *c = static_cast(converter());
+ c->setFancyPantsEnabled(m_isFancyPantsConfigEnabled);
c->convertAgain();
setTextDocument(c->document());
diff --git a/generators/markdown/generator_md.h b/generators/markdown/generator_md.h
index 4f64cbc6f..e9a1361a1 100644
--- a/generators/markdown/generator_md.h
+++ b/generators/markdown/generator_md.h
@@ -24,14 +24,9 @@ public:
bool reparseConfig() override;
void addPages(KConfigDialog *dlg) override;
- static bool isFancyPantsEnabled()
- {
- return s_isFancyPantsEnabled;
- }
-
private:
- static bool s_isFancyPantsEnabled;
- static bool s_wasFancyPantsEnabled;
+ bool m_isFancyPantsConfigEnabled = true;
+ bool m_wasFancyPantsConfigEnabled = true;
};
#endif