Editor plugin: WIP

This commit is contained in:
Jakub Melka
2023-03-06 16:09:09 +01:00
parent 1e52c0c063
commit 1b6bb6086c
32 changed files with 2243 additions and 311 deletions

View File

@@ -148,6 +148,8 @@ add_library(Pdf4QtLibCore SHARED
sources/pdfcertificatestore.cpp
sources/pdfblpainter.h
sources/pdfblpainter.cpp
sources/pdfpagecontenteditorprocessor.h
sources/pdfpagecontenteditorprocessor.cpp
)
include(GenerateExportHeader)

View File

@@ -749,7 +749,7 @@ void PDFRealizedFontImpl::fillTextSequence(const QByteArray& byteArray, TextSequ
if (glyphIndex)
{
const Glyph& glyph = getGlyph(glyphIndex);
textSequence.items.emplace_back(&glyph.glyph, (*encoding)[static_cast<uint8_t>(byteArray[i])], glyph.advance);
textSequence.items.emplace_back(&glyph.glyph, (*encoding)[static_cast<uint8_t>(byteArray[i])], glyph.advance, static_cast<CID>(byteArray[i]));
}
else
{
@@ -757,7 +757,7 @@ void PDFRealizedFontImpl::fillTextSequence(const QByteArray& byteArray, TextSequ
if (glyphWidth > 0)
{
const QPainterPath* nullpath = nullptr;
textSequence.items.emplace_back(nullpath, QChar(), glyphWidth * m_pixelSize * FONT_WIDTH_MULTIPLIER);
textSequence.items.emplace_back(nullpath, QChar(), glyphWidth * m_pixelSize * FONT_WIDTH_MULTIPLIER, static_cast<CID>(byteArray[i]));
}
}
}
@@ -784,7 +784,7 @@ void PDFRealizedFontImpl::fillTextSequence(const QByteArray& byteArray, TextSequ
{
QChar character = toUnicode->getToUnicode(cid);
const Glyph& glyph = getGlyph(glyphIndex);
textSequence.items.emplace_back(&glyph.glyph, character, glyph.advance);
textSequence.items.emplace_back(&glyph.glyph, character, glyph.advance, cid);
}
else
{
@@ -799,7 +799,7 @@ void PDFRealizedFontImpl::fillTextSequence(const QByteArray& byteArray, TextSequ
// We do not multiply advance with font size and FONT_WIDTH_MULTIPLIER, because in the code,
// "advance" is treated as in font space.
const QPainterPath* nullpath = nullptr;
textSequence.items.emplace_back(nullpath, QChar(), -glyphWidth);
textSequence.items.emplace_back(nullpath, QChar(), -glyphWidth, cid);
}
}
}
@@ -2680,7 +2680,7 @@ void PDFRealizedType3FontImpl::fillTextSequence(const QByteArray& byteArray, Tex
if (contentStream)
{
textSequence.items.emplace_back(contentStream, character, width);
textSequence.items.emplace_back(contentStream, character, width, index);
}
else
{

View File

@@ -70,9 +70,9 @@ public:
struct TextSequenceItem
{
inline explicit TextSequenceItem() = default;
inline explicit TextSequenceItem(const QPainterPath* glyph, QChar character, PDFReal advance) : glyph(glyph), character(character), advance(advance) { }
inline explicit TextSequenceItem(const QPainterPath* glyph, QChar character, PDFReal advance, CID cid) : glyph(glyph), character(character), advance(advance), cid(cid) { }
inline explicit TextSequenceItem(PDFReal advance) : character(), advance(advance) { }
inline explicit TextSequenceItem(const QByteArray* characterContentStream, QChar character, PDFReal advance) : characterContentStream(characterContentStream), character(character), advance(advance) { }
inline explicit TextSequenceItem(const QByteArray* characterContentStream, QChar character, PDFReal advance, uint cid) : characterContentStream(characterContentStream), character(character), advance(advance), cid(cid) { }
inline bool isContentStream() const { return characterContentStream; }
inline bool isCharacter() const { return glyph; }
@@ -83,6 +83,7 @@ struct TextSequenceItem
const QByteArray* characterContentStream = nullptr;
QChar character;
PDFReal advance = 0;
CID cid = 0;
};
struct TextSequence

View File

@@ -0,0 +1,589 @@
// Copyright (C) 2023 Jakub Melka
//
// This file is part of PDF4QT.
//
// PDF4QT is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// with the written consent of the copyright owner, any later version.
//
// PDF4QT is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
#include "pdfpagecontenteditorprocessor.h"
namespace pdf
{
PDFPageContentEditorProcessor::PDFPageContentEditorProcessor(const PDFPage* page,
const PDFDocument* document,
const PDFFontCache* fontCache,
const PDFCMS* CMS,
const PDFOptionalContentActivity* optionalContentActivity,
QTransform pagePointToDevicePointMatrix,
const PDFMeshQualitySettings& meshQualitySettings) :
BaseClass(page, document, fontCache, CMS, optionalContentActivity, pagePointToDevicePointMatrix, meshQualitySettings)
{
m_clippingPaths.push(QPainterPath());
}
const PDFEditedPageContent& PDFPageContentEditorProcessor::getEditedPageContent() const
{
return m_content;
}
PDFEditedPageContent PDFPageContentEditorProcessor::takeEditedPageContent()
{
return std::move(m_content);
}
void PDFPageContentEditorProcessor::performInterceptInstruction(Operator currentOperator,
ProcessOrder processOrder,
const QByteArray& operatorAsText)
{
Q_UNUSED(operatorAsText);
if (processOrder == ProcessOrder::BeforeOperation)
{
if (currentOperator == Operator::TextBegin && !isTextProcessing())
{
m_contentElementText.reset(new PDFEditedPageContentElementText(*getGraphicState()));
}
}
else
{
if (currentOperator == Operator::TextEnd && !isTextProcessing())
{
if (m_contentElementText && !m_contentElementText->isEmpty())
{
m_content.addContentElement(std::move(m_contentElementText));
}
m_contentElementText.reset();
m_textBoundingRect = QRectF();
}
}
}
void PDFPageContentEditorProcessor::performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule)
{
if (path.isEmpty())
{
return;
}
Q_UNUSED(fillRule);
Q_UNUSED(stroke);
Q_UNUSED(fill);
Q_UNUSED(text);
if (text)
{
QPainterPath mappedPath = getCurrentWorldMatrix().map(path);
QRectF boundingRect = mappedPath.boundingRect();
m_textBoundingRect = m_textBoundingRect.united(boundingRect);
}
else
{
m_content.addContentPath(*getGraphicState(), path, stroke, fill);
}
}
void PDFPageContentEditorProcessor::performUpdateGraphicsState(const PDFPageContentProcessorState& state)
{
if (isTextProcessing() && m_contentElementText)
{
PDFEditedPageContentElementText::Item item;
item.isUpdateGraphicState = true;
item.state = state;
m_contentElementText->addItem(item);
}
}
void PDFPageContentEditorProcessor::performProcessTextSequence(const TextSequence& textSequence, ProcessOrder order)
{
if (order == ProcessOrder::BeforeOperation)
{
PDFEditedPageContentElementText::Item item;
item.isText = true;
item.textSequence = textSequence;
m_contentElementText->addItem(item);
}
}
bool PDFPageContentEditorProcessor::performOriginalImagePainting(const PDFImage& image, const PDFStream* stream)
{
Q_UNUSED(image);
PDFObject imageObject = PDFObject::createStream(std::make_shared<PDFStream>(*stream));
m_content.addContentImage(*getGraphicState(), std::move(imageObject), QImage());
return false;
}
void PDFPageContentEditorProcessor::performImagePainting(const QImage& image)
{
PDFEditedPageContentElement* backElement = m_content.getBackElement();
Q_ASSERT(backElement);
PDFEditedPageContentElementImage* imageElement = backElement->asImage();
imageElement->setImage(image);
}
void PDFPageContentEditorProcessor::performSaveGraphicState(ProcessOrder order)
{
if (order == ProcessOrder::BeforeOperation)
{
m_clippingPaths.push(m_clippingPaths.top());
}
}
void PDFPageContentEditorProcessor::performRestoreGraphicState(ProcessOrder order)
{
if (order == ProcessOrder::AfterOperation)
{
m_clippingPaths.pop();
}
}
void PDFPageContentEditorProcessor::performClipping(const QPainterPath& path, Qt::FillRule fillRule)
{
Q_UNUSED(fillRule);
if (m_clippingPaths.top().isEmpty())
{
m_clippingPaths.top() = path;
}
else
{
m_clippingPaths.top() = m_clippingPaths.top().intersected(path);
}
}
bool PDFPageContentEditorProcessor::isContentKindSuppressed(ContentKind kind) const
{
switch (kind)
{
case ContentKind::Shading:
case ContentKind::Tiling:
return true;
default:
break;
}
return false;
}
QString PDFEditedPageContent::getOperatorToString(PDFPageContentProcessor::Operator operatorValue)
{
switch (operatorValue)
{
case pdf::PDFPageContentProcessor::Operator::SetLineWidth:
return "set_line_width";
case pdf::PDFPageContentProcessor::Operator::SetLineCap:
return "set_line_cap";
case pdf::PDFPageContentProcessor::Operator::SetLineJoin:
return "set_line_join";
case pdf::PDFPageContentProcessor::Operator::SetMitterLimit:
return "set_mitter_limit";
case pdf::PDFPageContentProcessor::Operator::SetLineDashPattern:
return "set_line_dash_pattern";
case pdf::PDFPageContentProcessor::Operator::SetRenderingIntent:
return "set_rendering_intent";
case pdf::PDFPageContentProcessor::Operator::SetFlatness:
return "set_flatness";
case pdf::PDFPageContentProcessor::Operator::SetGraphicState:
return "set_graphic_state";
case pdf::PDFPageContentProcessor::Operator::SaveGraphicState:
return "save";
case pdf::PDFPageContentProcessor::Operator::RestoreGraphicState:
return "restore";
case pdf::PDFPageContentProcessor::Operator::AdjustCurrentTransformationMatrix:
return "set_cm";
case pdf::PDFPageContentProcessor::Operator::MoveCurrentPoint:
return "move_to";
case pdf::PDFPageContentProcessor::Operator::LineTo:
return "line_to";
case pdf::PDFPageContentProcessor::Operator::Bezier123To:
return "cubic123_to";
case pdf::PDFPageContentProcessor::Operator::Bezier23To:
return "cubic23_to";
case pdf::PDFPageContentProcessor::Operator::Bezier13To:
return "cubic13_to";
case pdf::PDFPageContentProcessor::Operator::EndSubpath:
return "close_path";
case pdf::PDFPageContentProcessor::Operator::Rectangle:
return "rect";
case pdf::PDFPageContentProcessor::Operator::PathStroke:
return "path_stroke";
case pdf::PDFPageContentProcessor::Operator::PathCloseStroke:
return "path_close_and_stroke";
case pdf::PDFPageContentProcessor::Operator::PathFillWinding:
return "path_fill_winding";
case pdf::PDFPageContentProcessor::Operator::PathFillWinding2:
return "path_fill_winding";
case pdf::PDFPageContentProcessor::Operator::PathFillEvenOdd:
return "path_fill_even_odd";
case pdf::PDFPageContentProcessor::Operator::PathFillStrokeWinding:
return "path_fill_stroke_winding";
case pdf::PDFPageContentProcessor::Operator::PathFillStrokeEvenOdd:
return "path_fill_stroke_even_odd";
case pdf::PDFPageContentProcessor::Operator::PathCloseFillStrokeWinding:
return "path_close_fill_stroke_winding";
case pdf::PDFPageContentProcessor::Operator::PathCloseFillStrokeEvenOdd:
return "path_close_fill_stroke_even_odd";
case pdf::PDFPageContentProcessor::Operator::PathClear:
return "path_clear";
case pdf::PDFPageContentProcessor::Operator::ClipWinding:
return "clip_winding";
case pdf::PDFPageContentProcessor::Operator::ClipEvenOdd:
return "clip_even_odd";
case pdf::PDFPageContentProcessor::Operator::TextBegin:
return "text_begin";
case pdf::PDFPageContentProcessor::Operator::TextEnd:
return "text_end";
case pdf::PDFPageContentProcessor::Operator::TextSetCharacterSpacing:
return "set_char_spacing";
case pdf::PDFPageContentProcessor::Operator::TextSetWordSpacing:
return "set_word_spacing";
case pdf::PDFPageContentProcessor::Operator::TextSetHorizontalScale:
return "set_hor_scale";
case pdf::PDFPageContentProcessor::Operator::TextSetLeading:
return "set_leading";
case pdf::PDFPageContentProcessor::Operator::TextSetFontAndFontSize:
return "set_font";
case pdf::PDFPageContentProcessor::Operator::TextSetRenderMode:
return "set_text_render_mode";
case pdf::PDFPageContentProcessor::Operator::TextSetRise:
return "set_text_rise";
case pdf::PDFPageContentProcessor::Operator::TextMoveByOffset:
return "text_move_by_offset";
case pdf::PDFPageContentProcessor::Operator::TextSetLeadingAndMoveByOffset:
return "text_set_leading_and_move_by_offset";
case pdf::PDFPageContentProcessor::Operator::TextSetMatrix:
return "text_set_matrix";
case pdf::PDFPageContentProcessor::Operator::TextMoveByLeading:
return "text_move_by_leading";
case pdf::PDFPageContentProcessor::Operator::TextShowTextString:
return "text_show_string";
case pdf::PDFPageContentProcessor::Operator::TextShowTextIndividualSpacing:
return "text_show_string_with_spacing";
case pdf::PDFPageContentProcessor::Operator::TextNextLineShowText:
return "text_next_line_and_show_text";
case pdf::PDFPageContentProcessor::Operator::TextSetSpacingAndShowText:
return "text_set_spacing_and_show_text";
case pdf::PDFPageContentProcessor::Operator::Type3FontSetOffset:
return "text_t3_set_offset";
case pdf::PDFPageContentProcessor::Operator::Type3FontSetOffsetAndBB:
return "text_t3_set_offset_and_bb";
case pdf::PDFPageContentProcessor::Operator::ColorSetStrokingColorSpace:
return "set_stroke_color_space";
case pdf::PDFPageContentProcessor::Operator::ColorSetFillingColorSpace:
return "set_filling_color_space";
case pdf::PDFPageContentProcessor::Operator::ColorSetStrokingColor:
return "set_stroke_color";
case pdf::PDFPageContentProcessor::Operator::ColorSetStrokingColorN:
return "set_stroke_color_n";
case pdf::PDFPageContentProcessor::Operator::ColorSetFillingColor:
return "set_filling_color";
case pdf::PDFPageContentProcessor::Operator::ColorSetFillingColorN:
return "set_filling_color_n";
case pdf::PDFPageContentProcessor::Operator::ColorSetDeviceGrayStroking:
return "set_stroke_gray_cs";
case pdf::PDFPageContentProcessor::Operator::ColorSetDeviceGrayFilling:
return "set_filling_gray_cs";
case pdf::PDFPageContentProcessor::Operator::ColorSetDeviceRGBStroking:
return "set_stroke_rgb_cs";
case pdf::PDFPageContentProcessor::Operator::ColorSetDeviceRGBFilling:
return "set_filling_rgb_cs";
case pdf::PDFPageContentProcessor::Operator::ColorSetDeviceCMYKStroking:
return "set_stroke_cmyk_cs";
case pdf::PDFPageContentProcessor::Operator::ColorSetDeviceCMYKFilling:
return "set_filling_cmyk_cs";
case pdf::PDFPageContentProcessor::Operator::ShadingPaintShape:
return "shading_paint";
case pdf::PDFPageContentProcessor::Operator::InlineImageBegin:
return "ib";
case pdf::PDFPageContentProcessor::Operator::InlineImageData:
return "id";
case pdf::PDFPageContentProcessor::Operator::InlineImageEnd:
return "ie";
case pdf::PDFPageContentProcessor::Operator::PaintXObject:
return "paint_object";
case pdf::PDFPageContentProcessor::Operator::MarkedContentPoint:
return "mc_point";
case pdf::PDFPageContentProcessor::Operator::MarkedContentPointWithProperties:
return "mc_point_prop";
case pdf::PDFPageContentProcessor::Operator::MarkedContentBegin:
return "mc_begin";
case pdf::PDFPageContentProcessor::Operator::MarkedContentBeginWithProperties:
return "mc_begin_prop";
case pdf::PDFPageContentProcessor::Operator::MarkedContentEnd:
return "mc_end";
case pdf::PDFPageContentProcessor::Operator::CompatibilityBegin:
return "compat_begin";
case pdf::PDFPageContentProcessor::Operator::CompatibilityEnd:
return "compat_end";
default:
break;
}
return QString();
}
QString PDFEditedPageContent::getOperandName(PDFPageContentProcessor::Operator operatorValue, int operandIndex)
{
static const std::map<std::pair<PDFPageContentProcessor::Operator, int>, QString> operands =
{
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::SetLineWidth, 0), "lineWidth" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::SetLineCap, 0), "lineCap" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::SetLineJoin, 0), "lineJoin" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::SetMitterLimit, 0), "mitterLimit" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::SetRenderingIntent, 0), "renderingIntent" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::SetFlatness, 0), "flatness" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::SetGraphicState, 0), "graphicState" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::AdjustCurrentTransformationMatrix, 0), "a" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::AdjustCurrentTransformationMatrix, 1), "b" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::AdjustCurrentTransformationMatrix, 2), "c" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::AdjustCurrentTransformationMatrix, 3), "d" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::AdjustCurrentTransformationMatrix, 4), "e" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::AdjustCurrentTransformationMatrix, 5), "f" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::MoveCurrentPoint, 0), "x" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::MoveCurrentPoint, 1), "y" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::LineTo, 0), "x" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::LineTo, 1), "y" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier123To, 0), "x1" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier123To, 1), "y1" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier123To, 2), "x2" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier123To, 3), "y2" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier123To, 4), "x3" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier123To, 5), "y3" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier23To, 0), "x2" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier23To, 1), "y2" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier23To, 2), "x3" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier23To, 3), "y3" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier13To, 0), "x1" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier13To, 1), "y1" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier13To, 2), "x3" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Bezier13To, 3), "y3" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Rectangle, 0), "x" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Rectangle, 1), "y" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Rectangle, 2), "width" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::Rectangle, 3), "height" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetCharacterSpacing, 0), "charSpacing" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetWordSpacing, 0), "wordSpacing" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetHorizontalScale, 0), "scale" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetLeading, 0), "leading" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetFontAndFontSize, 0), "font" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetFontAndFontSize, 1), "fontSize" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetRenderMode, 0), "renderMode" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetRise, 0), "rise" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextMoveByOffset, 0), "tx" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextMoveByOffset, 1), "ty" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetLeadingAndMoveByOffset, 0), "tx" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetLeadingAndMoveByOffset, 1), "ty" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetMatrix, 0), "a" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetMatrix, 1), "b" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetMatrix, 2), "c" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetMatrix, 3), "d" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetMatrix, 4), "e" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetMatrix, 5), "f" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextShowTextString, 0), "string" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextNextLineShowText, 0), "string" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextShowTextIndividualSpacing, 0), "wSpacing" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextShowTextIndividualSpacing, 1), "chSpacing" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextShowTextIndividualSpacing, 2), "string" },
{ std::make_pair(pdf::PDFPageContentProcessor::Operator::TextSetSpacingAndShowText, 0), "string" },
};
auto it = operands.find(std::make_pair(operatorValue, operandIndex));
if (it != operands.cend())
{
return it->second;
}
return QString("op%1").arg(operandIndex);
}
void PDFEditedPageContent::addContentPath(PDFPageContentProcessorState state, QPainterPath path, bool strokePath, bool fillPath)
{
m_contentElements.emplace_back(new PDFEditedPageContentElementPath(std::move(state), std::move(path), strokePath, fillPath));
}
void PDFEditedPageContent::addContentImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image)
{
m_contentElements.emplace_back(new PDFEditedPageContentElementImage(std::move(state), std::move(imageObject), std::move(image)));
}
void PDFEditedPageContent::addContentElement(std::unique_ptr<PDFEditedPageContentElement> element)
{
m_contentElements.emplace_back(std::move(element));
}
PDFEditedPageContentElement* PDFEditedPageContent::getBackElement() const
{
if (m_contentElements.empty())
{
return nullptr;
}
return m_contentElements.back().get();
}
PDFEditedPageContentElement::PDFEditedPageContentElement(PDFPageContentProcessorState state) :
m_state(std::move(state))
{
}
const PDFPageContentProcessorState& PDFEditedPageContentElement::getState() const
{
return m_state;
}
void PDFEditedPageContentElement::setState(const PDFPageContentProcessorState& newState)
{
m_state = newState;
}
PDFEditedPageContentElementPath::PDFEditedPageContentElementPath(PDFPageContentProcessorState state, QPainterPath path, bool strokePath, bool fillPath) :
PDFEditedPageContentElement(std::move(state)),
m_path(std::move(path)),
m_strokePath(strokePath),
m_fillPath(fillPath)
{
}
PDFEditedPageContentElement::Type PDFEditedPageContentElementPath::getType() const
{
return Type::Path;
}
PDFEditedPageContentElementPath* PDFEditedPageContentElementPath::clone() const
{
return new PDFEditedPageContentElementPath(getState(), getPath(), getStrokePath(), getFillPath());
}
QRectF PDFEditedPageContentElementPath::getBoundingBox() const
{
QPainterPath mappedPath = getState().getCurrentTransformationMatrix().map(m_path);
return mappedPath.boundingRect();
}
QPainterPath PDFEditedPageContentElementPath::getPath() const
{
return m_path;
}
void PDFEditedPageContentElementPath::setPath(QPainterPath newPath)
{
m_path = newPath;
}
bool PDFEditedPageContentElementPath::getStrokePath() const
{
return m_strokePath;
}
void PDFEditedPageContentElementPath::setStrokePath(bool newStrokePath)
{
m_strokePath = newStrokePath;
}
bool PDFEditedPageContentElementPath::getFillPath() const
{
return m_fillPath;
}
void PDFEditedPageContentElementPath::setFillPath(bool newFillPath)
{
m_fillPath = newFillPath;
}
PDFEditedPageContentElementImage::PDFEditedPageContentElementImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image) :
PDFEditedPageContentElement(std::move(state)),
m_imageObject(std::move(imageObject)),
m_image(std::move(image))
{
}
PDFEditedPageContentElement::Type PDFEditedPageContentElementImage::getType() const
{
return PDFEditedPageContentElement::Type::Image;
}
PDFEditedPageContentElementImage* PDFEditedPageContentElementImage::clone() const
{
return new PDFEditedPageContentElementImage(getState(), getImageObject(), getImage());
}
PDFObject PDFEditedPageContentElementImage::getImageObject() const
{
return m_imageObject;
}
void PDFEditedPageContentElementImage::setImageObject(const PDFObject& newImageObject)
{
m_imageObject = newImageObject;
}
QImage PDFEditedPageContentElementImage::getImage() const
{
return m_image;
}
void PDFEditedPageContentElementImage::setImage(const QImage& newImage)
{
m_image = newImage;
}
PDFEditedPageContentElementText::PDFEditedPageContentElementText(PDFPageContentProcessorState state) :
PDFEditedPageContentElement(state)
{
}
PDFEditedPageContentElementText::PDFEditedPageContentElementText(PDFPageContentProcessorState state, std::vector<Item> items) :
PDFEditedPageContentElement(state),
m_items(std::move(items))
{
}
PDFEditedPageContentElement::Type PDFEditedPageContentElementText::getType() const
{
return Type::Text;
}
PDFEditedPageContentElementText* PDFEditedPageContentElementText::clone() const
{
return new PDFEditedPageContentElementText(getState(), getItems());
}
void PDFEditedPageContentElementText::addItem(Item item)
{
m_items.emplace_back(std::move(item));
}
const std::vector<PDFEditedPageContentElementText::Item>& PDFEditedPageContentElementText::getItems() const
{
return m_items;
}
void PDFEditedPageContentElementText::setItems(const std::vector<Item>& newItems)
{
m_items = newItems;
}
} // namespace pdf

