Dimension painting

This commit is contained in:
Jakub Melka 2020-11-21 18:47:25 +01:00
parent ae970640bb
commit 762a239193
6 changed files with 158 additions and 27 deletions

View File

@ -50,6 +50,13 @@ int PDFWidgetUtils::scaleDPI_x(QPaintDevice* device, int unscaledSize)
return (logicalDPI_x / defaultDPI_x) * unscaledSize;
}
int PDFWidgetUtils::scaleDPI_y(QPaintDevice* device, int unscaledSize)
{
const double logicalDPI_y = device->logicalDpiY();
const double defaultDPI_y = qt_default_dpi_y();
return (logicalDPI_y / defaultDPI_y) * unscaledSize;
}
PDFReal PDFWidgetUtils::scaleDPI_x(QPaintDevice* device, PDFReal unscaledSize)
{
const double logicalDPI_x = device->logicalDpiX();

View File

@ -37,6 +37,10 @@ public:
/// \param device Paint device to obtain logical DPI for scaling
static int scaleDPI_x(QPaintDevice* device, int unscaledSize);
/// Scale vertical DPI value
/// \param device Paint device to obtain logical DPI for scaling
static int scaleDPI_y(QPaintDevice* device, int unscaledSize);
/// Scale horizontal DPI value
/// \param device Paint device to obtain logical DPI for scaling
static PDFReal scaleDPI_x(QPaintDevice* device, PDFReal unscaledSize);

View File

@ -17,8 +17,12 @@
#include "dimensionsplugin.h"
#include "pdfdrawwidget.h"
#include "pdfwidgetutils.h"
#include "settingsdialog.h"
#include <QPainter>
#include <QFontMetricsF>
namespace pdfplugin
{
@ -131,42 +135,112 @@ void DimensionsPlugin::drawPage(QPainter* painter,
const QMatrix& pagePointToDevicePointMatrix,
QList<pdf::PDFRenderError>& errors) const
{
if (!m_showDimensionsAction || !m_showDimensionsAction->isChecked())
Q_UNUSED(compiledPage);
Q_UNUSED(layoutGetter);
Q_UNUSED(errors);
if (!m_showDimensionsAction || !m_showDimensionsAction->isChecked() || m_dimensions.empty())
{
// Nothing to draw
return;
}
QLocale locale;
for (const Dimension& dimension : m_dimensions)
{
if (pageIndex != dimension.getPageIndex())
{
continue;
}
switch (dimension.getType())
{
case Dimension::Linear:
{
QPointF p1 = pagePointToDevicePointMatrix.map(dimension.getPolygon().front());
QPointF p2 = pagePointToDevicePointMatrix.map(dimension.getPolygon().back());
// Swap so p1 is to the left of the page, before p2 (for correct determination of angle)
if (p1.x() > p2.x())
{
qSwap(p1, p2);
}
QLineF line(p1, p2);
if (qFuzzyIsNull(line.length()))
{
// If we have zero line, then do nothing
continue;
}
QLineF unitVectorLine = line.normalVector().unitVector();
QPointF unitVector = unitVectorLine.p2() - unitVectorLine.p1();
qreal extensionLineSize = pdf::PDFWidgetUtils::scaleDPI_y(painter->device(), 5);
painter->setPen(Qt::black);
painter->drawLine(line);
QLineF extensionLineLeft(p1 - unitVector * extensionLineSize, p1 + unitVector * extensionLineSize);
QLineF extensionLineRight(p2 - unitVector * extensionLineSize, p2 + unitVector * extensionLineSize);
painter->drawLine(extensionLineLeft);
painter->drawLine(extensionLineRight);
QPointF textPoint = line.center();
qreal angle = line.angle();
QFontMetricsF fontMetrics(painter->font());
QRectF textRect(-line.length() * 0.5, -fontMetrics.lineSpacing(), line.length(), fontMetrics.lineSpacing());
QString text = QString("%1 %2").arg(locale.toString(dimension.getMeasuredValue() * m_lengthUnit.scale, 'f', 2), m_lengthUnit.symbol);
painter->save();
painter->translate(textPoint);
painter->rotate(-angle);
painter->drawText(textRect, Qt::AlignCenter | Qt::TextDontClip, text);
painter->restore();
break;
}
case Dimension::Perimeter:
break;
case Dimension::Area:
break;
default:
Q_ASSERT(false);
break;
}
}
}
void DimensionsPlugin::onShowDimensionsTriggered()
{
if (m_widget)
{
m_widget->update();
}
updateGraphics();
}
void DimensionsPlugin::onClearDimensionsTriggered()
{
m_dimensions.clear();
if (m_widget)
{
m_widget->update();
}
updateActions();
updateGraphics();
}
void DimensionsPlugin::onSettingsTriggered()
{
SettingsDialog dialog(m_widget, m_lengthUnit, m_areaUnit, m_angleUnit);
dialog.exec();
m_widget->update();
updateGraphics();
}
void DimensionsPlugin::onDimensionCreated(Dimension dimension)
{
m_dimensions.emplace_back(qMove(dimension));
updateActions();
updateGraphics();
}
void DimensionsPlugin::updateActions()
@ -181,4 +255,12 @@ void DimensionsPlugin::updateActions()
}
}
void DimensionsPlugin::updateGraphics()
{
if (m_widget)
{
m_widget->getDrawWidget()->getWidget()->update();
}
}
}

View File

