mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Polygon/polyline annotation graphics
This commit is contained in:
@ -1254,7 +1254,7 @@ void PDFLineAnnotation::draw(AnnotationDrawParameters& parameters) const
|
||||
|
||||
QLineF lineToPaintOrig = info.LCStoGCS.map(lineToPaint);
|
||||
info = LineGeometryInfo::create(lineToPaintOrig);
|
||||
drawLine(info, painter, lineEndingSize, getStartLineEnding(), getEndLineEnding(), boundingPath);
|
||||
drawLine(info, painter, lineEndingSize, getStartLineEnding(), getEndLineEnding(), boundingPath, getCaptionOffset(), getContents(), getCaptionPosition() == CaptionPosition::Top);
|
||||
|
||||
parameters.boundingRectangle = boundingPath.boundingRect();
|
||||
parameters.boundingRectangle.adjust(-lineEndingSize, -lineEndingSize, lineEndingSize, lineEndingSize);
|
||||
@ -1270,6 +1270,79 @@ QColor PDFLineAnnotation::getFillColor() const
|
||||
return color;
|
||||
}
|
||||
|
||||
void PDFPolygonalGeometryAnnotation::draw(AnnotationDrawParameters& parameters) const
|
||||
{
|
||||
if (m_vertices.empty())
|
||||
{
|
||||
// Jakub Melka: do not draw empty lines
|
||||
return;
|
||||
}
|
||||
|
||||
QPainter& painter = *parameters.painter;
|
||||
painter.setPen(getPen());
|
||||
painter.setBrush(getBrush());
|
||||
|
||||
const PDFReal penWidth = painter.pen().widthF();
|
||||
switch (m_type)
|
||||
{
|
||||
case AnnotationType::Polygon:
|
||||
{
|
||||
QPolygonF polygon;
|
||||
polygon.reserve(int(m_vertices.size() + 1));
|
||||
for (const QPointF& point : m_vertices)
|
||||
{
|
||||
polygon << point;
|
||||
}
|
||||
if (!polygon.isClosed())
|
||||
{
|
||||
polygon << m_vertices.front();
|
||||
}
|
||||
|
||||
painter.drawPolygon(polygon, Qt::OddEvenFill);
|
||||
parameters.boundingRectangle = polygon.boundingRect();
|
||||
parameters.boundingRectangle.adjust(-penWidth, -penWidth, penWidth, penWidth);
|
||||
break;
|
||||
}
|
||||
|
||||
case AnnotationType::Polyline:
|
||||
{
|
||||
const PDFReal lineEndingSize = painter.pen().widthF() * 5.0;
|
||||
QPainterPath boundingPath;
|
||||
|
||||
const size_t pointCount = m_vertices.size();
|
||||
const size_t lastPoint = pointCount - 1;
|
||||
for (size_t i = 1; i < pointCount; ++i)
|
||||
{
|
||||
if (i == 1)
|
||||
{
|
||||
// We draw first line
|
||||
drawLine(LineGeometryInfo::create(QLineF(m_vertices[i - 1], m_vertices[i])), painter, lineEndingSize, getStartLineEnding(), AnnotationLineEnding::None, boundingPath, QPointF(), QString(), true);
|
||||
}
|
||||
else if (i == lastPoint)
|
||||
{
|
||||
// We draw last line
|
||||
drawLine(LineGeometryInfo::create(QLineF(m_vertices[i - 1], m_vertices[i])), painter, lineEndingSize, AnnotationLineEnding::None, getEndLineEnding(), boundingPath, QPointF(), QString(), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
QLineF line(m_vertices[i - 1], m_vertices[i]);
|
||||
boundingPath.moveTo(line.p1());
|
||||
boundingPath.lineTo(line.p2());
|
||||
painter.drawLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
parameters.boundingRectangle = boundingPath.boundingRect();
|
||||
parameters.boundingRectangle.adjust(-lineEndingSize, -lineEndingSize, lineEndingSize, lineEndingSize);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QColor PDFPolygonalGeometryAnnotation::getFillColor() const
|
||||
{
|
||||
QColor color = getDrawColorFromAnnotationColor(getInteriorColor());
|
||||
@ -1308,7 +1381,10 @@ void PDFAnnotation::drawLine(const PDFAnnotation::LineGeometryInfo& info,
|
||||
PDFReal lineEndingSize,
|
||||
AnnotationLineEnding p1Ending,
|
||||
AnnotationLineEnding p2Ending,
|
||||
QPainterPath& boundingPath) const
|
||||
QPainterPath& boundingPath,
|
||||
QPointF textOffset,
|
||||
const QString& text,
|
||||
bool textIsAboveLine) const
|
||||
{
|
||||
const PDFReal angle = 30;
|
||||
const PDFReal lineEndingHalfSize = lineEndingSize * 0.5;
|
||||
@ -1445,14 +1521,82 @@ void PDFAnnotation::drawLine(const PDFAnnotation::LineGeometryInfo& info,
|
||||
QLineF adjustedLine = info.transformedLine;
|
||||
adjustedLine.setP1(adjustedLine.p1() + QPointF(startOffset, 0));
|
||||
adjustedLine.setP2(adjustedLine.p2() - QPointF(endOffset, 0));
|
||||
adjustedLine = info.LCStoGCS.map(adjustedLine);
|
||||
|
||||
int textVerticalOffset = 0;
|
||||
const bool drawText = !text.isEmpty();
|
||||
QPainterPath textPath;
|
||||
|
||||
if (drawText)
|
||||
{
|
||||
QFont font = QApplication::font();
|
||||
font.setPixelSize(12.0);
|
||||
|
||||
QFontMetricsF fontMetrics(font, painter.device());
|
||||
textVerticalOffset = fontMetrics.descent() + fontMetrics.leading();
|
||||
|
||||
textPath.addText(0, 0, font, text);
|
||||
textPath = QMatrix(1, 0, 0, -1, 0, 0).map(textPath);
|
||||
}
|
||||
|
||||
drawLineEnding(info.transformedLine.p1(), p1Ending, false);
|
||||
drawLineEnding(info.transformedLine.p2(), p2Ending, true);
|
||||
|
||||
if (drawText && !textIsAboveLine)
|
||||
{
|
||||
// We will draw text in the line
|
||||
QRectF textBoundingRect = textPath.controlPointRect();
|
||||
QPointF center = textBoundingRect.center();
|
||||
const qreal offsetY = center.y();
|
||||
const qreal offsetX = center.x();
|
||||
textPath.translate(textOffset + adjustedLine.center() - QPointF(offsetX, offsetY));
|
||||
textBoundingRect = textPath.controlPointRect();
|
||||
|
||||
const qreal textPadding = 3.0;
|
||||
const qreal textStart = textBoundingRect.left() - textPadding;
|
||||
const qreal textEnd = textBoundingRect.right() + textPadding;
|
||||
|
||||
textPath = info.LCStoGCS.map(textPath);
|
||||
painter.fillPath(textPath, QBrush(painter.pen().color(), Qt::SolidPattern));
|
||||
boundingPath.addPath(textPath);
|
||||
|
||||
if (textStart > adjustedLine.p1().x())
|
||||
{
|
||||
QLineF leftLine(adjustedLine.p1(), QPointF(textStart, adjustedLine.p2().y()));
|
||||
painter.drawLine(info.LCStoGCS.map(leftLine));
|
||||
}
|
||||
|
||||
if (textEnd < adjustedLine.p2().x())
|
||||
{
|
||||
QLineF rightLine(QPointF(textEnd, adjustedLine.p2().y()), adjustedLine.p2());
|
||||
painter.drawLine(info.LCStoGCS.map(rightLine));
|
||||
}
|
||||
|
||||
// Include whole line to the bounding path
|
||||
adjustedLine = info.LCStoGCS.map(adjustedLine);
|
||||
boundingPath.moveTo(adjustedLine.p1());
|
||||
boundingPath.lineTo(adjustedLine.p2());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (drawText)
|
||||
{
|
||||
// We will draw text above the line
|
||||
QRectF textBoundingRect = textPath.controlPointRect();
|
||||
const qreal offsetY = textBoundingRect.top() - textVerticalOffset;
|
||||
const qreal offsetX = textBoundingRect.center().x();
|
||||
textPath.translate(textOffset + adjustedLine.center() - QPointF(offsetX, offsetY));
|
||||
|
||||
textPath = info.LCStoGCS.map(textPath);
|
||||
painter.fillPath(textPath, QBrush(painter.pen().color(), Qt::SolidPattern));
|
||||
boundingPath.addPath(textPath);
|
||||
}
|
||||
|
||||
adjustedLine = info.LCStoGCS.map(adjustedLine);
|
||||
painter.drawLine(adjustedLine);
|
||||
|
||||
boundingPath.moveTo(adjustedLine.p1());
|
||||
boundingPath.lineTo(adjustedLine.p2());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -526,12 +526,18 @@ protected:
|
||||
/// \param p1Ending Line endpoint graphics at p1
|
||||
/// \param p2Ending Line endpoint graphics at p2
|
||||
/// \param boundingPath Bounding path in global coordinate system
|
||||
/// \param textOffset Additional text offset
|
||||
/// \param text Text, which should be printed along the line
|
||||
/// \param textIsAboveLine Text should be printed above line
|
||||
void drawLine(const LineGeometryInfo& info,
|
||||
QPainter& painter,
|
||||
PDFReal lineEndingSize,
|
||||
AnnotationLineEnding p1Ending,
|
||||
AnnotationLineEnding p2Ending,
|
||||
QPainterPath& boundingPath) const;
|
||||
QPainterPath& boundingPath,
|
||||
QPointF textOffset,
|
||||
const QString& text,
|
||||
bool textIsAboveLine) const;
|
||||
|
||||
private:
|
||||
|
||||
@ -822,6 +828,7 @@ public:
|
||||
}
|
||||
|
||||
virtual AnnotationType getType() const override { return m_type; }
|
||||
virtual void draw(AnnotationDrawParameters& parameters) const override;
|
||||
|
||||
const std::vector<QPointF>& getVertices() const { return m_vertices; }
|
||||
AnnotationLineEnding getStartLineEnding() const { return m_startLineEnding; }
|
||||
|
Reference in New Issue
Block a user