Compare commits

..

4 Commits

Author SHA1 Message Date
da34674edc Fix more 2026-05-26 19:23:01 +03:00
377d66307e Fix for 4bytes wchars 2026-05-26 19:05:50 +03:00
e6c9415a26 Fix sdkjs building for x2t test example 2026-05-26 15:03:42 +03:00
cb3daf1b6a for bug #38234 2026-05-26 12:46:12 +03:00
19 changed files with 1733 additions and 1659 deletions

View File

@ -814,22 +814,7 @@ namespace XmlUtils
codepoint = w1;
}
#else
{
unsigned int w1 = static_cast<unsigned int>(data[pos]);
if (w1 >= 0xD800 && w1 <= 0xDBFF && pos + 1 < data.size())
{
unsigned int w2 = static_cast<unsigned int>(data[pos + 1]);
if (w2 >= 0xDC00 && w2 <= 0xDFFF)
{
codepoint = 0x10000 + ((w1 - 0xD800) << 10) + (w2 - 0xDC00);
consumed = 2;
}
else
codepoint = w1;
}
else
codepoint = w1;
}
codepoint = static_cast<unsigned int>(data[pos]);
#endif
if (IsUnicodeSymbol(codepoint))

View File

@ -327,6 +327,53 @@ template<typename T> int Binary_CommonReader2::ReadTrackRevision2(long length, T
READ1_DEF(length, res, this->ReadTrackRevisionInner2, poResult);
return res;
}
int Binary_CommonReader2::ReadEastAsianLayout(BYTE type, long length, void* poResult)
{
if (length < 0)
return 0;
int res = c_oSerConstants::ReadOk;
ComplexTypes::Word::CEastAsianLayout* pEastAsianLayout = static_cast<ComplexTypes::Word::CEastAsianLayout*>(poResult);
if (!pEastAsianLayout)
{
m_oBufferedStream.Skip(length);
return 0;
}
switch (type)
{
case c_oSerProp_EastAsianLayoute::ID:
{
pEastAsianLayout->m_oID.Init();
pEastAsianLayout->m_oID->SetValue(m_oBufferedStream.GetLong());
}break;
case c_oSerProp_EastAsianLayoute::Combine:
{
pEastAsianLayout->m_oCombine.Init();
pEastAsianLayout->m_oCombine->FromBool(m_oBufferedStream.GetBool());
}break;
case c_oSerProp_EastAsianLayoute::CombineBrackets:
{
pEastAsianLayout->m_oCombineBrackets.Init();
pEastAsianLayout->m_oCombineBrackets->SetValueFromByte(m_oBufferedStream.GetUChar());
}break;
case c_oSerProp_EastAsianLayoute::Vert:
{
pEastAsianLayout->m_oVert.Init();
pEastAsianLayout->m_oVert->FromBool(m_oBufferedStream.GetBool());
}break;
case c_oSerProp_EastAsianLayoute::VertCompress:
{
pEastAsianLayout->m_oVertCompress.Init();
pEastAsianLayout->m_oVertCompress->FromBool(m_oBufferedStream.GetBool());
}break;
default:
{
res = c_oSerConstants::ReadUnknown;
}break;
}
return res;
}
int Binary_CommonReader2::ReadShdComplexType(BYTE type, long length, void* poResult)
{
if (length < 0)
@ -887,7 +934,11 @@ int Binary_rPrReader::ReadContent(BYTE type, long length, void* poResult)
pRPr->m_oKern.Init(); pRPr->m_oKern->m_oVal.Init();
pRPr->m_oKern->m_oVal->FromHps(m_oBufferedStream.GetLong());
}break;
case c_oSerProp_rPrType::EastAsianLayout:
{
pRPr->m_oEastAsianLayout.Init();
READ2_DEF(length, res, oBinary_CommonReader2.ReadEastAsianLayout, pRPr->m_oEastAsianLayout.GetPointer());
}break;
default:
res = c_oSerConstants::ReadUnknown;
break;

View File

@ -66,6 +66,7 @@ public:
template<typename T> int ReadTrackRevision(long length, T* poResult);
template<typename T> int ReadTrackRevision2(long length, T* poResult);
int ReadShdComplexType(BYTE type, long length, void* poResult);
int ReadEastAsianLayout(BYTE type, long length, void* poResult);
private:
template<typename T> int ReadTrackRevisionInner(BYTE type, long length, T* poResult);
template<typename T> int ReadTrackRevisionInner2(BYTE type, long length, T* poResult);

View File

@ -422,8 +422,17 @@ extern int g_nCurFormatVersion;
Glow = 53,
Props3d = 54,
Scene3d = 55,
Kern = 56
Kern = 56,
EastAsianLayout = 57
};}
namespace c_oSerProp_EastAsianLayoute {enum c_oSerProp_EastAsianLayoute
{
Combine = 0,
CombineBrackets = 1,
ID = 2,
Vert = 3,
VertCompress = 4
}; }
namespace c_oSerProp_rowPrType{enum c_oSerProp_rowPrType
{
CantSplit = 0,

View File

@ -937,6 +937,15 @@ void Binary_rPrWriter::Write_rPr(OOX::Logic::CRunProperty* rPr)
m_oBcw.m_oStream.WriteBYTE(c_oSerPropLenType::Long);
m_oBcw.m_oStream.WriteLONG(rPr->m_oKern.get().m_oVal.get().ToHps());
}
if (rPr->m_oEastAsianLayout.IsInit())
{
m_oBcw.m_oStream.WriteBYTE(c_oSerProp_rPrType::EastAsianLayout);
m_oBcw.m_oStream.WriteBYTE(c_oSerPropLenType::Variable);
int nCurPos = m_oBcw.WriteItemWithLengthStart();
m_oBcw.WriteEastAsianLayout(rPr->m_oEastAsianLayout.get());
m_oBcw.WriteItemWithLengthEnd(nCurPos);
}
}
void Binary_rPrWriter::Write_rPrChange(const OOX::Logic::CRPrChange& rPrChange)
{
@ -949,6 +958,43 @@ void Binary_rPrWriter::Write_rPrChange(const OOX::Logic::CRPrChange& rPrChange)
m_oBcw.WriteItemWithLengthEnd(nCurPos);
}
}
void BinaryCommonWriter::WriteEastAsianLayout(const ComplexTypes::Word::CEastAsianLayout& EastAsianLayout)
{
int nCurPos = 0;
if (false != EastAsianLayout.m_oID.IsInit())
{
m_oStream.WriteBYTE(c_oSerProp_EastAsianLayoute::ID);
m_oStream.WriteBYTE(c_oSerPropLenType::Long);
m_oStream.WriteBOOL(EastAsianLayout.m_oID->GetValue());
}
if (false != EastAsianLayout.m_oCombine.IsInit())
{
bool val = SimpleTypes::onoffTrue == EastAsianLayout.m_oCombine->ToBool();
m_oStream.WriteBYTE(c_oSerProp_EastAsianLayoute::Combine);
m_oStream.WriteBYTE(c_oSerPropLenType::Byte);
m_oStream.WriteBOOL(val);
}
if (false != EastAsianLayout.m_oCombineBrackets.IsInit())
{
m_oStream.WriteBYTE(c_oSerProp_EastAsianLayoute::CombineBrackets);
m_oStream.WriteBYTE(c_oSerPropLenType::Byte);
m_oStream.WriteBYTE(EastAsianLayout.m_oCombineBrackets->GetValue());
}
if (false != EastAsianLayout.m_oVert.IsInit())
{
bool val = SimpleTypes::onoffTrue == EastAsianLayout.m_oVert->ToBool();
m_oStream.WriteBYTE(c_oSerProp_EastAsianLayoute::Vert);
m_oStream.WriteBYTE(c_oSerPropLenType::Byte);
m_oStream.WriteBOOL(val);
}
if (false != EastAsianLayout.m_oVertCompress.IsInit())
{
bool val = SimpleTypes::onoffTrue == EastAsianLayout.m_oVertCompress->ToBool();
m_oStream.WriteBYTE(c_oSerProp_EastAsianLayoute::VertCompress);
m_oStream.WriteBYTE(c_oSerPropLenType::Byte);
m_oStream.WriteBOOL(val);
}
}
Binary_pPrWriter::Binary_pPrWriter(ParamsWriter& oParamsWriter, BinaryHeaderFooterTableWriter* oBinaryHeaderFooterTableWriter):