View File

@@ -0,0 +1,212 @@
// Copyright (C) 2023 Jakub Melka
//
// This file is part of PDF4QT.
//
// PDF4QT is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// with the written consent of the copyright owner, any later version.
//
// PDF4QT is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
#ifndef PDFPAGECONTENTEDITORPROCESSOR_H
#define PDFPAGECONTENTEDITORPROCESSOR_H
#include "pdfpagecontentprocessor.h"
#include <memory>
namespace pdf
{
class PDFEditedPageContentElementPath;
class PDFEditedPageContentElementText;
class PDFEditedPageContentElementImage;
class PDFEditedPageContentElement
{
public:
PDFEditedPageContentElement() = default;
PDFEditedPageContentElement(PDFPageContentProcessorState state);
virtual ~PDFEditedPageContentElement() = default;
enum class Type
{
Path,
Text,
Image
};
virtual Type getType() const = 0;
virtual PDFEditedPageContentElement* clone() const = 0;
virtual PDFEditedPageContentElementPath* asPath() { return nullptr; }
virtual const PDFEditedPageContentElementPath* asPath() const { return nullptr; }
virtual PDFEditedPageContentElementText* asText() { return nullptr; }
virtual const PDFEditedPageContentElementText* asText() const { return nullptr; }
virtual PDFEditedPageContentElementImage* asImage() { return nullptr; }
virtual const PDFEditedPageContentElementImage* asImage() const { return nullptr; }
const PDFPageContentProcessorState& getState() const;
void setState(const PDFPageContentProcessorState& newState);
virtual QRectF getBoundingBox() const = 0;
protected:
PDFPageContentProcessorState m_state;
};
class PDFEditedPageContentElementPath : public PDFEditedPageContentElement
{
public:
PDFEditedPageContentElementPath(PDFPageContentProcessorState state, QPainterPath path, bool strokePath, bool fillPath);
virtual ~PDFEditedPageContentElementPath() = default;
virtual Type getType() const override;
virtual PDFEditedPageContentElementPath* clone() const override;
virtual PDFEditedPageContentElementPath* asPath() override { return this; }
virtual const PDFEditedPageContentElementPath* asPath() const override { return this; }
virtual QRectF getBoundingBox() const override;
QPainterPath getPath() const;
void setPath(QPainterPath newPath);
bool getStrokePath() const;
void setStrokePath(bool newStrokePath);
bool getFillPath() const;
void setFillPath(bool newFillPath);
private:
QPainterPath m_path;
bool m_strokePath;
bool m_fillPath;
};
class PDFEditedPageContentElementImage : public PDFEditedPageContentElement
{
public:
PDFEditedPageContentElementImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image);
virtual ~PDFEditedPageContentElementImage() = default;
virtual Type getType() const override;
virtual PDFEditedPageContentElementImage* clone() const override;
virtual PDFEditedPageContentElementImage* asImage() override { return this; }
virtual const PDFEditedPageContentElementImage* asImage() const override { return this; }
PDFObject getImageObject() const;
void setImageObject(const PDFObject& newImageObject);
QImage getImage() const;
void setImage(const QImage& newImage);
private:
PDFObject m_imageObject;
QImage m_image;
};
class PDFEditedPageContentElementText : public PDFEditedPageContentElement
{
public:
struct Item
{
bool isUpdateGraphicState = false;
bool isText = false;
TextSequence textSequence;
PDFPageContentProcessorState state;
};
PDFEditedPageContentElementText(PDFPageContentProcessorState state);
PDFEditedPageContentElementText(PDFPageContentProcessorState state, std::vector<Item> items);
virtual ~PDFEditedPageContentElementText() = default;
virtual Type getType() const override;
virtual PDFEditedPageContentElementText* clone() const override;
virtual PDFEditedPageContentElementText* asText() override { return this; }
virtual const PDFEditedPageContentElementText* asText() const override { return this; }
void addItem(Item item);
const std::vector<Item>& getItems() const;
void setItems(const std::vector<Item>& newItems);
bool isEmpty() const { return m_items.empty(); }
private:
std::vector<Item> m_items;
};
class PDFEditedPageContent
{
public:
PDFEditedPageContent() = default;
PDFEditedPageContent(const PDFEditedPageContent&) = delete;
PDFEditedPageContent(PDFEditedPageContent&&) = default;
PDFEditedPageContent& operator=(const PDFEditedPageContent&) = delete;
PDFEditedPageContent& operator=(PDFEditedPageContent&&) = default;
static QString getOperatorToString(PDFPageContentProcessor::Operator operatorValue);
static QString getOperandName(PDFPageContentProcessor::Operator operatorValue, int operandIndex);
void addContentPath(PDFPageContentProcessorState state, QPainterPath path, bool strokePath, bool fillPath);
void addContentImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image);
void addContentClipping(PDFPageContentProcessorState state, QPainterPath path);
void addContentElement(std::unique_ptr<PDFEditedPageContentElement> element);
std::size_t getElementCount() const { return m_contentElements.size(); }
PDFEditedPageContentElement* getElement(size_t index) const { return m_contentElements.at(index).get(); }
PDFEditedPageContentElement* getBackElement() const;
private:
std::vector<std::unique_ptr<PDFEditedPageContentElement>> m_contentElements;
};
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentEditorProcessor : public PDFPageContentProcessor
{
using BaseClass = PDFPageContentProcessor;
public:
PDFPageContentEditorProcessor(const PDFPage* page,
const PDFDocument* document,
const PDFFontCache* fontCache,
const PDFCMS* CMS,
const PDFOptionalContentActivity* optionalContentActivity,
QTransform pagePointToDevicePointMatrix,
const PDFMeshQualitySettings& meshQualitySettings);
const PDFEditedPageContent& getEditedPageContent() const;
PDFEditedPageContent takeEditedPageContent();
protected:
virtual void performInterceptInstruction(Operator currentOperator, ProcessOrder processOrder, const QByteArray& operatorAsText) override;
virtual void performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule) override;
virtual bool isContentKindSuppressed(ContentKind kind) const override;
virtual bool performOriginalImagePainting(const PDFImage& image, const PDFStream* stream) override;
virtual void performImagePainting(const QImage& image) override;
virtual void performClipping(const QPainterPath& path, Qt::FillRule fillRule) override;
virtual void performSaveGraphicState(ProcessOrder order) override;
virtual void performRestoreGraphicState(ProcessOrder order) override;
virtual void performUpdateGraphicsState(const PDFPageContentProcessorState& state) override;
virtual void performProcessTextSequence(const TextSequence& textSequence, ProcessOrder order) override;
private:
PDFEditedPageContent m_content;
QRectF m_textBoundingRect;
std::stack<QPainterPath> m_clippingPaths;
std::unique_ptr<PDFEditedPageContentElementText> m_contentElementText;
};
} // namespace pdf
#endif // PDFPAGECONTENTEDITORPROCESSOR_H

