mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-03-15 19:00:24 +01:00
Fix of font drawing
This commit is contained in:
parent
a462e0b768
commit
cd981183b0
@ -273,6 +273,17 @@ QByteArray PDFDocumentDataLoaderDecorator::readName(const PDFObject& object)
|
|||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray PDFDocumentDataLoaderDecorator::readString(const PDFObject& object)
|
||||||
|
{
|
||||||
|
const PDFObject& dereferencedObject = m_document->getObject(object);
|
||||||
|
if (dereferencedObject.isString())
|
||||||
|
{
|
||||||
|
return dereferencedObject.getString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
PDFInteger PDFDocumentDataLoaderDecorator::readInteger(const PDFObject& object, PDFInteger defaultValue) const
|
PDFInteger PDFDocumentDataLoaderDecorator::readInteger(const PDFObject& object, PDFInteger defaultValue) const
|
||||||
{
|
{
|
||||||
const PDFObject& dereferencedObject = m_document->getObject(object);
|
const PDFObject& dereferencedObject = m_document->getObject(object);
|
||||||
@ -479,4 +490,14 @@ QByteArray PDFDocumentDataLoaderDecorator::readNameFromDictionary(const PDFDicti
|
|||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray PDFDocumentDataLoaderDecorator::readStringFromDictionary(const PDFDictionary* dictionary, const char* key)
|
||||||
|
{
|
||||||
|
if (dictionary->hasKey(key))
|
||||||
|
{
|
||||||
|
return readString(dictionary->get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -92,6 +92,11 @@ public:
|
|||||||
/// \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)
|
||||||
QByteArray readName(const PDFObject& object);
|
QByteArray readName(const PDFObject& object);
|
||||||
|
|
||||||
|
/// Reads a string from the object, if it is possible. If object is not a string,
|
||||||
|
/// then empty byte array is returned.
|
||||||
|
/// \param object Object, can be an indirect reference to object (it is dereferenced)
|
||||||
|
QByteArray readString(const PDFObject& object);
|
||||||
|
|
||||||
/// Reads an integer from the object, if it is possible.
|
/// Reads an integer 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)
|
||||||
/// \param defaultValue Default value
|
/// \param defaultValue Default value
|
||||||
@ -227,6 +232,11 @@ public:
|
|||||||
/// \param key Entry key
|
/// \param key Entry key
|
||||||
QByteArray readNameFromDictionary(const PDFDictionary* dictionary, const char* key);
|
QByteArray readNameFromDictionary(const PDFDictionary* dictionary, const char* key);
|
||||||
|
|
||||||
|
/// Reads a string from dictionary. If dictionary entry doesn't exist, or error occurs, empty byte array is returned.
|
||||||
|
/// \param dictionary Dictionary containing desired data
|
||||||
|
/// \param key Entry key
|
||||||
|
QByteArray readStringFromDictionary(const PDFDictionary* dictionary, const char* key);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const PDFDocument* m_document;
|
const PDFDocument* m_document;
|
||||||
};
|
};
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
|
||||||
PDFFont::PDFFont()
|
PDFFont::PDFFont(FontDescriptor fontDescriptor) :
|
||||||
|
m_fontDescriptor(qMove(fontDescriptor))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -78,7 +79,57 @@ PDFFontPointer PDFFont::createFont(const PDFObject& object, const PDFDocument* d
|
|||||||
const StandardFontType standardFont = fontLoader.readEnumByName(fontDictionary->get("BaseFont"), standardFonts.cbegin(), standardFonts.cend(), StandardFontType::Invalid);
|
const StandardFontType standardFont = fontLoader.readEnumByName(fontDictionary->get("BaseFont"), standardFonts.cbegin(), standardFonts.cend(), StandardFontType::Invalid);
|
||||||
|
|
||||||
// Read Font Descriptor
|
// Read Font Descriptor
|
||||||
// TODO: Read font descriptor
|
FontDescriptor fontDescriptor;
|
||||||
|
const PDFObject& fontDescriptorObject = document->getObject(fontDictionary->get("FontDescriptor"));
|
||||||
|
if (fontDescriptorObject.isDictionary())
|
||||||
|
{
|
||||||
|
const PDFDictionary* fontDescriptorDictionary = fontDescriptorObject.getDictionary();
|
||||||
|
fontDescriptor.fontName = fontLoader.readNameFromDictionary(fontDescriptorDictionary, "FontName");
|
||||||
|
fontDescriptor.fontFamily = fontLoader.readStringFromDictionary(fontDescriptorDictionary, "FontFamily");
|
||||||
|
|
||||||
|
constexpr const std::array<std::pair<const char*, QFont::Stretch>, 9> stretches = {
|
||||||
|
std::pair<const char*, QFont::Stretch>{ "UltraCondensed", QFont::UltraCondensed },
|
||||||
|
std::pair<const char*, QFont::Stretch>{ "ExtraCondensed", QFont::ExtraCondensed },
|
||||||
|
std::pair<const char*, QFont::Stretch>{ "Condensed", QFont::Condensed },
|
||||||
|
std::pair<const char*, QFont::Stretch>{ "SemiCondensed", QFont::SemiCondensed },
|
||||||
|
std::pair<const char*, QFont::Stretch>{ "Normal", QFont::Unstretched },
|
||||||
|
std::pair<const char*, QFont::Stretch>{ "SemiExpanded", QFont::SemiExpanded },
|
||||||
|
std::pair<const char*, QFont::Stretch>{ "Expanded", QFont::Expanded },
|
||||||
|
std::pair<const char*, QFont::Stretch>{ "ExtraExpanded", QFont::ExtraExpanded },
|
||||||
|
std::pair<const char*, QFont::Stretch>{ "UltraExpanded", QFont::UltraExpanded }
|
||||||
|
};
|
||||||
|
fontDescriptor.fontStretch = fontLoader.readEnumByName(fontDescriptorDictionary->get("FontStretch"), stretches.cbegin(), stretches.cend(), QFont::Unstretched);
|
||||||
|
fontDescriptor.fontWeight = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "FontWeight", 500);
|
||||||
|
fontDescriptor.italicAngle = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "ItalicAngle", 0.0);
|
||||||
|
fontDescriptor.ascent = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "Ascent", 0.0);
|
||||||
|
fontDescriptor.descent = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "Descent", 0.0);
|
||||||
|
fontDescriptor.leading = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "Leading", 0.0);
|
||||||
|
fontDescriptor.capHeight = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "CapHeight", 0.0);
|
||||||
|
fontDescriptor.xHeight = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "XHeight", 0.0);
|
||||||
|
fontDescriptor.stemV = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "StemV", 0.0);
|
||||||
|
fontDescriptor.stemH = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "StemH", 0.0);
|
||||||
|
fontDescriptor.avgWidth = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "AvgWidth", 0.0);
|
||||||
|
fontDescriptor.maxWidth = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "MaxWidth", 0.0);
|
||||||
|
fontDescriptor.missingWidth = fontLoader.readNumberFromDictionary(fontDescriptorDictionary, "MissingWidth", 0.0);
|
||||||
|
fontDescriptor.flags = fontLoader.readIntegerFromDictionary(fontDescriptorDictionary, "Flags", 0);
|
||||||
|
fontDescriptor.boundingBox = fontLoader.readRectangle(fontDescriptorDictionary->get("FontBBox"), QRectF());
|
||||||
|
fontDescriptor.charset = fontLoader.readStringFromDictionary(fontDescriptorDictionary, "Charset");
|
||||||
|
|
||||||
|
auto loadStream = [fontDescriptorDictionary, document](QByteArray& byteArray, const char* name)
|
||||||
|
{
|
||||||
|
if (fontDescriptorDictionary->hasKey(name))
|
||||||
|
{
|
||||||
|
const PDFObject& streamObject = document->getObject(fontDescriptorDictionary->get(name));
|
||||||
|
if (streamObject.isStream())
|
||||||
|
{
|
||||||
|
byteArray = document->getDecodedStream(streamObject.getStream());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loadStream(fontDescriptor.fontFile, "FontFile");
|
||||||
|
loadStream(fontDescriptor.fontFile2, "FontFile2");
|
||||||
|
loadStream(fontDescriptor.fontFile3, "FontFile3");
|
||||||
|
}
|
||||||
|
|
||||||
// Read Font Encoding
|
// Read Font Encoding
|
||||||
// The font encoding for the simple font is determined by this algorithm:
|
// The font encoding for the simple font is determined by this algorithm:
|
||||||
@ -235,10 +286,10 @@ PDFFontPointer PDFFont::createFont(const PDFObject& object, const PDFDocument* d
|
|||||||
switch (fontType)
|
switch (fontType)
|
||||||
{
|
{
|
||||||
case FontType::Type1:
|
case FontType::Type1:
|
||||||
return PDFFontPointer(new PDFType1Font(qMove(name), qMove(baseFont), firstChar, lastChar, qMove(widths), encoding, simpleFontEncodingTable, standardFont));
|
return PDFFontPointer(new PDFType1Font(qMove(fontDescriptor), qMove(name), qMove(baseFont), firstChar, lastChar, qMove(widths), encoding, simpleFontEncodingTable, standardFont));
|
||||||
|
|
||||||
case FontType::TrueType:
|
case FontType::TrueType:
|
||||||
return PDFFontPointer(new PDFTrueTypeFont(qMove(name), qMove(baseFont), firstChar, lastChar, qMove(widths), encoding, simpleFontEncodingTable));
|
return PDFFontPointer(new PDFTrueTypeFont(qMove(fontDescriptor), qMove(name), qMove(baseFont), firstChar, lastChar, qMove(widths), encoding, simpleFontEncodingTable));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@ -255,13 +306,15 @@ PDFFontPointer PDFFont::createFont(const PDFObject& object, const PDFDocument* d
|
|||||||
return PDFFontPointer();
|
return PDFFontPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFSimpleFont::PDFSimpleFont(QByteArray name,
|
PDFSimpleFont::PDFSimpleFont(FontDescriptor fontDescriptor,
|
||||||
|
QByteArray name,
|
||||||
QByteArray baseFont,
|
QByteArray baseFont,
|
||||||
PDFInteger firstChar,
|
PDFInteger firstChar,
|
||||||
PDFInteger lastChar,
|
PDFInteger lastChar,
|
||||||
std::vector<PDFInteger> widths,
|
std::vector<PDFInteger> widths,
|
||||||
PDFEncoding::Encoding encodingType,
|
PDFEncoding::Encoding encodingType,
|
||||||
encoding::EncodingTable encoding) :
|
encoding::EncodingTable encoding) :
|
||||||
|
PDFFont(qMove(fontDescriptor)),
|
||||||
m_name(qMove(name)),
|
m_name(qMove(name)),
|
||||||
m_baseFont(qMove(baseFont)),
|
m_baseFont(qMove(baseFont)),
|
||||||
m_firstChar(firstChar),
|
m_firstChar(firstChar),
|
||||||
@ -276,10 +329,40 @@ PDFSimpleFont::PDFSimpleFont(QByteArray name,
|
|||||||
QRawFont PDFSimpleFont::getRealizedFont(PDFReal fontSize) const
|
QRawFont PDFSimpleFont::getRealizedFont(PDFReal fontSize) const
|
||||||
{
|
{
|
||||||
// TODO: Fix font creation to use also embedded fonts, font descriptor, etc.
|
// TODO: Fix font creation to use also embedded fonts, font descriptor, etc.
|
||||||
QFont font(m_baseFont);
|
QRawFont rawFont;
|
||||||
font.setHintingPreference(QFont::PreferNoHinting);
|
|
||||||
font.setPixelSize(fontSize);
|
if (m_fontDescriptor.isEmbedded())
|
||||||
return QRawFont::fromFont(font, QFontDatabase::Any);
|
{
|
||||||
|
// Type 1 font
|
||||||
|
if (!m_fontDescriptor.fontFile.isEmpty())
|
||||||
|
{
|
||||||
|
rawFont.loadFromData(m_fontDescriptor.fontFile, fontSize, QFont::PreferNoHinting);
|
||||||
|
}
|
||||||
|
else if (!m_fontDescriptor.fontFile2.isEmpty())
|
||||||
|
{
|
||||||
|
rawFont.loadFromData(m_fontDescriptor.fontFile2, fontSize, QFont::PreferNoHinting);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rawFont.isValid())
|
||||||
|
{
|
||||||
|
throw PDFParserException(PDFTranslationContext::tr("Can't load embedded font."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: Zkontrolovat, zda se zde opravdu prebiraji spravne fonty
|
||||||
|
const int weight = qBound<int>(0, m_fontDescriptor.fontWeight / 10.0, 99);
|
||||||
|
const int stretch = qBound<int>(1, m_fontDescriptor.fontStretch, 4000);
|
||||||
|
|
||||||
|
QFont font(m_baseFont);
|
||||||
|
font.setHintingPreference(QFont::PreferNoHinting);
|
||||||
|
font.setStretch(stretch);
|
||||||
|
font.setWeight(weight);
|
||||||
|
font.setPixelSize(fontSize);
|
||||||
|
rawFont = QRawFont::fromFont(font, QFontDatabase::Any);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rawFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PDFSimpleFont::getTextUsingEncoding(const QByteArray& byteArray) const
|
QString PDFSimpleFont::getTextUsingEncoding(const QByteArray& byteArray) const
|
||||||
@ -295,7 +378,8 @@ QString PDFSimpleFont::getTextUsingEncoding(const QByteArray& byteArray) const
|
|||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFType1Font::PDFType1Font(QByteArray name,
|
PDFType1Font::PDFType1Font(FontDescriptor fontDescriptor,
|
||||||
|
QByteArray name,
|
||||||
QByteArray baseFont,
|
QByteArray baseFont,
|
||||||
PDFInteger firstChar,
|
PDFInteger firstChar,
|
||||||
PDFInteger lastChar,
|
PDFInteger lastChar,
|
||||||
@ -303,7 +387,7 @@ PDFType1Font::PDFType1Font(QByteArray name,
|
|||||||
PDFEncoding::Encoding encodingType,
|
PDFEncoding::Encoding encodingType,
|
||||||
encoding::EncodingTable encoding,
|
encoding::EncodingTable encoding,
|
||||||
StandardFontType standardFontType) :
|
StandardFontType standardFontType) :
|
||||||
PDFSimpleFont(qMove(name), qMove(baseFont), firstChar, lastChar, qMove(widths), encodingType, encoding),
|
PDFSimpleFont(qMove(fontDescriptor), qMove(name), qMove(baseFont), firstChar, lastChar, qMove(widths), encodingType, encoding),
|
||||||
m_standardFontType(standardFontType)
|
m_standardFontType(standardFontType)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -129,6 +129,42 @@ static constexpr PDFEncoding::Encoding getEncodingForStandardFont(StandardFontTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FontDescriptor
|
||||||
|
{
|
||||||
|
bool isEmbedded() const { return !fontFile.isEmpty() || !fontFile2.isEmpty() || !fontFile3.isEmpty(); }
|
||||||
|
|
||||||
|
QByteArray fontName;
|
||||||
|
QByteArray fontFamily;
|
||||||
|
QFont::Stretch fontStretch = QFont::AnyStretch;
|
||||||
|
PDFReal fontWeight = 400.0;
|
||||||
|
PDFInteger flags;
|
||||||
|
QRectF boundingBox;
|
||||||
|
PDFReal italicAngle = 0.0;
|
||||||
|
PDFReal ascent = 0.0;
|
||||||
|
PDFReal descent = 0.0;
|
||||||
|
PDFReal leading = 0.0;
|
||||||
|
PDFReal capHeight = 0.0;
|
||||||
|
PDFReal xHeight = 0.0;
|
||||||
|
PDFReal stemV = 0.0;
|
||||||
|
PDFReal stemH = 0.0;
|
||||||
|
PDFReal avgWidth = 0.0;
|
||||||
|
PDFReal maxWidth = 0.0;
|
||||||
|
PDFReal missingWidth = 0.0;
|
||||||
|
|
||||||
|
/// Byte array with Type 1 font program (embedded font)
|
||||||
|
QByteArray fontFile;
|
||||||
|
|
||||||
|
/// Byte array with TrueType font program (embedded font)
|
||||||
|
QByteArray fontFile2;
|
||||||
|
|
||||||
|
/// Byte array with font program, whose format is defined by the Subtype array
|
||||||
|
/// in the font dictionary.
|
||||||
|
QByteArray fontFile3;
|
||||||
|
|
||||||
|
/// Character set
|
||||||
|
QByteArray charset;
|
||||||
|
};
|
||||||
|
|
||||||
class PDFFont;
|
class PDFFont;
|
||||||
|
|
||||||
using PDFFontPointer = QSharedPointer<PDFFont>;
|
using PDFFontPointer = QSharedPointer<PDFFont>;
|
||||||
@ -137,7 +173,7 @@ using PDFFontPointer = QSharedPointer<PDFFont>;
|
|||||||
class PDFFont
|
class PDFFont
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PDFFont();
|
explicit PDFFont(FontDescriptor fontDescriptor);
|
||||||
virtual ~PDFFont() = default;
|
virtual ~PDFFont() = default;
|
||||||
|
|
||||||
/// Returns the font type
|
/// Returns the font type
|
||||||
@ -152,7 +188,16 @@ public:
|
|||||||
/// \param byteArray Byte array with encoded string
|
/// \param byteArray Byte array with encoded string
|
||||||
virtual QString getTextUsingEncoding(const QByteArray& byteArray) const = 0;
|
virtual QString getTextUsingEncoding(const QByteArray& byteArray) const = 0;
|
||||||
|
|
||||||
|
/// Returns font descriptor
|
||||||
|
const FontDescriptor* getFontDescriptor() const { return &m_fontDescriptor; }
|
||||||
|
|
||||||
|
/// Creates font from the object. If font can't be created, exception is thrown.
|
||||||
|
/// \param object Font dictionary
|
||||||
|
/// \param document Document
|
||||||
static PDFFontPointer createFont(const PDFObject& object, const PDFDocument* document);
|
static PDFFontPointer createFont(const PDFObject& object, const PDFDocument* document);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FontDescriptor m_fontDescriptor;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Simple font, see PDF reference 1.7, chapter 5.5. Simple fonts have encoding table,
|
/// Simple font, see PDF reference 1.7, chapter 5.5. Simple fonts have encoding table,
|
||||||
@ -160,7 +205,8 @@ public:
|
|||||||
class PDFSimpleFont : public PDFFont
|
class PDFSimpleFont : public PDFFont
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PDFSimpleFont(QByteArray name,
|
explicit PDFSimpleFont(FontDescriptor fontDescriptor,
|
||||||
|
QByteArray name,
|
||||||
QByteArray baseFont,
|
QByteArray baseFont,
|
||||||
PDFInteger firstChar,
|
PDFInteger firstChar,
|
||||||
PDFInteger lastChar,
|
PDFInteger lastChar,
|
||||||
@ -185,7 +231,8 @@ protected:
|
|||||||
class PDFType1Font : public PDFSimpleFont
|
class PDFType1Font : public PDFSimpleFont
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PDFType1Font(QByteArray name,
|
explicit PDFType1Font(FontDescriptor fontDescriptor,
|
||||||
|
QByteArray name,
|
||||||
QByteArray baseFont,
|
QByteArray baseFont,
|
||||||
PDFInteger firstChar,
|
PDFInteger firstChar,
|
||||||
PDFInteger lastChar,
|
PDFInteger lastChar,
|
||||||
|
@ -1564,12 +1564,11 @@ void PDFPageContentProcessor::operatorTextMoveByOffset(PDFReal t_x, PDFReal t_y)
|
|||||||
{
|
{
|
||||||
const QMatrix& textLineMatrix = m_graphicState.getTextLineMatrix();
|
const QMatrix& textLineMatrix = m_graphicState.getTextLineMatrix();
|
||||||
|
|
||||||
QMatrix translationMatrix;
|
QMatrix transformedMatrix = textLineMatrix;
|
||||||
translationMatrix.translate(t_x, t_y);
|
transformedMatrix.translate(t_x, t_y);
|
||||||
|
|
||||||
QMatrix resultMatrix = textLineMatrix * translationMatrix;
|
m_graphicState.setTextMatrix(transformedMatrix);
|
||||||
m_graphicState.setTextMatrix(resultMatrix);
|
m_graphicState.setTextLineMatrix(transformedMatrix);
|
||||||
m_graphicState.setTextLineMatrix(resultMatrix);
|
|
||||||
updateGraphicState();
|
updateGraphicState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1705,6 +1704,7 @@ void PDFPageContentProcessor::operatorTextSetSpacingAndShowText(PDFReal t_w, PDF
|
|||||||
|
|
||||||
void PDFPageContentProcessor::drawText(const TextSequence& textSequence)
|
void PDFPageContentProcessor::drawText(const TextSequence& textSequence)
|
||||||
{
|
{
|
||||||
|
// TODO: Kdyz nejsme v text rezimu, tak nekreslime text
|
||||||
if (textSequence.items.empty())
|
if (textSequence.items.empty())
|
||||||
{
|
{
|
||||||
// Do not display empty text
|
// Do not display empty text
|
||||||
@ -1748,6 +1748,7 @@ void PDFPageContentProcessor::drawText(const TextSequence& textSequence)
|
|||||||
const bool stroke = isTextRenderingModeStroked(textRenderingMode);
|
const bool stroke = isTextRenderingModeStroked(textRenderingMode);
|
||||||
const bool clipped = isTextRenderingModeClipped(textRenderingMode);
|
const bool clipped = isTextRenderingModeClipped(textRenderingMode);
|
||||||
// TODO: Add Text Clipping
|
// TODO: Add Text Clipping
|
||||||
|
// TODO: Pouzit pravdepodobne sirky z widths array?
|
||||||
|
|
||||||
// Detect horizontal writing system
|
// Detect horizontal writing system
|
||||||
const bool isHorizontalWritingSystem = std::any_of(advances.cbegin(), advances.cend(), [](const QPointF& point) { return !qFuzzyIsNull(point.x()); });
|
const bool isHorizontalWritingSystem = std::any_of(advances.cbegin(), advances.cend(), [](const QPointF& point) { return !qFuzzyIsNull(point.x()); });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user