View File

@ -139,6 +139,7 @@ namespace BinDocxRW
void WriteFont(std::wstring sFontName, BYTE bType, DocWrapper::FontProcessor& m_oFontProcessor);
void WriteBytesArray(BYTE* pData, long nDataSize);
template<typename T> void WriteTrackRevision(const T& elem);
void WriteEastAsianLayout(const ComplexTypes::Word::CEastAsianLayout& EastAsianLayout);
};
class BinaryHeaderFooterTableWriter

View File

@ -576,7 +576,7 @@ namespace OOX
if (m_oSmallCaps.IsInit()) sResult += m_oSmallCaps->ValNode(L"w:smallCaps");
if (m_oStrike.IsInit()) sResult += m_oStrike->ValNode(L"w:strike");
if ((m_oDStrike.IsInit()) && (m_oDStrike->m_oVal.ToBool()))
sResult += m_oDStrike->ValNode(L"w:dstrike");
sResult += m_oDStrike->ValNode(L"w:dstrike");
if (m_oOutline.IsInit()) sResult += m_oOutline->ValNode(L"w:outline");
if (m_oShadow.IsInit()) sResult += m_oShadow->ValNode(L"w:shadow");
if (m_oEmboss.IsInit()) sResult += m_oEmboss->ValNode(L"w:emboss");
@ -600,7 +600,7 @@ namespace OOX
if (m_oFitText.IsInit()) sResult += m_oFitText->ValNode(L"w:fitText");
if (m_oVertAlign.IsInit()) sResult += m_oVertAlign->ValNode(L"w:vertAlign");
if (m_oRtL.IsInit()) sResult += m_oRtL->ValNode(L"w:rtl");
if (m_oCs.IsInit()) sResult += m_oCs->ValNode(L"w:cs");
if (m_oCs.IsInit()) sResult += m_oCs->ValNode(L"w:cs");
if (m_oEm.IsInit()) sResult += m_oEm->ValNode(L"w:em");
if (m_oLang.IsInit()) sResult += m_oLang->ValNode(L"w:lang");
if (m_oEastAsianLayout.IsInit())sResult += m_oEastAsianLayout->ValNode(L"w:eastAsianLayout");

View File

