Merge remote-tracking branch 'origin/develop' into fix/pdf-rtl

# Conflicts:
#	DesktopEditor/graphics/commands/AnnotField.cpp
#	DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js
#	DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp
#	PdfFile/PdfWriter.cpp
#	PdfFile/SrcReader/PdfAnnot.cpp
This commit is contained in:
Svetlana Kulikova
2025-07-30 16:30:59 +03:00
1036 changed files with 17376 additions and 3710 deletions

View File

@ -1360,6 +1360,7 @@ CAnnotWidget::CAnnotWidget(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefI
oObj.fetch(xref, &oField);
oObj.free();
m_bChangeFullName = false;
m_dFontSize = 0.0;
m_unFontStyle = 0;
@ -1401,7 +1402,13 @@ CAnnotWidget::CAnnotWidget(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefI
oObj.free();
// 0 - Альтернативное имя поля, используется во всплывающей подсказке и сообщениях об ошибке - TU
m_sTU = FieldLookupString(pField, "TU", 0);
if (oField.dictLookup("TU", &oObj))
{
m_sTU = getValue(&oObj);
if (!m_sTU.empty())
m_unFlags |= (1 << 0);
}
oObj.free();
// 1 - Строка стиля по умолчанию - DS
m_sDS = FieldLookupString(pField, "DS", 1);
@ -1484,9 +1491,6 @@ CAnnotWidget::CAnnotWidget(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefI
m_sT = DictLookupString(&oField, "T", 18);
m_sFullName = m_sT;
// 20 - OO метаданные форм - OMetadata
m_sOMetadata = DictLookupString(&oField, "OMetadata", 20);
// 21 - MEOptions
if (oField.dictLookup("MEOptions", &oObj)->isInt())
{
@ -1605,11 +1609,11 @@ void CAnnotWidget::SetButtonFont(PDFDoc* pdfDoc, AcroFormField* pField, NSFonts:
}
bool CAnnotWidget::ChangeFullName(const std::string& sPrefixForm)
{
m_bChangeFullName = true;
if (m_unFlags & (1 << 18))
{
m_sT += sPrefixForm;
m_sFullName += sPrefixForm;
// ClearActions();
return true;
}
return false;
@ -2412,7 +2416,7 @@ CAnnotStamp::CAnnotStamp(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int
else
sy = (m_pRect[3] - m_pRect[1]) / (formYMax - formYMin);
double tx = -formXMin * sx + m_pRect[0];
double ty = -formYMin * sy + m_pRect[1];
double ty = -formYMin * sy - m_pRect[3] + m_dHeight;
m[0] *= sx;
m[1] *= sy;
@ -2436,6 +2440,149 @@ CAnnotStamp::CAnnotStamp(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int
oAnnot.free();
}
//------------------------------------------------------------------------
// Redact
//------------------------------------------------------------------------
CAnnotRedact::CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// 15 - Координаты - QuadPoints
if (oAnnot.dictLookup("QuadPoints", &oObj)->isArray())
{
m_unFlags |= (1 << 15);
for (int i = 0; i < oObj.arrayGetLength(); ++i)
{
if (oObj.arrayGet(i, &oObj2)->isNum())
m_arrQuadPoints.push_back(i % 2 == 0 ? oObj2.getNum() - m_dX : m_dHeight - oObj2.getNum());
oObj2.free();
}
}
oObj.free();
// 16 - Цвет заполнения - IC
if (oAnnot.dictLookup("IC", &oObj)->isArray())
{
m_unFlags |= (1 << 16);
for (int j = 0; j < oObj.arrayGetLength(); ++j)
{
m_arrIC.push_back(oObj.arrayGet(j, &oObj2)->isNum() ? oObj2.getNum() : 0.0);
oObj2.free();
}
}
oObj.free();
// RO во внешних видах
// 17 - Текст наложения - OverlayText
m_sOverlayText = DictLookupString(&oAnnot, "OverlayText", 17);
// 18 - Повторять текст - Repeat
if (oAnnot.dictLookup("Repeat", &oObj)->isBool() && oObj.getBool())
m_unFlags |= (1 << 18);
// 19 - Выравнивание текста - Q
m_nQ = 0;
if (oAnnot.dictLookup("Q", &oObj)->isInt())
{
m_unFlags |= (1 << 19);
m_nQ = oObj.getInt();
}
oObj.free();
oAnnot.free();
}
void CAnnotRedact::SetFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef)
{
Object oAnnot, oObj;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// 20 - Шрифт, размер, цвет текста замены - DA
if (oAnnot.dictLookup("DA", &oObj)->isString())
{
m_unFlags |= (1 << 20);
// parse the default appearance string
GList* daToks = tokenize(oObj.getString());
for (int i = daToks->getLength() - 1; i > 0; --i)
{
// handle the g operator
if (!((GString *)daToks->get(i))->cmp("G") && m_arrCFromDA.empty())
{
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString()));
}
// handle the rg operator
else if (i >= 3 && !((GString *)daToks->get(i))->cmp("RG") && m_arrCFromDA.empty())
{
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 3))->getCString()));
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 2))->getCString()));
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString()));
}
// handle the k operator
else if (i >= 4 && !((GString *)daToks->get(i))->cmp("K") && m_arrCFromDA.empty())
{
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 4))->getCString()));
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 3))->getCString()));
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 2))->getCString()));
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString()));
}
else if (i >= 2 && !((GString *)daToks->get(i))->cmp("Tf"))
{
m_dFontSize = atof(((GString *)daToks->get(i - 1))->getCString());
m_unFontStyle = 0;
}
}
deleteGList(daToks, GString);
}
oObj.free();
Object oAP, oN;
if (!oAnnot.dictLookup("RO", &oN)->isStream())
{
oN.free();
if (!oAnnot.dictLookup("AP", &oAP)->isDict() || !oAP.dictLookup("D", &oN)->isStream())
{
oAP.free(); oN.free(); oAnnot.free();
return;
}
}
oAP.free();
Object oFonts;
if (!CAnnotFonts::FindFonts(&oN, 0, &oFonts))
{
oN.free(); oFonts.free(); oAnnot.free();
return;
}
oN.free();
for (int i = 0, nFonts = oFonts.dictGetLength(); i < nFonts; ++i)
{
Object oFontRef;
if (!oFonts.dictGetValNF(i, &oFontRef)->isRef())
{
oFontRef.free();
continue;
}
std::string sFontName, sActualFontName;
bool bBold = false, bItalic = false;
std::wstring sFontPath = CAnnotFonts::GetFontData(pdfDoc, pFontManager, pFontList, &oFontRef, m_sFontName, m_sActualFontName, bBold, bItalic);
oFontRef.free();
m_unFontStyle = 0;
if (bBold)
m_unFontStyle |= (1 << 0);
if (bItalic)
m_unFontStyle |= (1 << 1);
}
oFonts.free(); oAnnot.free();
}
//------------------------------------------------------------------------
// Annots
//------------------------------------------------------------------------
@ -2729,6 +2876,17 @@ void CAnnots::getParents(PDFDoc* pdfDoc, Object* oFieldRef, int nStartRefID)
}
oObj.free();
// 10 - TU
if (oField.dictLookup("TU", &oObj)->isString())
{
TextString* s = new TextString(oObj.getString());
std::string sStr = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
pAnnotParent->unFlags |= (1 << 10);
pAnnotParent->sTU = sStr;
delete s;
}
oObj.free();
// 11 - MEOptions
if (oField.dictLookup("MEOptions", &oObj)->isInt())
{
@ -2766,7 +2924,7 @@ bool CAnnots::ChangeFullNameAnnot(int nAnnot, const std::string& sPrefixForm)
return false;
CAnnotWidget* pWidget = m_arrAnnots[nAnnot];
if (pWidget->ChangeFullName(sPrefixForm))
if (pWidget->m_bChangeFullName)
return true;
unsigned int unRefNumParent = pWidget->GetRefNumParent();
if (unRefNumParent)
@ -2774,12 +2932,16 @@ bool CAnnots::ChangeFullNameAnnot(int nAnnot, const std::string& sPrefixForm)
std::vector<CAnnotParent*>::iterator it = std::find_if(m_arrParents.begin(), m_arrParents.end(), [unRefNumParent](CAnnotParent* pP) { return pP->unRefNum == unRefNumParent; });
if (it != m_arrParents.end() && ChangeFullNameParent(std::distance(m_arrParents.begin(), it), sPrefixForm))
{
pWidget->AddFullName(sPrefixForm);
// pWidget->ClearActions();
const std::string& sFullNameChild = pWidget->GetFullName();
if (sFullNameChild.empty())
pWidget->SetFullName((*it)->sFullName);
else
pWidget->SetFullName((*it)->sFullName + "." + sFullNameChild);
pWidget->m_bChangeFullName = true;
return true;
}
}
return false;
return pWidget->ChangeFullName(sPrefixForm);
}
bool CAnnots::ChangeFullNameParent(int nParent, const std::string& sPrefixForm)
{
@ -2787,24 +2949,30 @@ bool CAnnots::ChangeFullNameParent(int nParent, const std::string& sPrefixForm)
return false;
CAnnotParent* pParent = m_arrParents[nParent];
if (pParent->unFlags & (1 << 0))
{
pParent->sT += sPrefixForm;
pParent->sFullName += sPrefixForm;
// pParent->ClearActions();
if (pParent->bChangeFullName)
return true;
}
else if (pParent->unFlags & (1 << 4))
if (pParent->unFlags & (1 << 4))
{
unsigned int unRefNumParent = pParent->unRefNumParent;
std::vector<CAnnotParent*>::iterator it = std::find_if(m_arrParents.begin(), m_arrParents.end(), [unRefNumParent](CAnnotParent* pP) { return pP->unRefNum == unRefNumParent; });
if (it != m_arrParents.end() && ChangeFullNameParent(std::distance(m_arrParents.begin(), it), sPrefixForm))
{
pParent->sFullName += sPrefixForm;
// pParent->ClearActions();
if (pParent->sT.empty())
pParent->sFullName = (*it)->sFullName;
else
pParent->sFullName = (*it)->sFullName + "." + sPrefixForm;
pParent->bChangeFullName = true;
return true;
}
}
else if (pParent->unFlags & (1 << 0))
{
pParent->sT += sPrefixForm;
pParent->sFullName += sPrefixForm;
pParent->bChangeFullName = true;
return true;
}
return false;
}
void CAnnots::CAnnotParent::ClearActions()
@ -3162,6 +3330,16 @@ CAnnot::CAnnot(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefID)
delete s;
}
oObj.free();
// 9 - OO метаданные форм - OMetadata
if (pField->fieldLookup("OMetadata", &oObj)->isString())
{
m_unAFlags |= (1 << 9);
TextString* s = new TextString(oObj.getString());
m_sOMetadata = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
}
CAnnot::CAnnot(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID)
{
@ -3289,6 +3467,9 @@ CAnnot::CAnnot(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefI
}
oObj.free();
// 9 - OO метаданные форм - OMetadata
m_sOMetadata = DictLookupString(&oAnnot, "OMetadata", 9);
oAnnot.free();
}
CAnnot::~CAnnot()
@ -3763,6 +3944,8 @@ void CAnnots::CAnnotParent::ToWASM(NSWasm::CData& oRes)
}
if (unFlags & (1 << 9))
oRes.AddInt(unMaxLen);
if (unFlags & (1 << 10))
oRes.WriteString(sTU);
if (unFlags & (1 << 11))
oRes.AddInt(unMEOptions);
}
@ -3795,6 +3978,8 @@ void CAnnot::ToWASM(NSWasm::CData& oRes)
oRes.WriteString(m_sM);
if (m_unAFlags & (1 << 7))
oRes.WriteString(m_sOUserID);
if (m_unAFlags & (1 << 9))
oRes.WriteString(m_sOMetadata);
}
void CAnnot::CBorderType::ToWASM(NSWasm::CData& oRes)
{
@ -3860,8 +4045,6 @@ void CAnnotWidget::ToWASM(NSWasm::CData& oRes)
oRes.WriteString(m_sT);
if (m_unFlags & (1 << 19))
oRes.WriteString(m_sButtonFontName);
if (m_unFlags & (1 << 20))
oRes.WriteString(m_sOMetadata);
if (m_unFlags & (1 << 21))
oRes.AddInt(m_unMEOptions);
oRes.AddInt(m_arrAction.size());
@ -4347,4 +4530,37 @@ void CAnnotStamp::ToWASM(NSWasm::CData& oRes)
oRes.WriteDouble(m_dX4);
oRes.WriteDouble(m_dY4);
}
void CAnnotRedact::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(25); // Redact
CAnnotMarkup::ToWASM(oRes);
if (m_unFlags & (1 << 15))
{
oRes.AddInt((unsigned int)m_arrQuadPoints.size());
for (int i = 0; i < m_arrQuadPoints.size(); ++i)
oRes.AddDouble(m_arrQuadPoints[i]);
}
if (m_unFlags & (1 << 16))
{
oRes.AddInt((unsigned int)m_arrIC.size());
for (int i = 0; i < m_arrIC.size(); ++i)
oRes.WriteDouble(m_arrIC[i]);
}
if (m_unFlags & (1 << 17))
oRes.WriteString(m_sOverlayText);
if (m_unFlags & (1 << 19))
oRes.WriteBYTE(m_nQ);
if (m_unFlags & (1 << 20))
{
oRes.AddInt((unsigned int)m_arrCFromDA.size());
for (int i = 0; i < m_arrCFromDA.size(); ++i)
oRes.WriteDouble(m_arrCFromDA[i]);
oRes.AddDouble(m_dFontSize);
oRes.WriteString(m_sFontName);
oRes.WriteString(m_sActualFontName);
oRes.AddInt(m_unFontStyle);
}
}
}