@ -54,6 +54,7 @@ private:
void onSettingsTriggered();
void onDimensionCreated(Dimension dimension);
void updateActions();
void updateGraphics();
std::array<DimensionTool*, DimensionTool::LastStyle> m_dimensionTools;
std::vector<Dimension> m_dimensions;

View File

@ -77,10 +77,19 @@ void DimensionTool::drawPage(QPainter* painter,
void DimensionTool::onPointPicked(pdf::PDFInteger pageIndex, QPointF pagePoint)
{
Q_UNUSED(pagePoint);
if (Dimension::isComplete(getDimensionType(), m_pickTool->getPickedPoints()))
{
// Create a new dimension...
emit dimensionCreated(Dimension(pageIndex, getMeasuredValue(), m_pickTool->getPickedPoints()));
std::vector<QPointF> points = m_pickTool->getPickedPoints();
for (QPointF& point : points)
{
point = adjustPagePoint(point);
}
pdf::PDFReal measuredValue = getMeasuredValue(pageIndex, points);
emit dimensionCreated(Dimension(getDimensionType(), pageIndex, measuredValue, qMove(points)));
m_pickTool->resetTool();
}
}
@ -94,7 +103,17 @@ QPointF DimensionTool::adjustPagePoint(QPointF pagePoint) const
const std::vector<QPointF>& pickedPoints = m_pickTool->getPickedPoints();
if (!pickedPoints.empty())
{
pagePoint.setY(pickedPoints.front().y());
const pdf::PDFPage* page = getDocument()->getCatalog()->getPage(m_pickTool->getPageIndex());
const bool rotated = page->getPageRotation() == pdf::PageRotation::Rotate90 || page->getPageRotation() == pdf::PageRotation::Rotate270;
if (rotated)
{
pagePoint.setX(pickedPoints.front().x());
}
else
{
pagePoint.setY(pickedPoints.front().y());
}
}
break;
}
@ -104,7 +123,17 @@ QPointF DimensionTool::adjustPagePoint(QPointF pagePoint) const
const std::vector<QPointF>& pickedPoints = m_pickTool->getPickedPoints();
if (!pickedPoints.empty())
{
pagePoint.setX(pickedPoints.front().x());
const pdf::PDFPage* page = getDocument()->getCatalog()->getPage(m_pickTool->getPageIndex());
const bool rotated = page->getPageRotation() == pdf::PageRotation::Rotate90 || page->getPageRotation() == pdf::PageRotation::Rotate270;
if (!rotated)
{
pagePoint.setX(pickedPoints.front().x());
}
else
{
pagePoint.setY(pickedPoints.front().y());
}
}
break;
}
@ -136,9 +165,10 @@ Dimension::Type DimensionTool::getDimensionType() const
return Dimension::Type::Linear;
}
pdf::PDFReal DimensionTool::getMeasuredValue() const
pdf::PDFReal DimensionTool::getMeasuredValue(pdf::PDFInteger pageIndex, const std::vector<QPointF>& pickedPoints) const
{
const std::vector<QPointF>& pickedPoints = m_pickTool->getPickedPoints();
const pdf::PDFPage* page = getDocument()->getCatalog()->getPage(pageIndex);
Q_ASSERT(page);
switch (getDimensionType())
{
@ -153,7 +183,7 @@ pdf::PDFReal DimensionTool::getMeasuredValue() const
length += qSqrt(QPointF::dotProduct(vector, vector));
}
break;
return length * page->getUserUnit();
}
case Dimension::Area:
@ -171,7 +201,7 @@ pdf::PDFReal DimensionTool::getMeasuredValue() const
}
area = qAbs(area) * 0.5;
break;
return area * page->getUserUnit() * page->getUserUnit();
}
default:

View File

@ -48,15 +48,6 @@ class Dimension
{
public:
inline explicit Dimension() = default;
inline explicit Dimension(pdf::PDFInteger pageIndex, pdf::PDFReal measuredValue, std::vector<QPointF> polygon) :
m_pageIndex(pageIndex),
m_measuredValue(measuredValue),
m_polygon(qMove(polygon))
{
}
enum Type
{
Linear,
@ -64,10 +55,26 @@ public:
Area
};
inline explicit Dimension() = default;
inline explicit Dimension(Type type, pdf::PDFInteger pageIndex, pdf::PDFReal measuredValue, std::vector<QPointF> polygon) :
m_type(type),
m_pageIndex(pageIndex),
m_measuredValue(measuredValue),
m_polygon(qMove(polygon))
{
}
Type getType() const { return m_type; }
pdf::PDFInteger getPageIndex() const { return m_pageIndex; }
pdf::PDFReal getMeasuredValue() const { return m_measuredValue; }
const std::vector<QPointF>& getPolygon() const { return m_polygon; }
/// Returns true, if definition fo given type is complete
static bool isComplete(Type type, const std::vector<QPointF>& polygon);
private:
Type m_type = Linear;
pdf::PDFInteger m_pageIndex = -1;
pdf::PDFReal m_measuredValue = 0.0;
std::vector<QPointF> m_polygon;
@ -109,7 +116,7 @@ private:
void onPointPicked(pdf::PDFInteger pageIndex, QPointF pagePoint);
QPointF adjustPagePoint(QPointF pagePoint) const;
Dimension::Type getDimensionType() const;
pdf::PDFReal getMeasuredValue() const;
pdf::PDFReal getMeasuredValue(pdf::PDFInteger pageIndex, const std::vector<QPointF>& pickedPoints) const;
Style m_style;
int m_previewPointPixelSize;