@ -4692,7 +4692,7 @@ void CPdfEditor::ScanAndProcessFonts(PDFDoc* pPDFDocument, XRef* xref, Dict* pRe
if (gfxFont->getEmbeddedFontID(&oEmbRef) || PdfReader::IsBaseFont(wsFontBaseName) || ((pFontLoc = gfxFont->locateFont(xref, false)) && NSStrings::GetStringFromUTF32(pFontLoc->path).length()))
{
std::wstring wsFileName, wsFontName;
PdfReader::GetFont(xref, pFontManager, pFontList, gfxFont, wsFileName, wsFontName, false);
PdfReader::RendererOutputDev::GetFont(xref, pFontManager, pFontList, gfxFont, wsFileName, wsFontName, false);
// Collect information about embedded font
if (!PdfReader::IsBaseFont(wsFontBaseName))
@ -4710,7 +4710,7 @@ void CPdfEditor::ScanAndProcessFonts(PDFDoc* pPDFDocument, XRef* xref, Dict* pRe
else
{
std::map<unsigned int, unsigned int> mCodeToWidth, mCodeToUnicode, mCodeToGID;
int nDW = PdfReader::CollectFontWidths(oFont.getDict(), mCodeToWidth);
int nDW = PdfReader::CollectFontWidths(gfxFont, oFont.getDict(), mCodeToWidth);
for (int nIndex = 0; nIndex < pFontEntry.unLenUnicode; ++nIndex)
{
if (pFontEntry.pCodeToUnicode[nIndex])

View File

@ -40,6 +40,7 @@
#include "../DesktopEditor/graphics/IRenderer.h"
#include "../DesktopEditor/common/Directory.h"
#include "../DesktopEditor/common/StringExt.h"
#include "../DesktopEditor/graphics/pro/js/wasm/src/serialize.h"
#include "../DesktopEditor/graphics/MetafileToRenderer.h"
#include "../DesktopEditor/graphics/BaseThread.h"
@ -189,7 +190,7 @@ void CPdfReader::SetCMapMemory(BYTE* pData, DWORD nSizeData)
if (m_vPDFContext.empty())
return;
CPdfReaderContext* pPDFContext = m_vPDFContext.back();
std::map<std::wstring, std::wstring> mFonts = PdfReader::GetAllFonts(pPDFContext->m_pDocument, m_pFontManager, pPDFContext->m_pFontList);
std::map<std::wstring, std::wstring> mFonts = PdfReader::GetAllFonts(pPDFContext->m_pDocument, m_pFontManager, pPDFContext->m_pFontList, false);
m_mFonts.insert(mFonts.begin(), mFonts.end());
}
void CPdfReader::SetCMapFolder(const std::wstring& sFolder)
@ -251,34 +252,17 @@ void CPdfReader::SetParams(COfficeDrawingPageParams* pParams)
globalParams->setDrawAnnotations(bDraw);
}
// ============================================================
// CPdfReader::FindContext
// ============================================================
CPdfReaderContext* CPdfReader::FindContext(PDFDoc* _pDoc) const
int CPdfReader::GetStartRefID(PDFDoc* _pDoc)
{
for (CPdfReaderContext* pPDFContext : m_vPDFContext)
{
if (!pPDFContext || !pPDFContext->m_pDocument)
continue;
if (pPDFContext->m_pDocument == _pDoc)
return pPDFContext;
PDFDoc* pDoc = pPDFContext->m_pDocument;
if (_pDoc == pDoc)
return pPDFContext->m_nStartID;
}
return NULL;
}
int CPdfReader::GetStartRefID(PDFDoc* _pDoc)
{
CPdfReaderContext* pContext = FindContext(_pDoc);
return pContext ? pContext->m_nStartID : -1;
}
PdfReader::CPdfFontList* CPdfReader::GetFontList(PDFDoc* _pDoc)
{
CPdfReaderContext* pContext = FindContext(_pDoc);
return pContext ? pContext->m_pFontList : NULL;
}
std::string CPdfReader::GetPrefixForm(PDFDoc* _pDoc)
{
CPdfReaderContext* pContext = FindContext(_pDoc);
return pContext ? pContext->m_sPrefixForm : "";
return -1;
}
int CPdfReader::GetNumPagesBefore(PDFDoc* _pDoc)
{
@ -287,12 +271,37 @@ int CPdfReader::GetNumPagesBefore(PDFDoc* _pDoc)
{
if (!pPDFContext || !pPDFContext->m_pDocument)
continue;
if (pPDFContext->m_pDocument == _pDoc)
PDFDoc* pDoc = pPDFContext->m_pDocument;
if (_pDoc == pDoc)
return nPagesBefore;
nPagesBefore += pPDFContext->m_pDocument->getNumPages();
nPagesBefore += pDoc->getNumPages();
}
return -1;
}
PdfReader::CPdfFontList* CPdfReader::GetFontList(PDFDoc* _pDoc)
{
for (CPdfReaderContext* pPDFContext : m_vPDFContext)
{
if (!pPDFContext || !pPDFContext->m_pDocument)
continue;
PDFDoc* pDoc = pPDFContext->m_pDocument;
if (_pDoc == pDoc)
return pPDFContext->m_pFontList;
}
return NULL;
}
std::string CPdfReader::GetPrefixForm(PDFDoc* _pDoc)
{
for (CPdfReaderContext* pPDFContext : m_vPDFContext)
{
if (!pPDFContext || !pPDFContext->m_pDocument)
continue;
PDFDoc* pDoc = pPDFContext->m_pDocument;
if (_pDoc == pDoc)
return pPDFContext->m_sPrefixForm;
}
return "";
}
int CPdfReader::FindRefNum(int nObjID, PDFDoc** _pDoc, int* _nStartRefID)
{
for (CPdfReaderContext* pPDFContext : m_vPDFContext)
@ -302,8 +311,10 @@ int CPdfReader::FindRefNum(int nObjID, PDFDoc** _pDoc, int* _nStartRefID)
PDFDoc* pDoc = pPDFContext->m_pDocument;
if (nObjID < pPDFContext->m_nStartID + pDoc->getXRef()->getNumObjects())
{
if (_pDoc) *_pDoc = pDoc;
if (_nStartRefID) *_nStartRefID = pPDFContext->m_nStartID;
if (_pDoc)
*_pDoc = pDoc;
if (_nStartRefID)
*_nStartRefID = pPDFContext->m_nStartID;
return nObjID - pPDFContext->m_nStartID;
}
}
@ -317,19 +328,22 @@ int CPdfReader::GetPageIndex(int nAbsPageIndex, PDFDoc** _pDoc, PdfReader::CPdfF
if (!pPDFContext || !pPDFContext->m_pDocument)
continue;
PDFDoc* pDoc = pPDFContext->m_pDocument;
int nPages = pDoc->getNumPages();
if (nAbsPageIndex < nTotalPages + nPages)
{
if (_pDoc) *_pDoc = pDoc;
if (pFontList) *pFontList = pPDFContext->m_pFontList;
if (nStartRefID) *nStartRefID = pPDFContext->m_nStartID;
if (_pDoc)
*_pDoc = pDoc;
if (pFontList)
*pFontList = pPDFContext->m_pFontList;
if (nStartRefID)
*nStartRefID = pPDFContext->m_nStartID;
return nAbsPageIndex - nTotalPages + 1;
}
nTotalPages += nPages;
}
return -1;
}
int CPdfReader::GetError()
{
if (m_vPDFContext.empty())
@ -398,64 +412,6 @@ int CPdfReader::GetNumPages()
}
return nNumPages;
}
// ============================================================
// CPdfReader::ValidMetaData
// ============================================================
bool ValidateXRefTable(BaseStream* str, GFileOffset nOffset, GString* pID2)
{
Object oDict, oTID, oID, obj1;
char buf[100];
Stream* pSubStr = str->makeSubStream(nOffset + 5, gFalse, 0, &oDict);
int c = pSubStr->getChar();
while (c != 't')
c = pSubStr->getChar();
pSubStr->getBlock(buf, 6);
Parser* parser = new Parser(NULL, new Lexer(NULL, pSubStr->getBaseStream()->makeSubStream(pSubStr->getPos(), gFalse, 0, &oDict)), gTrue);
parser->getObj(&obj1);
delete parser;
delete pSubStr;
bool bRes = false;
if (obj1.isDict() && obj1.dictLookup("ID", &oTID)->isArray() && oTID.arrayGet(1, &oID)->isString())
bRes = pID2->cmp(oID.getString()) != 0;
obj1.free();
oTID.free();
oID.free();
return bRes;
}
bool ValidateXRefStream(BaseStream* str, GFileOffset nOffset, GString* pID2)
{
Object oDict, oTID, oID, obj1, obj2, obj3, obj4;
Stream* pSubStr = str->makeSubStream(nOffset, gFalse, 0, &oDict);
Parser* parser = new Parser(NULL, new Lexer(NULL, pSubStr), gTrue);
parser->getObj(&obj1);
parser->getObj(&obj2);
parser->getObj(&obj3);
parser->getObj(&obj4);
bool bRes = false;
if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") && obj4.isStream())
{
Dict* pPrevXRefDict = obj4.streamGetDict();
if (pPrevXRefDict->lookup("ID", &oTID)->isArray() && oTID.arrayGet(1, &oID)->isString())
bRes = pID2->cmp(oID.getString()) != 0;
oTID.free();
oID.free();
}
obj4.free();
obj3.free();
obj2.free();
obj1.free();
delete parser;
return bRes;
}
bool CPdfReader::ValidMetaData()
{
if (m_vPDFContext.empty() || m_vPDFContext.size() != 1)
@ -489,9 +445,9 @@ bool CPdfReader::ValidMetaData()
int nNumXRefTables = xref->getNumXRefTables();
if (bRes && nNumXRefTables > 1)
{
GFileOffset nOffset = xref->getXRefTablePos(nNumXRefTables - 2);
GFileOffset nOffeset = xref->getXRefTablePos(nNumXRefTables - 2);
BaseStream* str = pPDFContext->m_pDocument->getBaseStream();
str->setPos(nOffset);
str->setPos(nOffeset);
Object oDict, obj1, obj2, obj3, obj4;
char buf[100];
@ -499,58 +455,52 @@ bool CPdfReader::ValidMetaData()
for (i = 0; i < n && Lexer::isSpace(buf[i]); ++i);
// xref table
if (i + 4 < n && buf[i] == 'x' && buf[i+1] == 'r' && buf[i+2] == 'e' && buf[i+3] == 'f' && Lexer::isSpace(buf[i+4]))
bRes = ValidateXRefTable(str, nOffset + i + 5, oID2.getString());
else
bRes = ValidateXRefStream(str, nOffset, oID2.getString());
{
Stream* pSubStr = str->makeSubStream(nOffeset + i + 5, gFalse, 0, &oDict);
int c = pSubStr->getChar();
while (c != 't')
c = pSubStr->getChar();
pSubStr->getBlock(buf, 6);
Parser* parser = new Parser(NULL, new Lexer(NULL, pSubStr->getBaseStream()->makeSubStream(pSubStr->getPos(), gFalse, 0, &oDict)), gTrue);
parser->getObj(&obj1);
delete parser;
delete pSubStr;
if (obj1.isDict() && obj1.dictLookup("ID", &oTID)->isArray() && oTID.arrayGet(1, &oID)->isString())
{
bRes = oID2.getString()->cmp(oID.getString()) != 0;
}
obj1.free();
oTID.free();
}
else // xref stream
{
Stream* pSubStr = str->makeSubStream(nOffeset, gFalse, 0, &oDict);
Parser* parser = new Parser(NULL, new Lexer(NULL, pSubStr), gTrue);
parser->getObj(&obj1);
parser->getObj(&obj2);
parser->getObj(&obj3);
parser->getObj(&obj4);
if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") && obj4.isStream())
{
Dict* pPrevXRefDict = obj4.streamGetDict();
if (pPrevXRefDict->lookup("ID", &oTID)->isArray() && oTID.arrayGet(1, &oID)->isString())
{
bRes = oID2.getString()->cmp(oID.getString()) != 0;
}
oTID.free();
}
obj4.free();
obj3.free();
obj2.free();
obj1.free();
delete parser;
}
}
oID2.free(); oID.free();
return bRes;
}
// ============================================================
// CPdfReader::MergePages
// ============================================================
void CreatePasswords(const wchar_t* wsPassword, GString*& owner_pswd, GString*& user_pswd)
{
owner_pswd = NULL;
user_pswd = NULL;
if (wsPassword)
{
owner_pswd = NSStrings::CreateString(wsPassword);
user_pswd = NSStrings::CreateString(wsPassword);
}
}
CPdfReaderContext* CPdfReader::CreateContext(const std::string& sPrefixForm, int nMaxID)
{
CPdfReaderContext* pContext = new CPdfReaderContext();
pContext->m_pFontList = new PdfReader::CPdfFontList();
pContext->m_sPrefixForm = sPrefixForm;
if (nMaxID != 0)
pContext->m_nStartID = nMaxID;
else if (!m_vPDFContext.empty())
pContext->m_nStartID = m_vPDFContext.back()->m_nStartID + m_vPDFContext.back()->m_pDocument->getXRef()->getNumObjects();
return pContext;
}
bool CPdfReader::FinalizeMerge(CPdfReaderContext* pContext)
{
PDFDoc* pDoc = pContext->m_pDocument;
m_vPDFContext.push_back(pContext);
m_eError = pDoc ? pDoc->getErrorCode() : errMemory;
if (!pDoc || !pDoc->isOk())
{
delete pContext;
m_vPDFContext.pop_back();
return false;
}
IsNeedCMap();
std::map<std::wstring, std::wstring> mFonts = PdfReader::GetAllFonts(pDoc, m_pFontManager, pContext->m_pFontList);
m_mFonts.insert(mFonts.begin(), mFonts.end());
return true;
}
bool CPdfReader::MergePages(BYTE* pData, DWORD nLength, const wchar_t* wsPassword, int nMaxID, const std::string& sPrefixForm)
{
if (m_eError)
@ -580,11 +530,25 @@ bool CPdfReader::MergePages(BYTE* pData, DWORD nLength, const wchar_t* wsPasswor
pContext->m_nStartID = nMaxID;
else if (!m_vPDFContext.empty())
pContext->m_nStartID = m_vPDFContext.back()->m_nStartID + m_vPDFContext.back()->m_pDocument->getXRef()->getNumObjects();
PDFDoc* pDoc = pContext->m_pDocument;
m_vPDFContext.push_back(pContext);
RELEASEOBJECT(owner_pswd);
RELEASEOBJECT(user_pswd);
return FinalizeMerge(pContext);
m_eError = pDoc ? pDoc->getErrorCode() : errMemory;
if (!pDoc || !pDoc->isOk())
{
// pData is freed
delete pContext;
m_vPDFContext.pop_back();
return false;
}
std::map<std::wstring, std::wstring> mFonts = PdfReader::GetAllFonts(pDoc, m_pFontManager, pContext->m_pFontList, IsNeedCMap());
m_mFonts.insert(mFonts.begin(), mFonts.end());
return true;
}
bool CPdfReader::MergePages(const std::wstring& wsFile, const wchar_t* wsPassword, int nMaxID, const std::string& sPrefixForm)
{
@ -610,13 +574,25 @@ bool CPdfReader::MergePages(const std::wstring& wsFile, const wchar_t* wsPasswor
pContext->m_nStartID = nMaxID;
else if (!m_vPDFContext.empty())
pContext->m_nStartID = m_vPDFContext.back()->m_nStartID + m_vPDFContext.back()->m_pDocument->getXRef()->getNumObjects();
PDFDoc* pDoc = pContext->m_pDocument;
m_vPDFContext.push_back(pContext);
RELEASEOBJECT(owner_pswd);
RELEASEOBJECT(user_pswd);
return FinalizeMerge(pContext);
}
m_eError = pDoc ? pDoc->getErrorCode() : errMemory;
if (!pDoc || !pDoc->isOk())
{
delete pContext;
m_vPDFContext.pop_back();
return false;
}
std::map<std::wstring, std::wstring> mFonts = PdfReader::GetAllFonts(pDoc, m_pFontManager, pContext->m_pFontList, IsNeedCMap());
m_mFonts.insert(mFonts.begin(), mFonts.end());
return true;
}
bool CPdfReader::UnmergePages()
{
if (m_vPDFContext.size() <= 1)
@ -860,141 +836,6 @@ PDFDoc* CPdfReader::GetPDFDocument(int PDFIndex)
return NULL;
}
// ============================================================
// CPdfReader::GetInfo
// ============================================================
std::wstring GetMetaString(Object& oInfo, const char* sName, const wchar_t* wsName)
{
std::wstring sRes;
Object obj1;
if (oInfo.dictLookup(sName, &obj1)->isString())
{
TextString* s = new TextString(obj1.getString());
std::wstring sValue = NSStringExt::CConverter::GetUnicodeFromUTF32(s->getUnicode(), s->getLength());
delete s;
NSStringExt::Replace(sValue, L"\\", L"\\\\");
NSStringExt::Replace(sValue, L"\"", L"\\\"");
sValue.erase(std::remove_if(sValue.begin(), sValue.end(), [](const wchar_t& wc) { return wc < 0x20; }), sValue.end());
if (!sValue.empty())
{
sRes += L"\"";
sRes += wsName;
sRes += L"\":\"";
sRes += sValue;
sRes += L"\",";
}
}
obj1.free();
return sRes;
}
std::wstring GetMetaDate(Object& oInfo, const char* sName, const wchar_t* wsName)
{
std::wstring sRes;
Object obj1;
if (!oInfo.dictLookup(sName, &obj1)->isString() || !obj1.getString()->getLength())
{
obj1.free();
return sRes;
}
TextString* s = new TextString(obj1.getString());
std::wstring sNoDate = NSStringExt::CConverter::GetUnicodeFromUTF32(s->getUnicode(), s->getLength());
delete s;
if (sNoDate.length() > 16)
{
std::wstring sDate = sNoDate.substr(2, 4) + L'-' + sNoDate.substr(6, 2) + L'-' + sNoDate.substr(8, 2) + L'T' +
sNoDate.substr(10, 2) + L':' + sNoDate.substr(12, 2) + L':' + sNoDate.substr(14, 2);
if (sNoDate.length() > 21 && (sNoDate[16] == L'+' || sNoDate[16] == L'-'))
sDate += (L".000" + sNoDate.substr(16, 3) + L':' + sNoDate.substr(20, 2));
else
sDate += L"Z";
NSStringExt::Replace(sDate, L"\\", L"\\\\");
NSStringExt::Replace(sDate, L"\"", L"\\\"");
sDate.erase(std::remove_if(sDate.begin(), sDate.end(), [](const wchar_t& wc) { return wc < 0x20; }), sDate.end());
sRes += L"\"";
sRes += wsName;
sRes += L"\":\"";
sRes += sDate;
sRes += L"\",";
}
obj1.free();
return sRes;
}
std::wstring GetDocMetaFields(PDFDoc* pDoc)
{
std::wstring sRes;
Object oInfo;
if (!pDoc->getDocInfo(&oInfo)->isDict())
{
oInfo.free();
return sRes;
}
sRes += GetMetaString(oInfo, "Title", L"Title");
sRes += GetMetaString(oInfo, "Author", L"Author");
sRes += GetMetaString(oInfo, "Subject", L"Subject");
sRes += GetMetaString(oInfo, "Keywords", L"Keywords");
sRes += GetMetaString(oInfo, "Creator", L"Creator");
sRes += GetMetaString(oInfo, "Producer", L"Producer");
sRes += GetMetaDate (oInfo, "CreationDate", L"CreationDate");
sRes += GetMetaDate (oInfo, "ModDate", L"ModDate");
oInfo.free();
return sRes;
}
bool IsLinearized(PDFDoc* pDoc, XRef* xref, BaseStream* str, DWORD nFileLength)
{
Object obj1, obj2, obj3, obj4, obj5, obj6;
obj1.initNull();
Parser* parser = new Parser(xref, new Lexer(xref, str->makeSubStream(str->getStart(), gFalse, 0, &obj1)), gTrue);
parser->getObj(&obj1);
parser->getObj(&obj2);
parser->getObj(&obj3);
parser->getObj(&obj4);
bool bLinearized = false;
if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") && obj4.isDict())
{
obj4.dictLookup("Linearized", &obj5);
if (obj5.isNum() && obj5.getNum() > 0 && obj4.dictLookup("L", &obj6)->isNum())
{
unsigned long size = (unsigned long)obj6.getNum();
bLinearized = size == nFileLength;
}
obj6.free();
obj5.free();
}
obj4.free();
obj3.free();
obj2.free();
obj1.free();
delete parser;
return bLinearized;
}
bool IsTagged(XRef* xref)
{
bool bTagged = false;
Object catDict, markInfoObj;
if (xref->getCatalog(&catDict)->isDict() && catDict.dictLookup("MarkInfo", &markInfoObj)->isDict())
{
Object marked, suspects;
if (markInfoObj.dictLookup("Marked", &marked)->isBool() && marked.getBool() == gTrue)
{
bTagged = true;
if (markInfoObj.dictLookup("Suspects", &suspects)->isBool() && suspects.getBool() == gTrue)
bTagged = false;
}
marked.free();
suspects.free();
}
markInfoObj.free();
catDict.free();
return bTagged;
}
std::wstring CPdfReader::GetInfo()
{
std::wstring sRes;
@ -1006,13 +847,85 @@ std::wstring CPdfReader::GetInfo()
return sRes;
PDFDoc* pDoc = pPDFContext->m_pDocument;
XRef* xref = pDoc->getXRef();
XRef* xref = pDoc->getXRef();
BaseStream* str = pDoc->getBaseStream();
if (!xref || !str)
return sRes;
return NULL;
sRes = L"{";
sRes += GetDocMetaFields(pDoc);
Object oInfo;
if (pDoc->getDocInfo(&oInfo)->isDict())
{
auto fDictLookup = [&oInfo](const char* sName, const wchar_t* wsName)
{
std::wstring sRes;
Object obj1;
if (oInfo.dictLookup(sName, &obj1)->isString())
{
TextString* s = new TextString(obj1.getString());
std::wstring sValue = NSStringExt::CConverter::GetUnicodeFromUTF32(s->getUnicode(), s->getLength());
delete s;
NSStringExt::Replace(sValue, L"\\", L"\\\\");
NSStringExt::Replace(sValue, L"\"", L"\\\"");
sValue.erase(std::remove_if(sValue.begin(), sValue.end(), [] (const wchar_t& wc) { return wc < 0x20; } ), sValue.end());
if (!sValue.empty())
{
sRes += L"\"";
sRes += wsName;
sRes += L"\":\"";
sRes += sValue;
sRes += L"\",";
}
}
obj1.free();
return sRes;
};
sRes += fDictLookup("Title", L"Title");
sRes += fDictLookup("Author", L"Author");
sRes += fDictLookup("Subject", L"Subject");
sRes += fDictLookup("Keywords", L"Keywords");
sRes += fDictLookup("Creator", L"Creator");
sRes += fDictLookup("Producer", L"Producer");
auto fDictLookupDate = [&oInfo](const char* sName, const wchar_t* wsName)
{
std::wstring sRes;
Object obj1;
if (!oInfo.dictLookup(sName, &obj1)->isString() || !obj1.getString()->getLength())
{
obj1.free();
return sRes;
}
TextString* s = new TextString(obj1.getString());
std::wstring sNoDate = NSStringExt::CConverter::GetUnicodeFromUTF32(s->getUnicode(), s->getLength());
if (sNoDate.length() > 16)
{
std::wstring sDate = sNoDate.substr(2, 4) + L'-' + sNoDate.substr(6, 2) + L'-' + sNoDate.substr(8, 2) + L'T' +
sNoDate.substr(10, 2) + L':' + sNoDate.substr(12, 2) + L':' + sNoDate.substr(14, 2);
if (sNoDate.length() > 21 && (sNoDate[16] == L'+' || sNoDate[16] == L'-'))
sDate += (L".000" + sNoDate.substr(16, 3) + L':' + sNoDate.substr(20, 2));
else
sDate += L"Z";
NSStringExt::Replace(sDate, L"\\", L"\\\\");
NSStringExt::Replace(sDate, L"\"", L"\\\"");
sDate.erase(std::remove_if(sDate.begin(), sDate.end(), [] (const wchar_t& wc) { return wc < 0x20; } ), sDate.end());
sRes += L"\"";
sRes += wsName;
sRes += L"\":\"";
sRes += sDate;
sRes += L"\",";
}
delete s;
obj1.free();
return sRes;
};
sRes += fDictLookupDate("CreationDate", L"CreationDate");
sRes += fDictLookupDate("ModDate", L"ModDate");
}
oInfo.free();
std::wstring version = std::to_wstring(pDoc->getPDFVersion());
std::wstring::size_type posDot = version.find('.');
@ -1021,19 +934,71 @@ std::wstring CPdfReader::GetInfo()
if (!version.empty())
sRes += (L"\"Version\":" + version + L",");
double nW = 0, nH = 0, nDpi = 0;
double nW = 0;
double nH = 0;
double nDpi = 0;
GetPageInfo(0, &nW, &nH, &nDpi, &nDpi);
sRes += L"\"PageWidth\":" + std::to_wstring((int)(nW * 100));
sRes += L",\"PageHeight\":" + std::to_wstring((int)(nH * 100));
sRes += L",\"NumberOfPages\":" + std::to_wstring(GetNumPages());
sRes += L"\"PageWidth\":";
sRes += std::to_wstring((int)(nW * 100));
sRes += L",\"PageHeight\":";
sRes += std::to_wstring((int)(nH * 100));
sRes += L",\"NumberOfPages\":";
sRes += std::to_wstring(GetNumPages());
sRes += L",\"FastWebView\":";
bool bLinearized = (m_vPDFContext.size() == 1) && IsLinearized(pDoc, xref, str, m_nFileLength);
sRes += std::wstring(L",\"FastWebView\":") + (bLinearized ? L"true" : L"false");
sRes += std::wstring(L",\"Tagged\":") + (IsTagged(xref) ? L"true}" : L"false}");
bool bLinearized = false;
if (m_vPDFContext.size() == 1)
{
Object obj1, obj2, obj3, obj4, obj5, obj6;
obj1.initNull();
Parser* parser = new Parser(xref, new Lexer(xref, str->makeSubStream(str->getStart(), gFalse, 0, &obj1)), gTrue);
parser->getObj(&obj1);
parser->getObj(&obj2);
parser->getObj(&obj3);
parser->getObj(&obj4);
if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") && obj4.isDict())
{
obj4.dictLookup("Linearized", &obj5);
if (obj5.isNum() && obj5.getNum() > 0 && obj4.dictLookup("L", &obj6)->isNum())
{
unsigned long size = (unsigned long)obj6.getNum();
bLinearized = size == m_nFileLength;
}
obj6.free();
obj5.free();
}
obj4.free();
obj3.free();
obj2.free();
obj1.free();
delete parser;
}
sRes += bLinearized ? L"true" : L"false";
sRes += L",\"Tagged\":";
bool bTagged = false;
Object catDict, markInfoObj;
if (xref->getCatalog(&catDict)->isDict() && catDict.dictLookup("MarkInfo", &markInfoObj)->isDict())
{
Object marked, suspects;
if (markInfoObj.dictLookup("Marked", &marked)->isBool() && marked.getBool() == gTrue)
{
bTagged = true;
// If Suspects is true, the document may not completely conform to Tagged PDF conventions.
if (markInfoObj.dictLookup("Suspects", &suspects)->isBool() && suspects.getBool() == gTrue)
bTagged = false;
}
marked.free();
suspects.free();
}
markInfoObj.free();
catDict.free();
sRes += bTagged ? L"true}" : L"false}";
return sRes;
}
BYTE* CPdfReader::GetGIDByUnicode(const std::wstring& wsFontName)
{
std::map<std::wstring, std::wstring>::const_iterator oIter = m_mFonts.find(wsFontName);
@ -1084,8 +1049,8 @@ BYTE* CPdfReader::GetGIDByUnicode(const std::wstring& wsFontName)
NSWasm::CData oRes;
oRes.SkipLen();
oRes.AddInt(mGIDbyUnicode.size());
for (std::map<unsigned int, unsigned int>::const_iterator it = mGIDbyUnicode.begin(); it != mGIDbyUnicode.end(); ++it)
{
oRes.AddInt(it->first);
@ -1093,9 +1058,9 @@ BYTE* CPdfReader::GetGIDByUnicode(const std::wstring& wsFontName)
}
oRes.WriteLen();
BYTE* pRes = oRes.GetBuffer();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return pRes;
return bRes;
}
std::wstring CPdfReader::GetFontPath(const std::wstring& wsFontName, bool bSave)
{
@ -1205,9 +1170,10 @@ BYTE* CPdfReader::GetStructure()
}
oRes.WriteLen();
BYTE* pRes = oRes.GetBuffer();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return pRes;
return bRes;
}
BYTE* CPdfReader::GetLinks(int _nPageIndex)
{
@ -1382,9 +1348,9 @@ BYTE* CPdfReader::GetWidgets()
}
oRes.WriteLen();
BYTE* pRes = oRes.GetBuffer();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return pRes;
return bRes;
}
void CPdfReader::SetFonts(PdfReader::CPdfFontList* pFontList)
{
@ -1429,9 +1395,9 @@ BYTE* CPdfReader::GetFonts(bool bStandart)
oRes.AddInt(nFonts, nFontsPos);
oRes.WriteLen();
BYTE* pRes = oRes.GetBuffer();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return pRes;
return bRes;
}
BYTE* CPdfReader::VerifySign(const std::wstring& sFile, ICertificate* pCertificate, int nWidget)
{
@ -1514,9 +1480,9 @@ BYTE* CPdfReader::VerifySign(const std::wstring& sFile, ICertificate* pCertifica
}
oRes.WriteLen();
BYTE* pRes = oRes.GetBuffer();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return pRes;
return bRes;
}
BYTE* CPdfReader::GetAPWidget(int nRasterW, int nRasterH, int nBackgroundColor, int _nPageIndex, int nWidget, const char* sView, const char* sButtonView)
{
@ -1552,9 +1518,9 @@ BYTE* CPdfReader::GetAPWidget(int nRasterW, int nRasterH, int nBackgroundColor,
}
oRes.WriteLen();
BYTE* pRes = oRes.GetBuffer();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return pRes;
return bRes;
}
BYTE* CPdfReader::GetButtonIcon(int nBackgroundColor, int _nPageIndex, bool bBase64, int nButtonWidget, const char* sIconView)
{
@ -2001,9 +1967,9 @@ BYTE* CPdfReader::GetButtonIcon(int nBackgroundColor, int _nPageIndex, bool bBas
}
oRes.WriteLen();
BYTE* pRes = oRes.GetBuffer();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return pRes;
return bRes;
}
BYTE* CPdfReader::StreamToCData(BYTE* pSteam, int nLength)
{
@ -2013,6 +1979,7 @@ BYTE* CPdfReader::StreamToCData(BYTE* pSteam, int nLength)
oRes.Write(pSteam, nLength);
oRes.WriteLen();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return bRes;
@ -2173,9 +2140,9 @@ BYTE* CPdfReader::GetAnnots(int _nPageIndex)
}
oRes.WriteLen();
BYTE* pRes = oRes.GetBuffer();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return pRes;
return bRes;
}
BYTE* CPdfReader::GetAPAnnots(int nRasterW, int nRasterH, int nBackgroundColor, int _nPageIndex, int nAnnot, const char* sView)
{
@ -2238,10 +2205,11 @@ BYTE* CPdfReader::GetAPAnnots(int nRasterW, int nRasterH, int nBackgroundColor,
oAnnotRef.free();
}
oAnnots.free();
oRes.WriteLen();
BYTE* pRes = oRes.GetBuffer();
BYTE* bRes = oRes.GetBuffer();
oRes.ClearWithoutAttack();
return pRes;
return bRes;
}

