Clean up som pdf code.
This commit is contained in:
parent
650cfa5c6f
commit
290b64e230
24 changed files with 264 additions and 256 deletions
|
@ -1,21 +1,21 @@
|
||||||
#include "Dictionary.h"
|
#include "Dictionary.h"
|
||||||
|
|
||||||
bool Dictionary::HasKey(const std::string& key) const
|
bool Dictionary::hasKey(const std::string& key) const
|
||||||
{
|
{
|
||||||
return HasStringKey(key) || HasDictKey(key);
|
return hasStringKey(key) || hasDictKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dictionary::HasStringKey(const std::string& key) const
|
bool Dictionary::hasStringKey(const std::string& key) const
|
||||||
{
|
{
|
||||||
return mStringData.count(key) > 0;
|
return mStringData.count(key) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dictionary::HasDictKey(const std::string& key) const
|
bool Dictionary::hasDictKey(const std::string& key) const
|
||||||
{
|
{
|
||||||
return mDictData.count(key) > 0;
|
return mDictData.count(key) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Dictionary::GetStringKeys() const
|
std::vector<std::string> Dictionary::getStringKeys() const
|
||||||
{
|
{
|
||||||
std::vector<std::string> keys;
|
std::vector<std::string> keys;
|
||||||
for (const auto& item : mStringData)
|
for (const auto& item : mStringData)
|
||||||
|
@ -25,7 +25,7 @@ std::vector<std::string> Dictionary::GetStringKeys() const
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Dictionary::GetDictKeys() const
|
std::vector<std::string> Dictionary::getDictKeys() const
|
||||||
{
|
{
|
||||||
std::vector<std::string> keys;
|
std::vector<std::string> keys;
|
||||||
for (const auto& item : mDictData)
|
for (const auto& item : mDictData)
|
||||||
|
@ -35,22 +35,22 @@ std::vector<std::string> Dictionary::GetDictKeys() const
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary* Dictionary::GetDict(const std::string& key) const
|
Dictionary* Dictionary::getDict(const std::string& key) const
|
||||||
{
|
{
|
||||||
return mDictData.at(key).get();
|
return mDictData.at(key).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Dictionary::GetItem(const std::string& key) const
|
std::string Dictionary::getItem(const std::string& key) const
|
||||||
{
|
{
|
||||||
return mStringData.at(key);
|
return mStringData.at(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dictionary::AddStringItem(const std::string& key, const std::string& item)
|
void Dictionary::addStringItem(const std::string& key, const std::string& item)
|
||||||
{
|
{
|
||||||
mStringData[key] = item;
|
mStringData[key] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dictionary::AddDictItem(const std::string& key, std::unique_ptr<Dictionary> dict)
|
void Dictionary::addDictItem(const std::string& key, std::unique_ptr<Dictionary> dict)
|
||||||
{
|
{
|
||||||
mDictData[key] = std::move(dict);
|
mDictData[key] = std::move(dict);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,24 +10,23 @@ public:
|
||||||
Dictionary() = default;
|
Dictionary() = default;
|
||||||
virtual ~Dictionary() = default;
|
virtual ~Dictionary() = default;
|
||||||
|
|
||||||
bool HasKey(const std::string& key) const;
|
void addStringItem(const std::string& key, const std::string& item);
|
||||||
|
|
||||||
bool HasStringKey(const std::string& key) const;
|
void addDictItem(const std::string& key, std::unique_ptr<Dictionary> dict);
|
||||||
|
|
||||||
bool HasDictKey(const std::string& key) const;
|
Dictionary* getDict(const std::string& key) const;
|
||||||
|
|
||||||
Dictionary* GetDict(const std::string& key) const;
|
std::vector<std::string> getDictKeys() const;
|
||||||
|
|
||||||
std::vector<std::string> GetDictKeys() const;
|
std::vector<std::string> getStringKeys() const;
|
||||||
|
|
||||||
std::vector<std::string> GetStringKeys() const;
|
std::string getItem(const std::string& key) const;
|
||||||
|
|
||||||
std::string GetItem(const std::string& key) const;
|
bool hasKey(const std::string& key) const;
|
||||||
|
|
||||||
void AddStringItem(const std::string& key, const std::string& item);
|
bool hasStringKey(const std::string& key) const;
|
||||||
|
|
||||||
void AddDictItem(const std::string& key, std::unique_ptr<Dictionary> dict);
|
|
||||||
|
|
||||||
|
bool hasDictKey(const std::string& key) const;
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
std::map<std::string, std::string> mStringData;
|
std::map<std::string, std::string> mStringData;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "PdfDictionary.h"
|
#include "PdfDictionary.h"
|
||||||
|
|
||||||
std::string PdfDictionary::ToString() const
|
std::string PdfDictionary::toString() const
|
||||||
{
|
{
|
||||||
const auto keys = GetStringKeys();
|
const auto keys = getStringKeys();
|
||||||
if (keys.empty())
|
if (keys.empty())
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
|
@ -15,28 +15,28 @@ std::string PdfDictionary::ToString() const
|
||||||
{
|
{
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
content += " /" + key + " " + GetItem(key) + ending;
|
content += " /" + key + " " + getItem(key) + ending;
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
content += " /" + key + " " + GetItem(key) + ending;
|
content += " /" + key + " " + getItem(key) + ending;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto dictKeys = GetDictKeys();
|
const auto dictKeys = getDictKeys();
|
||||||
ending = dictKeys.size() == 1 ? "" : "\n";
|
ending = dictKeys.size() == 1 ? "" : "\n";
|
||||||
for (const auto& key : GetDictKeys())
|
for (const auto& key : getDictKeys())
|
||||||
{
|
{
|
||||||
auto pdfDict = dynamic_cast<PdfDictionary*>(GetDict(key));
|
auto pdfDict = dynamic_cast<PdfDictionary*>(getDict(key));
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
content += " /" + key + " " + pdfDict->ToString() + ending;
|
content += " /" + key + " " + pdfDict->toString() + ending;
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
content += " /" + key + " " + pdfDict->ToString() + ending;
|
content += " /" + key + " " + pdfDict->toString() + ending;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,5 @@
|
||||||
class PdfDictionary : public Dictionary
|
class PdfDictionary : public Dictionary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
std::string toString() const;
|
||||||
std::string ToString() const;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "PdfOutline.h"
|
#include "PdfOutline.h"
|
||||||
#include "PdfXRefTable.h"
|
#include "PdfXRefTable.h"
|
||||||
|
|
||||||
|
#include "StringUtils.h"
|
||||||
|
|
||||||
PdfDocument::PdfDocument()
|
PdfDocument::PdfDocument()
|
||||||
{
|
{
|
||||||
mXRefTable = std::make_unique<PdfXRefTable>();
|
mXRefTable = std::make_unique<PdfXRefTable>();
|
||||||
|
@ -18,56 +20,56 @@ PdfDocument::~PdfDocument()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfDocument::ToString()
|
std::string PdfDocument::toString()
|
||||||
{
|
{
|
||||||
IndexObjects();
|
indexObjects();
|
||||||
auto content = GetHeaderString();
|
auto content = getHeaderString();
|
||||||
content += GetBodyString();
|
content += getBodyString();
|
||||||
|
|
||||||
content += GetXRefString();
|
content += getXRefString();
|
||||||
|
|
||||||
content += GetTrailerString();
|
content += getTrailerString();
|
||||||
|
|
||||||
content += "%%EOF\n";
|
content += "%%EOF\n";
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfDocument::GetHeaderString()
|
std::string PdfDocument::getHeaderString()
|
||||||
{
|
{
|
||||||
auto content = "%PDF-" + mVersion + "\n";
|
auto content = "%PDF-" + mVersion + "\n";
|
||||||
mXRefOffset = content.size();
|
mXRefOffset = content.size();
|
||||||
mXRefTable->AddRecord(content.size(), 65535, true);
|
mXRefTable->addRecord(content.size(), 65535, true);
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfDocument::GetBodyString()
|
std::string PdfDocument::getBodyString()
|
||||||
{
|
{
|
||||||
const auto content = mCatalog->ToString(mXRefTable.get());
|
const auto content = mCatalog->toString(mXRefTable.get());
|
||||||
mXRefOffset += content.size();
|
mXRefOffset += content.size();
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfDocument::GetXRefString()
|
std::string PdfDocument::getXRefString()
|
||||||
{
|
{
|
||||||
return mXRefTable->ToString();
|
return mXRefTable->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfDocument::GetTrailerString()
|
std::string PdfDocument::getTrailerString()
|
||||||
{
|
{
|
||||||
const auto numObjects = mXRefTable->GetNumEntries();
|
const auto numObjects = mXRefTable->getNumEntries();
|
||||||
mTrailer.AddStringItem("Size", std::to_string(numObjects));
|
mTrailer.addStringItem("Size", std::to_string(numObjects));
|
||||||
mTrailer.AddStringItem("Root", mCatalog->GetRefString());
|
mTrailer.addStringItem("Root", mCatalog->getRefString());
|
||||||
|
|
||||||
std::string content = "trailer\n";
|
std::string content = "trailer\n";
|
||||||
content += mTrailer.ToString();
|
content += mTrailer.toString();
|
||||||
|
|
||||||
content += "startxref\n";
|
content += "startxref\n";
|
||||||
content += std::to_string(mXRefOffset) + "\n";
|
content += std::to_string(mXRefOffset) + "\n";
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfDocument::IndexObjects()
|
void PdfDocument::indexObjects()
|
||||||
{
|
{
|
||||||
mCatalog->IndexObjects(0);
|
mCatalog->indexObjects(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "PdfDictionary.h"
|
#include "PdfDictionary.h"
|
||||||
#include "StringUtils.h"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -15,26 +14,25 @@ using PdfXRefTablePtr = std::unique_ptr<PdfXRefTable>;
|
||||||
|
|
||||||
class PdfDocument
|
class PdfDocument
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PdfDocument();
|
PdfDocument();
|
||||||
~PdfDocument();
|
~PdfDocument();
|
||||||
|
|
||||||
std::string ToString();
|
std::string toString();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string GetHeaderString();
|
std::string getHeaderString();
|
||||||
|
|
||||||
std::string GetTrailerString();
|
std::string getTrailerString();
|
||||||
|
|
||||||
std::string GetBodyString();
|
std::string getBodyString();
|
||||||
|
|
||||||
std::string GetXRefString();
|
std::string getXRefString();
|
||||||
|
|
||||||
void IndexObjects();
|
void indexObjects();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PdfDictionary mTrailer;
|
PdfDictionary mTrailer;
|
||||||
|
|
||||||
std::string mVersion {"1.7"};
|
std::string mVersion {"1.7"};
|
||||||
PdfXRefTablePtr mXRefTable;
|
PdfXRefTablePtr mXRefTable;
|
||||||
unsigned mXRefOffset{0};
|
unsigned mXRefOffset{0};
|
||||||
|
|
|
@ -12,33 +12,33 @@ PdfDocumentCatalog::PdfDocumentCatalog()
|
||||||
mPages = std::make_unique<PdfPageTree>();
|
mPages = std::make_unique<PdfPageTree>();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PdfDocumentCatalog::IndexObjects(unsigned count)
|
unsigned PdfDocumentCatalog::indexObjects(unsigned count)
|
||||||
{
|
{
|
||||||
auto newCount = count + 1;
|
auto newCount = count + 1;
|
||||||
mObjectNumber = newCount;
|
mObjectNumber = newCount;
|
||||||
auto objectCount = mOutlines->IndexObjects(mObjectNumber);
|
auto objectCount = mOutlines->indexObjects(mObjectNumber);
|
||||||
objectCount = mPages->IndexObjects(objectCount);
|
objectCount = mPages->indexObjects(objectCount);
|
||||||
return objectCount;
|
return objectCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfDocumentCatalog::ToString(PdfXRefTable* xRefTable)
|
std::string PdfDocumentCatalog::toString(PdfXRefTable* xRefTable)
|
||||||
{
|
{
|
||||||
UpdateDictionary();
|
updateDictionary();
|
||||||
auto content = GetStringPrefix();
|
auto content = getStringPrefix();
|
||||||
content += mDictionary.ToString();
|
content += mDictionary.toString();
|
||||||
content += GetStringSuffix();
|
content += getStringSuffix();
|
||||||
xRefTable->AddRecord(content.size(), mGenerationNumber, mIsFree);
|
xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);
|
||||||
|
|
||||||
content += mOutlines->ToString(xRefTable);
|
content += mOutlines->toString(xRefTable);
|
||||||
|
|
||||||
content += mPages->ToString(xRefTable);
|
content += mPages->toString(xRefTable);
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfDocumentCatalog::UpdateDictionary()
|
void PdfDocumentCatalog::updateDictionary()
|
||||||
{
|
{
|
||||||
mDictionary.AddStringItem("Type", "/Catalog");
|
mDictionary.addStringItem("Type", "/Catalog");
|
||||||
mDictionary.AddStringItem("Outlines", mOutlines->GetRefString());
|
mDictionary.addStringItem("Outlines", mOutlines->getRefString());
|
||||||
mDictionary.AddStringItem("Pages", mPages->GetRefString());
|
mDictionary.addStringItem("Pages", mPages->getRefString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,14 @@ class PdfOutlineCollection;
|
||||||
class PdfDocumentCatalog : public PdfObject
|
class PdfDocumentCatalog : public PdfObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PdfDocumentCatalog();
|
PdfDocumentCatalog();
|
||||||
|
|
||||||
unsigned IndexObjects(unsigned count) override;
|
unsigned indexObjects(unsigned count) override;
|
||||||
|
|
||||||
std::string ToString(PdfXRefTable* xRefTable) override;
|
std::string toString(PdfXRefTable* xRefTable) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateDictionary() override;
|
void updateDictionary() override;
|
||||||
|
|
||||||
std::unique_ptr<PdfOutlineCollection> mOutlines;
|
std::unique_ptr<PdfOutlineCollection> mOutlines;
|
||||||
std::unique_ptr<PdfPageTree> mPages;
|
std::unique_ptr<PdfPageTree> mPages;
|
||||||
|
|
|
@ -3,56 +3,56 @@
|
||||||
#include "PdfDictionary.h"
|
#include "PdfDictionary.h"
|
||||||
#include "PdfXRefTable.h"
|
#include "PdfXRefTable.h"
|
||||||
|
|
||||||
std::string PdfObject::ToString(PdfXRefTable* xRefTable)
|
std::string PdfObject::toString(PdfXRefTable* xRefTable)
|
||||||
{
|
{
|
||||||
UpdateDictionary();
|
updateDictionary();
|
||||||
|
|
||||||
auto content = GetStringPrefix();
|
auto content = getStringPrefix();
|
||||||
content += mDictionary.ToString();
|
content += mDictionary.toString();
|
||||||
content += GetStringSuffix();
|
content += getStringSuffix();
|
||||||
|
|
||||||
xRefTable->AddRecord(content.size(), mGenerationNumber, mIsFree);
|
xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfObject::UpdateDictionary()
|
void PdfObject::updateDictionary()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfObject::GetStringSuffix() const
|
std::string PdfObject::getStringSuffix() const
|
||||||
{
|
{
|
||||||
return "endobj\n\n";
|
return "endobj\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PdfObject::IndexObjects(unsigned count)
|
unsigned PdfObject::indexObjects(unsigned count)
|
||||||
{
|
{
|
||||||
const auto newCount = count + 1;
|
const auto newCount = count + 1;
|
||||||
mObjectNumber = newCount;
|
mObjectNumber = newCount;
|
||||||
return newCount;
|
return newCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfObject::SetObjectNumber(unsigned num)
|
void PdfObject::setObjectNumber(unsigned num)
|
||||||
{
|
{
|
||||||
mObjectNumber = num;
|
mObjectNumber = num;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfObject::SetGenerationNumber(unsigned num)
|
void PdfObject::setGenerationNumber(unsigned num)
|
||||||
{
|
{
|
||||||
mGenerationNumber = num;
|
mGenerationNumber = num;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfObject::GetStringPrefix() const
|
std::string PdfObject::getStringPrefix() const
|
||||||
{
|
{
|
||||||
return std::to_string(mObjectNumber) + " " + std::to_string(mGenerationNumber) + " obj\n";
|
return std::to_string(mObjectNumber) + " " + std::to_string(mGenerationNumber) + " obj\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfObject::GetRefString() const
|
std::string PdfObject::getRefString() const
|
||||||
{
|
{
|
||||||
return std::to_string(mObjectNumber) + " " + std::to_string(mGenerationNumber) + " R";
|
return std::to_string(mObjectNumber) + " " + std::to_string(mGenerationNumber) + " R";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PdfObject::IsFree() const
|
bool PdfObject::isFree() const
|
||||||
{
|
{
|
||||||
return mIsFree;
|
return mIsFree;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,25 +12,24 @@ class PdfObject
|
||||||
public:
|
public:
|
||||||
virtual ~PdfObject() = default;
|
virtual ~PdfObject() = default;
|
||||||
|
|
||||||
std::string GetStringPrefix() const;
|
std::string getStringPrefix() const;
|
||||||
|
|
||||||
std::string GetStringSuffix() const;
|
std::string getStringSuffix() const;
|
||||||
|
|
||||||
std::string GetRefString() const;
|
std::string getRefString() const;
|
||||||
|
|
||||||
virtual unsigned IndexObjects(unsigned count);
|
virtual unsigned indexObjects(unsigned count);
|
||||||
|
|
||||||
bool IsFree() const;
|
bool isFree() const;
|
||||||
|
|
||||||
virtual std::string ToString(PdfXRefTable* xRefTable);
|
virtual std::string toString(PdfXRefTable* xRefTable);
|
||||||
|
|
||||||
void SetObjectNumber(unsigned num);
|
void setObjectNumber(unsigned num);
|
||||||
|
|
||||||
void SetGenerationNumber(unsigned num);
|
void setGenerationNumber(unsigned num);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void updateDictionary();
|
||||||
virtual void UpdateDictionary();
|
|
||||||
|
|
||||||
unsigned mObjectNumber{0};
|
unsigned mObjectNumber{0};
|
||||||
unsigned mGenerationNumber{0};
|
unsigned mGenerationNumber{0};
|
||||||
|
|
|
@ -2,39 +2,39 @@
|
||||||
|
|
||||||
#include "PdfXRefTable.h"
|
#include "PdfXRefTable.h"
|
||||||
|
|
||||||
std::string PdfOutline::ToString(PdfXRefTable* xRefTable)
|
std::string PdfOutline::toString(PdfXRefTable* xRefTable)
|
||||||
{
|
{
|
||||||
mDictionary.AddStringItem("Type", "/Outline");
|
mDictionary.addStringItem("Type", "/Outline");
|
||||||
auto content = GetStringPrefix();
|
auto content = getStringPrefix();
|
||||||
content += mDictionary.ToString();
|
content += mDictionary.toString();
|
||||||
content += GetStringSuffix();
|
content += getStringSuffix();
|
||||||
xRefTable->AddRecord(content.size(), mGenerationNumber, mIsFree);
|
xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PdfOutlineCollection::IndexObjects(unsigned count)
|
unsigned PdfOutlineCollection::indexObjects(unsigned count)
|
||||||
{
|
{
|
||||||
auto newCount = count + 1;
|
auto newCount = count + 1;
|
||||||
mObjectNumber = newCount;
|
mObjectNumber = newCount;
|
||||||
for (const auto& outline : mOutlines)
|
for (const auto& outline : mOutlines)
|
||||||
{
|
{
|
||||||
newCount = outline->IndexObjects(newCount);
|
newCount = outline->indexObjects(newCount);
|
||||||
}
|
}
|
||||||
return newCount;
|
return newCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfOutlineCollection::ToString(PdfXRefTable* xRefTable)
|
std::string PdfOutlineCollection::toString(PdfXRefTable* xRefTable)
|
||||||
{
|
{
|
||||||
UpdateDictionary();
|
updateDictionary();
|
||||||
std::string content = GetStringPrefix();
|
std::string content = getStringPrefix();
|
||||||
content += mDictionary.ToString();
|
content += mDictionary.toString();
|
||||||
content += GetStringSuffix();
|
content += getStringSuffix();
|
||||||
xRefTable->AddRecord(content.size(), mGenerationNumber, mIsFree);
|
xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfOutlineCollection::UpdateDictionary()
|
void PdfOutlineCollection::updateDictionary()
|
||||||
{
|
{
|
||||||
mDictionary.AddStringItem("Type", "/Outlines");
|
mDictionary.addStringItem("Type", "/Outlines");
|
||||||
mDictionary.AddStringItem("Count", std::to_string(mOutlines.size()));
|
mDictionary.addStringItem("Count", std::to_string(mOutlines.size()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
class PdfOutline : public PdfObject
|
class PdfOutline : public PdfObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string ToString(PdfXRefTable* xRefTable) override;
|
std::string toString(PdfXRefTable* xRefTable) override;
|
||||||
};
|
};
|
||||||
using PdfOutlinePtr = std::unique_ptr<PdfOutline>;
|
using PdfOutlinePtr = std::unique_ptr<PdfOutline>;
|
||||||
|
|
||||||
|
@ -15,11 +15,11 @@ class PdfOutlineCollection : public PdfObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
unsigned IndexObjects(unsigned count) override;
|
unsigned indexObjects(unsigned count) override;
|
||||||
|
|
||||||
std::string ToString(PdfXRefTable* xRefTable) override;
|
std::string toString(PdfXRefTable* xRefTable) override;
|
||||||
|
|
||||||
void UpdateDictionary();
|
void updateDictionary();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<PdfOutlinePtr> mOutlines;
|
std::vector<PdfOutlinePtr> mOutlines;
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
#include "PdfPage.h"
|
||||||
|
|
||||||
|
#include "PdfObject.h"
|
||||||
|
#include "PdfStream.h"
|
||||||
|
#include "PdfXRefTable.h"
|
||||||
|
#include "PdfPageTree.h"
|
||||||
|
|
||||||
|
std::string PdfProcSet::toString(PdfXRefTable* xRefTable)
|
||||||
|
{
|
||||||
|
updateDictionary();
|
||||||
|
auto content = getStringPrefix();
|
||||||
|
content += mDictionary.toString();
|
||||||
|
content += "[/PDF]\n";
|
||||||
|
content += getStringSuffix();
|
||||||
|
xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PdfFont::toString(PdfXRefTable* xRefTable)
|
||||||
|
{
|
||||||
|
updateDictionary();
|
||||||
|
auto content = getStringPrefix();
|
||||||
|
content += mDictionary.toString();
|
||||||
|
content += getStringSuffix();
|
||||||
|
xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PdfFont::updateDictionary()
|
||||||
|
{
|
||||||
|
mDictionary.addStringItem("Type", "/Font");
|
||||||
|
mDictionary.addStringItem("Subtype", "/Type1");
|
||||||
|
mDictionary.addStringItem("Name", "/F1");
|
||||||
|
mDictionary.addStringItem("BaseFont", "/Helvetica");
|
||||||
|
mDictionary.addStringItem("Encoding", "/MacRomanEncoding");
|
||||||
|
}
|
||||||
|
|
||||||
|
PdfPage::PdfPage(PdfPageTree* parent)
|
||||||
|
: mParent(parent)
|
||||||
|
{
|
||||||
|
mContent = std::make_unique<PdfStream>();
|
||||||
|
|
||||||
|
std::string pageContent = "BT\n";
|
||||||
|
pageContent += "/F1 24 Tf\n";
|
||||||
|
pageContent += "100 100 Td\n";
|
||||||
|
pageContent += "(Hello World) Tj\n";
|
||||||
|
pageContent += "ET";
|
||||||
|
|
||||||
|
mContent->setContent(pageContent);
|
||||||
|
mProcSet = std::make_unique<PdfProcSet>();
|
||||||
|
|
||||||
|
mDefaultFont = std::make_unique<PdfFont>();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned PdfPage::indexObjects(unsigned count)
|
||||||
|
{
|
||||||
|
auto newCount = count + 1;
|
||||||
|
mObjectNumber = newCount;
|
||||||
|
newCount = mContent->indexObjects(newCount);
|
||||||
|
newCount = mProcSet->indexObjects(newCount);
|
||||||
|
newCount = mDefaultFont->indexObjects(newCount);
|
||||||
|
return newCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PdfPage::toString(PdfXRefTable* xRefTable)
|
||||||
|
{
|
||||||
|
updateDictionary();
|
||||||
|
auto content = getStringPrefix();
|
||||||
|
content += mDictionary.toString();
|
||||||
|
content += getStringSuffix();
|
||||||
|
xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);
|
||||||
|
|
||||||
|
content += mContent->toString(xRefTable);
|
||||||
|
content += mProcSet->toString(xRefTable);
|
||||||
|
content += mDefaultFont->toString(xRefTable);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PdfPage::updateDictionary()
|
||||||
|
{
|
||||||
|
std::string mediaBox = "[0 0 " + std::to_string(mWidth) + " " + std::to_string(mHeight) + "]";
|
||||||
|
mDictionary.addStringItem("Type", "/Page");
|
||||||
|
mDictionary.addStringItem("MediaBox", mediaBox);
|
||||||
|
mDictionary.addStringItem("Parent", mParent->getRefString());
|
||||||
|
mDictionary.addStringItem("Contents", mContent->getRefString());
|
||||||
|
|
||||||
|
auto resourcesDict = std::make_unique<PdfDictionary>();
|
||||||
|
resourcesDict->addStringItem("ProcSet", mProcSet->getRefString());
|
||||||
|
|
||||||
|
auto fontDict = std::make_unique<PdfDictionary>();
|
||||||
|
fontDict->addStringItem("F1", mDefaultFont->getRefString());
|
||||||
|
resourcesDict->addDictItem("Font", std::move(fontDict));
|
||||||
|
|
||||||
|
mDictionary.addDictItem("Resources", std::move(resourcesDict));
|
||||||
|
}
|
|
@ -9,106 +9,27 @@ class PdfPageTree;
|
||||||
class PdfProcSet : public PdfObject
|
class PdfProcSet : public PdfObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string ToString(PdfXRefTable* xRefTable) override
|
std::string toString(PdfXRefTable* xRefTable) override;
|
||||||
{
|
|
||||||
UpdateDictionary();
|
|
||||||
auto content = GetStringPrefix();
|
|
||||||
content += mDictionary.ToString();
|
|
||||||
content += "[/PDF]\n";
|
|
||||||
content += GetStringSuffix();
|
|
||||||
xRefTable->AddRecord(content.size(), mGenerationNumber, mIsFree);
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PdfFont : public PdfObject
|
class PdfFont : public PdfObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string ToString(PdfXRefTable* xRefTable) override
|
std::string toString(PdfXRefTable* xRefTable) override;
|
||||||
{
|
|
||||||
UpdateDictionary();
|
|
||||||
auto content = GetStringPrefix();
|
|
||||||
content += mDictionary.ToString();
|
|
||||||
content += GetStringSuffix();
|
|
||||||
xRefTable->AddRecord(content.size(), mGenerationNumber, mIsFree);
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateDictionary()
|
void updateDictionary();
|
||||||
{
|
|
||||||
mDictionary.AddStringItem("Type", "/Font");
|
|
||||||
mDictionary.AddStringItem("Subtype", "/Type1");
|
|
||||||
mDictionary.AddStringItem("Name", "/F1");
|
|
||||||
mDictionary.AddStringItem("BaseFont", "/Helvetica");
|
|
||||||
mDictionary.AddStringItem("Encoding", "/MacRomanEncoding");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PdfPage : public PdfObject
|
class PdfPage : public PdfObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PdfPage(PdfPageTree* parent)
|
PdfPage(PdfPageTree* parent);
|
||||||
: mParent(parent)
|
|
||||||
{
|
|
||||||
mContent = std::make_unique<PdfStream>();
|
|
||||||
|
|
||||||
std::string pageContent = "BT\n";
|
unsigned indexObjects(unsigned count);
|
||||||
pageContent += "/F1 24 Tf\n";
|
|
||||||
pageContent += "100 100 Td\n";
|
|
||||||
pageContent += "(Hello World) Tj\n";
|
|
||||||
pageContent += "ET";
|
|
||||||
|
|
||||||
mContent->SetContent(pageContent);
|
std::string toString(PdfXRefTable* xRefTable) override;
|
||||||
mProcSet = std::make_unique<PdfProcSet>();
|
|
||||||
|
|
||||||
mDefaultFont = std::make_unique<PdfFont>();
|
void updateDictionary();
|
||||||
}
|
|
||||||
|
|
||||||
unsigned IndexObjects(unsigned count)
|
|
||||||
{
|
|
||||||
auto newCount = count + 1;
|
|
||||||
mObjectNumber = newCount;
|
|
||||||
newCount = mContent->IndexObjects(newCount);
|
|
||||||
newCount = mProcSet->IndexObjects(newCount);
|
|
||||||
newCount = mDefaultFont->IndexObjects(newCount);
|
|
||||||
return newCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToString(PdfXRefTable* xRefTable) override
|
|
||||||
{
|
|
||||||
UpdateDictionary();
|
|
||||||
auto content = GetStringPrefix();
|
|
||||||
content += mDictionary.ToString();
|
|
||||||
content += GetStringSuffix();
|
|
||||||
xRefTable->AddRecord(content.size(), mGenerationNumber, mIsFree);
|
|
||||||
|
|
||||||
content += mContent->ToString(xRefTable);
|
|
||||||
|
|
||||||
content += mProcSet->ToString(xRefTable);
|
|
||||||
|
|
||||||
content += mDefaultFont->ToString(xRefTable);
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateDictionary()
|
|
||||||
{
|
|
||||||
std::string mediaBox = "[0 0 " + std::to_string(mWidth) + " " + std::to_string(mHeight) + "]";
|
|
||||||
mDictionary.AddStringItem("Type", "/Page");
|
|
||||||
mDictionary.AddStringItem("MediaBox", mediaBox);
|
|
||||||
mDictionary.AddStringItem("Parent", mParent->GetRefString());
|
|
||||||
mDictionary.AddStringItem("Contents", mContent->GetRefString());
|
|
||||||
|
|
||||||
auto resourcesDict = std::make_unique<PdfDictionary>();
|
|
||||||
resourcesDict->AddStringItem("ProcSet", mProcSet->GetRefString());
|
|
||||||
|
|
||||||
auto fontDict = std::make_unique<PdfDictionary>();
|
|
||||||
fontDict->AddStringItem("F1", mDefaultFont->GetRefString());
|
|
||||||
resourcesDict->AddDictItem("Font", std::move(fontDict));
|
|
||||||
|
|
||||||
mDictionary.AddDictItem("Resources", std::move(resourcesDict));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned mWidth{612};
|
unsigned mWidth{612};
|
||||||
|
|
|
@ -8,30 +8,30 @@ PdfPageTree::PdfPageTree()
|
||||||
mRootPage = std::make_unique<PdfPage>(this);
|
mRootPage = std::make_unique<PdfPage>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PdfPageTree::IndexObjects(unsigned count)
|
unsigned PdfPageTree::indexObjects(unsigned count)
|
||||||
{
|
{
|
||||||
auto newCount = count + 1;
|
auto newCount = count + 1;
|
||||||
mObjectNumber = newCount;
|
mObjectNumber = newCount;
|
||||||
newCount = mRootPage->IndexObjects(newCount);
|
newCount = mRootPage->indexObjects(newCount);
|
||||||
return newCount;
|
return newCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfPageTree::ToString(PdfXRefTable* xRefTable)
|
std::string PdfPageTree::toString(PdfXRefTable* xRefTable)
|
||||||
{
|
{
|
||||||
UpdateDictionary();
|
updateDictionary();
|
||||||
std::string content = GetStringPrefix();
|
std::string content = getStringPrefix();
|
||||||
content += mDictionary.ToString();
|
content += mDictionary.toString();
|
||||||
content += GetStringSuffix();
|
content += getStringSuffix();
|
||||||
xRefTable->AddRecord(content.size(), mGenerationNumber, mIsFree);
|
xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);
|
||||||
|
|
||||||
content += mRootPage->ToString(xRefTable);
|
content += mRootPage->toString(xRefTable);
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfPageTree::UpdateDictionary()
|
void PdfPageTree::updateDictionary()
|
||||||
{
|
{
|
||||||
mDictionary.AddStringItem("Type", "/Pages");
|
mDictionary.addStringItem("Type", "/Pages");
|
||||||
std::string kids = "[" + mRootPage->GetRefString() + "]";
|
std::string kids = "[" + mRootPage->getRefString() + "]";
|
||||||
mDictionary.AddStringItem("Kids", kids);
|
mDictionary.addStringItem("Kids", kids);
|
||||||
mDictionary.AddStringItem("Count", "1");
|
mDictionary.addStringItem("Count", "1");
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,13 @@ using PdfPagePtr = std::unique_ptr<PdfPage>;
|
||||||
class PdfPageTree : public PdfObject
|
class PdfPageTree : public PdfObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PdfPageTree();
|
PdfPageTree();
|
||||||
|
|
||||||
unsigned IndexObjects(unsigned count) override;
|
unsigned indexObjects(unsigned count) override;
|
||||||
|
|
||||||
std::string ToString(PdfXRefTable* xRefTable) override;
|
std::string toString(PdfXRefTable* xRefTable) override;
|
||||||
|
|
||||||
void UpdateDictionary() override;
|
void updateDictionary() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -5,32 +5,32 @@
|
||||||
|
|
||||||
PdfStream::PdfStream()
|
PdfStream::PdfStream()
|
||||||
{
|
{
|
||||||
mDictionary.AddStringItem("Length", "0");
|
mDictionary.addStringItem("Length", "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfStream::SetContent(const std::string& content)
|
void PdfStream::setContent(const std::string& content)
|
||||||
{
|
{
|
||||||
mContent = content;
|
mContent = content;
|
||||||
Update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfStream::Update()
|
void PdfStream::update()
|
||||||
{
|
{
|
||||||
auto length = mContent.size();
|
auto length = mContent.size();
|
||||||
mDictionary.AddStringItem("Length", std::to_string(length));
|
mDictionary.addStringItem("Length", std::to_string(length));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfStream::ToString(PdfXRefTable* xRefTable)
|
std::string PdfStream::toString(PdfXRefTable* xRefTable)
|
||||||
{
|
{
|
||||||
std::string content = GetStringPrefix();
|
std::string content = getStringPrefix();
|
||||||
|
|
||||||
content += mDictionary.ToString();
|
content += mDictionary.toString();
|
||||||
|
|
||||||
content += "stream\n";
|
content += "stream\n";
|
||||||
content += mContent;
|
content += mContent;
|
||||||
content += "\nendstream\n";
|
content += "\nendstream\n";
|
||||||
content += "endobj\n\n";
|
content += "endobj\n\n";
|
||||||
|
|
||||||
xRefTable->AddRecord(content.size(), mGenerationNumber, mIsFree);
|
xRefTable->addRecord(content.size(), mGenerationNumber, mIsFree);
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,13 @@
|
||||||
class PdfStream : public PdfObject
|
class PdfStream : public PdfObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PdfStream();
|
PdfStream();
|
||||||
|
|
||||||
void Update();
|
void update();
|
||||||
|
|
||||||
void SetContent(const std::string& content);
|
void setContent(const std::string& content);
|
||||||
|
|
||||||
std::string ToString(PdfXRefTable* xRefTable) override;
|
std::string toString(PdfXRefTable* xRefTable) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mContent;
|
std::string mContent;
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
#include "PdfDocument.h"
|
#include "PdfDocument.h"
|
||||||
|
|
||||||
std::string PdfWriter::ToString(const std::unique_ptr<PdfDocument>& document) const
|
std::string PdfWriter::toString(PdfDocument* document) const
|
||||||
{
|
{
|
||||||
std::string content;
|
std::string content;
|
||||||
|
|
||||||
content += document->ToString();
|
content += document->toString();
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,5 +9,5 @@ class PdfWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
std::string ToString(const std::unique_ptr<PdfDocument>& document) const;
|
std::string toString(PdfDocument* document) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,7 +7,7 @@ PdfXRefTable::PdfXRefTable()
|
||||||
mSections.push_back(TableSubSection());
|
mSections.push_back(TableSubSection());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PdfXRefTable::ToString()
|
std::string PdfXRefTable::toString()
|
||||||
{
|
{
|
||||||
std::string content;
|
std::string content;
|
||||||
for (const auto& section : mSections)
|
for (const auto& section : mSections)
|
||||||
|
@ -27,7 +27,7 @@ std::string PdfXRefTable::ToString()
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PdfXRefTable::GetNextOffset()
|
unsigned PdfXRefTable::getNextOffset()
|
||||||
{
|
{
|
||||||
auto lastNumRecords = mSections[mSections.size() - 1].mRecords.size();
|
auto lastNumRecords = mSections[mSections.size() - 1].mRecords.size();
|
||||||
if (lastNumRecords > 0)
|
if (lastNumRecords > 0)
|
||||||
|
@ -45,18 +45,18 @@ unsigned PdfXRefTable::GetNextOffset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PdfXRefTable::AddRecord(unsigned numBytes, unsigned generation, unsigned isFree)
|
void PdfXRefTable::addRecord(unsigned numBytes, unsigned generation, unsigned isFree)
|
||||||
{
|
{
|
||||||
XRefRecord record;
|
XRefRecord record;
|
||||||
|
|
||||||
record.mOffsetBytes = GetNextOffset();
|
record.mOffsetBytes = getNextOffset();
|
||||||
record.mGenerationNumber = generation;
|
record.mGenerationNumber = generation;
|
||||||
record.mIsFree = isFree;
|
record.mIsFree = isFree;
|
||||||
mSections[mSections.size()-1].mRecords.push_back(record);
|
mSections[mSections.size()-1].mRecords.push_back(record);
|
||||||
mLastAddedBytes = numBytes;
|
mLastAddedBytes = numBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PdfXRefTable::GetNumEntries()
|
unsigned PdfXRefTable::getNumEntries()
|
||||||
{
|
{
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
for (const auto& section : mSections)
|
for (const auto& section : mSections)
|
||||||
|
|
|
@ -20,16 +20,15 @@ struct TableSubSection
|
||||||
class PdfXRefTable
|
class PdfXRefTable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PdfXRefTable();
|
PdfXRefTable();
|
||||||
|
|
||||||
std::string ToString();
|
std::string toString();
|
||||||
|
|
||||||
unsigned GetNextOffset();
|
unsigned getNextOffset();
|
||||||
|
|
||||||
void AddRecord(unsigned numBytes, unsigned generation, unsigned isFree);
|
void addRecord(unsigned numBytes, unsigned generation, unsigned isFree);
|
||||||
|
|
||||||
unsigned GetNumEntries();
|
unsigned getNumEntries();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned mLastAddedBytes{0};
|
unsigned mLastAddedBytes{0};
|
||||||
|
|
|
@ -11,7 +11,7 @@ TEST_CASE(TestDocumentConverterMarkdownToPdf, "publishing")
|
||||||
auto document = std::make_unique<PdfDocument>();
|
auto document = std::make_unique<PdfDocument>();
|
||||||
|
|
||||||
PdfWriter writer;
|
PdfWriter writer;
|
||||||
const auto output = writer.ToString(document);
|
const auto output = writer.toString(document.get());
|
||||||
|
|
||||||
File pdf_file(TestUtils::getTestOutputDir() / "TestDocumentConverterMarkdownToPdf.pdf");
|
File pdf_file(TestUtils::getTestOutputDir() / "TestDocumentConverterMarkdownToPdf.pdf");
|
||||||
pdf_file.open(File::AccessMode::Write);
|
pdf_file.open(File::AccessMode::Write);
|
||||||
|
|
|
@ -11,9 +11,8 @@ TEST_CASE(TestPdfWriter, "publishing")
|
||||||
auto document = std::make_unique<PdfDocument>();
|
auto document = std::make_unique<PdfDocument>();
|
||||||
|
|
||||||
PdfWriter writer;
|
PdfWriter writer;
|
||||||
const auto output = writer.ToString(document);
|
const auto output = writer.toString(document.get());
|
||||||
|
|
||||||
File pdf_file(TestUtils::getTestOutputDir() / "TestPdfWriter.pdf");
|
File pdf_file(TestUtils::getTestOutputDir() / "TestPdfWriter.pdf");
|
||||||
pdf_file.open(File::AccessMode::Write);
|
|
||||||
pdf_file.writeText(output);
|
pdf_file.writeText(output);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue