diff --git a/DesktopEditor/doctrenderer/drawingfile.h b/DesktopEditor/doctrenderer/drawingfile.h index e35e645523..24bd1fd258 100644 --- a/DesktopEditor/doctrenderer/drawingfile.h +++ b/DesktopEditor/doctrenderer/drawingfile.h @@ -311,7 +311,7 @@ public: return ((CPdfFile*)m_pFile)->UnmergePages(); return false; } - bool RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX4, BYTE* data, int size, bool bCopy = false) + bool RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX8, BYTE* data, int size, bool bCopy = false) { if (m_nType == 0) { @@ -323,7 +323,7 @@ public: data = pCopy; } // Захватывает полученную память data - return ((CPdfFile*)m_pFile)->RedactPage(nPageIndex, arrRedactBox, nLengthX4, data, size); + return ((CPdfFile*)m_pFile)->RedactPage(nPageIndex, arrRedactBox, nLengthX8, data, size); } return false; } diff --git a/DesktopEditor/fontengine/FontFile.cpp b/DesktopEditor/fontengine/FontFile.cpp index f6075cfb79..e3840f70b7 100644 --- a/DesktopEditor/fontengine/FontFile.cpp +++ b/DesktopEditor/fontengine/FontFile.cpp @@ -1046,6 +1046,28 @@ int CFontFile::GetGIDByUnicode(int code) return unGID; } +int CFontFile::GetUnicodeByGID(int gid) +{ + if (!m_pFace) + return 0; + + FT_ULong charcode; + FT_UInt gindex; + + charcode = FT_Get_First_Char(m_pFace, &gindex); + + while (gindex != 0) + { + if (gindex == gid) + { + return charcode; + } + charcode = FT_Get_Next_Char(m_pFace, charcode, &gindex); + } + + return 0; +} + INT CFontFile::GetString(CGlyphString& oString) { int nCountGlyph = oString.GetLength(); diff --git a/DesktopEditor/fontengine/FontFile.h b/DesktopEditor/fontengine/FontFile.h index e271978bad..da0ea7ff65 100644 --- a/DesktopEditor/fontengine/FontFile.h +++ b/DesktopEditor/fontengine/FontFile.h @@ -254,6 +254,7 @@ public: double GetCharWidth(int gid); int GetGIDByUnicode(int code); + int GetUnicodeByGID(int gid); int GetKerning(FT_UInt unPrevGID, FT_UInt unGID); void SetStringGID(const INT& bGID); diff --git a/DesktopEditor/fontengine/FontManager.cpp b/DesktopEditor/fontengine/FontManager.cpp index 875691f15b..6db559cd1e 100644 --- a/DesktopEditor/fontengine/FontManager.cpp +++ b/DesktopEditor/fontengine/FontManager.cpp @@ -851,6 +851,14 @@ unsigned int CFontManager::GetGIDByUnicode(const unsigned int& unCode) return m_pFont->GetGIDByUnicode(unCode); } +int CFontManager::GetUnicodeByGID(const int& gid) +{ + if (!m_pFont) + return 0; + + return m_pFont->GetUnicodeByGID(gid); +} + void CFontManager::SetSubpixelRendering(const bool& hmul, const bool& vmul) { if (hmul) diff --git a/DesktopEditor/fontengine/FontManager.h b/DesktopEditor/fontengine/FontManager.h index 1b88d218cf..553e8300fd 100644 --- a/DesktopEditor/fontengine/FontManager.h +++ b/DesktopEditor/fontengine/FontManager.h @@ -186,6 +186,7 @@ public: virtual std::wstring GetFontType(); virtual unsigned int GetNameIndex(const std::wstring& wsName); virtual unsigned int GetGIDByUnicode(const unsigned int& unCode); + virtual int GetUnicodeByGID(const int& gid); virtual void SetSubpixelRendering(const bool& hmul, const bool& vmul); diff --git a/DesktopEditor/graphics/BooleanOperations.cpp b/DesktopEditor/graphics/BooleanOperations.cpp index fec8dc879f..1e5d58890c 100644 --- a/DesktopEditor/graphics/BooleanOperations.cpp +++ b/DesktopEditor/graphics/BooleanOperations.cpp @@ -1188,7 +1188,10 @@ void CBooleanOperations::TracePaths() Segment tmp = GetNextSegment(prev.Inters->S); if (tmp.IsEmpty()) break; if (tmp.IsValid(Op)) + { s = tmp; + valid = true; + } } if (!valid && prev.Inters) @@ -1419,7 +1422,7 @@ void CBooleanOperations::CreateNewPath(const std::vector>& adjM break; auto add_seg = [&](int x, int prev_x) { - for (size_t j = adjMatr[x].size() - 1; j >= 0; j--) + for (int j = adjMatr[x].size() - 1; j >= 0; j--) { int ver = adjMatr[x][j]; if (seg_visited[ver] || ver == prev_x) @@ -1514,7 +1517,7 @@ void CBooleanOperations::CreateNewPath(const std::vector>& adjM return j; } } - x = x + 1; + x = (x >= Curves1.size() - 1) ? 0 : x + 1; prev_x = -1; if (Curves1[x].Segment2.IsCurve) Result.CurveTo(Curves1[x].Segment2.HI.X + Curves1[x].Segment2.P.X, Curves1[x].Segment2.HI.Y + Curves1[x].Segment2.P.Y, @@ -2378,17 +2381,17 @@ CGraphicsPath CalcBooleanOperation(const CGraphicsPath& path1, return op == Subtraction ? CGraphicsPath(paths1) : CGraphicsPath(paths); } -//For unit-tests -bool CGraphicsPath::operator==(const CGraphicsPath& other) noexcept +// For Unit-tests +bool CGraphicsPath::Equals(const CGraphicsPath& other) noexcept { unsigned pointsCount = GetPointCount(), - otherPointsCount = other.GetPointCount(); + otherPointsCount = other.GetPointCount(); if (pointsCount != otherPointsCount) return false; std::vector points = GetPoints(0, pointsCount), - otherPoints = other.GetPoints(0, otherPointsCount); + otherPoints = other.GetPoints(0, otherPointsCount); for (unsigned i = 0; i < pointsCount; i++) if (getDistance(points[i], otherPoints[i]) > POINT_EPSILON) diff --git a/DesktopEditor/graphics/GraphicsPath.cpp b/DesktopEditor/graphics/GraphicsPath.cpp index f2bb27f2ba..c77a08ef89 100644 --- a/DesktopEditor/graphics/GraphicsPath.cpp +++ b/DesktopEditor/graphics/GraphicsPath.cpp @@ -76,7 +76,7 @@ namespace Aggplus j += 2; } } - if (p.Is_poly_closed()) CloseFigure(); + //if (p.Is_poly_closed()) CloseFigure(); } } } @@ -917,14 +917,11 @@ namespace Aggplus PointD firstPoint = subPath.GetPoints(0, 1)[0]; double x, y; subPath.GetLastPoint(x, y); - if ((abs(firstPoint.X - x) <= 1e-2 && abs(firstPoint.Y - y) <= 1e-2) || + if ((abs(firstPoint.X - x) >= 1e-2 || abs(firstPoint.Y - y) >= 1e-2) || subPath.GetPointCount() == 1) - { - if (!firstPoint.Equals(PointD(x, y)) || subPath.GetPointCount() == 1) - subPath.LineTo(firstPoint.X, firstPoint.Y); - subPath.CloseFigure(); - } + subPath.LineTo(firstPoint.X, firstPoint.Y); + subPath.CloseFigure(); result.push_back(subPath); subPath.Reset(); } @@ -952,7 +949,7 @@ namespace Aggplus double x, y; subPath.GetLastPoint(x, y); - if (!firstPoint.Equals(PointD(x, y)) || subPath.GetPointCount() == 1) + if ((abs(firstPoint.X - x) >= 1e-2 || abs(firstPoint.Y - y) >= 1e-2) || subPath.GetPointCount() == 1) subPath.LineTo(firstPoint.X, firstPoint.Y); subPath.CloseFigure(); @@ -1006,6 +1003,24 @@ namespace Aggplus return *this; } + + bool CGraphicsPath::operator==(const CGraphicsPath& other) noexcept + { + unsigned pointsCount = GetPointCount(), + otherPointsCount = other.GetPointCount(); + + if (pointsCount != otherPointsCount) + return false; + + std::vector points = GetPoints(0, pointsCount), + otherPoints = other.GetPoints(0, otherPointsCount); + + for (unsigned i = 0; i < pointsCount; i++) + if (!points[i].Equals(otherPoints[i])) + return false; + + return true; + } } namespace Aggplus diff --git a/DesktopEditor/graphics/GraphicsPath.h b/DesktopEditor/graphics/GraphicsPath.h index f9023554f5..f067efdb97 100644 --- a/DesktopEditor/graphics/GraphicsPath.h +++ b/DesktopEditor/graphics/GraphicsPath.h @@ -117,6 +117,7 @@ namespace Aggplus std::vector GetPoints(unsigned idx, unsigned count) const noexcept; std::vector GetSubPaths() const; + bool Equals(const CGraphicsPath& other) noexcept; CGraphicsPath& operator=(const CGraphicsPath& other) noexcept; CGraphicsPath& operator=(CGraphicsPath&& other) noexcept; bool operator==(const CGraphicsPath& other) noexcept; diff --git a/DesktopEditor/graphics/aggplustypes.h b/DesktopEditor/graphics/aggplustypes.h index c6a231dc08..7240561b83 100644 --- a/DesktopEditor/graphics/aggplustypes.h +++ b/DesktopEditor/graphics/aggplustypes.h @@ -212,7 +212,7 @@ public: void Offset(const PointF_T& point) { Offset(point.X, point.Y); } void Offset(T dx, T dy) { X += dx; Y += dy; } - inline bool IsPositive() { return X >= 0 && Y >= 0 && Width > 0 && Height > 0; } + inline bool IsPositive() { return Width > 0 && Height > 0; } public: T X, Y, Width, Height; diff --git a/DesktopEditor/graphics/commands/AnnotField.cpp b/DesktopEditor/graphics/commands/AnnotField.cpp index b65298baf7..d3ce7dfb8d 100644 --- a/DesktopEditor/graphics/commands/AnnotField.cpp +++ b/DesktopEditor/graphics/commands/AnnotField.cpp @@ -1239,11 +1239,19 @@ bool CRedact::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafileToRe SRedact* pRedact = new SRedact(); pRedact->sID = pReader->ReadString(); int m = pReader->ReadInt(); - pRedact->arrQuadPoints.reserve(m * 4); + pRedact->arrQuadPoints.reserve(m * 8); for (int j = 0; j < m; ++j) { - for (int k = 0; k < 4; ++k) - pRedact->arrQuadPoints.push_back(pReader->ReadDouble()); + pRedact->arrQuadPoints.push_back(pReader->ReadDouble()); + pRedact->arrQuadPoints.push_back(pReader->ReadDouble()); + pRedact->arrQuadPoints.push_back(pReader->ReadDouble()); + pRedact->arrQuadPoints.push_back(pReader->ReadDouble()); + double x = pReader->ReadDouble(); + double y = pReader->ReadDouble(); + pRedact->arrQuadPoints.push_back(pReader->ReadDouble()); + pRedact->arrQuadPoints.push_back(pReader->ReadDouble()); + pRedact->arrQuadPoints.push_back(x); + pRedact->arrQuadPoints.push_back(y); } pRedact->nFlag = pReader->ReadInt(); if (pRedact->nFlag & (1 << 0)) diff --git a/DesktopEditor/graphics/pro/Fonts.h b/DesktopEditor/graphics/pro/Fonts.h index d41a82ee79..5fc78d93ac 100644 --- a/DesktopEditor/graphics/pro/Fonts.h +++ b/DesktopEditor/graphics/pro/Fonts.h @@ -639,6 +639,7 @@ namespace NSFonts virtual double GetCharWidth(int gid) = 0; virtual int GetGIDByUnicode(int code) = 0; + virtual int GetUnicodeByGID(int gid) = 0; virtual int GetEmbeddingLicenceType() = 0; virtual void FillFontSelectFormat(CFontSelectFormat& oFormat) = 0; @@ -736,6 +737,7 @@ namespace NSFonts virtual unsigned int GetNameIndex(const std::wstring& wsName) = 0; virtual unsigned int GetGIDByUnicode(const unsigned int& unCode) = 0; + virtual int GetUnicodeByGID(const int& gid) = 0; virtual void GetFace(double& d0, double& d1, double& d2) = 0; virtual void GetLimitsY(double& dMin, double& dMax) = 0; diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js index 0b3c07ac68..056b55a0bf 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js @@ -145,9 +145,9 @@ CFile.prototype["isNeedPassword"] = function() { return this._isNeedPassword; }; -CFile.prototype["SplitPages"] = function(arrPageIndex, arrayBufferChanges) +CFile.prototype["SplitPages"] = function(arrOriginIndex, arrayBufferChanges) { - let ptr = this._SplitPages(arrPageIndex, arrayBufferChanges); + let ptr = this._SplitPages(arrOriginIndex, arrayBufferChanges); let res = ptr.getMemory(true); ptr.free(); return res; @@ -160,9 +160,9 @@ CFile.prototype["UndoMergePages"] = function() { return this._UndoMergePages(); }; -CFile.prototype["RedactPage"] = function(pageIndex, arrRedactBox, arrayBufferFiller) +CFile.prototype["RedactPage"] = function(originIndex, arrRedactBox, arrayBufferFiller) { - return this._RedactPage(pageIndex, arrRedactBox, arrayBufferFiller); + return this._RedactPage(originIndex, arrRedactBox, arrayBufferFiller); }; CFile.prototype["UndoRedact"] = function() { @@ -259,9 +259,9 @@ CFile.prototype["getStructure"] = function() return res; }; -CFile.prototype["getLinks"] = function(pageIndex) +CFile.prototype["getLinks"] = function(originIndex) { - let ptr = this._getLinks(pageIndex); + let ptr = this._getLinks(originIndex); let reader = ptr.getReader(); if (!reader) return []; @@ -284,11 +284,12 @@ CFile.prototype["getLinks"] = function(pageIndex) }; // TEXT -CFile.prototype["getGlyphs"] = function(pageIndex) +CFile.prototype["getGlyphs"] = function(originIndex) { + let pageIndex = this.pages.findIndex(function(page) { + return page.originIndex == originIndex; + }); let page = this.pages[pageIndex]; - if (page.originIndex == undefined) - return []; if (page.fonts.length > 0) { // waiting fonts @@ -296,7 +297,7 @@ CFile.prototype["getGlyphs"] = function(pageIndex) } this.lockPageNumForFontsLoader(pageIndex, UpdateFontsSource.Page); - let res = this._getGlyphs(page.originIndex); + let res = this._getGlyphs(originIndex); // there is no need to delete the result; this buffer is used as a text buffer // for text commands on other pages. After receiving ALL text pages, // you need to call destroyTextInfo() @@ -1407,7 +1408,7 @@ CFile.prototype["getInteractiveFormsInfo"] = function() // optional nWidget - rec["AP"]["i"] // optional sView - N/D/R // optional sButtonView - state pushbutton-annotation - Off/Yes(or rec["ExportValue"]) -CFile.prototype["getInteractiveFormsAP"] = function(pageIndex, width, height, backgroundColor, nWidget, sView, sButtonView) +CFile.prototype["getInteractiveFormsAP"] = function(originIndex, width, height, backgroundColor, nWidget, sView, sButtonView) { let nView = -1; if (sView) @@ -1423,8 +1424,11 @@ CFile.prototype["getInteractiveFormsAP"] = function(pageIndex, width, height, ba if (sButtonView) nButtonView = (sButtonView == "Off" ? 0 : 1); + let pageIndex = this.pages.findIndex(function(page) { + return page.originIndex == originIndex; + }); this.lockPageNumForFontsLoader(pageIndex, UpdateFontsSource.Forms); - let ptr = this._getInteractiveFormsAP(width, height, backgroundColor, pageIndex, nWidget, nView, nButtonView); + let ptr = this._getInteractiveFormsAP(width, height, backgroundColor, originIndex, nWidget, nView, nButtonView); let reader = ptr.getReader(); this.unlockPageNumForFontsLoader(); @@ -1509,13 +1513,13 @@ CFile.prototype["getButtonIcons"] = function(pageIndex, width, height, backgroun ptr.free(); return res; }; -// optional pageIndex - get annotations from specific page -CFile.prototype["getAnnotationsInfo"] = function(pageIndex) +// optional originIndex - get annotations from specific page +CFile.prototype["getAnnotationsInfo"] = function(originIndex) { if (!this.nativeFile) return []; - let ptr = this._getAnnotationsInfo(pageIndex); + let ptr = this._getAnnotationsInfo(originIndex); let reader = ptr.getReader(); if (!reader) return []; @@ -1547,7 +1551,7 @@ CFile.prototype["getAnnotationsInfo"] = function(pageIndex) }; // optional nAnnot ... // optional sView ... -CFile.prototype["getAnnotationsAP"] = function(pageIndex, width, height, backgroundColor, nAnnot, sView) +CFile.prototype["getAnnotationsAP"] = function(originIndex, width, height, backgroundColor, nAnnot, sView) { let nView = -1; if (sView) @@ -1560,8 +1564,11 @@ CFile.prototype["getAnnotationsAP"] = function(pageIndex, width, height, backgro nView = 2; } + let pageIndex = this.pages.findIndex(function(page) { + return page.originIndex == originIndex; + }); this.lockPageNumForFontsLoader(pageIndex, UpdateFontsSource.Annotation); - let ptr = this._getAnnotationsAP(width, height, backgroundColor, pageIndex, nAnnot, nView); + let ptr = this._getAnnotationsAP(width, height, backgroundColor, originIndex, nAnnot, nView); let reader = ptr.getReader(); this.unlockPageNumForFontsLoader(); diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_wasm.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_wasm.js index cb22d3311c..be1c6a32d4 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_wasm.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_wasm.js @@ -211,7 +211,7 @@ CFile.prototype._RedactPage = function(pageIndex, arrRedactBox, arrayBufferFille let pointer = Module["_malloc"](memoryBuffer.length * 4); Module["HEAP32"].set(memoryBuffer, pointer >> 2); - let bRes = Module["_RedactPage"](this.nativeFile, pageIndex, pointer, memoryBuffer.length / 4, changesPtr, changesLen); + let bRes = Module["_RedactPage"](this.nativeFile, pageIndex, pointer, memoryBuffer.length / 8, changesPtr, changesLen); changesPtr = 0; // Success or not, changesPtr is either taken or freed Module["_free"](pointer); diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp index 23717a3125..e73a0557b8 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp @@ -178,12 +178,12 @@ WASM_EXPORT int UnmergePages(CDrawingFile* pFile) { return pFile->UnmergePages() ? 1 : 0; } -WASM_EXPORT int RedactPage(CDrawingFile* pFile, int nPageIndex, int* arrRedactBox, int nLengthX4, BYTE* data, int size) +WASM_EXPORT int RedactPage(CDrawingFile* pFile, int nPageIndex, int* arrRedactBox, int nLengthX8, BYTE* data, int size) { - double* arrDRedactBox = new double[nLengthX4 * 4]; - for (int i = 0; i < nLengthX4 * 4; ++i) + double* arrDRedactBox = new double[nLengthX8 * 8]; + for (int i = 0; i < nLengthX8 * 8; ++i) arrDRedactBox[i] = arrRedactBox[i] / 10000.0; - int nRes = pFile->RedactPage(nPageIndex, arrDRedactBox, nLengthX4, data, size) ? 1 : 0; + int nRes = pFile->RedactPage(nPageIndex, arrDRedactBox, nLengthX8, data, size) ? 1 : 0; delete[] arrDRedactBox; return nRes; } diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp index bd21fdbdf7..4f4d9dc439 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp @@ -976,6 +976,8 @@ bool GetFromBase64(const std::wstring& sPath, BYTE** pBuffer, int* nBufferLen) if (!NSBase64::Base64Decode((const char*)pFileContent, dwFileSize, *pBuffer, nBufferLen)) return false; } + else + return false; oFile.CloseFile(); return true; } @@ -1044,54 +1046,42 @@ int main(int argc, char* argv[]) RELEASEARRAYOBJECTS(pFileData); // SPLIT & MERGE - if (false) + if (true) { int nBufferLen = NULL; BYTE* pBuffer = NULL; - if (GetFromBase64(NSFile::GetProcessDirectory() + L"/split1.txt", &pBuffer, &nBufferLen)) + if (true && GetFromBase64(NSFile::GetProcessDirectory() + L"/split.txt", &pBuffer, &nBufferLen)) { - std::vector arrPages = { 0 }; + std::vector arrPages = { 2 }; BYTE* pSplitPages = SplitPages(pGrFile, arrPages.data(), arrPages.size(), pBuffer, nBufferLen); int nLength = READ_INT(pSplitPages); if (nLength > 4) { NSFile::CFileBinary oFile; - if (oFile.CreateFileW(NSFile::GetProcessDirectory() + L"/split1.pdf")) + if (oFile.CreateFileW(NSFile::GetProcessDirectory() + L"/split.pdf")) oFile.WriteFile(pSplitPages + 4, nLength - 4); oFile.CloseFile(); - - BYTE* pMallocData = (BYTE*)malloc(nLength - 4); - memcpy(pMallocData, pSplitPages + 4, nLength - 4); - - MergePages(pGrFile, pMallocData, nLength - 4, 0, "merge1"); } RELEASEARRAYOBJECTS(pSplitPages); } RELEASEARRAYOBJECTS(pBuffer); - if (GetFromBase64(NSFile::GetProcessDirectory() + L"/split2.txt", &pBuffer, &nBufferLen)) + if (true) { - std::vector arrPages = { 0 }; - BYTE* pSplitPages = SplitPages(pGrFile, arrPages.data(), arrPages.size(), pBuffer, nBufferLen); - int nLength = READ_INT(pSplitPages); - - if (nLength > 4) + NSFile::CFileBinary oFile; + if (oFile.OpenFile(NSFile::GetProcessDirectory() + L"/split.pdf")) { - NSFile::CFileBinary oFile; - if (oFile.CreateFileW(NSFile::GetProcessDirectory() + L"/split2.pdf")) - oFile.WriteFile(pSplitPages + 4, nLength - 4); - oFile.CloseFile(); + DWORD dwFileSize = oFile.GetFileSize(); + BYTE* pFileContent = (BYTE*)malloc(dwFileSize); - BYTE* pMallocData = (BYTE*)malloc(nLength - 4); - memcpy(pMallocData, pSplitPages + 4, nLength - 4); - - MergePages(pGrFile, pMallocData, nLength - 4, 0, "merge2"); + DWORD dwReaded; + if (oFile.ReadFile(pFileContent, dwFileSize, dwReaded)) + MergePages(pGrFile, pFileContent, dwReaded, 0, "merge1"); } - RELEASEARRAYOBJECTS(pSplitPages); + oFile.CloseFile(); } - RELEASEARRAYOBJECTS(pBuffer); } // INFO @@ -1137,9 +1127,9 @@ int main(int argc, char* argv[]) BYTE* pColor = new BYTE[12] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // REDACT - if (true) + if (false) { - int pRect[4] = { 307499, 217499, 1799999, 1124999 }; + int pRect[8] = { 307499, 217499, 307499, 1124999, 1799999, 1124999, 1799999, 217499 }; if (!RedactPage(pGrFile, nTestPage, pRect, 1, pColor, 12)) std::cout << "Redact false" << std::endl; } diff --git a/DesktopEditor/graphics/tests/BooleanOperations_Unit-tests/tst_booleanoperations.cpp b/DesktopEditor/graphics/tests/BooleanOperations_Unit-tests/tst_booleanoperations.cpp index 02d6720c40..5b37ea84e1 100644 --- a/DesktopEditor/graphics/tests/BooleanOperations_Unit-tests/tst_booleanoperations.cpp +++ b/DesktopEditor/graphics/tests/BooleanOperations_Unit-tests/tst_booleanoperations.cpp @@ -50,9 +50,9 @@ TEST(BooleanOperations, NoIntersOutside) resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, NoIntersInside) @@ -105,9 +105,9 @@ TEST(BooleanOperations, NoIntersInside) resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, OneIntersOutside) @@ -154,9 +154,9 @@ TEST(BooleanOperations, OneIntersOutside) resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, OneIntersInside) @@ -206,9 +206,9 @@ TEST(BooleanOperations, OneIntersInside) resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, OverlapOutside) @@ -258,9 +258,9 @@ TEST(BooleanOperations, OverlapOutside) resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, OverlapInside) @@ -312,9 +312,9 @@ TEST(BooleanOperations, OverlapInside) resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, LineIntersLine) @@ -368,9 +368,9 @@ TEST(BooleanOperations, LineIntersLine) resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, CurveIntersLine) @@ -415,9 +415,9 @@ TEST(BooleanOperations, CurveIntersLine) resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, CurveIntersCurve) @@ -453,9 +453,9 @@ TEST(BooleanOperations, CurveIntersCurve) resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, RectIntersRect) @@ -508,9 +508,9 @@ TEST(BooleanOperations, RectIntersRect) resultSubtract.LineTo(55.0, 25.0); resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, EllipseIntersEllipse) @@ -550,9 +550,9 @@ TEST(BooleanOperations, EllipseIntersEllipse) resultSubtract.CurveTo(303.228, 82.0, 348.0, 126.772, 348.0, 182.0); resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, EllipseIntersCross) @@ -621,9 +621,9 @@ TEST(BooleanOperations, EllipseIntersCross) resultSubtract.CurveTo(188.228, 60, 233, 104.772, 233, 160); resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, TriangleIntersEllipse) @@ -665,9 +665,9 @@ TEST(BooleanOperations, TriangleIntersEllipse) resultSubtract.CurveTo(243.078, 286.812, 260.127, 260.386, 263.419, 229.839); resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, TwoVerticesInters) @@ -715,9 +715,9 @@ TEST(BooleanOperations, TwoVerticesInters) resultSubtract.LineTo(-300, -300); resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, RectIntersEllipse) @@ -773,9 +773,9 @@ TEST(BooleanOperations, RectIntersEllipse) resultSubtract.CurveTo(257.623, 242.785, 258.883, 240.478, 260, 238.092); resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, RectIntersCross) @@ -869,9 +869,9 @@ TEST(BooleanOperations, RectIntersCross) resultSubtract.LineTo(-89.5, 24); resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, CrossIntersTriangle) @@ -977,9 +977,9 @@ TEST(BooleanOperations, CrossIntersTriangle) resultSubtract.LineTo(-6, 3.5); resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, CrossIntersCross) @@ -1077,9 +1077,9 @@ TEST(BooleanOperations, CrossIntersCross) resultSubtract.LineTo(-72, -191); resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, EllipseTouchEllipse) @@ -1119,9 +1119,9 @@ TEST(BooleanOperations, EllipseTouchEllipse) resultSubtract.CurveTo(138.137, 237, 165, 210.137, 165, 177); resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } TEST(BooleanOperations, TriangleOverlapTriangle) @@ -1170,7 +1170,7 @@ TEST(BooleanOperations, TriangleOverlapTriangle) resultSubtract.LineTo(-200, -300); resultSubtract.CloseFigure(); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection) == resultIntersect); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union) == resultUnite); - EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction) == resultSubtract); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Intersection).Equals(resultIntersect)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Union).Equals(resultUnite)); + EXPECT_TRUE(Aggplus::CalcBooleanOperation(path1, path2, Aggplus::Subtraction).Equals(resultSubtract)); } diff --git a/DesktopEditor/raster/PICT/PICFile.cpp b/DesktopEditor/raster/PICT/PICFile.cpp index 43c1257c57..beb3b6727f 100644 --- a/DesktopEditor/raster/PICT/PICFile.cpp +++ b/DesktopEditor/raster/PICT/PICFile.cpp @@ -60,6 +60,9 @@ bool CPictFile::Open(CBgraFrame* frame, const std::wstring& fileName, bool isRGB auto status = Decode(); file.CloseFile(); + if (!status) + return false; + BYTE* data = new BYTE[4 * m_oImgData.m_nWidth * m_oImgData.m_nHeight]; frame->put_Data(data); frame->put_Height(m_oImgData.m_nHeight); @@ -82,7 +85,7 @@ bool CPictFile::Open(CBgraFrame* frame, const std::wstring& fileName, bool isRGB } } - return status; + return true; } bool CPictFile::Open(CBgraFrame* frame, BYTE* buffer, const size_t& size, bool isRGB) @@ -191,6 +194,8 @@ bool CPictFile::DecodeData() int flag = 0; bool is_pix_data = false; + if (!m_oImgData.m_pPixelData) + m_oImgData.m_pPixelData = (BYTE*) malloc(m_oImgData.m_nWidth * m_oImgData.m_nHeight * 4); for (int code = 0; feof(m_pFile) == 0; ) { @@ -228,6 +233,7 @@ bool CPictFile::DecodeData() break; m_oImgData.m_nHeight = frame.Height; m_oImgData.m_nWidth = frame.Width; + m_oImgData.m_pPixelData = (BYTE*)realloc(m_oImgData.m_pPixelData, m_oImgData.m_nHeight * m_oImgData.m_nWidth * 4); break; } case 0x11: @@ -591,7 +597,7 @@ bool CPictFile::DecodeData() case 0x34: { if (!ReadRectangle(&m_oLastRect)) - return false; + break; DrawRect(code == 0x30); break; @@ -612,7 +618,7 @@ bool CPictFile::DecodeData() case 0x44: { if (!ReadRectangle(&m_oLastRoundRect)) - return false; + break; DrawRoundRect(code == 0x40); break; @@ -633,7 +639,7 @@ bool CPictFile::DecodeData() case 0x54: { if (!ReadRectangle(&m_oLastOval)) - return false; + break; DrawOval(code == 0x50); break; @@ -654,7 +660,7 @@ bool CPictFile::DecodeData() case 0x64: { if (!ReadRectangle(&m_oLastArc)) - return false; + break; DrawArc(); break; @@ -714,8 +720,7 @@ bool CPictFile::DecodeData() if (frame.Height != 0) tile_image.m_nHeight = frame.Height; - tile_image.m_pPixelData = new BYTE[4 * tile_image.m_nWidth * tile_image.m_nHeight]; - + tile_image.m_pPixelData = (BYTE*)malloc(4 * tile_image.m_nWidth * tile_image.m_nHeight); if ((code == 0x9a) || (code == 0x9b) || ((bytes_per_line & 0x8000) != 0)) { fseek(m_pFile, 18, SEEK_CUR); @@ -727,8 +732,8 @@ bool CPictFile::DecodeData() fseek(m_pFile, 12, SEEK_CUR); if (feof(m_pFile) != 0 || bits_per_pixel <= 0 || - bits_per_pixel > 32 || component_count <= 0 || - component_count > 4 || component_size <= 0) + bits_per_pixel > 32 || component_count < 0 || + component_count > 4 || component_size < 0) return false; tile_image.m_eAlphaTrait = component_count == 4 ? BlendPixelTrait : UndefinedPixelTrait; @@ -829,7 +834,7 @@ bool CPictFile::DecodeData() } BYTE* p = pixels; - for (size_t y = 0; y < tile_image.m_nHeight; y++) + for (size_t y = 0; y < tile_image.m_nHeight; y++) { if (p > (pixels + extent + m_oImgData.m_nWidth)) { @@ -917,9 +922,15 @@ bool CPictFile::DecodeData() if (feof(m_pFile) == 0) if ((code == 0x9a) || (code == 0x9b) || ((bytes_per_line & 0x8000) != 0)) { - m_oImgData = tile_image; - m_oImgData.m_pPixelData = new BYTE[4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth]; - memcpy(m_oImgData.m_pPixelData, tile_image.m_pPixelData, 4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth); + if (m_oImgData.m_nHeight <= tile_image.m_nHeight && m_oImgData.m_nWidth <= tile_image.m_nWidth) + { + m_oImgData.m_nHeight = tile_image.m_nHeight; + m_oImgData.m_nWidth = tile_image.m_nWidth; + m_oImgData.m_pPixelData = (BYTE*)realloc(m_oImgData.m_pPixelData, m_oImgData.m_nHeight * m_oImgData.m_nWidth * 4); + memcpy(m_oImgData.m_pPixelData, tile_image.m_pPixelData, m_oImgData.m_nHeight * m_oImgData.m_nWidth * 4); + } + else + CompositeImage(tile_image, destination.X, destination.Y); } break; } @@ -969,8 +980,10 @@ bool CPictFile::DecodeData() if (!is_pix_data) { - m_oImgData.m_pPixelData = new BYTE[4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth]; - memcpy(m_oImgData.m_pPixelData, m_oFrame.get_Data(), 4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth); + if (!m_oImgData.m_pPixelData) + m_oImgData.m_pPixelData = (BYTE*)malloc(4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth); + if (m_oFrame.get_Data()) + memcpy(m_oImgData.m_pPixelData, m_oFrame.get_Data(), 4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth); } return true; @@ -1057,10 +1070,12 @@ unsigned int CPictFile::ReadLongValue() bool CPictFile::ReadRectangle(Aggplus::Rect* rect) { - rect->Y = ReadShortValue(); - rect->X = ReadShortValue(); - rect->Height = ReadShortValue() - rect->Y; - rect->Width = ReadShortValue() - rect->X; + rect->Y = (short) ReadShortValue(); + rect->X = (short) ReadShortValue(); + short bottom = (short) ReadShortValue(); + short right = (short) ReadShortValue(); + rect->Height = bottom - rect->Y; + rect->Width = right - rect->X; if (feof(m_pFile) != 0) return false; @@ -1076,7 +1091,7 @@ void CPictFile::SetImageAlpha(Image* img, const BYTE alpha) bool status = true; if (!img->m_pPixelData) - img->m_pPixelData = new BYTE[4 * img->m_nHeight * img->m_nWidth]; + img->m_pPixelData = (BYTE*)malloc(4 * img->m_nHeight * img->m_nWidth); img->m_eAlphaTrait = BlendPixelTrait; img->m_pChannelMap[AlphaPixelChannel].traits = UpdatePixelTrait; @@ -1694,3 +1709,227 @@ void CPictFile::InitializeRenderer() m_pRenderer->SetSwapRGB(false); m_pRenderer->put_PenColor(0x000000); } + + +BYTE* CPictFile::GetPixels(const Image& image, const long long& x, const long long& y, const size_t& width, const size_t& height) const +{ + BYTE* pixels = image.m_pPixelData + 4 * (y * image.m_nWidth + x); + + if (!pixels) + return nullptr; + + if (image.m_nWidth == 0) + return nullptr; + + long long offset = y * image.m_nWidth; + + offset += x; + size_t length = 4 * width * sizeof(unsigned char); + + size_t rows = height; + size_t extent = length * rows; + + BYTE* q = pixels; + + if (image.m_nWidth == width) + { + length = extent; + rows = 1UL; + } + + BYTE* p = image.m_pPixelData + 4 * offset; + for (size_t i = 0; i < rows; i++) + { + memcpy(q, p, length); + p += 4 * image.m_nWidth; + q += 4 * width; + } + + return pixels; +} + +void CPictFile::CompositeImage(const Image& composite,const long long& xOffset, const long long& yOffset) +{ + m_oImgData.m_eStorageClass = DirectClass; + Image source_image(composite); + source_image.m_pPixelData = (BYTE*)malloc(source_image.m_nWidth * source_image.m_nHeight * 4); + memcpy(source_image.m_pPixelData, composite.m_pPixelData, source_image.m_nWidth * source_image.m_nHeight * 4); + + m_oImgData.m_pChannelMap[RedPixelChannel].traits = UpdatePixelTrait; + m_oImgData.m_pChannelMap[GreenPixelChannel].traits = UpdatePixelTrait; + m_oImgData.m_pChannelMap[BluePixelChannel].traits = UpdatePixelTrait; + m_oImgData.m_pChannelMap[AlphaPixelChannel].traits = UpdatePixelTrait; + + source_image.m_pChannelMap[RedPixelChannel].traits = CopyPixelTrait; + source_image.m_pChannelMap[GreenPixelChannel].traits = CopyPixelTrait; + source_image.m_pChannelMap[BluePixelChannel].traits = CopyPixelTrait; + source_image.m_pChannelMap[AlphaPixelChannel].traits = CopyPixelTrait; + + bool status = false; + if (!((xOffset < 0) || (yOffset < 0)) && !((xOffset + source_image.m_nWidth) > m_oImgData.m_nWidth) && !((yOffset + source_image.m_nHeight) > m_oImgData.m_nHeight)) + { + if ((source_image.m_eAlphaTrait == UndefinedPixelTrait) && + (m_oImgData.m_eAlphaTrait != UndefinedPixelTrait)) + SetImageAlpha(&source_image, 255); + + status = true; + for (size_t y = 0; y < source_image.m_nHeight; y++) + { + if (!status) + continue; + + const BYTE* p = GetPixels(source_image,0,y,source_image.m_nWidth, 1); + BYTE* q = GetPixels(m_oImgData, xOffset, y + yOffset, source_image.m_nWidth, 1); + + if (p == nullptr || q == nullptr) + { + status = false; + continue; + } + + for (size_t x = 0; x < source_image.m_nWidth; x++) + { + BYTE read_mask; + if (source_image.m_pChannelMap[ReadMaskPixelChannel].traits == UndefinedPixelTrait) + read_mask = 255; + else + read_mask = p[source_image.m_pChannelMap[ReadMaskPixelChannel].offset]; + + if (read_mask <= (255.0 / 2.0)) + { + p += 4; + q += 4; + continue; + } + + for (int i = 0; i < 4; i++) + { + PixelChannel channel = source_image.m_pChannelMap[i].channel; + PixelTrait source_traits = source_image.m_pChannelMap[channel].traits; + PixelTrait traits = m_oImgData.m_pChannelMap[channel].traits; + + if ((source_traits == UndefinedPixelTrait) || (traits == UndefinedPixelTrait)) + continue; + q[m_oImgData.m_pChannelMap[channel].offset] = p[i]; + } + p += 4; + q += 4; + } + } + + return; + } + + status = true; + for (size_t y = 0; y < m_oImgData.m_nHeight; y++) + { + if (!status) + continue; + + if (y < yOffset) + continue; + if (y - yOffset >= source_image.m_nHeight) + continue; + + const BYTE* pixels = nullptr; + const BYTE* p = nullptr; + if (y >= yOffset && y - yOffset < source_image.m_nHeight) + { + p = GetPixels(source_image, 0, y - yOffset, source_image.m_nWidth,1); + if (!p) + { + status = false; + continue; + } + pixels = p; + if (xOffset < 0) + p -= xOffset * 4; + } + + BYTE* q = GetPixels(m_oImgData, 0, y, m_oImgData.m_nWidth,1); + if (!q) + { + status = false; + continue; + } + + for (size_t x = 0; x < m_oImgData.m_nWidth; x++) + { + double + Dc = 0.0, + Sa = 0.0, + Sc = 0.0; + + if (x < xOffset) + { + q += 4; + continue; + } + if (x - xOffset >= source_image.m_nWidth) + break; + + if (!pixels || x < xOffset || x - xOffset >= source_image.m_nWidth) + { + for (int i = 0; i < 4; i++) + { + PixelChannel channel = m_oImgData.m_pChannelMap[i].channel; + PixelTrait traits = m_oImgData.m_pChannelMap[channel].traits; + PixelTrait source_traits = source_image.m_pChannelMap[channel].traits; + if (traits == UndefinedPixelTrait || source_traits == UndefinedPixelTrait) + continue; + + q[i] = 0; + } + q += 4; + continue; + } + + BYTE pixel_alpha = 0; + if (source_image.m_pChannelMap[AlphaPixelChannel].traits != UndefinedPixelTrait) + pixel_alpha = p[source_image.m_pChannelMap[AlphaPixelChannel].offset]; + Sa = (1.0 / 255.0) * pixel_alpha; + Sa = Sa == 0 ? 1 : Sa; + pixel_alpha = 0; + if (m_oImgData.m_pChannelMap[AlphaPixelChannel].traits != UndefinedPixelTrait) + pixel_alpha = q[m_oImgData.m_pChannelMap[AlphaPixelChannel].offset]; + + for (int i = 0; i < 4; i++) + { + double pixel = 0.0; + PixelChannel channel = m_oImgData.m_pChannelMap[i].channel; + PixelTrait traits = m_oImgData.m_pChannelMap[channel].traits; + PixelTrait source_traits = source_image.m_pChannelMap[channel].traits; + if (traits == UndefinedPixelTrait) + continue; + if ((channel == AlphaPixelChannel) && + ((traits & UpdatePixelTrait) != 0)) + { + pixel = 255.0 * Sa; + q[i] = pixel > 255 ? 255 : pixel < 0 ? 0 : pixel; + continue; + } + if (source_traits == UndefinedPixelTrait) + continue; + + Sc = p[source_image.m_pChannelMap[channel].offset]; + Dc=q[i]; + + if ((traits & CopyPixelTrait) != 0) + { + q[i] = Dc > 255 ? 255 : Dc < 0 ? 0 : Dc; + continue; + } + + pixel = 255.0 * (1.0 / 255.0) * Sa * Sc; + q[i] = pixel > 255 ? 255 : pixel < 0 ? 0 : pixel; + } + + p += 4; + if (p >= (pixels + 4 * source_image.m_nWidth)) + p = pixels; + q += 4; + } + } + + return; +} diff --git a/DesktopEditor/raster/PICT/PICFile.h b/DesktopEditor/raster/PICT/PICFile.h index d426868baf..41ca86d822 100644 --- a/DesktopEditor/raster/PICT/PICFile.h +++ b/DesktopEditor/raster/PICT/PICFile.h @@ -139,7 +139,7 @@ struct Image delete[] m_pColormap; if (m_pPixelData) - delete[] m_pPixelData; + free(m_pPixelData); } Image& operator=(const Image& other) @@ -190,6 +190,8 @@ private: void SetImageAlpha(Image* img, const BYTE alpha); BYTE* DecodeImage(const Image& img, size_t bytesPerLine, size_t bitsPerPixel, size_t* extent); const BYTE* UnpackScanline(const BYTE* pixels, const size_t& bitsPerPixel, BYTE* scanline, size_t* bytesPerLine); + BYTE* GetPixels(const Image& image, const long long& x, const long long& y, const size_t& width, const size_t& height) const; + void CompositeImage(const Image& composite,const long long& xOffset, const long long& yOffset); void ReadPolygon(); Aggplus::Rect ContractRect(const Aggplus::Rect& rect, bool isFrame); diff --git a/OOXML/DocxFormat/Document.cpp b/OOXML/DocxFormat/Document.cpp index d887148c67..7440d6b27d 100644 --- a/OOXML/DocxFormat/Document.cpp +++ b/OOXML/DocxFormat/Document.cpp @@ -384,23 +384,32 @@ namespace OOX pItem = new Logic::CSdt( document ); else if (L"sectPr" == sName ) { - m_oSectPr = new Logic::CSectionProperty( document ); - m_oSectPr->fromXML(oReader); -//------------------------------------------------------------------------- - OOX::CDocx* docx = dynamic_cast(document); - OOX::CDocument* document = docx ? (docx->m_bGlossaryRead ? docx->m_oGlossary.document : (docx->m_oMain.document ? docx->m_oMain.document : this)) : this; + Logic::CSectionProperty *pSectPr = new Logic::CSectionProperty( document ); + pSectPr->fromXML(oReader); - if (document) + if (pSectPr->m_bEmpty) { - if (document->m_arrSections.empty()) - { - OOX::CDocument::_section section; - document->m_arrSections.push_back(section); - } - document->m_arrSections.back().sect = m_oSectPr.GetPointer(); - document->m_arrSections.back().end_elm = document->m_arrItems.size(); //активный рутовый еще не добавлен + delete pSectPr; + pSectPr = NULL; + } + else + { + m_oSectPr = pSectPr; + + OOX::CDocx* docx = dynamic_cast(document); + OOX::CDocument* document = docx ? (docx->m_bGlossaryRead ? docx->m_oGlossary.document : (docx->m_oMain.document ? docx->m_oMain.document : this)) : this; + + if (document) + { + if (document->m_arrSections.empty()) + { + OOX::CDocument::_section section; + document->m_arrSections.push_back(section); + } + document->m_arrSections.back().sect = m_oSectPr.GetPointer(); + document->m_arrSections.back().end_elm = document->m_arrItems.size(); //активный рутовый еще не добавлен + } } -//------------------------------------------------------------------------- } else if (L"tbl" == sName ) pItem = new Logic::CTbl( document ); diff --git a/OOXML/DocxFormat/Logic/ParagraphProperty.cpp b/OOXML/DocxFormat/Logic/ParagraphProperty.cpp index ecfb005ba0..346700e229 100644 --- a/OOXML/DocxFormat/Logic/ParagraphProperty.cpp +++ b/OOXML/DocxFormat/Logic/ParagraphProperty.cpp @@ -640,27 +640,36 @@ namespace OOX m_oRPr = oReader; else if ( !m_bPPrChange && L"sectPr" == sName ) { - m_oSectPr = new CSectionProperty(document); - m_oSectPr->fromXML(oReader); -//------------------------------------------------------------------------------------ - OOX::CDocx *docx = dynamic_cast(document); - if (docx) - { - OOX::CDocument *doc = docx->m_bGlossaryRead ? docx->m_oGlossary.document : docx->m_oMain.document; + Logic::CSectionProperty* pSectPr = new Logic::CSectionProperty(document); + pSectPr->fromXML(oReader); - if (doc->m_arrSections.empty()) + if (pSectPr->m_bEmpty) + { + delete pSectPr; + pSectPr = NULL; + } + else + { + m_oSectPr = pSectPr; + + OOX::CDocx* docx = dynamic_cast(document); + if (docx) { + OOX::CDocument* doc = docx->m_bGlossaryRead ? docx->m_oGlossary.document : docx->m_oMain.document; + + if (doc->m_arrSections.empty()) + { + OOX::CDocument::_section section; + doc->m_arrSections.push_back(section); + } + doc->m_arrSections.back().sect = m_oSectPr.GetPointer(); + doc->m_arrSections.back().end_elm = doc->m_arrItems.size() + 1; // порядок выше - сначала читаем, потом добавляем + OOX::CDocument::_section section; + section.start_elm = doc->m_arrItems.size() + 1; doc->m_arrSections.push_back(section); } - doc->m_arrSections.back().sect = m_oSectPr.GetPointer(); - doc->m_arrSections.back().end_elm = doc->m_arrItems.size() + 1; // порядок выше - сначала читаем, потом добавляем - - OOX::CDocument::_section section; - section.start_elm = doc->m_arrItems.size() + 1; - doc->m_arrSections.push_back(section); } -//------------------------------------------------------------------------------------ } else if ( L"shd" == sName ) m_oShd = oReader; diff --git a/OOXML/DocxFormat/Logic/SectionProperty.cpp b/OOXML/DocxFormat/Logic/SectionProperty.cpp index 45f1c0a919..785c9ab18a 100644 --- a/OOXML/DocxFormat/Logic/SectionProperty.cpp +++ b/OOXML/DocxFormat/Logic/SectionProperty.cpp @@ -78,7 +78,6 @@ namespace ComplexTypes } void CColumn::ReadAttributes(XmlUtils::CXmlLiteReader& oReader) { - // Читаем атрибуты WritingElement_ReadAttributes_Start( oReader ) WritingElement_ReadAttributes_Read_if ( oReader, (L"w:space"), m_oSpace ) WritingElement_ReadAttributes_Read_else_if( oReader, (L"w:w"), m_oW ) @@ -245,7 +244,6 @@ namespace ComplexTypes } void CLineNumber::ReadAttributes(XmlUtils::CXmlLiteReader& oReader) { - // Читаем атрибуты WritingElement_ReadAttributes_Start( oReader ) WritingElement_ReadAttributes_Read_if ( oReader, (L"w:countBy"), m_oCountBy ) WritingElement_ReadAttributes_Read_else_if( oReader, (L"w:distance"), m_oDistance ) @@ -298,7 +296,6 @@ namespace ComplexTypes } void CPaperSource::ReadAttributes(XmlUtils::CXmlLiteReader& oReader) { - // Читаем атрибуты WritingElement_ReadAttributes_Start( oReader ) WritingElement_ReadAttributes_Read_if ( oReader, (L"w:first"), m_oFirst ) WritingElement_ReadAttributes_Read_else_if( oReader, (L"w:other"), m_oOther ) @@ -851,7 +848,6 @@ namespace ComplexTypes } void CPageNumber::ReadAttributes(XmlUtils::CXmlLiteReader& oReader) { - // Читаем атрибуты WritingElement_ReadAttributes_Start( oReader ) WritingElement_ReadAttributes_Read_if ( oReader, (L"w:chapSep"), m_oChapSep ) WritingElement_ReadAttributes_Read_else_if( oReader, (L"w:chapStyle"), m_oChapStyle ) @@ -918,7 +914,6 @@ namespace ComplexTypes } void CPageSz::ReadAttributes(XmlUtils::CXmlLiteReader& oReader) { - // Читаем атрибуты WritingElement_ReadAttributes_Start( oReader ) WritingElement_ReadAttributes_Read_if ( oReader, (L"w:code"), m_oCode ) WritingElement_ReadAttributes_Read_else_if( oReader, (L"w:h"), m_oH ) @@ -963,7 +958,6 @@ namespace ComplexTypes } void CSectType::ReadAttributes(XmlUtils::CXmlLiteReader& oReader) { - // Читаем атрибуты WritingElement_ReadAttributes_Start( oReader ) WritingElement_ReadAttributes_ReadSingle( oReader, (L"w:val"), m_oVal ) WritingElement_ReadAttributes_End( oReader ) @@ -1081,7 +1075,6 @@ namespace OOX } void CColumns::ReadAttributes(XmlUtils::CXmlLiteReader& oReader) { - // Читаем атрибуты WritingElement_ReadAttributes_Start( oReader ) WritingElement_ReadAttributes_Read_if ( oReader, (L"w:equalWidth"), m_oEqualWidth ) WritingElement_ReadAttributes_Read_else_if( oReader, (L"w:num"), m_oNum ) @@ -1378,11 +1371,10 @@ namespace OOX } void CPageBorders::ReadAttributes(XmlUtils::CXmlLiteReader& oReader) { - // Читаем атрибуты WritingElement_ReadAttributes_Start( oReader ) - WritingElement_ReadAttributes_Read_if ( oReader, (L"w:display"), m_oDisplay ) - WritingElement_ReadAttributes_Read_else_if( oReader, (L"w:offsetFrom"), m_oOffsetFrom ) - WritingElement_ReadAttributes_Read_else_if( oReader, (L"w:zOrder"), m_oZOrder ) + WritingElement_ReadAttributes_Read_if ( oReader, L"w:display", m_oDisplay ) + WritingElement_ReadAttributes_Read_else_if( oReader, L"w:offsetFrom", m_oOffsetFrom ) + WritingElement_ReadAttributes_Read_else_if( oReader, L"w:zOrder", m_oZOrder ) WritingElement_ReadAttributes_End( oReader ) } @@ -1400,14 +1392,14 @@ namespace OOX } void CSectPrChange::fromXML(XmlUtils::CXmlNode& oNode) { - XmlMacroReadAttributeBase( oNode, _T("w:author"), m_sAuthor ); - XmlMacroReadAttributeBase( oNode, _T("w:date"), m_oDate ); - XmlMacroReadAttributeBase( oNode, _T("w:id"), m_oId ); - XmlMacroReadAttributeBase( oNode, _T("oouserid"), m_sUserId ); + XmlMacroReadAttributeBase( oNode, L"w:author", m_sAuthor ); + XmlMacroReadAttributeBase( oNode, L"w:date", m_oDate ); + XmlMacroReadAttributeBase( oNode, L"w:id", m_oId ); + XmlMacroReadAttributeBase( oNode, L"oouserid", m_sUserId ); XmlUtils::CXmlNode oNode_sectPr; - if ( m_pSecPr.IsInit() && oNode.GetNode( _T("w:sectPr"), oNode_sectPr ) ) + if ( m_pSecPr.IsInit() && oNode.GetNode( L"w:sectPr", oNode_sectPr ) ) m_pSecPr->fromXML( oNode_sectPr ); } @@ -1422,13 +1414,13 @@ namespace OOX while( oReader.ReadNextSiblingNode( nParentDepth ) ) { std::wstring sName = oReader.GetName(); - if ( _T("w:sectPr") == sName ) + if ( L"w:sectPr" == sName ) m_pSecPr->fromXML( oReader ); } } std::wstring CSectPrChange::toXML() const { - std::wstring sResult = _T("ToString(); - sResult += _T("\" "); + sResult += L"\" "; } if ( m_oId.IsInit() ) { - sResult += _T("w:id=\""); + sResult += L"w:id=\""; sResult += m_oId->ToString(); - sResult += _T("\" "); + sResult += L"\" "; } if ( m_sUserId.IsInit() ) { - sResult += _T("oouserid=\""); + sResult += L"oouserid=\""; sResult += m_sUserId.get2(); - sResult += _T("\" "); + sResult += L"\" "; } - sResult += _T(">"); + sResult += L">"; if ( m_pSecPr.IsInit() ) sResult += m_pSecPr->toXML(); - sResult += _T(""); + sResult += L""; return sResult; } @@ -1473,12 +1465,11 @@ namespace OOX } void CSectPrChange::ReadAttributes(XmlUtils::CXmlLiteReader& oReader) { - // Читаем атрибуты WritingElement_ReadAttributes_Start( oReader ) - WritingElement_ReadAttributes_Read_if ( oReader, _T("w:author"), m_sAuthor ) - WritingElement_ReadAttributes_Read_else_if( oReader, _T("w:date"), m_oDate ) - WritingElement_ReadAttributes_Read_else_if( oReader, _T("w:id"), m_oId ) - WritingElement_ReadAttributes_Read_else_if( oReader, _T("oouserid"), m_sUserId ) + WritingElement_ReadAttributes_Read_if ( oReader, L"w:author", m_sAuthor ) + WritingElement_ReadAttributes_Read_else_if( oReader, L"w:date", m_oDate ) + WritingElement_ReadAttributes_Read_else_if( oReader, L"w:id", m_oId ) + WritingElement_ReadAttributes_Read_else_if( oReader, L"oouserid", m_sUserId ) WritingElement_ReadAttributes_End( oReader ) } @@ -1511,116 +1502,70 @@ namespace OOX } void CSectionProperty::fromXML(XmlUtils::CXmlNode &oNode) { - if ( (L"w:sectPr") != oNode.GetName() ) - return; + std::vector oChilds; + oNode.GetNodes(L"*", oChilds); + if (oChilds.empty() && oNode.GetAttributesCount() < 1) + { + m_bEmpty = true; + return; + } XmlMacroReadAttributeBase( oNode, (L"w:rsidDel"), m_oRsidDel ); XmlMacroReadAttributeBase( oNode, (L"w:rsidR"), m_oRsidR ); XmlMacroReadAttributeBase( oNode, (L"w:rsidRPr"), m_oRsidRPr ); XmlMacroReadAttributeBase( oNode, (L"w:rsidSect"), m_oRsidSect ); - XmlUtils::CXmlNode oChild; - - if ( oNode.GetNode( (L"w:bidi"), oChild ) ) - m_oBidi = oChild; - - if ( oNode.GetNode( (L"w:cols"), oChild ) ) - m_oCols = oChild; - - if ( oNode.GetNode( (L"w:docGrid"), oChild ) ) - m_oDocGrid = oChild; - - if ( oNode.GetNode( (L"w:endnotePr"), oChild ) ) - m_oEndnotePr = oChild; - - if ( !m_bSectPrChange ) + for (size_t nIndex = 0; nIndex < oChilds.size(); nIndex++) { - std::vector oNodes; - if ( oNode.GetNodes( (L"w:footerReference"), oNodes ) ) + XmlUtils::CXmlNode& oChild = oChilds[nIndex]; + if (oChild.IsValid()) { - for ( int nIndex = 0; nIndex < oNodes.size(); nIndex++ ) - { - XmlUtils::CXmlNode& oNode = oNodes[nIndex]; - if ( oNode.IsValid() ) - { - nullable oFooter; oFooter.Init(); - oFooter->FromXML(oNode); + std::wstring sName = oChild.GetName(); - m_arrFooterReference.push_back( oFooter ); - } + if (L"w:bidi" == sName) m_oBidi = oChild; + else if (L"w:cols" == sName) m_oCols = oChild; + else if (L"w:docGrid" == sName) m_oDocGrid = oChild; + else if (L"w:endnotePr" == sName) m_oEndnotePr = oChild; + else if (L"w:footnotePr" == sName) m_oFootnotePr = oChild; + else if (L"w:formProt" == sName) m_oFormProt = oChild; + else if (!m_bSectPrChange && L"w:footerReference" == sName) + { + nullable oFooter; oFooter.Init(); + oFooter->FromXML(oChild); + + m_arrFooterReference.push_back(oFooter); } + else if (!m_bSectPrChange && L"w:headerReference" == sName) + { + nullable < ComplexTypes::Word::CHdrFtrRef> oHeader; oHeader.Init(); + oHeader->FromXML(oChild); + + m_arrHeaderReference.push_back(oHeader); + } + else if (L"w:lnNumType" == sName) m_oLnNumType = oChild; + else if (L"w:noEndnote" == sName) m_oNoEndnote = oChild; + else if (L"w:paperSrc" == sName) m_oPaperSrc = oChild; + else if (L"w:pgBorders" == sName) m_oPgBorders = oChild; + else if (L"w:pgMar" == sName) m_oPgMar = oChild; + else if (L"w:pgNumType" == sName) m_oPgNumType = oChild; + else if (L"w:pgSz" == sName) m_oPgSz = oChild; + else if (L"w:printerSettings" == sName) m_oPrinterSettings = oChild; + else if (L"w:rtlGutter" == sName) m_oRtlGutter = oChild; + else if (!m_bSectPrChange && L"w:sectPrChange" == sName) m_oSectPrChange = oChild; + else if (L"w:textDirection" == sName) m_oTextDirection = oChild; + else if (L"w:titlePg" == sName) m_oTitlePg = oChild; + else if (L"w:type" == sName) m_oType = oChild; + else if (L"w:vAlign" == sName) m_oVAlign = oChild; } } - - if ( oNode.GetNode( (L"w:footnotePr"), oChild ) ) - m_oFootnotePr = oChild; - - if ( oNode.GetNode( (L"w:formProt"), oChild ) ) - m_oFormProt = oChild; - - if ( !m_bSectPrChange ) - { - std::vector oNodes; - if ( oNode.GetNodes( L"w:headerReference", oNodes ) ) - { - for ( size_t nIndex = 0; nIndex < oNodes.size(); nIndex++ ) - { - XmlUtils::CXmlNode& oNode = oNodes[nIndex]; - if ( oNode.IsValid()) - { - nullable < ComplexTypes::Word::CHdrFtrRef> oHeader; oHeader.Init(); - oHeader->FromXML(oNode); - - m_arrHeaderReference.push_back( oHeader ); - } - } - } - } - - if ( oNode.GetNode( (L"w:lnNumType"), oChild ) ) - m_oLnNumType = oChild; - - if ( oNode.GetNode( (L"w:noEndnote"), oChild ) ) - m_oNoEndnote = oChild; - - if ( oNode.GetNode( (L"w:paperSrc"), oChild ) ) - m_oPaperSrc = oChild; - - if ( oNode.GetNode( (L"w:pgBorders"), oChild ) ) - m_oPgBorders = oChild; - - if ( oNode.GetNode( (L"w:pgMar"), oChild ) ) - m_oPgMar = oChild; - - if ( oNode.GetNode( (L"w:pgNumType"), oChild ) ) - m_oPgNumType = oChild; - - if ( oNode.GetNode( (L"w:pgSz"), oChild ) ) - m_oPgSz = oChild; - - if ( oNode.GetNode( (L"w:printerSettings"), oChild ) ) - m_oPrinterSettings = oChild; - - if ( oNode.GetNode( (L"w:rtlGutter"), oChild ) ) - m_oRtlGutter = oChild; - - if ( !m_bSectPrChange && oNode.GetNode( (L"w:sectPrChange"), oChild ) ) - m_oSectPrChange = oChild; - - if ( oNode.GetNode( (L"w:textDirection"), oChild ) ) - m_oTextDirection = oChild; - - if ( oNode.GetNode( (L"w:titlePg"), oChild ) ) - m_oTitlePg = oChild; - - if ( oNode.GetNode( (L"w:type"), oChild ) ) - m_oType = oChild; - - if ( oNode.GetNode( (L"w:vAlign"), oChild ) ) - m_oVAlign = oChild; } void CSectionProperty::fromXML(XmlUtils::CXmlLiteReader& oReader) { + if (oReader.IsEmptyNode() && oReader.GetAttributesCount() < 1) + { + m_bEmpty = true; + return; + } ReadAttributes( oReader ); if ( oReader.IsEmptyNode() ) diff --git a/OOXML/DocxFormat/Logic/SectionProperty.h b/OOXML/DocxFormat/Logic/SectionProperty.h index 27c7aa490f..8ff29a160b 100644 --- a/OOXML/DocxFormat/Logic/SectionProperty.h +++ b/OOXML/DocxFormat/Logic/SectionProperty.h @@ -503,7 +503,8 @@ namespace OOX void ReadAttributes(XmlUtils::CXmlLiteReader& oReader); public: - bool m_bSectPrChange; + bool m_bSectPrChange = false; + bool m_bEmpty = false; nullable m_oRsidDel; nullable m_oRsidR; diff --git a/OdfFile/Reader/Converter/pptx_output_xml.cpp b/OdfFile/Reader/Converter/pptx_output_xml.cpp index caceabeea8..6daf5f038c 100644 --- a/OdfFile/Reader/Converter/pptx_output_xml.cpp +++ b/OdfFile/Reader/Converter/pptx_output_xml.cpp @@ -280,7 +280,9 @@ void pptx_xml_slideMaster::write_to(std::wostream & strm) CP_XML_ATTR(L"xmlns:p14", L"http://schemas.microsoft.com/office/powerpoint/2010/main"); CP_XML_ATTR(L"xmlns:p15", L"http://schemas.microsoft.com/office/powerpoint/2012/main"); CP_XML_ATTR(L"xmlns:mc", L"http://schemas.openxmlformats.org/markup-compatibility/2006"); - + + CP_XML_ATTR(L"preserve", 1); + CP_XML_NODE(L"p:cSld") { CP_XML_STREAM() << strmBackground_.str(); diff --git a/OdfFile/Writer/Format/odp_conversion_context.cpp b/OdfFile/Writer/Format/odp_conversion_context.cpp index 868268e8cd..de3d616ab6 100644 --- a/OdfFile/Writer/Format/odp_conversion_context.cpp +++ b/OdfFile/Writer/Format/odp_conversion_context.cpp @@ -141,9 +141,19 @@ void odp_conversion_context::end_slide() { slide_context_.end_page(); } -void odp_conversion_context::start_master_slide(std::wstring name) +void odp_conversion_context::start_master_slide(std::wstring & name) { slide_context_.set_styles_context(page_layout_context()->get_local_styles_context()); + + std::map::iterator pFind = map_masterNames_.find(name); + if (map_masterNames_.end() == pFind) + { + map_masterNames_.insert(std::make_pair(name, 1)); + } + else + { + name += std::to_wstring(++pFind->second); + } page_layout_context()->add_master_page(name); slide_context_.start_page(page_layout_context()->last_master()->get_root()); diff --git a/OdfFile/Writer/Format/odp_conversion_context.h b/OdfFile/Writer/Format/odp_conversion_context.h index 210ee24627..30f65dbee0 100644 --- a/OdfFile/Writer/Format/odp_conversion_context.h +++ b/OdfFile/Writer/Format/odp_conversion_context.h @@ -64,7 +64,7 @@ public: size_t get_pages_count(); - void start_master_slide(std::wstring name); + void start_master_slide(std::wstring & name); void end_master_slide(); void start_layout_slide(); @@ -99,13 +99,15 @@ public: std::map map_table_styles_; - // NOTE(Kamil Kerimov): Key - PPTX identifier, value - ODP identifier + // Key - PPTX identifier, value - ODP identifier using IdentifierMap = std::unordered_map; std::vector map_identifiers_; - // NOTE(Kamil Kerimov): Key - slide name in pptx (e.g. slide1.xml), Value - slide name in odp (e.g. "This is a title") + // Key - slide name in pptx (e.g. slide1.xml), Value - slide name in odp (e.g. "This is a title") using SlidenameMap = std::map; SlidenameMap map_slidenames_; + + std::map map_masterNames_; private: odp_slide_context slide_context_; office_presentation* root_presentation_; diff --git a/PdfFile/PdfEditor.cpp b/PdfFile/PdfEditor.cpp index 7f2bfdbfe5..c229e350f2 100644 --- a/PdfFile/PdfEditor.cpp +++ b/PdfFile/PdfEditor.cpp @@ -377,7 +377,7 @@ PdfWriter::CObjectBase* DictToCDictObject2(Object* obj, PdfWriter::CDocument* pD Object oType, oSubtype; PdfWriter::CDictObject* pDict = NULL; - if (obj->dictLookup("Type", &oType)->isName("Annot") && obj->dictLookup("Subtype", &oSubtype)->isName()) + if (obj->dictLookup("Subtype", &oSubtype)->isName()) { PdfWriter::CAnnotation* pAnnot = CreateAnnot(obj, &oSubtype, NULL); if (pAnnot) @@ -386,7 +386,7 @@ PdfWriter::CObjectBase* DictToCDictObject2(Object* obj, PdfWriter::CDocument* pD pDict = pAnnot; } } - oType.free(); oSubtype.free(); + oSubtype.free(); if (obj->dictLookup("Type", &oType)->isName("ExtGState")) { @@ -1105,6 +1105,11 @@ bool CPdfEditor::IncrementalUpdates() } else if (strcmp("Fields", chKey) == 0) oAcroForm.dictGetVal(nIndex, &oTemp2); + else if (strcmp("NeedAppearances", chKey) == 0) + { + oTemp2.free(); + continue; + } else oAcroForm.dictGetValNF(nIndex, &oTemp2); DictToCDictObject(&oTemp2, pAcroForm, chKey); @@ -1649,6 +1654,10 @@ bool CPdfEditor::EditPage(int _nPageIndex, bool bSet, bool bActualPos) if (m_nMode == Mode::Unknown && !IncrementalUpdates()) return false; + m_pWriter->AddRedact({}); + WriteRedact({}); + m_arrRedact.clear(); + PDFDoc* pPDFDocument = NULL; PdfReader::CPdfFontList* pFontList = NULL; int nStartRefID = 0; @@ -2692,6 +2701,10 @@ bool CPdfEditor::DeletePage(int nPageIndex) if (m_nMode == Mode::Unknown && !IncrementalUpdates()) return false; + m_pWriter->AddRedact({}); + WriteRedact({}); + m_arrRedact.clear(); + PdfWriter::CDocument* pDoc = m_pWriter->GetDocument(); PdfWriter::CPage* pPage = pDoc->GetPage(nPageIndex); int nObjID = m_mObjManager.FindObj(pPage); @@ -2716,6 +2729,11 @@ bool CPdfEditor::AddPage(int nPageIndex) { if (m_nMode == Mode::Unknown && !IncrementalUpdates()) return false; + + m_pWriter->AddRedact({}); + WriteRedact({}); + m_arrRedact.clear(); + if (m_nMode == Mode::Split) { std::vector::iterator it = std::find(m_mObjManager.m_arrSplitAddPages.begin(), m_mObjManager.m_arrSplitAddPages.end(), m_nOriginIndex++); @@ -2747,6 +2765,10 @@ bool CPdfEditor::AddPage(int nPageIndex) } bool CPdfEditor::MovePage(int nPageIndex, int nPos) { + m_pWriter->AddRedact({}); + WriteRedact({}); + m_arrRedact.clear(); + if (m_nMode == Mode::Split || m_nMode == Mode::WriteNew || EditPage(nPageIndex, true, true)) return m_pWriter->GetDocument()->MovePage(nPageIndex, nPos); return false; @@ -3296,8 +3318,8 @@ bool CPdfEditor::EditWidgets(IAdvancedCommand* pCommand) if (m_nMode == Mode::Unknown && !IncrementalUpdates()) return false; - WriteRedact({}); m_pWriter->AddRedact({}); + WriteRedact({}); m_arrRedact.clear(); CWidgetsInfo* pFieldInfo = (CWidgetsInfo*)pCommand; @@ -3542,21 +3564,13 @@ void CPdfEditor::Redact(IAdvancedCommand* _pCommand) std::vector arrRedacts = pCommand->GetRedact(); for (CRedact::SRedact* pRedact : arrRedacts) { - int nRect = pRedact->arrQuadPoints.size() / 4; m_arrRedact.push_back(CRedactData()); m_arrRedact.back().sID = pRedact->sID; - m_arrRedact.back().arrQuads.reserve(nRect); - for (int i = 0; i < nRect; ++i) + m_arrRedact.back().arrQuads = pRedact->arrQuadPoints; + for (int i = 0; i < pRedact->arrQuadPoints.size(); i += 2) { - std::vector arrQuads = { pRedact->arrQuadPoints[i * 4 + 0], pRedact->arrQuadPoints[i * 4 + 1], pRedact->arrQuadPoints[i * 4 + 2], pRedact->arrQuadPoints[i * 4 + 3] }; - m_arrRedact.back().arrQuads.insert(m_arrRedact.back().arrQuads.end(), arrQuads.begin(), arrQuads.end()); - - arrQuads[0] += cropBox->x1; - double dQ = arrQuads[1]; - arrQuads[1] = cropBox->y2 - arrQuads[3]; - arrQuads[2] += cropBox->x1; - arrQuads[3] = cropBox->y2 - dQ; - arrAllQuads.insert(arrAllQuads.end(), arrQuads.begin(), arrQuads.end()); + arrAllQuads.push_back(pRedact->arrQuadPoints[i + 0] + cropBox->x1); + arrAllQuads.push_back(cropBox->y2 - pRedact->arrQuadPoints[i + 1]); } int nFlags = pRedact->nFlag; if (nFlags & (1 << 0)) @@ -3575,7 +3589,7 @@ void CPdfEditor::Redact(IAdvancedCommand* _pCommand) Object oContents; pPage->getContents(&oContents); PDFRectangle* box = pPage->getMediaBox(); - Gfx* gfx = new Gfx(pPDFDocument, &oRedactOut, nPageIndex, pPage->getResourceDict(), 72.0, 72.0, box, NULL, 0); + Gfx* gfx = new Gfx(pPDFDocument, &oRedactOut, m_nEditPage, pPage->getResourceDict(), 72.0, 72.0, box, NULL, 0); gfx->saveState(); gfx->display(&oContents); gfx->endOfPage(); @@ -3605,7 +3619,6 @@ std::vector CPdfEditor::WriteRedact(const std::vector& arr if (oRedact.bDraw || !oRedact.pRender) continue; - m_pWriter->SetTransform(1, 0, 0, 1, 0, 0); LONG nLenRender = oRedact.nLenRender; BYTE* pRender = oRedact.pRender; @@ -3620,19 +3633,23 @@ std::vector CPdfEditor::WriteRedact(const std::vector& arr double B = ret / 100000.0; LONG lColor = (LONG)(((LONG)(R * 255)) | ((LONG)(G * 255) << 8) | ((LONG)(B * 255) << 16) | ((LONG)255 << 24)); - for (int i = 0; i < oRedact.arrQuads.size(); i += 4) + m_pWriter->SetTransform(1, 0, 0, 1, 0, 0); + m_pWriter->PathCommandEnd(); + m_pWriter->put_BrushType(c_BrushTypeSolid); + m_pWriter->put_BrushColor1(lColor); + + for (int i = 0; i < oRedact.arrQuads.size(); i += 8) { - m_pWriter->PathCommandEnd(); - m_pWriter->put_BrushColor1(lColor); m_pWriter->PathCommandMoveTo(PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 0]), PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 1])); - m_pWriter->PathCommandLineTo(PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 0]), PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 3])); m_pWriter->PathCommandLineTo(PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 2]), PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 3])); - m_pWriter->PathCommandLineTo(PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 2]), PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 1])); + m_pWriter->PathCommandLineTo(PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 4]), PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 5])); + m_pWriter->PathCommandLineTo(PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 6]), PdfReader::PDFCoordsToMM(oRedact.arrQuads[i + 7])); m_pWriter->PathCommandClose(); - m_pWriter->DrawPath(NULL, L"", c_nWindingFillMode); - m_pWriter->PathCommandEnd(); } + m_pWriter->DrawPath(NULL, L"", c_nWindingFillMode); + m_pWriter->PathCommandEnd(); + // TODO рендер редакта должен быть пересечён со всеми последующими редактами // TODO на самом деле должен быть рендер команд редакта /* diff --git a/PdfFile/PdfFile.cpp b/PdfFile/PdfFile.cpp index b21368a3c5..6c057ee7a1 100644 --- a/PdfFile/PdfFile.cpp +++ b/PdfFile/PdfFile.cpp @@ -361,14 +361,14 @@ bool CPdfFile::UnmergePages() return false; return m_pInternal->pReader->UnmergePages(); } -bool CPdfFile::RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX4, BYTE* pChanges, int nLength) +bool CPdfFile::RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX8, BYTE* pChanges, int nLength) { if (!m_pInternal->pReader) { free(pChanges); return false; } - return m_pInternal->pReader->RedactPage(nPageIndex, arrRedactBox, nLengthX4, pChanges, nLength); + return m_pInternal->pReader->RedactPage(nPageIndex, arrRedactBox, nLengthX8, pChanges, nLength); } bool CPdfFile::UndoRedact() { diff --git a/PdfFile/PdfFile.h b/PdfFile/PdfFile.h index 6aea19c287..711e5b1426 100644 --- a/PdfFile/PdfFile.h +++ b/PdfFile/PdfFile.h @@ -131,7 +131,7 @@ public: // Захватывает полученную память malloc data bool MergePages(BYTE* data, DWORD length, int nMaxID = 0, const std::string& sPrefixForm = ""); bool UnmergePages(); - bool RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX4, BYTE* pChanges = NULL, int nLength = 0); + bool RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX8, BYTE* pChanges = NULL, int nLength = 0); bool UndoRedact(); int GetRotate(int nPageIndex); int GetMaxRefID(); diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index 6f0c5ac0f1..e697c1de4e 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -756,7 +756,7 @@ bool CPdfReader::UnmergePages() m_vPDFContext.pop_back(); return true; } -bool CPdfReader::RedactPage(int _nPageIndex, double* arrRedactBox, int nLengthX4, BYTE* pChanges, int nLength) +bool CPdfReader::RedactPage(int _nPageIndex, double* arrRedactBox, int nLengthX8, BYTE* pChanges, int nLength) { if (m_eError) { @@ -774,12 +774,10 @@ bool CPdfReader::RedactPage(int _nPageIndex, double* arrRedactBox, int nLengthX4 CPdfRedact* pRedact = new CPdfRedact(); pRedact->m_nPageIndex = _nPageIndex; - for (int i = 0; i < nLengthX4; ++i) + for (int i = 0; i < nLengthX8 * 8; i += 2) { - pRedact->m_arrRedactBox.push_back(arrRedactBox[i * 4 + 0] + cropBox->x1); - pRedact->m_arrRedactBox.push_back(cropBox->y2 - arrRedactBox[i * 4 + 3]); - pRedact->m_arrRedactBox.push_back(arrRedactBox[i * 4 + 2] + cropBox->x1); - pRedact->m_arrRedactBox.push_back(cropBox->y2 - arrRedactBox[i * 4 + 1]); + pRedact->m_arrRedactBox.push_back(arrRedactBox[i + 0] + cropBox->x1); + pRedact->m_arrRedactBox.push_back(cropBox->y2 - arrRedactBox[i + 1]); } pRedact->m_pChanges = pChanges; pRedact->m_nChangeLength = nLength; @@ -839,14 +837,14 @@ void CPdfReader::DrawPageOnRenderer(IRenderer* pRenderer, int _nPageIndex, bool* double B = ret / 100000.0; LONG lColor = (LONG)(((LONG)(R * 255)) | ((LONG)(G * 255) << 8) | ((LONG)(B * 255) << 16) | ((LONG)255 << 24)); - for (int j = 0; j < m_vRedact[i]->m_arrRedactBox.size(); j += 4) + for (int j = 0; j < m_vRedact[i]->m_arrRedactBox.size(); j += 8) { pRenderer->PathCommandEnd(); pRenderer->put_BrushColor1(lColor); pRenderer->PathCommandMoveTo(PdfReader::PDFCoordsToMM(m_vRedact[i]->m_arrRedactBox[j + 0] - cropBox->x1), PdfReader::PDFCoordsToMM(cropBox->y2 - m_vRedact[i]->m_arrRedactBox[j + 1])); - pRenderer->PathCommandLineTo(PdfReader::PDFCoordsToMM(m_vRedact[i]->m_arrRedactBox[j + 0] - cropBox->x1), PdfReader::PDFCoordsToMM(cropBox->y2 - m_vRedact[i]->m_arrRedactBox[j + 3])); pRenderer->PathCommandLineTo(PdfReader::PDFCoordsToMM(m_vRedact[i]->m_arrRedactBox[j + 2] - cropBox->x1), PdfReader::PDFCoordsToMM(cropBox->y2 - m_vRedact[i]->m_arrRedactBox[j + 3])); - pRenderer->PathCommandLineTo(PdfReader::PDFCoordsToMM(m_vRedact[i]->m_arrRedactBox[j + 2] - cropBox->x1), PdfReader::PDFCoordsToMM(cropBox->y2 - m_vRedact[i]->m_arrRedactBox[j + 1])); + pRenderer->PathCommandLineTo(PdfReader::PDFCoordsToMM(m_vRedact[i]->m_arrRedactBox[j + 6] - cropBox->x1), PdfReader::PDFCoordsToMM(cropBox->y2 - m_vRedact[i]->m_arrRedactBox[j + 7])); + pRenderer->PathCommandLineTo(PdfReader::PDFCoordsToMM(m_vRedact[i]->m_arrRedactBox[j + 4] - cropBox->x1), PdfReader::PDFCoordsToMM(cropBox->y2 - m_vRedact[i]->m_arrRedactBox[j + 5])); pRenderer->PathCommandClose(); pRenderer->DrawPath(c_nWindingFillMode); pRenderer->PathCommandEnd(); diff --git a/PdfFile/PdfReader.h b/PdfFile/PdfReader.h index e2ecefccb8..03e8e74359 100644 --- a/PdfFile/PdfReader.h +++ b/PdfFile/PdfReader.h @@ -93,7 +93,7 @@ public: bool MergePages(BYTE* pData, DWORD nLength, const std::wstring& wsPassword = L"", int nMaxID = 0, const std::string& sPrefixForm = ""); bool MergePages(const std::wstring& wsFile, const std::wstring& wsPassword = L"", int nMaxID = 0, const std::string& sPrefixForm = ""); bool UnmergePages(); - bool RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX4, BYTE* pChanges, int nLength); + bool RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX8, BYTE* pChanges, int nLength); bool UndoRedact(); void GetPageInfo(int nPageIndex, double* pdWidth, double* pdHeight, double* pdDpiX, double* pdDpiY); void DrawPageOnRenderer(IRenderer* pRenderer, int nPageIndex, bool* pBreak); diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index 7e43582889..efdd13ba21 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -2052,8 +2052,11 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF if (nFlags & (1 << 18)) pTextAnnot->SetState(pPr->GetState()); - pMarkupAnnot->RemoveAP(); - pTextAnnot->SetAP(); + if (!m_bSplit) + { + pMarkupAnnot->RemoveAP(); + pTextAnnot->SetAP(); + } } else if (oInfo.IsInk()) { @@ -2111,8 +2114,6 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF BYTE* pRender = oInfo.GetRender(nLen); DrawAP(pAnnot, pRender, nLen); } - else - pLineAnnot->SetAP(); } else if (oInfo.IsTextMarkup()) { @@ -2122,8 +2123,11 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF pTextMarkupAnnot->SetSubtype(pTMPr->GetSubtype()); pTextMarkupAnnot->SetQuadPoints(pTMPr->GetQuadPoints()); - pMarkupAnnot->RemoveAP(); - pTextMarkupAnnot->SetAP(pTMPr->GetQuadPoints(), pPr->GetCA()); + if (!m_bSplit) + { + pMarkupAnnot->RemoveAP(); + pTextMarkupAnnot->SetAP(pTMPr->GetQuadPoints(), pPr->GetCA()); + } } else if (oInfo.IsSquareCircle()) { @@ -2268,6 +2272,7 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF pRedactAnnot->SetRepeat(true); if (nFlags & (1 << 19)) pRedactAnnot->SetQ(pPr->GetQ()); + pRedactAnnot->SetOC(oInfo.GetC()); if (nFlags & (1 << 20)) { std::wstring wsFontName = pPr->GetFontName(); @@ -2646,13 +2651,10 @@ HRESULT CPdfWriter::AddRedact(const std::vector& arrRedact) pD = pPageBox->Get(0); double dPageX = pD->GetType() == PdfWriter::object_type_NUMBER ? ((PdfWriter::CNumberObject*)pD)->Get() : ((PdfWriter::CRealObject*)pD)->Get(); - for (int i = 0; i < m_arrRedact.size(); i += 4) + for (int i = 0; i < m_arrRedact.size(); i += 2) { - m_arrRedact[i * 4 + 0] += dPageX; - double dQ = m_arrRedact[i * 4 + 1]; - m_arrRedact[i * 4 + 1] = dPageH - m_arrRedact[i * 4 + 3]; - m_arrRedact[i * 4 + 2] += dPageX; - m_arrRedact[i * 4 + 3] = dPageH - dQ; + m_arrRedact[i + 0] += dPageX; + m_arrRedact[i + 1] = dPageH - m_arrRedact[i + 1]; } return S_OK; @@ -3178,16 +3180,64 @@ bool CPdfWriter::SkipRedact(const double& dX, const double& dY, const double& dW if (m_arrRedact.empty()) return false; double dXmin = MM_2_PT(dX), dYmin = MM_2_PT(m_dPageHeight - dY - dH), dXmax = MM_2_PT(dX + dW), dYmax = MM_2_PT(m_dPageHeight - dY); - m_oTransform.Transform(dXmin, dYmin, &dXmin, &dYmin); - m_oTransform.Transform(dXmax, dYmax, &dXmax, &dYmax); - for (int i = 0; i < m_arrRedact.size(); i += 4) - { - double xMin = m_arrRedact[i + 0]; - double yMin = m_arrRedact[i + 1]; - double xMax = m_arrRedact[i + 2]; - double yMax = m_arrRedact[i + 3]; + CTransform& t = m_oTransform; + CTransform oT; + oT.Set(t.m11, -t.m12, -t.m21, t.m22, MM_2_PT(t.dx + t.m21 * m_dPageHeight), MM_2_PT(m_dPageHeight - m_dPageHeight * t.m22 - t.dy)); - if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax)) + double dX1, dY1, dX2, dY2, dX3, dY3, dX4, dY4; + dX1 = dXmin, dY1 = dYmin; + dX2 = dXmin, dY2 = dYmax; + dX3 = dXmax, dY3 = dYmax; + dX4 = dXmax, dY4 = dYmin; + + oT.Transform(dX1, dY1, &dX1, &dY1); + oT.Transform(dX2, dY2, &dX2, &dY2); + oT.Transform(dX3, dY3, &dX3, &dY3); + oT.Transform(dX4, dY4, &dX4, &dY4); + + std::vector poly2 = + { + PdfWriter::CPoint(dX1, dY1), + PdfWriter::CPoint(dX2, dY2), + PdfWriter::CPoint(dX3, dY3), + PdfWriter::CPoint(dX4, dY4) + }; + for (int i = 0; i < m_arrRedact.size(); i += 8) + { + std::vector poly1 = + { + PdfWriter::CPoint(m_arrRedact[i + 0], m_arrRedact[i + 1]), + PdfWriter::CPoint(m_arrRedact[i + 2], m_arrRedact[i + 3]), + PdfWriter::CPoint(m_arrRedact[i + 4], m_arrRedact[i + 5]), + PdfWriter::CPoint(m_arrRedact[i + 6], m_arrRedact[i + 7]) + }; + + if (PdfWriter::SAT(poly1, poly2)) + return true; + } + return false; +} +bool CPdfWriter::SkipRedact(const double& dX, const double& dY) +{ + if (m_arrRedact.empty()) + return false; + double dXc = MM_2_PT(dX), dYc = MM_2_PT(m_dPageHeight - dY); + CTransform& t = m_oTransform; + CTransform oT; + oT.Set(t.m11, -t.m12, -t.m21, t.m22, MM_2_PT(t.dx + t.m21 * m_dPageHeight), MM_2_PT(m_dPageHeight - m_dPageHeight * t.m22 - t.dy)); + oT.Transform(dXc, dYc, &dXc, &dYc); + for (int i = 0; i < m_arrRedact.size(); i += 8) + { + double x1 = m_arrRedact[i + 0]; + double y1 = m_arrRedact[i + 1]; + double x2 = m_arrRedact[i + 2]; + double y2 = m_arrRedact[i + 3]; + double x3 = m_arrRedact[i + 4]; + double y3 = m_arrRedact[i + 5]; + double x4 = m_arrRedact[i + 6]; + double y4 = m_arrRedact[i + 7]; + + if (PdfWriter::isPointInQuad(dXc, dYc, x1, y1, x2, y2, x3, y3, x4, y4)) return true; } return false; @@ -3307,23 +3357,10 @@ bool CPdfWriter::DrawText(unsigned char* pCodes, const unsigned int& unLen, cons if (!pCodes || !unLen) return false; - if (!m_arrRedact.empty()) - { - double dXc = MM_2_PT(dX), dYc = MM_2_PT(m_dPageHeight - dY); - m_oTransform.Transform(dXc, dYc, &dXc, &dYc); - // TODO должна быть проверка центрального положения, а не точки начала - // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта - for (int i = 0; i < m_arrRedact.size(); i += 4) - { - double xMin = m_arrRedact[i + 0]; - double yMin = m_arrRedact[i + 1]; - double xMax = m_arrRedact[i + 2]; - double yMax = m_arrRedact[i + 3]; - - if (xMin < dXc && dXc < xMax && yMin < dYc && dYc < yMax) - return true; - } - } + // TODO должна быть проверка центрального положения, а не точки начала + // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта + if (SkipRedact(dX, dY)) + return true; CTransform& t = m_oTransform; m_oCommandManager.SetTransform(t.m11, -t.m12, -t.m21, t.m22, MM_2_PT(t.dx + t.m21 * m_dPageHeight), MM_2_PT(m_dPageHeight - m_dPageHeight * t.m22 - t.dy)); @@ -3347,23 +3384,10 @@ bool CPdfWriter::DrawTextToRenderer(const unsigned int* unGid, const unsigned in { if (m_bSplit) return false; - if (!m_arrRedact.empty()) - { - double dXc = MM_2_PT(dX), dYc = MM_2_PT(m_dPageHeight - dY); - m_oTransform.Transform(dXc, dYc, &dXc, &dYc); - // TODO должна быть проверка центрального положения, а не точки начала - // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта - for (int i = 0; i < m_arrRedact.size(); i += 4) - { - double xMin = m_arrRedact[i + 0]; - double yMin = m_arrRedact[i + 1]; - double xMax = m_arrRedact[i + 2]; - double yMax = m_arrRedact[i + 3]; - - if (xMin < dXc && dXc < xMax && yMin < dYc && dYc < yMax) - return true; - } - } + // TODO должна быть проверка центрального положения, а не точки начала + // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта + if (SkipRedact(dX, dY)) + return true; // TODO pdf позволяет создание своего шрифта, но не следует это использовать для воссоздания шрифта запрещенного для редактирования или встраивания Aggplus::CGraphicsPathSimpleConverter simplifier; simplifier.SetRenderer(m_pRenderer); @@ -3379,23 +3403,10 @@ bool CPdfWriter::DrawTextToRenderer(const unsigned int* unGid, const unsigned in } bool CPdfWriter::PathCommandDrawText(unsigned int* pUnicodes, unsigned int unLen, const double& dX, const double& dY, const unsigned int* pGids) { - if (!m_arrRedact.empty()) - { - double dXc = MM_2_PT(dX), dYc = MM_2_PT(m_dPageHeight - dY); - m_oTransform.Transform(dXc, dYc, &dXc, &dYc); - // TODO должна быть проверка центрального положения, а не точки начала - // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта - for (int i = 0; i < m_arrRedact.size(); i += 4) - { - double xMin = m_arrRedact[i + 0]; - double yMin = m_arrRedact[i + 1]; - double xMax = m_arrRedact[i + 2]; - double yMax = m_arrRedact[i + 3]; - - if (xMin < dXc && dXc < xMax && yMin < dYc && dYc < yMax) - return true; - } - } + // TODO должна быть проверка центрального положения, а не точки начала + // TODO Сюда приходит много символов за раз, и нужно отрисовать только те, что вне областей редакта + if (SkipRedact(dX, dY)) + return true; unsigned char* pCodes = EncodeString(pUnicodes, unLen, pGids); if (!pCodes) diff --git a/PdfFile/PdfWriter.h b/PdfFile/PdfWriter.h index b6db52c232..12edd3f0bd 100644 --- a/PdfFile/PdfWriter.h +++ b/PdfFile/PdfWriter.h @@ -230,6 +230,7 @@ public: private: bool SkipRedact(const double& dX, const double& dY, const double& dW, const double& dH); + bool SkipRedact(const double& dX, const double& dY); PdfWriter::CImageDict* LoadImage(Aggplus::CImage* pImage, BYTE nAlpha); PdfWriter::CImageDict* DrawImage(Aggplus::CImage* pImage, const double& dX, const double& dY, const double& dW, const double& dH, const BYTE& nAlpha); bool DrawText(unsigned char* pCodes, const unsigned int& unLen, const double& dX, const double& dY, const std::string& sPUA); diff --git a/PdfFile/SrcReader/Adaptors.cpp b/PdfFile/SrcReader/Adaptors.cpp index a248ef68f1..68c8cc630b 100644 --- a/PdfFile/SrcReader/Adaptors.cpp +++ b/PdfFile/SrcReader/Adaptors.cpp @@ -186,16 +186,32 @@ void GlobalParamsAdaptor::AddRedact(const std::vector& arrRedactBox) { m_arrRedactBox.insert(m_arrRedactBox.end(), arrRedactBox.begin(), arrRedactBox.end()); } +double crossProduct(double x1, double y1, double x2, double y2, double x3, double y3) +{ + return (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1); +} bool GlobalParamsAdaptor::InRedact(double dX, double dY) { - for (int i = 0; i < m_arrRedactBox.size(); i += 4) + for (int i = 0; i < m_arrRedactBox.size(); i += 8) { - double xMin = m_arrRedactBox[i + 0]; - double yMin = m_arrRedactBox[i + 1]; - double xMax = m_arrRedactBox[i + 2]; - double yMax = m_arrRedactBox[i + 3]; + double x1 = m_arrRedactBox[i + 0]; + double y1 = m_arrRedactBox[i + 1]; + double x2 = m_arrRedactBox[i + 2]; + double y2 = m_arrRedactBox[i + 3]; + double x3 = m_arrRedactBox[i + 6]; + double y3 = m_arrRedactBox[i + 7]; + double x4 = m_arrRedactBox[i + 4]; + double y4 = m_arrRedactBox[i + 5]; - if (xMin < dX && dX < xMax && yMin < dY && dY < yMax) + // Проверяем знаки векторных произведений для всех сторон + double cross1 = crossProduct(x1, y1, x2, y2, dX, dY); + double cross2 = crossProduct(x2, y2, x3, y3, dX, dY); + double cross3 = crossProduct(x3, y3, x4, y4, dX, dY); + double cross4 = crossProduct(x4, y4, x1, y1, dX, dY); + + // Точка внутри, если все векторные произведения имеют одинаковый знак + if ((cross1 >= 0 && cross2 >= 0 && cross3 >= 0 && cross4 >= 0) || + (cross1 <= 0 && cross2 <= 0 && cross3 <= 0 && cross4 <= 0)) return true; } return false; diff --git a/PdfFile/SrcReader/PdfAnnot.cpp b/PdfFile/SrcReader/PdfAnnot.cpp index 1d03788639..0aa826733c 100644 --- a/PdfFile/SrcReader/PdfAnnot.cpp +++ b/PdfFile/SrcReader/PdfAnnot.cpp @@ -2369,6 +2369,21 @@ CAnnotStamp::CAnnotStamp(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int } } } + else + { + m_dX1 = 0; + m_dY1 = 0; + + m_dX2 = 0; + m_dY2 = 0; + + m_dX3 = 0; + m_dY3 = 0; + + m_dX4 = 0; + m_dY4 = 0; + return; + } oAP.free(); oObj2.free(); oObj.free(); double formXMin, formYMin, formXMax, formYMax, x, y, sx, sy; @@ -2493,6 +2508,19 @@ CAnnotRedact::CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, in } oObj.free(); + // Замена C: 3 - Цвет - C + if (oAnnot.dictLookup("OC", &oObj)->isArray()) + { + m_unAFlags |= (1 << 3); + int nBCLength = oObj.arrayGetLength(); + for (int j = 0; j < nBCLength; ++j) + { + m_arrC.push_back(oObj.arrayGet(j, &oObj2)->isNum() ? oObj2.getNum() : 0.0); + oObj2.free(); + } + } + oObj.free(); + oAnnot.free(); } void CAnnotRedact::SetFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef) diff --git a/PdfFile/SrcReader/PdfAnnot.h b/PdfFile/SrcReader/PdfAnnot.h index 0f85941fb0..2cf88669e5 100644 --- a/PdfFile/SrcReader/PdfAnnot.h +++ b/PdfFile/SrcReader/PdfAnnot.h @@ -194,6 +194,7 @@ protected: double m_dHeight; // Высота холста, для Y трансформации double m_dX; // Смещение по X для трансформации double m_pRect[4]; // Координаты + std::vector m_arrC; // Специальный цвет private: unsigned int m_unAnnotFlag; // Флаг аннотации - F @@ -205,7 +206,6 @@ private: std::string m_sM; // Дата последнего изменения std::string m_sOUserID; // OO User ID std::string m_sOMetadata; // OO метаданные формы - std::vector m_arrC; // Специальный цвет CBorderType* m_pBorder; // Граница }; diff --git a/PdfFile/SrcWriter/Annotation.cpp b/PdfFile/SrcWriter/Annotation.cpp index 37d3ff9322..80af28a25b 100644 --- a/PdfFile/SrcWriter/Annotation.cpp +++ b/PdfFile/SrcWriter/Annotation.cpp @@ -1268,6 +1268,10 @@ namespace PdfWriter { AddToVectorD(this, "IC", arrIC); } + void CRedactAnnotation::SetOC(const std::vector& arrOC) + { + AddToVectorD(this, "OC", arrOC); + } void CRedactAnnotation::SetQuadPoints(const std::vector& arrQuadPoints) { CArrayObject* pArray = new CArrayObject(); @@ -2141,11 +2145,18 @@ namespace PdfWriter { std::string sName = m_sAP_N_Yes.empty() ? "Yes" : m_sAP_N_Yes; Add("AS", sName.c_str()); + + if (!m_nParentID) + Add("V", sName.c_str()); + return sName; } void CCheckBoxWidget::Off() { Add("AS", "Off"); + + if (!m_nParentID) + Add("V", "Off"); } void CCheckBoxWidget::SwitchAP(const std::string& sV, int nI) { diff --git a/PdfFile/SrcWriter/Annotation.h b/PdfFile/SrcWriter/Annotation.h index 3bb7dfd82d..3cf363e56a 100644 --- a/PdfFile/SrcWriter/Annotation.h +++ b/PdfFile/SrcWriter/Annotation.h @@ -432,6 +432,7 @@ namespace PdfWriter void SetQ(BYTE nQ); void SetOverlayText(const std::wstring& wsOverlayText); void SetIC(const std::vector& arrIC); + void SetOC(const std::vector& arrOC); void SetQuadPoints(const std::vector& arrQuadPoints); }; class CWidgetAnnotation : public CAnnotation diff --git a/PdfFile/SrcWriter/Document.cpp b/PdfFile/SrcWriter/Document.cpp index a50e4e000b..c952e60b99 100644 --- a/PdfFile/SrcWriter/Document.cpp +++ b/PdfFile/SrcWriter/Document.cpp @@ -1326,7 +1326,7 @@ namespace PdfWriter pObj->SetHidden(); if (!pObj->IsIndirect()) return; - TXrefEntry* pEntry = m_pXref->GetEntryByObjectId(pObj->GetObjId()); + TXrefEntry* pEntry = pObj->GetXrefEntry(); if (pEntry) { pEntry->nEntryType = 'f'; // FREE_ENTRY diff --git a/PdfFile/SrcWriter/Objects.cpp b/PdfFile/SrcWriter/Objects.cpp index f511e66667..3f8d014a71 100644 --- a/PdfFile/SrcWriter/Objects.cpp +++ b/PdfFile/SrcWriter/Objects.cpp @@ -859,6 +859,37 @@ namespace PdfWriter return NULL; } + void CXref::Add(CObjectBase* pObject) + { + if (!pObject) + return; + + if (pObject->IsDirect() || pObject->IsIndirect()) + return; + + if (m_arrEntries.size() >= LIMIT_MAX_XREF_ELEMENT) + { + RELEASE_OBJECT(pObject); + return; + } + + // В случае ошибки r объектe нужно применить dispose + TXrefEntry* pEntry = new TXrefEntry; + if (NULL == pEntry) + { + RELEASE_OBJECT(pObject); + return; + } + + m_arrEntries.push_back(pEntry); + + pEntry->nEntryType = IN_USE_ENTRY; + pEntry->unByteOffset = 0; + pEntry->unGenNo = 0; + pEntry->pObject = pObject; + pObject->SetIndirect(); + pObject->SetXrefEntry(pEntry); + } void CXref::Add(CObjectBase* pObject, unsigned int unObjectGen) { if (!pObject) @@ -887,7 +918,7 @@ namespace PdfWriter pEntry->unByteOffset = 0; pEntry->unGenNo = unObjectGen; pEntry->pObject = pObject; - pObject->SetRef(0, pEntry->unGenNo); + pObject->SetRef(m_unStartOffset + m_arrEntries.size() - 1, pEntry->unGenNo); pObject->SetIndirect(); pObject->SetXrefEntry(pEntry); } diff --git a/PdfFile/SrcWriter/Objects.h b/PdfFile/SrcWriter/Objects.h index 8ab7736fd4..ed57b8803f 100644 --- a/PdfFile/SrcWriter/Objects.h +++ b/PdfFile/SrcWriter/Objects.h @@ -518,7 +518,8 @@ namespace PdfWriter TXrefEntry* GetEntry(unsigned int unIndex) const; TXrefEntry* GetEntryByObjectId(unsigned int unObjectId) const; CXref* GetXrefByObjectId(unsigned int unObjectId); - void Add(CObjectBase* pObject, unsigned int unObjectGen = 0); + void Add(CObjectBase* pObject); + void Add(CObjectBase* pObject, unsigned int unObjectGen); void Remove(CObjectBase* pObject); void WriteToStream(CStream* pStream, CEncrypt* pEncrypt, bool bStream = false); void SetPrev(CXref* pPrev) diff --git a/PdfFile/SrcWriter/RedactOutputDev.cpp b/PdfFile/SrcWriter/RedactOutputDev.cpp index 6fc764d6e5..084066fc09 100644 --- a/PdfFile/SrcWriter/RedactOutputDev.cpp +++ b/PdfFile/SrcWriter/RedactOutputDev.cpp @@ -33,6 +33,7 @@ #include "RedactOutputDev.h" #include "Types.h" #include "Streams.h" +#include "Utils.h" #include "../lib/xpdf/GfxFont.h" #include "../lib/xpdf/XRef.h" @@ -67,13 +68,13 @@ RedactOutputDev::~RedactOutputDev() void RedactOutputDev::SetRedact(const std::vector& arrQuadPoints) { m_arrQuadPoints = arrQuadPoints; - for (int i = 0; i < m_arrQuadPoints.size(); i += 4) + for (int i = 0; i < m_arrQuadPoints.size(); i += 8) { m_oPathRedact.StartFigure(); m_oPathRedact.MoveTo(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1]); - m_oPathRedact.LineTo(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 3]); m_oPathRedact.LineTo(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3]); - m_oPathRedact.LineTo(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 1]); + m_oPathRedact.LineTo(m_arrQuadPoints[i + 4], m_arrQuadPoints[i + 5]); + m_oPathRedact.LineTo(m_arrQuadPoints[i + 6], m_arrQuadPoints[i + 7]); m_oPathRedact.CloseFigure(); } } @@ -90,7 +91,7 @@ void RedactOutputDev::setDefaultCTM(double *ctm) } void RedactOutputDev::startPage(int nPageIndex, GfxState *pGState) { - m_pPage = m_pDoc->GetEditPage(nPageIndex - 1); + m_pPage = m_pDoc->GetEditPage(nPageIndex); m_pRenderer->EditPage(m_pPage); m_pDoc->SetCurPage(m_pPage); m_pDoc->ClearPageFull(); @@ -495,14 +496,18 @@ void RedactOutputDev::drawChar(GfxState *pGState, double dX, double dY, double d pGState->transform(dX + dDx, dY + dDy, &endX, &endY); double dCenterX = (startX + endX) / 2; double dCenterY = (startY + endY) / 2; - for (int i = 0; i < m_arrQuadPoints.size(); i += 4) + for (int i = 0; i < m_arrQuadPoints.size(); i += 8) { - double xMin = m_arrQuadPoints[i + 0]; - double yMin = m_arrQuadPoints[i + 1]; - double xMax = m_arrQuadPoints[i + 2]; - double yMax = m_arrQuadPoints[i + 3]; + double x1 = m_arrQuadPoints[i + 0]; + double y1 = m_arrQuadPoints[i + 1]; + double x2 = m_arrQuadPoints[i + 2]; + double y2 = m_arrQuadPoints[i + 3]; + double x3 = m_arrQuadPoints[i + 4]; + double y3 = m_arrQuadPoints[i + 5]; + double x4 = m_arrQuadPoints[i + 6]; + double y4 = m_arrQuadPoints[i + 7]; - if (xMin < dCenterX && dCenterX < xMax && yMin < dCenterY && dCenterY < yMax) + if (isPointInQuad(dCenterX, dCenterY, x1, y1, x2, y2, x3, y3, x4, y4)) { m_pRenderer->put_FontSize(dOldSize); return; @@ -719,41 +724,73 @@ void RedactOutputDev::drawForm(GfxState *pGState, Ref id, const char* name) return; } - // TODO нужно учитывать Matrix у формы double dXmin = 0, dYmin = 0, dXmax = 0, dYmax = 0; - Object oBBox; - if (oForm.streamGetDict()->lookup("BBox", &oBBox)->isArray() && oBBox.arrayGetLength() == 4) + double dX1 = 0, dY1 = 0, dX2 = 0, dY2 = 1, dX3 = 1, dY3 = 1, dX4 = 1, dY4 = 0; + Object oObj; + if (oForm.streamGetDict()->lookup("BBox", &oObj)->isArray() && oObj.arrayGetLength() == 4) { Object oNum; - if (oBBox.arrayGet(0, &oNum)->isNum()) + if (oObj.arrayGet(0, &oNum)->isNum()) dXmin = oNum.getNum(); oNum.free(); - if (oBBox.arrayGet(1, &oNum)->isNum()) + if (oObj.arrayGet(1, &oNum)->isNum()) dYmin = oNum.getNum(); oNum.free(); - if (oBBox.arrayGet(2, &oNum)->isNum()) + if (oObj.arrayGet(2, &oNum)->isNum()) dXmax = oNum.getNum(); oNum.free(); - if (oBBox.arrayGet(3, &oNum)->isNum()) + if (oObj.arrayGet(3, &oNum)->isNum()) dYmax = oNum.getNum(); - oNum.free(); + oNum.free(); oObj.free(); - Transform(m_arrMatrix, dXmin, dYmin, &dXmin, &dYmin); - Transform(m_arrMatrix, dXmax, dYmax, &dXmax, &dYmax); + dX1 = dXmin, dY1 = dYmin; + dX2 = dXmin, dY2 = dYmax; + dX3 = dXmax, dY3 = dYmax; + dX4 = dXmax, dY4 = dYmin; + + double oMatrix[6] = { 1, 0, 0, 1, 0, 0 }; + if (oForm.streamGetDict()->lookup("Matrix", &oObj)->isArray() && oObj.arrayGetLength() == 6) + { + Object oObj2; + for (int i = 0; i < 6; ++i) + { + oMatrix[i] = oObj.arrayGet(i, &oObj2)->getNum(); + oObj2.free(); + } + } + + Transform(oMatrix, dX1, dY1, &dX1, &dY1); + Transform(oMatrix, dX2, dY2, &dX2, &dY2); + Transform(oMatrix, dX3, dY3, &dX3, &dY3); + Transform(oMatrix, dX4, dY4, &dX4, &dY4); + + Transform(m_arrMatrix, dX1, dY1, &dX1, &dY1); + Transform(m_arrMatrix, dX2, dY2, &dX2, &dY2); + Transform(m_arrMatrix, dX3, dY3, &dX3, &dY3); + Transform(m_arrMatrix, dX4, dY4, &dX4, &dY4); } - oBBox.free(); + oObj.free(); - for (int i = 0; i < m_arrQuadPoints.size(); i += 4) + std::vector poly2 = { - double xMin = m_arrQuadPoints[i + 0]; - double yMin = m_arrQuadPoints[i + 1]; - double xMax = m_arrQuadPoints[i + 2]; - double yMax = m_arrQuadPoints[i + 3]; + CPoint(dX1, dY1), + CPoint(dX2, dY2), + CPoint(dX3, dY3), + CPoint(dX4, dY4) + }; + for (int i = 0; i < m_arrQuadPoints.size(); i += 8) + { + std::vector poly1 = + { + CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1]), + CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3]), + CPoint(m_arrQuadPoints[i + 4], m_arrQuadPoints[i + 5]), + CPoint(m_arrQuadPoints[i + 6], m_arrQuadPoints[i + 7]) + }; - if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax)) + if (PdfWriter::SAT(poly1, poly2)) return; } - oForm.free(); m_pPage->GrSave(); UpdateTransform(); @@ -770,18 +807,30 @@ void RedactOutputDev::drawImage(GfxState *pGState, Ref id, const char* name) // TODO пока что исключается всё изображение - double dXmin = 0, dYmin = 0, dXmax = 1, dYmax = 1; - Transform(m_arrMatrix, dXmin, dYmin, &dXmin, &dYmin); - Transform(m_arrMatrix, dXmax, dYmax, &dXmax, &dYmax); + double dX1 = 0, dY1 = 0, dX2 = 0, dY2 = 1, dX3 = 1, dY3 = 1, dX4 = 1, dY4 = 0; + Transform(m_arrMatrix, dX1, dY1, &dX1, &dY1); + Transform(m_arrMatrix, dX2, dY2, &dX2, &dY2); + Transform(m_arrMatrix, dX3, dY3, &dX3, &dY3); + Transform(m_arrMatrix, dX4, dY4, &dX4, &dY4); - for (int i = 0; i < m_arrQuadPoints.size(); i += 4) + std::vector poly2 = { - double xMin = m_arrQuadPoints[i + 0]; - double yMin = m_arrQuadPoints[i + 1]; - double xMax = m_arrQuadPoints[i + 2]; - double yMax = m_arrQuadPoints[i + 3]; + CPoint(dX1, dY1), + CPoint(dX2, dY2), + CPoint(dX3, dY3), + CPoint(dX4, dY4) + }; + for (int j = 0; j < m_arrQuadPoints.size(); j += 8) + { + std::vector poly1 = + { + CPoint(m_arrQuadPoints[j + 0], m_arrQuadPoints[j + 1]), + CPoint(m_arrQuadPoints[j + 2], m_arrQuadPoints[j + 3]), + CPoint(m_arrQuadPoints[j + 4], m_arrQuadPoints[j + 5]), + CPoint(m_arrQuadPoints[j + 6], m_arrQuadPoints[j + 7]) + }; - if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax)) + if (PdfWriter::SAT(poly1, poly2)) return; } @@ -943,7 +992,6 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC m_pRenderer->m_oPath.Clear(); CMatrix oMatrix(m_arrMatrix[0], m_arrMatrix[1], m_arrMatrix[2], m_arrMatrix[3], m_arrMatrix[4], m_arrMatrix[5]); - CMatrix oInverse = oMatrix.Inverse(); std::vector arrForStroke; Aggplus::CGraphicsPath oPath, oPathResult; @@ -952,15 +1000,12 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC if (bStroke) { - std::vector rectangles; - for (int i = 0; i < m_arrQuadPoints.size(); i += 4) + for (int i = 0; i < m_arrQuadPoints.size(); i += 8) { - arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1]), CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 3]))); - arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 3]), CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3]))); - arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3]), CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 1]))); - arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 1]), CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1]))); - - rectangles.push_back({m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 3], m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 1]}); + arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1]), CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3]))); + arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 2], m_arrQuadPoints[i + 3]), CPoint(m_arrQuadPoints[i + 4], m_arrQuadPoints[i + 5]))); + arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 4], m_arrQuadPoints[i + 5]), CPoint(m_arrQuadPoints[i + 6], m_arrQuadPoints[i + 7]))); + arrForStroke.push_back(CSegment(CPoint(m_arrQuadPoints[i + 6], m_arrQuadPoints[i + 7]), CPoint(m_arrQuadPoints[i + 0], m_arrQuadPoints[i + 1]))); } for (int nSubPathIndex = 0, nSubPathCount = pPath->getNumSubpaths(); nSubPathIndex < nSubPathCount; ++nSubPathIndex) @@ -1007,6 +1052,18 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC oMatrix.Apply(dX, dY); ++nCurPointIndex; + oPath.StartFigure(); + oPath.MoveTo(dXCur, dYCur); + oPath.LineTo(dX, dY); + oPath.CloseFigure(); + + dXCur = dX, dYCur = dY; + + oPathResult = Aggplus::CalcBooleanOperation(oPath, m_oPathRedact, Aggplus::BooleanOpType::Subtraction); + DrawPathRedact(&oPathResult, bStroke); + oPathResult.Reset(); oPath.Reset(); + + /* CLineClipper clipper(rectangles); CSegment line(CPoint(dXCur, dYCur), CPoint(dX, dY)); dXCur = dX; dYCur = dY; @@ -1021,10 +1078,21 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC oInverse.Apply(dX2, dY2); m_pRenderer->m_oPath.LineTo(dX2, dY2); } + */ } } if (pSubpath->isClosed()) { + oPath.StartFigure(); + oPath.MoveTo(dXCur, dYCur); + oPath.LineTo(dXStart, dYStart); + oPath.CloseFigure(); + + oPathResult = Aggplus::CalcBooleanOperation(oPath, m_oPathRedact, Aggplus::BooleanOpType::Subtraction); + DrawPathRedact(&oPathResult, bStroke); + oPathResult.Reset(); oPath.Reset(); + + /* CLineClipper clipper(rectangles); CSegment line(CPoint(dXCur, dYCur), CPoint(dXStart, dYStart)); auto visibleSegments = clipper.getVisibleSegments(line); @@ -1037,6 +1105,7 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC oInverse.Apply(dX2, dY2); m_pRenderer->m_oPath.LineTo(dX2, dY2); } + */ } } } @@ -1079,7 +1148,7 @@ void RedactOutputDev::DoPathRedact(GfxState* pGState, GfxPath* pPath, double* pC ++nCurPointIndex; } } - if (pSubpath->isClosed()) + // if (pSubpath->isClosed()) Принудительное замыкание фигур для CGraphicsPath oPath.CloseFigure(); } diff --git a/PdfFile/SrcWriter/States.cpp b/PdfFile/SrcWriter/States.cpp index 57b75a973d..465fc90ec0 100644 --- a/PdfFile/SrcWriter/States.cpp +++ b/PdfFile/SrcWriter/States.cpp @@ -297,12 +297,14 @@ bool SkipPath(const std::vector& arrForStroke, const PdfWri } return false; } -void CPath::DrawPathRedact(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector& arrForStroke) +bool CPath::DrawPathRedact(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector& arrForStroke) { PdfWriter::CMatrix oInverse = pMatrix->Inverse(); size_t length = oPath->GetPointCount(), compound = oPath->GetCloseCount(); std::vector points = oPath->GetPoints(0, length + compound); + if (length + compound == 0) + return false; double dXStart = -1, dYStart = -1, dXCur = -1, dYCur = -1; bool bBreak = false; @@ -388,6 +390,7 @@ void CPath::DrawPathRedact(PdfWriter::CMatrix* pMatrix, Aggplus::CGraphicsPath* Close(); } } + return true; } void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRedact, PdfWriter::CPage* pPage, bool bStroke, bool bFill, bool bEoFill, PdfWriter::CShading* pShading, PdfWriter::CExtGrState* pShadingExtGrState) @@ -395,13 +398,13 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe PdfWriter::CMatrix oInverse = pMatrix->Inverse(); Aggplus::CGraphicsPath oPath, oPathRedact, oPathResult; - for (int i = 0; i < arrRedact.size(); i += 4) + for (int i = 0; i < arrRedact.size(); i += 8) { oPathRedact.StartFigure(); oPathRedact.MoveTo(arrRedact[i + 0], arrRedact[i + 1]); - oPathRedact.LineTo(arrRedact[i + 0], arrRedact[i + 3]); oPathRedact.LineTo(arrRedact[i + 2], arrRedact[i + 3]); - oPathRedact.LineTo(arrRedact[i + 2], arrRedact[i + 1]); + oPathRedact.LineTo(arrRedact[i + 4], arrRedact[i + 5]); + oPathRedact.LineTo(arrRedact[i + 6], arrRedact[i + 7]); oPathRedact.CloseFigure(); } @@ -419,20 +422,23 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe if (bFill || bEoFill) { oPathResult = Aggplus::CalcBooleanOperation(oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction); - DrawPathRedact(pMatrix, &oPathResult, bStroke); + bool bPath = DrawPathRedact(pMatrix, &oPathResult, bStroke); - if (!pShading) - Draw(pPage, false, bFill, bEoFill); - else + if (bPath) { - pPage->GrSave(); - Clip(pPage, bEoFill); + if (!pShading) + Draw(pPage, false, bFill, bEoFill); + else + { + pPage->GrSave(); + Clip(pPage, bEoFill); - if (pShadingExtGrState) - pPage->SetExtGrState(pShadingExtGrState); + if (pShadingExtGrState) + pPage->SetExtGrState(pShadingExtGrState); - pPage->DrawShading(pShading); - pPage->GrRestore(); + pPage->DrawShading(pShading); + pPage->GrRestore(); + } } } @@ -440,16 +446,14 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe if (bStroke) { + bool bPath = false; std::vector arrForStroke; - std::vector rectangles; - for (int i = 0; i < arrRedact.size(); i += 4) + for (int i = 0; i < arrRedact.size(); i += 8) { - arrForStroke.push_back(PdfWriter::CSegment(PdfWriter::CPoint(arrRedact[i + 0], arrRedact[i + 1]), PdfWriter::CPoint(arrRedact[i + 0], arrRedact[i + 3]))); - arrForStroke.push_back(PdfWriter::CSegment(PdfWriter::CPoint(arrRedact[i + 0], arrRedact[i + 3]), PdfWriter::CPoint(arrRedact[i + 2], arrRedact[i + 3]))); - arrForStroke.push_back(PdfWriter::CSegment(PdfWriter::CPoint(arrRedact[i + 2], arrRedact[i + 3]), PdfWriter::CPoint(arrRedact[i + 2], arrRedact[i + 1]))); - arrForStroke.push_back(PdfWriter::CSegment(PdfWriter::CPoint(arrRedact[i + 2], arrRedact[i + 1]), PdfWriter::CPoint(arrRedact[i + 0], arrRedact[i + 1]))); - - rectangles.push_back({arrRedact[i + 0], arrRedact[i + 3], arrRedact[i + 2], arrRedact[i + 1]}); + arrForStroke.push_back(PdfWriter::CSegment(PdfWriter::CPoint(arrRedact[i + 0], arrRedact[i + 1]), PdfWriter::CPoint(arrRedact[i + 2], arrRedact[i + 3]))); + arrForStroke.push_back(PdfWriter::CSegment(PdfWriter::CPoint(arrRedact[i + 2], arrRedact[i + 3]), PdfWriter::CPoint(arrRedact[i + 4], arrRedact[i + 5]))); + arrForStroke.push_back(PdfWriter::CSegment(PdfWriter::CPoint(arrRedact[i + 4], arrRedact[i + 5]), PdfWriter::CPoint(arrRedact[i + 6], arrRedact[i + 7]))); + arrForStroke.push_back(PdfWriter::CSegment(PdfWriter::CPoint(arrRedact[i + 6], arrRedact[i + 7]), PdfWriter::CPoint(arrRedact[i + 0], arrRedact[i + 1]))); } size_t length = oPath.GetPointCount(), compound = oPath.GetCloseCount(); @@ -477,7 +481,7 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe dXCur = dX3, dYCur = dY3; oPathResult = Aggplus::CalcBooleanOperation(_oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction); - DrawPathRedact(pMatrix, &oPathResult, bStroke, arrForStroke); + bPath = bPath || DrawPathRedact(pMatrix, &oPathResult, bStroke, arrForStroke); oPathResult.Reset(); } else if (oPath.IsMovePoint(i)) @@ -489,11 +493,25 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe { double dX = points[i].X, dY = points[i].Y; + Aggplus::CGraphicsPath _oPath; + _oPath.StartFigure(); + _oPath.MoveTo(dXCur, dYCur); + _oPath.LineTo(dX, dY); + _oPath.CloseFigure(); + + dXCur = dX, dYCur = dY; + + oPathResult = Aggplus::CalcBooleanOperation(_oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction); + bPath = bPath || DrawPathRedact(pMatrix, &oPathResult, bStroke); + oPathResult.Reset(); + + /* PdfWriter::CLineClipper clipper(rectangles); PdfWriter::CSegment line(PdfWriter::CPoint(dXCur, dYCur), PdfWriter::CPoint(dX, dY)); dXCur = dX; dYCur = dY; auto visibleSegments = clipper.getVisibleSegments(line); + bPath = bPath || visibleSegments.size() != 0; for (int i = 0; i < visibleSegments.size(); ++i) { double dX1 = visibleSegments[i].start.x, dY1 = visibleSegments[i].start.y; @@ -503,12 +521,24 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe MoveTo(dX1, dY1); LineTo(dX2, dY2); } + */ } else if (oPath.IsClosePoint(i)) { + Aggplus::CGraphicsPath _oPath; + _oPath.StartFigure(); + _oPath.MoveTo(dXCur, dYCur); + _oPath.LineTo(dXStart, dYStart); + _oPath.CloseFigure(); + + oPathResult = Aggplus::CalcBooleanOperation(_oPath, oPathRedact, Aggplus::BooleanOpType::Subtraction); + bPath = bPath || DrawPathRedact(pMatrix, &oPathResult, bStroke); + oPathResult.Reset(); + /* PdfWriter::CLineClipper clipper(rectangles); PdfWriter::CSegment line(PdfWriter::CPoint(dXCur, dYCur), PdfWriter::CPoint(dXStart, dYStart)); auto visibleSegments = clipper.getVisibleSegments(line); + bPath = bPath || visibleSegments.size() != 0; for (int i = 0; i < visibleSegments.size(); ++i) { double dX1 = visibleSegments[i].start.x, dY1 = visibleSegments[i].start.y; @@ -518,10 +548,12 @@ void CPath::Redact(PdfWriter::CMatrix* pMatrix, const std::vector& arrRe MoveTo(dX1, dY1); LineTo(dX2, dY2); } + */ } } - Draw(pPage, bStroke, false, false); + if (bPath) + Draw(pPage, bStroke, false, false); } m_vCommands = vCommands; diff --git a/PdfFile/SrcWriter/States.h b/PdfFile/SrcWriter/States.h index 7ed7463e66..de49508ba5 100644 --- a/PdfFile/SrcWriter/States.h +++ b/PdfFile/SrcWriter/States.h @@ -1594,7 +1594,7 @@ public: void GetBounds(double& dL, double& dT, double& dR, double& dB); void Redact(PdfWriter::CMatrix* oMatrix, const std::vector& arrRedact, PdfWriter::CPage* pPage, bool bStroke, bool bFill, bool bEoFill, PdfWriter::CShading* pShading, PdfWriter::CExtGrState* pShadingExtGrState); - void DrawPathRedact(PdfWriter::CMatrix* oMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector& arrForStroke = {}); + bool DrawPathRedact(PdfWriter::CMatrix* oMatrix, Aggplus::CGraphicsPath* oPath, bool bStroke, const std::vector& arrForStroke = {}); private: diff --git a/PdfFile/SrcWriter/Utils.cpp b/PdfFile/SrcWriter/Utils.cpp index 9157d95983..48d41a7dae 100644 --- a/PdfFile/SrcWriter/Utils.cpp +++ b/PdfFile/SrcWriter/Utils.cpp @@ -316,4 +316,67 @@ namespace PdfWriter return sRes; } + void projectPolygon(const std::vector& polygon, const CPoint& axis, double& min, double& max) + { + min = std::numeric_limits::max(); + max = std::numeric_limits::lowest(); + + for (const auto& point : polygon) + { + double projection = (point.x * axis.x + point.y * axis.y) / (axis.x * axis.x + axis.y * axis.y); + projection *= (axis.x * axis.x + axis.y * axis.y); + + if (projection < min) min = projection; + if (projection > max) max = projection; + } + } + bool SAT(const std::vector& poly1, const std::vector& poly2) + { + std::vector axes; + for (size_t i = 0; i < poly1.size(); i++) + { + CPoint p1 = poly1[i]; + CPoint p2 = poly1[(i + 1) % poly1.size()]; + CPoint edge(p2.x - p1.x, p2.y - p1.y); + CPoint normal(-edge.y, edge.x); // Перпендикуляр к ребру + axes.push_back(normal); + } + + for (size_t i = 0; i < poly2.size(); i++) + { + CPoint p1 = poly2[i]; + CPoint p2 = poly2[(i + 1) % poly2.size()]; + CPoint edge(p2.x - p1.x, p2.y - p1.y); + CPoint normal(-edge.y, edge.x); // Перпендикуляр к ребру + axes.push_back(normal); + } + + // Проверяем все оси на разделение + for (const auto& axis : axes) + { + double min1, max1, min2, max2; + projectPolygon(poly1, axis, min1, max1); + projectPolygon(poly2, axis, min2, max2); + + if (max1 < min2 || max2 < min1) + return false; // Найдена разделяющая ось + } + return true; // Пересекаются + } + double crossProduct(double x1, double y1, double x2, double y2, double x3, double y3) + { + return (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1); + } + bool isPointInQuad(double px, double py, double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) + { + // Проверяем знаки векторных произведений для всех сторон + double cross1 = crossProduct(x1, y1, x2, y2, px, py); + double cross2 = crossProduct(x2, y2, x3, y3, px, py); + double cross3 = crossProduct(x3, y3, x4, y4, px, py); + double cross4 = crossProduct(x4, y4, x1, y1, px, py); + + // Точка внутри, если все векторные произведения имеют одинаковый знак + return (cross1 >= 0 && cross2 >= 0 && cross3 >= 0 && cross4 >= 0) || + (cross1 <= 0 && cross2 <= 0 && cross3 <= 0 && cross4 <= 0); + } } diff --git a/PdfFile/SrcWriter/Utils.h b/PdfFile/SrcWriter/Utils.h index 776fffabe1..2a935f5b91 100644 --- a/PdfFile/SrcWriter/Utils.h +++ b/PdfFile/SrcWriter/Utils.h @@ -141,6 +141,13 @@ namespace PdfWriter std::string DateNow(); std::wstring NormalizeWhitespace(const std::wstring& s); + + // Пересечение многоугольников по теореме о разделяющей оси + bool SAT(const std::vector& poly1, const std::vector& poly2); + // Проверка принадлежности точки выпуклому четырехугольнику + bool isPointInQuad(double px, double py, + double x1, double y1, double x2, double y2, + double x3, double y3, double x4, double y4); } #endif // _PDF_WRITER_SRC_UTILS_H