mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-01-30 09:04:48 +01:00
Graphic state operator (gs)
This commit is contained in:
parent
959ed6599b
commit
ffc56d38e1
@ -190,7 +190,7 @@ PDFColorSpacePointer PDFAbstractColorSpace::createDeviceColorSpaceByNameImpl(con
|
|||||||
|
|
||||||
if (name == COLOR_SPACE_NAME_DEVICE_GRAY || name == COLOR_SPACE_NAME_ABBREVIATION_DEVICE_GRAY)
|
if (name == COLOR_SPACE_NAME_DEVICE_GRAY || name == COLOR_SPACE_NAME_ABBREVIATION_DEVICE_GRAY)
|
||||||
{
|
{
|
||||||
if (colorSpaceDictionary->hasKey(COLOR_SPACE_NAME_DEFAULT_GRAY))
|
if (colorSpaceDictionary && colorSpaceDictionary->hasKey(COLOR_SPACE_NAME_DEFAULT_GRAY))
|
||||||
{
|
{
|
||||||
return createColorSpaceImpl(colorSpaceDictionary, document, document->getObject(colorSpaceDictionary->get(COLOR_SPACE_NAME_DEFAULT_GRAY)), recursion);
|
return createColorSpaceImpl(colorSpaceDictionary, document, document->getObject(colorSpaceDictionary->get(COLOR_SPACE_NAME_DEFAULT_GRAY)), recursion);
|
||||||
}
|
}
|
||||||
@ -201,7 +201,7 @@ PDFColorSpacePointer PDFAbstractColorSpace::createDeviceColorSpaceByNameImpl(con
|
|||||||
}
|
}
|
||||||
else if (name == COLOR_SPACE_NAME_DEVICE_RGB || name == COLOR_SPACE_NAME_ABBREVIATION_DEVICE_RGB)
|
else if (name == COLOR_SPACE_NAME_DEVICE_RGB || name == COLOR_SPACE_NAME_ABBREVIATION_DEVICE_RGB)
|
||||||
{
|
{
|
||||||
if (colorSpaceDictionary->hasKey(COLOR_SPACE_NAME_DEFAULT_RGB))
|
if (colorSpaceDictionary && colorSpaceDictionary->hasKey(COLOR_SPACE_NAME_DEFAULT_RGB))
|
||||||
{
|
{
|
||||||
return createColorSpaceImpl(colorSpaceDictionary, document, document->getObject(colorSpaceDictionary->get(COLOR_SPACE_NAME_DEFAULT_RGB)), recursion);
|
return createColorSpaceImpl(colorSpaceDictionary, document, document->getObject(colorSpaceDictionary->get(COLOR_SPACE_NAME_DEFAULT_RGB)), recursion);
|
||||||
}
|
}
|
||||||
@ -212,7 +212,7 @@ PDFColorSpacePointer PDFAbstractColorSpace::createDeviceColorSpaceByNameImpl(con
|
|||||||
}
|
}
|
||||||
else if (name == COLOR_SPACE_NAME_DEVICE_CMYK || name == COLOR_SPACE_NAME_ABBREVIATION_DEVICE_CMYK)
|
else if (name == COLOR_SPACE_NAME_DEVICE_CMYK || name == COLOR_SPACE_NAME_ABBREVIATION_DEVICE_CMYK)
|
||||||
{
|
{
|
||||||
if (colorSpaceDictionary->hasKey(COLOR_SPACE_NAME_DEFAULT_CMYK))
|
if (colorSpaceDictionary && colorSpaceDictionary->hasKey(COLOR_SPACE_NAME_DEFAULT_CMYK))
|
||||||
{
|
{
|
||||||
return createColorSpaceImpl(colorSpaceDictionary, document, document->getObject(colorSpaceDictionary->get(COLOR_SPACE_NAME_DEFAULT_CMYK)), recursion);
|
return createColorSpaceImpl(colorSpaceDictionary, document, document->getObject(colorSpaceDictionary->get(COLOR_SPACE_NAME_DEFAULT_CMYK)), recursion);
|
||||||
}
|
}
|
||||||
|
@ -273,7 +273,7 @@ PDFInteger PDFDocumentDataLoaderDecorator::readInteger(const PDFObject& object,
|
|||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFReal PDFDocumentDataLoaderDecorator::readNumber(const PDFObject& object, PDFInteger defaultValue) const
|
PDFReal PDFDocumentDataLoaderDecorator::readNumber(const PDFObject& object, PDFReal defaultValue) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_document->getObject(object);
|
||||||
|
|
||||||
@ -357,4 +357,32 @@ PDFInteger PDFDocumentDataLoaderDecorator::readIntegerFromDictionary(const PDFDi
|
|||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<PDFReal> PDFDocumentDataLoaderDecorator::readNumberArray(const PDFObject& object) const
|
||||||
|
{
|
||||||
|
const PDFObject& dereferencedObject = m_document->getObject(object);
|
||||||
|
if (dereferencedObject.isArray())
|
||||||
|
{
|
||||||
|
const PDFArray* array = dereferencedObject.getArray();
|
||||||
|
std::vector<PDFReal> result;
|
||||||
|
const size_t count = array->getCount();
|
||||||
|
result.reserve(count);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
const PDFReal number = readNumber(array->getItem(i), std::numeric_limits<PDFReal>::quiet_NaN());
|
||||||
|
if (std::isnan(number))
|
||||||
|
{
|
||||||
|
return std::vector<PDFReal>();
|
||||||
|
}
|
||||||
|
result.push_back(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We assume, that RVO (return value optimization) will not work for this function
|
||||||
|
// (multiple return points).
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::vector<PDFReal>();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -96,7 +96,7 @@ public:
|
|||||||
/// then it is converted to real number.
|
/// then it is converted to real number.
|
||||||
/// \param object Object, can be an indirect reference to object (it is dereferenced)
|
/// \param object Object, can be an indirect reference to object (it is dereferenced)
|
||||||
/// \param defaultValue Default value
|
/// \param defaultValue Default value
|
||||||
PDFReal readNumber(const PDFObject& object, PDFInteger defaultValue) const;
|
PDFReal readNumber(const PDFObject& object, PDFReal defaultValue) const;
|
||||||
|
|
||||||
/// Reads a text string from the object, if it is possible.
|
/// Reads a text string from the object, if it is possible.
|
||||||
/// \param object Object, can be an indirect reference to object (it is dereferenced)
|
/// \param object Object, can be an indirect reference to object (it is dereferenced)
|
||||||
@ -186,6 +186,12 @@ public:
|
|||||||
/// \param defaultValue Default value
|
/// \param defaultValue Default value
|
||||||
PDFInteger readIntegerFromDictionary(const PDFDictionary* dictionary, const char* key, PDFInteger defaultValue) const;
|
PDFInteger readIntegerFromDictionary(const PDFDictionary* dictionary, const char* key, PDFInteger defaultValue) const;
|
||||||
|
|
||||||
|
/// Reads number array from dictionary. Reads all values. If some value is not
|
||||||
|
/// real number (or integer number), empty array is returned. Empty array is also returned,
|
||||||
|
/// if \p object is invalid.
|
||||||
|
/// \param object Object containing array of numbers
|
||||||
|
std::vector<PDFReal> readNumberArray(const PDFObject& object) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const PDFDocument* m_document;
|
const PDFDocument* m_document;
|
||||||
};
|
};
|
||||||
|
@ -656,12 +656,12 @@ void PDFPageContentProcessor::operatorSetLineWidth(PDFReal lineWidth)
|
|||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFPageContentProcessor::operatorSetLineCap(PDFInteger lineCap)
|
Qt::PenCapStyle PDFPageContentProcessor::convertLineCapToPenCapStyle(PDFInteger lineCap)
|
||||||
{
|
{
|
||||||
lineCap = qBound<PDFInteger>(0, lineCap, 2);
|
lineCap = qBound<PDFInteger>(0, lineCap, 2);
|
||||||
|
|
||||||
Qt::PenCapStyle penCapStyle = Qt::FlatCap;
|
Qt::PenCapStyle penCapStyle = Qt::FlatCap;
|
||||||
switch (penCapStyle)
|
switch (lineCap)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
@ -689,16 +689,42 @@ void PDFPageContentProcessor::operatorSetLineCap(PDFInteger lineCap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return penCapStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFInteger PDFPageContentProcessor::convertPenCapStyleToLineCap(Qt::PenCapStyle penCapStyle)
|
||||||
|
{
|
||||||
|
switch (penCapStyle)
|
||||||
|
{
|
||||||
|
case Qt::FlatCap:
|
||||||
|
return 0;
|
||||||
|
case Qt::SquareCap:
|
||||||
|
return 2;
|
||||||
|
case Qt::RoundCap:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalid pen cap style occured
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFPageContentProcessor::operatorSetLineCap(PDFInteger lineCap)
|
||||||
|
{
|
||||||
|
const Qt::PenCapStyle penCapStyle = convertLineCapToPenCapStyle(lineCap);
|
||||||
m_graphicState.setLineCapStyle(penCapStyle);
|
m_graphicState.setLineCapStyle(penCapStyle);
|
||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFPageContentProcessor::operatorSetLineJoin(PDFInteger lineJoin)
|
Qt::PenJoinStyle PDFPageContentProcessor::convertLineJoinToPenJoinStyle(PDFInteger lineJoin)
|
||||||
{
|
{
|
||||||
lineJoin = qBound<PDFInteger>(0, lineJoin, 2);
|
lineJoin = qBound<PDFInteger>(0, lineJoin, 2);
|
||||||
|
|
||||||
Qt::PenJoinStyle penJoinStyle = Qt::MiterJoin;
|
Qt::PenJoinStyle penJoinStyle = Qt::MiterJoin;
|
||||||
switch (penJoinStyle)
|
switch (lineJoin)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
@ -726,6 +752,32 @@ void PDFPageContentProcessor::operatorSetLineJoin(PDFInteger lineJoin)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return penJoinStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFInteger PDFPageContentProcessor::convertPenJoinStyleToLineJoin(Qt::PenJoinStyle penJoinStyle)
|
||||||
|
{
|
||||||
|
switch (penJoinStyle)
|
||||||
|
{
|
||||||
|
case Qt::MiterJoin:
|
||||||
|
return 0;
|
||||||
|
case Qt::BevelJoin:
|
||||||
|
return 2;
|
||||||
|
case Qt::RoundJoin:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalid pen join style occured
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFPageContentProcessor::operatorSetLineJoin(PDFInteger lineJoin)
|
||||||
|
{
|
||||||
|
const Qt::PenJoinStyle penJoinStyle = convertLineJoinToPenJoinStyle(lineJoin);
|
||||||
m_graphicState.setLineJoinStyle(penJoinStyle);
|
m_graphicState.setLineJoinStyle(penJoinStyle);
|
||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
}
|
}
|
||||||
@ -784,6 +836,85 @@ void PDFPageContentProcessor::operatorSetFlatness(PDFReal flatness)
|
|||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFPageContentProcessor::operatorSetGraphicState(PDFName dictionaryName)
|
||||||
|
{
|
||||||
|
const PDFObject& resources = m_page->getResources();
|
||||||
|
if (resources.isDictionary())
|
||||||
|
{
|
||||||
|
const PDFDictionary* resourcesDictionary = resources.getDictionary();
|
||||||
|
if (resourcesDictionary->hasKey(PDF_RESOURCE_EXTGSTATE))
|
||||||
|
{
|
||||||
|
const PDFObject& graphicStatesObject = m_document->getObject(resourcesDictionary->get(PDF_RESOURCE_EXTGSTATE));
|
||||||
|
if (graphicStatesObject.isDictionary())
|
||||||
|
{
|
||||||
|
const PDFDictionary* graphicStatesDictionary = graphicStatesObject.getDictionary();
|
||||||
|
if (graphicStatesDictionary->hasKey(dictionaryName.name))
|
||||||
|
{
|
||||||
|
const PDFObject& graphicStateObject = m_document->getObject(graphicStatesDictionary->get(dictionaryName.name));
|
||||||
|
if (graphicStateObject.isDictionary())
|
||||||
|
{
|
||||||
|
const PDFDictionary* graphicStateDictionary = graphicStateObject.getDictionary();
|
||||||
|
|
||||||
|
PDFDocumentDataLoaderDecorator loader(m_document);
|
||||||
|
const PDFReal lineWidth = loader.readNumberFromDictionary(graphicStateDictionary, "LW", m_graphicState.getLineWidth());
|
||||||
|
const Qt::PenCapStyle penCapStyle = convertLineCapToPenCapStyle(loader.readNumberFromDictionary(graphicStateDictionary, "LC", convertPenCapStyleToLineCap(m_graphicState.getLineCapStyle())));
|
||||||
|
const Qt::PenJoinStyle penJoinStyle = convertLineJoinToPenJoinStyle(loader.readNumberFromDictionary(graphicStateDictionary, "LJ", convertPenJoinStyleToLineJoin(m_graphicState.getLineJoinStyle())));
|
||||||
|
const PDFReal mitterLimit = loader.readNumberFromDictionary(graphicStateDictionary, "MT", m_graphicState.getMitterLimit());
|
||||||
|
|
||||||
|
const PDFObject& lineDashPatternObject = m_document->getObject(graphicStateDictionary->get("D"));
|
||||||
|
if (lineDashPatternObject.isArray())
|
||||||
|
{
|
||||||
|
const PDFArray* lineDashPatternDefinitionArray = lineDashPatternObject.getArray();
|
||||||
|
if (lineDashPatternDefinitionArray->getCount() == 2)
|
||||||
|
{
|
||||||
|
PDFLineDashPattern pattern(loader.readNumberArray(lineDashPatternDefinitionArray->getItem(0)), loader.readNumber(lineDashPatternDefinitionArray->getItem(1), 0.0));
|
||||||
|
m_graphicState.setLineDashPattern(pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const PDFObject& renderingIntentObject = m_document->getObject(graphicStateDictionary->get("RI"));
|
||||||
|
if (renderingIntentObject.isName())
|
||||||
|
{
|
||||||
|
m_graphicState.setRenderingIntent(renderingIntentObject.getString());
|
||||||
|
}
|
||||||
|
|
||||||
|
const PDFReal flatness = loader.readNumberFromDictionary(graphicStateDictionary, "FL", m_graphicState.getFlatness());
|
||||||
|
const PDFReal smoothness = loader.readNumberFromDictionary(graphicStateDictionary, "SM", m_graphicState.getSmoothness());
|
||||||
|
|
||||||
|
m_graphicState.setLineWidth(lineWidth);
|
||||||
|
m_graphicState.setLineCapStyle(penCapStyle);
|
||||||
|
m_graphicState.setLineJoinStyle(penJoinStyle);
|
||||||
|
m_graphicState.setMitterLimit(mitterLimit);
|
||||||
|
m_graphicState.setFlatness(flatness);
|
||||||
|
m_graphicState.setSmoothness(smoothness);
|
||||||
|
updateGraphicState();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Graphic state '%1' found, but invalid in resource dictionary.").arg(QString::fromLatin1(dictionaryName.name)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Graphic state '%1' not found in resource dictionary.").arg(QString::fromLatin1(dictionaryName.name)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Invalid page resource dictionary."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Invalid page resource dictionary."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Invalid page resource dictionary."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PDFPageContentProcessor::operatorSaveGraphicState()
|
void PDFPageContentProcessor::operatorSaveGraphicState()
|
||||||
{
|
{
|
||||||
performSaveGraphicState(ProcessOrder::BeforeOperation);
|
performSaveGraphicState(ProcessOrder::BeforeOperation);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
static constexpr const char* PDF_RESOURCE_EXTGSTATE = "ExtGState";
|
||||||
|
|
||||||
class PDFRendererException : public std::exception
|
class PDFRendererException : public std::exception
|
||||||
{
|
{
|
||||||
@ -391,6 +392,24 @@ private:
|
|||||||
return QColor();
|
return QColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts PDF line cap to Qt's pen cap style. Function always succeeds,
|
||||||
|
/// if invalid \p lineCap occurs, then some valid pen cap style is returned.
|
||||||
|
/// \param lineCap PDF Line cap style (see PDF Reference 1.7, values can be 0, 1, and 2)
|
||||||
|
static Qt::PenCapStyle convertLineCapToPenCapStyle(PDFInteger lineCap);
|
||||||
|
|
||||||
|
/// Convers Qt's pen cap style to PDF's line cap style (defined in the PDF Reference)
|
||||||
|
/// \param penCapStyle Qt's pen cap style to be converted
|
||||||
|
static PDFInteger convertPenCapStyleToLineCap(Qt::PenCapStyle penCapStyle);
|
||||||
|
|
||||||
|
/// Converts PDF line join to Qt's pen join style. Function always succeeds,
|
||||||
|
/// if invalid \p lineJoin occurs, then some valid pen join style is returned.
|
||||||
|
/// \param lineJoin PDF Line join style (see PDF Reference 1.7, values can be 0, 1, and 2)
|
||||||
|
static Qt::PenJoinStyle convertLineJoinToPenJoinStyle(PDFInteger lineJoin);
|
||||||
|
|
||||||
|
/// Convers Qt's pen join style to PDF's line join style (defined in the PDF Reference)
|
||||||
|
/// \param penJoinStyle Qt's pen join style to be converted
|
||||||
|
static PDFInteger convertPenJoinStyleToLineJoin(Qt::PenJoinStyle penJoinStyle);
|
||||||
|
|
||||||
// General graphic state w, J, j, M, d, ri, i, gs
|
// General graphic state w, J, j, M, d, ri, i, gs
|
||||||
void operatorSetLineWidth(PDFReal lineWidth); ///< w, sets the line width
|
void operatorSetLineWidth(PDFReal lineWidth); ///< w, sets the line width
|
||||||
void operatorSetLineCap(PDFInteger lineCap); ///< J, sets the line cap
|
void operatorSetLineCap(PDFInteger lineCap); ///< J, sets the line cap
|
||||||
|
@ -8,7 +8,7 @@ QT += core gui
|
|||||||
|
|
||||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||||
|
|
||||||
TARGET = PdfForQtViewer
|
TARGET = PdfForQtViewer.exe
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
|
|
||||||
# The following define makes your compiler emit warnings if you use
|
# The following define makes your compiler emit warnings if you use
|
||||||
|
Loading…
x
Reference in New Issue
Block a user