Merge branch 'release/v9.1.0' into fix/bug-72300

This commit is contained in:
Kirill Polyakov
2025-10-09 16:50:28 +03:00
45 changed files with 1065 additions and 502 deletions

View File

@ -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;
}

View File

@ -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();

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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<std::vector<int>>& 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<std::vector<int>>& 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<PointD> 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)

View File

@ -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<PointD> 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

View File

@ -117,6 +117,7 @@ namespace Aggplus
std::vector<PointD> GetPoints(unsigned idx, unsigned count) const noexcept;
std::vector<CGraphicsPath> 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;

View File

@ -212,7 +212,7 @@ public:
void Offset(const PointF_T<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;

View File

@ -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))

View File

@ -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;

View File

@ -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();

View File

@ -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);

View File

@ -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;
}

View File

@ -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<int> arrPages = { 0 };
std::vector<int> 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<int> 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;
}

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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);