mirror of https://github.com/JakubMelka/PDF4QT.git
XFA: draw text nodes
This commit is contained in:
parent
1c2aff30a3
commit
1656f3b874
|
@ -22,6 +22,8 @@
|
||||||
#include <QDomElement>
|
#include <QDomElement>
|
||||||
#include <QDomDocument>
|
#include <QDomDocument>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QImageReader>
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -9654,6 +9656,7 @@ public:
|
||||||
QRectF nominalExtent;
|
QRectF nominalExtent;
|
||||||
const xfa::XFA_draw* draw = nullptr;
|
const xfa::XFA_draw* draw = nullptr;
|
||||||
const xfa::XFA_field* field = nullptr;
|
const xfa::XFA_field* field = nullptr;
|
||||||
|
size_t paragraphSettingsIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
using LayoutItems = std::vector<LayoutItem>;
|
using LayoutItems = std::vector<LayoutItem>;
|
||||||
|
@ -9684,6 +9687,15 @@ private:
|
||||||
QPen createPenFromEdge(const std::vector<xfa::XFA_Node<xfa::XFA_edge>>& edges, size_t index, QList<PDFRenderError>& errors) const;
|
QPen createPenFromEdge(const std::vector<xfa::XFA_Node<xfa::XFA_edge>>& edges, size_t index, QList<PDFRenderError>& errors) const;
|
||||||
QPen createPenFromCorner(const std::vector<xfa::XFA_Node<xfa::XFA_corner>>& corners, size_t index, QList<PDFRenderError>& errors) const;
|
QPen createPenFromCorner(const std::vector<xfa::XFA_Node<xfa::XFA_corner>>& corners, size_t index, QList<PDFRenderError>& errors) const;
|
||||||
|
|
||||||
|
struct NodeValue
|
||||||
|
{
|
||||||
|
QVariant value;
|
||||||
|
PDFInteger hintTextMaxChars = 0;
|
||||||
|
PDFInteger hintFloatFracDigits = 2;
|
||||||
|
PDFInteger hintFloatLeadDigits = -1;
|
||||||
|
bool hintTextHtml = false;
|
||||||
|
};
|
||||||
|
|
||||||
void drawItemBorder(const xfa::XFA_border* item,
|
void drawItemBorder(const xfa::XFA_border* item,
|
||||||
QList<PDFRenderError>& errors,
|
QList<PDFRenderError>& errors,
|
||||||
QRectF nominalContentArea,
|
QRectF nominalContentArea,
|
||||||
|
@ -9694,6 +9706,11 @@ private:
|
||||||
QRectF nominalContentArea,
|
QRectF nominalContentArea,
|
||||||
QPainter* painter);
|
QPainter* painter);
|
||||||
|
|
||||||
|
void drawItemLine(const xfa::XFA_line* item,
|
||||||
|
QList<PDFRenderError>& errors,
|
||||||
|
QRectF nominalContentArea,
|
||||||
|
QPainter* painter);
|
||||||
|
|
||||||
void drawItemRectEdges(const std::vector<xfa::XFA_Node<xfa::XFA_edge>>& edges,
|
void drawItemRectEdges(const std::vector<xfa::XFA_Node<xfa::XFA_edge>>& edges,
|
||||||
const std::vector<xfa::XFA_Node<xfa::XFA_corner>>& corners,
|
const std::vector<xfa::XFA_Node<xfa::XFA_corner>>& corners,
|
||||||
QList<PDFRenderError>& errors,
|
QList<PDFRenderError>& errors,
|
||||||
|
@ -9704,6 +9721,7 @@ private:
|
||||||
void drawItemDraw(const xfa::XFA_draw* item,
|
void drawItemDraw(const xfa::XFA_draw* item,
|
||||||
QList<PDFRenderError>& errors,
|
QList<PDFRenderError>& errors,
|
||||||
QRectF nominalExtentArea,
|
QRectF nominalExtentArea,
|
||||||
|
size_t paragraphSettingsIndex,
|
||||||
QPainter* painter);
|
QPainter* painter);
|
||||||
|
|
||||||
void drawItemField(const xfa::XFA_field* item,
|
void drawItemField(const xfa::XFA_field* item,
|
||||||
|
@ -9711,6 +9729,19 @@ private:
|
||||||
QRectF nominalExtentArea,
|
QRectF nominalExtentArea,
|
||||||
QPainter* painter);
|
QPainter* painter);
|
||||||
|
|
||||||
|
void drawUi(const xfa::XFA_ui* ui,
|
||||||
|
const NodeValue& value,
|
||||||
|
QList<PDFRenderError>& errors,
|
||||||
|
QRectF nominalExtentArea,
|
||||||
|
size_t paragraphSettingsIndex,
|
||||||
|
QPainter* painter);
|
||||||
|
|
||||||
|
void drawUiTextEdit(const xfa::XFA_textEdit* textEdit,
|
||||||
|
const NodeValue& value,
|
||||||
|
QList<PDFRenderError>& errors,
|
||||||
|
QRectF nominalExtentArea,
|
||||||
|
size_t paragraphSettingsIndex,
|
||||||
|
QPainter* painter);
|
||||||
|
|
||||||
xfa::XFA_Node<xfa::XFA_template> m_template;
|
xfa::XFA_Node<xfa::XFA_template> m_template;
|
||||||
const PDFDocument* m_document;
|
const PDFDocument* m_document;
|
||||||
|
@ -10541,6 +10572,7 @@ void PDFXFALayoutEngine::performLayout(PDFXFAEngineImpl* engine, const xfa::XFA_
|
||||||
engineLayoutItem.nominalExtent = layoutItem.nominalExtent;
|
engineLayoutItem.nominalExtent = layoutItem.nominalExtent;
|
||||||
engineLayoutItem.draw = layoutItem.draw;
|
engineLayoutItem.draw = layoutItem.draw;
|
||||||
engineLayoutItem.field = layoutItem.field;
|
engineLayoutItem.field = layoutItem.field;
|
||||||
|
engineLayoutItem.paragraphSettingsIndex = layoutItem.paragraphSettingsIndex;
|
||||||
layoutItems.emplace_back(std::move(engineLayoutItem));
|
layoutItems.emplace_back(std::move(engineLayoutItem));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11273,7 +11305,7 @@ void PDFXFAEngineImpl::draw(const QMatrix& pagePointToDevicePointMatrix,
|
||||||
const LayoutItems& items = it->second;
|
const LayoutItems& items = it->second;
|
||||||
for (const LayoutItem& item : items)
|
for (const LayoutItem& item : items)
|
||||||
{
|
{
|
||||||
drawItemDraw(item.draw, errors, item.nominalExtent, painter);
|
drawItemDraw(item.draw, errors, item.nominalExtent, item.paragraphSettingsIndex, painter);
|
||||||
drawItemField(item.field, errors, item.nominalExtent, painter);
|
drawItemField(item.field, errors, item.nominalExtent, painter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11281,6 +11313,7 @@ void PDFXFAEngineImpl::draw(const QMatrix& pagePointToDevicePointMatrix,
|
||||||
void PDFXFAEngineImpl::drawItemDraw(const xfa::XFA_draw* item,
|
void PDFXFAEngineImpl::drawItemDraw(const xfa::XFA_draw* item,
|
||||||
QList<PDFRenderError>& errors,
|
QList<PDFRenderError>& errors,
|
||||||
QRectF nominalExtentArea,
|
QRectF nominalExtentArea,
|
||||||
|
size_t paragraphSettingsIndex,
|
||||||
QPainter* painter)
|
QPainter* painter)
|
||||||
{
|
{
|
||||||
if (!item)
|
if (!item)
|
||||||
|
@ -11298,12 +11331,135 @@ void PDFXFAEngineImpl::drawItemDraw(const xfa::XFA_draw* item,
|
||||||
|
|
||||||
if (const xfa::XFA_value* value = item->getValue())
|
if (const xfa::XFA_value* value = item->getValue())
|
||||||
{
|
{
|
||||||
|
std::optional<NodeValue> nodeValue;
|
||||||
|
|
||||||
if (const xfa::XFA_rectangle* rectangle = value->getRectangle())
|
if (const xfa::XFA_rectangle* rectangle = value->getRectangle())
|
||||||
{
|
{
|
||||||
drawItemFill(rectangle->getFill(), errors, nominalContentArea, painter);
|
drawItemFill(rectangle->getFill(), errors, nominalContentArea, painter);
|
||||||
drawItemRectEdges(rectangle->getEdge(), rectangle->getCorner(), errors, nominalContentArea, rectangle->getHand(), painter);
|
drawItemRectEdges(rectangle->getEdge(), rectangle->getCorner(), errors, nominalContentArea, rectangle->getHand(), painter);
|
||||||
}
|
}
|
||||||
|
else if (const xfa::XFA_line* line = value->getLine())
|
||||||
|
{
|
||||||
|
drawItemLine(line, errors, nominalContentArea, painter);
|
||||||
|
}
|
||||||
|
else if (const xfa::XFA_text* text = value->getText())
|
||||||
|
{
|
||||||
|
nodeValue.emplace();
|
||||||
|
nodeValue->value = text->getNodeValue() ? *text->getNodeValue() : QString();
|
||||||
|
nodeValue->hintTextMaxChars = text->getMaxChars();
|
||||||
|
}
|
||||||
|
else if (const xfa::XFA_exData* exData = value->getExData())
|
||||||
|
{
|
||||||
|
if (exData->getContentType() == "text/html")
|
||||||
|
{
|
||||||
|
nodeValue.emplace();
|
||||||
|
nodeValue->value = exData->getNodeValue() ? *exData->getNodeValue() : QString();
|
||||||
|
nodeValue->hintTextMaxChars = exData->getMaxLength();
|
||||||
|
nodeValue->hintTextHtml = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errors << PDFRenderError(RenderErrorType::NotImplemented, PDFTranslationContext::tr("Rendering of content type '%1' is not implemented.").arg(exData->getContentType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (const xfa::XFA_integer* integer = value->getInteger())
|
||||||
|
{
|
||||||
|
QString textValue = integer->getNodeValue() ? *integer->getNodeValue() : QString();
|
||||||
|
nodeValue.emplace();
|
||||||
|
nodeValue->value = textValue.toInt();
|
||||||
|
}
|
||||||
|
else if (const xfa::XFA_boolean* boolean = value->getBoolean())
|
||||||
|
{
|
||||||
|
QString textValue = boolean->getNodeValue() ? *boolean->getNodeValue() : QString();
|
||||||
|
nodeValue.emplace();
|
||||||
|
nodeValue->value = bool(textValue.toInt() != 0);
|
||||||
|
}
|
||||||
|
else if (const xfa::XFA_decimal* decimal = value->getDecimal())
|
||||||
|
{
|
||||||
|
QString textValue = decimal->getNodeValue() ? *decimal->getNodeValue() : QString();
|
||||||
|
nodeValue.emplace();
|
||||||
|
nodeValue->hintFloatFracDigits = decimal->getFracDigits();
|
||||||
|
nodeValue->hintFloatLeadDigits = decimal->getLeadDigits();
|
||||||
|
nodeValue->value = textValue.toDouble();
|
||||||
|
}
|
||||||
|
else if (const xfa::XFA_float* floatItem = value->getFloat())
|
||||||
|
{
|
||||||
|
QString textValue = floatItem->getNodeValue() ? *floatItem->getNodeValue() : QString();
|
||||||
|
nodeValue.emplace();
|
||||||
|
nodeValue->hintFloatFracDigits = -1;
|
||||||
|
nodeValue->hintFloatLeadDigits = -1;
|
||||||
|
nodeValue->value = textValue.toDouble();
|
||||||
|
}
|
||||||
|
else if (const xfa::XFA_dateTime* dateTime = value->getDateTime())
|
||||||
|
{
|
||||||
|
QString textValue = dateTime->getNodeValue() ? *dateTime->getNodeValue() : QString();
|
||||||
|
QDateTime dateTimeVal = QDateTime::fromString(textValue, Qt::ISODate);
|
||||||
|
if (dateTimeVal.isValid())
|
||||||
|
{
|
||||||
|
nodeValue.emplace();
|
||||||
|
nodeValue->value = std::move(dateTimeVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (const xfa::XFA_date* date = value->getDate())
|
||||||
|
{
|
||||||
|
QString textValue = date->getNodeValue() ? *date->getNodeValue() : QString();
|
||||||
|
QDate dateVal = QDate::fromString(textValue, Qt::ISODate);
|
||||||
|
if (dateVal.isValid())
|
||||||
|
{
|
||||||
|
nodeValue.emplace();
|
||||||
|
nodeValue->value = std::move(dateVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (const xfa::XFA_time* time = value->getTime())
|
||||||
|
{
|
||||||
|
QString textValue = time->getNodeValue() ? *time->getNodeValue() : QString();
|
||||||
|
QTime timeVal = QTime::fromString(textValue, Qt::ISODate);
|
||||||
|
if (timeVal.isValid())
|
||||||
|
{
|
||||||
|
nodeValue.emplace();
|
||||||
|
nodeValue->value = std::move(timeVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (const xfa::XFA_image* image = value->getImage())
|
||||||
|
{
|
||||||
|
QByteArray ba;
|
||||||
|
QString textValue = image->getNodeValue() ? *image->getNodeValue() : QString();
|
||||||
|
|
||||||
|
switch (image->getTransferEncoding())
|
||||||
|
{
|
||||||
|
case pdf::xfa::XFA_BaseNode::TRANSFERENCODING1::Base64:
|
||||||
|
ba = QByteArray::fromBase64(textValue.toLatin1());
|
||||||
|
break;
|
||||||
|
case pdf::xfa::XFA_BaseNode::TRANSFERENCODING1::None:
|
||||||
|
ba = textValue.toLatin1();
|
||||||
|
break;
|
||||||
|
case pdf::xfa::XFA_BaseNode::TRANSFERENCODING1::Package:
|
||||||
|
errors << PDFRenderError(RenderErrorType::NotImplemented, PDFTranslationContext::tr("Image encoded by 'package' mode not decoded."));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QBuffer buffer(&ba);
|
||||||
|
QImageReader reader(&buffer);
|
||||||
|
reader.setDecideFormatFromContent(true);
|
||||||
|
QImage imageValue = reader.read();
|
||||||
|
|
||||||
|
if (!imageValue.isNull())
|
||||||
|
{
|
||||||
|
nodeValue.emplace();
|
||||||
|
nodeValue->value = std::move(imageValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errors << PDFRenderError(RenderErrorType::NotImplemented, PDFTranslationContext::tr("Image of type '%1' not decoded.").arg(image->getContentType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodeValue)
|
||||||
|
{
|
||||||
|
drawUi(item->getUi(), nodeValue.value(), errors, nominalContentArea, paragraphSettingsIndex, painter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement draw arc (getArc())
|
||||||
// TODO: implement draw value
|
// TODO: implement draw value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11329,6 +11485,119 @@ void PDFXFAEngineImpl::drawItemField(const xfa::XFA_field* item,
|
||||||
// TODO: implement this
|
// TODO: implement this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFXFAEngineImpl::drawUi(const xfa::XFA_ui* ui,
|
||||||
|
const NodeValue& value,
|
||||||
|
QList<PDFRenderError>& errors,
|
||||||
|
QRectF nominalExtentArea,
|
||||||
|
size_t paragraphSettingsIndex,
|
||||||
|
QPainter* painter)
|
||||||
|
{
|
||||||
|
if (!value.value.isValid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const xfa::XFA_barcode* barcode = nullptr;
|
||||||
|
const xfa::XFA_button* button = nullptr;
|
||||||
|
const xfa::XFA_checkButton* checkButton = nullptr;
|
||||||
|
const xfa::XFA_choiceList* choiceList = nullptr;
|
||||||
|
const xfa::XFA_dateTimeEdit* dateTimeEdit = nullptr;
|
||||||
|
const xfa::XFA_defaultUi* defaultUi = nullptr;
|
||||||
|
const xfa::XFA_imageEdit* imageEdit = nullptr;
|
||||||
|
const xfa::XFA_numericEdit* numericEdit = nullptr;
|
||||||
|
const xfa::XFA_passwordEdit* passwordEdit = nullptr;
|
||||||
|
const xfa::XFA_signature* signature = nullptr;
|
||||||
|
const xfa::XFA_textEdit* textEdit = nullptr;
|
||||||
|
|
||||||
|
if (ui)
|
||||||
|
{
|
||||||
|
barcode = ui->getBarcode();
|
||||||
|
button = ui->getButton();
|
||||||
|
checkButton = ui->getCheckButton();
|
||||||
|
choiceList = ui->getChoiceList();
|
||||||
|
dateTimeEdit = ui->getDateTimeEdit();
|
||||||
|
defaultUi = ui->getDefaultUi();
|
||||||
|
imageEdit = ui->getImageEdit();
|
||||||
|
numericEdit = ui->getNumericEdit();
|
||||||
|
passwordEdit = ui->getPasswordEdit();
|
||||||
|
signature = ui->getSignature();
|
||||||
|
textEdit = ui->getTextEdit();
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool isNonDefaultUi = barcode || button || checkButton || choiceList ||
|
||||||
|
dateTimeEdit || imageEdit || numericEdit ||
|
||||||
|
passwordEdit || signature || textEdit;
|
||||||
|
const bool isDefaultUi = !isNonDefaultUi || defaultUi;
|
||||||
|
|
||||||
|
if (textEdit || (isDefaultUi && value.value.type() == QVariant::String))
|
||||||
|
{
|
||||||
|
drawUiTextEdit(textEdit, value, errors, nominalExtentArea, paragraphSettingsIndex, painter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement all ui
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFXFAEngineImpl::drawUiTextEdit(const xfa::XFA_textEdit* textEdit,
|
||||||
|
const NodeValue& value,
|
||||||
|
QList<PDFRenderError>& errors,
|
||||||
|
QRectF nominalExtentArea,
|
||||||
|
size_t paragraphSettingsIndex,
|
||||||
|
QPainter* painter)
|
||||||
|
{
|
||||||
|
QRectF nominalExtent = nominalExtentArea;
|
||||||
|
QRectF nominalContentArea = nominalExtent;
|
||||||
|
QMarginsF contentMargins = textEdit ? createMargin(textEdit->getMargin()) : QMarginsF();
|
||||||
|
nominalContentArea = nominalExtent.marginsRemoved(contentMargins);
|
||||||
|
|
||||||
|
bool isComb = false;
|
||||||
|
bool isMultiline = true;
|
||||||
|
bool isRichTextAllowed = value.hintTextHtml;
|
||||||
|
PDFInteger combNumberOfCells = value.hintTextMaxChars;
|
||||||
|
|
||||||
|
if (textEdit)
|
||||||
|
{
|
||||||
|
isMultiline = textEdit->getMultiLine() == xfa::XFA_textEdit::MULTILINE::_1;
|
||||||
|
isRichTextAllowed = textEdit->getAllowRichText();
|
||||||
|
|
||||||
|
if (const xfa::XFA_comb* comb = textEdit->getComb())
|
||||||
|
{
|
||||||
|
isComb = true;
|
||||||
|
PDFInteger combCells = comb->getNumberOfCells();
|
||||||
|
if (combCells > 0)
|
||||||
|
{
|
||||||
|
combNumberOfCells = combCells;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawItemBorder(textEdit->getBorder(), errors, nominalExtent, painter);
|
||||||
|
}
|
||||||
|
|
||||||
|
combNumberOfCells = qMax(combNumberOfCells, PDFInteger(1));
|
||||||
|
const xfa::XFA_ParagraphSettings& settings = m_layout.paragraphSettings.at(paragraphSettingsIndex);
|
||||||
|
|
||||||
|
if (!isComb)
|
||||||
|
{
|
||||||
|
painter->setFont(settings.getFont());
|
||||||
|
|
||||||
|
QRectF textRect = nominalContentArea;
|
||||||
|
textRect = textRect.marginsRemoved(settings.getMargins());
|
||||||
|
|
||||||
|
if (!isRichTextAllowed)
|
||||||
|
{
|
||||||
|
const int textFlag = isMultiline ? Qt::TextWordWrap : Qt::TextSingleLine;
|
||||||
|
painter->drawText(textRect, textFlag | int(settings.getAlignment()), value.value.toString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: handle rich text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: We draw comb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PDFXFAEngineImpl::drawItemBorder(const xfa::XFA_border* item,
|
void PDFXFAEngineImpl::drawItemBorder(const xfa::XFA_border* item,
|
||||||
QList<PDFRenderError>& errors,
|
QList<PDFRenderError>& errors,
|
||||||
QRectF nominalContentArea,
|
QRectF nominalContentArea,
|
||||||
|
@ -11430,6 +11699,59 @@ void PDFXFAEngineImpl::drawItemFill(const xfa::XFA_fill* item,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFXFAEngineImpl::drawItemLine(const xfa::XFA_line* item,
|
||||||
|
QList<PDFRenderError>& errors,
|
||||||
|
QRectF nominalContentArea,
|
||||||
|
QPainter* painter)
|
||||||
|
{
|
||||||
|
if (!item)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPen pen = createPenFromEdge(item->getEdge(), errors);
|
||||||
|
|
||||||
|
if (pen.style() == Qt::NoPen)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLineF line;
|
||||||
|
switch (item->getSlope())
|
||||||
|
{
|
||||||
|
case pdf::xfa::XFA_BaseNode::SLOPE::Backslash:
|
||||||
|
line = QLineF(nominalContentArea.topLeft(), nominalContentArea.bottomRight());
|
||||||
|
break;
|
||||||
|
case pdf::xfa::XFA_BaseNode::SLOPE::Slash:
|
||||||
|
line = QLineF(nominalContentArea.bottomLeft(), nominalContentArea.topRight());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFReal offset = 0.0;
|
||||||
|
switch (item->getHand())
|
||||||
|
{
|
||||||
|
case xfa::XFA_BaseNode::HAND::Even:
|
||||||
|
break;
|
||||||
|
case xfa::XFA_BaseNode::HAND::Left:
|
||||||
|
offset = -pen.widthF() * 0.5;
|
||||||
|
break;
|
||||||
|
case xfa::XFA_BaseNode::HAND::Right:
|
||||||
|
offset = +pen.widthF() * 0.5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qFuzzyIsNull(offset))
|
||||||
|
{
|
||||||
|
const QLineF unitVector = line.normalVector().unitVector();
|
||||||
|
const qreal offsetX = unitVector.dx() * offset;
|
||||||
|
const qreal offsetY = unitVector.dy() * offset;
|
||||||
|
line.translate(offsetX, offsetY);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter->setPen(std::move(pen));
|
||||||
|
painter->drawLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
void PDFXFAEngineImpl::drawItemRectEdges(const std::vector<xfa::XFA_Node<xfa::XFA_edge>>& edges,
|
void PDFXFAEngineImpl::drawItemRectEdges(const std::vector<xfa::XFA_Node<xfa::XFA_edge>>& edges,
|
||||||
const std::vector<xfa::XFA_Node<xfa::XFA_corner>>& corners,
|
const std::vector<xfa::XFA_Node<xfa::XFA_corner>>& corners,
|
||||||
QList<PDFRenderError>& errors,
|
QList<PDFRenderError>& errors,
|
||||||
|
|
Loading…
Reference in New Issue