View File

@ -204,6 +204,7 @@ private:
std::string m_sNM; // Уникальное имя
std::string m_sM; // Дата последнего изменения
std::string m_sOUserID; // OO User ID
std::string m_sOMetadata; // OO метаданные формы
std::vector<double> m_arrC; // Специальный цвет
CBorderType* m_pBorder; // Граница
};
@ -222,12 +223,13 @@ public:
unsigned int GetRefNumParent() { return m_unRefNumParent; }
const std::string& GetFullName() { return m_sFullName; }
void SetFullName(const std::string& sFullName) { m_sFullName = sFullName; }
void AddFullName(const std::string& sPrefixForm) { m_sFullName += sPrefixForm; }
bool ChangeFullName(const std::string& sPrefixForm);
void ClearActions();
virtual std::string GetType() = 0;
virtual void ToWASM(NSWasm::CData& oRes) override;
bool m_bChangeFullName;
protected:
CAnnotWidget(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefID);
@ -255,7 +257,6 @@ private:
std::string m_sFontKey; // Уникальный идентификатор шрифта
std::string m_sFullName; // Полное имя поля
std::string m_sFontName; // Имя шрифта - из DA
std::string m_sOMetadata; // OO метаданные формы
std::string m_sActualFontName; // Имя замененного шрифта
std::string m_sButtonFontName; // Имя шрифта кнопки
};
@ -591,12 +592,38 @@ public:
CAnnotStamp(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID);
void ToWASM(NSWasm::CData& oRes) override;
private:
std::string m_sName; // Иконка
double m_dRotate;
double m_dX1, m_dY1, m_dX2, m_dY2, m_dX3, m_dY3, m_dX4, m_dY4;
};
//------------------------------------------------------------------------
// PdfReader::CAnnotRedact
//------------------------------------------------------------------------
class CAnnotRedact final : public CAnnotMarkup
{
public:
CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID);
void SetFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef);
void ToWASM(NSWasm::CData& oRes) override;
private:
BYTE m_nQ; // Выравнивание текста
unsigned int m_unFontStyle; // Стиль шрифта - из DA
double m_dFontSize; // Размер шрифта - из DA
std::string m_sFontName; // Имя шрифта - из DA
std::string m_sActualFontName; // Имя замененного шрифта
std::string m_sOverlayText; // Текст наложения
std::vector<double> m_arrQuadPoints; // Координаты
std::vector<double> m_arrIC; // Цвет заполнения
std::vector<double> m_arrCFromDA; // Цвет текста
};
//------------------------------------------------------------------------
// PdfReader::CAnnots
//------------------------------------------------------------------------
@ -620,6 +647,7 @@ private:
unFlags = 0;
unRefNum = 0;
unRefNumParent = 0;
bChangeFullName = false;
}
~CAnnotParent()
{
@ -629,6 +657,7 @@ private:
void ToWASM(NSWasm::CData& oRes);
bool bChangeFullName;
unsigned int unFlags;
unsigned int unRefNum; // Номер ссылки на объект
unsigned int unMaxLen; // Ограничение на максимальную длину text field
@ -642,6 +671,7 @@ private:
std::string sT;
std::string sV;
std::string sDV;
std::string sTU;
std::string sFullName;
};
@ -665,7 +695,6 @@ public:
static bool GetFontFromAP(PDFDoc* pdfDoc, AcroFormField* pField, Object* oFontRef, std::string& sFontKey);
static std::map<std::wstring, std::wstring> GetAnnotFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef);
static std::map<std::wstring, std::wstring> GetFreeTextFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, Object* oAnnotRef, std::vector<CAnnotMarkup::CFontData*>& arrRC);
private:
static bool FindFonts(Object* oStream, int nDepth, Object* oResFonts);
};

