mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Text operators (first part)
This commit is contained in:
@ -53,7 +53,9 @@ SOURCES += \
|
||||
sources/pdfpagecontentprocessor.cpp \
|
||||
sources/pdfpainter.cpp \
|
||||
sources/pdfrenderingerrorswidget.cpp \
|
||||
sources/pdffunction.cpp
|
||||
sources/pdffunction.cpp \
|
||||
sources/pdfnametounicode.cpp \
|
||||
sources/pdffont.cpp
|
||||
|
||||
HEADERS += \
|
||||
sources/pdfobject.h \
|
||||
@ -79,7 +81,9 @@ HEADERS += \
|
||||
sources/pdfpainter.h \
|
||||
sources/pdfutils.h \
|
||||
sources/pdfrenderingerrorswidget.h \
|
||||
sources/pdffunction.h
|
||||
sources/pdffunction.h \
|
||||
sources/pdfnametounicode.h \
|
||||
sources/pdffont.h
|
||||
|
||||
unix {
|
||||
target.path = /usr/lib
|
||||
|
@ -288,6 +288,18 @@ PDFReal PDFDocumentDataLoaderDecorator::readNumber(const PDFObject& object, PDFR
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
bool PDFDocumentDataLoaderDecorator::readBoolean(const PDFObject& object, bool defaultValue) const
|
||||
{
|
||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
||||
|
||||
if (dereferencedObject.isBool())
|
||||
{
|
||||
return dereferencedObject.getBool();
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
QString PDFDocumentDataLoaderDecorator::readTextString(const PDFObject& object, const QString& defaultValue) const
|
||||
{
|
||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
||||
@ -436,4 +448,14 @@ std::vector<PDFInteger> PDFDocumentDataLoaderDecorator::readIntegerArray(const P
|
||||
return std::vector<PDFInteger>();
|
||||
}
|
||||
|
||||
bool PDFDocumentDataLoaderDecorator::readBooleanFromDictionary(const PDFDictionary* dictionary, const char* key, bool defaultValue) const
|
||||
{
|
||||
if (dictionary->hasKey(key))
|
||||
{
|
||||
return readBoolean(dictionary->get(key), defaultValue);
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -98,6 +98,11 @@ public:
|
||||
/// \param defaultValue Default value
|
||||
PDFReal readNumber(const PDFObject& object, PDFReal defaultValue) const;
|
||||
|
||||
/// Reads a boolean from the object, if it is possible.
|
||||
/// \param object Object, can be an indirect reference to object (it is dereferenced)
|
||||
/// \param defaultValue Default value
|
||||
bool readBoolean(const PDFObject& object, bool defaultValue) const;
|
||||
|
||||
/// 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 defaultValue Default value
|
||||
@ -206,6 +211,12 @@ public:
|
||||
/// \param object Object containing array of numbers
|
||||
std::vector<PDFInteger> readIntegerArray(const PDFObject& object) const;
|
||||
|
||||
/// Reads boolean from dictionary. If dictionary entry doesn't exist, or error occurs, default value is returned.
|
||||
/// \param dictionary Dictionary containing desired data
|
||||
/// \param key Entry key
|
||||
/// \param defaultValue Default value
|
||||
bool readBooleanFromDictionary(const PDFDictionary* dictionary, const char* key, bool defaultValue) const;
|
||||
|
||||
private:
|
||||
const PDFDocument* m_document;
|
||||
};
|
||||
|
28
PdfForQtLib/sources/pdffont.cpp
Normal file
28
PdfForQtLib/sources/pdffont.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2019 Jakub Melka
|
||||
//
|
||||
// This file is part of PdfForQt.
|
||||
//
|
||||
// PdfForQt 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// PdfForQt 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 PDFForQt. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdffont.h"
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
PDFFont::PDFFont()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
} // namespace pdf
|
95
PdfForQtLib/sources/pdffont.h
Normal file
95
PdfForQtLib/sources/pdffont.h
Normal file
@ -0,0 +1,95 @@
|
||||
// Copyright (C) 2019 Jakub Melka
|
||||
//
|
||||
// This file is part of PdfForQt.
|
||||
//
|
||||
// PdfForQt 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// PdfForQt 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 PDFForQt. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFFONT_H
|
||||
#define PDFFONT_H
|
||||
|
||||
#include "pdfglobal.h"
|
||||
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
enum class TextRenderingMode
|
||||
{
|
||||
Fill = 0,
|
||||
Stroke = 1,
|
||||
FillStroke = 2,
|
||||
Invisible = 3,
|
||||
FillClip = 4,
|
||||
StrokeClip = 5,
|
||||
FillStrokeClip = 6,
|
||||
Clip = 7
|
||||
};
|
||||
|
||||
constexpr bool isTextRenderingModeFilled(TextRenderingMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case TextRenderingMode::Fill:
|
||||
case TextRenderingMode::FillClip:
|
||||
case TextRenderingMode::FillStroke:
|
||||
case TextRenderingMode::FillStrokeClip:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool isTextRenderingModeStroked(TextRenderingMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case TextRenderingMode::Stroke:
|
||||
case TextRenderingMode::FillStroke:
|
||||
case TextRenderingMode::StrokeClip:
|
||||
case TextRenderingMode::FillStrokeClip:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool isTextRenderingModeClipped(TextRenderingMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case TextRenderingMode::Clip:
|
||||
case TextRenderingMode::FillClip:
|
||||
case TextRenderingMode::StrokeClip:
|
||||
case TextRenderingMode::FillStrokeClip:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class PDFFont
|
||||
{
|
||||
public:
|
||||
PDFFont();
|
||||
};
|
||||
|
||||
using PDFFontPointer = QSharedPointer<PDFFont>;
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
#endif // PDFFONT_H
|
4543
PdfForQtLib/sources/pdfnametounicode.cpp
Normal file
4543
PdfForQtLib/sources/pdfnametounicode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
61
PdfForQtLib/sources/pdfnametounicode.h
Normal file
61
PdfForQtLib/sources/pdfnametounicode.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2018 Jakub Melka
|
||||
//
|
||||
// This file is part of PdfForQt.
|
||||
//
|
||||
// PdfForQt 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
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// PdfForQt 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 PDFForQt. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#ifndef PDFNAMETOUNICODE_H
|
||||
#define PDFNAMETOUNICODE_H
|
||||
|
||||
#include "pdfglobal.h"
|
||||
|
||||
#include <QChar>
|
||||
#include <QByteArray>
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
class PDFFORQTLIBSHARED_EXPORT PDFNameToUnicode
|
||||
{
|
||||
public:
|
||||
explicit PDFNameToUnicode() = delete;
|
||||
|
||||
/// Returns unicode character for name. If name is not found, then null character is returned.
|
||||
static QChar getUnicodeForName(const QByteArray& name);
|
||||
|
||||
/// Returns unicode character for name (for ZapfDingbats). If name is not found, then null character is returned.
|
||||
static QChar getUnicodeForNameZapfDingbats(const QByteArray& name);
|
||||
|
||||
private:
|
||||
struct Comparator
|
||||
{
|
||||
inline bool operator()(const QByteArray& left, const std::pair<QChar, const char*>& right)
|
||||
{
|
||||
return left < right.second;
|
||||
}
|
||||
inline bool operator()(const std::pair<QChar, const char*>& left, const QByteArray& right)
|
||||
{
|
||||
return left.second < right;
|
||||
}
|
||||
inline bool operator()(const std::pair<QChar, const char*>& left, const std::pair<QChar, const char*>& right)
|
||||
{
|
||||
return QLatin1String(left.second) < QLatin1String(right.second);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
#endif // PDFNAMETOUNICODE_H
|
@ -152,7 +152,8 @@ static constexpr const std::pair<const char*, PDFPageContentProcessor::Operator>
|
||||
PDFPageContentProcessor::PDFPageContentProcessor(const PDFPage* page, const PDFDocument* document) :
|
||||
m_page(page),
|
||||
m_document(document),
|
||||
m_colorSpaceDictionary(nullptr)
|
||||
m_colorSpaceDictionary(nullptr),
|
||||
m_textBeginEndState(0)
|
||||
{
|
||||
Q_ASSERT(page);
|
||||
Q_ASSERT(document);
|
||||
@ -597,6 +598,97 @@ void PDFPageContentProcessor::processCommand(const QByteArray& command)
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextBegin:
|
||||
{
|
||||
// BT, begin text object, initialize text matrices, cannot be nested
|
||||
operatorTextBegin();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextEnd:
|
||||
{
|
||||
// ET, end text object, cannot be nested
|
||||
operatorTextEnd();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextSetCharacterSpacing:
|
||||
{
|
||||
// Tc, set text character spacing
|
||||
invokeOperator(&PDFPageContentProcessor::operatorTextSetCharacterSpacing);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextSetWordSpacing:
|
||||
{
|
||||
// Tw, set text word spacing
|
||||
invokeOperator(&PDFPageContentProcessor::operatorTextSetWordSpacing);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextSetHorizontalScale:
|
||||
{
|
||||
// Tz, set text horizontal scaling (in percents, 100% = normal scaling)
|
||||
invokeOperator(&PDFPageContentProcessor::operatorTextSetHorizontalScale);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextSetLeading:
|
||||
{
|
||||
// TL, set text leading
|
||||
invokeOperator(&PDFPageContentProcessor::operatorTextSetLeading);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextSetFontAndFontSize:
|
||||
{
|
||||
// Tf, set text font (name from dictionary) and its size
|
||||
invokeOperator(&PDFPageContentProcessor::operatorTextSetFontAndFontSize);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextSetRenderMode:
|
||||
{
|
||||
// Tr, set text render mode
|
||||
invokeOperator(&PDFPageContentProcessor::operatorTextSetRenderMode);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextSetRise:
|
||||
{
|
||||
// Ts, set text rise
|
||||
invokeOperator(&PDFPageContentProcessor::operatorTextSetRise);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextMoveByOffset:
|
||||
{
|
||||
// Td, move by offset
|
||||
invokeOperator(&PDFPageContentProcessor::operatorTextMoveByOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextSetLeadingAndMoveByOffset:
|
||||
{
|
||||
// TD, sets text leading and moves by offset, x y TD is equivalent to sequence -y TL x y Td
|
||||
invokeOperator(&PDFPageContentProcessor::operatorTextSetLeadingAndMoveByOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextSetMatrix:
|
||||
{
|
||||
// Tm, set text matrix
|
||||
invokeOperator(&PDFPageContentProcessor::operatorTextSetMatrix);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::TextMoveByLeading:
|
||||
{
|
||||
// T*, moves text by leading, equivalent to 0 leading Td
|
||||
operatorTextMoveByLeading();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operator::Invalid:
|
||||
{
|
||||
m_errorList.append(PDFRenderError(RenderErrorType::Error, PDFTranslationContext::tr("Unknown operator '%1'.").arg(QString::fromLatin1(command))));
|
||||
@ -867,6 +959,7 @@ void PDFPageContentProcessor::operatorSetGraphicState(PDFName dictionaryName)
|
||||
|
||||
const PDFReal flatness = loader.readNumberFromDictionary(graphicStateDictionary, "FL", m_graphicState.getFlatness());
|
||||
const PDFReal smoothness = loader.readNumberFromDictionary(graphicStateDictionary, "SM", m_graphicState.getSmoothness());
|
||||
const bool textKnockout = loader.readBooleanFromDictionary(graphicStateDictionary, "TK", m_graphicState.getTextKnockout());
|
||||
|
||||
m_graphicState.setLineWidth(lineWidth);
|
||||
m_graphicState.setLineCapStyle(penCapStyle);
|
||||
@ -874,6 +967,7 @@ void PDFPageContentProcessor::operatorSetGraphicState(PDFName dictionaryName)
|
||||
m_graphicState.setMitterLimit(mitterLimit);
|
||||
m_graphicState.setFlatness(flatness);
|
||||
m_graphicState.setSmoothness(smoothness);
|
||||
m_graphicState.setTextKnockout(textKnockout);
|
||||
updateGraphicState();
|
||||
}
|
||||
else
|
||||
@ -1315,6 +1409,130 @@ void PDFPageContentProcessor::operatorColorSetDeviceCMYKFilling(PDFReal c, PDFRe
|
||||
updateGraphicState();
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextBegin()
|
||||
{
|
||||
m_graphicState.setTextMatrix(QMatrix());
|
||||
m_graphicState.setTextLineMatrix(QMatrix());
|
||||
updateGraphicState();
|
||||
|
||||
++m_textBeginEndState;
|
||||
|
||||
if (m_textBeginEndState > 1)
|
||||
{
|
||||
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Text object already started."));
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextEnd()
|
||||
{
|
||||
if (--m_textBeginEndState < 0)
|
||||
{
|
||||
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Text object ended more than once."));
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextSetCharacterSpacing(PDFReal charSpacing)
|
||||
{
|
||||
m_graphicState.setTextCharacterSpacing(charSpacing);
|
||||
updateGraphicState();
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextSetWordSpacing(PDFReal wordSpacing)
|
||||
{
|
||||
m_graphicState.setTextWordSpacing(wordSpacing);
|
||||
updateGraphicState();
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextSetHorizontalScale(PDFReal horizontalScaling)
|
||||
{
|
||||
// We disable horizontal scaling to less than 1%
|
||||
horizontalScaling = qMax(horizontalScaling, 1.0);
|
||||
|
||||
m_graphicState.setTextHorizontalScaling(horizontalScaling / 100.0);
|
||||
updateGraphicState();
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextSetLeading(PDFReal leading)
|
||||
{
|
||||
m_graphicState.setTextLeading(leading);
|
||||
updateGraphicState();
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextSetFontAndFontSize(PDFPageContentProcessor::PDFName fontName, PDFReal fontSize)
|
||||
{
|
||||
Q_UNUSED(fontName);
|
||||
Q_UNUSED(fontSize);
|
||||
|
||||
// TODO: Implement this operator
|
||||
throw PDFRendererException(RenderErrorType::NotImplemented, PDFTranslationContext::tr("Set font not implemented."));
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextSetRenderMode(PDFInteger mode)
|
||||
{
|
||||
mode = qBound<PDFInteger>(0, mode, 7);
|
||||
m_graphicState.setTextRenderingMode(static_cast<TextRenderingMode>(mode));
|
||||
updateGraphicState();
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextSetRise(PDFReal rise)
|
||||
{
|
||||
m_graphicState.setTextRise(rise);
|
||||
updateGraphicState();
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextMoveByOffset(PDFReal t_x, PDFReal t_y)
|
||||
{
|
||||
const QMatrix& textLineMatrix = m_graphicState.getTextLineMatrix();
|
||||
|
||||
QMatrix translationMatrix;
|
||||
translationMatrix.translate(t_x, t_y);
|
||||
|
||||
QMatrix resultMatrix = textLineMatrix * translationMatrix;
|
||||
m_graphicState.setTextMatrix(resultMatrix);
|
||||
m_graphicState.setTextLineMatrix(resultMatrix);
|
||||
updateGraphicState();
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextSetLeadingAndMoveByOffset(PDFReal t_x, PDFReal t_y)
|
||||
{
|
||||
// Update of graphic state is
|
||||
m_graphicState.setTextLeading(-t_y);
|
||||
operatorTextMoveByOffset(t_x, t_y);
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextSetMatrix(PDFReal a, PDFReal b, PDFReal c, PDFReal d, PDFReal e, PDFReal f)
|
||||
{
|
||||
// We will comment following equation:
|
||||
// Adobe PDF Reference 1.7 says, that we have this transformation using coefficient a, b, c, d, e and f:
|
||||
// [ a, b, 0 ]
|
||||
// [x', y', 1] = [ x, y, 1] * [ c, d, 0 ]
|
||||
// [ e, f, 1 ]
|
||||
// If we transpose this equation (we want this, because Qt uses transposed matrices (QMatrix).
|
||||
// So, we will get following result:
|
||||
//
|
||||
// [ x' ] [ a, c, e] [ x ]
|
||||
// [ y' ] = [ b, d, f] * [ y ]
|
||||
// [ 1 ] [ 0, 0, 1] [ 1 ]
|
||||
//
|
||||
// So, it is obvious, than we will have following coefficients:
|
||||
// m_11 = a, m_21 = c, dx = e
|
||||
// m_12 = b, m_22 = d, dy = f
|
||||
//
|
||||
// We must also check, that matrix is invertible. If it is not, then we will throw exception
|
||||
// to avoid errors later (for some operations, we assume matrix is invertible).
|
||||
|
||||
QMatrix matrix(a, b, c, d, e, f);
|
||||
|
||||
m_graphicState.setTextMatrix(matrix);
|
||||
m_graphicState.setTextLineMatrix(matrix);
|
||||
updateGraphicState();
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::operatorTextMoveByLeading()
|
||||
{
|
||||
operatorTextMoveByOffset(0.0, m_graphicState.getTextLeading());
|
||||
}
|
||||
|
||||
PDFPageContentProcessor::PDFPageContentProcessorState::PDFPageContentProcessorState() :
|
||||
m_currentTransformationMatrix(),
|
||||
m_fillColorSpace(),
|
||||
@ -1328,6 +1546,14 @@ PDFPageContentProcessor::PDFPageContentProcessorState::PDFPageContentProcessorSt
|
||||
m_renderingIntent(),
|
||||
m_flatness(1.0),
|
||||
m_smoothness(0.01),
|
||||
m_textCharacterSpacing(0.0),
|
||||
m_textWordSpacing(0.0),
|
||||
m_textHorizontalScaling(100.0),
|
||||
m_textLeading(0.0),
|
||||
m_textFontSize(0.0),
|
||||
m_textRenderingMode(TextRenderingMode::Fill),
|
||||
m_textRise(0.0),
|
||||
m_textKnockout(true),
|
||||
m_stateFlags(StateUnchanged)
|
||||
{
|
||||
m_fillColorSpace.reset(new PDFDeviceGrayColorSpace);
|
||||
@ -1354,6 +1580,17 @@ PDFPageContentProcessor::PDFPageContentProcessorState& PDFPageContentProcessor::
|
||||
setRenderingIntent(other.getRenderingIntent());
|
||||
setFlatness(other.getFlatness());
|
||||
setSmoothness(other.getSmoothness());
|
||||
setTextCharacterSpacing(other.getTextCharacterSpacing());
|
||||
setTextWordSpacing(other.getTextWordSpacing());
|
||||
setTextHorizontalScaling(other.getTextHorizontalScaling());
|
||||
setTextLeading(other.getTextLeading());
|
||||
setTextFont(other.getTextFont());
|
||||
setTextFontSize(other.getTextFontSize());
|
||||
setTextRenderingMode(other.getTextRenderingMode());
|
||||
setTextRise(other.getTextRise());
|
||||
setTextKnockout(other.getTextKnockout());
|
||||
setTextMatrix(other.getTextMatrix());
|
||||
setTextLineMatrix(other.getTextLineMatrix());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1429,7 +1666,7 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setLineJoinStyle(Qt:
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setMitterLimit(const PDFReal& mitterLimit)
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setMitterLimit(PDFReal mitterLimit)
|
||||
{
|
||||
if (m_mitterLimit != mitterLimit)
|
||||
{
|
||||
@ -1474,4 +1711,103 @@ void PDFPageContentProcessor::PDFPageContentProcessorState::setSmoothness(PDFRea
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextLeading(PDFReal textLeading)
|
||||
{
|
||||
if (m_textLeading != textLeading)
|
||||
{
|
||||
m_textLeading = textLeading;
|
||||
m_stateFlags |= StateTextLeading;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextFontSize(PDFReal textFontSize)
|
||||
{
|
||||
if (m_textFontSize != textFontSize)
|
||||
{
|
||||
m_textFontSize = textFontSize;
|
||||
m_stateFlags |= StateTextFontSize;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextKnockout(bool textKnockout)
|
||||
{
|
||||
if (m_textKnockout != textKnockout)
|
||||
{
|
||||
m_textKnockout = textKnockout;
|
||||
m_stateFlags |= StateTextKnockout;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextLineMatrix(const QMatrix& textLineMatrix)
|
||||
{
|
||||
if (m_textLineMatrix != textLineMatrix)
|
||||
{
|
||||
m_textLineMatrix = textLineMatrix;
|
||||
m_stateFlags |= StateTextLineMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextMatrix(const QMatrix& textMatrix)
|
||||
{
|
||||
if (m_textMatrix != textMatrix)
|
||||
{
|
||||
m_textMatrix = textMatrix;
|
||||
m_stateFlags |= StateTextMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextRise(PDFReal textRise)
|
||||
{
|
||||
if (m_textRise != textRise)
|
||||
{
|
||||
m_textRise = textRise;
|
||||
m_stateFlags |= StateTextRise;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextRenderingMode(TextRenderingMode textRenderingMode)
|
||||
{
|
||||
if (m_textRenderingMode != textRenderingMode)
|
||||
{
|
||||
m_textRenderingMode = textRenderingMode;
|
||||
m_stateFlags |= StateTextRenderingMode;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextFont(const PDFFontPointer& textFont)
|
||||
{
|
||||
if (m_textFont != textFont)
|
||||
{
|
||||
m_textFont = textFont;
|
||||
m_stateFlags |= StateTextFont;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextHorizontalScaling(PDFReal textHorizontalScaling)
|
||||
{
|
||||
if (m_textHorizontalScaling != textHorizontalScaling)
|
||||
{
|
||||
m_textHorizontalScaling = textHorizontalScaling;
|
||||
m_stateFlags |= StateTextHorizontalScaling;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextWordSpacing(PDFReal textWordSpacing)
|
||||
{
|
||||
if (m_textWordSpacing != textWordSpacing)
|
||||
{
|
||||
m_textWordSpacing = textWordSpacing;
|
||||
m_stateFlags |= StateTextWordSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
void PDFPageContentProcessor::PDFPageContentProcessorState::setTextCharacterSpacing(PDFReal textCharacterSpacing)
|
||||
{
|
||||
if (m_textCharacterSpacing != textCharacterSpacing)
|
||||
{
|
||||
m_textCharacterSpacing = textCharacterSpacing;
|
||||
m_stateFlags |= StateTextCharacterSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "pdfrenderer.h"
|
||||
#include "pdfparser.h"
|
||||
#include "pdfcolorspaces.h"
|
||||
#include "pdffont.h"
|
||||
|
||||
#include <QMatrix>
|
||||
#include <QPainterPath>
|
||||
@ -113,7 +114,7 @@ public:
|
||||
|
||||
// Text positioning: Td, TD, Tm, T*
|
||||
TextMoveByOffset, ///< Td, move by offset
|
||||
TextSetLeadingAndMoveByOffset, ///< TD, sets thext leading and moves by offset, x y TD is equivalent to sequence -y TL x y Td
|
||||
TextSetLeadingAndMoveByOffset, ///< TD, sets text leading and moves by offset, x y TD is equivalent to sequence -y TL x y Td
|
||||
TextSetMatrix, ///< Tm, set text matrix
|
||||
TextMoveByLeading, ///< T*, moves text by leading, equivalent to 0 leading Td
|
||||
|
||||
@ -214,20 +215,31 @@ protected:
|
||||
|
||||
enum StateFlag
|
||||
{
|
||||
StateUnchanged = 0x0000,
|
||||
StateCurrentTransformationMatrix = 0x0001,
|
||||
StateStrokeColorSpace = 0x0002,
|
||||
StateFillColorSpace = 0x0004,
|
||||
StateStrokeColor = 0x0008,
|
||||
StateFillColor = 0x0010,
|
||||
StateLineWidth = 0x0020,
|
||||
StateLineCapStyle = 0x0040,
|
||||
StateLineJoinStyle = 0x0080,
|
||||
StateMitterLimit = 0x0100,
|
||||
StateLineDashPattern = 0x0200,
|
||||
StateRenderingIntent = 0x0400,
|
||||
StateFlatness = 0x0800,
|
||||
StateSmoothness = 0x1000,
|
||||
StateUnchanged = 0x00000000,
|
||||
StateCurrentTransformationMatrix = 0x00000001,
|
||||
StateStrokeColorSpace = 0x00000002,
|
||||
StateFillColorSpace = 0x00000004,
|
||||
StateStrokeColor = 0x00000008,
|
||||
StateFillColor = 0x00000010,
|
||||
StateLineWidth = 0x00000020,
|
||||
StateLineCapStyle = 0x00000040,
|
||||
StateLineJoinStyle = 0x00000080,
|
||||
StateMitterLimit = 0x00000100,
|
||||
StateLineDashPattern = 0x00000200,
|
||||
StateRenderingIntent = 0x00000400,
|
||||
StateFlatness = 0x00000800,
|
||||
StateSmoothness = 0x00001000,
|
||||
StateTextMatrix = 0x00002000,
|
||||
StateTextLineMatrix = 0x00004000,
|
||||
StateTextCharacterSpacing = 0x00008000,
|
||||
StateTextWordSpacing = 0x00010000,
|
||||
StateTextHorizontalScaling = 0x00020000,
|
||||
StateTextLeading = 0x00040000,
|
||||
StateTextFont = 0x00080000,
|
||||
StateTextFontSize = 0x00100000,
|
||||
StateTextRenderingMode = 0x00200000,
|
||||
StateTextRise = 0x00400000,
|
||||
StateTextKnockout = 0x00800000,
|
||||
StateAll = 0xFFFF
|
||||
};
|
||||
|
||||
@ -258,7 +270,7 @@ protected:
|
||||
void setLineJoinStyle(Qt::PenJoinStyle lineJoinStyle);
|
||||
|
||||
PDFReal getMitterLimit() const { return m_mitterLimit; }
|
||||
void setMitterLimit(const PDFReal& mitterLimit);
|
||||
void setMitterLimit(PDFReal mitterLimit);
|
||||
|
||||
const PDFLineDashPattern& getLineDashPattern() const { return m_lineDashPattern; }
|
||||
void setLineDashPattern(PDFLineDashPattern pattern);
|
||||
@ -275,6 +287,39 @@ protected:
|
||||
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 QMatrix& getTextMatrix() const { return m_textMatrix; }
|
||||
void setTextMatrix(const QMatrix& textMatrix);
|
||||
|
||||
const QMatrix& getTextLineMatrix() const { return m_textLineMatrix; }
|
||||
void setTextLineMatrix(const QMatrix& textLineMatrix);
|
||||
|
||||
private:
|
||||
QMatrix m_currentTransformationMatrix;
|
||||
PDFColorSpacePointer m_strokeColorSpace;
|
||||
@ -289,6 +334,17 @@ protected:
|
||||
QByteArray m_renderingIntent;
|
||||
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;
|
||||
QMatrix m_textMatrix;
|
||||
QMatrix m_textLineMatrix;
|
||||
StateFlags m_stateFlags;
|
||||
};
|
||||
|
||||
@ -475,6 +531,25 @@ private:
|
||||
void operatorColorSetDeviceCMYKStroking(PDFReal c, PDFReal m, PDFReal y, PDFReal k); ///< K, set DeviceCMYK color space for stroking color and set color
|
||||
void operatorColorSetDeviceCMYKFilling(PDFReal c, PDFReal m, PDFReal y, PDFReal k); ///< k, set DeviceCMYK color space for filling color and set color
|
||||
|
||||
// Text object: BT, ET
|
||||
void operatorTextBegin(); ///< BT, begin text object, initialize text matrices, cannot be nested
|
||||
void operatorTextEnd(); ///< ET, end text object, cannot be nested
|
||||
|
||||
// Text state: Tc, Tw, Tz, TL, Tf, Tr, Ts
|
||||
void operatorTextSetCharacterSpacing(PDFReal charSpacing); ///< Tc, set text character spacing
|
||||
void operatorTextSetWordSpacing(PDFReal wordSpacing); ///< Tw, set text word spacing
|
||||
void operatorTextSetHorizontalScale(PDFReal horizontalScaling); ///< Tz, set text horizontal scaling (in percents, 100% = normal scaling)
|
||||
void operatorTextSetLeading(PDFReal leading); ///< TL, set text leading
|
||||
void operatorTextSetFontAndFontSize(PDFName fontName, PDFReal fontSize); ///< Tf, set text font (name from dictionary) and its size
|
||||
void operatorTextSetRenderMode(PDFInteger mode); ///< Tr, set text render mode
|
||||
void operatorTextSetRise(PDFReal rise); ///< Ts, set text rise
|
||||
|
||||
// Text positioning: Td, TD, Tm, T*
|
||||
void operatorTextMoveByOffset(PDFReal t_x, PDFReal t_y); ///< Td, move by offset
|
||||
void operatorTextSetLeadingAndMoveByOffset(PDFReal t_x, PDFReal t_y); ///< TD, sets text leading and moves by offset, x y TD is equivalent to sequence -y TL x y Td
|
||||
void operatorTextSetMatrix(PDFReal a, PDFReal b, PDFReal c, PDFReal d, PDFReal e, PDFReal f); ///< Tm, set text matrix
|
||||
void operatorTextMoveByLeading(); ///< T*, moves text by leading, equivalent to 0 leading Td
|
||||
|
||||
const PDFPage* m_page;
|
||||
const PDFDocument* m_document;
|
||||
const PDFDictionary* m_colorSpaceDictionary;
|
||||
@ -498,6 +573,9 @@ private:
|
||||
|
||||
/// Current painter path
|
||||
QPainterPath m_currentPath;
|
||||
|
||||
/// Nesting level of the begin/end of text object
|
||||
int m_textBeginEndState;
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
Reference in New Issue
Block a user