diff --git a/Common/js/__pycache__/common.cpython-310.pyc b/Common/js/__pycache__/common.cpython-310.pyc new file mode 100644 index 0000000000..d8dcf0ac0d Binary files /dev/null and b/Common/js/__pycache__/common.cpython-310.pyc differ diff --git a/DesktopEditor/graphics/commands/AnnotField.cpp b/DesktopEditor/graphics/commands/AnnotField.cpp index e9e1bf3446..6f5727b1b8 100644 --- a/DesktopEditor/graphics/commands/AnnotField.cpp +++ b/DesktopEditor/graphics/commands/AnnotField.cpp @@ -1153,7 +1153,10 @@ bool CWidgetsInfo::Read(NSOnlineOfficeBinToPdf::CBufferReader* pReader, IMetafil for (int i = 0; i < n; ++i) { std::string sImagePath = pReader->ReadStringA(); - m_arrButtonImg.push_back(pCorrector->GetImagePath(UTF8_TO_U(sImagePath))); + std::wstring sImage = UTF8_TO_U(sImagePath); + if (sImagePath.find("data:") != 0 && !sImagePath.empty()) + sImage = pCorrector->GetImagePath(sImage); + m_arrButtonImg.push_back(sImage); } return true; diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js index 284b07012b..1d83857a96 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js @@ -450,10 +450,13 @@ function readAction(reader, rec, readDoubleFunc, readStringFunc) } function readAnnot(reader, rec, readDoubleFunc, readDouble2Func, readStringFunc, isRead = false) { - rec["AP"] = {}; + if (!isRead) + rec["AP"] = {}; // Annot // number for relations with AP - rec["AP"]["i"] = reader.readInt(); + let APi = reader.readInt(); + if (!isRead) + rec["AP"]["i"] = APi; rec["annotflag"] = reader.readInt(); // 12.5.3 let bHidden = (rec["annotflag"] >> 1) & 1; // Hidden @@ -536,16 +539,18 @@ function readAnnot(reader, rec, readDoubleFunc, readDouble2Func, readStringFunc, if (flags & (1 << 6)) { if (isRead) - rec["AP"]["render"] = reader.readData(); // TODO use Render - Uint8Array + { + let APrender = reader.readData(); // TODO use Render - Uint8Array + // rec["AP"]["render"] = APrender; + } else rec["AP"]["have"] = (flags >> 6) & 1; } // User ID if (flags & (1 << 7)) rec["OUserID"] = readStringFunc.call(reader); - // User ID - if (flags & (1 << 8)) - rec["AP"]["Copy"] = reader.readInt(); + // if (flags & (1 << 8)) + // reader.readInt(); } function readAnnotAP(reader, AP) { @@ -581,7 +586,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF { // Markup let flags = 0; - if ((rec["Type"] < 18 && rec["Type"] != 1 && rec["Type"] != 15) || rec["Type"] == 25) + if ((rec["type"] < 18 && rec["type"] != 1 && rec["type"] != 15) || rec["type"] == 25) { flags = reader.readInt(); if (flags & (1 << 0)) @@ -636,7 +641,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF rec["Subj"] = readStringFunc.call(reader); } // Text - if (rec["Type"] == 0) + if (rec["type"] == 0) { // Background color - C->IC if (rec["C"]) @@ -660,7 +665,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF } // Line - else if (rec["Type"] == 3) + else if (rec["type"] == 3) { // L rec["L"] = []; @@ -710,7 +715,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF } } // Ink - else if (rec["Type"] == 14) + else if (rec["type"] == 14) { // offsets like getStructure and viewer.navigate let n = reader.readInt(); @@ -724,7 +729,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF } } // Highlight, Underline, Squiggly, Strikeout - else if (rec["Type"] > 7 && rec["Type"] < 12) + else if (rec["type"] > 7 && rec["type"] < 12) { // QuadPoints let n = reader.readInt(); @@ -733,7 +738,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF rec["QuadPoints"].push(readDoubleFunc.call(reader)); } // Square, Circle - else if (rec["Type"] == 4 || rec["Type"] == 5) + else if (rec["type"] == 4 || rec["type"] == 5) { // Rect and RD differences if (flags & (1 << 15)) @@ -752,7 +757,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF } } // Polygon, PolyLine - else if (rec["Type"] == 6 || rec["Type"] == 7) + else if (rec["type"] == 6 || rec["type"] == 7) { let nVertices = reader.readInt(); rec["Vertices"] = []; @@ -780,8 +785,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF rec["IT"] = reader.readByte(); } // Popup - /* - else if (rec["Type"] == 15) + else if (rec["type"] == 15) { flags = reader.readInt(); rec["Open"] = (flags >> 0) & 1; @@ -789,9 +793,8 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF if (flags & (1 << 1)) rec["PopupParent"] = reader.readInt(); } - */ // FreeText - else if (rec["Type"] == 2) + else if (rec["type"] == 2) { // Background color - C->IC if (!isRead && rec["C"]) @@ -847,7 +850,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF } } // Caret - else if (rec["Type"] == 13) + else if (rec["type"] == 13) { // Rect and RD differenses if (flags & (1 << 15)) @@ -862,7 +865,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF rec["Sy"] = reader.readByte(); } // FileAttachment - else if (rec["Type"] == 16) + else if (rec["type"] == 16) { if (flags & (1 << 15)) rec["Icon"] = readStringFunc.call(reader); @@ -961,7 +964,7 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF rec["Desc"] = readStringFunc.call(reader); } // Stamp - else if (rec["Type"] == 12) + else if (rec["type"] == 12) { rec["Icon"] = readStringFunc.call(reader); rec["Rotate"] = readDouble2Func.call(reader); @@ -969,6 +972,52 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF for (let i = 0; i < 8; ++i) rec["InRect"].push(readDouble2Func.call(reader)); } + // Redact + else if (rec["type"] == 25) + { + // QuadPoints + if (flags & (1 << 15)) + { + let n = reader.readInt(); + rec["QuadPoints"] = []; + for (let i = 0; i < n; ++i) + rec["QuadPoints"].push(readDoubleFunc.call(reader)); + } + // IC + if (flags & (1 << 16)) + { + let n = reader.readInt(); + rec["IC"] = []; + for (let i = 0; i < n; ++i) + rec["IC"].push(readDouble2Func.call(reader)); + } + // OverlayText + if (flags & (1 << 17)) + rec["OverlayText"] = readStringFunc.call(reader); + // Repeat + rec["Repeat"] = (flags >> 18) & 1; + // Q - alignment + if (flags & (1 << 19)) + { + // 0 - left-justified, 1 - centered, 2 - right-justified + rec["alignment"] = reader.readByte(); + } + // Font from DA + if (flags & (1 << 20)) + { + rec["font"] = {}; + let n = reader.readInt(); + rec["font"]["color"] = []; + for (let i = 0; i < n; ++i) + rec["font"]["color"].push(readDouble2Func.call(reader)); + rec["font"]["size"] = readDoubleFunc.call(reader); + rec["font"]["name"] = readStringFunc.call(reader); + let fontActual = readStringFunc.call(reader); + if (fontActual != "") + rec["font"]["actual"] = fontActual; + rec["font"]["style"] = reader.readInt(); + } + } } function readWidgetType(reader, rec, readDoubleFunc, readDouble2Func, readStringFunc, isRead = false) { @@ -987,7 +1036,7 @@ function readWidgetType(reader, rec, readDoubleFunc, readDouble2Func, readString rec["font"]["color"].push(readDouble2Func.call(reader)); } // 0 - left-justified, 1 - centered, 2 - right-justified - if (!isRead || (rec["Type"] != 29 && rec["Type"] != 28 && rec["Type"] != 27)) + if (!isRead || (rec["type"] != 29 && rec["type"] != 28 && rec["type"] != 27)) rec["alignment"] = reader.readByte(); rec["flag"] = reader.readInt(); // 12.7.3.1 @@ -1131,9 +1180,15 @@ function readWidgetType(reader, rec, readDoubleFunc, readDouble2Func, readString if (isRead) { if (flags & (1 << 12)) - rec["AP"]["V"] = readStringFunc.call(reader); + { + let APV = readStringFunc.call(reader); + // rec["AP"]["V"] = APV; + } if (flags & (1 << 13)) - rec["AP"]["render"] = reader.readData(); // TODO use Render - Uint8Array + { + let APrender = reader.readData(); // TODO use Render - Uint8Array + // rec["AP"]["render"] = APrender; + } } // 12.7.4.3 if (rec["flag"] >= 0) @@ -1170,7 +1225,10 @@ function readWidgetType(reader, rec, readDoubleFunc, readDouble2Func, readString if (isRead) { if (flags & (1 << 12)) - rec["AP"]["V"] = readStringFunc.call(reader); + { + let APV = readStringFunc.call(reader); + // rec["AP"]["V"] = APV; + } } else { @@ -1199,7 +1257,10 @@ function readWidgetType(reader, rec, readDoubleFunc, readDouble2Func, readString rec["I"].push(reader.readInt()); } if (flags & (1 << 15)) - rec["AP"]["render"] = reader.readData(); // TODO use Render - Uint8Array + { + let APrender = reader.readData(); // TODO use Render - Uint8Array + // rec["AP"]["render"] = APrender; + } } // 12.7.4.4 if (rec["flag"] >= 0) @@ -1473,7 +1534,7 @@ CFile.prototype["getAnnotationsInfo"] = function(pageIndex) // 11 - Strikeout, 12 - Stamp, 13 - Caret, 14 - Ink, 15 - Popup, 16 - FileAttachment, // 17 - Sound, 18 - Movie, 19 - Widget, 20 - Screen, 21 - PrinterMark, // 22 - TrapNet, 23 - Watermark, 24 - 3D, 25 - Redact - rec["Type"] = reader.readByte(); + rec["type"] = reader.readByte(); // Annot readAnnot(reader, rec, reader.readDouble, reader.readDouble2, reader.readString); // Annot type @@ -1548,12 +1609,12 @@ CFile.prototype["readAnnotationsInfoFromBinary"] = function(AnnotInfo) // 11 - Strikeout, 12 - Stamp, 13 - Caret, 14 - Ink, 15 - Popup, 16 - FileAttachment, // 17 - Sound, 18 - Movie, 19 - Widget, 20 - Screen, 21 - PrinterMark, // 22 - TrapNet, 23 - Watermark, 24 - 3D, 25 - Redact - rec["Type"] = reader.readByte(); + rec["type"] = reader.readByte(); // Annot readAnnot(reader, rec, reader.readDouble3, reader.readDouble3, reader.readString2, true); // Annot type readAnnotType(reader, rec, reader.readDouble3, reader.readDouble3, reader.readString2, true); - if (rec["Type"] >= 26 && rec["Type"] <= 33) + if (rec["type"] >= 26 && rec["type"] <= 33) { // Widget type readWidgetType(reader, rec, reader.readDouble3, reader.readDouble3, reader.readString2, true); diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp index 7b001932d5..a62f7ee2ed 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp @@ -2043,6 +2043,83 @@ int main(int argc, char* argv[]) i += 4; std::cout << "Y4 " << (double)nPathLength / 10000.0 << ", "; } + else if (sType == "Redact") + { + if (nFlags & (1 << 15)) + { + std::cout << "QuadPoints"; + int nQuadPointsLength = READ_INT(pAnnots + i); + i += 4; + + for (int j = 0; j < nQuadPointsLength; ++j) + { + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << " " << (double)nPathLength / 100.0; + } + std::cout << ", "; + } + if (nFlags & (1 << 16)) + { + int nICLength = READ_INT(pAnnots + i); + i += 4; + std::cout << "IC "; + + for (int j = 0; j < nICLength; ++j) + { + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << (double)nPathLength / 10000.0 << " "; + } + std::cout << ", "; + } + if (nFlags & (1 << 17)) + { + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << "OverlayText " << std::string((char*)(pAnnots + i), nPathLength) << ", "; + i += nPathLength; + } + if (nFlags & (1 << 18)) + std::cout << "Repeat true, "; + else + std::cout << "Repeat false, "; + if (nFlags & (1 << 19)) + { + std::string arrQ[] = {"left-justified", "centered", "right-justified"}; + nPathLength = READ_BYTE(pAnnots + i); + i += 1; + std::cout << "Q " << arrQ[nPathLength] << ", "; + } + if (nFlags & (1 << 20)) + { + int nICLength = READ_INT(pAnnots + i); + i += 4; + std::cout << "DA color "; + + for (int j = 0; j < nICLength; ++j) + { + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << (double)nPathLength / 10000.0 << " "; + } + std::cout << ", size "; + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << (double)nPathLength / 100.0 << ", font "; + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << std::string((char*)(pAnnots + i), nPathLength) << " actual "; + i += nPathLength; + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << std::string((char*)(pAnnots + i), nPathLength) << ", style "; + i += nPathLength; + nPathLength = READ_INT(pAnnots + i); + i += 4; + std::cout << nPathLength << ", "; + } + } std::cout << std::endl << "]" << std::endl; } diff --git a/DesktopEditor/raster/Metafile/svg/CSvgFile.cpp b/DesktopEditor/raster/Metafile/svg/CSvgFile.cpp index f6df395d0f..49aa94753a 100644 --- a/DesktopEditor/raster/Metafile/svg/CSvgFile.cpp +++ b/DesktopEditor/raster/Metafile/svg/CSvgFile.cpp @@ -79,9 +79,9 @@ bool CSvgFile::GetBounds(double &dX, double &dY, double &dWidth, double &dHeight else dHeight = m_oContainer.GetViewBox().m_oHeight.ToDouble(NSCSS::Pixel); - if (0. == dWidth) + if (DBL_EPSILON > dWidth) dWidth = SVG_FILE_WIDTH; - if (0. == dHeight) + if (DBL_EPSILON > dHeight) dHeight = SVG_FILE_HEIGHT; return true; diff --git a/DocxRenderer/src/logic/elements/Shape.cpp b/DocxRenderer/src/logic/elements/Shape.cpp index 52278ad575..1a3c6fdfbf 100644 --- a/DocxRenderer/src/logic/elements/Shape.cpp +++ b/DocxRenderer/src/logic/elements/Shape.cpp @@ -1100,16 +1100,15 @@ namespace NSDocxRenderer // WriteRecord WriteXfrm oWriter.StartRecord(0); oWriter.WriteBYTE(kBin_g_nodeAttributeStart); - oWriter.WriteBYTE(0); oWriter.AddInt(static_cast(left * c_dMMToEMU)); - oWriter.WriteBYTE(1); oWriter.AddInt(static_cast(top * c_dMMToEMU)); - oWriter.WriteBYTE(2); oWriter.AddInt(static_cast(width * c_dMMToEMU)); - oWriter.WriteBYTE(3); oWriter.AddInt(static_cast(height * c_dMMToEMU)); + oWriter.WriteBYTE(0); oWriter.AddSInt(static_cast(left * c_dMMToEMU)); + oWriter.WriteBYTE(1); oWriter.AddSInt(static_cast(top * c_dMMToEMU)); + oWriter.WriteBYTE(2); oWriter.AddSInt(static_cast(width * c_dMMToEMU)); + oWriter.WriteBYTE(3); oWriter.AddSInt(static_cast(height * c_dMMToEMU)); if (fabs(m_dRotation) > c_dMIN_ROTATION) { - double degree = m_dRotation; - if (m_dRotation < 0) degree = 360.0 - m_dRotation; - oWriter.WriteBYTE(10); oWriter.AddInt(degree * c_dDegreeToAngle); + int degree = static_cast(m_dRotation * c_dDegreeToAngle); + oWriter.WriteBYTE(10); oWriter.AddSInt(degree); } oWriter.WriteBYTE(kBin_g_nodeAttributeEnd); oWriter.EndRecord(); diff --git a/MsBinaryFile/DocFile/VMLShapeMapping.cpp b/MsBinaryFile/DocFile/VMLShapeMapping.cpp index 55e7d3aff5..9f79914b0a 100644 --- a/MsBinaryFile/DocFile/VMLShapeMapping.cpp +++ b/MsBinaryFile/DocFile/VMLShapeMapping.cpp @@ -1052,7 +1052,8 @@ namespace DocFileFormat { if (nAdjValues) { - m_pXmlWriter->WriteAttribute(L"arcsize", m_nAdjValues[0]); + double dArcsize = m_nAdjValues[0] / 21600.; + m_pXmlWriter->WriteAttribute(L"arcsize", dArcsize); } } else if (DocFileFormat::msosptPictureFrame == nCode) diff --git a/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp b/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp index 5bf8ce0801..896bf315aa 100644 --- a/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp +++ b/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.cpp @@ -2350,7 +2350,10 @@ void CDrawingConverter::ConvertShape(PPTX::Logic::SpTreeElem *elem, XmlUtils::CX } else { - pPPTShape->SetAdjustment(0, value.GetValue() / 10.); + if (value.GetValue() < 1) + pPPTShape->SetAdjustment(0, value.GetValue() * 10000); + else + pPPTShape->SetAdjustment(0, value.GetValue() / 10.); } } pPPTShape->ReCalculate(); @@ -2560,7 +2563,10 @@ void CDrawingConverter::ConvertShape(PPTX::Logic::SpTreeElem *elem, XmlUtils::CX if (pPPTShape != NULL) { if (!bSetShape) + { oShapeElem.m_pShape->setBaseShape(CBaseShapePtr(pPPTShape)); + bSetShape = true; + } if (bIsNeedCoordSizes) { LoadCoordSize(oNodeShape, oShapeElem.m_pShape); @@ -3022,13 +3028,13 @@ void CDrawingConverter::ConvertShape(PPTX::Logic::SpTreeElem *elem, XmlUtils::CX } CheckBrushShape(elem, oNodeShape, pPPTShape); - CheckBorderShape(elem, oNodeShape, pPPTShape); + CheckEffectShape(elem, oNodeShape, pPPTShape); ////test - NSBinPptxRW::CXmlWriter oXml; - elem->toXmlWriter(&oXml); - std::wstring test = oXml.GetXmlString(); + //NSBinPptxRW::CXmlWriter oXml; + //elem->toXmlWriter(&oXml); + //std::wstring test = oXml.GetXmlString(); } @@ -4845,6 +4851,89 @@ void CDrawingConverter::SendMainProps(const std::wstring& strMainProps, std::wst **pMainProps = strMainProps; } } +void CDrawingConverter::CheckEffectShape(PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape) +{ + if (!oElem) return; + + PPTX::Logic::Shape* pShape = dynamic_cast (oElem->GetElem().operator ->()); + PPTX::Logic::Pic* pPicture = dynamic_cast (oElem->GetElem().operator ->()); + + PPTX::Logic::SpPr* pSpPr = NULL; + + if (pShape) pSpPr = &pShape->spPr; + if (pPicture) pSpPr = &pPicture->spPr; + + if (!pSpPr) return; + + XmlUtils::CXmlNode oNodeShadow = oNode.ReadNode(L"v:shadow"); + SimpleTypes::CTrueFalse bShadowEnabled = SimpleTypes::booleanTrue; + + if (oNodeShadow.IsValid()) + { + XmlMacroReadAttributeBase(oNodeShadow, L"on", bShadowEnabled); + } + if (bShadowEnabled.GetBool()) + { + nullable oColor; + nullable oColor2; + nullable_string oId; + nullable oMatrix; + SimpleTypes::CTrueFalse oObscured; + SimpleTypes::Vml::CVml_Vector2D_Units_Or_Percentage oOffset; + SimpleTypes::Vml::CVml_Vector2D_Units_Or_Percentage oOffset2; + nullable oOpacity; + nullable oOrigin; + SimpleTypes::CShadowType oType; + + XmlMacroReadAttributeBase(oNodeShadow, L"id", oId); + XmlMacroReadAttributeBase(oNodeShadow, L"type", oType); + XmlMacroReadAttributeBase(oNodeShadow, L"color", oColor); + XmlMacroReadAttributeBase(oNodeShadow, L"opacity", oOpacity); + XmlMacroReadAttributeBase(oNodeShadow, L"offset", oOffset); + XmlMacroReadAttributeBase(oNodeShadow, L"origin", oOrigin); + XmlMacroReadAttributeBase(oNodeShadow, L"obscured", oObscured); + XmlMacroReadAttributeBase(oNodeShadow, L"color2", oColor2); + XmlMacroReadAttributeBase(oNodeShadow, L"offset2", oOffset2); + XmlMacroReadAttributeBase(oNodeShadow, L"matrix", oMatrix); + + if (false == pSpPr->EffectList.is_init()) + pSpPr->EffectList.List = new PPTX::Logic::EffectLst(); + + PPTX::Logic::EffectLst* pEffectLst = dynamic_cast(pSpPr->EffectList.List.GetPointer()); + + pEffectLst->outerShdw.Init(); + + pEffectLst->outerShdw->Color.Color = new PPTX::Logic::SrgbClr(); + + if (oColor.IsInit()) + pEffectLst->outerShdw->Color.Color->SetRGB(oColor->Get_R(), oColor->Get_G(), oColor->Get_B()); + else + pEffectLst->outerShdw->Color.Color->SetRGB(0x80, 0x80, 0x80); + + if (oOpacity.is_init()) + { + BYTE lAlpha = oOpacity->GetValue() * 255; + + PPTX::Logic::ColorModifier oMod; + oMod.name = L"alpha"; + int nA = (int)(lAlpha * 100000.0 / 255.0); + oMod.val = nA; + pEffectLst->outerShdw->Color.Color->Modifiers.push_back(oMod); + } + double offsetX = oOffset.IsXinPoints() ? oOffset.GetX() : 0; + double offsetY = oOffset.IsYinPoints() ? oOffset.GetY() : 0; + + double dist = sqrt(offsetX * offsetX + offsetY * offsetY); + double dir = (offsetX != 0) ? atan(offsetY / offsetX) * 180. / 3.1415926 : 0; + if (offsetX < 0) dir += 180; + if (dir < 0) dir += 360; + + pEffectLst->outerShdw->dist = dist * (635 * 20); + pEffectLst->outerShdw->dir = (int)(dir * 60000); + pEffectLst->outerShdw->rotWithShape = false; + } + +} void CDrawingConverter::CheckBorderShape(PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape) { if (!oElem) return; diff --git a/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.h b/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.h index b7e8b9f468..3fc3dd46f7 100644 --- a/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.h +++ b/OOXML/PPTXFormat/DrawingConverter/ASCOfficeDrawingConverter.h @@ -298,6 +298,7 @@ namespace NSBinPptxRW void CheckBrushShape (PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape); void CheckPenShape (PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape); void CheckBorderShape (PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape); + void CheckEffectShape (PPTX::Logic::SpTreeElem* oElem, XmlUtils::CXmlNode& oNode, CPPTShape* pPPTShape); void ConvertColor (PPTX::Logic::UniColor& uniColor, nullable_string& sColor, nullable_string& sOpacity); void LoadCoordSize (XmlUtils::CXmlNode& oNode, ::CShapePtr pShape); diff --git a/OdfFile/Reader/Converter/xlsxconversioncontext.cpp b/OdfFile/Reader/Converter/xlsxconversioncontext.cpp index 56d45d6488..5153d35096 100644 --- a/OdfFile/Reader/Converter/xlsxconversioncontext.cpp +++ b/OdfFile/Reader/Converter/xlsxconversioncontext.cpp @@ -466,6 +466,7 @@ void xlsx_conversion_context::serialize_bookViews(std::wostream & strm) if (false == sheets_[i]->external_ref().empty() && sheets_[i]->name() == *sActiveTable) { CP_XML_ATTR(L"activeTab", i); + break; } } } diff --git a/PdfFile/PdfFile.cpp b/PdfFile/PdfFile.cpp index d8993c2d2e..abd3bfbc5d 100644 --- a/PdfFile/PdfFile.cpp +++ b/PdfFile/PdfFile.cpp @@ -452,8 +452,10 @@ BYTE* CPdfFile::SplitPages(const int* arrPageIndex, unsigned int unLength, BYTE* { if (pChanges && nLength > 3) { + m_pInternal->pWriter->SetSplit(true); CConvertFromBinParams* pParams = new CConvertFromBinParams(); AddToPdfFromBinary(pChanges + 4, nLength - 4, pParams); + m_pInternal->pWriter->SetSplit(false); } m_pInternal->pEditor->AfterSplitPages(); diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index 876378e611..66e9aaad66 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -1258,25 +1258,11 @@ BYTE* CPdfReader::GetWidgets() const std::vector& arrAnnots = pAnnots->GetAnnots(); for (int i = 0; i < arrAnnots.size(); ++i) { - const std::string& sFullName = arrAnnots[i]->GetFullName(); - std::map::iterator it = mForms.find(sFullName); - if (it == mForms.end()) - mForms[sFullName] = arrAnnots[i]->GetType(); - else if (mForms[sFullName] != arrAnnots[i]->GetType()) - { - if (iPDF == 0) - { - // error - // throw "Same full names for forms of different types within the same file"; - } - else - { - int nPrefix = 0; - std::string sPrefix = m_vPDFContext[iPDF]->m_sPrefixForm + "_" + std::to_string(nPrefix); - while (!pAnnots->ChangeFullNameAnnot(i, sPrefix)) - sPrefix = m_vPDFContext[iPDF]->m_sPrefixForm + "_" + std::to_string(++nPrefix); - } - } + if (m_vPDFContext[iPDF]->m_sPrefixForm.empty()) + continue; + + std::string sPrefix = "_" + m_vPDFContext[iPDF]->m_sPrefixForm; + pAnnots->ChangeFullNameAnnot(i, sPrefix); } pAnnots->ToWASM(oRes); @@ -1985,6 +1971,12 @@ int GetPageAnnots(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, PdfReader { pAnnot = new PdfReader::CAnnotInk(pdfDoc, &oAnnotRef, nPageIndex, nStartRefID); } + else if (sType == "Redact") + { + PdfReader::CAnnotRedact* pRedact = new PdfReader::CAnnotRedact(pdfDoc, &oAnnotRef, nPageIndex, nStartRefID); + pRedact->SetFont(pdfDoc, pFontManager, pFontList, &oAnnotRef); + pAnnot = pRedact; + } // else if (sType == "FileAttachment") // { // pAnnot = new PdfReader::CAnnotFileAttachment(pdfDoc, &oAnnotRef, nPageIndex, nStartRefID); diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index cb1746949b..6b1dd8e5a9 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -101,6 +101,28 @@ static const long c_BrushTypeRadialGradient = 8002; Aggplus::CImage* ConvertMetafile(NSFonts::IApplicationFonts* pAppFonts, const std::wstring& wsPath, const std::wstring& wsTempDirectory, double dWidth = -1, double dHeight = -1) { + if (wsPath.find(L"data:") == 0) + { + std::wstring::size_type posZ = wsPath.find(L','); + int nBase64Size = (int)(wsPath.length() - posZ - 1); + const wchar_t* pBase64Data = wsPath.c_str() + posZ + 1; + + char* pBase64Buffer = new char[nBase64Size]; + for (int i = 0; i < nBase64Size; ++i) + pBase64Buffer[i] = (char)pBase64Data[i]; + + int nBufferLen = NSBase64::Base64DecodeGetRequiredLength(nBase64Size); + BYTE* pImageBuffer = new BYTE[nBufferLen + 64]; + + Aggplus::CImage* pImage = new Aggplus::CImage(); + if (NSBase64::Base64Decode(pBase64Buffer, nBase64Size, pImageBuffer, &nBufferLen)) + pImage->Decode(pImageBuffer, nBufferLen); + + RELEASEARRAYOBJECTS(pImageBuffer); + RELEASEARRAYOBJECTS(pBase64Buffer); + return pImage; + } + CImageFileFormatChecker oImageFormat(wsPath); if (_CXIMAGE_FORMAT_WMF == oImageFormat.eFileType || _CXIMAGE_FORMAT_EMF == oImageFormat.eFileType || @@ -161,6 +183,7 @@ CPdfWriter::CPdfWriter(NSFonts::IApplicationFonts* pAppFonts, bool isPDFA, IRend m_pDocument->SetCompressionMode(COMP_ALL); m_bValid = true; + m_bSplit = false; m_dPageHeight = 297; m_dPageWidth = 210; m_pPage = NULL; @@ -2067,7 +2090,6 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF pLineAnnot->SetCO(dCO1, dCO2); } - //pLineAnnot->SetAP(); if (bRender) { pMarkupAnnot->RemoveAP(); @@ -2187,8 +2209,6 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF } if (nFlags & (1 << 16)) pCaretAnnot->SetSy(pPr->GetSy()); - - // pMarkupAnnot->RemoveAP(); } else if (oInfo.IsStamp()) { @@ -2354,19 +2374,19 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF if (nFlags & (1 << 10)) { pButtonWidget->SetCA(pPr->GetCA()); - if (nTP == 0) + if (nTP == 0 && !m_bSplit) DrawButtonWidget(pAppFonts, pButtonWidget, 0, NULL); } if (nFlags & (1 << 11)) { pButtonWidget->SetRC(pPr->GetRC()); - if (nTP == 0) + if (nTP == 0 && !m_bSplit) DrawButtonWidget(pAppFonts, pButtonWidget, 1, NULL); } if (nFlags & (1 << 12)) { pButtonWidget->SetAC(pPr->GetAC()); - if (nTP == 0) + if (nTP == 0 && !m_bSplit) DrawButtonWidget(pAppFonts, pButtonWidget, 2, NULL); } } @@ -2475,7 +2495,7 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF if (pFont) pWidgetAnnot->SetDA(pFont, oInfo.GetWidgetAnnotPr()->GetFontSize(), dFontSize, oInfo.GetWidgetAnnotPr()->GetTC()); } - else if ((bValue && pTextWidget->Get("T")) || bAPValue) + else if (!m_bSplit && ((bValue && pTextWidget->Get("T")) || bAPValue)) { put_FontName(wsFontName); put_FontStyle(nStyle); @@ -2542,7 +2562,7 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF if (pFont) pWidgetAnnot->SetDA(pFont, oInfo.GetWidgetAnnotPr()->GetFontSize(), dFontSize, oInfo.GetWidgetAnnotPr()->GetTC()); } - else if (!arrValue.empty()) + else if (!m_bSplit && !arrValue.empty()) { put_FontName(wsFontName); put_FontStyle(nStyle); @@ -2671,7 +2691,7 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi int nFlags = pParent->nFlags; // Adobe не может смешивать юникод и utf имена полей if (nFlags & (1 << 0)) - pParentObj->Add("T", new PdfWriter::CStringObject((U_TO_UTF8(pParent->sName)).c_str())); + pParentObj->Add("T", new PdfWriter::CStringObject((U_TO_UTF8(pParent->sName)).c_str(), true)); std::string sFT = m_pDocument->SetParentKids(pParent->nID); PdfWriter::CArrayObject* pKids = dynamic_cast(pParentObj->Get("Kids")); @@ -2724,7 +2744,7 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi if (nType == PdfWriter::WidgetCombobox || nType == PdfWriter::WidgetListbox) { PdfWriter::CChoiceWidget* pKid = dynamic_cast(pObj); - if (!pKid->HaveAPV()) + if (!pKid->HaveAPV() && !m_bSplit) DrawChoiceWidget(pAppFonts, pKid, pParent->arrV); } } @@ -2856,13 +2876,13 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi if (nType == PdfWriter::WidgetCombobox || nType == PdfWriter::WidgetListbox) { PdfWriter::CChoiceWidget* pKid = dynamic_cast(pObj); - if (!pKid->HaveAPV()) + if (!pKid->HaveAPV() && !m_bSplit) DrawChoiceWidget(pAppFonts, pKid, {pParent->sV}); } else if (nType == PdfWriter::WidgetText) { PdfWriter::CTextWidget* pKid = dynamic_cast(pObj); - if (!pKid->HaveAPV()) + if (!pKid->HaveAPV() && !m_bSplit) DrawTextWidget(pAppFonts, pKid, pParent->sV); } } @@ -2913,7 +2933,7 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi std::wstring sTempImagePath = GetDownloadFile(wsPath, wsTempDirectory); std::wstring wsImagePath = sTempImagePath.empty() ? wsPath : sTempImagePath; - Aggplus::CImage* pCImage = ConvertMetafile(pAppFonts, wsImagePath, GetTempFile(wsTempDirectory)); + Aggplus::CImage* pCImage = ConvertMetafile(pAppFonts, wsImagePath, m_bSplit ? L"" : GetTempFile(wsTempDirectory)); PdfWriter::CImageDict* pImage = LoadImage(pCImage, 255); RELEASEOBJECT(pCImage); @@ -2959,7 +2979,7 @@ HRESULT CPdfWriter::EditWidgetParents(NSFonts::IApplicationFonts* pAppFonts, CWi } } - if (!pPBWidget->Get("AP")) + if (!pPBWidget->Get("AP") && !m_bSplit) DrawButtonWidget(pAppFonts, pPBWidget, 0, NULL); } @@ -3207,6 +3227,8 @@ bool CPdfWriter::DrawText(unsigned char* pCodes, const unsigned int& unLen, cons } bool CPdfWriter::DrawTextToRenderer(const unsigned int* unGid, const unsigned int& unLen, const double& dX, const double& dY, const std::wstring& wsUnicodeText) { + if (m_bSplit) + return false; // TODO pdf позволяет создание своего шрифта, но не следует это использовать для воссоздания шрифта запрещенного для редактирования или встраивания Aggplus::CGraphicsPathSimpleConverter simplifier; simplifier.SetRenderer(m_pRenderer); @@ -3301,6 +3323,8 @@ bool CPdfWriter::GetBaseFont14(const std::wstring& wsFontName, int nBase14) if (!FindFontPath(wsFontName, m_oFont.IsBold(), m_oFont.IsItalic(), wsFontPath, lFaceIndex)) return false; } + if (m_bSplit) + return false; if (!m_pFontManager->LoadFontFromFile(wsFontPath, lFaceIndex, m_oFont.GetSize(), 72, 72)) return false; PdfWriter::EStandard14Fonts nType = (PdfWriter::EStandard14Fonts)nBase14; @@ -3378,6 +3402,9 @@ bool CPdfWriter::GetFontPath(const std::wstring &wsFontName, const bool &bBold, if (!bFind) { + if (m_bSplit) + return false; + NSFonts::CFontSelectFormat oFontSelect; oFontSelect.wsName = new std::wstring(wsFontName); oFontSelect.bItalic = new INT(bItalic ? 1 : 0); @@ -3412,6 +3439,9 @@ PdfWriter::CFontCidTrueType* CPdfWriter::GetFont(const std::wstring& wsFontPath, if (pFont) return pFont; + if (m_bSplit) + return pFont; + // TODO: Пока мы здесь предполагаем, что шрифты только либо TrueType, либо OpenType if (!m_pFontManager->LoadFontFromFile(wsFontPath, lFaceIndex, 10, 72, 72)) { @@ -4348,7 +4378,7 @@ void CPdfWriter::DrawButtonWidget(NSFonts::IApplicationFonts* pAppFonts, PdfWrit if (nTP != 1 && !pForm) nTP = 0; - if (nTP != 1) + if (nTP != 1 && !m_bSplit) { PdfWriter::CFontCidTrueType* pFont = pButtonWidget->GetFont(); if (!pFont) @@ -4420,7 +4450,7 @@ void CPdfWriter::DrawButtonWidget(NSFonts::IApplicationFonts* pAppFonts, PdfWrit } } - pButtonWidget->SetAP(pForm, nAP, pCodes, unLen, dShiftX, dShiftY, dLineW, dLineH, ppFonts); + pButtonWidget->SetAP(pForm, nAP, pCodes, unLen, dShiftX, dShiftY, dLineW, dLineH, ppFonts, m_bSplit); RELEASEARRAYOBJECTS(pUnicodes); RELEASEARRAYOBJECTS(pCodes); diff --git a/PdfFile/PdfWriter.h b/PdfFile/PdfWriter.h index 9c982d4120..c27a7ed9ae 100644 --- a/PdfFile/PdfWriter.h +++ b/PdfFile/PdfWriter.h @@ -222,6 +222,7 @@ public: void AddFont(const std::wstring& wsFontName, const bool& bBold, const bool& bItalic, const std::wstring& wsFontPath, const LONG& lFaceIndex); void SetHeadings(CHeadings* pCommand); void SetNeedAddHelvetica(bool bNeedAddHelvetica); + void SetSplit(bool bSplit) { m_bSplit = bSplit; } private: PdfWriter::CImageDict* LoadImage(Aggplus::CImage* pImage, BYTE nAlpha); @@ -284,6 +285,7 @@ private: CMultiLineTextManager m_oLinesManager; bool m_bValid; + bool m_bSplit; }; #endif // _PDF_WRITER_H diff --git a/PdfFile/SrcReader/PdfAnnot.cpp b/PdfFile/SrcReader/PdfAnnot.cpp index 29f6fee0e9..454a63d1db 100644 --- a/PdfFile/SrcReader/PdfAnnot.cpp +++ b/PdfFile/SrcReader/PdfAnnot.cpp @@ -1360,6 +1360,7 @@ CAnnotWidget::CAnnotWidget(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefI oObj.fetch(xref, &oField); oObj.free(); + m_bChangeFullName = false; m_dFontSize = 0.0; m_unFontStyle = 0; @@ -1603,11 +1604,11 @@ void CAnnotWidget::SetButtonFont(PDFDoc* pdfDoc, AcroFormField* pField, NSFonts: } bool CAnnotWidget::ChangeFullName(const std::string& sPrefixForm) { + m_bChangeFullName = true; if (m_unFlags & (1 << 18)) { m_sT += sPrefixForm; m_sFullName += sPrefixForm; - // ClearActions(); return true; } return false; @@ -2434,6 +2435,149 @@ CAnnotStamp::CAnnotStamp(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int oAnnot.free(); } +//------------------------------------------------------------------------ +// Redact +//------------------------------------------------------------------------ + +CAnnotRedact::CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID) +{ + Object oAnnot, oObj, oObj2; + XRef* pXref = pdfDoc->getXRef(); + oAnnotRef->fetch(pXref, &oAnnot); + + // 15 - Координаты - QuadPoints + if (oAnnot.dictLookup("QuadPoints", &oObj)->isArray()) + { + m_unFlags |= (1 << 15); + for (int i = 0; i < oObj.arrayGetLength(); ++i) + { + if (oObj.arrayGet(i, &oObj2)->isNum()) + m_arrQuadPoints.push_back(i % 2 == 0 ? oObj2.getNum() - m_dX : m_dHeight - oObj2.getNum()); + oObj2.free(); + } + } + oObj.free(); + + // 16 - Цвет заполнения - IC + if (oAnnot.dictLookup("IC", &oObj)->isArray()) + { + m_unFlags |= (1 << 16); + for (int j = 0; j < oObj.arrayGetLength(); ++j) + { + m_arrIC.push_back(oObj.arrayGet(j, &oObj2)->isNum() ? oObj2.getNum() : 0.0); + oObj2.free(); + } + } + oObj.free(); + + // RO во внешних видах + + // 17 - Текст наложения - OverlayText + m_sOverlayText = DictLookupString(&oAnnot, "OverlayText", 17); + + // 18 - Повторять текст - Repeat + if (oAnnot.dictLookup("Repeat", &oObj)->isBool() && oObj.getBool()) + m_unFlags |= (1 << 18); + + // 19 - Выравнивание текста - Q + m_nQ = 0; + if (oAnnot.dictLookup("Q", &oObj)->isInt()) + { + m_unFlags |= (1 << 19); + m_nQ = oObj.getInt(); + } + oObj.free(); + + oAnnot.free(); +} +void CAnnotRedact::SetFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef) +{ + Object oAnnot, oObj; + XRef* pXref = pdfDoc->getXRef(); + oAnnotRef->fetch(pXref, &oAnnot); + + // 20 - Шрифт, размер, цвет текста замены - DA + if (oAnnot.dictLookup("DA", &oObj)->isString()) + { + m_unFlags |= (1 << 20); + // parse the default appearance string + GList* daToks = tokenize(oObj.getString()); + for (int i = daToks->getLength() - 1; i > 0; --i) + { + // handle the g operator + if (!((GString *)daToks->get(i))->cmp("G") && m_arrCFromDA.empty()) + { + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString())); + } + // handle the rg operator + else if (i >= 3 && !((GString *)daToks->get(i))->cmp("RG") && m_arrCFromDA.empty()) + { + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 3))->getCString())); + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 2))->getCString())); + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString())); + } + // handle the k operator + else if (i >= 4 && !((GString *)daToks->get(i))->cmp("K") && m_arrCFromDA.empty()) + { + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 4))->getCString())); + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 3))->getCString())); + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 2))->getCString())); + m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString())); + } + else if (i >= 2 && !((GString *)daToks->get(i))->cmp("Tf")) + { + m_dFontSize = atof(((GString *)daToks->get(i - 1))->getCString()); + m_unFontStyle = 0; + } + } + deleteGList(daToks, GString); + } + oObj.free(); + + Object oAP, oN; + if (!oAnnot.dictLookup("RO", &oN)->isStream()) + { + oN.free(); + if (!oAnnot.dictLookup("AP", &oAP)->isDict() || !oAP.dictLookup("D", &oN)->isStream()) + { + oAP.free(); oN.free(); oAnnot.free(); + return; + } + } + oAP.free(); + + Object oFonts; + if (!CAnnotFonts::FindFonts(&oN, 0, &oFonts)) + { + oN.free(); oFonts.free(); oAnnot.free(); + return; + } + oN.free(); + + for (int i = 0, nFonts = oFonts.dictGetLength(); i < nFonts; ++i) + { + Object oFontRef; + if (!oFonts.dictGetValNF(i, &oFontRef)->isRef()) + { + oFontRef.free(); + continue; + } + + std::string sFontName, sActualFontName; + bool bBold = false, bItalic = false; + std::wstring sFontPath = CAnnotFonts::GetFontData(pdfDoc, pFontManager, pFontList, &oFontRef, m_sFontName, m_sActualFontName, bBold, bItalic); + oFontRef.free(); + + m_unFontStyle = 0; + if (bBold) + m_unFontStyle |= (1 << 0); + if (bItalic) + m_unFontStyle |= (1 << 1); + } + + oFonts.free(); oAnnot.free(); +} + //------------------------------------------------------------------------ // Annots //------------------------------------------------------------------------ @@ -2767,7 +2911,7 @@ bool CAnnots::ChangeFullNameAnnot(int nAnnot, const std::string& sPrefixForm) return false; CAnnotWidget* pWidget = m_arrAnnots[nAnnot]; - if (pWidget->ChangeFullName(sPrefixForm)) + if (pWidget->m_bChangeFullName) return true; unsigned int unRefNumParent = pWidget->GetRefNumParent(); if (unRefNumParent) @@ -2775,12 +2919,16 @@ bool CAnnots::ChangeFullNameAnnot(int nAnnot, const std::string& sPrefixForm) std::vector::iterator it = std::find_if(m_arrParents.begin(), m_arrParents.end(), [unRefNumParent](CAnnotParent* pP) { return pP->unRefNum == unRefNumParent; }); if (it != m_arrParents.end() && ChangeFullNameParent(std::distance(m_arrParents.begin(), it), sPrefixForm)) { - pWidget->AddFullName(sPrefixForm); - // pWidget->ClearActions(); + const std::string& sFullNameChild = pWidget->GetFullName(); + if (sFullNameChild.empty()) + pWidget->SetFullName((*it)->sFullName); + else + pWidget->SetFullName((*it)->sFullName + "." + sFullNameChild); + pWidget->m_bChangeFullName = true; return true; } } - return false; + return pWidget->ChangeFullName(sPrefixForm); } bool CAnnots::ChangeFullNameParent(int nParent, const std::string& sPrefixForm) { @@ -2788,24 +2936,30 @@ bool CAnnots::ChangeFullNameParent(int nParent, const std::string& sPrefixForm) return false; CAnnotParent* pParent = m_arrParents[nParent]; - if (pParent->unFlags & (1 << 0)) - { - pParent->sT += sPrefixForm; - pParent->sFullName += sPrefixForm; - // pParent->ClearActions(); + if (pParent->bChangeFullName) return true; - } - else if (pParent->unFlags & (1 << 4)) + + if (pParent->unFlags & (1 << 4)) { unsigned int unRefNumParent = pParent->unRefNumParent; std::vector::iterator it = std::find_if(m_arrParents.begin(), m_arrParents.end(), [unRefNumParent](CAnnotParent* pP) { return pP->unRefNum == unRefNumParent; }); if (it != m_arrParents.end() && ChangeFullNameParent(std::distance(m_arrParents.begin(), it), sPrefixForm)) { - pParent->sFullName += sPrefixForm; - // pParent->ClearActions(); + if (pParent->sT.empty()) + pParent->sFullName = (*it)->sFullName; + else + pParent->sFullName = (*it)->sFullName + "." + sPrefixForm; + pParent->bChangeFullName = true; return true; } } + else if (pParent->unFlags & (1 << 0)) + { + pParent->sT += sPrefixForm; + pParent->sFullName += sPrefixForm; + pParent->bChangeFullName = true; + return true; + } return false; } void CAnnots::CAnnotParent::ClearActions() @@ -4346,4 +4500,37 @@ void CAnnotStamp::ToWASM(NSWasm::CData& oRes) oRes.WriteDouble(m_dX4); oRes.WriteDouble(m_dY4); } +void CAnnotRedact::ToWASM(NSWasm::CData& oRes) +{ + oRes.WriteBYTE(25); // Redact + + CAnnotMarkup::ToWASM(oRes); + + if (m_unFlags & (1 << 15)) + { + oRes.AddInt((unsigned int)m_arrQuadPoints.size()); + for (int i = 0; i < m_arrQuadPoints.size(); ++i) + oRes.AddDouble(m_arrQuadPoints[i]); + } + if (m_unFlags & (1 << 16)) + { + oRes.AddInt((unsigned int)m_arrIC.size()); + for (int i = 0; i < m_arrIC.size(); ++i) + oRes.WriteDouble(m_arrIC[i]); + } + if (m_unFlags & (1 << 17)) + oRes.WriteString(m_sOverlayText); + if (m_unFlags & (1 << 19)) + oRes.WriteBYTE(m_nQ); + if (m_unFlags & (1 << 20)) + { + oRes.AddInt((unsigned int)m_arrCFromDA.size()); + for (int i = 0; i < m_arrCFromDA.size(); ++i) + oRes.WriteDouble(m_arrCFromDA[i]); + oRes.AddDouble(m_dFontSize); + oRes.WriteString(m_sFontName); + oRes.WriteString(m_sActualFontName); + oRes.AddInt(m_unFontStyle); + } +} } diff --git a/PdfFile/SrcReader/PdfAnnot.h b/PdfFile/SrcReader/PdfAnnot.h index a3b473757a..e5e284e117 100644 --- a/PdfFile/SrcReader/PdfAnnot.h +++ b/PdfFile/SrcReader/PdfAnnot.h @@ -222,12 +222,13 @@ public: unsigned int GetRefNumParent() { return m_unRefNumParent; } const std::string& GetFullName() { return m_sFullName; } void SetFullName(const std::string& sFullName) { m_sFullName = sFullName; } - void AddFullName(const std::string& sPrefixForm) { m_sFullName += sPrefixForm; } bool ChangeFullName(const std::string& sPrefixForm); void ClearActions(); virtual std::string GetType() = 0; virtual void ToWASM(NSWasm::CData& oRes) override; + bool m_bChangeFullName; + protected: CAnnotWidget(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefID); @@ -590,12 +591,38 @@ public: CAnnotStamp(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID); void ToWASM(NSWasm::CData& oRes) override; + private: std::string m_sName; // Иконка double m_dRotate; double m_dX1, m_dY1, m_dX2, m_dY2, m_dX3, m_dY3, m_dX4, m_dY4; }; +//------------------------------------------------------------------------ +// PdfReader::CAnnotRedact +//------------------------------------------------------------------------ + +class CAnnotRedact final : public CAnnotMarkup +{ +public: + CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID); + + void SetFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef); + + void ToWASM(NSWasm::CData& oRes) override; + +private: + BYTE m_nQ; // Выравнивание текста + unsigned int m_unFontStyle; // Стиль шрифта - из DA + double m_dFontSize; // Размер шрифта - из DA + std::string m_sFontName; // Имя шрифта - из DA + std::string m_sActualFontName; // Имя замененного шрифта + std::string m_sOverlayText; // Текст наложения + std::vector m_arrQuadPoints; // Координаты + std::vector m_arrIC; // Цвет заполнения + std::vector m_arrCFromDA; // Цвет текста +}; + //------------------------------------------------------------------------ // PdfReader::CAnnots //------------------------------------------------------------------------ @@ -619,6 +646,7 @@ private: unFlags = 0; unRefNum = 0; unRefNumParent = 0; + bChangeFullName = false; } ~CAnnotParent() { @@ -628,6 +656,7 @@ private: void ToWASM(NSWasm::CData& oRes); + bool bChangeFullName; unsigned int unFlags; unsigned int unRefNum; // Номер ссылки на объект unsigned int unMaxLen; // Ограничение на максимальную длину text field @@ -664,7 +693,6 @@ public: static bool GetFontFromAP(PDFDoc* pdfDoc, AcroFormField* pField, Object* oFontRef, std::string& sFontKey); static std::map GetAnnotFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef); static std::map GetFreeTextFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, Object* oAnnotRef, std::vector& arrRC); -private: static bool FindFonts(Object* oStream, int nDepth, Object* oResFonts); }; diff --git a/PdfFile/SrcWriter/Annotation.cpp b/PdfFile/SrcWriter/Annotation.cpp index 03baa7468a..b2e22ce9d5 100644 --- a/PdfFile/SrcWriter/Annotation.cpp +++ b/PdfFile/SrcWriter/Annotation.cpp @@ -823,6 +823,9 @@ namespace PdfWriter } void CFreeTextAnnotation::SetDA(CFontDict* pFont, const double& dFontSize, const std::vector& arrC) { + if (!pFont) + return; + CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources(); const char* sFontName = pFieldsResources->GetFontName(pFont); @@ -1229,6 +1232,9 @@ namespace PdfWriter } void CWidgetAnnotation::SetDA(CFontDict* pFont, const double& dFontSize, const double& dFontSizeAP, const std::vector& arrTC) { + if (!pFont) + return; + CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources(); const char* sFontName = pFieldsResources->GetFontName(pFont); @@ -1711,7 +1717,7 @@ namespace PdfWriter m_pMK->Add("AC", new CStringObject(sValue.c_str(), true)); m_wsAC = wsAC; } - void CPushButtonWidget::SetAP(CXObject* pForm, BYTE nAP, unsigned short* pCodes, unsigned int unCount, double dX, double dY, double dLineW, double dLineH, CFontCidTrueType** ppFonts) + void CPushButtonWidget::SetAP(CXObject* pForm, BYTE nAP, unsigned short* pCodes, unsigned int unCount, double dX, double dY, double dLineW, double dLineH, CFontCidTrueType** ppFonts, bool bNoAP) { if (!pForm && !pCodes) { @@ -1763,6 +1769,22 @@ namespace PdfWriter } } + if (bNoAP) + { + if (pForm) + { + CheckMK(); + std::string sAP = nAP == 0 ? "I" : (nAP == 1 ? "RI" : "IX"); + m_pMK->Add(sAP, pForm); + } + else if (m_pMK) + { + std::string sAP = nAP == 0 ? "I" : (nAP == 1 ? "RI" : "IX"); + m_pMK->Remove(sAP); + } + return; + } + CAnnotAppearanceObject* pAppearance = NULL; m_pResources = new CResourcesDict(NULL, true, false); if (nAP == 0) diff --git a/PdfFile/SrcWriter/Annotation.h b/PdfFile/SrcWriter/Annotation.h index d9c00afc15..6fa8f0f8cb 100644 --- a/PdfFile/SrcWriter/Annotation.h +++ b/PdfFile/SrcWriter/Annotation.h @@ -521,7 +521,7 @@ namespace PdfWriter void SetRC(const std::wstring& wsRC); void SetAC(const std::wstring& wsAC); - void SetAP(CXObject* pForm, BYTE nAP, unsigned short* pCodes, unsigned int unCount, double dX, double dY, double dLineW, double dLineH, CFontCidTrueType** ppFonts); + void SetAP(CXObject* pForm, BYTE nAP, unsigned short* pCodes, unsigned int unCount, double dX, double dY, double dLineW, double dLineH, CFontCidTrueType** ppFonts, bool bNoAP = false); const std::wstring& GetCA() { return m_wsCA; } const std::wstring& GetRC() { return m_wsRC; } const std::wstring& GetAC() { return m_wsAC; } diff --git a/PdfFile/SrcWriter/FontOTWriter.cpp b/PdfFile/SrcWriter/FontOTWriter.cpp index 2cd23ac93e..c99e5d484e 100644 --- a/PdfFile/SrcWriter/FontOTWriter.cpp +++ b/PdfFile/SrcWriter/FontOTWriter.cpp @@ -4394,7 +4394,8 @@ namespace PdfWriter std::vector subsetGlyphIDs; for (unsigned long i = 0; i < unCodesCount; ++i) subsetGlyphIDs.push_back(pCodeToGID[i]); - // Убедиться, что есть 0 глиф + if (subsetGlyphIDs.empty()) + subsetGlyphIDs.push_back(0); // Добавить зависимые глифы // Они есть в m_vCodeToGid из pCodeToGID. В pUseGlyfs они тоже есть из m_mGlyphs, но только в m_mGlyphs, они имеют false diff --git a/PdfFile/SrcWriter/FontTT.cpp b/PdfFile/SrcWriter/FontTT.cpp index 21419e9543..3dee4ff587 100644 --- a/PdfFile/SrcWriter/FontTT.cpp +++ b/PdfFile/SrcWriter/FontTT.cpp @@ -108,7 +108,10 @@ namespace PdfWriter if (m_pFontFile && m_pFontFileDict) { CStream* pStream = m_pFontFileDict->GetStream(); - m_pFontFile->WriteTTF(pStream); + if (m_pFontFile->GetOpenTypeCFF()) + m_pFontFile->WriteOTF(pStream); + else + m_pFontFile->WriteTTF(pStream); m_pFontFileDict->Add("Length1", pStream->Size()); m_pFontFileDict->SetFilter(STREAM_FILTER_FLATE_DECODE); } diff --git a/PdfFile/lib/xpdf/Gfx.cc b/PdfFile/lib/xpdf/Gfx.cc index 5baf41c4f2..e8264fb6d4 100644 --- a/PdfFile/lib/xpdf/Gfx.cc +++ b/PdfFile/lib/xpdf/Gfx.cc @@ -4347,6 +4347,21 @@ GBool Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { maskColorMap = NULL; // make gcc happy dict->lookup("Mask", &maskObj); dict->lookup("SMask", &smaskObj); + + if (maskObj.isString()) + { + GString* maskStr = maskObj.getString(); + Object oDict, oMaskObj; + oDict.initNull(); + MemStream* stream = new MemStream(maskStr->getCString(), 0, maskStr->getLength(), &oDict); + Parser* parser = new Parser(NULL, new Lexer(NULL, stream), gTrue); + parser->getObj(&oMaskObj); + maskObj.free(); + oMaskObj.copy(&maskObj); + oMaskObj.free(); + delete parser; + } + if (smaskObj.isStream()) { // soft mask if (inlineImg) { diff --git a/PdfFile/lib/xpdf/Page.cc b/PdfFile/lib/xpdf/Page.cc index 05b03ce739..df078072c2 100644 --- a/PdfFile/lib/xpdf/Page.cc +++ b/PdfFile/lib/xpdf/Page.cc @@ -395,7 +395,7 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, sType = annotList->getAnnot(i)->getType(); if (globalParams->getDrawAnnotations() || sType->cmp("Link") == 0 || sType->cmp("FileAttachment") == 0 || sType->cmp("Sound") == 0 || sType->cmp("Movie") == 0 || sType->cmp("Screen") == 0 || sType->cmp("PrinterMark") == 0 || - sType->cmp("TrapNet") == 0 || sType->cmp("Watermark") == 0 || sType->cmp("3D") == 0 || sType->cmp("Redact") == 0) + sType->cmp("TrapNet") == 0 || sType->cmp("Watermark") == 0 || sType->cmp("3D") == 0) annotList->getAnnot(i)->draw(gfx, printing); } }