VTextEdit: support previewing inline images

This commit is contained in:
Le Tan 2017-11-29 21:44:01 +08:00
parent 3e7fa998ee
commit d2ee3e66d6
6 changed files with 432 additions and 77 deletions

View File

@ -23,20 +23,44 @@ bool VImageResourceManager2::contains(const QString &p_name) const
QSet<int> VImageResourceManager2::updateBlockInfos(const QVector<VBlockImageInfo2> &p_blocksInfo) QSet<int> VImageResourceManager2::updateBlockInfos(const QVector<VBlockImageInfo2> &p_blocksInfo)
{ {
QSet<QString> usedImages; QSet<QString> usedImages;
QHash<int, VBlockImageInfo2> newBlocksInfo; QHash<int, QVector<VBlockImageInfo2>> newBlocksInfo;
for (auto const & info : p_blocksInfo) { for (auto const & info : p_blocksInfo) {
auto it = newBlocksInfo.insert(info.m_blockNumber, info); VBlockImageInfo2 *newInfo = NULL;
VBlockImageInfo2 &newInfo = it.value(); auto blockIt = newBlocksInfo.find(info.m_blockNumber);
if (newInfo.m_padding < 0) { if (blockIt == newBlocksInfo.end()) {
newInfo.m_padding = 0; // New block.
QVector<VBlockImageInfo2> vec(1, info);
auto it = newBlocksInfo.insert(info.m_blockNumber, vec);
newInfo = &it.value().last();
} else {
// Multiple images for a block.
QVector<VBlockImageInfo2> &vec = blockIt.value();
int i;
for (i = 0; i < vec.size(); ++i) {
Q_ASSERT(vec[i].m_blockNumber == info.m_blockNumber);
if (info < vec[i]) {
vec.insert(i, info);
newInfo = &vec[i];
break;
}
}
if (i == vec.size()) {
vec.append(info);
newInfo = &vec.last();
}
} }
auto imageIt = m_images.find(newInfo.m_imageName); if (newInfo->m_padding < 0) {
newInfo->m_padding = 0;
}
auto imageIt = m_images.find(newInfo->m_imageName);
if (imageIt != m_images.end()) { if (imageIt != m_images.end()) {
// Fill the width and height. // Fill the width and height.
newInfo.m_imageSize = imageIt.value().size(); newInfo->m_imageSize = imageIt.value().size();
usedImages.insert(newInfo.m_imageName); usedImages.insert(newInfo->m_imageName);
} }
} }
@ -61,7 +85,7 @@ QSet<int> VImageResourceManager2::updateBlockInfos(const QVector<VBlockImageInfo
return affectedBlocks; return affectedBlocks;
} }
const VBlockImageInfo2 *VImageResourceManager2::findImageInfoByBlock(int p_blockNumber) const const QVector<VBlockImageInfo2> *VImageResourceManager2::findImageInfoByBlock(int p_blockNumber) const
{ {
auto it = m_blocksInfo.find(p_blockNumber); auto it = m_blocksInfo.find(p_blockNumber);
if (it != m_blocksInfo.end()) { if (it != m_blocksInfo.end()) {

View File

@ -28,7 +28,7 @@ public:
// Return changed blocks' block number. // Return changed blocks' block number.
QSet<int> updateBlockInfos(const QVector<VBlockImageInfo2> &p_blocksInfo); QSet<int> updateBlockInfos(const QVector<VBlockImageInfo2> &p_blocksInfo);
const VBlockImageInfo2 *findImageInfoByBlock(int p_blockNumber) const; const QVector<VBlockImageInfo2> *findImageInfoByBlock(int p_blockNumber) const;
const QPixmap *findImage(const QString &p_name) const; const QPixmap *findImage(const QString &p_name) const;
@ -39,7 +39,9 @@ private:
QHash<QString, QPixmap> m_images; QHash<QString, QPixmap> m_images;
// Image info of all the blocks with image. // Image info of all the blocks with image.
QHash<int, VBlockImageInfo2> m_blocksInfo; // One block may contain multiple inline images or only one block image.
// If there are multiple inline images, they are sorted by the start position.
QHash<int, QVector<VBlockImageInfo2>> m_blocksInfo;
}; };
#endif // VIMAGERESOURCEMANAGER2_H #endif // VIMAGERESOURCEMANAGER2_H

View File

@ -226,11 +226,6 @@ void VPreviewManager::updateBlockImageInfo(const QVector<ImageLinkInfo> &p_image
for (int i = 0; i < p_imageLinks.size(); ++i) { for (int i = 0; i < p_imageLinks.size(); ++i) {
const ImageLinkInfo &link = p_imageLinks[i]; const ImageLinkInfo &link = p_imageLinks[i];
// Skip inline images.
if (!link.m_isBlock) {
continue;
}
QString name = imageResourceName(link); QString name = imageResourceName(link);
if (name.isEmpty()) { if (name.isEmpty()) {
continue; continue;
@ -240,7 +235,9 @@ void VPreviewManager::updateBlockImageInfo(const QVector<ImageLinkInfo> &p_image
name, name,
link.m_startPos - link.m_blockPos, link.m_startPos - link.m_blockPos,
link.m_endPos - link.m_blockPos, link.m_endPos - link.m_blockPos,
link.m_padding); link.m_padding,
!link.m_isBlock);
blockInfos.push_back(info); blockInfos.push_back(info);
} }
} }

View File

@ -13,6 +13,8 @@
#include "vimageresourcemanager2.h" #include "vimageresourcemanager2.h"
#include "vtextedit.h" #include "vtextedit.h"
#define MARKER_THICKNESS 2
#define MAX_INLINE_IMAGE_HEIGHT 400
VTextDocumentLayout::VTextDocumentLayout(QTextDocument *p_doc, VTextDocumentLayout::VTextDocumentLayout(QTextDocument *p_doc,
VImageResourceManager2 *p_imageMgr) VImageResourceManager2 *p_imageMgr)
@ -223,7 +225,9 @@ void VTextDocumentLayout::draw(QPainter *p_painter, const PaintContext &p_contex
selections, selections,
p_context.clip.isValid() ? p_context.clip : QRectF()); p_context.clip.isValid() ? p_context.clip : QRectF());
drawBlockImage(p_painter, block, offset); drawImages(p_painter, block, offset);
drawMarkers(p_painter, block, offset);
// Draw the cursor. // Draw the cursor.
int blpos = block.position(); int blpos = block.position();
@ -502,8 +506,6 @@ void VTextDocumentLayout::layoutBlock(const QTextBlock &p_block)
QTextDocument *doc = document(); QTextDocument *doc = document();
Q_ASSERT(m_margin == doc->documentMargin()); Q_ASSERT(m_margin == doc->documentMargin());
// The height (y) of the next line.
qreal height = 0;
QTextLayout *tl = p_block.layout(); QTextLayout *tl = p_block.layout();
QTextOption option = doc->defaultTextOption(); QTextOption option = doc->defaultTextOption();
tl->setTextOption(option); tl->setTextOption(option);
@ -521,40 +523,126 @@ void VTextDocumentLayout::layoutBlock(const QTextBlock &p_block)
availableWidth -= (2 * m_margin + extraMargin + m_cursorMargin + m_cursorWidth); availableWidth -= (2 * m_margin + extraMargin + m_cursorMargin + m_cursorWidth);
tl->beginLayout(); QVector<Marker> markers;
QVector<ImagePaintInfo> images;
while (true) { layoutLines(p_block, tl, markers, images, availableWidth, 0);
QTextLine line = tl->createLine();
if (!line.isValid()) {
break;
}
line.setLeadingIncluded(true);
line.setLineWidth(availableWidth);
height += m_lineLeading;
line.setPosition(QPointF(m_margin, height));
height += line.height();
}
tl->endLayout();
// Set this block's line count to its layout's line count. // Set this block's line count to its layout's line count.
// That is one block may occupy multiple visual lines. // That is one block may occupy multiple visual lines.
const_cast<QTextBlock&>(p_block).setLineCount(p_block.isVisible() ? tl->lineCount() : 0); const_cast<QTextBlock&>(p_block).setLineCount(p_block.isVisible() ? tl->lineCount() : 0);
// Update the info about this block. // Update the info about this block.
finishBlockLayout(p_block); finishBlockLayout(p_block, markers, images);
} }
void VTextDocumentLayout::finishBlockLayout(const QTextBlock &p_block) qreal VTextDocumentLayout::layoutLines(const QTextBlock &p_block,
QTextLayout *p_tl,
QVector<Marker> &p_markers,
QVector<ImagePaintInfo> &p_images,
qreal p_availableWidth,
qreal p_height)
{
// Handle block inline image.
bool hasInlineImages = false;
const QVector<VBlockImageInfo2> *info = NULL;
if (m_blockImageEnabled) {
info = m_imageMgr->findImageInfoByBlock(p_block.blockNumber());
if (info
&& !info->isEmpty()
&& info->first().m_inlineImage) {
hasInlineImages = true;
}
}
p_tl->beginLayout();
int imgIdx = 0;
while (true) {
QTextLine line = p_tl->createLine();
if (!line.isValid()) {
break;
}
line.setLeadingIncluded(true);
line.setLineWidth(p_availableWidth);
p_height += m_lineLeading;
if (hasInlineImages) {
QVector<const VBlockImageInfo2 *> images;
QVector<QPair<qreal, qreal>> imageRange;
qreal imgHeight = fetchInlineImagesForOneLine(*info,
&line,
m_margin,
imgIdx,
images,
imageRange);
for (int i = 0; i < images.size(); ++i) {
layoutInlineImage(images[i],
p_height,
imgHeight,
imageRange[i].first,
imageRange[i].second,
p_markers,
p_images);
}
if (!images.isEmpty()) {
p_height += imgHeight + MARKER_THICKNESS + MARKER_THICKNESS;
}
}
line.setPosition(QPointF(m_margin, p_height));
p_height += line.height();
}
p_tl->endLayout();
return p_height;
}
void VTextDocumentLayout::layoutInlineImage(const VBlockImageInfo2 *p_info,
qreal p_heightInBlock,
qreal p_imageSpaceHeight,
qreal p_xStart,
qreal p_xEnd,
QVector<Marker> &p_markers,
QVector<ImagePaintInfo> &p_images)
{
Marker mk;
qreal mky = p_imageSpaceHeight + p_heightInBlock + MARKER_THICKNESS;
mk.m_start = QPointF(p_xStart, mky);
mk.m_end = QPointF(p_xEnd, mky);
p_markers.append(mk);
if (p_info) {
QSize size = p_info->m_imageSize;
scaleSize(size, p_xEnd - p_xStart, p_imageSpaceHeight);
ImagePaintInfo ipi;
ipi.m_name = p_info->m_imageName;
ipi.m_rect = QRectF(QPointF(p_xStart,
p_heightInBlock + p_imageSpaceHeight - size.height()),
size);
p_images.append(ipi);
}
}
void VTextDocumentLayout::finishBlockLayout(const QTextBlock &p_block,
const QVector<Marker> &p_markers,
const QVector<ImagePaintInfo> &p_images)
{ {
// Update rect and offset. // Update rect and offset.
Q_ASSERT(p_block.isValid()); Q_ASSERT(p_block.isValid());
int num = p_block.blockNumber(); int num = p_block.blockNumber();
Q_ASSERT(m_blocks.size() > num); Q_ASSERT(m_blocks.size() > num);
ImagePaintInfo ipi;
BlockInfo &info = m_blocks[num]; BlockInfo &info = m_blocks[num];
info.reset(); info.reset();
info.m_rect = blockRectFromTextLayout(p_block); info.m_rect = blockRectFromTextLayout(p_block, &ipi);
Q_ASSERT(!info.m_rect.isNull()); Q_ASSERT(!info.m_rect.isNull());
int pre = previousValidBlockNumber(num); int pre = previousValidBlockNumber(num);
if (pre == -1) { if (pre == -1) {
@ -563,6 +651,30 @@ void VTextDocumentLayout::finishBlockLayout(const QTextBlock &p_block)
info.m_offset = m_blocks[pre].bottom(); info.m_offset = m_blocks[pre].bottom();
} }
bool hasImage = false;
if (ipi.isValid()) {
Q_ASSERT(p_markers.isEmpty());
Q_ASSERT(p_images.isEmpty());
info.m_images.append(ipi);
hasImage = true;
} else if (!p_markers.isEmpty()) {
// Q_ASSERT(!p_images.isEmpty());
info.m_markers = p_markers;
info.m_images = p_images;
hasImage = true;
}
// Add vertical marker.
if (hasImage) {
// Fill the marker.
// Will be adjusted using offset.
Marker mk;
mk.m_start = QPointF(-1, 0);
mk.m_end = QPointF(-1, info.m_rect.height());
info.m_markers.append(mk);
}
if (info.hasOffset()) { if (info.hasOffset()) {
fillOffsetFrom(num); fillOffsetFrom(num);
} }
@ -622,8 +734,13 @@ int VTextDocumentLayout::cursorWidth() const
return m_cursorWidth; return m_cursorWidth;
} }
QRectF VTextDocumentLayout::blockRectFromTextLayout(const QTextBlock &p_block) QRectF VTextDocumentLayout::blockRectFromTextLayout(const QTextBlock &p_block,
ImagePaintInfo *p_image)
{ {
if (p_image) {
*p_image = ImagePaintInfo();
}
QTextLayout *tl = p_block.layout(); QTextLayout *tl = p_block.layout();
if (tl->lineCount() < 1) { if (tl->lineCount() < 1) {
return QRectF(); return QRectF();
@ -637,17 +754,29 @@ QRectF VTextDocumentLayout::blockRectFromTextLayout(const QTextBlock &p_block)
br.setWidth(qMax(br.width(), tl->lineAt(0).naturalTextWidth())); br.setWidth(qMax(br.width(), tl->lineAt(0).naturalTextWidth()));
} }
// Handle block image. // Handle block non-inline image.
if (m_blockImageEnabled) { if (m_blockImageEnabled) {
const VBlockImageInfo2 *info = m_imageMgr->findImageInfoByBlock(p_block.blockNumber()); const QVector<VBlockImageInfo2> *info = m_imageMgr->findImageInfoByBlock(p_block.blockNumber());
if (info && !info->m_imageSize.isNull()) { if (info && info->size() == 1) {
int maximumWidth = tlRect.width(); const VBlockImageInfo2& img = info->first();
int padding; if (!img.m_inlineImage && !img.m_imageSize.isNull()) {
QSize size; int maximumWidth = tlRect.width();
adjustImagePaddingAndSize(info, maximumWidth, padding, size); int padding;
int dw = padding + size.width() + m_margin - br.width(); QSize size;
int dh = size.height() + m_lineLeading; adjustImagePaddingAndSize(&img, maximumWidth, padding, size);
br.adjust(0, 0, dw > 0 ? dw : 0, dh);
if (p_image) {
p_image->m_name = img.m_imageName;
p_image->m_rect = QRectF(padding + m_margin,
br.height() + m_lineLeading,
size.width(),
size.height());
}
int dw = padding + size.width() + m_margin - br.width();
int dh = size.height() + m_lineLeading;
br.adjust(0, 0, dw > 0 ? dw : 0, dh);
}
} }
} }
@ -729,41 +858,53 @@ void VTextDocumentLayout::adjustImagePaddingAndSize(const VBlockImageInfo2 *p_in
} }
} }
void VTextDocumentLayout::drawBlockImage(QPainter *p_painter, void VTextDocumentLayout::drawImages(QPainter *p_painter,
const QTextBlock &p_block, const QTextBlock &p_block,
const QPointF &p_offset) const QPointF &p_offset)
{ {
if (!m_blockImageEnabled) { if (m_blocks.size() <= p_block.blockNumber()) {
return; return;
} }
const VBlockImageInfo2 *info = m_imageMgr->findImageInfoByBlock(p_block.blockNumber()); const QVector<ImagePaintInfo> &images = m_blocks[p_block.blockNumber()].m_images;
if (!info || info->m_imageSize.isNull()) { if (images.isEmpty()) {
return; return;
} }
const QPixmap *image = m_imageMgr->findImage(info->m_imageName); for (auto const & img : images) {
Q_ASSERT(image); const QPixmap *image = m_imageMgr->findImage(img.m_name);
Q_ASSERT(image);
QRect targetRect = img.m_rect.adjusted(p_offset.x(),
p_offset.y(),
p_offset.x(),
p_offset.y()).toRect();
// Draw block image. p_painter->drawPixmap(targetRect, *image);
QTextLayout *tl = p_block.layout(); }
QRectF tlRect = tl->boundingRect(); }
int maximumWidth = tlRect.width();
int padding;
QSize size;
adjustImagePaddingAndSize(info, maximumWidth, padding, size);
QRect targetRect(p_offset.x() + padding,
p_offset.y() + tlRect.height() + m_lineLeading,
size.width(),
size.height());
p_painter->drawPixmap(targetRect, *image);
// Draw a thin line to link them. void VTextDocumentLayout::drawMarkers(QPainter *p_painter,
const QTextBlock &p_block,
const QPointF &p_offset)
{
if (m_blocks.size() <= p_block.blockNumber()) {
return;
}
const QVector<Marker> &markers = m_blocks[p_block.blockNumber()].m_markers;
if (markers.isEmpty()) {
return;
}
QPen oldPen = p_painter->pen(); QPen oldPen = p_painter->pen();
QPen newPen(m_imageLineColor, 2, Qt::DashLine); QPen newPen(m_imageLineColor, MARKER_THICKNESS, Qt::DashLine);
p_painter->setPen(newPen); p_painter->setPen(newPen);
p_painter->drawLine(QPointF(2, p_offset.y()), QPointF(2, targetRect.bottom()));
for (auto const & mk : markers) {
p_painter->drawLine(mk.m_start + p_offset, mk.m_end + p_offset);
}
p_painter->setPen(oldPen); p_painter->setPen(oldPen);
} }
@ -810,3 +951,101 @@ void VTextDocumentLayout::relayout(const QSet<int> &p_blocks)
updateDocumentSize(); updateDocumentSize();
} }
qreal VTextDocumentLayout::fetchInlineImagesForOneLine(const QVector<VBlockImageInfo2> &p_info,
const QTextLine *p_line,
qreal p_margin,
int &p_index,
QVector<const VBlockImageInfo2 *> &p_images,
QVector<QPair<qreal, qreal>> &p_imageRange)
{
qreal maxHeight = 0;
int start = p_line->textStart();
int end = p_line->textLength() + start;
for (int i = 0; i < p_info.size(); ++i) {
const VBlockImageInfo2 &img = p_info[i];
Q_ASSERT(img.m_inlineImage);
if (img.m_imageSize.isNull()) {
p_index = i + 1;
continue;
}
if (img.m_startPos >= start && img.m_startPos < end) {
// Start of a new image.
qreal startX = p_line->cursorToX(img.m_startPos) + p_margin;
qreal endX;
if (img.m_endPos <= end) {
// End an image.
endX = p_line->cursorToX(img.m_endPos) + p_margin;
p_images.append(&img);
p_imageRange.append(QPair<qreal, qreal>(startX, endX));
QSize size = img.m_imageSize;
scaleSize(size, endX - startX, MAX_INLINE_IMAGE_HEIGHT);
if (size.height() > maxHeight) {
maxHeight = size.height();
}
// Image i has been drawn.
p_index = i + 1;
} else {
// This image cross the line.
endX = p_line->x() + p_line->width() + p_margin;
if (end - img.m_startPos >= ((img.m_endPos - img.m_startPos) >> 1)) {
// Put image at this side.
p_images.append(&img);
p_imageRange.append(QPair<qreal, qreal>(startX, endX));
QSize size = img.m_imageSize;
scaleSize(size, endX - startX, MAX_INLINE_IMAGE_HEIGHT);
if (size.height() > maxHeight) {
maxHeight = size.height();
}
// Image i has been drawn.
p_index = i + 1;
} else {
// Just put a marker here.
p_images.append(NULL);
p_imageRange.append(QPair<qreal, qreal>(startX, endX));
}
break;
}
} else if (img.m_endPos > start && img.m_startPos < start) {
qreal startX = p_line->x() + p_margin;
qreal endX = img.m_endPos > end ? p_line->x() + p_line->width()
: p_line->cursorToX(img.m_endPos);
if (p_index <= i) {
// Image i has not been drawn. Draw it here.
p_images.append(&img);
p_imageRange.append(QPair<qreal, qreal>(startX, endX));
QSize size = img.m_imageSize;
scaleSize(size, endX - startX, MAX_INLINE_IMAGE_HEIGHT);
if (size.height() > maxHeight) {
maxHeight = size.height();
}
// Image i has been drawn.
p_index = i + 1;
} else {
// Image i has been drawn. Just put a marker here.
p_images.append(NULL);
p_imageRange.append(QPair<qreal, qreal>(startX, endX));
}
if (img.m_endPos >= end) {
break;
}
} else if (img.m_endPos <= start) {
continue;
} else {
break;
}
}
return maxHeight;
}