View File

@ -37,7 +37,6 @@
#include "../DesktopEditor/graphics/pro/Fonts.h"
#include "../DesktopEditor/graphics/pro/officedrawingfile.h"
#include "../DesktopEditor/graphics/pro/js/wasm/src/serialize.h"
#include "../DesktopEditor/xmlsec/src/include/Certificate.h"
#include "SrcReader/RendererOutputDev.h"
@ -93,7 +92,6 @@ public:
int GetMaxRefID();
int GetNumPages();
bool ValidMetaData();
// Takes ownership of malloc data memory
bool MergePages(BYTE* pData, DWORD nLength, const wchar_t* wsPassword = NULL, int nMaxID = 0, const std::string& sPrefixForm = "");
bool MergePages(const std::wstring& wsFile, const wchar_t* wsPassword = NULL, int nMaxID = 0, const std::string& sPrefixForm = "");
@ -137,18 +135,13 @@ public:
private:
void Clear();
CPdfReaderContext* CreateContext(const std::string& sPrefixForm, int nMaxID);
bool FinalizeMerge(CPdfReaderContext* pContext);
CPdfReaderContext* FindContext(PDFDoc* pDoc) const;
private:
std::wstring m_wsTempFolder;
NSFonts::IFontManager* m_pFontManager;
DWORD m_nFileLength;
int m_eError;
IOfficeDrawingFilePainter* m_pPainter;
IOfficeDrawingFilePainter* m_pPainter;
std::vector<CPdfReaderContext*> m_vPDFContext;
std::vector<CPdfRedact*> m_vRedact;
std::vector<CPdfRedact*> m_vRedact;
std::map<std::wstring, std::wstring> m_mFonts;
};