View File

@ -742,6 +742,15 @@ namespace PdfReader
oFontDescriptor.dictLookup("FontBBox", &oDictItem);
oDictItem.free();
oFontDescriptor.dictLookup("Flags", &oDictItem);
if (oDictItem.isInt() && 0 != oDictItem.getInt())
{
int nFlags = oDictItem.getInt();
if (nFlags & 1) // моноширинный
oFontSelect.bFixedWidth = new INT(1);
}
oDictItem.free();
oFontDescriptor.dictLookup("ItalicAngle", &oDictItem);
if (oDictItem.isInt() && 0 != oDictItem.getInt())
{
@ -2414,6 +2423,7 @@ namespace PdfReader
arrMatrix[4] = pNewTm[4] * pCTM[0] + pNewTm[5] * pCTM[2] + pCTM[4];
arrMatrix[5] = -(pNewTm[4] * pCTM[1] + pNewTm[5] * pCTM[3] + pCTM[5]) + pGState->getPageHeight();
double dSize = 1;
if (true)
{
double dNorma = std::min(sqrt(arrMatrix[0] * arrMatrix[0] + arrMatrix[1] * arrMatrix[1]), sqrt(arrMatrix[2] * arrMatrix[2] + arrMatrix[3] * arrMatrix[3]));
@ -2424,9 +2434,9 @@ namespace PdfReader
arrMatrix[2] /= dNorma;
arrMatrix[3] /= dNorma;
double dSize = 1;
m_pRenderer->get_FontSize(&dSize);
m_pRenderer->put_FontSize(dSize * dNorma);
dSize *= dNorma;
m_pRenderer->put_FontSize(dSize);
if (nRenderMode == 1 || nRenderMode == 2 || nRenderMode == 5 || nRenderMode == 6)
m_pRenderer->put_PenSize(PDFCoordsToMM(pGState->getLineWidth() * dNorma));
}
@ -2491,9 +2501,12 @@ namespace PdfReader
{
unsigned int lUnicode = (unsigned int)wsUnicodeText[0];
long lStyle;
double dDpiX, dDpiY;
m_pRenderer->get_FontStyle(&lStyle);
m_pRenderer->get_DpiX(&dDpiX);
m_pRenderer->get_DpiY(&dDpiY);
m_pFontManager->SetStringGID(FALSE);
m_pFontManager->LoadFontFromFile(sFontPath, 0, dOldSize, 72, 72);
m_pFontManager->LoadFontFromFile(sFontPath, 0, dOldSize, dDpiX, dDpiY);
NSFonts::IFontFile* pFontFile = m_pFontManager->GetFile();
if (pFontFile)
@ -2529,7 +2542,7 @@ namespace PdfReader
return;
}
m_pRenderer->put_FontPath(wsFileName);
m_pFontManager->LoadFontFromFile(wsFileName, 0, dOldSize, 72, 72);
m_pFontManager->LoadFontFromFile(wsFileName, 0, dSize, dDpiX, dDpiY);
bReplace = true;
}
}