preview: support force background for previewed images

- Add [editor]/preview-image-background config in MDHL;
- Will fill background first before drawing an image if specified;
This commit is contained in:
Le Tan 2018-06-06 21:53:02 +08:00
parent d59a1010c5
commit 93b26f41e4
11 changed files with 98 additions and 22 deletions

View File

@ -37,6 +37,8 @@ color-column-background: c9302c
color-column-foreground: eeeeee color-column-foreground: eeeeee
# [VNote] Style for preview image line # [VNote] Style for preview image line
preview-image-line-foreground: 6f5799 preview-image-line-foreground: 6f5799
# [VNote] Style for preview image (useful for SVG in dark theme)
preview-image-background: b0bec5
# [VNote] Style for MathJax # [VNote] Style for MathJax
mathjax-foreground: 4db6ac mathjax-foreground: 4db6ac

View File

@ -7,7 +7,7 @@ mdhl_file=v_moonlight.mdhl
css_file=v_moonlight.css css_file=v_moonlight.css
codeblock_css_file=v_moonlight_codeblock.css codeblock_css_file=v_moonlight_codeblock.css
mermaid_css_file=v_moonlight_mermaid.css mermaid_css_file=v_moonlight_mermaid.css
version=11 version=12
; This mapping will be used to translate colors when the content of HTML is copied ; This mapping will be used to translate colors when the content of HTML is copied
; without background. You could just specify the foreground colors mapping here. ; without background. You could just specify the foreground colors mapping here.

View File

