Bugfixing: correct handling of optional content

This commit is contained in:
Jakub Melka 2020-01-18 17:53:06 +01:00
parent 1fd01c14fd
commit 7ad4c46124
4 changed files with 52 additions and 18 deletions

View File

@ -516,7 +516,17 @@ PDFOptionalContentMembershipObject PDFOptionalContentMembershipObject::create(co
{
// First, scan all optional content groups
PDFDocumentDataLoaderDecorator loader(document);
std::vector<PDFObjectReference> ocgs = loader.readReferenceArrayFromDictionary(dictionary, "OCGs");
std::vector<PDFObjectReference> ocgs;
PDFObject singleOCG = dictionary->get("OCGs");
if (singleOCG.isReference())
{
ocgs = { singleOCG.getReference() };
}
else
{
ocgs = loader.readReferenceArrayFromDictionary(dictionary, "OCGs");
}
if (!ocgs.empty())
{

View File

@ -2741,29 +2741,29 @@ void PDFPageContentProcessor::operatorPaintXObject(PDFPageContentProcessor::PDFO
if (m_xobjectDictionary)
{
// According to the specification, XObjects are skipped entirely, as no operator was invoked.
if (m_xobjectDictionary->hasKey("OC"))
{
const PDFObject& object = m_xobjectDictionary->get("OC");
if (object.isReference())
{
if (isContentSuppressedByOC(object.getReference()))
{
return;
}
}
else
{
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Reference to optional content expected."));
}
}
const PDFObject& object = m_document->getObject(m_xobjectDictionary->get(name.name));
if (object.isStream())
{
const PDFStream* stream = object.getStream();
const PDFDictionary* streamDictionary = stream->getDictionary();
// According to the specification, XObjects are skipped entirely, as no operator was invoked.
if (streamDictionary->hasKey("OC"))
{
const PDFObject& object = streamDictionary->get("OC");
if (object.isReference())
{
if (isContentSuppressedByOC(object.getReference()))
{
return;
}
}
else
{
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Reference to optional content expected."));
}
}
PDFDocumentDataLoaderDecorator loader(m_document);
QByteArray subtype = loader.readNameFromDictionary(streamDictionary, "Subtype");
if (subtype == "Image")

View File

@ -413,6 +413,27 @@ void PDFPrecompiledPageGenerator::performImagePainting(const QImage& image)
return;
}
if (isTransparencyGroupActive())
{
PDFReal alpha = getEffectiveFillingAlpha();
if (alpha != 1.0)
{
// Try to approximate transparency group using alpha channel
QImage imageWithAlpha = image;
QImage alphaChannel = imageWithAlpha.convertToFormat(QImage::Format_Alpha8);
uchar* bits = alphaChannel.bits();
for (qsizetype i = 0, sizeInBytes = alphaChannel.sizeInBytes(); i < sizeInBytes; ++i)
{
bits[i] *= alpha;
}
imageWithAlpha.setAlphaChannel(alphaChannel);
m_precompiledPage->addImage(imageWithAlpha);
return;
}
}
m_precompiledPage->addImage(image);
}

View File

@ -72,6 +72,9 @@ protected:
/// Returns, if feature is turned on
bool hasFeature(PDFRenderer::Feature feature) const { return m_features.testFlag(feature); }
/// Is transparency group active?
bool isTransparencyGroupActive() const { return !m_transparencyGroupDataStack.empty(); }
private:
/// Returns current pen (implementation)
QPen getCurrentPenImpl() const;