aboutsummaryrefslogtreecommitdiff
path: root/geminirenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'geminirenderer.cpp')
-rw-r--r--geminirenderer.cpp404
1 files changed, 0 insertions, 404 deletions
diff --git a/geminirenderer.cpp b/geminirenderer.cpp
deleted file mode 100644
index 811a946..0000000
--- a/geminirenderer.cpp
+++ /dev/null
@@ -1,404 +0,0 @@
-#include "geminirenderer.hpp"
-
-#include <QTextList>
-#include <QCryptographicHash>
-#include <QTextBlock>
-#include <QDebug>
-#include <cmath>
-
-static QByteArray trim_whitespace(QByteArray items)
-{
- int start = 0;
- while (start < items.size() and isspace(items.at(start)))
- {
- start += 1;
- }
- int end = items.size() - 1;
- while (end > 0 and isspace(items.at(end)))
- {
- end -= 1;
- }
- return items.mid(start, end - start + 1);
-}
-
-GeminiStyle::GeminiStyle() : theme(Fixed),
- standard_font(),
- h1_font(),
- h2_font(),
- h3_font(),
- preformatted_font(),
- background_color("#edefff"),
- standard_color(0x00, 0x00, 0x00),
- preformatted_color(0x00, 0x00, 0x00),
- h1_color("#022f90"),
- h2_color("#022f90"),
- h3_color("#022f90"),
- internal_link_color("#0e8fff"),
- external_link_color("#0e8fff"),
- cross_scheme_link_color("#0960a7"),
- internal_link_prefix("→ "),
- external_link_prefix("⇒ "),
- margin(55.0)
-{
- preformatted_font.setFamily("monospace");
- preformatted_font.setPointSizeF(10.0);
-
- standard_font.setFamily("sans");
- standard_font.setPointSizeF(10.0);
-
- h1_font.setFamily("sans");
- h1_font.setBold(true);
- h1_font.setPointSizeF(20.0);
-
- h2_font.setFamily("sans");
- h2_font.setBold(true);
- h2_font.setPointSizeF(15.0);
-
- h3_font.setFamily("sans");
- h3_font.setBold(true);
- h3_font.setPointSizeF(12.0);
-}
-
-bool GeminiStyle::save(QSettings &settings) const
-{
- settings.beginGroup("Theme");
-
- settings.setValue("standard_font", standard_font.toString());
- settings.setValue("h1_font", h1_font.toString());
- settings.setValue("h2_font", h2_font.toString());
- settings.setValue("h3_font", h3_font.toString());
- settings.setValue("preformatted_font", preformatted_font.toString());
-
- settings.setValue("background_color", background_color.name());
- settings.setValue("standard_color", standard_color.name());
- settings.setValue("preformatted_color", preformatted_color.name());
- settings.setValue("h1_color", h1_color.name());
- settings.setValue("h2_color", h2_color.name());
- settings.setValue("h3_color", h3_color.name());
- settings.setValue("internal_link_color", internal_link_color.name());
- settings.setValue("external_link_color", external_link_color.name());
- settings.setValue("cross_scheme_link_color", cross_scheme_link_color.name());
-
- settings.setValue("internal_link_prefix", internal_link_prefix);
- settings.setValue("external_link_prefix", external_link_prefix);
-
- settings.setValue("margins", margin);
- settings.setValue("theme", int(theme));
-
- settings.endGroup();
- return true;
-}
-
-bool GeminiStyle::load(QSettings &settings)
-{
- settings.beginGroup("Theme");
-
- if(settings.contains("standard_color"))
- {
- standard_font.fromString(settings.value("standard_font").toString());
- h1_font.fromString(settings.value("h1_font").toString());
- h2_font.fromString(settings.value("h2_font").toString());
- h3_font.fromString(settings.value("h3_font").toString());
- preformatted_font.fromString(settings.value("preformatted_font").toString());
-
- background_color = QColor(settings.value("background_color").toString());
- standard_color = QColor(settings.value("standard_color").toString());
- preformatted_color = QColor(settings.value("preformatted_color").toString());
- h1_color = QColor(settings.value("h1_color").toString());
- h2_color = QColor(settings.value("h2_color").toString());
- h3_color = QColor(settings.value("h3_color").toString());
- internal_link_color = QColor(settings.value("internal_link_color").toString());
- external_link_color = QColor(settings.value("external_link_color").toString());
- cross_scheme_link_color = QColor(settings.value("cross_scheme_link_color").toString());
-
- internal_link_prefix = settings.value("internal_link_prefix").toString();
- external_link_prefix = settings.value("external_link_prefix").toString();
-
- margin = settings.value("margins").toDouble();
- theme = Theme(settings.value("theme").toInt());
- }
-
- settings.endGroup();
- return true;
-}
-
-GeminiStyle GeminiStyle::derive(const QUrl &url) const
-{
- if (this->theme == Fixed)
- return *this;
-
- QByteArray hash = QCryptographicHash::hash(url.host().toUtf8(), QCryptographicHash::Md5);
-
- std::array<uint8_t, 16> items;
- assert(items.size() == hash.size());
- memcpy(items.data(), hash.data(), items.size());
-
- float hue = (items[0] + items[1]) / 510.0;
- float saturation = items[2] / 255.0;
-
- double tmp;
- GeminiStyle themed = *this;
- switch (this->theme)
- {
- case AutoDarkTheme:
- {
- themed.background_color = QColor::fromHslF(hue, saturation, 0.25f);
- themed.standard_color = QColor{0xFF, 0xFF, 0xFF};
-
- themed.h1_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.75);
- themed.h2_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.75);
- themed.h3_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.75);
-
- themed.external_link_color = QColor::fromHslF(std::modf(hue + 0.25, &tmp), 1.0, 0.75);
- themed.internal_link_color = themed.external_link_color.lighter(110);
- themed.cross_scheme_link_color = themed.external_link_color.darker(110);
-
- break;
- }
-
- case AutoLightTheme:
- {
- themed.background_color = QColor::fromHslF(hue, items[2] / 255.0, 0.85);
- themed.standard_color = QColor{0x00, 0x00, 0x00};
-
- themed.h1_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.25);
- themed.h2_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.25);
- themed.h3_color = QColor::fromHslF(std::modf(hue + 0.5, &tmp), 1.0 - saturation, 0.25);
-
- themed.external_link_color = QColor::fromHslF(std::modf(hue + 0.25, &tmp), 1.0, 0.25);
- themed.internal_link_color = themed.external_link_color.darker(110);
- themed.cross_scheme_link_color = themed.external_link_color.lighter(110);
-
- break;
- }
-
- case Fixed:
- assert(false);
- }
-
- // Same for all themes
- themed.preformatted_color = themed.standard_color;
-
- return themed;
-}
-
-GeminiRenderer::GeminiRenderer(GeminiStyle const &_style) : style(_style)
-{
-}
-
-std::unique_ptr<GeminiDocument> GeminiRenderer::render(const QByteArray &input, QUrl const &root_url, DocumentOutlineModel &outline)
-{
- auto themed_style = style.derive(root_url);
-
- QTextCharFormat preformatted;
- preformatted.setFont(themed_style.preformatted_font);
- preformatted.setForeground(themed_style.preformatted_color);
-
- QTextCharFormat standard;
- standard.setFont(themed_style.standard_font);
- standard.setForeground(themed_style.standard_color);
-
- QTextCharFormat standard_link;
- standard_link.setFont(themed_style.standard_font);
- standard_link.setForeground(QBrush(themed_style.internal_link_color));
-
- QTextCharFormat external_link;
- external_link.setFont(themed_style.standard_font);
- external_link.setForeground(QBrush(themed_style.external_link_color));
-
- QTextCharFormat cross_protocol_link;
- cross_protocol_link.setFont(themed_style.standard_font);
- cross_protocol_link.setForeground(QBrush(themed_style.cross_scheme_link_color));
-
- QTextCharFormat standard_h1;
- standard_h1.setFont(themed_style.h1_font);
- standard_h1.setForeground(QBrush(themed_style.h1_color));
-
- QTextCharFormat standard_h2;
- standard_h2.setFont(themed_style.h2_font);
- standard_h2.setForeground(QBrush(themed_style.h2_color));
-
- QTextCharFormat standard_h3;
- standard_h3.setFont(themed_style.h3_font);
- standard_h3.setForeground(QBrush(themed_style.h3_color));
-
- std::unique_ptr<GeminiDocument> result = std::make_unique<GeminiDocument>();
- result->setDocumentMargin(themed_style.margin);
- result->background_color = themed_style.background_color;
-
- QTextCursor cursor{result.get()};
-
- QTextBlockFormat non_list_format = cursor.blockFormat();
-
- bool verbatim = false;
- QTextList *current_list = nullptr;
-
- outline.beginBuild();
-
- int anchor_id = 0;
-
- auto unique_anchor_name = [&]() -> QString {
- return QString("auto-title-%1").arg(++anchor_id);
- };
-
- QList<QByteArray> lines = input.split('\n');
- for (auto const &line : lines)
- {
- if (verbatim)
- {
- if (line.startsWith("```"))
- {
- verbatim = false;
- }
- else
- {
- cursor.setCharFormat(preformatted);
- cursor.insertText(line + "\n");
- }
- }
- else
- {
- if (line.startsWith("*"))
- {
- if (current_list == nullptr)
- {
- cursor.deletePreviousChar();
- current_list = cursor.insertList(QTextListFormat::ListDisc);
- }
- else
- {
- cursor.insertBlock();
- }
-
- QString item = trim_whitespace(line.mid(1));
-
- cursor.insertText(item, standard);
- continue;
- }
- else
- {
- if (current_list != nullptr)
- {
- cursor.insertBlock();
- cursor.setBlockFormat(non_list_format);
- }
- current_list = nullptr;
- }
-
- if (line.startsWith("###"))
- {
- auto heading = trim_whitespace(line.mid(3));
-
- auto id = unique_anchor_name();
- auto fmt = standard_h3;
- fmt.setAnchor(true);
- fmt.setAnchorNames(QStringList { id });
-
- cursor.insertText(heading + "\n", fmt);
- outline.appendH3(heading, id);
- }
- else if (line.startsWith("##"))
- {
- auto heading = trim_whitespace(line.mid(2));
-
- auto id = unique_anchor_name();
- auto fmt = standard_h2;
- fmt.setAnchor(true);
- fmt.setAnchorNames(QStringList { id });
-
- cursor.insertText(heading + "\n", fmt);
- outline.appendH2(heading, id);
- }
- else if (line.startsWith("#"))
- {
- auto heading = trim_whitespace(line.mid(1));
-
- auto id = unique_anchor_name();
- auto fmt = standard_h1;
- fmt.setAnchor(true);
- fmt.setAnchorNames(QStringList { id });
-
- cursor.insertText(heading + "\n", fmt);
- outline.appendH1(heading, id);
- }
- else if (line.startsWith("=>"))
- {
- auto const part = line.mid(2).trimmed();
-
- QByteArray link, title;
-
- int index = -1;
- for (int i = 0; i < part.size(); i++)
- {
- if (isspace(part[i]))
- {
- index = i;
- break;
- }
- }
-
- if (index > 0)
- {
- link = trim_whitespace(part.mid(0, index));
- title = trim_whitespace(part.mid(index + 1));
- }
- else
- {
- link = trim_whitespace(part);
- title = trim_whitespace(part);
- }
-
- auto local_url = QUrl(link);
-
- auto absolute_url = root_url.resolved(QUrl(link));
-
- // qDebug() << link << title;
-
- auto fmt = standard_link;
-
- QString prefix;
- if (absolute_url.host() == root_url.host())
- {
- prefix = themed_style.internal_link_prefix;
- fmt = standard_link;
- }
- else
- {
- prefix = themed_style.external_link_prefix;
- fmt = external_link;
- }
-
- QString suffix = "";
- if (absolute_url.scheme() != root_url.scheme())
- {
- suffix = " [" + absolute_url.scheme().toUpper() + "]";
- fmt = cross_protocol_link;
- }
-
- fmt.setAnchor(true);
- fmt.setAnchorHref(absolute_url.toString());
- cursor.insertText(prefix + title + suffix + "\n", fmt);
- }
- else if (line.startsWith("```"))
- {
- verbatim = true;
- }
- else
- {
- cursor.insertText(line + "\n", standard);
- }
- }
- }
-
- outline.endBuild();
- return result;
-}
-
-GeminiDocument::GeminiDocument(QObject *parent) : QTextDocument(parent),
- background_color(0x00, 0x00, 0x00)
-{
-}
-
-GeminiDocument::~GeminiDocument()
-{
-}