mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-02-26 16:37:46 +01:00
Blend functions
This commit is contained in:
parent
ccb84401db
commit
d3827cfcc4
@ -17,6 +17,8 @@
|
||||
|
||||
#include "pdfblendfunction.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
@ -197,4 +199,227 @@ std::vector<BlendMode> PDFBlendModeInfo::getBlendModes()
|
||||
};
|
||||
}
|
||||
|
||||
PDFColorComponent PDFBlendFunction::blend(BlendMode mode, PDFColorComponent Cb, PDFColorComponent Cs)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case BlendMode::Normal:
|
||||
case BlendMode::Compatible:
|
||||
return Cs;
|
||||
|
||||
case BlendMode::Multiply:
|
||||
return Cb * Cs;
|
||||
|
||||
case BlendMode::Screen:
|
||||
return Cb + Cs - Cb * Cs;
|
||||
|
||||
case BlendMode::Overlay:
|
||||
return blend(BlendMode::HardLight, Cs, Cb);
|
||||
|
||||
case BlendMode::Darken:
|
||||
return qMin(Cb, Cs);
|
||||
|
||||
case BlendMode::Lighten:
|
||||
return qMax(Cb, Cs);
|
||||
|
||||
case BlendMode::ColorDodge:
|
||||
{
|
||||
if (qFuzzyIsNull(Cb))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const PDFColorComponent CsInverted = 1.0f - Cs;
|
||||
if (Cb >= CsInverted)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
return Cb / CsInverted;
|
||||
}
|
||||
|
||||
case BlendMode::ColorBurn:
|
||||
{
|
||||
const PDFColorComponent CbInverted = 1.0f - Cb;
|
||||
if (qFuzzyIsNull(CbInverted))
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if (CbInverted >= Cs)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f - CbInverted / Cs;
|
||||
}
|
||||
|
||||
case BlendMode::HardLight:
|
||||
{
|
||||
if (Cs <= 0.5f)
|
||||
{
|
||||
return blend(BlendMode::Multiply, Cb, 2.0f * Cs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return blend(BlendMode::Screen, Cb, 2.0f * Cs - 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
case BlendMode::SoftLight:
|
||||
{
|
||||
if (Cs <= 0.5f)
|
||||
{
|
||||
return Cb - (1.0f - 2.0f * Cs) * Cb * (1.0f - Cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
PDFColorComponent D = 0.0f;
|
||||
if (Cb <= 0.25)
|
||||
{
|
||||
D = ((16.0f * Cb - 12.0f) * Cb + 4.0f) * Cb;
|
||||
}
|
||||
else
|
||||
{
|
||||
D = std::sqrt(Cb);
|
||||
}
|
||||
return Cb + (2.0f * Cs - 1.0f) * (D - Cb);
|
||||
}
|
||||
}
|
||||
|
||||
case BlendMode::Difference:
|
||||
return qAbs(Cb - Cs);
|
||||
|
||||
case BlendMode::Exclusion:
|
||||
return Cb + Cs - 2.0f * Cb * Cs;
|
||||
|
||||
default:
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Cs;
|
||||
}
|
||||
|
||||
PDFRGB PDFBlendFunction::blend_Hue(PDFRGB Cb, PDFRGB Cs)
|
||||
{
|
||||
return nonseparable_SetLum(nonseparable_SetSat(Cs, nonseparable_Sat(Cb)), nonseparable_Lum(Cb));
|
||||
}
|
||||
|
||||
PDFRGB PDFBlendFunction::blend_Saturation(PDFRGB Cb, PDFRGB Cs)
|
||||
{
|
||||
return nonseparable_SetLum(nonseparable_SetSat(Cb, nonseparable_Sat(Cs)), nonseparable_Lum(Cb));
|
||||
}
|
||||
|
||||
PDFRGB PDFBlendFunction::blend_Color(PDFRGB Cb, PDFRGB Cs)
|
||||
{
|
||||
return nonseparable_SetLum(Cs, nonseparable_Lum(Cb));
|
||||
}
|
||||
|
||||
PDFRGB PDFBlendFunction::blend_Luminosity(PDFRGB Cb, PDFRGB Cs)
|
||||
{
|
||||
return nonseparable_SetLum(Cb, nonseparable_Lum(Cs));
|
||||
}
|
||||
|
||||
PDFRGB PDFBlendFunction::nonseparable_gray2rgb(PDFGray gray)
|
||||
{
|
||||
return PDFRGB{ gray, gray, gray };
|
||||
}
|
||||
|
||||
PDFGray PDFBlendFunction::nonseparable_rgb2gray(PDFRGB rgb)
|
||||
{
|
||||
// Just convert to luminosity
|
||||
return nonseparable_Lum(rgb);
|
||||
}
|
||||
|
||||
PDFRGB PDFBlendFunction::nonseparable_cmyk2rgb(PDFCMYK cmyk)
|
||||
{
|
||||
return PDFRGB{ 1.0f - cmyk[0], 1.0f - cmyk[1], 1.0f - cmyk[2] };
|
||||
}
|
||||
|
||||
PDFCMYK PDFBlendFunction::nonseparable_rgb2cmyk(PDFRGB rgb, PDFColorComponent K)
|
||||
{
|
||||
return PDFCMYK{ 1.0f - rgb[0], 1.0f - rgb[1], 1.0f - rgb[2], K };
|
||||
}
|
||||
|
||||
PDFColorComponent PDFBlendFunction::nonseparable_Lum(PDFRGB rgb)
|
||||
{
|
||||
return 0.30 * rgb[0] + 0.59 * rgb[1] + 0.11 * rgb[2];
|
||||
}
|
||||
|
||||
PDFColorComponent PDFBlendFunction::nonseparable_Sat(PDFRGB rgb)
|
||||
{
|
||||
const PDFColorComponent min = *std::min_element(rgb.cbegin(), rgb.cend());
|
||||
const PDFColorComponent max = *std::max_element(rgb.cbegin(), rgb.cend());
|
||||
return max - min;
|
||||
}
|
||||
|
||||
PDFRGB PDFBlendFunction::nonseparable_SetLum(PDFRGB C, PDFColorComponent l)
|
||||
{
|
||||
const PDFColorComponent d = l - nonseparable_Lum(C);
|
||||
PDFRGB result = C;
|
||||
result[0] += d;
|
||||
result[1] += d;
|
||||
result[2] += d;
|
||||
return nonseparable_ClipColor(result);
|
||||
}
|
||||
|
||||
PDFRGB PDFBlendFunction::nonseparable_SetSat(PDFRGB C, PDFColorComponent s)
|
||||
{
|
||||
auto it_min = std::min_element(C.begin(), C.end());
|
||||
auto it_max = std::max_element(C.begin(), C.end());
|
||||
auto it_mid = C.end();
|
||||
for (auto it = C.begin(); it != C.end(); ++it)
|
||||
{
|
||||
if (it != it_min && it != it_max)
|
||||
{
|
||||
it_mid = it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Q_ASSERT(it_mid != C.end());
|
||||
|
||||
PDFRGB result = C;
|
||||
if (*it_max > *it_min)
|
||||
{
|
||||
*it_mid = (*it_mid - *it_min) * s / (*it_max - *it_min);
|
||||
*it_max = s;
|
||||
result = C;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fill(result.begin(), result.end(), 0.0f);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFRGB PDFBlendFunction::nonseparable_ClipColor(PDFRGB C)
|
||||
{
|
||||
PDFRGB result = C;
|
||||
const PDFColorComponent l = nonseparable_Lum(C);
|
||||
const PDFColorComponent n = *std::min_element(C.cbegin(), C.cend());
|
||||
const PDFColorComponent x = *std::max_element(C.cbegin(), C.cend());
|
||||
|
||||
if (n < 0.0f)
|
||||
{
|
||||
const PDFColorComponent factor = 1.0f / (l - n);
|
||||
result[0] = l + (result[0] - l) * l * factor;
|
||||
result[1] = l + (result[1] - l) * l * factor;
|
||||
result[2] = l + (result[2] - l) * l * factor;
|
||||
}
|
||||
|
||||
if (x > 1.0f)
|
||||
{
|
||||
const PDFColorComponent factor = 1.0f / (x - l);
|
||||
result[0] = l + (result[0] - l) * (1.0f - l) * factor;
|
||||
result[1] = l + (result[1] - l) * (1.0f - l) * factor;
|
||||
result[2] = l + (result[2] - l) * (1.0f - l) * factor;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -88,6 +88,50 @@ public:
|
||||
static std::vector<BlendMode> getBlendModes();
|
||||
};
|
||||
|
||||
/// Class grouping together blend functions. Can also blend non-separable blend modes,
|
||||
/// such as Color, Hue, Saturation and Luminosity, according 11.3.5.3 of PDF 2.0 specification.
|
||||
class PDFBlendFunction
|
||||
{
|
||||
public:
|
||||
PDFBlendFunction() = delete;
|
||||
|
||||
/// Blend function used to blend separable blend modes
|
||||
/// \param Cb Backdrop color
|
||||
/// \param Cs Source color
|
||||
static PDFColorComponent blend(BlendMode mode, PDFColorComponent Cb, PDFColorComponent Cs);
|
||||
|
||||
/// Blend non-separable hue function
|
||||
/// \param Cb Backdrop color
|
||||
/// \param Cs Source color
|
||||
static PDFRGB blend_Hue(PDFRGB Cb, PDFRGB Cs);
|
||||
|
||||
/// Blend non-separable saturation function
|
||||
/// \param Cb Backdrop color
|
||||
/// \param Cs Source color
|
||||
static PDFRGB blend_Saturation(PDFRGB Cb, PDFRGB Cs);
|
||||
|
||||
/// Blend non-separable color function
|
||||
/// \param Cb Backdrop color
|
||||
/// \param Cs Source color
|
||||
static PDFRGB blend_Color(PDFRGB Cb, PDFRGB Cs);
|
||||
|
||||
/// Blend non-separable luminosity function
|
||||
/// \param Cb Backdrop color
|
||||
/// \param Cs Source color
|
||||
static PDFRGB blend_Luminosity(PDFRGB Cb, PDFRGB Cs);
|
||||
|
||||
private:
|
||||
static PDFRGB nonseparable_gray2rgb(PDFGray gray);
|
||||
static PDFGray nonseparable_rgb2gray(PDFRGB rgb);
|
||||
static PDFRGB nonseparable_cmyk2rgb(PDFCMYK cmyk);
|
||||
static PDFCMYK nonseparable_rgb2cmyk(PDFRGB rgb, PDFColorComponent K);
|
||||
static PDFColorComponent nonseparable_Lum(PDFRGB rgb);
|
||||
static PDFColorComponent nonseparable_Sat(PDFRGB rgb);
|
||||
static PDFRGB nonseparable_SetLum(PDFRGB C, PDFColorComponent l);
|
||||
static PDFRGB nonseparable_SetSat(PDFRGB C, PDFColorComponent s);
|
||||
static PDFRGB nonseparable_ClipColor(PDFRGB C);
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
#endif // PDFBLENDFUNCTION_H
|
||||
|
@ -41,7 +41,6 @@ class PDFAbstractColorSpace;
|
||||
class PDFPatternColorSpace;
|
||||
class PDFRenderErrorReporter;
|
||||
|
||||
using PDFColorComponent = float;
|
||||
using PDFColor = PDFFlatArray<PDFColorComponent, 4>;
|
||||
using PDFColorSpacePointer = QSharedPointer<PDFAbstractColorSpace>;
|
||||
using PDFColorBuffer = PDFBuffer<PDFColorComponent>;
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
#include <array>
|
||||
|
||||
#if defined(Pdf4QtLIB_LIBRARY)
|
||||
# define Pdf4QtLIBSHARED_EXPORT Q_DECL_EXPORT
|
||||
@ -36,6 +37,10 @@ namespace pdf
|
||||
|
||||
using PDFInteger = int64_t;
|
||||
using PDFReal = double;
|
||||
using PDFColorComponent = float;
|
||||
using PDFGray = PDFColorComponent;
|
||||
using PDFRGB = std::array<PDFColorComponent, 3>;
|
||||
using PDFCMYK = std::array<PDFColorComponent, 4>;
|
||||
|
||||
// These constants define minimum/maximum integer and are defined in such a way,
|
||||
// that even 100 times bigger integers are representable.
|
||||
|
@ -455,6 +455,32 @@ bool PDFPageContentProcessor::isContentSuppressed() const
|
||||
return std::any_of(m_markedContentStack.cbegin(), m_markedContentStack.cend(), [](const MarkedContentState& state) { return state.contentSuppressed; });
|
||||
}
|
||||
|
||||
PDFPageContentProcessor::PDFTransparencyGroup PDFPageContentProcessor::parseTransparencyGroup(const PDFObject& object)
|
||||
{
|
||||
PDFTransparencyGroup group;
|
||||
|
||||
if (const PDFDictionary* transparencyDictionary = m_document->getDictionaryFromObject(object))
|
||||
{
|
||||
const PDFObject& colorSpaceObject = m_document->getObject(transparencyDictionary->get("CS"));
|
||||
if (!colorSpaceObject.isNull())
|
||||
{
|
||||
group.colorSpacePointer = PDFAbstractColorSpace::createColorSpace(m_colorSpaceDictionary, m_document, colorSpaceObject);
|
||||
|
||||
if (group.colorSpacePointer && !group.colorSpacePointer->isBlendColorSpace())
|
||||
{
|
||||
reportRenderError(RenderErrorType::Error, PDFTranslationContext::tr("Transparency group blending color space is invalid."));
|
||||
group.colorSpacePointer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(m_document);
|
||||
group.isolated = loader.readBooleanFromDictionary(transparencyDictionary, "I", false);
|
||||
group.knockout = loader.readBooleanFromDictionary(transparencyDictionary, "K", false);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::processContent(const QByteArray& content)
|
||||
{
|
||||
PDFLexicalAnalyzer parser(content.constBegin(), content.constEnd());
|
||||
|
@ -607,6 +607,25 @@ protected:
|
||||
/// only for compatibility purposes. See chapter 14.2 in PDF 2.0 specification.
|
||||
ProcedureSets getProcedureSets() const { return m_procedureSets; }
|
||||
|
||||
/// Returns page
|
||||
const PDFPage* getPage() const { return m_page; }
|
||||
|
||||
/// Returns document
|
||||
const PDFDocument* getDocument() const { return m_document; }
|
||||
|
||||
/// Parses transparency group
|
||||
PDFTransparencyGroup parseTransparencyGroup(const PDFObject& object);
|
||||
|
||||
class PDFTransparencyGroupGuard
|
||||
{
|
||||
public:
|
||||
explicit PDFTransparencyGroupGuard(PDFPageContentProcessor* processor, PDFTransparencyGroup&& group);
|
||||
~PDFTransparencyGroupGuard();
|
||||
|
||||
private:
|
||||
PDFPageContentProcessor* m_processor;
|
||||
};
|
||||
|
||||
private:
|
||||
/// Initializes the resources dictionaries
|
||||
void initDictionaries(const PDFObject& resourcesObject);
|
||||
@ -701,16 +720,6 @@ private:
|
||||
PDFPageContentProcessor* m_processor;
|
||||
};
|
||||
|
||||
class PDFTransparencyGroupGuard
|
||||
{
|
||||
public:
|
||||
explicit PDFTransparencyGroupGuard(PDFPageContentProcessor* processor, PDFTransparencyGroup&& group);
|
||||
~PDFTransparencyGroupGuard();
|
||||
|
||||
private:
|
||||
PDFPageContentProcessor* m_processor;
|
||||
};
|
||||
|
||||
/// Wrapper for PDF Name
|
||||
struct PDFOperandName
|
||||
{
|
||||
|
@ -16,6 +16,7 @@
|
||||
// along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdftransparencyrenderer.h"
|
||||
#include "pdfdocument.h"
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
@ -41,7 +42,8 @@ PDFFloatBitmap::PDFFloatBitmap(size_t width, size_t height, PDFPixelFormat forma
|
||||
|
||||
PDFColorBuffer PDFFloatBitmap::getPixel(size_t x, size_t y)
|
||||
{
|
||||
s
|
||||
const size_t index = getPixelIndex(x, y);
|
||||
return PDFColorBuffer(m_data.data() + index, m_pixelSize);
|
||||
}
|
||||
|
||||
const PDFColorComponent* PDFFloatBitmap::begin() const
|
||||
@ -64,9 +66,78 @@ PDFColorComponent* PDFFloatBitmap::end()
|
||||
return m_data.data() + m_data.size();
|
||||
}
|
||||
|
||||
PDFTransparencyRenderer::PDFTransparencyRenderer()
|
||||
size_t PDFFloatBitmap::getPixelIndex(size_t x, size_t y) const
|
||||
{
|
||||
return (y * m_width + x) * m_pixelSize;
|
||||
}
|
||||
|
||||
PDFTransparencyRenderer::PDFTransparencyRenderer(const PDFPage* page,
|
||||
const PDFDocument* document,
|
||||
const PDFFontCache* fontCache,
|
||||
const PDFCMS* cms,
|
||||
const PDFOptionalContentActivity* optionalContentActivity,
|
||||
QMatrix pagePointToDevicePointMatrix) :
|
||||
BaseClass(page, document, fontCache, cms, optionalContentActivity, pagePointToDevicePointMatrix, PDFMeshQualitySettings()),
|
||||
m_active(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PDFTransparencyRenderer::setDeviceColorSpace(PDFColorSpacePointer colorSpace)
|
||||
{
|
||||
if (!colorSpace || colorSpace->isBlendColorSpace())
|
||||
{
|
||||
// Set device color space only, when it is a blend color space
|
||||
m_deviceColorSpace = colorSpace;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFTransparencyRenderer::beginPaint()
|
||||
{
|
||||
Q_ASSERT(!m_active);
|
||||
m_active = true;
|
||||
|
||||
// Create page transparency group
|
||||
PDFObject pageTransparencyGroupObject = getPage()->getTransparencyGroup(&getDocument()->getStorage());
|
||||
PDFTransparencyGroup transparencyGroup = parseTransparencyGroup(pageTransparencyGroupObject);
|
||||
transparencyGroup.isolated = true;
|
||||
|
||||
m_pageTransparencyGroupGuard.reset(new PDFTransparencyGroupGuard(this, qMove(transparencyGroup)));
|
||||
}
|
||||
|
||||
const PDFFloatBitmap& PDFTransparencyRenderer::endPaint()
|
||||
{
|
||||
Q_ASSERT(m_active);
|
||||
m_pageTransparencyGroupGuard.reset();
|
||||
m_active = false;
|
||||
}
|
||||
|
||||
void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule)
|
||||
{
|
||||
}
|
||||
|
||||
void PDFTransparencyRenderer::performClipping(const QPainterPath& path, Qt::FillRule fillRule)
|
||||
{
|
||||
}
|
||||
|
||||
void PDFTransparencyRenderer::performUpdateGraphicsState(const PDFPageContentProcessorState& state)
|
||||
{
|
||||
}
|
||||
|
||||
void PDFTransparencyRenderer::performSaveGraphicState(ProcessOrder order)
|
||||
{
|
||||
}
|
||||
|
||||
void PDFTransparencyRenderer::performRestoreGraphicState(ProcessOrder order)
|
||||
{
|
||||
}
|
||||
|
||||
void PDFTransparencyRenderer::performBeginTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup)
|
||||
{
|
||||
}
|
||||
|
||||
void PDFTransparencyRenderer::performEndTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "pdfglobal.h"
|
||||
#include "pdfcolorspaces.h"
|
||||
#include "pdfpagecontentprocessor.h"
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
@ -36,7 +37,7 @@ class PDFPixelFormat
|
||||
public:
|
||||
inline explicit constexpr PDFPixelFormat() = default;
|
||||
|
||||
constexpr uint8_t INVALID_CHANNEL_INDEX = 0xFF;
|
||||
constexpr static uint8_t INVALID_CHANNEL_INDEX = 0xFF;
|
||||
|
||||
constexpr bool hasProcessColors() const { return m_processColors > 0; }
|
||||
constexpr bool hasSpotColors() const { return m_spotColors > 0; }
|
||||
@ -96,9 +97,9 @@ private:
|
||||
|
||||
}
|
||||
|
||||
constexpr uint8_t FLAG_HAS_SHAPE_CHANNEL = 0x01;
|
||||
constexpr uint8_t FLAG_HAS_OPACITY_CHANNEL = 0x02;
|
||||
constexpr uint8_t FLAG_PROCESS_COLORS_SUBTRACTIVE = 0x04;
|
||||
constexpr static uint8_t FLAG_HAS_SHAPE_CHANNEL = 0x01;
|
||||
constexpr static uint8_t FLAG_HAS_OPACITY_CHANNEL = 0x02;
|
||||
constexpr static uint8_t FLAG_PROCESS_COLORS_SUBTRACTIVE = 0x04;
|
||||
|
||||
uint8_t m_processColors = 0;
|
||||
uint8_t m_spotColors = 0;
|
||||
@ -113,7 +114,7 @@ public:
|
||||
explicit PDFFloatBitmap();
|
||||
explicit PDFFloatBitmap(size_t width, size_t height, PDFPixelFormat format);
|
||||
|
||||
/// Returns buffer with pixel
|
||||
/// Returns buffer with pixel channels
|
||||
PDFColorBuffer getPixel(size_t x, size_t y);
|
||||
|
||||
const PDFColorComponent* begin() const;
|
||||
@ -135,10 +136,62 @@ private:
|
||||
std::vector<PDFColorComponent> m_data;
|
||||
};
|
||||
|
||||
class PDFTransparencyRenderer
|
||||
/// Renders PDF pages with transparency, using 32-bit floating point precision.
|
||||
/// Both device color space and blending color space can be defined. It implements
|
||||
/// page blending space and device blending space. So, painted graphics is being
|
||||
/// blended to the page blending space, and then converted to the device blending
|
||||
/// space.
|
||||
class PDFTransparencyRenderer : public PDFPageContentProcessor
|
||||
{
|
||||
private:
|
||||
using BaseClass = PDFPageContentProcessor;
|
||||
|
||||
public:
|
||||
PDFTransparencyRenderer();
|
||||
PDFTransparencyRenderer(const PDFPage* page,
|
||||
const PDFDocument* document,
|
||||
const PDFFontCache* fontCache,
|
||||
const PDFCMS* cms,
|
||||
const PDFOptionalContentActivity* optionalContentActivity,
|
||||
QMatrix pagePointToDevicePointMatrix);
|
||||
|
||||
void setDeviceColorSpace(PDFColorSpacePointer colorSpace);
|
||||
|
||||
/// Starts painting on the device. This function must be called before page
|
||||
/// content stream is being processed (and must be called exactly once).
|
||||
void beginPaint();
|
||||
|
||||
/// Finishes painting on the device. This function must be called after page
|
||||
/// content stream is processed and all result graphics is being drawn. Page
|
||||
/// transparency group collapses nad contents are draw onto device transparency
|
||||
/// group.
|
||||
const PDFFloatBitmap& endPaint();
|
||||
|
||||
virtual void performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule) override;
|
||||
virtual void performClipping(const QPainterPath& path, Qt::FillRule fillRule) override;
|
||||
virtual void performUpdateGraphicsState(const PDFPageContentProcessorState& state) override;
|
||||
virtual void performSaveGraphicState(ProcessOrder order) override;
|
||||
virtual void performRestoreGraphicState(ProcessOrder order) override;
|
||||
virtual void performBeginTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup) override;
|
||||
virtual void performEndTransparencyGroup(ProcessOrder order, const PDFTransparencyGroup& transparencyGroup) override;
|
||||
|
||||
private:
|
||||
|
||||
struct PDFTransparencyGroupPainterData
|
||||
{
|
||||
PDFTransparencyGroup group;
|
||||
bool alphaIsShape = false;
|
||||
PDFReal alphaStroke = 1.0;
|
||||
PDFReal alphaFill = 1.0;
|
||||
BlendMode blendMode = BlendMode::Normal;
|
||||
BlackPointCompensationMode blackPointCompensationMode = BlackPointCompensationMode::Default;
|
||||
RenderingIntent RenderingIntent = RenderingIntent::RelativeColorimetric;
|
||||
};
|
||||
|
||||
PDFColorSpacePointer m_deviceColorSpace; ///< Device color space (color space for final result)
|
||||
PDFColorSpacePointer m_processColorSpace; ///< Process color space (color space, in which is page graphic's blended)
|
||||
std::unique_ptr<PDFTransparencyGroupGuard> m_pageTransparencyGroupGuard;
|
||||
std::vector<PDFTransparencyGroupPainterData> m_transparencyGroupDataStack;
|
||||
bool m_active;
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
Loading…
x
Reference in New Issue
Block a user