View File

@ -49,6 +49,7 @@
#include "../../DesktopEditor/common/Types.h"
#include "../../DesktopEditor/common/StringExt.h"
#include "../../DesktopEditor/xml/include/xmlutils.h"
#include "../../DesktopEditor/fontengine/ApplicationFonts.h"
#include "../../DesktopEditor/graphics/pro/Fonts.h"
@ -1856,7 +1857,7 @@ CAnnotFreeText::CAnnotFreeText(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex
if (oAnnot.dictLookup("RC", &oObj2)->isNull() && oAnnot.dictLookup("Contents", &oObj)->isString() && oObj.getString()->getLength())
{
m_arrRC = ReadRC(GetRCFromDS(m_sDS, &oObj, m_arrCFromDA));
m_arrRC = CAnnotMarkup::ReadRC(GetRCFromDS(m_sDS, &oObj, m_arrCFromDA));
if (m_arrRC.empty())
m_unFlags &= ~(1 << 3);
else
@ -2748,7 +2749,7 @@ CAnnotMarkup::CAnnotMarkup(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, in
// std::cout << sRC << std::endl;
// if (oAnnot.dictLookup("RC", &oObj)->isStream())
// TODO streamGetBlock
m_arrRC = ReadRC(sRC);
m_arrRC = CAnnotMarkup::ReadRC(sRC);
if (m_arrRC.empty())
m_unFlags &= ~(1 << 3);
else
@ -2785,6 +2786,166 @@ CAnnotMarkup::~CAnnotMarkup()
for (int i = 0; i < m_arrRC.size(); ++i)
RELEASEOBJECT(m_arrRC[i]);
}
void ReadFontData(const std::string& sData, CAnnotMarkup::CFontData* pFont)
{
size_t nSemicolon = 0;
size_t nColon = sData.find(':');
while (nColon != std::string::npos && nColon > nSemicolon)
{
std::string sProperty = sData.substr(nSemicolon, nColon - nSemicolon);
nSemicolon = sData.find(';', nSemicolon);
nColon++;
std::string sValue = sData.substr(nColon, nSemicolon - nColon);
nColon = sData.find(':', nSemicolon);
nSemicolon++;
if (sProperty == "font-size")
pFont->dFontSise = std::stod(sValue);
else if (sProperty == "text-align")
{
// 0 start / left
if (sValue == "center" || sValue == "middle")
pFont->nAlign = 1;
else if (sValue == "right" || sValue == "end")
pFont->nAlign = 2;
else if (sValue == "justify")
pFont->nAlign = 3;
}
else if (sProperty == "color")
{
if (sValue[0] == '#')
{
sValue = sValue.substr(1);
BYTE nColor1 = 0, nColor2 = 0, nColor3 = 0;
if (sValue.length() == 6)
sscanf(sValue.c_str(), "%2hhx%2hhx%2hhx", &nColor1, &nColor2, &nColor3);
else if (sValue.length() == 3)
{
sscanf(sValue.c_str(), "%1hhx%1hhx%1hhx", &nColor1, &nColor2, &nColor3);
nColor1 *= 17;
nColor2 *= 17;
nColor3 *= 17;
}
pFont->dColor[0] = (double)nColor1 / 255.0;
pFont->dColor[1] = (double)nColor2 / 255.0;
pFont->dColor[2] = (double)nColor3 / 255.0;
}
}
else if (sProperty == "font-weight")
{
// 0 normal / 300 / 400 / 500
if (sValue == "normal" || sValue == "300" || sValue == "400" || sValue == "500")
pFont->unFontFlags &= ~(1 << 0);
else if (sValue == "bold" || sValue == "bolder" || sValue == "600" || sValue == "700" || sValue == "800" || sValue == "900")
pFont->unFontFlags |= (1 << 0);
}
else if (sProperty == "font-style")
{
// 0 normal
if (sValue == "normal")
pFont->unFontFlags &= ~(1 << 1);
else if (sValue == "italic" || sValue.find("oblique") != std::string::npos)
pFont->unFontFlags |= (1 << 1);
}
else if (sProperty == "font-family")
pFont->sFontFamily = sValue[0] == '\'' ? sValue.substr(1, sValue.length() - 2) : sValue;
else if (sProperty == "text-decoration")
{
if (sValue.find("line-through") != std::string::npos)
pFont->unFontFlags |= (1 << 3);
if (sValue.find("word") != std::string::npos || sValue.find("underline") != std::string::npos)
pFont->unFontFlags |= (1 << 4);
if (sValue.find("none") != std::string::npos)
{
pFont->unFontFlags &= ~(1 << 3);
pFont->unFontFlags &= ~(1 << 4);
}
}
else if (sProperty == "vertical-align")
{
pFont->unFontFlags |= (1 << 5);
pFont->dVAlign = std::stod(sValue);
if (pFont->dVAlign == 0 && sValue[0] == '-')
pFont->dVAlign = -0.01;
}
// font-stretch
}
}
std::vector<CAnnotMarkup::CFontData*> CAnnotMarkup::ReadRC(const std::string& sRC)
{
std::vector<CAnnotMarkup::CFontData*> arrRC;
XmlUtils::CXmlLiteReader oLightReader;
if (sRC.empty() || !oLightReader.FromStringA(sRC) || !oLightReader.ReadNextNode() || oLightReader.GetNameA() != "body")
return arrRC;
CAnnotMarkup::CFontData oFontBase;
while (oLightReader.MoveToNextAttribute())
{
if (oLightReader.GetNameA() == "style")
{
ReadFontData(oLightReader.GetTextA(), &oFontBase);
break;
}
}
oLightReader.MoveToElement();
int nDepthP = oLightReader.GetDepth();
while (oLightReader.ReadNextSiblingNode2(nDepthP))
{
if (oLightReader.GetNameA() != "p")
continue;
bool bRTL = false;
while (oLightReader.MoveToNextAttribute())
{
if (oLightReader.GetNameA() == "dir" && oLightReader.GetTextA() == "rtl")
{
bRTL = true;
break;
}
}
oLightReader.MoveToElement();
int nDepthSpan = oLightReader.GetDepth();
if (oLightReader.IsEmptyNode() || !oLightReader.ReadNextSiblingNode2(nDepthSpan))
continue;
do
{
std::string sName = oLightReader.GetNameA();
if (sName == "span")
{
CAnnotMarkup::CFontData* pFont = new CAnnotMarkup::CFontData(oFontBase);
while (oLightReader.MoveToNextAttribute())
{
if (oLightReader.GetNameA() == "style")
{
ReadFontData(oLightReader.GetTextA(), pFont);
break;
}
}
oLightReader.MoveToElement();
if (bRTL)
pFont->unFontFlags |= (1 << 7);
pFont->sText = oLightReader.GetText2A();
arrRC.push_back(pFont);
}
else if (sName == "#text")
{
CAnnotMarkup::CFontData* pFont = new CAnnotMarkup::CFontData(oFontBase);
if (bRTL)
pFont->unFontFlags |= (1 << 7);
pFont->sText = oLightReader.GetTextA();
arrRC.push_back(pFont);
}
} while (oLightReader.ReadNextSiblingNode2(nDepthSpan));
}
return arrRC;
}
void CAnnotMarkup::SetFont(PDFDoc* pdfDoc, Object* oAnnotRef, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList)
{
GetFreeTextFont(pdfDoc, pFontManager, pFontList, oAnnotRef, m_arrRC);

View File

@ -46,7 +46,6 @@
#include "../../DesktopEditor/graphics/pro/js/wasm/src/serialize.h"
#include "RendererOutputDev.h"
#include "PdfFont.h"
namespace PdfReader
{
@ -388,7 +387,25 @@ private:
class CAnnotMarkup : public CAnnot
{
public:
struct CFontData final
{
bool bFind;
BYTE nAlign;
unsigned int unFontFlags; // 0 Bold, 1 Italic, 3 strikethrough, 4 underline, 5 vertical-align, 6 actual font, 7 RTL
double dFontSise;
double dVAlign;
double dColor[3];
std::string sFontFamily;
std::string sActualFont;
std::string sText;
CFontData() : bFind(false), nAlign(0), unFontFlags(4), dFontSise(10), dVAlign(0), dColor{0, 0, 0} {}
CFontData(const CFontData& oFont) : bFind(oFont.bFind), nAlign(oFont.nAlign), unFontFlags(oFont.unFontFlags), dFontSise(oFont.dFontSise), dVAlign(oFont.dVAlign),
dColor{oFont.dColor[0], oFont.dColor[1], oFont.dColor[2]}, sFontFamily(oFont.sFontFamily), sActualFont(oFont.sActualFont), sText(oFont.sText) {}
};
void SetFont(PDFDoc* pdfDoc, Object* oAnnotRef, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList);
static std::vector<CAnnotMarkup::CFontData*> ReadRC(const std::string& sRC);
protected:
CAnnotMarkup(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID);

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,7 @@
#include "../../DesktopEditor/graphics/pro/Fonts.h"
#include "RendererOutputDev.h"
#include "PdfAnnot.h"
namespace PdfReader
{
@ -83,40 +84,20 @@ struct CType3FontMetrics
return dUnitsPerEm * 0.5;
}
};
struct CFontData
{
bool bFind;
BYTE nAlign;
unsigned int unFontFlags; // 0 Bold, 1 Italic, 3 strikethrough, 4 underline, 5 vertical-align, 6 actual font, 7 RTL
double dFontSise;
double dVAlign;
double dColor[3];
std::string sFontFamily;
std::string sActualFont;
std::string sText;
CFontData() : bFind(false), nAlign(0), unFontFlags(4), dFontSise(10), dVAlign(0), dColor{0, 0, 0} {}
CFontData(const CFontData& oFont) : bFind(oFont.bFind), nAlign(oFont.nAlign), unFontFlags(oFont.unFontFlags), dFontSise(oFont.dFontSise), dVAlign(oFont.dVAlign),
dColor{oFont.dColor[0], oFont.dColor[1], oFont.dColor[2]}, sFontFamily(oFont.sFontFamily), sActualFont(oFont.sActualFont), sText(oFont.sText) {}
};
std::vector<CFontData*> ReadRC(const std::string& sRC);
std::string GetRCFromDS(const std::string& sDS, Object* pContents, const std::vector<double>& arrCFromDA);
bool IsNeedCMap(PDFDoc* pDoc);
bool IsBaseFont(const std::wstring& wsName);
std::map<std::wstring, std::wstring> GetAllFonts(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList);
std::wstring GetFontData(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oFontRef, std::string& sFontName, std::string& sActualFontName, bool& bBold, bool& bItalic);
std::map<std::wstring, std::wstring> GetAllFonts(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, bool bIsNeedCMap);
std::wstring GetFontData(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oFontRef, std::string& sFontName, std::string& sActualFontName, bool& bBold, bool& bItalic, bool bIsNeedCMap = false);
bool GetFontFromAP(PDFDoc* pdfDoc, AcroFormField* pField, Object* oFontRef, std::string& sFontKey);
std::vector<CAnnotFontInfo> GetAnnotFontInfos(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, Object* oAnnotRef);
std::map<std::wstring, std::wstring> GetFreeTextFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, Object* oAnnotRef, std::vector<CFontData*>& arrRC);
std::map<std::wstring, std::wstring> GetFreeTextFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, Object* oAnnotRef, std::vector<CAnnotMarkup::CFontData*>& arrRC);
bool FindFonts(Object* oStream, int nDepth, Object* oResFonts);
int CollectFontWidths(Dict* pFontDict, std::map<unsigned int, unsigned int>& mGIDToWidth);
int CollectFontWidths(GfxFont* gfxFont, Dict* pFontDict, std::map<unsigned int, unsigned int>& mGIDToWidth);
double CheckFontStylePDF(std::wstring& sName, bool& bBold, bool& bItalic);
bool EraseSubsetTag(std::wstring& sFontName);
NSFonts::CFontInfo* GetFontByParams(XRef* pXref, NSFonts::IFontManager* pFontManager, GfxFont* pFont, std::wstring& wsFontBaseName, double& dStretch);
void GetFont(XRef* pXref, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, GfxFont* pFont, std::wstring& wsFileName, std::wstring& wsFontName, bool bNotFullName = true);
CType3FontMetrics* BuildType3FontMetrics(XRef* pXref, GfxFont* pFont);
}

File diff suppressed because it is too large Load Diff

View File

@ -249,6 +249,8 @@ namespace PdfReader
{
m_pbBreak = pbBreak;
}
static NSFonts::CFontInfo* GetFontByParams(XRef* pXref, NSFonts::IFontManager* pFontManager, GfxFont* pFont, std::wstring& wsFontBaseName, double& dStretch);
static void GetFont(XRef* pXref, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, GfxFont* pFont, std::wstring& wsFileName, std::wstring& wsFontName, bool bNotFullName = true);
private:
struct GfxOutputState

View File

@ -146,7 +146,7 @@ public:
GBool isName(const char *nameA)
{ return type == objName && !strcmp(name, nameA); }
GBool isDict(const char *dictType);
GBool isStream(const char *dictType);
GBool isStream(char *dictType);
GBool isCmd(const char *cmdA)
{ return type == objCmd && !strcmp(cmd, cmdA); }
@ -182,7 +182,7 @@ public:
Object *dictGetValNF(int i, Object *obj);
// Stream accessors.
GBool streamIs(const char *dictType);
GBool streamIs(char *dictType);
void streamReset();
void streamClose();
int streamGetChar();
@ -284,10 +284,10 @@ inline Object *Object::dictGetValNF(int i, Object *obj)
#include "Stream.h"
inline GBool Object::streamIs(const char *dictType)
inline GBool Object::streamIs(char *dictType)
{ return stream->getDict()->is(dictType); }
inline GBool Object::isStream(const char *dictType)
inline GBool Object::isStream(char *dictType)
{ return type == objStream && streamIs(dictType); }
inline void Object::streamReset()

View File

@ -183,6 +183,22 @@ bool RtfAbstractReader::RtfAbstractReader::Parse(RtfDocument& oDocument, RtfRead
oReader.m_oLex.m_oFileWriter = m_oFileWriter;
int res = 0;
unsigned short nLastHigh = 0;
// only for 4 bytes wchar_t, returns true if high surrogate
auto handle_u32wchar_surrogate = [&nLastHigh] (std::wstring& res) -> bool {
if (res[0] >= 0xD800 && res[0] <= 0xDBFF) // high
{
nLastHigh = res[0];
return true;
}
if (nLastHigh && res[0] >= 0xDC00 && res[0] <= 0xDFFF) // low
res[0] = 0x10000 + ((wchar_t)(nLastHigh - 0xD800) << 10) + (res[0] - 0xDC00);
nLastHigh = 0;
return false;
};
m_oTok = oReader.m_oLex.NextCurToken();
if (m_oTok.Type == m_oTok.None)
@ -194,13 +210,14 @@ bool RtfAbstractReader::RtfAbstractReader::Parse(RtfDocument& oDocument, RtfRead
{
case RtfToken::GroupStart:
{
nLastHigh = 0;
ExecuteTextInternal2(oDocument, oReader, m_oTok.Key, m_nSkipChars);
PushState(oReader);
}break;
case RtfToken::GroupEnd:
{
nLastHigh = 0;
ExecuteTextInternal2(oDocument, oReader, m_oTok.Key, m_nSkipChars);
PopState(oDocument, oReader);
}break;
case RtfToken::Keyword:
@ -208,7 +225,11 @@ bool RtfAbstractReader::RtfAbstractReader::Parse(RtfDocument& oDocument, RtfRead
ExecuteTextInternal2(oDocument, oReader, m_oTok.Key, m_nSkipChars);
if (m_oTok.Key == "u")
{
ExecuteText(oDocument, oReader, ExecuteTextInternal(oDocument, oReader, m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter, m_nSkipChars));
std::wstring sRes = ExecuteTextInternal(oDocument, oReader, m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter, m_nSkipChars);
if (sizeof(wchar_t) == 4)
if (!sRes.empty() && handle_u32wchar_surrogate(sRes))
break;
ExecuteText(oDocument, oReader, std::move(sRes));
break;
}
else

View File

@ -11,15 +11,19 @@ platform = base.host_platform()
if platform == "windows":
platform_postfix = "win_64"
elif platform == "mac" and base.is_os_arm():
platform_postfix = "mac_arm64"
elif platform == "mac":
platform_postfix = "mac_64"
else:
platform_postfix = "linux_64"
print(f'Platform: {platform_postfix}')
x2t_build_dir = "../../../build/bin/" + platform_postfix + "/debug"
config.parse()
build_js.build_sdk_builder("../../../../sdkjs/build")
build_js.build_sdk_builder("../../../../onlyoffice/sdkjs/build")
if base.is_dir(x2t_build_dir + "/sdkjs"):
base.delete_dir(x2t_build_dir + "/sdkjs")