Files
DocumentServer-v-9.2.0/core/DesktopEditor/graphics/MetafileToRenderer.cpp
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

1273 lines
31 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* (c) Copyright Ascensio System SIA 2010-2023
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#pragma once
#include "agg_math.h"
#include "./MetafileToRenderer.h"
#include "../fontengine/FontManager.h"
#include "../raster/BgraFrame.h"
#include "../common/StringExt.h"
// этот класс нужно переписать. должно работать как и в js
// а не просто на каждом символе переключаться, если нужно
class CMetafileFontPicker
{
private:
NSFonts::IApplicationFonts* m_pApplication;
NSFonts::IFontManager* m_pManager;
IRenderer* m_pRenderer;
public:
CMetafileFontPicker(std::wstring sFolder)
{
m_pApplication = NSFonts::NSApplication::Create();
m_pApplication->InitializeFromFolder(sFolder);
m_pManager = m_pApplication->GenerateFontManager();
NSFonts::IFontsCache* pCache = NSFonts::NSFontCache::Create();
pCache->SetStreams(m_pApplication->GetStreams());
m_pManager->SetOwnerCache(pCache);
m_pRenderer = NULL;
}
CMetafileFontPicker(NSFonts::IApplicationFonts* pFonts)
{
m_pApplication = pFonts;
m_pApplication->AddRef();
m_pManager = m_pApplication->GenerateFontManager();
NSFonts::IFontsCache* pCache = NSFonts::NSFontCache::Create();
pCache->SetStreams(m_pApplication->GetStreams());
m_pManager->SetOwnerCache(pCache);
m_pRenderer = NULL;
}
~CMetafileFontPicker()
{
m_pManager->Release();
m_pApplication->Release();
}
void SetFont(const std::wstring& sName, const bool& bBold, const bool& bItalic)
{
int nStyle = 0;
if (bBold) nStyle |= 0x01;
if (bItalic) nStyle |= 0x02;
SetFont(sName, nStyle);
}
void SetFont(const std::wstring& sName, const int& nStyle)
{
m_pManager->LoadFontByName(sName, 10, nStyle, 72, 72);
}
void FillText(const std::wstring& bsText, const double& x, const double& y, const double& w, const double& h)
{
int bGID = 0;
m_pRenderer->get_FontStringGID(&bGID);
CGlyphString oString(bsText, 0, 0);
if (bGID || oString.GetLength() != 1)
{
m_pRenderer->CommandDrawText(bsText, x, y, w, h);
return;
}
std::wstring sName;
LONG nStyle = 0;
m_pRenderer->get_FontName(&sName);
m_pRenderer->get_FontStyle(&nStyle);
SetFont(sName, (int)nStyle);
NSFonts::IFontFile* pFont = m_pManager->GetFile();
if (!pFont)
{
m_pRenderer->CommandDrawText(bsText, x, y, w, h);
return;
}
int code = oString.GetAt(0)->lUnicode;
if (pFont->GetGIDByUnicode(code))
{
m_pRenderer->CommandDrawText(bsText, x, y, w, h);
return;
}
CFontFile* pFileNew = ((CFontManager*)m_pManager)->GetFontFileBySymbol((CFontFile*)m_pManager->GetFile(), code);
if (!pFileNew)
{
m_pRenderer->CommandDrawText(bsText, x, y, w, h);
return;
}
m_pRenderer->put_FontName(pFileNew->m_sName);
int nNewStyle = 0;
if (pFileNew->IsBold()) nNewStyle |= 0x01;
if (pFileNew->IsItalic()) nNewStyle |= 0x02;
m_pRenderer->put_FontStyle(nNewStyle);
m_pRenderer->CommandDrawText(bsText, x, y, w, h);
m_pRenderer->put_FontName(sName);
m_pRenderer->put_FontStyle(nStyle);
RELEASEINTERFACE(pFileNew);
}
void SetRenderer(IRenderer* pRenderer)
{
m_pRenderer = pRenderer;
}
};
IMetafileToRenderter::IMetafileToRenderter(IRenderer* pRenderer)
{
m_pRenderer = pRenderer;
m_pPicker = NULL;
}
IMetafileToRenderter::~IMetafileToRenderter()
{
if (m_pPicker)
{
CMetafileFontPicker* pPicker = (CMetafileFontPicker*)m_pPicker;
RELEASEOBJECT(pPicker);
m_pPicker = NULL;
}
}
void IMetafileToRenderter::SetTempDirectory(const std::wstring& sDir) { m_sTempDir = sDir; }
std::wstring IMetafileToRenderter::GetTempDirectory() { return m_sTempDir; }
void IMetafileToRenderter::SetMediaDirectory(const std::wstring& sDir) { m_sMediaDir = sDir; }
std::wstring IMetafileToRenderter::GetMediaDirectory() { return m_sMediaDir; }
void IMetafileToRenderter::SetInternalMediaDirectory(const std::wstring& sDir) { m_sInternalMediaDir = sDir; }
std::wstring IMetafileToRenderter::GetInternalMediaDirectory() { return m_sInternalMediaDir; }
void IMetafileToRenderter::SetThemesDirectory(const std::wstring& sDir) { m_sThemesDir = sDir; }
std::wstring IMetafileToRenderter::GetThemesDirectory() { return m_sThemesDir; }
std::wstring IMetafileToRenderter::GetImagePath(const std::wstring& sPath)
{
std::wstring sImagePath = L"";
if (0 == sPath.find(L"data:"))
{
try
{
std::wstring::size_type posZ = sPath.find(',');
if (std::wstring::npos == posZ)
throw;
bool bIsOnlyOfficeHatch = false;
if (std::wstring::npos != sPath.substr(0, posZ).find(L"onlyoffice_hatch"))
bIsOnlyOfficeHatch = true;
int nBase64Size = (int)(sPath.length() - posZ - 1);
const wchar_t* pBase64Data = sPath.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];
if (NSBase64::Base64Decode(pBase64Buffer, nBase64Size, pImageBuffer, &nBufferLen))
{
if (m_sTempDir.empty())
m_sTempDir = NSFile::CFileBinary::GetTempPath();
std::wstring sTempFile = NSFile::CFileBinary::CreateTempFileWithUniqueName(m_sTempDir, L"Image_");
if (!bIsOnlyOfficeHatch)
{
NSFile::CFileBinary oFile;
if (oFile.CreateFileW(sTempFile))
{
oFile.WriteFile(pImageBuffer, nBufferLen);
oFile.CloseFile();
sImagePath = sTempFile;
}
}
else
{
int nSize = (int)sqrt(nBufferLen >> 2);
CBgraFrame oFrame;
oFrame.put_Data(pImageBuffer);
oFrame.put_Width(nSize);
oFrame.put_Height(nSize);
oFrame.put_Stride(4 * nSize);
oFrame.put_IsRGBA(true);
oFrame.SaveFile(sTempFile, 4); // PNG
oFrame.put_Data(NULL);
sImagePath = sTempFile;
}
}
RELEASEARRAYOBJECTS(pImageBuffer);
RELEASEARRAYOBJECTS(pBase64Buffer);
if (sImagePath.empty())
throw;
}
catch (...)
{
}
}
else
{
if (0 != sPath.find(L"http:") &&
0 != sPath.find(L"https:") &&
0 != sPath.find(L"ftp:") &&
0 != sPath.find(L"file:"))
{
if (0 == sPath.find(L"theme") && !m_sThemesDir.empty())
{
sImagePath = m_sThemesDir + L"/" + sPath;
}
else
{
if (!m_sMediaDir.empty())
{
std::wstring::size_type posMedia = sPath.find(L"media/");
if (std::wstring::npos != posMedia)
{
if (0 == posMedia || NSFile::CFileBinary::Exists(m_sMediaDir + L"/" + sPath))
{
sImagePath = m_sMediaDir + L"/" + sPath;
}
else if (!m_sInternalMediaDir.empty() && (3 <= posMedia && posMedia <= 5) && NSFile::CFileBinary::Exists(m_sInternalMediaDir + L"/" + sPath))
{
// word/media/.. ppt/media/.. xl/media/..
sImagePath = m_sInternalMediaDir + L"/" + sPath;
}
else
{
sImagePath = m_sMediaDir + L"/media/" + sPath;
}
}
else
{
sImagePath = m_sMediaDir + L"/media/" + sPath;
}
}
std::wstring wsSvgExt(L".svg");
if (0 == sImagePath.compare(sImagePath.length() - wsSvgExt.length(), std::wstring::npos, wsSvgExt))
{
std::wstring wsTestPath = sImagePath.substr(0, sImagePath.length() - wsSvgExt.length());
if (NSFile::CFileBinary::Exists(wsTestPath + L".emf"))
sImagePath = wsTestPath + L".emf";
else if (NSFile::CFileBinary::Exists(wsTestPath + L".wmf"))
sImagePath = wsTestPath + L".wmf";
}
}
NSStringExt::Replace(sImagePath, L"\\", L"/");
}
if (0 == sImagePath.find(L"file:///"))
{
// TODO: под linux код неправильный
NSStringExt::Replace(sImagePath, L"file:///", L"");
NSStringExt::Replace(sImagePath, L"\\", L"/");
}
}
return sImagePath.empty() ? sPath : sImagePath;
}
void IMetafileToRenderter::SetLinearGradiant(const double& x0, const double& y0, const double& x1, const double& y1)
{
double dAngle = 0;
if (fabs(x1 - x0) >= FLT_EPSILON || fabs(y1 - y0) >= FLT_EPSILON)
dAngle = 180 * atan2(y1 - y0, x1 - x0) / agg::pi;
m_pRenderer->put_BrushType(/*c_BrushTypePathGradient1*/2006);
m_pRenderer->put_BrushLinearAngle(dAngle);
}
void IMetafileToRenderter::SetRadialGradiant(const double& dX0, const double& dY0, const double& dR0, const double& dX1, const double& dY1, const double& dR1)
{
// TODO:
m_pRenderer->put_BrushType(/*c_BrushTypePathGradient2*/2007);
}
void IMetafileToRenderter::InitPicker(const std::wstring& sFontsFolder)
{
CMetafileFontPicker* pPicker = new CMetafileFontPicker(sFontsFolder);
m_pPicker = (void*)pPicker;
}
void IMetafileToRenderter::InitPicker(NSFonts::IApplicationFonts* pFonts)
{
CMetafileFontPicker* pPicker = new CMetafileFontPicker(pFonts);
m_pPicker = (void*)pPicker;
}
namespace NSOnlineOfficeBinToPdf
{
bool ConvertBufferToRenderer(BYTE* pBuffer, LONG lBufferLen, IMetafileToRenderter* pCorrector)
{
IRenderer* pRenderer = pCorrector->m_pRenderer;
CMetafileFontPicker* pPicker = NULL;
if (pCorrector->m_pPicker)
{
pPicker = (CMetafileFontPicker*)pCorrector->m_pPicker;
pPicker->SetRenderer(pRenderer);
}
LONG lRendererType = 0;
pRenderer->get_Type(&lRendererType);
// из команд js - точные имена
pRenderer->CommandLong(c_nUseDictionaryFonts, 0);
CommandType eCommand = ctError;
bool bIsPathOpened = false;
bool bIsEnableBrushRect = false;
CBufferReader oReader(pBuffer, lBufferLen);
while (oReader.Check())
{
eCommand = (CommandType)(oReader.ReadByte());
switch (eCommand)
{
case ctPageWidth:
{
pRenderer->put_Width(oReader.ReadDouble());
break;
}
case ctPageHeight:
{
pRenderer->put_Height(oReader.ReadDouble());
break;
}
case ctPageStart:
{
pRenderer->NewPage();
pRenderer->BeginCommand(c_nPageType);
// TODO:
pRenderer->put_PenLineStartCap(Aggplus::LineCapFlat);
pRenderer->put_PenLineEndCap(Aggplus::LineCapFlat);
break;
}
case ctPageEnd:
{
if (bIsPathOpened)
{
pRenderer->PathCommandEnd();
pRenderer->EndCommand(c_nPathType);
}
bIsPathOpened = false;
pRenderer->EndCommand(c_nPageType);
if (lRendererType == c_nGrRenderer)
return true;
break;
}
case ctPenColor:
{
pRenderer->put_PenColor(oReader.ReadInt());
break;
}
case ctPenAlpha:
{
pRenderer->put_PenAlpha(oReader.ReadByte());
break;
}
case ctPenSize:
{
pRenderer->put_PenSize(oReader.ReadDouble());
break;
}
case ctPenDashStyle:
{
BYTE nDashType = oReader.ReadByte();
switch (nDashType)
{
case Aggplus::DashStyleCustom:
{
int nCountDash = oReader.ReadInt();
if (0 < nCountDash)
{
double* pDash = new double[nCountDash];
for (int nDash = 0; nDash < nCountDash; ++nDash)
{
pDash[nDash] = oReader.ReadDouble();
}
pRenderer->PenDashPattern(pDash, nCountDash);
delete[] pDash;
}
}
default:
pRenderer->put_PenDashStyle(nDashType);
break;
}
break;
}
case ctPenLineJoin:
{
pRenderer->put_PenLineJoin(oReader.ReadByte());
break;
}
case ctBrushType:
{
pRenderer->put_BrushType(oReader.ReadInt());
break;
}
case ctBrushColor1:
{
pRenderer->put_BrushColor1(oReader.ReadInt());
break;
}
case ctBrushAlpha1:
{
pRenderer->put_BrushAlpha1(oReader.ReadByte());
break;
}
case ctBrushColor2:
{
pRenderer->put_BrushColor1(oReader.ReadInt());
break;
}
case ctBrushAlpha2:
{
pRenderer->put_BrushAlpha2(oReader.ReadByte());
break;
}
case ctBrushRectable:
{
double m1 = oReader.ReadDouble();
double m2 = oReader.ReadDouble();
double m3 = oReader.ReadDouble();
double m4 = oReader.ReadDouble();
pRenderer->BrushRect(bIsEnableBrushRect ? 1 : 0, m1, m2, m3, m4);
break;
}
case ctBrushRectableEnabled:
{
bIsEnableBrushRect = oReader.ReadBool();
if (!bIsEnableBrushRect)
pRenderer->BrushRect(bIsEnableBrushRect ? 1 : 0, 0, 0, 1, 1);
break;
}
case ctBrushTexturePathOld:
{
int nLen = 2 * oReader.ReadUShort();
std::wstring sTempPath = oReader.ReadString16(nLen);
std::wstring sImagePath = pCorrector->GetImagePath(sTempPath);
pRenderer->put_BrushTexturePath(sImagePath);
break;
}
case ctBrushTexturePath:
{
int nLen = oReader.ReadInt();
std::wstring sTempPath = oReader.ReadString16(nLen);
std::wstring sImagePath = pCorrector->GetImagePath(sTempPath);
pRenderer->put_BrushTexturePath(sImagePath);
break;
}
case ctBrushGradient:
{
oReader.Skip(1);
while (true)
{
BYTE _command = oReader.ReadByte();
if (251 == _command)
break;
switch (_command)
{
case 0:
{
oReader.Skip(5);
double x0 = oReader.ReadDouble();
double y0 = oReader.ReadDouble();
double x1 = oReader.ReadDouble();
double y1 = oReader.ReadDouble();
pCorrector->SetLinearGradiant(x0, y0, x1, y1);
break;
}
case 1:
{
oReader.Skip(1);
double x0 = oReader.ReadDouble();
double y0 = oReader.ReadDouble();
double x1 = oReader.ReadDouble();
double y1 = oReader.ReadDouble();
double r0 = oReader.ReadDouble();
double r1 = oReader.ReadDouble();
pCorrector->SetRadialGradiant(x0, y0, r0, x1, y1, r1);
break;
}
case 2:
{
LONG lColorsCount = (LONG)oReader.ReadInt();
if (0 >= lColorsCount)
{
pRenderer->put_BrushGradientColors(NULL, NULL, 0);
}
else
{
LONG* pColors = new LONG[lColorsCount];
double* pPositions = new double[lColorsCount];
if (!pColors)
break;
if (!pPositions)
{
delete[] pColors;
break;
}
for (LONG lIndex = 0; lIndex < lColorsCount; lIndex++)
{
pPositions[lIndex] = oReader.ReadDouble();
pColors[lIndex] = oReader.ReadInt();
}
pRenderer->put_BrushGradientColors(pColors, pPositions, lColorsCount);
delete[] pColors;
delete[] pPositions;
}
break;
}
default:
{
break;
}
};
}
break;
}
case ctBrushTextureMode:
{
LONG lMode = (LONG)oReader.ReadByte();
pRenderer->put_BrushTextureMode(lMode);
break;
}
case ctBrushTextureAlpha:
{
LONG lAlpha = (LONG)oReader.ReadByte();
pRenderer->put_BrushTextureAlpha(lAlpha);
break;
}
case ctSetTransform:
{
double m1 = oReader.ReadDouble();
double m2 = oReader.ReadDouble();
double m3 = oReader.ReadDouble();
double m4 = oReader.ReadDouble();
double m5 = oReader.ReadDouble();
double m6 = oReader.ReadDouble();
pRenderer->SetTransform(m1, m2, m3, m4, m5, m6);
break;
}
case ctPathCommandStart:
{
if (bIsPathOpened)
{
pRenderer->PathCommandEnd();
pRenderer->EndCommand(c_nPathType);
}
pRenderer->BeginCommand(c_nPathType);
pRenderer->PathCommandStart();
bIsPathOpened = true;
break;
}
case ctPathCommandMoveTo:
{
double m1 = oReader.ReadDouble();
double m2 = oReader.ReadDouble();
pRenderer->PathCommandMoveTo(m1, m2);
break;
}
case ctPathCommandLineTo:
{
double m1 = oReader.ReadDouble();
double m2 = oReader.ReadDouble();
pRenderer->PathCommandLineTo(m1, m2);
break;
}
case ctPathCommandCurveTo:
{
double m1 = oReader.ReadDouble();
double m2 = oReader.ReadDouble();
double m3 = oReader.ReadDouble();
double m4 = oReader.ReadDouble();
double m5 = oReader.ReadDouble();
double m6 = oReader.ReadDouble();
pRenderer->PathCommandCurveTo(m1, m2, m3, m4, m5, m6);
break;
}
case ctPathCommandClose:
{
pRenderer->PathCommandClose();
break;
}
case ctPathCommandEnd:
{
if (bIsPathOpened)
{
pRenderer->PathCommandEnd();
pRenderer->EndCommand(c_nPathType);
bIsPathOpened = false;
}
break;
}
case ctDrawPath:
{
pRenderer->DrawPath(oReader.ReadInt());
break;
}
case ctDrawImageFromFile:
{
int nLen = oReader.ReadInt();
std::wstring sTempPath = oReader.ReadString16(nLen);
std::wstring sImagePath = pCorrector->GetImagePath(sTempPath);
double m1 = oReader.ReadDouble();
double m2 = oReader.ReadDouble();
double m3 = oReader.ReadDouble();
double m4 = oReader.ReadDouble();
try
{
pRenderer->DrawImageFromFile(sImagePath, m1, m2, m3, m4);
}
catch (...)
{
}
break;
}
case ctFontName:
{
int nLen = 2 * (int)oReader.ReadUShort();
std::wstring wsTempString = oReader.ReadString16(nLen);
pRenderer->put_FontName(wsTempString);
break;
}
case ctFontSize:
{
pRenderer->put_FontSize(oReader.ReadDouble());
break;
}
case ctFontStyle:
{
pRenderer->put_FontStyle(oReader.ReadInt());
break;
}
case ctDrawText:
{
int nLen = 2 * (int)oReader.ReadUShort();
std::wstring wsTempString = oReader.ReadString16(nLen);
double x = oReader.ReadDouble();
double y = oReader.ReadDouble();
if (!pPicker)
pRenderer->CommandDrawText(wsTempString, x, y, 0, 0);
else
pPicker->FillText(wsTempString, x, y, 0, 0);
break;
}
case ctDrawTextCodeGid:
{
unsigned int nGid = (unsigned int)oReader.ReadInt();
double x = oReader.ReadDouble();
double y = oReader.ReadDouble();
unsigned int nCountUnicodes = (unsigned int)oReader.ReadInt();
unsigned int* pCodePoints = (0 != nCountUnicodes) ? new unsigned int[nCountUnicodes] : NULL;
for (unsigned int nCodePointIndex = 0; nCodePointIndex < nCountUnicodes; ++nCodePointIndex)
pCodePoints[nCodePointIndex] = oReader.ReadInt();
pRenderer->CommandDrawTextCHAR2(pCodePoints, nCountUnicodes, nGid, x, y, 0, 0);
if (pCodePoints)
delete [] pCodePoints;
break;
}
case ctBeginCommand:
{
if (bIsPathOpened)
{
pRenderer->PathCommandEnd();
pRenderer->EndCommand(4);
bIsPathOpened = false;
}
pRenderer->BeginCommand((DWORD)(oReader.ReadInt()));
break;
}
case ctEndCommand:
{
if (bIsPathOpened)
{
pRenderer->EndCommand(4);
bIsPathOpened = false;
}
pRenderer->EndCommand((DWORD)(oReader.ReadInt()));
pRenderer->PathCommandEnd();
break;
}
case ctGradientFill:
{
// TODO: Эта команда не должна приходить
INT32 gradientType = oReader.ReadInt();
std::wstring sXml, sXmlStop;
if (0 == gradientType) // linearGradient
{
double x1 = oReader.ReadDouble();
double x2 = oReader.ReadDouble();
double y1 = oReader.ReadDouble();
double y2 = oReader.ReadDouble();
int stops = oReader.ReadInt();
for (int i = 0; i < stops; ++i)
{
INT32 color = static_cast<INT32>(oReader.ReadByte());
double opacity = static_cast<double>(static_cast<INT32>(oReader.ReadByte())) / 255.0;
double offset = static_cast<double>(static_cast<INT32>(oReader.ReadByte())) / 255.0;
oReader.Skip(6 * 4 - 3);
}
}
else if (1 == gradientType)
{
double cx = oReader.ReadDouble();
double cy = oReader.ReadDouble();
double r = oReader.ReadDouble();
double fx = oReader.ReadDouble();
double fy = oReader.ReadDouble();
int stops = oReader.ReadInt();
for (int i = 0; i < stops; ++i)
{
INT32 color = static_cast<INT32>(oReader.ReadByte());
double opacity = static_cast<double>(static_cast<INT32>(oReader.ReadByte())) / 255.0;
double offset = static_cast<double>(static_cast<INT32>(oReader.ReadByte())) / 255.0;
oReader.Skip(6 * 4 - 3);
}
}
break;
}
case ctGradientFillXML:
{
// TODO: Эта команда не должна приходить
INT32 gradientType = oReader.ReadInt();
int nLen = oReader.ReadInt();
std::wstring wsTempString = oReader.ReadString16(nLen);
break;
}
case ctGradientStroke:
{
// TODO: Эта команда не должна приходить
INT32 gradientType = oReader.ReadInt();
if (0 == gradientType) // linearGradient
{
double x1 = oReader.ReadDouble();
double x2 = oReader.ReadDouble();
double y1 = oReader.ReadDouble();
double y2 = oReader.ReadDouble();
int stops = oReader.ReadInt();
for (int i = 0; i < stops; ++i)
{
INT32 color = static_cast<INT32>(oReader.ReadByte());
double opacity = static_cast<double>(static_cast<INT32>(oReader.ReadByte())) / 255.0;
double offset = static_cast<double>(static_cast<INT32>(oReader.ReadByte())) / 255.0;
oReader.Skip(6 * 4 - 3);
}
}
else if (1 == gradientType)
{
double cx = oReader.ReadDouble();
double cy = oReader.ReadDouble();
double r = oReader.ReadDouble();
double fx = oReader.ReadDouble();
double fy = oReader.ReadDouble();
int stops = oReader.ReadInt();
for (int i = 0; i < stops; ++i)
{
INT32 color = static_cast<INT32>(oReader.ReadByte());
double opacity = static_cast<double>(static_cast<INT32>(oReader.ReadByte())) / 255.0;
double offset = static_cast<double>(static_cast<INT32>(oReader.ReadByte())) / 255.0;
oReader.Skip(6 * 4 - 3);
}
}
break;
}
case ctGradientStrokeXML:
{
// TODO: Эта команда не должна приходить
INT32 gradientType = oReader.ReadInt();
int nLen = (int)oReader.ReadInt();
std::wstring wsTempString = oReader.ReadString16(nLen);
break;
}
// дополнительные команды. из-за совместимости версий не можем менят формат.
// но все следующие - должны быть по одной схеме
case ctHyperlink:
{
if (S_OK == pRenderer->IsSupportAdvancedCommand(IAdvancedCommand::AdvancedCommandType::Hyperlink))
{
IAdvancedCommand* pCommand = oReader.Read(ctHyperlink, pCorrector);
if (pCommand)
{
pRenderer->AdvancedCommand(pCommand);
delete pCommand;
}
}
else
{
oReader.SkipDouble(4);
oReader.SkipString();
oReader.SkipString();
}
break;
}
case ctLink:
{
if (S_OK == pRenderer->IsSupportAdvancedCommand(IAdvancedCommand::AdvancedCommandType::Link))
{
IAdvancedCommand* pCommand = oReader.Read(ctLink, pCorrector);
if (pCommand)
{
pRenderer->AdvancedCommand(pCommand);
delete pCommand;
}
}
else
{
oReader.SkipDouble(6);
oReader.SkipInt();
}
break;
}
case ctDocInfo:
{
if (S_OK == pRenderer->IsSupportAdvancedCommand(IAdvancedCommand::AdvancedCommandType::DocInfo))
{
IAdvancedCommand* pCommand = oReader.Read(ctDocInfo, pCorrector);
pRenderer->AdvancedCommand(pCommand);
delete pCommand;
}
else
{
int nFlags = oReader.ReadInt();
if (nFlags & 1)
oReader.SkipString();
if (nFlags & 2)
oReader.SkipString();
if (nFlags & 4)
oReader.SkipString();
if (nFlags & 8)
oReader.SkipString();
}
break;
}
case ctFormField:
case ctAnnotField:
case ctAnnotFieldDelete:
case ctWidgetsInfo:
case ctShapeStart:
case ctShapeEnd:
case ctPageClear:
case ctPageRotate:
case ctHeadings:
case ctRedact:
{
IAdvancedCommand::AdvancedCommandType eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::Undefined;
switch (eCommand)
{
case ctFormField: eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::FormField; break;
case ctAnnotField: eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::Annotaion; break;
case ctAnnotFieldDelete: eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::DeleteAnnot; break;
case ctWidgetsInfo: eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::WidgetsInfo; break;
case ctShapeStart: eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::ShapeStart; break;
case ctShapeEnd: eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::ShapeEnd; break;
case ctPageClear: eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::PageClear; break;
case ctPageRotate: eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::PageRotate; break;
case ctHeadings: eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::Headings; break;
case ctRedact: eAdvancedCommandType = IAdvancedCommand::AdvancedCommandType::Redact; break;
default:
break;
}
BYTE* cur = oReader.GetCurrentBuffer();
int nLen = oReader.ReadInt();
if ((IAdvancedCommand::AdvancedCommandType::Undefined != eAdvancedCommandType) &&
(S_OK == pRenderer->IsSupportAdvancedCommand(eAdvancedCommandType)))
{
IAdvancedCommand* pCommand = oReader.Read(eCommand, pCorrector, nLen);
if (pCommand)
{
pRenderer->AdvancedCommand(pCommand);
delete pCommand;
}
}
oReader.SetCurrentBuffer(cur + nLen);
break;
}
default:
{
BYTE* cur = oReader.GetCurrentBuffer();
oReader.SetCurrentBuffer(cur + oReader.ReadInt());
break;
}
}; // switch (eCommand)
}
return true;
}
void CMetafilePagesInfo::CheckBuffer(BYTE* pBuffer, LONG lBufferLen)
{
CommandType eCommand = ctError;
bool bIsPathOpened = false;
CBufferReader oReader(pBuffer, lBufferLen);
while (oReader.Check())
{
eCommand = (CommandType)(oReader.ReadByte());
switch (eCommand)
{
case ctPageWidth:
{
arSizes[PagesCount - 1].width = oReader.ReadDouble();
break;
}
case ctPageHeight:
{
arSizes[PagesCount - 1].height = oReader.ReadDouble();
break;
}
case ctPageStart:
{
AddPage();
arSizes[PagesCount - 1].data = oReader.GetCurrentBuffer();
break;
}
case ctPageEnd:
{
break;
}
case ctPenColor:
{
oReader.SkipInt();
break;
}
case ctPenAlpha:
{
oReader.Skip(1);
break;
}
case ctPenSize:
{
oReader.SkipInt();
break;
}
case ctPenDashStyle:
{
BYTE nDashType = oReader.ReadByte();
switch (nDashType)
{
case Aggplus::DashStyleCustom:
{
int nCountDash = oReader.ReadInt();
if (0 < nCountDash)
oReader.SkipInt(nCountDash);
}
default:
break;
}
break;
}
case ctPenLineJoin:
{
oReader.Skip(1);
break;
}
case ctBrushType:
{
oReader.SkipInt();
break;
}
case ctBrushColor1:
{
oReader.SkipInt();
break;
}
case ctBrushAlpha1:
{
oReader.Skip(1);
break;
}
case ctBrushColor2:
{
oReader.SkipInt();
break;
}
case ctBrushAlpha2:
{
oReader.Skip(1);
break;
}
case ctBrushRectable:
{
oReader.SkipInt(4);
break;
}
case ctBrushRectableEnabled:
{
oReader.Skip(1);
break;
}
case ctBrushTexturePathOld:
{
int nLen = 2 * oReader.ReadUShort();
oReader.SkipString16(nLen);
break;
}
case ctBrushTexturePath:
{
int nLen = oReader.ReadInt();
oReader.SkipString16(nLen);
break;
}
case ctBrushGradient:
{
oReader.Skip(1);
while (true)
{
BYTE _command = oReader.ReadByte();
if (251 == _command)
break;
switch (_command)
{
case 0:
{
oReader.Skip(5 + (4 * 4));
break;
}
case 1:
{
oReader.Skip(1 + (6 * 4));
break;
}
case 2:
{
LONG lColorsCount = (LONG)oReader.ReadInt();
if (0 <= lColorsCount)
oReader.SkipInt(2 * lColorsCount);
break;
}
default:
{
break;
}
};
}
break;
}
case ctBrushTextureMode:
{
oReader.Skip(1);
break;
}
case ctBrushTextureAlpha:
{
oReader.Skip(1);
break;
}
case ctSetTransform:
{
oReader.SkipInt(6);
break;
}
case ctPathCommandStart:
{
break;
}
case ctPathCommandMoveTo:
{
oReader.SkipInt(2);
break;
}
case ctPathCommandLineTo:
{
oReader.SkipInt(2);
break;
}
case ctPathCommandCurveTo:
{
oReader.SkipInt(6);
break;
}
case ctPathCommandClose:
{
break;
}
case ctPathCommandEnd:
{
break;
}
case ctDrawPath:
{
oReader.SkipInt();
break;
}
case ctDrawImageFromFile:
{
int nLen = oReader.ReadInt();
oReader.SkipString16(nLen);
oReader.SkipInt(4);
break;
}
case ctFontName:
{
int nLen = 2 * (int)oReader.ReadUShort();
oReader.SkipString16(nLen);
break;
}
case ctFontSize:
{
oReader.SkipInt();
break;
}
case ctFontStyle:
{
oReader.SkipInt();
break;
}
case ctDrawText:
{
int nLen = 2 * (int)oReader.ReadUShort();
oReader.SkipString16(nLen);
oReader.SkipInt(2);
break;
}
case ctDrawTextCodeGid:
{
oReader.SkipInt();
oReader.SkipDouble(2);
int nCountUnicodes = oReader.ReadInt();
oReader.SkipInt(nCountUnicodes);
break;
}
case ctBeginCommand:
{
oReader.SkipInt();
break;
}
case ctEndCommand:
{
oReader.SkipInt();
break;
}
case ctGradientFill:
case ctGradientFillXML:
case ctGradientStroke:
case ctGradientStrokeXML:
{
// TODO: Эта команда не должна приходить
return;
}
case ctHyperlink:
{
oReader.SkipDouble(4);
oReader.SkipString();
oReader.SkipString();
break;
}
case ctLink:
{
oReader.SkipDouble(6);
oReader.SkipInt();
break;
}
case ctDocInfo:
{
int nFlags = oReader.ReadInt();
if (nFlags & 1)
oReader.SkipString();
if (nFlags & 2)
oReader.SkipString();
if (nFlags & 4)
oReader.SkipString();
if (nFlags & 8)
oReader.SkipString();
break;
}
case ctFormField:
case ctAnnotField:
case ctAnnotFieldDelete:
case ctWidgetsInfo:
case ctShapeStart:
case ctShapeEnd:
case ctPageRotate:
case ctHeadings:
default:
{
BYTE* cur = oReader.GetCurrentBuffer();
oReader.SetCurrentBuffer(cur + oReader.ReadInt());
break;
}
}; // switch (eCommand)
} // while (curindex < len)
}
}