From 7d6a95d521588a5adc10c2342c3fc8d7ffab33d2 Mon Sep 17 00:00:00 2001 From: Oleg Korshul Date: Sun, 18 Feb 2024 22:10:54 +0300 Subject: [PATCH] Fix bug 65583 --- DesktopEditor/doctrenderer/doctrenderer.cpp | 87 +++++++++++++++---- DesktopEditor/doctrenderer/doctrenderer.h | 15 ++-- .../doctrenderer/embed/GraphicsEmbed.cpp | 11 +++ .../doctrenderer/embed/GraphicsEmbed.h | 8 +- DesktopEditor/doctrenderer/embed/ZipEmbed.cpp | 4 +- .../embed/jsc/jsc_GraphicsEmbed.mm | 4 + .../embed/v8/v8_GraphicsEmbed.cpp | 4 + DesktopEditor/doctrenderer/graphics.cpp | 46 ++++++---- DesktopEditor/doctrenderer/graphics.h | 4 + X2tConverter/src/lib/pdf_image.h | 64 +++++++++++++- 10 files changed, 199 insertions(+), 48 deletions(-) diff --git a/DesktopEditor/doctrenderer/doctrenderer.cpp b/DesktopEditor/doctrenderer/doctrenderer.cpp index d1786ad8c6..7fca40bcb7 100644 --- a/DesktopEditor/doctrenderer/doctrenderer.cpp +++ b/DesktopEditor/doctrenderer/doctrenderer.cpp @@ -540,6 +540,42 @@ namespace NSDoctRenderer } break; } + case DoctRendererFormat::WATERMARK: + { + if (!pParams->m_sJsonParams.empty()) + { + std::string sTmp = U_TO_UTF8((pParams->m_sJsonParams)); + args[0] = context->JSON_Parse(sTmp.c_str()); + + JSSmart js_watermark = js_objectApi->call_func("asc_nativeGetWatermark", 1, args); + if (!try_catch->Check() && js_watermark->isString()) + { + std::string sWatermark = js_watermark->toStringA(); + std::string::size_type pos = sWatermark.find(','); + if (pos != std::string::npos) + { + int nInputSize = (int)(sWatermark.length() - pos) - 1; + char* pInput = (char*)(sWatermark.c_str() + pos + 1); + + int nOutputSize = 0; + BYTE* pOutput = NULL; + + if (NSFile::CBase64Converter::Decode(pInput, nInputSize, pOutput, nOutputSize)) + { + NSFile::CFileBinary oFileWatermark; + if (oFileWatermark.CreateFileW(pParams->m_strDstFilePath)) + { + oFileWatermark.WriteFile(pOutput, nOutputSize); + oFileWatermark.CloseFile(); + } + + RELEASEARRAYOBJECTS(pOutput); + } + } + } + } + break; + } default: break; } @@ -606,27 +642,20 @@ namespace NSDoctRenderer // Api object JSSmart js_objectApi; - // OPEN + bool bIsWatermark = (m_oParams.m_eDstFormat == NSDoctRenderer::DoctRendererFormat::WATERMARK) ? true : false; + JSSmart openOptions; + if (!bIsBreak) { - CChangesWorker oWorkerLoader; - int nVersion = oWorkerLoader.OpenNative(pNative->GetFilePath()); - - JSSmart args_open[4]; - args_open[0] = oWorkerLoader.GetDataFull()->toValue(); - args_open[1] = CJSContext::createInt(nVersion); - std::wstring sXlsx = NSFile::GetDirectoryName(pNative->GetFilePath()) + L"/Editor.xlsx"; - args_open[2] = NSFile::CFileBinary::Exists(sXlsx) ? CJSContext::createString(sXlsx) : CJSContext::createUndefined(); - if (!m_oParams.m_sJsonParams.empty()) { std::string sTmp = U_TO_UTF8((m_oParams.m_sJsonParams)); - args_open[3] = context->JSON_Parse(sTmp.c_str()); + openOptions = context->JSON_Parse(sTmp.c_str()); if (0 < m_oParams.m_nLcid) { - if (args_open[3]->isObject()) - args_open[3]->toObject()->set("locale", CJSContext::createInt(m_oParams.m_nLcid)); + if (openOptions->isObject()) + openOptions->toObject()->set("locale", CJSContext::createInt(m_oParams.m_nLcid)); } } else @@ -634,10 +663,35 @@ namespace NSDoctRenderer JSSmart optionsParams = CJSContext::createObject(); if (0 < m_oParams.m_nLcid) optionsParams->set("locale", CJSContext::createInt(m_oParams.m_nLcid)); - args_open[3] = optionsParams->toValue(); + openOptions = optionsParams->toValue(); + } + } + + // OPEN + if (!bIsBreak) + { + if (!bIsWatermark) + { + CChangesWorker oWorkerLoader; + int nVersion = oWorkerLoader.OpenNative(pNative->GetFilePath()); + + JSSmart args_open[4]; + args_open[0] = oWorkerLoader.GetDataFull()->toValue(); + args_open[1] = CJSContext::createInt(nVersion); + std::wstring sXlsx = NSFile::GetDirectoryName(pNative->GetFilePath()) + L"/Editor.xlsx"; + args_open[2] = NSFile::CFileBinary::Exists(sXlsx) ? CJSContext::createString(sXlsx) : CJSContext::createUndefined(); + args_open[3] = openOptions; + + global_js->call_func("NativeOpenFileData", 4, args_open); + } + else + { + JSSmart args_open[1]; + args_open[0] = openOptions; + + global_js->call_func("NativeCreateApi", 1, args_open); } - global_js->call_func("NativeOpenFileData", 4, args_open); if (try_catch->Check()) { strError = L"code=\"open\""; @@ -655,7 +709,7 @@ namespace NSDoctRenderer LOGGER_SPEED_LAP("open"); // CHANGES - if (!bIsBreak) + if (!bIsBreak && !bIsWatermark) { if (m_oParams.m_arChanges.size() != 0) { @@ -892,6 +946,7 @@ namespace NSDoctRenderer case DoctRendererFormat::PDF: case DoctRendererFormat::IMAGE: case DoctRendererFormat::HTML: + case DoctRendererFormat::WATERMARK: { arSdkFiles = &m_pInternal->m_arDoctSDK; m_pInternal->m_strEditorType = L"document"; diff --git a/DesktopEditor/doctrenderer/doctrenderer.h b/DesktopEditor/doctrenderer/doctrenderer.h index 01e7963e5f..32325f7682 100644 --- a/DesktopEditor/doctrenderer/doctrenderer.h +++ b/DesktopEditor/doctrenderer/doctrenderer.h @@ -42,14 +42,15 @@ namespace NSDoctRenderer { enum FormatFile { - DOCT = 0, - XLST = 1, - PPTT = 2, - PDF = 3, - HTML = 4, + DOCT = 0, + XLST = 1, + PPTT = 2, + PDF = 3, + HTML = 4, PPTX_THEME_THUMBNAIL = 5, - IMAGE = 6, - VSDT = 7, + IMAGE = 6, + VSDT = 7, + WATERMARK = 8, INVALID = 255 }; diff --git a/DesktopEditor/doctrenderer/embed/GraphicsEmbed.cpp b/DesktopEditor/doctrenderer/embed/GraphicsEmbed.cpp index 69f21471bb..9ef11b3673 100644 --- a/DesktopEditor/doctrenderer/embed/GraphicsEmbed.cpp +++ b/DesktopEditor/doctrenderer/embed/GraphicsEmbed.cpp @@ -564,3 +564,14 @@ JSSmart CGraphicsEmbed::GetTransform() e->set("ty", res.ty); return e->toValue(); } + +JSSmart CGraphicsEmbed::CreateLayer(JSSmart opacity) +{ + m_pInternal->CreateLayer(opacity->toDouble()); + return NULL; +} +JSSmart CGraphicsEmbed::BlendLayer() +{ + m_pInternal->BlendLayer(); + return NULL; +} diff --git a/DesktopEditor/doctrenderer/embed/GraphicsEmbed.h b/DesktopEditor/doctrenderer/embed/GraphicsEmbed.h index 5982da9892..1d386f4d25 100644 --- a/DesktopEditor/doctrenderer/embed/GraphicsEmbed.h +++ b/DesktopEditor/doctrenderer/embed/GraphicsEmbed.h @@ -82,11 +82,11 @@ public: JSSmart drawHorLine (JSSmart align, JSSmart y, JSSmart x, JSSmart r, JSSmart penW); JSSmart drawHorLine2(JSSmart align, JSSmart y, JSSmart x, JSSmart r, JSSmart penW); JSSmart drawVerLine (JSSmart align, JSSmart x, JSSmart y, JSSmart b, JSSmart penW); - // мега крутые функции для таблиц + JSSmart drawHorLineExt(JSSmart align, JSSmart y, JSSmart x, JSSmart r, JSSmart penW, JSSmart leftMW, JSSmart rightMW); JSSmart rect (JSSmart x, JSSmart y, JSSmart w, JSSmart h); JSSmart TableRect(JSSmart x, JSSmart y, JSSmart w, JSSmart h); - // функции клиппирования + JSSmart AddClipRect(JSSmart x, JSSmart y, JSSmart w, JSSmart h); JSSmart RemoveClipRect(); JSSmart SetClip(JSSmart x, JSSmart y, JSSmart w, JSSmart h); @@ -132,6 +132,10 @@ public: JSSmart CoordTransformOffset(JSSmart tx, JSSmart ty); JSSmart GetTransform(); + // layer + JSSmart CreateLayer(JSSmart opacity); + JSSmart BlendLayer(); + DECLARE_EMBED_METHODS }; diff --git a/DesktopEditor/doctrenderer/embed/ZipEmbed.cpp b/DesktopEditor/doctrenderer/embed/ZipEmbed.cpp index 5fb12ec5cc..e2151d1f28 100644 --- a/DesktopEditor/doctrenderer/embed/ZipEmbed.cpp +++ b/DesktopEditor/doctrenderer/embed/ZipEmbed.cpp @@ -176,7 +176,7 @@ JSSmart CZipEmbed::encodeImageData(JSSmart typedArray, JSSma if (oFrame.Encode(pBuffer, nEncodedSize, format->toInt32())) { BYTE* pData = NSAllocator::Alloc((size_t)nEncodedSize); - memcpy(pData, oFrame.get_Data(), (size_t)nEncodedSize); + memcpy(pData, pBuffer, (size_t)nEncodedSize); oFrame.FreeEncodedMemory(pBuffer); oFrame.put_Data(NULL); @@ -230,7 +230,7 @@ JSSmart CZipEmbed::encodeImage(JSSmart typedArray, JSSmarttoInt32())) { BYTE* pData = NSAllocator::Alloc((size_t)nEncodedSize); - memcpy(pData, oFrame.get_Data(), (size_t)nEncodedSize); + memcpy(pData, pBuffer, (size_t)nEncodedSize); oFrame.FreeEncodedMemory(pBuffer); oFrame.put_Data(NULL); diff --git a/DesktopEditor/doctrenderer/embed/jsc/jsc_GraphicsEmbed.mm b/DesktopEditor/doctrenderer/embed/jsc/jsc_GraphicsEmbed.mm index 0928dcb2d6..cb6ddd924a 100644 --- a/DesktopEditor/doctrenderer/embed/jsc/jsc_GraphicsEmbed.mm +++ b/DesktopEditor/doctrenderer/embed/jsc/jsc_GraphicsEmbed.mm @@ -108,6 +108,8 @@ -(JSValue*) DrawPath : (JSValue*)path; -(JSValue*) CoordTransformOffset : (JSValue*)tx : (JSValue*)ty; -(JSValue*) GetTransform; +-(JSValue*) CreateLayer : (JSValue*)opacity; +-(JSValue*) BlendLayer; @end @interface CJSCGraphicsEmbed : NSObject @@ -223,6 +225,8 @@ FUNCTION_WRAPPER_JS_0(GetlineWidth, GetlineWidth) FUNCTION_WRAPPER_JS_1(DrawPath, DrawPath) FUNCTION_WRAPPER_JS_2(CoordTransformOffset, CoordTransformOffset) FUNCTION_WRAPPER_JS_0(GetTransform, GetTransform) +FUNCTION_WRAPPER_JS_1(CreateLayer, CreateLayer) +FUNCTION_WRAPPER_JS_0(BlendLayer, BlendLayer) @end class CGraphicsEmbedAdapter : public CJSEmbedObjectAdapterJSC diff --git a/DesktopEditor/doctrenderer/embed/v8/v8_GraphicsEmbed.cpp b/DesktopEditor/doctrenderer/embed/v8/v8_GraphicsEmbed.cpp index ce4aac9e74..8724353630 100644 --- a/DesktopEditor/doctrenderer/embed/v8/v8_GraphicsEmbed.cpp +++ b/DesktopEditor/doctrenderer/embed/v8/v8_GraphicsEmbed.cpp @@ -111,6 +111,8 @@ namespace NSGraphicsEmbed FUNCTION_WRAPPER_V8_1(_DrawPath, DrawPath) FUNCTION_WRAPPER_V8_2(_CoordTransformOffset, CoordTransformOffset) FUNCTION_WRAPPER_V8_0(_GetTransform, GetTransform) + FUNCTION_WRAPPER_V8_1(_CreateLayer, CreateLayer) + FUNCTION_WRAPPER_V8_0(_BlendLayer, BlendLayer) v8::Handle CreateTemplate(v8::Isolate* isolate) { @@ -221,6 +223,8 @@ namespace NSGraphicsEmbed NSV8Objects::Template_Set(result, "DrawPath", _DrawPath); NSV8Objects::Template_Set(result, "CoordTransformOffset", _CoordTransformOffset); NSV8Objects::Template_Set(result, "GetTransform", _GetTransform); + NSV8Objects::Template_Set(result, "CreateLayer", _CreateLayer); + NSV8Objects::Template_Set(result, "BlendLayer", _BlendLayer); return handle_scope.Escape(result); } diff --git a/DesktopEditor/doctrenderer/graphics.cpp b/DesktopEditor/doctrenderer/graphics.cpp index d15a8183c3..005d6738e4 100644 --- a/DesktopEditor/doctrenderer/graphics.cpp +++ b/DesktopEditor/doctrenderer/graphics.cpp @@ -1133,28 +1133,30 @@ namespace NSGraphics } std::string CGraphics::toDataURL(std::wstring type) { - std::wstring sPath = NSFile::CFileBinary::CreateTempFileWithUniqueName(m_sApplicationImagesDirectory, L"img"); #ifdef _DEBUG - std::wcout << "toDataURL " << sPath << std::endl; + std::wcout << "toDataURL " << type << std::endl; #endif - m_oFrame.SaveFile(sPath, _CXIMAGE_FORMAT_PNG); + std::wstring sFormat = (type.length() > 6) ? type.substr(6) : type; - NSFile::CFileBinary oReader; - if (oReader.OpenFile(sPath)) + BYTE* pDataImage = NULL; + int nDataImageSize = 0; + int nImageFormat = _CXIMAGE_FORMAT_PNG; + if ((L"jpg" == sFormat) ||(L"jpeg" == sFormat)) + nImageFormat = _CXIMAGE_FORMAT_JPG; + + std::string sRes = ""; + if (m_oFrame.Encode(pDataImage, nDataImageSize, nImageFormat)) { - DWORD dwFileSize = oReader.GetFileSize(); - BYTE* pFileContent = new BYTE[dwFileSize]; - DWORD dwReaded; - oReader.ReadFile(pFileContent, dwFileSize, dwReaded); - oReader.CloseFile(); - - NSFile::CFileBinary::Remove(sPath); - int nEncodeLen = NSBase64::Base64EncodeGetRequiredLength(dwFileSize); - BYTE* pImageData = new BYTE[nEncodeLen]; - if (TRUE == NSBase64::Base64Encode(pFileContent, dwFileSize, pImageData, &nEncodeLen)) - return "data:" + U_TO_UTF8(type) + ";base64, " + std::string((char*)pImageData, nEncodeLen); + char* cData64 = NULL; + int nData64Dst = 0; + if (NSFile::CBase64Converter::Encode(pDataImage, nDataImageSize, cData64, nData64Dst, NSBase64::B64_BASE64_FLAG_NOCRLF)) + { + sRes = ("data:" + U_TO_UTF8(type) + ";base64," + std::string(cData64, nData64Dst)); + } + RELEASEARRAYOBJECTS(cData64); } - return ""; + RELEASEARRAYOBJECTS(pDataImage); + return sRes; } CColor CGraphics::GetPenColor() { @@ -1372,4 +1374,14 @@ namespace NSGraphics m_pRenderer->GetTransform(&oRes.sx, &oRes.shy, &oRes.shx, &oRes.sy, &oRes.tx, &oRes.ty); return oRes; } + + void CGraphics::CreateLayer(double opacity) + { + m_pRenderer->BeginCommand(c_nLayerType); + m_pRenderer->put_LayerOpacity(opacity); + } + void CGraphics::BlendLayer() + { + m_pRenderer->EndCommand(c_nLayerType); + } } diff --git a/DesktopEditor/doctrenderer/graphics.h b/DesktopEditor/doctrenderer/graphics.h index 2b8a45b1c7..68683c3329 100644 --- a/DesktopEditor/doctrenderer/graphics.h +++ b/DesktopEditor/doctrenderer/graphics.h @@ -235,6 +235,10 @@ namespace NSGraphics void DrawPath(int path); void CoordTransformOffset(double tx, double ty); CTransform GetTransform(); + + // layer + void CreateLayer(double opacity); + void BlendLayer(); }; } diff --git a/X2tConverter/src/lib/pdf_image.h b/X2tConverter/src/lib/pdf_image.h index d2b7b62dda..58f4282131 100644 --- a/X2tConverter/src/lib/pdf_image.h +++ b/X2tConverter/src/lib/pdf_image.h @@ -32,6 +32,7 @@ #pragma once #include "../../../DesktopEditor/graphics/MetafileToGraphicsRenderer.h" +#include "../../../DesktopEditor/graphics/Image.h" #include "../../../DjVuFile/DjVu.h" #include "../../../DocxRenderer/DocxRenderer.h" @@ -780,15 +781,70 @@ namespace NExtractTools } } - if (sFrom == sFromSrc) + if ((NULL == params.m_sJsonParams) || + (std::wstring::npos == params.m_sJsonParams->find(L"\"watermark\":"))) { - nRes = NSFile::CFileBinary::Copy(sFrom, sTo) ? 0 : AVS_FILEUTILS_ERROR_CONVERT; + if (sFrom == sFromSrc) + { + nRes = NSFile::CFileBinary::Copy(sFrom, sTo) ? 0 : AVS_FILEUTILS_ERROR_CONVERT; + } + else + { + nRes = NSFile::CFileBinary::Move(sFrom, sTo) ? 0 : AVS_FILEUTILS_ERROR_CONVERT; + } } else { - nRes = NSFile::CFileBinary::Move(sFrom, sTo) ? 0 : AVS_FILEUTILS_ERROR_CONVERT; - sFrom = sFromSrc; + NSDoctRenderer::CDoctrenderer oDoctRenderer(NULL != params.m_sAllFontsPath ? *params.m_sAllFontsPath : L""); + + std::wstring sWatermarkTmp = NSFile::CFileBinary::CreateTempFileWithUniqueName(convertParams.m_sTempDir, L"WWW_"); + if (NSFile::CFileBinary::Exists(sWatermarkTmp)) + NSFile::CFileBinary::Remove(sWatermarkTmp); + + std::wstring sXml = getDoctXml(NSDoctRenderer::DoctRendererFormat::DOCT, + NSDoctRenderer::DoctRendererFormat::WATERMARK, + L"", sWatermarkTmp, L"", convertParams.m_sThemesDir, -1, L"", params); + + std::wstring sResult = L""; + oDoctRenderer.Execute(sXml, sResult); + + if (sResult.empty()) + { + std::wstring password = params.getSavePassword(); + CPdfFile oPdfResult(pApplicationFonts); + if (!oPdfResult.LoadFromFile(sFrom, L"", password, password)) + return false; + + if (!oPdfResult.EditPdf(sTo)) + return false; + + Aggplus::CImage oImageW(sWatermarkTmp); + + double dW = 0, dH = 0, dDpiX = 0, dDpiY = 0; + + int nPagesCount = oPdfResult.GetPagesCount(); + for (int nPage = 0; nPage < nPagesCount; ++nPage) + { + oPdfResult.EditPage(nPage); + + oPdfResult.GetPageInfo(nPage, &dW, &dH, &dDpiX, &dDpiY); + + double dPageW_MM = dW * 25.4 / dDpiX; + double dPageH_MM = dH * 25.4 / dDpiY; + + double dImageW_MM = 25.4 * oImageW.GetWidth() / dDpiX; + double dImageH_MM = 25.4 * oImageW.GetHeight() / dDpiY; + + oPdfResult.DrawImage(&oImageW, (dPageW_MM - dImageW_MM) / 2, (dPageH_MM - dImageH_MM) / 2, dImageW_MM, dImageH_MM); + } + + oPdfResult.Close(); + } + + if (NSFile::CFileBinary::Exists(sWatermarkTmp)) + NSFile::CFileBinary::Remove(sWatermarkTmp); } + sFrom = sFromSrc; } else {