Issue #123: Drawing texts, finishing painter

This commit is contained in:
Jakub Melka 2024-02-11 13:58:07 +01:00
parent d1d0fe30d6
commit f80b7b059e
2 changed files with 190 additions and 11 deletions

View File

@ -19,6 +19,7 @@
#include "pdffont.h"
#include <QThread>
#include <QRawFont>
#include <QPainterPath>
#include <QPaintEngine>
@ -83,6 +84,9 @@ private:
/// Returns composition operator
static BLCompOp getBLCompOp(QPainter::CompositionMode mode);
void setFillRule(Qt::FillRule fillRule);
void updateFont(QFont newFont);
bool isStrokeActive() const { return m_currentPen.style() != Qt::NoPen; }
bool isFillActive() const { return m_currentBrush.style() != Qt::NoBrush; }
@ -94,6 +98,7 @@ private:
QPen m_currentPen;
QBrush m_currentBrush;
QFont m_currentFont;
QRawFont m_currentRawFont;
};
PDFBLPaintDevice::PDFBLPaintDevice(QImage& offscreenBuffer, bool isMultithreaded) :
@ -191,6 +196,10 @@ bool PDFBLPaintEngine::begin(QPaintDevice*)
qreal devicePixelRatio = m_qtOffscreenBuffer.devicePixelRatioF();
m_blContext->scale(devicePixelRatio);
m_blContext->userToMeta();
setBLPen(m_blContext.value(), m_currentPen);
setBLBrush(m_blContext.value(), m_currentBrush);
updateFont(QFont());
return true;
}
else
@ -215,10 +224,26 @@ bool PDFBLPaintEngine::end()
return true;
}
void PDFBLPaintEngine::updateFont(QFont newFont)
{
m_currentFont = newFont;
m_currentFont.setHintingPreference(QFont::PreferNoHinting);
PDFReal pixelSize = m_currentFont.pixelSize();
if (pixelSize == -1)
{
PDFReal pointSizeF = m_currentFont.pointSizeF();
PDFReal dpi = m_qtOffscreenBuffer.logicalDpiY();
pixelSize = pointSizeF / 72 * dpi;
m_currentFont.setPixelSize(pixelSize);
}
m_currentRawFont = QRawFont::fromFont(m_currentFont);
}
void PDFBLPaintEngine::updateState(const QPaintEngineState& updatedState)
{
/* DirtyBrushOrigin = 0x0004,
DirtyFont = 0x0008,
DirtyBackground = 0x0010,
DirtyBackgroundMode = 0x0020,
DirtyClipRegion = 0x0080,
@ -252,6 +277,11 @@ void PDFBLPaintEngine::updateState(const QPaintEngineState& updatedState)
{
m_blContext->setMatrix(getBLMatrix(updatedState.transform()));
}
if (updatedState.state().testFlag(QPaintEngine::DirtyFont))
{
updateFont(updatedState.font());
}
}
void PDFBLPaintEngine::drawRects(const QRect* rects, int rectCount)
@ -356,20 +386,18 @@ void PDFBLPaintEngine::drawEllipse(const QRect& r)
}
}
void PDFBLPaintEngine::drawPath(const QPainterPath& path)
void PDFBLPaintEngine::setFillRule(Qt::FillRule fillRule)
{
BLPath blPath = getBLPath(path);
BLFillRule blFillRule{};
BLFillRule fillRule{};
switch (path.fillRule())
switch (fillRule)
{
case Qt::OddEvenFill:
fillRule = BL_FILL_RULE_EVEN_ODD;
blFillRule = BL_FILL_RULE_EVEN_ODD;
break;
case Qt::WindingFill:
fillRule = BL_FILL_RULE_NON_ZERO;
blFillRule = BL_FILL_RULE_NON_ZERO;
break;
default:
@ -377,7 +405,14 @@ void PDFBLPaintEngine::drawPath(const QPainterPath& path)
break;
}
m_blContext->setFillRule(fillRule);
m_blContext->setFillRule(blFillRule);
}
void PDFBLPaintEngine::drawPath(const QPainterPath& path)
{
BLPath blPath = getBLPath(path);
setFillRule(path.fillRule());
if (isFillActive())
{
@ -392,35 +427,176 @@ void PDFBLPaintEngine::drawPath(const QPainterPath& path)
void PDFBLPaintEngine::drawPoints(const QPointF* points, int pointCount)
{
m_blContext->save();
m_blContext->setFillStyle(BLRgba32(m_currentPen.color().rgba()));
for (int i = 0; i < pointCount; ++i)
{
const QPointF& c = points[i];
BLEllipse blEllipse(c.x(), c.y(), m_currentPen.widthF() * 0.5, m_currentPen.widthF() * 0.5);
m_blContext->fillEllipse(blEllipse);
}
m_blContext->restore();
}
void PDFBLPaintEngine::drawPoints(const QPoint* points, int pointCount)
{
m_blContext->save();
m_blContext->setFillStyle(BLRgba32(m_currentPen.color().rgba()));
for (int i = 0; i < pointCount; ++i)
{
const QPointF& c = points[i];
BLEllipse blEllipse(c.x(), c.y(), m_currentPen.widthF() * 0.5, m_currentPen.widthF() * 0.5);
m_blContext->fillEllipse(blEllipse);
}
m_blContext->restore();
}
void PDFBLPaintEngine::drawPolygon(const QPointF* points, int pointCount, PolygonDrawMode mode)
{
QPainterPath path;
QPolygonF polygon;
polygon.assign(points, points + pointCount);
path.addPolygon(polygon);
switch (mode)
{
case QPaintEngine::OddEvenMode:
path.setFillRule(Qt::OddEvenFill);
break;
case QPaintEngine::WindingMode:
path.setFillRule(Qt::WindingFill);
break;
case QPaintEngine::ConvexMode:
path.setFillRule(Qt::OddEvenFill);
break;
case QPaintEngine::PolylineMode:
path.setFillRule(Qt::OddEvenFill);
break;
}
setFillRule(path.fillRule());
BLPath blPath = getBLPath(path);
if (isFillActive() && mode != QPaintEngine::PolylineMode)
{
m_blContext->fillPath(blPath);
}
if (isStrokeActive())
{
m_blContext->strokePath(blPath);
}
}
void PDFBLPaintEngine::drawPolygon(const QPoint* points, int pointCount, PolygonDrawMode mode)
{
QPainterPath path;
QPolygonF polygon;
polygon.assign(points, points + pointCount);
path.addPolygon(polygon);
switch (mode)
{
case QPaintEngine::OddEvenMode:
path.setFillRule(Qt::OddEvenFill);
break;
case QPaintEngine::WindingMode:
path.setFillRule(Qt::WindingFill);
break;
case QPaintEngine::ConvexMode:
path.setFillRule(Qt::OddEvenFill);
break;
case QPaintEngine::PolylineMode:
path.setFillRule(Qt::OddEvenFill);
break;
}
setFillRule(path.fillRule());
BLPath blPath = getBLPath(path);
if (isFillActive() && mode != QPaintEngine::PolylineMode)
{
m_blContext->fillPath(blPath);
}
if (isStrokeActive())
{
m_blContext->strokePath(blPath);
}
}
void PDFBLPaintEngine::drawPixmap(const QRectF& r, const QPixmap& pm, const QRectF& sr)
{
drawImage(r, pm.toImage(), sr, Qt::ImageConversionFlags());
}
void PDFBLPaintEngine::drawTextItem(const QPointF& p, const QTextItem& textItem)
{
if (m_currentRawFont.isValid())
{
QString text = textItem.text();
QList<quint32> glyphIndices = m_currentRawFont.glyphIndexesForString(text);
QList<QPointF> glyphPositions = m_currentRawFont.advancesForGlyphIndexes(glyphIndices);
QPointF currentPosition = p;
QPainterPath path;
for (int i = 0; i < glyphIndices.size(); ++i)
{
QPainterPath glyphPath = m_currentRawFont.pathForGlyph(glyphIndices[i]);
glyphPath.translate(currentPosition);
path.addPath(glyphPath);
currentPosition += glyphPositions[i];
}
m_blContext->save();
setFillRule(path.fillRule());
m_blContext->setFillStyle(BLRgba32(m_currentPen.color().rgba()));
m_blContext->fillPath(getBLPath(path));
m_blContext->restore();
}
}
void PDFBLPaintEngine::drawTiledPixmap(const QRectF& r, const QPixmap& pixmap, const QPointF& s)
{
QImage image = pixmap.toImage();
if (image.format() != QImage::Format_ARGB32_Premultiplied)
{
image.convertTo(QImage::Format_ARGB32_Premultiplied);
}
int tilesX = qCeil(r.width() / pixmap.width());
int tilesY = qCeil(r.height() / pixmap.height());
BLImage blImage;
blImage.createFromData(image.width(), image.height(), BL_FORMAT_PRGB32, image.bits(), image.bytesPerLine());
BLImage blDrawImage;
blDrawImage.assignDeep(blImage);
for (int x = 0; x < tilesX; ++x)
{
for (int y = 0; y < tilesY; ++y)
{
QPointF tilePos = QPointF(r.left() + x * pixmap.width() + s.x(),
r.top() + y * pixmap.height() + s.y());
if (tilePos.x() < r.right() && tilePos.y() < r.bottom())
{
m_blContext->blitImage(getBLPoint(tilePos), blDrawImage);
}
}
}
}
void PDFBLPaintEngine::drawImage(const QRectF& r, const QImage& pm, const QRectF& sr, Qt::ImageConversionFlags flags)
{
Q_UNUSED(flags);
QImage image = pm;
if (image.format() != QImage::Format_ARGB32_Premultiplied)

View File

@ -586,8 +586,11 @@ void PDFDrawWidget::paintEvent(QPaintEvent* event)
qreal devicePixelRatio = devicePixelRatioF();
m_blend2DframeBuffer.setDevicePixelRatio(devicePixelRatio);
m_blend2DframeBuffer.setDotsPerMeterX(logicalDpiX());
m_blend2DframeBuffer.setDotsPerMeterY(logicalDpiY());
qreal dpmX = logicalDpiX() / 0.0254;
qreal dpmY = logicalDpiY() / 0.0254;
m_blend2DframeBuffer.setDotsPerMeterX(qCeil(dpmX));
m_blend2DframeBuffer.setDotsPerMeterY(qCeil(dpmY));
QSize requiredSize = rect.size() * devicePixelRatio;
if (m_blend2DframeBuffer.size() != requiredSize)