Files
core/HtmlRenderer/src/SVGWriter2.h
Oleg Korshul 245dfe198a Fix bug 45336
2020-06-29 11:55:04 +03:00

1947 lines
60 KiB
C++
Raw 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-2019
*
* 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-12 Ernesta Birznieka-Upisha
* 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
*
*/
#ifndef _ASC_HTMLRENDERER_SVGWRITER2_H_
#define _ASC_HTMLRENDERER_SVGWRITER2_H_
#include "Common2.h"
#include "SVGWriter.h"
#include "../../DesktopEditor/graphics/pro/Graphics.h"
#define SVG_INLINE_MAX_SIZE 500000 // 500Kb
#define SVG_TO_RASTER_MIN_SIZE 50000000 // 1Mb
const long c_nClipType2 = 0x0021; // c_nClipType + 1
namespace NSHtmlRenderer
{
#define USE_SIMPLE_GRAPHICS_NOSVG
//#define USE_BIG_GRAPHICS_TORASTER // разкоментировать, как научимся скидывать в растр!!! (пока свг не кроссплатформенный)
class CRendererGr
{
public:
NSGraphics::IGraphicsRenderer* m_pRenderer;
CBgraFrame* m_pFrame;
double m_dWidth;
double m_dHeight;
LONG m_lWidthPix;
LONG m_lHeightPix;
bool m_bIsRasterNeed;
public:
CRendererGr()
{
m_pRenderer = NULL;
m_pFrame = NULL;
m_dWidth = -1;
m_dHeight = -1;
m_lWidthPix = -1;
m_lHeightPix = -1;
}
~CRendererGr()
{
RELEASEOBJECT(m_pRenderer);
RELEASEOBJECT(m_pFrame);
}
inline void UncheckRaster()
{
m_bIsRasterNeed = false;
}
inline void CheckRasterNeed(const bool& bIsRaster)
{
if (!m_bIsRasterNeed)
m_bIsRasterNeed = bIsRaster;
}
void CheckRaster(double dWidth, double dHeight)
{
if (dWidth != m_dWidth || dHeight != m_dHeight)
{
RELEASEOBJECT(m_pFrame);
m_dWidth = dWidth;
m_dHeight = dHeight;
}
RELEASEOBJECT(m_pRenderer);
m_lWidthPix = (LONG)(96 * m_dWidth / 25.4);
m_lHeightPix = (LONG)(96 * m_dHeight / 25.4);
if (NULL == m_pFrame)
{
m_pFrame = new CBgraFrame();
m_pFrame->put_Width((int)m_lWidthPix);
m_pFrame->put_Height((int)m_lHeightPix);
m_pFrame->put_Stride(4 * ((int)m_lWidthPix));
BYTE* pData = new BYTE[4 * m_lWidthPix * m_lHeightPix];
memset(pData, 0xFF, 4 * m_lWidthPix * m_lHeightPix);
m_pFrame->put_Data(pData);
}
m_pRenderer = NSGraphics::Create();
m_pRenderer->put_Width(m_dWidth);
m_pRenderer->put_Height(m_dHeight);
m_pRenderer->CreateFromBgraFrame(m_pFrame);
}
template<typename T>
void CheckRasterData(T pPage, double& dWidth, double& dHeight)
{
if (m_bIsRasterNeed)
{
CheckRaster(dWidth, dHeight);
GetRasterData(pPage);
}
UncheckRaster();
}
template<typename T>
void GetRasterData(T pPage)
{
// определяем размеры картинки
if (NULL == m_pFrame)
return;
BYTE* pBuffer = m_pFrame->get_Data();
RECT rect = GetImageBounds(m_pFrame);
if (((rect.right - rect.left) < 5) && ((rect.bottom - rect.top) < 5))
return;
BYTE* pBufferSrcMem = pBuffer + 4 * rect.top * m_lWidthPix + 4 * rect.left;
LONG lWidthShape = rect.right - rect.left + 1;
LONG lHeightShape = rect.bottom - rect.top + 1;
CBgraFrame* pShapePicture = new CBgraFrame();
pShapePicture->put_Width((int)lWidthShape);
pShapePicture->put_Height((int)lHeightShape);
pShapePicture->put_Stride(4 * ((int)lWidthShape));
BYTE* pBufferDst = new BYTE[4 * lWidthShape * lHeightShape];
m_pFrame->put_Data(pBufferDst);
for (LONG lLine = 0; lLine < lHeightShape; ++lLine)
{
memcpy(pBufferDst, pBufferSrcMem, 4 * lWidthShape);
pBufferDst += 4 * lWidthShape;
pBufferSrcMem += 4 * m_lWidthPix;
}
double dL = 25.4 * rect.left / 96.0;
double dT = 25.4 * rect.top / 96.0;
double dW = 25.4 * lWidthShape / 96.0;
double dH = 25.4 * lHeightShape / 96.0;
double dHeightMM = 25.4 * m_lWidthPix / 96.0;
dT = (dHeightMM - dT - dH);
pPage->WriteImage(pShapePicture, dL, dT, dW, dH);
RELEASEOBJECT(pShapePicture);
}
};
class CDoubleBounds
{
public:
bool IsCleared;
double x;
double y;
double r;
double b;
public:
CDoubleBounds()
{
Clear();
}
void Clear()
{
IsCleared = true;
x = 10000000.0;
y = 10000000.0;
r = -10000000.0;
b = -10000000.0;
}
inline void CheckPoint(const double& _x, const double& _y)
{
IsCleared = false;
if (x > _x)
x = _x;
if (y > _y)
y = _y;
if (r < _x)
r = _x;
if (b < _y)
b = _y;
}
inline void Intersect(const CDoubleBounds& oBounds)
{
if (IsCleared)
{
x = oBounds.x;
y = oBounds.y;
r = oBounds.r;
b = oBounds.b;
IsCleared = false;
}
else
{
if (oBounds.x > x)
x = oBounds.x;
if (oBounds.y > y)
y = oBounds.y;
if (oBounds.r < r)
r = oBounds.r;
if (oBounds.b < b)
b = oBounds.b;
}
}
};
class CSVGWriter2
{
public:
NSStringUtils::CStringBuilder m_oPath;
NSStringUtils::CStringBuilder m_oDocument;
LONG m_lCurDocumentID;
LONG m_lClippingPath;
LONG m_lPatternID;
bool m_bIsClipping;
bool m_bIsNeedUpdateClip;
LONG m_lClipMode;
NSStructures::CPen* m_pPen;
NSStructures::CBrush* m_pBrush;
NSStructures::CPen* m_pLastPen;
NSStructures::CBrush* m_pLastBrush;
Aggplus::CMatrix* m_pTransform;
int m_lWidth;
int m_lHeight;
double m_dDpiX;
double m_dDpiY;
CClipSVG2 m_oClip;
// здесь храним пат в координатах не трансформированных
// (чтобы, если заливки сложные - можно было делать трансформы
// непосредственно при использовании графического пути).
double* m_pCoordsArray;
unsigned int m_lCoordsSize;
double* m_pCoordsArrayCur;
unsigned int m_lCoordsSizeCur;
bool m_bIsCurveToExist;
BYTE* m_pPathTypes;
unsigned int m_lPathTypesSize;
BYTE* m_pPathTypesCur;
unsigned int m_lPathTypesSizeCur;
double m_dCoordsScaleX;
double m_dCoordsScaleY;
unsigned int m_lEmtyDocChecker;
BYTE* m_pBase64Code;
CDoubleBounds m_oTextClipBounds;
// переменная говорит о том, какой клип для текста записан сейчас
// если true - то послана команда ResetTextClipRect
// если false - то нет
bool m_bIsTextClipWriteCleared;
// были ли новые clip'ы
bool m_bIsIntersectNewClipRect;
// сохранение в растр. (если сложная заливка, или слишком большая векторная графика)
//CRendererGr m_oGrRenderer;
//Graphics::IASCMetafile* m_pGrRenderer;
// клип для картинок. для конвертации сложной векторной графики в растр
CMetafile m_oClipMetafile;
int m_nDEBUG_svg_index;
#ifdef USE_SIMPLE_GRAPHICS_NOSVG
CMetafile m_oVectors;
bool m_bIsSimpleGraphics;
bool m_bIsSimpleSetupBrush;
LONG m_lBrushColorOld;
LONG m_lBrushAlphaOld;
#endif
public:
CSVGWriter2() : m_oPath(), m_oDocument()
{
m_lCurDocumentID = 0;
m_lClippingPath = 0;
m_lPatternID = 0;
m_pPen = NULL;
m_pBrush = NULL;
m_pLastPen = NULL;
m_pLastBrush = NULL;
m_dDpiX = 96;
m_dDpiY = 96;
m_dCoordsScaleX = m_dDpiX / 25.4;
m_dCoordsScaleY = m_dDpiY / 25.4;
m_lClipMode = c_nClipRegionTypeWinding;
m_bIsClipping = false;
m_bIsNeedUpdateClip = false;
m_pCoordsArray = NULL;
m_lCoordsSize = 0;
m_pCoordsArrayCur = NULL;
m_lCoordsSizeCur = 0;
m_pPathTypes = NULL;
m_lPathTypesSize = 0;
m_pPathTypesCur = NULL;
m_lPathTypesSizeCur = 0;
m_lEmtyDocChecker = 0;
m_pBase64Code = new BYTE[2 * SVG_INLINE_MAX_SIZE];
m_bIsTextClipWriteCleared = true;
m_bIsIntersectNewClipRect = false;
m_bIsCurveToExist = false;
m_nDEBUG_svg_index = 0;
#ifdef USE_SIMPLE_GRAPHICS_NOSVG
m_bIsSimpleGraphics = true;
m_bIsSimpleSetupBrush = false;
m_lBrushColorOld = 0;
m_lBrushAlphaOld = 255;
#endif
}
~CSVGWriter2()
{
RELEASEARRAYOBJECTS(m_pBase64Code);
}
void ReInit()
{
m_bIsTextClipWriteCleared = true;
m_bIsIntersectNewClipRect = false;
m_oTextClipBounds.Clear();
m_oClip.Clear();
m_oPath.ClearNoAttack();
m_oDocument.ClearNoAttack();
m_lCurDocumentID = 0;
m_lClippingPath = 0;
m_lPatternID = 0;
m_dDpiX = 96;
m_dDpiY = 96;
m_lClipMode = c_nClipRegionTypeWinding;
m_bIsClipping = false;
m_bIsNeedUpdateClip = false;
}
void SetSettings(NSStructures::CPen* pPen, NSStructures::CBrush* pBrush)
{
m_pPen = pPen;
m_pBrush = pBrush;
}
void CloseFile(std::wstring strFile = L"")
{
if (!strFile.empty())
{
m_oDocument.WriteString(L"</svg>", 6);
NSFile::CFileBinary::SaveToFile(strFile, m_oDocument.GetData());
}
if (3000000 < m_oDocument.GetSize())
m_oDocument.Clear();
m_oDocument.ClearNoAttack();
m_oPath.ClearNoAttack();
m_oClip.Clear();
m_lClippingPath = 0;
m_lPatternID = 0;
m_bIsClipping = false;
}
std::wstring GetSVGXml()
{
m_oClip.WriteEnd(m_oDocument);
m_oDocument.WriteString(L"</svg>", 6);
return m_oDocument.GetData();
}
void DEBUG_DumpSVG(const std::wstring& sTempPath)
{
std::wstring sEndDebug = L"";
int nCountWriteClips = m_oClip.m_lCountWriteClips;
while (nCountWriteClips > 0)
{
sEndDebug += L"</g>\n";
--nCountWriteClips;
}
sEndDebug += L"</svg>";
m_nDEBUG_svg_index++;
std::wstring sDocument = m_oDocument.GetData() + sEndDebug;
NSFile::CFileBinary::SaveToFile(sTempPath + L"/svg_" + std::to_wstring(m_nDEBUG_svg_index) + L".svg", sDocument);
}
void CloseFile2(std::wstring strFile, bool bIsNeedEnd = true)
{
if (bIsNeedEnd)
{
m_oClip.WriteEnd(m_oDocument);
m_oDocument.WriteString(L"</svg>", 6);
}
NSFile::CFileBinary::SaveToFile(strFile, m_oDocument.GetData());
m_oDocument.ClearNoAttack();
m_oPath.ClearNoAttack();
if (m_bIsClipping)
{
m_bIsNeedUpdateClip = true;
}
m_lPatternID = 0;
}
int CloseFile3(NSHtmlRenderer::CMetafile* m_pMeta, bool bIsNeedEnd = true)
{
if (bIsNeedEnd)
{
m_oClip.WriteEnd(m_oDocument);
m_oDocument.WriteString(L"</svg>", 6);
}
BYTE* pDataSrc = NULL;
LONG nLenSrc = 0;
NSFile::CUtf8Converter::GetUtf8StringFromUnicode(m_oDocument.GetBuffer(), (LONG)m_oDocument.GetCurSize(), pDataSrc, nLenSrc);
char* pBase64 = NULL;
int nLenDst = 2 * SVG_INLINE_MAX_SIZE;
NSBase64::Base64Encode(pDataSrc, (int)nLenSrc, m_pBase64Code, &nLenDst);
RELEASEARRAYOBJECTS(pDataSrc);
m_pMeta->WriteLONG(nLenDst);
m_pMeta->Write(m_pBase64Code, nLenDst);
m_oDocument.ClearNoAttack();
m_oPath.ClearNoAttack();
if (m_bIsClipping)
{
m_bIsNeedUpdateClip = true;
}
m_lPatternID = 0;
return nLenDst;
}
void NewDocument(const double& dWidth, const double& dHeigth, const LONG& lPageNumber)
{
m_lWidth = (int)(dWidth * m_dCoordsScaleX);
m_lHeight = (int)(dHeigth * m_dCoordsScaleY);
m_oClip.m_lWidth = m_lWidth;
m_oClip.m_lHeight = m_lHeight;
m_lCurDocumentID = lPageNumber;
m_oDocument.ClearNoAttack();
m_oDocument.WriteString(L"<svg width=\"", 12);
m_oDocument.AddInt(m_lWidth);
m_oDocument.WriteString(L"px\" height=\"", 12);
m_oDocument.AddInt(m_lHeight);
m_oDocument.WriteString(L"px\" viewBox=\"0 0 ", 17);
m_oDocument.AddInt(m_lWidth);
m_oDocument.AddCharSafe(' ');
m_oDocument.AddInt(m_lHeight);
m_oDocument.WriteString(L"\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", 95);
m_oClip.Clear();
m_lClippingPath = 0;
m_bIsClipping = false;
m_bIsNeedUpdateClip = false;
m_lEmtyDocChecker = (unsigned int)m_oDocument.GetCurSize();
}
public:
inline void WritePathEnd()
{
m_bIsCurveToExist = false;
m_oPath.ClearNoAttack();
ClearVectorCoords();
}
inline void WritePathStart()
{
m_bIsCurveToExist = false;
m_oPath.ClearNoAttack();
ClearVectorCoords();
}
void WritePathClose()
{
CheckSizeVectorB();
*m_pPathTypesCur++ = 3;
++m_lPathTypesSizeCur;
/*
m_oPath.AddSize(2);
m_oPath.AddCharNoCheck('Z');
m_oPath.AddSpaceNoCheck();
*/
}
void WritePathMoveTo(const double& x, const double& y)
{
CheckSizeVectorB();
*m_pPathTypesCur++ = 0;
++m_lPathTypesSizeCur;
CheckSizeVectorD(2);
m_pCoordsArrayCur[0] = x;
m_pCoordsArrayCur[1] = y;
m_pTransform->TransformPoint(m_pCoordsArrayCur[0], m_pCoordsArrayCur[1]);
m_pCoordsArrayCur += 2;
m_lCoordsSizeCur += 2;
/*
m_oPath.AddSize(30);
m_oPath.AddCharNoCheck('M');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheck(round(x));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheck(round(y));
m_oPath.AddSpaceNoCheck();
*/
}
void WritePathLineTo(const double& x, const double& y)
{
if (0 == m_lPathTypesSizeCur)
{
WritePathMoveTo(x, y);
return;
}
CheckSizeVectorB();
*m_pPathTypesCur++ = 1;
++m_lPathTypesSizeCur;
CheckSizeVectorD(2);
m_pCoordsArrayCur[0] = x;
m_pCoordsArrayCur[1] = y;
m_pTransform->TransformPoint(m_pCoordsArrayCur[0], m_pCoordsArrayCur[1]);
if (fabs(m_pCoordsArray[m_lCoordsSizeCur - 2] - m_pCoordsArrayCur[0]) < 0.1 &&
fabs(m_pCoordsArray[m_lCoordsSizeCur - 1] - m_pCoordsArrayCur[1]) < 0.1)
{
// попали в текущую точку. не добавляем
--m_pPathTypesCur;
--m_lPathTypesSizeCur;
return;
}
m_pCoordsArrayCur += 2;
m_lCoordsSizeCur += 2;
/*
m_oPath.AddSize(30);
m_oPath.AddCharNoCheck('L');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheck(round(x));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheck(round(y));
m_oPath.AddSpaceNoCheck();
*/
}
void WritePathCurveTo(const double& x1, const double& y1, const double& x2, const double& y2, const double& x3, const double& y3)
{
if (0 == m_lPathTypesSizeCur)
WritePathMoveTo(x1, y1);
CheckSizeVectorB();
*m_pPathTypesCur++ = 2;
++m_lPathTypesSizeCur;
CheckSizeVectorD(6);
m_pCoordsArrayCur[0] = x1;
m_pCoordsArrayCur[1] = y1;
m_pCoordsArrayCur[2] = x2;
m_pCoordsArrayCur[3] = y2;
m_pCoordsArrayCur[4] = x3;
m_pCoordsArrayCur[5] = y3;
m_pTransform->TransformPoint(m_pCoordsArrayCur[0], m_pCoordsArrayCur[1]);
m_pTransform->TransformPoint(m_pCoordsArrayCur[2], m_pCoordsArrayCur[3]);
m_pTransform->TransformPoint(m_pCoordsArrayCur[4], m_pCoordsArrayCur[5]);
m_pCoordsArrayCur += 6;
m_lCoordsSizeCur += 6;
m_bIsCurveToExist = true;
/*
m_oPath.AddSize(80);
m_oPath.AddCharNoCheck('C');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheck(round(x1));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheck(round(y1));
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheck(round(x2));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheck(round(y2));
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheck(round(x3));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheck(round(y3));
m_oPath.AddSpaceNoCheck();
*/
}
void WriteDrawPath(LONG nType, Aggplus::CGraphicsPathSimpleConverter* pConverter, CImageInfo& oInfo)
{
if (m_lPathTypesSizeCur == 0)
return;
WriteClip();
#ifdef USE_SIMPLE_GRAPHICS_NOSVG
if (m_bIsClipping)
m_bIsSimpleGraphics = false;
#endif
if (0 == m_pPen->Alpha)
nType &= 0xFF00;
if (c_BrushTypeTexture == m_pBrush->Type)
{
if (0 == m_pBrush->TextureAlpha)
nType &= 0xFF;
}
else
{
if (0 == m_pBrush->Alpha1)
nType &= 0xFF;
}
bool bIsNeedTransform = true;
// первым делом нужно понять, будем ли мы трансформировать пути
if (nType > 0xFF && m_pBrush->Type == c_BrushTypeTexture)
{
bIsNeedTransform = false;
}
int nPenW = 1;
if (0 != m_pPen->Size)
{
if (!bIsNeedTransform)
{
nPenW = (int)(m_pPen->Size);
}
else
{
double _x1 = 0;
double _y1 = 0;
double _x2 = 1;
double _y2 = 1;
m_pTransform->TransformPoint(_x1, _y1);
m_pTransform->TransformPoint(_x2, _y2);
double dScaleTransform = sqrt(((_x2 - _x1) * (_x2 - _x1) + (_y2 - _y1) * (_y2 - _y1)) / 2) * m_dCoordsScaleX;
nPenW = (int)(m_pPen->Size * dScaleTransform);
}
}
bool bStroke = (0x01 == (0x01 & nType));
if (nPenW == 0 && bStroke)
nPenW = 1;
bool bFill = (0x01 < nType);
bool bIsLine = false;
#ifdef USE_SIMPLE_GRAPHICS_NOSVG
if (m_bIsSimpleGraphics)
{
if (bFill && ((0 != (nType & c_nEvenOddFillMode)) || m_pBrush->Type != c_BrushTypeSolid))
m_bIsSimpleGraphics = false;
if (bStroke && m_pPen->DashStyle != 0)
m_bIsSimpleGraphics = false;
}
if (m_bIsSimpleGraphics)
{
// пишем вектор и настройки brush/pen
m_oVectors.WriteCommandType(CMetafile::ctPathCommandStart);
WriteToPathToSimpleVector();
bIsLine = WriteToPathToSVGPath(false, (bFill && !bStroke) ? true : false);
if (bFill && !bIsLine)
{
if (!m_pLastBrush->IsEqual(m_pBrush))
{
if (!m_bIsSimpleSetupBrush)
{
m_lBrushColorOld = m_pLastBrush->Color1;
m_lBrushAlphaOld = m_pLastBrush->Alpha1;
m_bIsSimpleSetupBrush = true;
}
*m_pLastBrush = *m_pBrush;
m_oVectors.WriteCommandType(CMetafile::ctBrushColor1);
LONG lBGR = m_pBrush->Color1;
m_oVectors.WriteBYTE((BYTE)(lBGR & 0xFF));
m_oVectors.WriteBYTE((BYTE)((lBGR >> 8) & 0xFF));
m_oVectors.WriteBYTE((BYTE)((lBGR >> 16) & 0xFF));
m_oVectors.WriteBYTE((BYTE)m_pBrush->Alpha1);
}
}
else if (bIsLine)
{
LONG _C = m_pPen->Color;
LONG _A = m_pPen->Alpha;
double _W = m_pPen->Size;
m_pPen->Color = m_pBrush->Color1;
m_pPen->Alpha = m_pBrush->Alpha1;
m_pPen->Size = 1 / m_dCoordsScaleX;
if (!m_pLastPen->IsEqual(m_pPen))
{
*m_pLastPen = *m_pPen;
m_oVectors.WriteCommandType(CMetafile::ctPenColor);
LONG lBGR = m_pPen->Color;
m_oVectors.WriteBYTE((BYTE)(lBGR & 0xFF));
m_oVectors.WriteBYTE((BYTE)((lBGR >> 8) & 0xFF));
m_oVectors.WriteBYTE((BYTE)((lBGR >> 16) & 0xFF));
m_oVectors.WriteBYTE((BYTE)m_pPen->Alpha);
m_oVectors.WriteCommandType(CMetafile::ctPenSize);
m_oVectors.WriteDouble((double)nPenW / m_dCoordsScaleX);
}
m_pPen->Color = _C;
m_pPen->Alpha = _A;
m_pPen->Size = _W;
}
if (bStroke)
{
if (!m_pLastPen->IsEqual(m_pPen))
{
*m_pLastPen = *m_pPen;
m_oVectors.WriteCommandType(CMetafile::ctPenColor);
LONG lBGR = m_pPen->Color;
m_oVectors.WriteBYTE((BYTE)(lBGR & 0xFF));
m_oVectors.WriteBYTE((BYTE)((lBGR >> 8) & 0xFF));
m_oVectors.WriteBYTE((BYTE)((lBGR >> 16) & 0xFF));
m_oVectors.WriteBYTE((BYTE)m_pPen->Alpha);
m_oVectors.WriteCommandType(CMetafile::ctPenSize);
m_oVectors.WriteDouble((double)nPenW / m_dCoordsScaleX);
}
}
m_oVectors.WriteCommandType(CMetafile::ctDrawPath);
m_oVectors.WriteLONG(bIsLine ? 1 : nType);
m_oVectors.WriteCommandType(CMetafile::ctPathCommandStart);
}
else
{
bIsLine = WriteToPathToSVGPath(false, (bFill && !bStroke) ? true : false);
}
#else
bIsLine = WriteToPathToSVGPath(false, (bFill && !bStroke) ? true : false);
#endif
if (!bFill)
{
// stroke
m_oDocument.WriteString(L"<path style=\"fill:none;stroke:", 30);
if (bStroke)
m_oDocument.WriteHexColor3(m_pPen->Color);
else
m_oDocument.WriteString(L"none");
m_oDocument.WriteString(L";stroke-width:", 14);
m_oDocument.AddInt(nPenW);
m_oDocument.WriteString(L";stroke-opacity:", 16);
m_oDocument.AddDouble((double)m_pPen->Alpha / 255, 2);
if (m_pPen->DashStyle == 0)
m_oDocument.WriteString(L";\" ", 3);
else
m_oDocument.WriteString(L";stroke-dasharray: 2,2;\" ", 25);
WriteStyleClip();
m_oDocument.WriteString(L" d=\"", 4);
m_oDocument.Write(m_oPath);
m_oDocument.WriteString(L"\" />\n", 5);
return;
}
else if (c_BrushTypeTexture == m_pBrush->Type)
{
double x = 0;
double y = 0;
double w = 0;
double h = 0;
pConverter->PathCommandGetBounds(x, y, w, h);
if (m_pBrush->TextureMode == c_BrushTextureModeStretch || true)
{
// 1) пишем паттерн
double _tx = m_pTransform->tx() * m_dCoordsScaleX;
double _ty = m_pTransform->ty() * m_dCoordsScaleY;
double _w = w * m_dCoordsScaleX;
double _h = h * m_dCoordsScaleY;
m_oDocument.WriteString(L"<pattern id=\"pt", 15);
m_oDocument.AddInt(m_lPatternID);
m_oDocument.WriteString(L"\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width=\"", 51);
m_oDocument.AddInt(round(_w));
m_oDocument.WriteString(L"\" height=\"", 10);
m_oDocument.AddInt(round(_h));
m_oDocument.WriteString(L"\" viewBox=\"0 0 ", 15);
m_oDocument.AddInt(round(_w));
m_oDocument.AddCharSafe(' ');
m_oDocument.AddInt(round(_h));
m_oDocument.WriteString(L"\" transform=\"matrix(");
m_oDocument.AddDouble(m_pTransform->sx(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(m_pTransform->shy(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(m_pTransform->shx(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(m_pTransform->sy(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(_tx, 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(_ty, 3);
m_oDocument.WriteString(L")\"><image x=\"0\" y=\"0\" width=\"", 29);
m_oDocument.AddInt(round(_w));
m_oDocument.WriteString(L"\" height=\"", 10);
m_oDocument.AddInt(round(_h));
m_oDocument.WriteString(L"\" xlink:href=\"image", 19);
m_oDocument.AddInt(oInfo.m_lID);
if (itJPG == oInfo.m_eType)
m_oDocument.WriteString(L".jpg\" preserveAspectRatio=\"none\"/></pattern>", 44);
else
m_oDocument.WriteString(L".png\" preserveAspectRatio=\"none\"/></pattern>", 44);
}
else
{
// TODO:
}
m_oDocument.WriteString(L"<path style=\"fill:url(#pt", 25);
m_oDocument.AddInt(m_lPatternID);
m_oDocument.WriteString(L");fill-opacity:");
m_oDocument.AddDouble((double)m_pBrush->Alpha1 / 255, 2);
if (nType & c_nEvenOddFillMode)
m_oDocument.WriteString(L";fill-rule:evenodd;", 19);
else
m_oDocument.WriteString(L";fill-rule:nonzero;", 19);
if (!bStroke)
{
m_oDocument.WriteString(L"stroke:none;\" ", 14);
}
else
{
m_oDocument.WriteString(L"stroke:", 7);
m_oDocument.WriteHexColor3(m_pPen->Color);
m_oDocument.WriteString(L";stroke-width:", 14);
m_oDocument.AddInt(nPenW);
m_oDocument.WriteString(L";stroke-opacity:", 16);
m_oDocument.AddDouble((double)m_pPen->Alpha / 255, 2);
m_oDocument.WriteString(L"\" ", 2);
}
WriteStyleClip();
m_oDocument.WriteString(L" d=\"", 4);
m_oDocument.Write(m_oPath);
m_oDocument.WriteString(L"\" />\n", 5);
++m_lPatternID;
return;
}
int nColorBrush = ConvertColor(m_pBrush->Color1);
if (nType & c_nEvenOddFillMode)
{
#ifdef USE_SIMPLE_GRAPHICS_NOSVG
m_bIsSimpleGraphics = false;
#endif
}
if (!bStroke)
{
if (bIsLine)
{
m_oDocument.WriteString(L"<path style=\"fill:none;stroke:", 30);
m_oDocument.WriteHexColor3(m_pBrush->Color1);
m_oDocument.WriteString(L";stroke-width:", 14);
m_oDocument.AddInt(1);
m_oDocument.WriteString(L";stroke-opacity:", 16);
m_oDocument.AddDouble((double)m_pBrush->Alpha1 / 255, 2);
m_oDocument.WriteString(L";\" ", 3);
WriteStyleClip();
m_oDocument.WriteString(L" d=\"", 4);
m_oDocument.Write(m_oPath);
m_oDocument.WriteString(L"\" />\n", 5);
return;
}
m_oDocument.WriteString(L"<path style=\"fill:", 18);
m_oDocument.WriteHexColor3(m_pBrush->Color1);
m_oDocument.WriteString(L";fill-opacity:", 14);
m_oDocument.AddDouble((double)m_pBrush->Alpha1 / 255, 2);
if (nType & c_nEvenOddFillMode)
m_oDocument.WriteString(L";fill-rule:evenodd;stroke:none\" ", 32);
else
m_oDocument.WriteString(L";fill-rule:nonzero;stroke:none\" ", 32);
WriteStyleClip();
m_oDocument.WriteString(L" d=\"", 4);
m_oDocument.Write(m_oPath);
m_oDocument.WriteString(L"\" />\n", 5);
return;
}
m_oDocument.WriteString(L"<path style=\"fill:", 18);
m_oDocument.WriteHexColor3(m_pBrush->Color1);
m_oDocument.WriteString(L";fill-opacity:", 14);
m_oDocument.AddDouble((double)m_pBrush->Alpha1 / 255, 2);
if (nType & c_nEvenOddFillMode)
m_oDocument.WriteString(L";fill-rule:evenodd;stroke:", 26);
else
m_oDocument.WriteString(L";fill-rule:nonzero;stroke:", 26);
m_oDocument.WriteHexColor3(m_pPen->Color);
m_oDocument.WriteString(L";stroke-width:", 14);
m_oDocument.AddInt(nPenW);
m_oDocument.WriteString(L";stroke-opacity:", 16);
m_oDocument.AddDouble((double)m_pPen->Alpha / 255, 2);
m_oDocument.WriteString(L";\" ", 3);
WriteStyleClip();
m_oDocument.WriteString(L" d=\"", 4);
m_oDocument.Write(m_oPath);
m_oDocument.WriteString(L"\" />\n", 5);
}
void WritePathClip()
{
m_bIsClipping = true;
m_bIsNeedUpdateClip = true;
}
void WritePathClipEnd()
{
/*
if (1 == m_lPathTypesSizeCur && m_pPathTypes[0] <= 1)
{
// не надо клип делать. пат странен)
return;
}
else if (2 == m_lPathTypesSizeCur &&
((m_pPathTypes[0] == 0 || m_pPathTypes[1] == 0) && (m_pPathTypes[0] <= 1 && m_pPathTypes[1] <= 1)))
{
// пат все еще странен
return;
}
*/
m_oClip.WriteEnd(m_oDocument);
m_bIsIntersectNewClipRect = true;
WriteToPathToSVGPath(true);
if (0 == m_oPath.GetCurSize())
return;
m_oClip.m_arPaths.push_back(m_oPath.GetData());
m_oClip.m_arTypes.push_back(m_lClipMode);
}
void WritePathResetClip()
{
m_bIsClipping = false;
m_bIsNeedUpdateClip = false;
m_oClip.Clear();
m_oTextClipBounds.Clear();
m_oClipMetafile.ClearNoAttack();
m_oClip.WriteEnd(m_oDocument);
}
void WriteImage(CImageInfo& oInfo, const double& x, const double& y, const double& w, const double& h)
{
bool bIsClipping = false;
if ((1 < h) && (1 < w))
{
WriteClip();
bIsClipping = m_bIsClipping;
}
double dCentreX = x + w / 2.0;
double dCentreY = y + h / 2.0;
bool bIsNoNeedTransform = m_pTransform->IsIdentity2(0.0001);
if (bIsNoNeedTransform)
{
double _x = x + m_pTransform->tx();
double _y = y + m_pTransform->ty();
_x *= m_dCoordsScaleX;
_y *= m_dCoordsScaleY;
double _w = w * m_dCoordsScaleX;
double _h = h * m_dCoordsScaleY;
if (itJPG == oInfo.m_eType)
{
/*if (bIsClipping)
{
//("<image x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" clip-path=\"url(#clip%d)\" xlink:href=\"image%d.jpg\" preserveAspectRatio=\"none\"/>");
strImage.Format(g_svg_string_image_clip_jpg1, round(_x), round(_y), round(_w), round(_h), m_lClippingPath - 1, oInfo.m_lID);
}
else*/
{
m_oDocument.WriteString(L"<image x=\"", 10);
m_oDocument.AddInt(round(_x));
m_oDocument.WriteString(L"\" y=\"", 5);
m_oDocument.AddInt(round(_y));
m_oDocument.WriteString(L"\" width=\"", 9);
m_oDocument.AddInt( round(_w));
m_oDocument.WriteString(L"\" height=\"", 10);
m_oDocument.AddInt( round(_h));
m_oDocument.WriteString(L"\" xlink:href=\"image", 19);
m_oDocument.AddInt(oInfo.m_lID);
m_oDocument.WriteString(L".jpg\" preserveAspectRatio=\"none\"/>", 34);
}
}
else
{
/*if (bIsClipping)
{
//("<image x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" clip-path=\"url(#clip%d)\" xlink:href=\"image%d.png\" preserveAspectRatio=\"none\"/>");
strImage.Format(g_svg_string_image_clip_png1, round(_x), round(_y), round(_w), round(_h), m_lClippingPath - 1, oInfo.m_lID);
}
else*/
{
m_oDocument.WriteString(L"<image x=\"", 10);
m_oDocument.AddInt(round(_x));
m_oDocument.WriteString(L"\" y=\"", 5);
m_oDocument.AddInt(round(_y));
m_oDocument.WriteString(L"\" width=\"", 9);
m_oDocument.AddInt( round(_w));
m_oDocument.WriteString(L"\" height=\"", 10);
m_oDocument.AddInt( round(_h));
m_oDocument.WriteString(L"\" xlink:href=\"image", 19);
m_oDocument.AddInt(oInfo.m_lID);
m_oDocument.WriteString(L".png\" preserveAspectRatio=\"none\"/>", 34);
}
}
}
else
{
double _tx = m_pTransform->tx() * m_dCoordsScaleX;
double _ty = m_pTransform->ty() * m_dCoordsScaleY;
double _x = x * m_dCoordsScaleX;
double _y = y * m_dCoordsScaleY;
double _w = w * m_dCoordsScaleX;
double _h = h * m_dCoordsScaleY;
if (itJPG == oInfo.m_eType)
{
/*if (bIsClipping)
{
//_T("<image x=\"%.3lf\" y=\"%.3lf\" width=\"%.3lf\" height=\"%.3lf\" clip-path=\"url(#clip%d)\" xlink:href=\"image%d.jpg\" preserveAspectRatio=\"none\" transform=\"matrix(%.3lf, %.3lf,%.3lf,%.3lf, %.3lf,%.3lf)\"/>");
strImage.Format(g_svg_string_image_clip_jpg_mtx, _x, _y, _w, _h, m_lClippingPath - 1, oInfo.m_lID, mtx->sx, mtx->shy, mtx->shx, mtx->sy, _tx, _ty);
}
else*/
{
m_oDocument.WriteString(L"<image x=\"", 10);
m_oDocument.AddDouble(_x, 3);
m_oDocument.WriteString(L"\" y=\"", 5);
m_oDocument.AddDouble(_y, 3);
m_oDocument.WriteString(L"\" width=\"", 9);
m_oDocument.AddDouble(_w, 3);
m_oDocument.WriteString(L"\" height=\"", 10);
m_oDocument.AddDouble(_h, 3);
m_oDocument.WriteString(L"\" xlink:href=\"image", 19);
m_oDocument.AddInt(oInfo.m_lID);
m_oDocument.WriteString(L".jpg\" preserveAspectRatio=\"none\" transform=\"matrix(/>", 53);
m_oDocument.AddDouble(m_pTransform->sx(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(m_pTransform->shy(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(m_pTransform->shx(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(m_pTransform->sy(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(_tx, 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(_ty, 3);
m_oDocument.WriteString(L")\"/>", 4);
}
}
else
{
/*if (bIsClipping)
{
//_T("<image x=\"%.3lf\" y=\"%.3lf\" width=\"%.3lf\" height=\"%.3lf\" clip-path=\"url(#clip%d)\" xlink:href=\"image%d.jpg\" preserveAspectRatio=\"none\" transform=\"matrix(%.3lf, %.3lf,%.3lf,%.3lf, %.3lf,%.3lf)\"/>");
strImage.Format(g_svg_string_image_clip_png_mtx, _x, _y, _w, _h, m_lClippingPath - 1, oInfo.m_lID, mtx->sx, mtx->shy, mtx->shx, mtx->sy, _tx, _ty);
}
else*/
{
m_oDocument.WriteString(L"<image x=\"", 10);
m_oDocument.AddDouble(_x, 3);
m_oDocument.WriteString(L"\" y=\"", 5);
m_oDocument.AddDouble(_y, 3);
m_oDocument.WriteString(L"\" width=\"", 9);
m_oDocument.AddDouble(_w, 3);
m_oDocument.WriteString(L"\" height=\"", 10);
m_oDocument.AddDouble(_h, 3);
m_oDocument.WriteString(L"\" xlink:href=\"image", 19);
m_oDocument.AddInt(oInfo.m_lID);
m_oDocument.WriteString(L".png\" preserveAspectRatio=\"none\" transform=\"matrix(/>", 53);
m_oDocument.AddDouble(m_pTransform->sx(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(m_pTransform->shy(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(m_pTransform->shx(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(m_pTransform->sy(), 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(_tx, 3);
m_oDocument.AddCharSafe(',');
m_oDocument.AddDouble(_ty, 3);
m_oDocument.WriteString(L")\"/>", 4);
}
}
}
}
inline void WriteClip()
{
if (m_bIsClipping && m_bIsNeedUpdateClip && (m_oClip.IsInit()))
{
m_oClip.Write(m_oDocument, m_lClippingPath);
//m_oClip.Clear();
m_bIsNeedUpdateClip = false;
}
}
inline void WriteStyleClip()
{
// сейчас не пишем (оборачиваем в g)
return;
if (m_bIsClipping)
{
//_T("clip-path=\"url(#clip%d)\" ");
m_oDocument.WriteString(L"clip-path=\"url(#clip", 20);
m_oDocument.AddInt(m_lClippingPath - 1);
m_oDocument.WriteString(L")\" ", 3);
}
}
void CheckSizeVectorB(const int& len = 1)
{
if (NULL != m_pPathTypes)
{
unsigned int nNewSize = (unsigned int)(m_lPathTypesSizeCur + len);
if (nNewSize >= m_lPathTypesSize)
{
if (nNewSize >= m_lPathTypesSize)
{
while (nNewSize >= m_lPathTypesSize)
{
m_lPathTypesSize *= 2;
}
BYTE* pNew = new BYTE[m_lPathTypesSize];
memcpy(pNew, m_pPathTypes, m_lPathTypesSizeCur);
RELEASEARRAYOBJECTS(m_pPathTypes);
m_pPathTypes = pNew;
m_pPathTypesCur = m_pPathTypes + m_lPathTypesSizeCur;
}
}
}
else
{
m_lPathTypesSize = 1000;
m_pPathTypes = new BYTE[m_lPathTypesSize];
m_pPathTypesCur = m_pPathTypes;
m_lPathTypesSizeCur = 0;
}
}
void CheckSizeVectorD(const int& len)
{
if (NULL != m_pCoordsArray)
{
unsigned int nNewSize = (unsigned int)(m_lCoordsSizeCur + len);
if (nNewSize >= m_lCoordsSize)
{
while (nNewSize >= m_lCoordsSize)
{
m_lCoordsSize *= 2;
}
double* pNew = new double[m_lCoordsSize];
memcpy(pNew, m_pCoordsArray, m_lCoordsSizeCur * sizeof(double));
RELEASEARRAYOBJECTS(m_pCoordsArray);
m_pCoordsArray = pNew;
m_pCoordsArrayCur = m_pCoordsArray + m_lCoordsSizeCur;
}
}
else
{
m_lCoordsSize = 1000;
m_pCoordsArray = new double[m_lCoordsSize];
m_pCoordsArrayCur = m_pCoordsArray;
m_lCoordsSizeCur = 0;
}
}
void ClearVectorCoords()
{
m_lCoordsSizeCur = 0;
m_pCoordsArrayCur = m_pCoordsArray;
m_lPathTypesSizeCur = 0;
m_pPathTypesCur = m_pPathTypes;
}
bool WriteToPathToSVGPath(bool bIsClipping = false, bool bIsNeedAnalyzeLine = false)
{
m_oPath.ClearNoAttack();
CDoubleBounds oBounds;
if (!bIsNeedAnalyzeLine)
{
unsigned int lSize = m_lCoordsSizeCur;
for (unsigned int i = 0; i < lSize; i += 2)
{
if (bIsClipping)
{
oBounds.CheckPoint(m_pCoordsArray[i], m_pCoordsArray[i + 1]);
}
m_pCoordsArray[i] *= m_dCoordsScaleX;
m_pCoordsArray[i + 1] *= m_dCoordsScaleY;
}
}
else
{
if (!bIsClipping && m_lPathTypesSizeCur <= 4 && !m_bIsCurveToExist)
{
unsigned int lSize = m_lCoordsSizeCur;
for (unsigned int i = 0; i < lSize; i += 2)
{
m_pCoordsArray[i] *= m_dCoordsScaleX;
m_pCoordsArray[i + 1] *= m_dCoordsScaleY;
}
switch (m_lPathTypesSizeCur)
{
case 2:
{
if (0 == m_pPathTypes[0] && 1 == m_pPathTypes[1])
{
m_oPath.AddSize(60);
m_oPath.AddCharNoCheck('M');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[0]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[1]));
m_oPath.AddSpaceNoCheck();
m_oPath.AddCharNoCheck('L');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[2]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[3]));
m_oPath.AddSpaceNoCheck();
return true;
}
break;
}
case 3:
{
if (0 == m_pPathTypes[0] && 1 == m_pPathTypes[1])
{
if (3 == m_pPathTypes[2])
{
m_oPath.AddSize(60);
m_oPath.AddCharNoCheck('M');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[0]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[1]));
m_oPath.AddSpaceNoCheck();
m_oPath.AddCharNoCheck('L');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[2]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[3]));
m_oPath.AddSpaceNoCheck();
return true;
}
else
{
if ((fabs(m_pCoordsArray[4] - m_pCoordsArray[0]) < 0.2) &&
(fabs(m_pCoordsArray[5] - m_pCoordsArray[1]) < 0.2))
{
m_oPath.AddSize(60);
m_oPath.AddCharNoCheck('M');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[0]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[1]));
m_oPath.AddSpaceNoCheck();
m_oPath.AddCharNoCheck('L');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[2]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[3]));
m_oPath.AddSpaceNoCheck();
return true;
}
else if ((fabs(m_pCoordsArray[2] - m_pCoordsArray[0]) < 0.2) &&
(fabs(m_pCoordsArray[3] - m_pCoordsArray[1]) < 0.2))
{
m_oPath.AddSize(60);
m_oPath.AddCharNoCheck('M');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[0]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[1]));
m_oPath.AddSpaceNoCheck();
m_oPath.AddCharNoCheck('L');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[4]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[5]));
m_oPath.AddSpaceNoCheck();
return true;
}
}
}
break;
}
case 4:
{
if (0 == m_pPathTypes[0] && 1 == m_pPathTypes[1] && 1 == m_pPathTypes[2])
{
if ((fabs(m_pCoordsArray[4] - m_pCoordsArray[0]) < 0.2) &&
(fabs(m_pCoordsArray[5] - m_pCoordsArray[1]) < 0.2))
{
if (3 == m_pPathTypes[3])
{
m_oPath.AddSize(60);
m_oPath.AddCharNoCheck('M');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[0]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[1]));
m_oPath.AddSpaceNoCheck();
m_oPath.AddCharNoCheck('L');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[2]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[3]));
m_oPath.AddSpaceNoCheck();
return true;
}
else if (1 == m_pPathTypes[3] && ((fabs(m_pCoordsArray[6] - m_pCoordsArray[2]) < 0.2) &&
(fabs(m_pCoordsArray[7] - m_pCoordsArray[3]) < 0.2)))
{
m_oPath.AddSize(60);
m_oPath.AddCharNoCheck('M');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[0]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[1]));
m_oPath.AddSpaceNoCheck();
m_oPath.AddCharNoCheck('L');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[2]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[3]));
m_oPath.AddSpaceNoCheck();
return true;
}
}
else if ((fabs(m_pCoordsArray[2] - m_pCoordsArray[0]) < 0.2) &&
(fabs(m_pCoordsArray[3] - m_pCoordsArray[1]) < 0.2))
{
if (3 == m_pPathTypes[3])
{
m_oPath.AddSize(60);
m_oPath.AddCharNoCheck('M');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[0]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[1]));
m_oPath.AddSpaceNoCheck();
m_oPath.AddCharNoCheck('L');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[4]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[5]));
m_oPath.AddSpaceNoCheck();
return true;
}
else if (1 == m_pPathTypes[3] && ((fabs(m_pCoordsArray[6] - m_pCoordsArray[2]) < 0.2) &&
(fabs(m_pCoordsArray[7] - m_pCoordsArray[3]) < 0.2)))
{
m_oPath.AddSize(60);
m_oPath.AddCharNoCheck('M');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[0]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[1]));
m_oPath.AddSpaceNoCheck();
m_oPath.AddCharNoCheck('L');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[4]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[5]));
m_oPath.AddSpaceNoCheck();
return true;
}
}
}
break;
}
default:
break;
}
}
else
{
unsigned int lSize = m_lCoordsSizeCur;
for (unsigned int i = 0; i < lSize; i += 2)
{
if (bIsClipping)
{
oBounds.CheckPoint(m_pCoordsArray[i], m_pCoordsArray[i + 1]);
}
m_pCoordsArray[i] *= m_dCoordsScaleX;
m_pCoordsArray[i + 1] *= m_dCoordsScaleY;
}
}
}
if (bIsClipping)
m_oTextClipBounds.Intersect(oBounds);
unsigned int lCurrentCoord = 0;
for (unsigned int nCommand = 0; nCommand < m_lPathTypesSizeCur; ++nCommand)
{
switch (m_pPathTypes[nCommand])
{
case 0:
{
m_oPath.AddSize(30);
m_oPath.AddCharNoCheck('M');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[lCurrentCoord++]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[lCurrentCoord++]));
m_oPath.AddSpaceNoCheck();
break;
}
case 1:
{
m_oPath.AddSize(30);
m_oPath.AddCharNoCheck('L');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[lCurrentCoord++]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[lCurrentCoord++]));
m_oPath.AddSpaceNoCheck();
break;
}
case 2:
{
m_oPath.AddSize(80);
m_oPath.AddCharNoCheck('C');
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[lCurrentCoord++]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[lCurrentCoord++]));
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[lCurrentCoord++]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[lCurrentCoord++]));
m_oPath.AddSpaceNoCheck();
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[lCurrentCoord++]));
m_oPath.AddCharNoCheck(',');
m_oPath.AddIntNoCheckDel10(round(10 * m_pCoordsArray[lCurrentCoord++]));
m_oPath.AddSpaceNoCheck();
break;
}
case 3:
{
m_oPath.AddSize(2);
m_oPath.AddCharNoCheck('Z');
m_oPath.AddSpaceNoCheck();
break;
}
default:
break;
}
}
if (bIsClipping)
{
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandStart);
m_oClipMetafile.WriteLONG(CMetafile::ctBeginCommand, c_nClipType);
lCurrentCoord = 0;
for (ULONG nCommand = 0; nCommand < m_lPathTypesSizeCur; ++nCommand)
{
switch (m_pPathTypes[nCommand])
{
case 0:
{
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandMoveTo);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++] / m_dCoordsScaleX);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++] / m_dCoordsScaleY);
break;
}
case 1:
{
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandLineTo);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++] / m_dCoordsScaleX);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++] / m_dCoordsScaleY);
break;
}
case 2:
{
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandCurveTo);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++] / m_dCoordsScaleX);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++] / m_dCoordsScaleY);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++] / m_dCoordsScaleX);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++] / m_dCoordsScaleY);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++] / m_dCoordsScaleX);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++] / m_dCoordsScaleY);
break;
}
case 3:
{
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandClose);
break;
}
default:
break;
}
}
m_oClipMetafile.WriteLONG(CMetafile::ctEndCommand, c_nClipType2);
m_oClipMetafile.WriteLONG(m_lClipMode);
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandEnd);
}
return false;
}
LONG WriteTempClip()
{
LONG nRet = m_oClipMetafile.GetPosition();
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandStart);
m_oClipMetafile.WriteLONG(CMetafile::ctBeginCommand, c_nClipType);
LONG lCurrentCoord = 0;
for (ULONG nCommand = 0; nCommand < m_lPathTypesSizeCur; ++nCommand)
{
switch (m_pPathTypes[nCommand])
{
case 0:
{
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandMoveTo);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
break;
}
case 1:
{
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandLineTo);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
break;
}
case 2:
{
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandCurveTo);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oClipMetafile.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
break;
}
case 3:
{
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandClose);
break;
}
default:
break;
}
}
m_oClipMetafile.WriteLONG(CMetafile::ctEndCommand, c_nClipType2);
m_oClipMetafile.WriteLONG(m_lClipMode);
m_oClipMetafile.WriteCommandType(CMetafile::ctPathCommandEnd);
return nRet;
}
#ifdef USE_SIMPLE_GRAPHICS_NOSVG
void WriteToPathToSimpleVector()
{
if (m_lPathTypesSizeCur <= 4 && !m_bIsCurveToExist)
{
switch (m_lPathTypesSizeCur)
{
case 2:
{
if (0 == m_pPathTypes[0] && 1 == m_pPathTypes[1])
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandMoveTo);
m_oVectors.WriteDouble(m_pCoordsArray[0]);
m_oVectors.WriteDouble(m_pCoordsArray[1]);
m_oVectors.WriteCommandType(CMetafile::ctPathCommandLineTo);
m_oVectors.WriteDouble(m_pCoordsArray[2]);
m_oVectors.WriteDouble(m_pCoordsArray[3]);
return;
}
break;
}
case 3:
{
if (0 == m_pPathTypes[0] && 1 == m_pPathTypes[1])
{
if (3 == m_pPathTypes[2])
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandMoveTo);
m_oVectors.WriteDouble(m_pCoordsArray[0]);
m_oVectors.WriteDouble(m_pCoordsArray[1]);
m_oVectors.WriteCommandType(CMetafile::ctPathCommandLineTo);
m_oVectors.WriteDouble(m_pCoordsArray[2]);
m_oVectors.WriteDouble(m_pCoordsArray[3]);
return;
}
else
{
if ((fabs(m_pCoordsArray[4] - m_pCoordsArray[0]) < 0.2) &&
(fabs(m_pCoordsArray[5] - m_pCoordsArray[1]) < 0.2))
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandMoveTo);
m_oVectors.WriteDouble(m_pCoordsArray[0]);
m_oVectors.WriteDouble(m_pCoordsArray[1]);
m_oVectors.WriteCommandType(CMetafile::ctPathCommandLineTo);
m_oVectors.WriteDouble(m_pCoordsArray[2]);
m_oVectors.WriteDouble(m_pCoordsArray[3]);
return;
}
else if ((fabs(m_pCoordsArray[2] - m_pCoordsArray[0]) < 0.2) &&
(fabs(m_pCoordsArray[3] - m_pCoordsArray[1]) < 0.2))
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandMoveTo);
m_oVectors.WriteDouble(m_pCoordsArray[0]);
m_oVectors.WriteDouble(m_pCoordsArray[1]);
m_oVectors.WriteCommandType(CMetafile::ctPathCommandLineTo);
m_oVectors.WriteDouble(m_pCoordsArray[4]);
m_oVectors.WriteDouble(m_pCoordsArray[5]);
return;
}
}
}
break;
}
case 4:
{
if (0 == m_pPathTypes[0] && 1 == m_pPathTypes[1] && 1 == m_pPathTypes[2])
{
if ((fabs(m_pCoordsArray[4] - m_pCoordsArray[0]) < 0.2) &&
(fabs(m_pCoordsArray[5] - m_pCoordsArray[1]) < 0.2))
{
if (3 == m_pPathTypes[3])
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandMoveTo);
m_oVectors.WriteDouble(m_pCoordsArray[0]);
m_oVectors.WriteDouble(m_pCoordsArray[1]);
m_oVectors.WriteCommandType(CMetafile::ctPathCommandLineTo);
m_oVectors.WriteDouble(m_pCoordsArray[2]);
m_oVectors.WriteDouble(m_pCoordsArray[3]);
return;
}
else if (1 == m_pPathTypes[3] && ((fabs(m_pCoordsArray[6] - m_pCoordsArray[2]) < 0.2) &&
(fabs(m_pCoordsArray[7] - m_pCoordsArray[3]) < 0.2)))
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandMoveTo);
m_oVectors.WriteDouble(m_pCoordsArray[0]);
m_oVectors.WriteDouble(m_pCoordsArray[1]);
m_oVectors.WriteCommandType(CMetafile::ctPathCommandLineTo);
m_oVectors.WriteDouble(m_pCoordsArray[2]);
m_oVectors.WriteDouble(m_pCoordsArray[3]);
return;
}
}
else if ((fabs(m_pCoordsArray[2] - m_pCoordsArray[0]) < 0.2) &&
(fabs(m_pCoordsArray[3] - m_pCoordsArray[1]) < 0.2))
{
if (3 == m_pPathTypes[3])
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandMoveTo);
m_oVectors.WriteDouble(m_pCoordsArray[0]);
m_oVectors.WriteDouble(m_pCoordsArray[1]);
m_oVectors.WriteCommandType(CMetafile::ctPathCommandLineTo);
m_oVectors.WriteDouble(m_pCoordsArray[4]);
m_oVectors.WriteDouble(m_pCoordsArray[5]);
return;
}
else if (1 == m_pPathTypes[3] && ((fabs(m_pCoordsArray[6] - m_pCoordsArray[2]) < 0.2) &&
(fabs(m_pCoordsArray[7] - m_pCoordsArray[3]) < 0.2)))
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandMoveTo);
m_oVectors.WriteDouble(m_pCoordsArray[0]);
m_oVectors.WriteDouble(m_pCoordsArray[1]);
m_oVectors.WriteCommandType(CMetafile::ctPathCommandLineTo);
m_oVectors.WriteDouble(m_pCoordsArray[4]);
m_oVectors.WriteDouble(m_pCoordsArray[5]);
return;
}
}
}
break;
}
default:
break;
}
}
unsigned int lCurrentCoord = 0;
for (unsigned int nCommand = 0; nCommand < m_lPathTypesSizeCur; ++nCommand)
{
switch (m_pPathTypes[nCommand])
{
case 0:
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandMoveTo);
m_oVectors.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oVectors.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
break;
}
case 1:
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandLineTo);
m_oVectors.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oVectors.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
break;
}
case 2:
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandCurveTo);
m_oVectors.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oVectors.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oVectors.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oVectors.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oVectors.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
m_oVectors.WriteDouble(m_pCoordsArray[lCurrentCoord++]);
break;
}
case 3:
{
m_oVectors.WriteCommandType(CMetafile::ctPathCommandClose);
break;
}
default:
break;
}
}
}
#endif
void CheckPathTextRect(CDoubleBounds& oBounds)
{
unsigned int lSize = m_lCoordsSizeCur;
for (unsigned int i = 0; i < lSize; i += 2)
{
oBounds.CheckPoint(m_pCoordsArray[i] * m_dCoordsScaleX, m_pCoordsArray[i + 1] * m_dCoordsScaleY);
}
}
inline void NewSVG()
{
m_oDocument.SetCurSize(m_lEmtyDocChecker);
#ifdef USE_SIMPLE_GRAPHICS_NOSVG
if (m_bIsSimpleSetupBrush && !m_bIsSimpleGraphics)
{
m_pLastBrush->Color1 = m_lBrushColorOld;
m_pLastBrush->Alpha1 = m_lBrushAlphaOld;
}
m_oVectors.ClearNoAttack();
m_bIsSimpleGraphics = true;
m_bIsSimpleSetupBrush = false;
#endif
}
};
}
#endif // _ASC_HTMLRENDERER_SVGWRITER2_H_