View File

@@ -23,6 +23,7 @@
#include "pdfexecutionpolicy.h"
#include "pdfstreamfilters.h"
#include <QScopeGuard>
#include <QPainterPathStroker>
#include <QtMath>
@@ -390,9 +391,10 @@ void PDFPageContentProcessor::performClipping(const QPainterPath& path, Qt::Fill
Q_UNUSED(fillRule);
}
bool PDFPageContentProcessor::performOriginalImagePainting(const PDFImage& image)
bool PDFPageContentProcessor::performOriginalImagePainting(const PDFImage& image, const PDFStream* stream)
{
Q_UNUSED(image);
Q_UNUSED(stream);
return false;
}
@@ -485,6 +487,12 @@ void PDFPageContentProcessor::performTextEnd(ProcessOrder order)
Q_UNUSED(order);
}
void PDFPageContentProcessor::performProcessTextSequence(const TextSequence& textSequence, ProcessOrder order)
{
Q_UNUSED(textSequence);
Q_UNUSED(order);
}
bool PDFPageContentProcessor::isContentKindSuppressed(ContentKind kind) const
{
Q_UNUSED(kind);
@@ -528,6 +536,15 @@ PDFPageContentProcessor::PDFTransparencyGroup PDFPageContentProcessor::parseTran
return group;
}
void PDFPageContentProcessor::performInterceptInstruction(Operator currentOperator,
ProcessOrder processOrder,
const QByteArray& operatorAsText)
{
Q_UNUSED(currentOperator);
Q_UNUSED(processOrder);
Q_UNUSED(operatorAsText);
}
void PDFPageContentProcessor::processContent(const QByteArray& content)
{
PDFLexicalAnalyzer parser(content.constBegin(), content.constEnd());
@@ -738,6 +755,12 @@ void PDFPageContentProcessor::processForm(const QTransform& matrix,
const QByteArray& content,
PDFInteger formStructuralParent)
{
if (isContentKindSuppressed(ContentKind::Forms))
{
// Process of forms is suppressed
return;
}
PDFPageContentProcessorStateGuard guard(this);
PDFTemporaryValueChange structuralParentChangeGuard(&m_structuralParentKey, formStructuralParent);
@@ -1129,6 +1152,9 @@ void PDFPageContentProcessor::processCommand(const QByteArray& command)
}
}
performInterceptInstruction(op, ProcessOrder::BeforeOperation, command);
auto callInterceptInstAtEnd = qScopeGuard([&, this](){ performInterceptInstruction(op, ProcessOrder::AfterOperation, command); });
switch (op)
{
case Operator::SetLineWidth:
@@ -1855,6 +1881,11 @@ bool PDFPageContentProcessor::isProcessingCancelled() const
return m_operationControl && m_operationControl->isOperationCancelled();
}
bool PDFPageContentProcessor::isTextProcessing() const
{
return m_textBeginEndState > 0;
}
void PDFPageContentProcessor::reportRenderErrorOnce(RenderErrorType type, QString message)
{
if (!m_onceReportedErrors.count(message))
@@ -2973,7 +3004,7 @@ void PDFPageContentProcessor::paintXObjectImage(const PDFStream* stream)
PDFImage pdfImage = PDFImage::createImage(m_document, stream, qMove(colorSpace), false, m_graphicState.getRenderingIntent(), this);
if (!performOriginalImagePainting(pdfImage))
if (!performOriginalImagePainting(pdfImage, stream))
{
QImage image = pdfImage.getImage(m_CMS, this, m_operationControl);
@@ -3007,6 +3038,12 @@ void PDFPageContentProcessor::reportWarningAboutColorOperatorsInUTP()
void PDFPageContentProcessor::processForm(const PDFStream* stream)
{
if (isContentKindSuppressed(ContentKind::Forms))
{
// Process of forms is suppressed
return;
}
PDFDocumentDataLoaderDecorator loader(getDocument());
const PDFDictionary* streamDictionary = stream->getDictionary();
@@ -3165,6 +3202,8 @@ void PDFPageContentProcessor::drawText(const TextSequence& textSequence)
return;
}
performProcessTextSequence(textSequence, ProcessOrder::BeforeOperation);
const PDFRealizedFontPointer& font = getRealizedFont();
if (font)
{
@@ -3340,6 +3379,8 @@ void PDFPageContentProcessor::drawText(const TextSequence& textSequence)
{
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Invalid font, text can't be printed."));
}
performProcessTextSequence(textSequence, ProcessOrder::AfterOperation);
}
PDFRealizedFontPointer PDFPageContentProcessor::getRealizedFontImpl()
@@ -3415,7 +3456,7 @@ bool PDFPageContentProcessor::isContentSuppressedByOC(PDFObjectReference ocgOrOc
return false;
}
PDFPageContentProcessor::PDFPageContentProcessorState::PDFPageContentProcessorState() :
PDFPageContentProcessorState::PDFPageContentProcessorState() :
m_currentTransformationMatrix(),
m_strokeColorSpace(),
m_fillColorSpace(),
@@ -3456,12 +3497,12 @@ PDFPageContentProcessor::PDFPageContentProcessorState::PDFPageContentProcessorSt
m_strokeColorOriginal = m_fillColorOriginal;
}
PDFPageContentProcessor::PDFPageContentProcessorState::~PDFPageContentProcessorState()
PDFPageContentProcessorState::~PDFPageContentProcessorState()
{
}
PDFPageContentProcessor::PDFPageContentProcessorState& PDFPageContentProcessor::PDFPageContentProcessorState::operator=(const PDFPageContentProcessor::PDFPageContentProcessorState& other)
PDFPageContentProcessorState& PDFPageContentProcessorState::operator=(const PDFPageContentProcessorState& other)
{
setCurrentTransformationMatrix(other.getCurrentTransformationMatrix());
setStrokeColorSpace(other.m_strokeColorSpace);
@@ -3504,7 +3545,7 @@ PDFPageContentProcessor::PDFPageContentProcessorState& PDFPageContentProcessor::
return *this;
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setCurrentTransformationMatrix(const QTransform& currentTransformationMatrix)
void PDFPageContentProcessorState::setCurrentTransformationMatrix(const QTransform& currentTransformationMatrix)
{
if (m_currentTransformationMatrix != currentTransformationMatrix)
{
@@ -3513,7 +3554,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setCurrentTransforma
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setStrokeColorSpace(const QSharedPointer<PDFAbstractColorSpace>& strokeColorSpace)
void PDFPageContentProcessorState::setStrokeColorSpace(const QSharedPointer<PDFAbstractColorSpace>& strokeColorSpace)
{
if (m_strokeColorSpace != strokeColorSpace)
{
@@ -3522,7 +3563,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setStrokeColorSpace(
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setFillColorSpace(const QSharedPointer<PDFAbstractColorSpace>& fillColorSpace)
void PDFPageContentProcessorState::setFillColorSpace(const QSharedPointer<PDFAbstractColorSpace>& fillColorSpace)
{
if (m_fillColorSpace != fillColorSpace)
{
@@ -3531,7 +3572,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setFillColorSpace(co
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setStrokeColor(const QColor& strokeColor, const PDFColor& originalColor)
void PDFPageContentProcessorState::setStrokeColor(const QColor& strokeColor, const PDFColor& originalColor)
{
if (m_strokeColor != strokeColor || m_strokeColorOriginal != originalColor)
{
@@ -3541,7 +3582,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setStrokeColor(const
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setFillColor(const QColor& fillColor, const PDFColor& originalColor)
void PDFPageContentProcessorState::setFillColor(const QColor& fillColor, const PDFColor& originalColor)
{
if (m_fillColor != fillColor || m_fillColorOriginal != originalColor)
{
@@ -3551,7 +3592,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setFillColor(const Q
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setLineWidth(PDFReal lineWidth)
void PDFPageContentProcessorState::setLineWidth(PDFReal lineWidth)
{
if (m_lineWidth != lineWidth)
{
@@ -3560,7 +3601,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setLineWidth(PDFReal
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setLineCapStyle(Qt::PenCapStyle lineCapStyle)
void PDFPageContentProcessorState::setLineCapStyle(Qt::PenCapStyle lineCapStyle)
{
if (m_lineCapStyle != lineCapStyle)
{
@@ -3569,7 +3610,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setLineCapStyle(Qt::
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setLineJoinStyle(Qt::PenJoinStyle lineJoinStyle)
void PDFPageContentProcessorState::setLineJoinStyle(Qt::PenJoinStyle lineJoinStyle)
{
if (m_lineJoinStyle != lineJoinStyle)
{
@@ -3578,7 +3619,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setLineJoinStyle(Qt:
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setMitterLimit(PDFReal mitterLimit)
void PDFPageContentProcessorState::setMitterLimit(PDFReal mitterLimit)
{
if (m_mitterLimit != mitterLimit)
{
@@ -3587,7 +3628,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setMitterLimit(PDFRe
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setLineDashPattern(PDFLineDashPattern pattern)
void PDFPageContentProcessorState::setLineDashPattern(PDFLineDashPattern pattern)
{
if (m_lineDashPattern != pattern)
{
@@ -3596,7 +3637,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setLineDashPattern(P
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setRenderingIntentName(const QByteArray& renderingIntentName)
void PDFPageContentProcessorState::setRenderingIntentName(const QByteArray& renderingIntentName)
{
if (m_renderingIntentName != renderingIntentName)
{
@@ -3605,7 +3646,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setRenderingIntentNa
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setFlatness(PDFReal flatness)
void PDFPageContentProcessorState::setFlatness(PDFReal flatness)
{
if (m_flatness != flatness)
{
@@ -3614,7 +3655,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setFlatness(PDFReal
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setSmoothness(PDFReal smoothness)
void PDFPageContentProcessorState::setSmoothness(PDFReal smoothness)
{
if (m_smoothness != smoothness)
{
@@ -3623,7 +3664,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setSmoothness(PDFRea
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextLeading(PDFReal textLeading)
void PDFPageContentProcessorState::setTextLeading(PDFReal textLeading)
{
if (m_textLeading != textLeading)
{
@@ -3632,7 +3673,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setTextLeading(PDFRe
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextFontSize(PDFReal textFontSize)
void PDFPageContentProcessorState::setTextFontSize(PDFReal textFontSize)
{
if (m_textFontSize != textFontSize)
{
@@ -3641,7 +3682,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setTextFontSize(PDFR
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextKnockout(bool textKnockout)
void PDFPageContentProcessorState::setTextKnockout(bool textKnockout)
{
if (m_textKnockout != textKnockout)
{
@@ -3650,7 +3691,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setTextKnockout(bool
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextLineMatrix(const QTransform& textLineMatrix)
void PDFPageContentProcessorState::setTextLineMatrix(const QTransform& textLineMatrix)
{
if (m_textLineMatrix != textLineMatrix)
{
@@ -3659,7 +3700,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setTextLineMatrix(co
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setAlphaStroking(PDFReal alpha)
void PDFPageContentProcessorState::setAlphaStroking(PDFReal alpha)
{
if (m_alphaStroking != alpha)
{
@@ -3668,7 +3709,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setAlphaStroking(PDF
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setAlphaFilling(PDFReal alpha)
void PDFPageContentProcessorState::setAlphaFilling(PDFReal alpha)
{
if (m_alphaFilling != alpha)
{
@@ -3677,7 +3718,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setAlphaFilling(PDFR
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setBlendMode(BlendMode mode)
void PDFPageContentProcessorState::setBlendMode(BlendMode mode)
{
if (m_blendMode != mode)
{
@@ -3686,7 +3727,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setBlendMode(BlendMo
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setRenderingIntent(RenderingIntent renderingIntent)
void PDFPageContentProcessorState::setRenderingIntent(RenderingIntent renderingIntent)
{
if (m_renderingIntent != renderingIntent)
{
@@ -3695,21 +3736,21 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setRenderingIntent(R
}
}
QColor PDFPageContentProcessor::PDFPageContentProcessorState::getStrokeColorWithAlpha() const
QColor PDFPageContentProcessorState::getStrokeColorWithAlpha() const
{
QColor color = getStrokeColor();
color.setAlphaF(m_alphaStroking);
return color;
}
QColor PDFPageContentProcessor::PDFPageContentProcessorState::getFillColorWithAlpha() const
QColor PDFPageContentProcessorState::getFillColorWithAlpha() const
{
QColor color = getFillColor();
color.setAlphaF(m_alphaFilling);
return color;
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setOverprintMode(PDFOverprintMode overprintMode)
void PDFPageContentProcessorState::setOverprintMode(PDFOverprintMode overprintMode)
{
if (m_overprintMode != overprintMode)
{
@@ -3718,7 +3759,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setOverprintMode(PDF
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setAlphaIsShape(bool alphaIsShape)
void PDFPageContentProcessorState::setAlphaIsShape(bool alphaIsShape)
{
if (m_alphaIsShape != alphaIsShape)
{
@@ -3727,12 +3768,12 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setAlphaIsShape(bool
}
}
bool PDFPageContentProcessor::PDFPageContentProcessorState::getStrokeAdjustment() const
bool PDFPageContentProcessorState::getStrokeAdjustment() const
{
return m_strokeAdjustment;
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setStrokeAdjustment(bool strokeAdjustment)
void PDFPageContentProcessorState::setStrokeAdjustment(bool strokeAdjustment)
{
if (m_strokeAdjustment != strokeAdjustment)
{
@@ -3741,12 +3782,12 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setStrokeAdjustment(
}
}
const PDFDictionary* PDFPageContentProcessor::PDFPageContentProcessorState::getSoftMask() const
const PDFDictionary* PDFPageContentProcessorState::getSoftMask() const
{
return m_softMask;
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setSoftMask(const PDFDictionary* softMask)
void PDFPageContentProcessorState::setSoftMask(const PDFDictionary* softMask)
{
if (m_softMask != softMask)
{
@@ -3755,12 +3796,12 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setSoftMask(const PD
}
}
BlackPointCompensationMode PDFPageContentProcessor::PDFPageContentProcessorState::getBlackPointCompensationMode() const
BlackPointCompensationMode PDFPageContentProcessorState::getBlackPointCompensationMode() const
{
return m_blackPointCompensationMode;
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setBlackPointCompensationMode(BlackPointCompensationMode blackPointCompensationMode)
void PDFPageContentProcessorState::setBlackPointCompensationMode(BlackPointCompensationMode blackPointCompensationMode)
{
if (m_blackPointCompensationMode != blackPointCompensationMode)
{
@@ -3769,12 +3810,12 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setBlackPointCompens
}
}
PDFObject PDFPageContentProcessor::PDFPageContentProcessorState::getHalftone() const
PDFObject PDFPageContentProcessorState::getHalftone() const
{
return m_halftone;
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setHalftone(const PDFObject& halftone)
void PDFPageContentProcessorState::setHalftone(const PDFObject& halftone)
{
if (m_halftone != halftone)
{
@@ -3783,12 +3824,12 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setHalftone(const PD
}
}
QPointF PDFPageContentProcessor::PDFPageContentProcessorState::getHalftoneOrigin() const
QPointF PDFPageContentProcessorState::getHalftoneOrigin() const
{
return m_halftoneOrigin;
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setHalftoneOrigin(const QPointF& halftoneOrigin)
void PDFPageContentProcessorState::setHalftoneOrigin(const QPointF& halftoneOrigin)
{
if (m_halftoneOrigin != halftoneOrigin)
{
@@ -3797,12 +3838,12 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setHalftoneOrigin(co
}
}
PDFObject PDFPageContentProcessor::PDFPageContentProcessorState::getTransferFunction() const
PDFObject PDFPageContentProcessorState::getTransferFunction() const
{
return m_transferFunction;
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTransferFunction(const PDFObject& transferFunction)
void PDFPageContentProcessorState::setTransferFunction(const PDFObject& transferFunction)
{
if (m_transferFunction != transferFunction)
{
@@ -3811,12 +3852,12 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setTransferFunction(
}
}
PDFObject PDFPageContentProcessor::PDFPageContentProcessorState::getUndercolorRemovalFunction() const
PDFObject PDFPageContentProcessorState::getUndercolorRemovalFunction() const
{
return m_undercolorRemovalFunction;
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setUndercolorRemovalFunction(const PDFObject& undercolorRemovalFunction)
void PDFPageContentProcessorState::setUndercolorRemovalFunction(const PDFObject& undercolorRemovalFunction)
{
if (m_undercolorRemovalFunction != undercolorRemovalFunction)
{
@@ -3825,12 +3866,12 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setUndercolorRemoval
}
}
PDFObject PDFPageContentProcessor::PDFPageContentProcessorState::getBlackGenerationFunction() const
PDFObject PDFPageContentProcessorState::getBlackGenerationFunction() const
{
return m_blackGenerationFunction;
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setBlackGenerationFunction(const PDFObject& blackGenerationFunction)
void PDFPageContentProcessorState::setBlackGenerationFunction(const PDFObject& blackGenerationFunction)
{
if (m_blackGenerationFunction != blackGenerationFunction)
{
@@ -3839,7 +3880,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setBlackGenerationFu
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextMatrix(const QTransform& textMatrix)
void PDFPageContentProcessorState::setTextMatrix(const QTransform& textMatrix)
{
if (m_textMatrix != textMatrix)
{
@@ -3848,7 +3889,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setTextMatrix(const
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextRise(PDFReal textRise)
void PDFPageContentProcessorState::setTextRise(PDFReal textRise)
{
if (m_textRise != textRise)
{
@@ -3857,7 +3898,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setTextRise(PDFReal
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextRenderingMode(TextRenderingMode textRenderingMode)
void PDFPageContentProcessorState::setTextRenderingMode(TextRenderingMode textRenderingMode)
{
if (m_textRenderingMode != textRenderingMode)
{
@@ -3866,7 +3907,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setTextRenderingMode
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextFont(const PDFFontPointer& textFont)
void PDFPageContentProcessorState::setTextFont(const PDFFontPointer& textFont)
{
if (m_textFont != textFont)
{
@@ -3875,7 +3916,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setTextFont(const PD
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextHorizontalScaling(PDFReal textHorizontalScaling)
void PDFPageContentProcessorState::setTextHorizontalScaling(PDFReal textHorizontalScaling)
{
if (m_textHorizontalScaling != textHorizontalScaling)
{
@@ -3884,7 +3925,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setTextHorizontalSca
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextWordSpacing(PDFReal textWordSpacing)
void PDFPageContentProcessorState::setTextWordSpacing(PDFReal textWordSpacing)
{
if (m_textWordSpacing != textWordSpacing)
{
@@ -3893,7 +3934,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setTextWordSpacing(P
}
}
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextCharacterSpacing(PDFReal textCharacterSpacing)
void PDFPageContentProcessorState::setTextCharacterSpacing(PDFReal textCharacterSpacing)
{
if (m_textCharacterSpacing != textCharacterSpacing)
{

View File

@@ -48,6 +48,7 @@ class PDFOptionalContentActivity;
static constexpr const char* PDF_RESOURCE_EXTGSTATE = "ExtGState";
class PDFLineDashPattern
{
public:
@@ -79,6 +80,251 @@ private:
PDFReal m_dashOffset = 0.0;
};
struct PDFOverprintMode
{
bool overprintStroking = false;
bool overprintFilling = false;
int overprintMode = 0;
inline bool operator==(const PDFOverprintMode& other) const
{
return std::tie(overprintStroking, overprintFilling, overprintMode) == std::tie(other.overprintStroking, other.overprintFilling, other.overprintMode);
}
inline bool operator!=(const PDFOverprintMode& other) const
{
return !(*this == other);
}
};
/// Represents graphic state of the PDF (holding current graphic state parameters).
/// Please see PDF Reference 1.7, Chapter 4.3 "Graphic State"
class PDFPageContentProcessorState
{
public:
explicit PDFPageContentProcessorState();
~PDFPageContentProcessorState();
PDFPageContentProcessorState(const PDFPageContentProcessorState&) = default;
PDFPageContentProcessorState(PDFPageContentProcessorState&&) = default;
PDFPageContentProcessorState& operator=(PDFPageContentProcessorState&&) = delete;
PDFPageContentProcessorState& operator=(const PDFPageContentProcessorState& other);
enum StateFlag : uint64_t
{
StateUnchanged = 0x0000000000000000,
StateCurrentTransformationMatrix = 0x0000000000000001,
StateStrokeColorSpace = 0x0000000000000002,
StateFillColorSpace = 0x0000000000000004,
StateStrokeColor = 0x0000000000000008,
StateFillColor = 0x0000000000000010,
StateLineWidth = 0x0000000000000020,
StateLineCapStyle = 0x0000000000000040,
StateLineJoinStyle = 0x0000000000000080,
StateMitterLimit = 0x0000000000000100,
StateLineDashPattern = 0x0000000000000200,
StateRenderingIntentName = 0x0000000000000400,
StateFlatness = 0x0000000000000800,
StateSmoothness = 0x0000000000001000,
StateTextMatrix = 0x0000000000002000,
StateTextLineMatrix = 0x0000000000004000,
StateTextCharacterSpacing = 0x0000000000008000,
StateTextWordSpacing = 0x0000000000010000,
StateTextHorizontalScaling = 0x0000000000020000,
StateTextLeading = 0x0000000000040000,
StateTextFont = 0x0000000000080000,
StateTextFontSize = 0x0000000000100000,
StateTextRenderingMode = 0x0000000000200000,
StateTextRise = 0x0000000000400000,
StateTextKnockout = 0x0000000000800000,
StateAlphaStroking = 0x0000000001000000,
StateAlphaFilling = 0x0000000002000000,
StateBlendMode = 0x0000000004000000,
StateRenderingIntent = 0x0000000008000000,
StateOverprint = 0x0000000010000000,
StateAlphaIsShape = 0x0000000020000000,
StateStrokeAdjustment = 0x0000000040000000,
StateSoftMask = 0x0000000080000000,
StateBlackPointCompensation = 0x0000000100000000,
StateBlackGenerationFunction = 0x0000000200000000,
StateUndercolorRemovalFunction = 0x0000000400000000,
StateTransferFunction = 0x0000000800000000,
StateHalftone = 0x0000001000000000,
StateHalftoneOrigin = 0x0000002000000000,
StateAll = 0xFFFFFFFFFFFFFFFF
};
using StateFlags = PDFFlags<StateFlag>;
const QTransform& getCurrentTransformationMatrix() const { return m_currentTransformationMatrix; }
void setCurrentTransformationMatrix(const QTransform& currentTransformationMatrix);
const PDFAbstractColorSpace* getStrokeColorSpace() const { return m_strokeColorSpace.data(); }
void setStrokeColorSpace(const QSharedPointer<PDFAbstractColorSpace>& strokeColorSpace);
const PDFAbstractColorSpace* getFillColorSpace() const { return m_fillColorSpace.data(); }
void setFillColorSpace(const QSharedPointer<PDFAbstractColorSpace>& fillColorSpace);
const QColor& getStrokeColor() const { return m_strokeColor; }
const PDFColor& getStrokeColorOriginal() const { return m_strokeColorOriginal; }
void setStrokeColor(const QColor& strokeColor, const PDFColor& originalColor);
const QColor& getFillColor() const { return m_fillColor; }
const PDFColor& getFillColorOriginal() const { return m_fillColorOriginal; }
void setFillColor(const QColor& fillColor, const PDFColor& originalColor);
PDFReal getLineWidth() const { return m_lineWidth; }
void setLineWidth(PDFReal lineWidth);
Qt::PenCapStyle getLineCapStyle() const { return m_lineCapStyle; }
void setLineCapStyle(Qt::PenCapStyle lineCapStyle);
Qt::PenJoinStyle getLineJoinStyle() const { return m_lineJoinStyle; }
void setLineJoinStyle(Qt::PenJoinStyle lineJoinStyle);
PDFReal getMitterLimit() const { return m_mitterLimit; }
void setMitterLimit(PDFReal mitterLimit);
const PDFLineDashPattern& getLineDashPattern() const { return m_lineDashPattern; }
void setLineDashPattern(PDFLineDashPattern pattern);
const QByteArray& getRenderingIntentName() const { return m_renderingIntentName; }
void setRenderingIntentName(const QByteArray& renderingIntentName);
PDFReal getFlatness() const { return m_flatness; }
void setFlatness(PDFReal flatness);
PDFReal getSmoothness() const { return m_smoothness; }
void setSmoothness(PDFReal smoothness);
StateFlags getStateFlags() const { return m_stateFlags; }
void setStateFlags(StateFlags stateFlags) { m_stateFlags = stateFlags; }
PDFReal getTextCharacterSpacing() const { return m_textCharacterSpacing; }
void setTextCharacterSpacing(PDFReal textCharacterSpacing);
PDFReal getTextWordSpacing() const { return m_textWordSpacing; }
void setTextWordSpacing(PDFReal textWordSpacing);
PDFReal getTextHorizontalScaling() const { return m_textHorizontalScaling; }
void setTextHorizontalScaling(PDFReal textHorizontalScaling);
PDFReal getTextLeading() const { return m_textLeading; }
void setTextLeading(PDFReal textLeading);
const PDFFontPointer& getTextFont() const { return m_textFont; }
void setTextFont(const PDFFontPointer& textFont);
PDFReal getTextFontSize() const { return m_textFontSize; }
void setTextFontSize(PDFReal textFontSize);
TextRenderingMode getTextRenderingMode() const { return m_textRenderingMode; }
void setTextRenderingMode(TextRenderingMode textRenderingMode);
PDFReal getTextRise() const { return m_textRise; }
void setTextRise(PDFReal textRise);
bool getTextKnockout() const { return m_textKnockout; }
void setTextKnockout(bool textKnockout);
const QTransform& getTextMatrix() const { return m_textMatrix; }
void setTextMatrix(const QTransform& textMatrix);
const QTransform& getTextLineMatrix() const { return m_textLineMatrix; }
void setTextLineMatrix(const QTransform& textLineMatrix);
PDFReal getAlphaStroking() const { return m_alphaStroking; }
void setAlphaStroking(PDFReal alpha);
PDFReal getAlphaFilling() const { return m_alphaFilling; }
void setAlphaFilling(PDFReal alpha);
BlendMode getBlendMode() const { return m_blendMode; }
void setBlendMode(BlendMode mode);
RenderingIntent getRenderingIntent() const { return m_renderingIntent; }
void setRenderingIntent(RenderingIntent renderingIntent);
/// Returns stroke color with alpha channel
QColor getStrokeColorWithAlpha() const;
/// Returns fill color with alpha channel
QColor getFillColorWithAlpha() const;
PDFOverprintMode getOverprintMode() const { return m_overprintMode; }
void setOverprintMode(PDFOverprintMode overprintMode);
bool getAlphaIsShape() const { return m_alphaIsShape; }
void setAlphaIsShape(bool alphaIsShape);
bool getStrokeAdjustment() const;
void setStrokeAdjustment(bool strokeAdjustment);
const PDFDictionary* getSoftMask() const;
void setSoftMask(const PDFDictionary* softMask);
BlackPointCompensationMode getBlackPointCompensationMode() const;
void setBlackPointCompensationMode(BlackPointCompensationMode blackPointCompensationMode);
PDFObject getBlackGenerationFunction() const;
void setBlackGenerationFunction(const PDFObject& blackGenerationFunction);
PDFObject getUndercolorRemovalFunction() const;
void setUndercolorRemovalFunction(const PDFObject& undercolorRemovalFunction);
PDFObject getTransferFunction() const;
void setTransferFunction(const PDFObject& transferFunction);
PDFObject getHalftone() const;
void setHalftone(const PDFObject& halftone);
QPointF getHalftoneOrigin() const;
void setHalftoneOrigin(const QPointF& halftoneOrigin);
private:
QTransform m_currentTransformationMatrix;
PDFColorSpacePointer m_strokeColorSpace;
PDFColorSpacePointer m_fillColorSpace;
QColor m_strokeColor;
PDFColor m_strokeColorOriginal;
QColor m_fillColor;
PDFColor m_fillColorOriginal;
PDFReal m_lineWidth;
Qt::PenCapStyle m_lineCapStyle;
Qt::PenJoinStyle m_lineJoinStyle;
PDFReal m_mitterLimit;
PDFLineDashPattern m_lineDashPattern;
QByteArray m_renderingIntentName;
PDFReal m_flatness;
PDFReal m_smoothness;
PDFReal m_textCharacterSpacing; // T_c
PDFReal m_textWordSpacing; // T_w
PDFReal m_textHorizontalScaling; // T_h, percentage
PDFReal m_textLeading; // T_l
PDFFontPointer m_textFont; // Text font
PDFReal m_textFontSize; // T_fs
TextRenderingMode m_textRenderingMode; // Text rendering mode
PDFReal m_textRise; // T_rise
bool m_textKnockout;
QTransform m_textMatrix;
QTransform m_textLineMatrix;
PDFReal m_alphaStroking;
PDFReal m_alphaFilling;
BlendMode m_blendMode;
RenderingIntent m_renderingIntent;
PDFOverprintMode m_overprintMode;
bool m_alphaIsShape;
bool m_strokeAdjustment;
const PDFDictionary* m_softMask;
BlackPointCompensationMode m_blackPointCompensationMode;
PDFObject m_blackGenerationFunction;
PDFObject m_undercolorRemovalFunction;
PDFObject m_transferFunction;
PDFObject m_halftone;
QPointF m_halftoneOrigin;
StateFlags m_stateFlags;
};
/// Process the contents of the page.
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentProcessor : public PDFRenderErrorReporter
{
@@ -253,6 +499,9 @@ public:
/// Returns true, if page content processing is being cancelled
bool isProcessingCancelled() const;
/// Returns true, if we are in a text processing
bool isTextProcessing() const;
protected:
struct PDFTransparencyGroup
@@ -296,257 +545,21 @@ protected:
friend class PDFPageContentProcessor;
};
struct PDFOverprintMode
{
bool overprintStroking = false;
bool overprintFilling = false;
int overprintMode = 0;
inline bool operator==(const PDFOverprintMode& other) const
{
return std::tie(overprintStroking, overprintFilling, overprintMode) == std::tie(other.overprintStroking, other.overprintFilling, other.overprintMode);
}
inline bool operator!=(const PDFOverprintMode& other) const
{
return !(*this == other);
}
};
/// Represents graphic state of the PDF (holding current graphic state parameters).
/// Please see PDF Reference 1.7, Chapter 4.3 "Graphic State"
class PDFPageContentProcessorState
{
public:
explicit PDFPageContentProcessorState();
~PDFPageContentProcessorState();
PDFPageContentProcessorState(const PDFPageContentProcessorState&) = default;
PDFPageContentProcessorState(PDFPageContentProcessorState&&) = default;
PDFPageContentProcessorState& operator=(PDFPageContentProcessorState&&) = delete;
PDFPageContentProcessorState& operator=(const PDFPageContentProcessorState& other);
enum StateFlag : uint64_t
{
StateUnchanged = 0x0000000000000000,
StateCurrentTransformationMatrix = 0x0000000000000001,
StateStrokeColorSpace = 0x0000000000000002,
StateFillColorSpace = 0x0000000000000004,
StateStrokeColor = 0x0000000000000008,
StateFillColor = 0x0000000000000010,
StateLineWidth = 0x0000000000000020,
StateLineCapStyle = 0x0000000000000040,
StateLineJoinStyle = 0x0000000000000080,
StateMitterLimit = 0x0000000000000100,
StateLineDashPattern = 0x0000000000000200,
StateRenderingIntentName = 0x0000000000000400,
StateFlatness = 0x0000000000000800,
StateSmoothness = 0x0000000000001000,
StateTextMatrix = 0x0000000000002000,
StateTextLineMatrix = 0x0000000000004000,
StateTextCharacterSpacing = 0x0000000000008000,
StateTextWordSpacing = 0x0000000000010000,
StateTextHorizontalScaling = 0x0000000000020000,
StateTextLeading = 0x0000000000040000,
StateTextFont = 0x0000000000080000,
StateTextFontSize = 0x0000000000100000,
StateTextRenderingMode = 0x0000000000200000,
StateTextRise = 0x0000000000400000,
StateTextKnockout = 0x0000000000800000,
StateAlphaStroking = 0x0000000001000000,
StateAlphaFilling = 0x0000000002000000,
StateBlendMode = 0x0000000004000000,
StateRenderingIntent = 0x0000000008000000,
StateOverprint = 0x0000000010000000,
StateAlphaIsShape = 0x0000000020000000,
StateStrokeAdjustment = 0x0000000040000000,
StateSoftMask = 0x0000000080000000,
StateBlackPointCompensation = 0x0000000100000000,
StateBlackGenerationFunction = 0x0000000200000000,
StateUndercolorRemovalFunction = 0x0000000400000000,
StateTransferFunction = 0x0000000800000000,
StateHalftone = 0x0000001000000000,
StateHalftoneOrigin = 0x0000002000000000,
StateAll = 0xFFFFFFFFFFFFFFFF
};
using StateFlags = PDFFlags<StateFlag>;
const QTransform& getCurrentTransformationMatrix() const { return m_currentTransformationMatrix; }
void setCurrentTransformationMatrix(const QTransform& currentTransformationMatrix);
const PDFAbstractColorSpace* getStrokeColorSpace() const { return m_strokeColorSpace.data(); }
void setStrokeColorSpace(const QSharedPointer<PDFAbstractColorSpace>& strokeColorSpace);
const PDFAbstractColorSpace* getFillColorSpace() const { return m_fillColorSpace.data(); }
void setFillColorSpace(const QSharedPointer<PDFAbstractColorSpace>& fillColorSpace);
const QColor& getStrokeColor() const { return m_strokeColor; }
const PDFColor& getStrokeColorOriginal() const { return m_strokeColorOriginal; }
void setStrokeColor(const QColor& strokeColor, const PDFColor& originalColor);
const QColor& getFillColor() const { return m_fillColor; }
const PDFColor& getFillColorOriginal() const { return m_fillColorOriginal; }
void setFillColor(const QColor& fillColor, const PDFColor& originalColor);
PDFReal getLineWidth() const { return m_lineWidth; }
void setLineWidth(PDFReal lineWidth);
Qt::PenCapStyle getLineCapStyle() const { return m_lineCapStyle; }
void setLineCapStyle(Qt::PenCapStyle lineCapStyle);
Qt::PenJoinStyle getLineJoinStyle() const { return m_lineJoinStyle; }
void setLineJoinStyle(Qt::PenJoinStyle lineJoinStyle);
PDFReal getMitterLimit() const { return m_mitterLimit; }
void setMitterLimit(PDFReal mitterLimit);
const PDFLineDashPattern& getLineDashPattern() const { return m_lineDashPattern; }
void setLineDashPattern(PDFLineDashPattern pattern);
const QByteArray& getRenderingIntentName() const { return m_renderingIntentName; }
void setRenderingIntentName(const QByteArray& renderingIntentName);
PDFReal getFlatness() const { return m_flatness; }
void setFlatness(PDFReal flatness);
PDFReal getSmoothness() const { return m_smoothness; }
void setSmoothness(PDFReal smoothness);
StateFlags getStateFlags() const { return m_stateFlags; }
void setStateFlags(StateFlags stateFlags) { m_stateFlags = stateFlags; }
PDFReal getTextCharacterSpacing() const { return m_textCharacterSpacing; }
void setTextCharacterSpacing(PDFReal textCharacterSpacing);
PDFReal getTextWordSpacing() const { return m_textWordSpacing; }
void setTextWordSpacing(PDFReal textWordSpacing);
PDFReal getTextHorizontalScaling() const { return m_textHorizontalScaling; }
void setTextHorizontalScaling(PDFReal textHorizontalScaling);
PDFReal getTextLeading() const { return m_textLeading; }
void setTextLeading(PDFReal textLeading);
const PDFFontPointer& getTextFont() const { return m_textFont; }
void setTextFont(const PDFFontPointer& textFont);
PDFReal getTextFontSize() const { return m_textFontSize; }
void setTextFontSize(PDFReal textFontSize);
TextRenderingMode getTextRenderingMode() const { return m_textRenderingMode; }
void setTextRenderingMode(TextRenderingMode textRenderingMode);
PDFReal getTextRise() const { return m_textRise; }
void setTextRise(PDFReal textRise);
bool getTextKnockout() const { return m_textKnockout; }
void setTextKnockout(bool textKnockout);
const QTransform& getTextMatrix() const { return m_textMatrix; }
void setTextMatrix(const QTransform& textMatrix);
const QTransform& getTextLineMatrix() const { return m_textLineMatrix; }
void setTextLineMatrix(const QTransform& textLineMatrix);
PDFReal getAlphaStroking() const { return m_alphaStroking; }
void setAlphaStroking(PDFReal alpha);
PDFReal getAlphaFilling() const { return m_alphaFilling; }
void setAlphaFilling(PDFReal alpha);
BlendMode getBlendMode() const { return m_blendMode; }
void setBlendMode(BlendMode mode);
RenderingIntent getRenderingIntent() const { return m_renderingIntent; }
void setRenderingIntent(RenderingIntent renderingIntent);
/// Returns stroke color with alpha channel
QColor getStrokeColorWithAlpha() const;
/// Returns fill color with alpha channel
QColor getFillColorWithAlpha() const;
PDFOverprintMode getOverprintMode() const { return m_overprintMode; }
void setOverprintMode(PDFOverprintMode overprintMode);
bool getAlphaIsShape() const { return m_alphaIsShape; }
void setAlphaIsShape(bool alphaIsShape);
bool getStrokeAdjustment() const;
void setStrokeAdjustment(bool strokeAdjustment);
const PDFDictionary* getSoftMask() const;
void setSoftMask(const PDFDictionary* softMask);
BlackPointCompensationMode getBlackPointCompensationMode() const;
void setBlackPointCompensationMode(BlackPointCompensationMode blackPointCompensationMode);
PDFObject getBlackGenerationFunction() const;
void setBlackGenerationFunction(const PDFObject& blackGenerationFunction);
PDFObject getUndercolorRemovalFunction() const;
void setUndercolorRemovalFunction(const PDFObject& undercolorRemovalFunction);
PDFObject getTransferFunction() const;
void setTransferFunction(const PDFObject& transferFunction);
PDFObject getHalftone() const;
void setHalftone(const PDFObject& halftone);
QPointF getHalftoneOrigin() const;
void setHalftoneOrigin(const QPointF& halftoneOrigin);
private:
QTransform m_currentTransformationMatrix;
PDFColorSpacePointer m_strokeColorSpace;
PDFColorSpacePointer m_fillColorSpace;
QColor m_strokeColor;
PDFColor m_strokeColorOriginal;
QColor m_fillColor;
PDFColor m_fillColorOriginal;
PDFReal m_lineWidth;
Qt::PenCapStyle m_lineCapStyle;
Qt::PenJoinStyle m_lineJoinStyle;
PDFReal m_mitterLimit;
PDFLineDashPattern m_lineDashPattern;
QByteArray m_renderingIntentName;
PDFReal m_flatness;
PDFReal m_smoothness;
PDFReal m_textCharacterSpacing; // T_c
PDFReal m_textWordSpacing; // T_w
PDFReal m_textHorizontalScaling; // T_h, percentage
PDFReal m_textLeading; // T_l
PDFFontPointer m_textFont; // Text font
PDFReal m_textFontSize; // T_fs
TextRenderingMode m_textRenderingMode; // Text rendering mode
PDFReal m_textRise; // T_rise
bool m_textKnockout;
QTransform m_textMatrix;
QTransform m_textLineMatrix;
PDFReal m_alphaStroking;
PDFReal m_alphaFilling;
BlendMode m_blendMode;
RenderingIntent m_renderingIntent;
PDFOverprintMode m_overprintMode;
bool m_alphaIsShape;
bool m_strokeAdjustment;
const PDFDictionary* m_softMask;
BlackPointCompensationMode m_blackPointCompensationMode;
PDFObject m_blackGenerationFunction;
PDFObject m_undercolorRemovalFunction;
PDFObject m_transferFunction;
PDFObject m_halftone;
QPointF m_halftoneOrigin;
StateFlags m_stateFlags;
};
enum class ProcessOrder
{
BeforeOperation,
AfterOperation
};
/// This function is used, when we directly want to intercept content
/// stream instructions and operands.
/// \param currentOperator Current operator
/// \param processOrder Mark before/after instruction is executed
/// \param operatorAsText Operator converted to text
virtual void performInterceptInstruction(Operator currentOperator,
ProcessOrder processOrder,
const QByteArray& operatorAsText);
/// This function has to be implemented in the client drawing implementation, it should
/// draw the path according to the parameters.
/// \param path Path, which should be drawn (can be emtpy - in that case nothing happens)
@@ -575,8 +588,9 @@ protected:
/// original image, it should return true, so no conversion to QImage occurs,
/// which can be performance bottleneck.
/// \param image Image
/// \param stream Stream, from which image originated
/// \returns true, if image is successfully processed
virtual bool performOriginalImagePainting(const PDFImage& image);
virtual bool performOriginalImagePainting(const PDFImage& image, const PDFStream* stream);
/// This function has to be implemented in the client drawing implementation, it should
/// draw the image.
@@ -645,6 +659,9 @@ protected:
/// Implement to respond to text end operator
virtual void performTextEnd(ProcessOrder order);
/// Implement to respond to text sequence processing
virtual void performProcessTextSequence(const TextSequence& textSequence, ProcessOrder order);
enum class ContentKind
{
Shapes, ///< General shapes (they can be also shaded / tiled)
@@ -652,6 +669,7 @@ protected:
Images, ///< Images
Shading, ///< Shading
Tiling, ///< Tiling
Forms, ///< Forms
};
/// Override this function to disable particular content type (for example
@@ -706,6 +724,9 @@ protected:
/// Returns optional content activity
const PDFOptionalContentActivity* getOptionalContentActivity() const { return m_optionalContentActivity; }
/// Returns operand for current operator
const PDFFlatArray<PDFLexicalAnalyzer::Token, 33>& getOperands() const { return m_operands; }
class PDF4QTLIBCORESHARED_EXPORT PDFTransparencyGroupGuard
{
public:
@@ -857,8 +878,6 @@ private:
template<typename... Operands>
inline QColor getColorFromColorSpace(const PDFAbstractColorSpace* colorSpace, Operands... operands)
{
constexpr const size_t operandCount = sizeof...(Operands);
const size_t colorSpaceComponentCount = colorSpace->getColorComponentCount();
if (operandCount == colorSpaceComponentCount)

View File

@@ -2615,8 +2615,10 @@ void PDFTransparencyRenderer::performTextEnd(ProcessOrder order)
}
}
bool PDFTransparencyRenderer::performOriginalImagePainting(const PDFImage& image)
bool PDFTransparencyRenderer::performOriginalImagePainting(const PDFImage& image, const PDFStream* stream)
{
Q_UNUSED(stream);
PDFFloatBitmap texture = getImage(image);
if (m_settings.flags.testFlag(PDFTransparencyRendererSettings::SmoothImageTransformation) && image.isInterpolated())

View File

@@ -703,7 +703,7 @@ public:
virtual void performEndTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup) override;
virtual void performTextBegin(ProcessOrder order) override;
virtual void performTextEnd(ProcessOrder order) override;
virtual bool performOriginalImagePainting(const PDFImage& image) override;
virtual bool performOriginalImagePainting(const PDFImage& image, const PDFStream* stream) override;
virtual void performImagePainting(const QImage& image) override;
virtual void performMeshPainting(const PDFMesh& mesh) override;