@ -634,6 +634,7 @@ void VConfigManager::updateMarkdownEditStyle()
m_editorColorColumnBg = defaultColor; m_editorColorColumnBg = defaultColor;
m_editorColorColumnFg = defaultColor; m_editorColorColumnFg = defaultColor;
m_editorPreviewImageLineFg = defaultColor; m_editorPreviewImageLineFg = defaultColor;
m_editorPreviewImageBg.clear();
m_editorMathjaxFg = defaultColor; m_editorMathjaxFg = defaultColor;
auto editorIt = styles.find("editor"); auto editorIt = styles.find("editor");
@ -708,6 +709,11 @@ void VConfigManager::updateMarkdownEditStyle()
m_editorPreviewImageLineFg = "#" + *it; m_editorPreviewImageLineFg = "#" + *it;
} }
it = editorIt->find("preview-image-background");
if (it != editorIt->end()) {
m_editorPreviewImageBg = "#" + *it;
}
it = editorIt->find("mathjax-foreground"); it = editorIt->find("mathjax-foreground");
if (it != editorIt->end()) { if (it != editorIt->end()) {
m_editorMathjaxFg = "#" + *it; m_editorMathjaxFg = "#" + *it;

View File

@ -327,6 +327,8 @@ public:
const QString &getEditorPreviewImageLineFg() const; const QString &getEditorPreviewImageLineFg() const;
const QString &getEditorPreviewImageBg() const;
const QString &getEditorMathjaxFg() const; const QString &getEditorMathjaxFg() const;
bool getEnableCodeBlockLineNumber() const; bool getEnableCodeBlockLineNumber() const;
@ -812,6 +814,9 @@ private:
// The foreground color of the preview image line. // The foreground color of the preview image line.
QString m_editorPreviewImageLineFg; QString m_editorPreviewImageLineFg;
// The forced background color of the preview image. Can be empty.
QString m_editorPreviewImageBg;
// The foreground color of the MathJax. // The foreground color of the MathJax.
QString m_editorMathjaxFg; QString m_editorMathjaxFg;
@ -1897,6 +1902,11 @@ inline const QString &VConfigManager::getEditorPreviewImageLineFg() const
return m_editorPreviewImageLineFg; return m_editorPreviewImageLineFg;
} }
inline const QString &VConfigManager::getEditorPreviewImageBg() const
{
return m_editorPreviewImageBg;
}
inline const QString &VConfigManager::getEditorMathjaxFg() const inline const QString &VConfigManager::getEditorMathjaxFg() const
{ {
return m_editorMathjaxFg; return m_editorMathjaxFg;

View File

@ -40,7 +40,8 @@ CodeBlockPreviewInfo::CodeBlockPreviewInfo(const VCodeBlock &p_cb)
void CodeBlockPreviewInfo::updateInplacePreview(const VEditor *p_editor, void CodeBlockPreviewInfo::updateInplacePreview(const VEditor *p_editor,
const QTextDocument *p_doc, const QTextDocument *p_doc,
const QPixmap &p_image) const QPixmap &p_image,
const QString &p_background)
{ {
QTextBlock block = p_doc->findBlockByNumber(m_codeBlock.m_endBlock); QTextBlock block = p_doc->findBlockByNumber(m_codeBlock.m_endBlock);
if (block.isValid()) { if (block.isValid()) {
@ -53,6 +54,7 @@ void CodeBlockPreviewInfo::updateInplacePreview(const VEditor *p_editor,
preview->m_padding = VPreviewManager::calculateBlockMargin(block, preview->m_padding = VPreviewManager::calculateBlockMargin(block,
p_editor->tabStopWidthW()); p_editor->tabStopWidthW());
preview->m_name = QString::number(getImageIndex()); preview->m_name = QString::number(getImageIndex());
preview->m_background = p_background;
preview->m_isBlock = true; preview->m_isBlock = true;
preview->m_image = p_image; preview->m_image = p_image;
@ -158,7 +160,16 @@ void VLivePreviewHelper::updateCodeBlocks(const QVector<VCodeBlock> &p_codeBlock
entry->m_ts = m_timeStamp; entry->m_ts = m_timeStamp;
cached = true; cached = true;
m_codeBlocks[idx].setImageData(entry->m_imgFormat, entry->m_imgData); m_codeBlocks[idx].setImageData(entry->m_imgFormat, entry->m_imgData);
m_codeBlocks[idx].updateInplacePreview(m_editor, m_doc, entry->m_image);
QString background;
if (vcb.m_lang == "puml") {
background = g_config->getEditorPreviewImageBg();
}
m_codeBlocks[idx].updateInplacePreview(m_editor,
m_doc,
entry->m_image,
background);
} }
if (m_inplacePreviewEnabled if (m_inplacePreviewEnabled
@ -323,13 +334,20 @@ void VLivePreviewHelper::localAsyncResultReady(int p_id,
Q_UNUSED(p_format); Q_UNUSED(p_format);
Q_ASSERT(p_format == "svg"); Q_ASSERT(p_format == "svg");
int idx = p_id & INDEX_MASK;
bool livePreview = (p_id & TYPE_MASK) == TYPE_LIVE_PREVIEW;
QString lang;
int idx = p_id & INDEX_MASK;
if (idx >= m_codeBlocks.size()) {
return;
}
bool livePreview = (p_id & TYPE_MASK) == TYPE_LIVE_PREVIEW;
QString lang;
QString background;
switch (p_id & LANG_PREFIX_MASK) { switch (p_id & LANG_PREFIX_MASK) {
case LANG_PREFIX_PLANTUML: case LANG_PREFIX_PLANTUML:
lang = "puml"; lang = "puml";
background = g_config->getEditorPreviewImageBg();
break; break;
case LANG_PREFIX_GRAPHVIZ: case LANG_PREFIX_GRAPHVIZ:
@ -340,10 +358,6 @@ void VLivePreviewHelper::localAsyncResultReady(int p_id,
return; return;
} }
if (idx >= m_codeBlocks.size()) {
return;
}
CodeBlockPreviewInfo &cb = m_codeBlocks[idx]; CodeBlockPreviewInfo &cb = m_codeBlocks[idx];
const QString &text = cb.codeBlock().m_text; const QString &text = cb.codeBlock().m_text;
@ -354,7 +368,7 @@ void VLivePreviewHelper::localAsyncResultReady(int p_id,
m_cache.insert(text, entry); m_cache.insert(text, entry);
cb.setImageData(p_format, p_result); cb.setImageData(p_format, p_result);
cb.updateInplacePreview(m_editor, m_doc, entry->m_image); cb.updateInplacePreview(m_editor, m_doc, entry->m_image, background);
if (livePreview) { if (livePreview) {
if (idx != m_cbIndex) { if (idx != m_cbIndex) {

View File

@ -23,7 +23,15 @@ public:
void updateInplacePreview(const VEditor *p_editor, void updateInplacePreview(const VEditor *p_editor,
const QTextDocument *p_doc, const QTextDocument *p_doc,
const QPixmap &p_image); const QPixmap &p_image,
const QString &p_background);
void updateInplacePreview(const VEditor *p_editor,
const QTextDocument *p_doc,
const QPixmap &p_image)
{
updateInplacePreview(p_editor, p_doc, p_image, QString());
}
VCodeBlock &codeBlock() VCodeBlock &codeBlock()
{ {

View File

@ -395,7 +395,8 @@ void VPreviewManager::updateBlockPreviewInfo(TS p_timeStamp,
link.m_padding, link.m_padding,
!link.m_isBlock, !link.m_isBlock,
name, name,
m_editor->imageSize(name)); m_editor->imageSize(name),
QString());
bool tsUpdated = blockData->insertPreviewInfo(info); bool tsUpdated = blockData->insertPreviewInfo(info);
imageCache(PreviewSource::ImageLink).insert(name, p_timeStamp); imageCache(PreviewSource::ImageLink).insert(name, p_timeStamp);
if (!tsUpdated) { if (!tsUpdated) {
@ -441,7 +442,8 @@ void VPreviewManager::updateBlockPreviewInfo(TS p_timeStamp,
img->m_padding, img->m_padding,
!img->m_isBlock, !img->m_isBlock,
name, name,
m_editor->imageSize(name)); m_editor->imageSize(name),
img->m_background);
bool tsUpdated = blockData->insertPreviewInfo(info); bool tsUpdated = blockData->insertPreviewInfo(info);
imageCache(p_source).insert(name, p_timeStamp); imageCache(p_source).insert(name, p_timeStamp);
if (!tsUpdated) { if (!tsUpdated) {

View File

@ -25,6 +25,7 @@ struct VImageToPreview
m_padding = 0; m_padding = 0;
m_image = QPixmap(); m_image = QPixmap();
m_name.clear(); m_name.clear();
m_background.clear();
m_isBlock = true; m_isBlock = true;
}; };
@ -45,6 +46,9 @@ struct VImageToPreview
// If @m_name are the same, then they are the same imges. // If @m_name are the same, then they are the same imges.
QString m_name; QString m_name;
// If not empty, we should draw a background before drawing this image.
QString m_background;
// Whether it is an image block. // Whether it is an image block.
bool m_isBlock; bool m_isBlock;
}; };

View File

@ -30,13 +30,15 @@ struct VPreviewedImageInfo
int p_padding, int p_padding,
bool p_inline, bool p_inline,
const QString &p_imageName, const QString &p_imageName,
const QSize &p_imageSize) const QSize &p_imageSize,
const QString &p_background)
: m_startPos(p_startPos), : m_startPos(p_startPos),
m_endPos(p_endPos), m_endPos(p_endPos),
m_padding(p_padding), m_padding(p_padding),
m_inline(p_inline), m_inline(p_inline),
m_imageName(p_imageName), m_imageName(p_imageName),
m_imageSize(p_imageSize) m_imageSize(p_imageSize),
m_background(p_background)
{ {
} }
@ -52,7 +54,8 @@ struct VPreviewedImageInfo
&& m_padding == a.m_padding && m_padding == a.m_padding
&& m_inline == a.m_inline && m_inline == a.m_inline
&& m_imageName == a.m_imageName && m_imageName == a.m_imageName
&& m_imageSize == a.m_imageSize; && m_imageSize == a.m_imageSize
&& m_background == a.m_background;
} }
bool intersect(const VPreviewedImageInfo &a) const bool intersect(const VPreviewedImageInfo &a) const
@ -62,14 +65,15 @@ struct VPreviewedImageInfo
QString toString() const QString toString() const
{ {
return QString("previewed image (%1): [%2, %3] padding %4 inline %5 (%6,%7)") return QString("previewed image (%1): [%2, %3] padding %4 inline %5 (%6,%7) bg(%8)")
.arg(m_imageName) .arg(m_imageName)
.arg(m_startPos) .arg(m_startPos)
.arg(m_endPos) .arg(m_endPos)
.arg(m_padding) .arg(m_padding)
.arg(m_inline) .arg(m_inline)
.arg(m_imageSize.width()) .arg(m_imageSize.width())
.arg(m_imageSize.height()); .arg(m_imageSize.height())
.arg(m_background);
} }
// Start position of text corresponding to the image within block. // Start position of text corresponding to the image within block.
@ -89,6 +93,9 @@ struct VPreviewedImageInfo
// Image size of the image. Cache for performance. // Image size of the image. Cache for performance.
QSize m_imageSize; QSize m_imageSize;
// Forced background before drawing this image.
QString m_background;
}; };
@ -107,7 +114,8 @@ struct VPreviewInfo
int p_padding, int p_padding,
bool p_inline, bool p_inline,
const QString &p_imageName, const QString &p_imageName,
const QSize &p_imageSize) const QSize &p_imageSize,
const QString &p_background)
: m_source(p_source), : m_source(p_source),
m_timeStamp(p_timeStamp), m_timeStamp(p_timeStamp),
m_imageInfo(p_startPos, m_imageInfo(p_startPos,
@ -115,7 +123,8 @@ struct VPreviewInfo
p_padding, p_padding,
p_inline, p_inline,
p_imageName, p_imageName,
p_imageSize) p_imageSize,
p_background)
{ {
} }

View File

@ -674,6 +674,10 @@ void VTextDocumentLayout::layoutInlineImage(const VPreviewedImageInfo *p_info,
ipi.m_rect = QRectF(QPointF(p_xStart, ipi.m_rect = QRectF(QPointF(p_xStart,
p_heightInBlock + p_imageSpaceHeight - size.height()), p_heightInBlock + p_imageSpaceHeight - size.height()),
size); size);
if (!p_info->m_background.isEmpty()) {
ipi.m_background = QColor(p_info->m_background);
}
p_images.append(ipi); p_images.append(ipi);
} }
} }
@ -820,6 +824,9 @@ QRectF VTextDocumentLayout::blockRectFromTextLayout(const QTextBlock &p_block,
br.height() + m_lineLeading, br.height() + m_lineLeading,
size.width(), size.width(),
size.height()); size.height());
if (!img.m_background.isEmpty()) {
p_image->m_background = QColor(img.m_background);
}
} }
int dw = padding + size.width() + m_margin - br.width(); int dw = padding + size.width() + m_margin - br.width();
@ -932,6 +939,12 @@ void VTextDocumentLayout::drawImages(QPainter *p_painter,
p_offset.x(), p_offset.x(),
p_offset.y()).toRect(); p_offset.y()).toRect();
// Qt do not render the background of some SVGs.
// We add a forced background mechanism to complement this.
if (img.hasForcedBackground()) {
p_painter->fillRect(targetRect, img.m_background);
}
p_painter->drawPixmap(targetRect, *image); p_painter->drawPixmap(targetRect, *image);
} }
} }

View File

@ -99,10 +99,18 @@ private:
// Name of the image. // Name of the image.
QString m_name; QString m_name;
bool isValid() // Forced background.
QColor m_background;
bool isValid() const
{ {
return !m_name.isEmpty(); return !m_name.isEmpty();
} }
bool hasForcedBackground() const
{
return m_background.isValid();
}
}; };
struct BlockInfo struct BlockInfo