View File

@ -57,6 +57,27 @@ protected:
void documentChanged(int p_from, int p_charsRemoved, int p_charsAdded) Q_DECL_OVERRIDE; void documentChanged(int p_from, int p_charsRemoved, int p_charsAdded) Q_DECL_OVERRIDE;
private: private:
// Denote the start and end position of a marker line.
struct Marker
{
QPointF m_start;
QPointF m_end;
};
struct ImagePaintInfo
{
// The rect to draw the image.
QRectF m_rect;
// Name of the image.
QString m_name;
bool isValid()
{
return !m_name.isEmpty();
}
};
struct BlockInfo struct BlockInfo
{ {
BlockInfo() BlockInfo()
@ -68,6 +89,8 @@ private:
{ {
m_offset = -1; m_offset = -1;
m_rect = QRectF(); m_rect = QRectF();
m_markers.clear();
m_images.clear();
} }
bool hasOffset() const bool hasOffset() const
@ -94,10 +117,50 @@ private:
// The bounding rect of this block, including the margins. // The bounding rect of this block, including the margins.
// Null for invalid. // Null for invalid.
QRectF m_rect; QRectF m_rect;
// Markers to draw for this block.
// Y is the offset within this block.
QVector<Marker> m_markers;
// Images to draw for this block.
// Y is the offset within this block.
QVector<ImagePaintInfo> m_images;
}; };
void layoutBlock(const QTextBlock &p_block); void layoutBlock(const QTextBlock &p_block);
// Returns the total height of this block after layouting lines and inline
// images.
qreal layoutLines(const QTextBlock &p_block,
QTextLayout *p_tl,
QVector<Marker> &p_markers,
QVector<ImagePaintInfo> &p_images,
qreal p_availableWidth,
qreal p_height);
// Layout inline image in a line.
// @p_info: if NULL, means just layout a marker.
// Returns the image height.
void layoutInlineImage(const VBlockImageInfo2 *p_info,
qreal p_heightInBlock,
qreal p_imageSpaceHeight,
qreal p_xStart,
qreal p_xEnd,
QVector<Marker> &p_markers,
QVector<ImagePaintInfo> &p_images);
// Get inline images belonging to @p_line from @p_info.
// @p_index: image [0, p_index) has been drawn.
// @p_images: contains all images and markers (NULL element indicates it
// is just a placeholder for the marker.
// Returns the maximum height of the images.
qreal fetchInlineImagesForOneLine(const QVector<VBlockImageInfo2> &p_info,
const QTextLine *p_line,
qreal p_margin,
int &p_index,
QVector<const VBlockImageInfo2 *> &p_images,
QVector<QPair<qreal, qreal>> &p_imageRange);
// Clear the layout of @p_block. // Clear the layout of @p_block.
// Also clear all the offset behind this block. // Also clear all the offset behind this block.
void clearBlockLayout(QTextBlock &p_block); void clearBlockLayout(QTextBlock &p_block);
@ -115,7 +178,9 @@ private:
bool validateBlocks() const; bool validateBlocks() const;
void finishBlockLayout(const QTextBlock &p_block); void finishBlockLayout(const QTextBlock &p_block,
const QVector<Marker> &p_markers,
const QVector<ImagePaintInfo> &p_images);
int previousValidBlockNumber(int p_number) const; int previousValidBlockNumber(int p_number) const;
@ -136,8 +201,11 @@ private:
void blockRangeFromRectBS(const QRectF &p_rect, int &p_first, int &p_last) const; void blockRangeFromRectBS(const QRectF &p_rect, int &p_first, int &p_last) const;
// Return a rect from the layout. // Return a rect from the layout.
// If @p_imageRect is not NULL and there is block image for this block, it will
// be set to the rect of that image.
// Return a null rect if @p_block has not been layouted. // Return a null rect if @p_block has not been layouted.
QRectF blockRectFromTextLayout(const QTextBlock &p_block); QRectF blockRectFromTextLayout(const QTextBlock &p_block,
ImagePaintInfo *p_image = NULL);
// Update document size when only block @p_blockNumber is changed and the height // Update document size when only block @p_blockNumber is changed and the height
// remain the same. // remain the same.
@ -150,9 +218,15 @@ private:
// Draw images of block @p_block. // Draw images of block @p_block.
// @p_offset: the offset for the drawing of the block. // @p_offset: the offset for the drawing of the block.
void drawBlockImage(QPainter *p_painter, void drawImages(QPainter *p_painter,
const QTextBlock &p_block, const QTextBlock &p_block,
const QPointF &p_offset); const QPointF &p_offset);
void drawMarkers(QPainter *p_painter,
const QTextBlock &p_block,
const QPointF &p_offset);
void scaleSize(QSize &p_size, int p_width, int p_height);
// Document margin on left/right/bottom. // Document margin on left/right/bottom.
qreal m_margin; qreal m_margin;
@ -201,4 +275,10 @@ inline void VTextDocumentLayout::setImageLineColor(const QColor &p_color)
m_imageLineColor = p_color; m_imageLineColor = p_color;
} }
inline void VTextDocumentLayout::scaleSize(QSize &p_size, int p_width, int p_height)
{
if (p_size.width() > p_width || p_size.height() > p_height) {
p_size.scale(p_width, p_height, Qt::KeepAspectRatio);
}
}
#endif // VTEXTDOCUMENTLAYOUT_H #endif // VTEXTDOCUMENTLAYOUT_H

View File

@ -50,6 +50,19 @@ public:
&& m_imageSize == p_other.m_imageSize; && m_imageSize == p_other.m_imageSize;
} }
bool operator<(const VBlockImageInfo2 &p_other) const
{
if (m_blockNumber < p_other.m_blockNumber) {
return true;
} else if (m_blockNumber > p_other.m_blockNumber) {
return false;
} else if (m_startPos < p_other.m_startPos) {
return true;
} else {
return false;
}
}
QString toString() const QString toString() const
{ {
return QString("VBlockImageInfo2 block %1 start %2 end %3 padding %4 " return QString("VBlockImageInfo2 block %1 start %2 end %3 padding %4 "