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/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/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index 72ae947837..66e9aaad66 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -1971,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/SrcReader/PdfAnnot.cpp b/PdfFile/SrcReader/PdfAnnot.cpp index d42f128372..454a63d1db 100644 --- a/PdfFile/SrcReader/PdfAnnot.cpp +++ b/PdfFile/SrcReader/PdfAnnot.cpp @@ -2435,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 //------------------------------------------------------------------------ @@ -4357,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 1149762025..e5e284e117 100644 --- a/PdfFile/SrcReader/PdfAnnot.h +++ b/PdfFile/SrcReader/PdfAnnot.h @@ -591,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 //------------------------------------------------------------------------ @@ -667,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/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); } }