Commit 5c7a88b4 authored by Ilya.Kirillov's avatar Ilya.Kirillov Committed by Alexander Trofimov

Исправлен баг с тем что неработал клип у патов, немного переделана схема...

Исправлен баг с тем что неработал клип у патов, немного переделана схема работы со стеком трансформов, на манер клипов. Добавлен класс для чтения статических ресурсов, теперь отдельный файл читается только 1 раз, а не как раньше заново на каждой странице. Полностью переделан парсинг строки с патом, теперь он быстрый и делается за один проход строки. Удалены старые функции чтения Xml, теперь только новые через XmlLiteReader. Доработано чтение пунктирных линий, стилей окончания и соединения линий. 

git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@63410 954022d7-b5bf-4e40-9824-e11837661b57
parent a2f0d339
......@@ -13,6 +13,7 @@
#include "../../DesktopEditor/fontengine/ApplicationFonts.h"
#include <iostream>
#include <ctime>
std::vector<std::wstring> GetAllFilesInFolder(std::wstring wsFolder, std::wstring wsExt)
{
......@@ -99,9 +100,15 @@ void ConvertFolderToPdf(const std::wstring& wsFolderPath)
void main()
{
clock_t oBeginTime = clock();
//ConvertFolderToRaster(L"D:/Test Files//Xps//");
ConvertFolderToPdf(L"D:/Test Files//Xps//");
clock_t oEndTime = clock();
double dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC;
printf("%fseconds\n", dElapsedSecs);
char q;
std::cin >> q;
}
......@@ -6,35 +6,27 @@
namespace XPS
{
CContextState::CContextState() : m_oCurrentTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)
CContextState::CContextState(IRenderer* pRenderer) : m_oCurrentTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0), m_pRenderer(pRenderer)
{
m_lTransformStack.push_back(m_oCurrentTransform);
}
CContextState::~CContextState()
{
}
void CContextState::AddFigure(const std::wstring& wsKey, const std::wstring& wsValue)
{
m_mFigures.insert(std::pair<std::wstring, std::wstring>(wsKey, wsValue));
}
std::wstring CContextState::GetFigure(const std::wstring& wsKey)
{
std::map<std::wstring, std::wstring>::iterator oIter = m_mFigures.find(wsKey);
if (oIter != m_mFigures.end())
return oIter->second;
return L"";
m_vClipStack.clear();
m_lTransformStack.clear();
}
void CContextState::PushTransform(const double arrTransform[6])
{
Aggplus::CMatrix oTransform(arrTransform[0], arrTransform[1], arrTransform[2], arrTransform[3], arrTransform[4], arrTransform[5]);
m_oCurrentTransform.Multiply(&oTransform);
m_lTransformStack.push_back(m_oCurrentTransform);
SetTransformToRenderer();
}
void CContextState::PopTransform()
{
m_lTransformStack.pop_back();
m_oCurrentTransform = m_lTransformStack.back();
SetTransformToRenderer();
}
double CContextState::NormalizeTransform()
{
......@@ -46,13 +38,51 @@ namespace XPS
oMatrix.sy /= dDet;
oMatrix.shy /= dDet;
SetTransformToRenderer();
return dDet;
}
void CContextState::SetTransformToRenderer(IRenderer* pRenderer)
void CContextState::PushClip(const CWString& wsClip)
{
m_vClipStack.push_back(wsClip);
SetClipToRenderer(wsClip);
}
void CContextState::PopClip()
{
m_vClipStack.pop_back();
if (m_pRenderer)
{
m_pRenderer->BeginCommand(c_nResetClipType);
m_pRenderer->EndCommand(c_nResetClipType);
for (int nIndex = 0, nCount = m_vClipStack.size(); nIndex < nCount; nIndex++)
{
CWString wsClip = m_vClipStack.at(nIndex);
SetClipToRenderer(wsClip);
}
}
}
void CContextState::SetTransformToRenderer()
{
if (m_pRenderer)
{
pRenderer->SetTransform(m_oCurrentTransform.m_agg_mtx.sx, m_oCurrentTransform.m_agg_mtx.shy,
m_pRenderer->SetTransform(m_oCurrentTransform.m_agg_mtx.sx, m_oCurrentTransform.m_agg_mtx.shy,
m_oCurrentTransform.m_agg_mtx.shx, m_oCurrentTransform.m_agg_mtx.sy,
xpsUnitToMM(m_oCurrentTransform.m_agg_mtx.tx), xpsUnitToMM(m_oCurrentTransform.m_agg_mtx.ty));
}
}
void CContextState::SetClipToRenderer(const CWString& wsClip)
{
if (!wsClip.empty() && m_pRenderer)
{
m_pRenderer->PathCommandStart();
m_pRenderer->BeginCommand(c_nClipType);
m_pRenderer->BeginCommand(c_nPathType);
bool bWinding = VmlToRenderer(wsClip.c_str(), m_pRenderer);
m_pRenderer->put_ClipMode(bWinding ? c_nClipRegionTypeWinding : c_nClipRegionTypeEvenOdd);
m_pRenderer->EndCommand(c_nPathType);
m_pRenderer->EndCommand(c_nClipType);
m_pRenderer->PathCommandEnd();
}
}
}
\ No newline at end of file
#ifndef _XPS_XPSLIB_CONTEXTSTATE_H
#define _XPS_XPSLIB_CONTEXTSTATE_H
#include "Utils.h"
#include "../../DesktopEditor/graphics/Matrix.h"
#include "../../DesktopEditor/graphics/IRenderer.h"
......@@ -13,21 +15,26 @@ namespace XPS
{
public:
CContextState();
CContextState(IRenderer* pRenderer);
~CContextState();
void AddFigure(const std::wstring& wsKey, const std::wstring& wsName);
std::wstring GetFigure(const std::wstring& wsKey);
void PushClip(const CWString& wsClip);
void PopClip();
void PushTransform(const double arrTransform[6]);
void PopTransform();
double NormalizeTransform();
void SetTransformToRenderer(IRenderer* pRenderer);
public:
private:
void SetClipToRenderer(const CWString& wsClip);
void SetTransformToRenderer();
private:
Aggplus::CMatrix m_oCurrentTransform;
std::list<Aggplus::CMatrix> m_lTransformStack;
std::map<std::wstring, std::wstring> m_mFigures;
std::vector<CWString> m_vClipStack;
IRenderer* m_pRenderer;
};
}
......
......@@ -249,5 +249,24 @@ namespace XPS
}
m_mPages.clear();
m_oFontList.Clear();
for (std::map<std::wstring, CStaticResource*>::iterator oIter = m_mStaticResources.begin(); oIter != m_mStaticResources.end(); oIter++)
{
if (oIter->second)
delete oIter->second;
}
m_mStaticResources.clear();
}
CStaticResource* CDocument::GetStaticResource(const std::wstring& wsPath)
{
for (auto oIt : m_mStaticResources)
{
if (oIt.first == wsPath)
return oIt.second;
}
CStaticResource* pStaticResource = new CStaticResource(wsPath);
m_mStaticResources.insert(std::pair<std::wstring, CStaticResource*>(wsPath, pStaticResource));
return pStaticResource;
}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@
#include "FontList.h"
#include "Page.h"
#include <map>
#include <vector>
#define UNICODE
#define _UNICODE
......@@ -15,6 +16,8 @@
namespace XPS
{
class CPath;
class CStaticResource;
class CDocument
{
public:
......@@ -26,6 +29,7 @@ namespace XPS
void GetPageSize(int nPageIndex, int& nW, int& nH);
void DrawPage(int nPageIndex, IRenderer* pRenderer, bool* pbBreak);
void Close();
CStaticResource* GetStaticResource(const std::wstring& wsPath);
private:
......@@ -33,6 +37,101 @@ namespace XPS
std::map<int, XPS::Page*> m_mPages;
CFontList m_oFontList;
CFontManager* m_pFontManager;
std::map<std::wstring, CStaticResource*> m_mStaticResources;
};
class CStaticResource
{
public:
CStaticResource(const std::wstring& wsPath)
{
clock_t oBeginTime = clock();
XmlUtils::CXmlLiteReader oReader;
if (!oReader.FromFile(wsPath))
return;
Parse(oReader);
clock_t oEndTime = clock();
double dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC;
printf("\n\nSTATIC RESOURCE %S %fseconds\n\n", wsPath.c_str() , dElapsedSecs);
}
CStaticResource(XmlUtils::CXmlLiteReader& oReader)
{
if (oReader.IsEmptyNode())
return;
Parse(oReader);
}
~CStaticResource()
{
}
const wchar_t* Get(const wchar_t* wsKey)
{
CWString _wsKey((wchar_t*)wsKey, false);
std::map<CWString, CWString>::iterator oIter = m_mFigures.find(_wsKey);
if (oIter != m_mFigures.end())
return oIter->second.c_str();
return NULL;
}
const wchar_t* Get(CWString wsKey)
{
std::map<CWString, CWString>::iterator oIter = m_mFigures.find(wsKey);
if (oIter != m_mFigures.end())
return oIter->second.c_str();
return NULL;
}
private:
void Parse(XmlUtils::CXmlLiteReader& oReader)
{
CWString wsNodeName;
CWString wsAttrName;
int nCurDepth = oReader.GetDepth();
while (oReader.ReadNextSiblingNode(nCurDepth))
{
wsNodeName = oReader.GetName();
if (wsNodeName == L"PathGeometry")
{
CWString wsKey, wsValue;
if (oReader.MoveToFirstAttribute())
{
wsAttrName = oReader.GetName();
while (!wsAttrName.empty())
{
if (wsAttrName == L"x:Key")
wsKey.create(oReader.GetText(), true);
else if (wsAttrName == L"Figures")
wsValue.create(oReader.GetText(), true);
if (!oReader.MoveToNextAttribute())
break;
wsAttrName = oReader.GetName();
}
oReader.MoveToElement();
}
if (!wsKey.empty() && !wsValue.empty())
Add(wsKey, wsValue);
}
}
}
void Add(const CWString& wsKey, const CWString& wsValue)
{
m_mFigures.insert(std::pair<CWString, CWString>(wsKey, wsValue));
}
private:
std::map<CWString, CWString> m_mFigures;
};
}
......
......@@ -16,143 +16,6 @@
namespace XPS
{
static inline void PageCommandL(std::vector<std::wstring>& arrElements, double& dCurX, double& dCurY, IRenderer* pRenderer, int& nPos)
{
dCurX = GetDouble(arrElements[nPos + 1]);
dCurY = GetDouble(arrElements[nPos + 2]);
nPos += 2;
pRenderer->PathCommandLineTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
}
static inline void PageCommandA(std::vector<std::wstring>& arrElements, double& dCurX, double& dCurY, IRenderer* pRenderer, int& nPos)
{
Aggplus::CMatrix tmatx, rmatx, smatx, itmatx, irmatx, ismatx;
double x_cur_temp = dCurX;
double y_cur_temp = dCurY;
double x_end = GetDouble(arrElements[nPos + 6]);
double y_end = GetDouble(arrElements[nPos + 7]);
tmatx.Translate(-dCurX, -dCurY);
tmatx.TransformPoint(x_cur_temp, y_cur_temp);
tmatx.TransformPoint(x_end, y_end);
double angle = GetDouble(arrElements[nPos + 3]);
rmatx.Rotate(-angle);
rmatx.TransformPoint(x_cur_temp, y_cur_temp);
rmatx.TransformPoint(x_end, y_end);
double rx = GetDouble(arrElements[nPos + 1]);
double ry = GetDouble(arrElements[nPos + 2]);
smatx.Scale(ry / rx, 1);
smatx.TransformPoint(x_cur_temp, y_cur_temp);
smatx.TransformPoint(x_end, y_end);
double mid_x = (x_cur_temp + x_end) / 2.0, mid_y = (y_cur_temp + y_end) / 2.0;
double vect_x = x_end - x_cur_temp, vect_y = y_end - y_cur_temp;
double length = sqrt(vect_x * vect_x + vect_y * vect_y);
double halfChord = length / 2.0;
bool isLarge = GetBool(arrElements[nPos + 4]);
bool isCCW = !GetBool(arrElements[nPos + 5]);
double rotated_x, rotated_y;
if (isLarge == isCCW)
{
rotated_x = -vect_y;
rotated_y = vect_x;
}
else
{
rotated_x = vect_y;
rotated_y = -vect_x;
}
rotated_x = rotated_x / length;
rotated_y = rotated_y / length;
double centerDistance = sqrt(max(ry * ry - halfChord * halfChord, 0));
double center_x = mid_x + centerDistance * rotated_x, center_y = mid_y + centerDistance * rotated_y;
double angle1 = atan2(y_cur_temp - center_y, x_cur_temp - center_x);
double angle2 = atan2(y_end - center_y, x_end - center_x);
if ((!isCCW) && (abs(y_end - center_y) < 0.000001) && (x_end - center_x < 0))
angle2 = -M_PI;
if ((isCCW) && (abs(y_cur_temp - center_y) < 0.000001) && (x_cur_temp - center_x < 0))
angle1 = -M_PI;
if (isLarge == (abs(angle2 - angle1) < M_PI))
{
if (angle1 < angle2)
angle1 += 2 * M_PI;
else
angle2 += 2 * M_PI;
}
if (abs(angle2 - angle1) == M_PI)
{
if ((angle1 < angle2) && (isCCW) && (angle1 != -M_PI) && (angle1 != 0.0) && (angle1 != M_PI))
angle1 += 2 * M_PI;
}
itmatx.Translate(dCurX, dCurY);
irmatx.Rotate(angle);
ismatx.Scale(rx / ry, 1);
int max = (int)((4 * (rx + ry) * abs(angle2 - angle1) / (2 * M_PI)) / 1/*tolerance*/);
double x, y;
for (int counter = 0; counter <= max; counter++)
{
double angle_cur = ((max - counter) * angle1 + counter * angle2) / max;
x = center_x + ry * cos(angle_cur);
y = center_y + ry * sin(angle_cur);
// Transform the point back
ismatx.TransformPoint(x, y);
irmatx.TransformPoint(x, y);
itmatx.TransformPoint(x, y);
pRenderer->PathCommandLineTo(xpsUnitToMM(x), xpsUnitToMM(y));
}
dCurX = x;
dCurY = y;
nPos += 7;
}
static inline void PageCommandC(std::vector<std::wstring>& arrElements, double& dCurX, double& dCurY, double& dCpX, double& dCpY, IRenderer* pRenderer, int& nPos)
{
dCpX = GetDouble(arrElements[nPos + 3]);
dCpY = GetDouble(arrElements[nPos + 4]);
dCurX = GetDouble(arrElements[nPos + 5]);
dCurY = GetDouble(arrElements[nPos + 6]);
pRenderer->PathCommandCurveTo(xpsUnitToMM(GetDouble(arrElements[nPos + 1])), xpsUnitToMM(GetDouble(arrElements[nPos + 2])), xpsUnitToMM(dCpX), xpsUnitToMM(dCpY), xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
nPos += 6;
}
static inline void PageCommandQ(std::vector<std::wstring>& arrElements, double& dCurX, double& dCurY, IRenderer* pRenderer, int& nPos)
{
double x1 = 2.0 * GetDouble(arrElements[nPos + 1]);
double y1 = 2.0 * GetDouble(arrElements[nPos + 2]);
double x2 = GetDouble(arrElements[nPos + 3]);
double y2 = GetDouble(arrElements[nPos + 4]);
pRenderer->PathCommandCurveTo(xpsUnitToMM((dCurX + x1) / 3.0), xpsUnitToMM((dCurY + y1) / 3.0), xpsUnitToMM((x1 + x2) / 3.0), xpsUnitToMM((y1 + y2) / 3.0), xpsUnitToMM(x2), xpsUnitToMM(y2));
dCurX = x2;
dCurY = y2;
nPos += 4;
}
static inline void PageCommandS(std::vector<std::wstring>& arrElements, double& dCurX, double& dCurY, double& dCpX, double& dCpY, IRenderer* pRenderer, int& nPos)
{
dCpX = 2 * dCurX - dCpX;
dCpY = 2 * dCurY - dCpY;
dCurX = GetDouble(arrElements[nPos + 3]);
dCurY = GetDouble(arrElements[nPos + 4]);
pRenderer->PathCommandCurveTo(xpsUnitToMM(dCpX), xpsUnitToMM(dCpY),
xpsUnitToMM(GetDouble(arrElements[nPos + 1])), xpsUnitToMM(GetDouble(arrElements[nPos + 2])),
xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
dCpX = GetDouble(arrElements[nPos + 1]);
dCpY = GetDouble(arrElements[nPos + 2]);
nPos += 4;
}
Page::Page(const std::wstring& wsPagePath, const std::wstring& wsRootPath, CFontList* pFontList, CFontManager* pFontManager, CDocument* pDocument)
{
m_wsPagePath = wsPagePath;
......@@ -160,9 +23,16 @@ namespace XPS
m_pFontList = pFontList;
m_pFontManager = pFontManager;
m_pDocument = pDocument;
m_pStaticResource = NULL;
m_bDeleteStaticResource = false;
m_nCounter = 0;
}
Page::~Page()
{
if (m_bDeleteStaticResource)
RELEASEOBJECT(m_pStaticResource);
}
void Page::GetSize(int& nW, int& nH) const
{
......@@ -209,124 +79,29 @@ namespace XPS
if (L"FixedPage" != wsNodeName)
return;
CContextState oState;
CContextState oState(pRenderer);
DrawCanvas(oReader, pRenderer, &oState, pbBreak);
/*XmlUtils::CXmlNode oNode;
clock_t oBeginTime = clock();
if (!oNode.FromXmlFile(m_wsPagePath.c_str()))
return;
clock_t oEndTime = clock();
double dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC;
printf("%S %fseconds\n", m_wsPagePath.c_str(), dElapsedSecs);
if (L"FixedPage" != oNode.GetName())
return;
CContextState oState;
XmlUtils::CXmlNode oNodeResources;
if (oNode.GetNode(L"FixedPage.Resources", oNodeResources))
{
XmlUtils::CXmlNode oNodeDictionary;
if (oNodeResources.GetNode(L"ResourceDictionary", oNodeDictionary))
{
std::wstring wsXmlSource = oNodeDictionary.GetAttribute(L"Source");
if (L"" != wsXmlSource)
{
std::wstring wsPath = m_wsRootPath + wsXmlSource;
XmlUtils::CXmlNode oNodeSource;
clock_t oBeginTime = clock();
oNodeSource.FromXmlFile(wsPath.c_str());
clock_t oEndTime = clock();
double dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC;
printf("%S %fseconds\n", wsPath.c_str(), dElapsedSecs);
if (oNodeSource.IsValid())
{
XmlUtils::CXmlNodes arrNodes;
if (oNodeSource.GetNodes(L"PathGeometry", arrNodes))
{
for (int nIndex = 0, nCount = arrNodes.GetCount(); nIndex < nCount; nIndex++)
{
XmlUtils::CXmlNode oNode;
arrNodes.GetAt(nIndex, oNode);
std::wstring wsKey = oNode.GetAttribute(L"x:Key");
std::wstring wsValue = oNode.GetAttribute(L"Figures");
wsKey = L"{StaticResource " + wsKey + L"}";
oState.AddFigure(wsKey, wsValue);
}
}
}
}
else
{
XmlUtils::CXmlNodes arrNodes;
if (oNodeDictionary.GetNodes(L"PathGeometry", arrNodes))
{
for (int nIndex = 0, nCount = arrNodes.GetCount(); nIndex < nCount; nIndex++)
{
XmlUtils::CXmlNode oNode;
arrNodes.GetAt(nIndex, oNode);
std::wstring wsKey = oNode.GetAttribute(L"x:Key");
std::wstring wsValue = oNode.GetAttribute(L"Figures");
wsKey = (L"{StaticResource " + wsKey + L"}");
oState.AddFigure(wsKey, wsValue);
}
}
}
}
}
DrawCanvas(oNode, pRenderer, &oState, pbBreak);
return;*/
}
void Page::DrawCanvas(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState, bool* pbBreak)
{
std::wstring wsClip;
ReadAttribute(oReader, L"Clip", wsClip);
bool bClip = false;
if (L"" != wsClip)
bool bTransform = false, bClip = false;
if (oReader.MoveToFirstAttribute())
{
std::wstring wsValue = pState->GetFigure(wsClip);
if (L"" != wsValue)
wsClip = wsValue;
bClip = true;
pRenderer->PathCommandStart();
pRenderer->BeginCommand(c_nClipType);
pRenderer->put_ClipMode(0);
pRenderer->BeginCommand(c_nPathType);
CWString wsAttrName = oReader.GetName();
while (!wsAttrName.empty())
{
if (wsAttrName == L"Clip")
bClip = ClipToRenderer(oReader.GetText(), pState);
else if (wsAttrName == L"RenderTransform")
bTransform = TransformToRenderer(oReader.GetText(), pState);
VmlToRenderer(wsClip, pRenderer);
if (!oReader.MoveToNextAttribute())
break;
pRenderer->EndCommand(c_nPathType);
pRenderer->EndCommand(c_nClipType);
pRenderer->PathCommandEnd();
wsAttrName = oReader.GetName();
}
std::wstring wsTransform;
ReadAttribute(oReader, L"RenderTransform", wsTransform);
bool bTransform = false;
if (L"" != wsTransform)
{
bTransform = true;
TransformToRenderer(wsTransform, pRenderer, pState);
}
oReader.MoveToElement();
if (oReader.IsEmptyNode())
return;
......@@ -353,10 +128,7 @@ namespace XPS
else if (L"Canvas.RenderTransform" == wsNodeName)
{
if (!bTransform)
{
CanvasTransform(oReader, pRenderer, pState);
bTransform = true;
}
bTransform = ReadTransform(oReader, pRenderer, pState);
}
else if (L"Path" == wsNodeName)
{
......@@ -368,13 +140,10 @@ namespace XPS
}
if (bClip)
{
pRenderer->BeginCommand(c_nResetClipType);
pRenderer->EndCommand(c_nResetClipType);
}
pState->PopClip();
if (bTransform)
ResetTransform(pRenderer, pState);
pState->PopTransform();
}
void Page::ReadPageResources(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState)
{
......@@ -394,386 +163,47 @@ namespace XPS
{
std::wstring wsPath = m_wsRootPath + wsSource;
XmlUtils::CXmlLiteReader oSourceReader;
clock_t oBeginTime = clock();
if (!oSourceReader.FromFile(wsPath))
return;
std::wstring wsNodeText;
while (oSourceReader.ReadNextNode())
{
wsNodeName = oSourceReader.GetName();
if (L"PathGeometry" == wsNodeName)
{
std::wstring wsKey, wsValue;
if (oSourceReader.MoveToFirstAttribute())
{
std::wstring wsAttrName = oSourceReader.GetName();
while (!wsAttrName.empty())
{
if (L"x:Key" == wsAttrName)
wsKey = oSourceReader.GetText();
else if (L"Figures" == wsAttrName)
wsValue = oSourceReader.GetText();
if (!oSourceReader.MoveToNextAttribute())
break;
wsAttrName = oSourceReader.GetName();
}
oSourceReader.MoveToElement();
}
wsKey = L"{StaticResource " + wsKey + L"}";
pState->AddFigure(wsKey, wsValue);
}
}
clock_t oEndTime = clock();
double dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC;
printf("%S %fseconds\n", wsPath.c_str(), dElapsedSecs);
m_pStaticResource = m_pDocument->GetStaticResource(wsPath);
m_bDeleteStaticResource = false;
}
else
{
if (oReader.IsEmptyNode())
return;
int nPathDepth = oReader.GetDepth();
while (oReader.ReadNextSiblingNode(nPathDepth))
{
wsNodeName = oReader.GetName();
if (L"PathGeometry" == wsNodeName)
{
std::wstring wsKey, wsValue;
ReadAttribute(oReader, L"x:Key", wsKey);
ReadAttribute(oReader, L"Figures", wsValue);
wsKey = L"{StaticResource " + wsKey + L"}";
pState->AddFigure(wsKey, wsValue);
}
}
}
}
}
}
void Page::DrawCanvas(XmlUtils::CXmlNode& oCanvasNode, IRenderer* pRenderer, CContextState* pState, bool* pbBreak)
{
bool bClip = false;
std::wstring wsClip = oCanvasNode.GetAttribute(L"Clip", L"");
if (L"" != wsClip)
{
std::wstring wsValue = pState->GetFigure(wsClip);
if (L"" != wsValue)
wsClip = wsValue;
bClip = true;
pRenderer->PathCommandStart();
pRenderer->BeginCommand(c_nClipType);
pRenderer->put_ClipMode(0);
pRenderer->BeginCommand(c_nPathType);
VmlToRenderer(wsClip, pRenderer);
pRenderer->EndCommand(c_nPathType);
pRenderer->EndCommand(c_nClipType);
pRenderer->PathCommandEnd();
}
bool bTransform = false;
std::wstring wsTransform = oCanvasNode.GetAttribute(L"RenderTransform", L"");
if (L"" != wsTransform)
{
bTransform = true;
TransformToRenderer(wsTransform, pRenderer, pState);
}
XmlUtils::CXmlNodes arrNodes;
XmlUtils::CXmlNode oNode;
std::wstring wsNodeName;
oCanvasNode.GetNodes(L"*", arrNodes);
for (int nIndex = 0, nCount = arrNodes.GetCount(); nIndex < nCount; nIndex++)
{
arrNodes.GetAt(nIndex, oNode);
wsNodeName = oNode.GetName();
wsNodeName = RemoveNamespace(wsNodeName);
if (L"Glyphs" == wsNodeName)
DrawGlyph(oNode, pRenderer, pState);
else if (L"Canvas" == wsNodeName)
DrawCanvas(oNode, pRenderer, pState, pbBreak);
else if (L"Canvas.RenderTransform" == wsNodeName)
{
if (!bTransform)
{
CanvasTransform(oNode, pRenderer, pState);
bTransform = true;
}
}
else if (L"Path" == wsNodeName)
DrawPath(oNode, pRenderer, pState);
if (NULL != pbBreak)
{
if (*pbBreak)
return;
}
}
if (bClip)
{
pRenderer->BeginCommand(c_nResetClipType);
pRenderer->EndCommand(c_nResetClipType);
}
if (bTransform)
ResetTransform(pRenderer, pState);
}
bool Page::VmlToRenderer(std::wstring& wsString, IRenderer* pRenderer)
{
bool bResult = false;
double dCurX = 0.0, dCurY = 0.0;
double dCpX = 0.0, dCpY = 0.0;
bool bPrevCommandIsCurve = false;
PrepareVmlString(wsString);
std::vector<std::wstring> arrElements = NSString::Split(wsString, L" ,", false);
int nElementsCount = (int)arrElements.size();
for (int nPos = 0; nPos < nElementsCount; nPos++)
{
bPrevCommandIsCurve = false;
if (L"F" == arrElements[nPos])
{
bResult = GetBool(arrElements[nPos + 1]);
}
else if (L"M" == arrElements[nPos] || L"m" == arrElements[nPos])
{
dCurX = GetDouble(arrElements[nPos + 1]);
dCurY = GetDouble(arrElements[nPos + 2]);
nPos += 2;
pRenderer->PathCommandMoveTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
m_pStaticResource = new CStaticResource(oReader);
m_bDeleteStaticResource = true;
}
else if (L"L" == arrElements[nPos] || L"l" == arrElements[nPos])
{
PageCommandL(arrElements, dCurX, dCurY, pRenderer, nPos);
if (nPos + 2 < nElementsCount)
{
while ((nPos + 2 < nElementsCount) && (!IsAlpha(arrElements[nPos + 1][0])))
{
PageCommandL(arrElements, dCurX, dCurY, pRenderer, nPos);
}
}
}
else if (L"A" == arrElements[nPos] || L"a" == arrElements[nPos])
bool Page::ClipToRenderer(const wchar_t* wsString, CContextState* pState)
{
PageCommandA(arrElements, dCurX, dCurY, pRenderer, nPos);
if (nPos + 7 < nElementsCount)
CWString wsClip;
wsClip.create(wsString, true);
if (!wsClip.empty())
{
while ((nPos + 7 < nElementsCount) && (!IsAlpha(arrElements[nPos + 1][0])))
if ('{' == wsClip[0] && wsClip.size() >= 17)
{
PageCommandA(arrElements, dCurX, dCurY, pRenderer, nPos);
}
}
}
else if (L"H" == arrElements[nPos] || L"h" == arrElements[nPos])
{
dCurX = GetDouble(arrElements[nPos + 1]);
pRenderer->PathCommandLineTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
nPos += 1;
}
else if (L"V" == arrElements[nPos] || L"v" == arrElements[nPos])
{
dCurY = GetDouble(arrElements[nPos + 1]);
pRenderer->PathCommandLineTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
nPos += 1;
}
else if (L"C" == arrElements[nPos] || L"c" == arrElements[nPos])
{
PageCommandC(arrElements, dCurX, dCurY, dCpX, dCpY, pRenderer, nPos);
if (nPos + 6 < nElementsCount)
{
while ((nPos + 6 < nElementsCount) && (!IsAlpha(arrElements[nPos + 1][0])))
{
PageCommandC(arrElements, dCurX, dCurY, dCpX, dCpY, pRenderer, nPos);
}
}
bPrevCommandIsCurve = true;
}
else if (L"Q" == arrElements[nPos] || L"q" == arrElements[nPos])
{
PageCommandQ(arrElements, dCurX, dCurY, pRenderer, nPos);
if (nPos + 4 < nElementsCount)
{
while ((nPos + 4 < nElementsCount) && (!IsAlpha(arrElements[nPos + 1][0])))
{
PageCommandQ(arrElements, dCurX, dCurY, pRenderer, nPos);
}
}
}
else if (L"S" == arrElements[nPos] || L"s" == arrElements[nPos])
{
if ((!bPrevCommandIsCurve) || (nPos == 0))
{
dCpX = dCurX;
dCpY = dCurY;
}
PageCommandS(arrElements, dCurX, dCurY, dCpX, dCpY, pRenderer, nPos);
if (nPos + 4 < nElementsCount)
{
while ((nPos + 4 < nElementsCount) && (!IsAlpha(arrElements[nPos + 1][0])))
{
PageCommandS(arrElements, dCurX, dCurY, dCpX, dCpY, pRenderer, nPos);
}
}
bPrevCommandIsCurve = true;
}
else if (L"Z" == arrElements[nPos] || L"Z" == arrElements[nPos])
{
pRenderer->PathCommandClose();
CWString wsKey((wchar_t*)(wsClip.c_str() + 16), false, wsClip.size() - 17);
wsClip = m_pStaticResource->Get(wsKey.c_str());
}
pState->PushClip(wsClip);
return true;
}
return bResult;
return false;
}
void Page::PrepareVmlString(std::wstring& wsString)
{
const wchar_t* wsVml = L"FMLHVCQSAZfmlhvcqsaz";
std::wstring wsResult;
int nPos = wsString.find(wsVml);
while (std::wstring::npos != nPos)
bool Page::TransformToRenderer(const wchar_t* wsString, CContextState* pState)
{
wsResult += wsString.substr(0, nPos);
wsResult += L" ";
wsResult += wsString.substr(nPos, 1);
wsResult += L" ";
wsString.erase(0, nPos + 1);
nPos = wsString.find(wsVml);
}
wsResult += wsString;
wsString = wsResult;
}
void Page::TransformToRenderer(const std::wstring& wsString, IRenderer* pRenderer, CContextState* pState)
CWString wsTransform = wsString;
if (!wsTransform.empty())
{
std::vector<std::wstring> arrElements = NSString::Split(wsString, L',');
std::vector<std::wstring> arrElements = NSStringExt::Split(wsString, L',');
double arrRes[6] ={ 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 };
for (int nIndex = 0, nCount = min(6, arrElements.size()); nIndex < nCount; nIndex++)
arrRes[nIndex] = GetDouble(arrElements[nIndex]);
pState->PushTransform(arrRes);
pState->SetTransformToRenderer(pRenderer);
}
void Page::ResetTransform(IRenderer* pRenderer, CContextState* pState)
{
pState->PopTransform();
pState->SetTransformToRenderer(pRenderer);
}
void Page::DrawGlyph(XmlUtils::CXmlNode& oRootNode, IRenderer* pRenderer, CContextState* pState)
{
std::wstring wsFontPath = oRootNode.GetAttribute(L"FontUri", L"");
if (L"" != wsFontPath)
{
std::wstring wsFontName = GetFileName(wsFontPath);
wsFontPath = m_wsRootPath + L"/" + wsFontPath;
std::wstring wsExt = GetFileExtension(wsFontPath);
NSString::ToLower(wsExt);
if(L"odttf" == wsExt)
{
NSString::ToLower(wsFontName);
m_pFontList->Check(wsFontName, wsFontPath);
}
wsFontPath = NormalizePath(wsFontPath);
pRenderer->put_FontPath(wsFontPath);
}
int nBgr, nAlpha;
std::wstring wsFontColor = oRootNode.GetAttribute(L"Fill", L"#FF000000");
GetBgra(wsFontColor, nBgr, nAlpha);
pRenderer->put_BrushColor1(nBgr & 0x00FFFFFF);
pRenderer->put_BrushAlpha1(nAlpha);
pRenderer->put_BrushType(c_BrushTypeSolid);
std::wstring wsFontStyle = oRootNode.GetAttribute(L"StyleSimulations", L"");
if (L"ItalicSimulation" == wsFontStyle)
pRenderer->put_FontStyle(0x02);
else if (L"BoldSimulation" == wsFontStyle)
pRenderer->put_FontStyle(0x01);
else if (L"BoldItalicSimulation" == wsFontStyle)
pRenderer->put_FontStyle(0x03);
std::wstring wsFontSize = oRootNode.GetAttribute(L"FontRenderingEmSize");
double dFontSize = GetDouble(wsFontSize);
bool bTransform = false;
std::wstring wsTransform = oRootNode.GetAttribute(L"RenderTransform", L"");
if(L"" != wsTransform)
{
TransformToRenderer(wsTransform, pRenderer, pState);
bTransform = true;
if(dFontSize < 5)
{
double dDet = pState->NormalizeTransform();
dFontSize *= dDet;
pState->SetTransformToRenderer(pRenderer);
}
}
pRenderer->put_FontSize(dFontSize * 0.75);
std::wstring wsText = oRootNode.GetAttribute(L"UnicodeString", L"");
std::wstring wsTextX = oRootNode.GetAttribute(L"OriginX");
std::wstring wsTextY = oRootNode.GetAttribute(L"OriginY");
int nTextLen = wsText.length();
double dX = GetDouble(wsTextX);
double dY = GetDouble(wsTextY);
std::wstring wsChar = wsText.substr(0, 1);
std::wstring wsIndicies = oRootNode.GetAttribute(L"Indices", L"");
std::vector<std::vector<std::wstring>> arrElements = Split(wsIndicies, L';', L',');
m_pFontManager->LoadFontFromFile(wsFontPath, 0, (float)(dFontSize * 0.75), 96, 96);
for(int nIndex = 0; nIndex < nTextLen - 1; nIndex++)
{
if (nIndex >= arrElements.size())
arrElements.push_back(std::vector<std::wstring>());
pRenderer->CommandDrawText(wsChar, xpsUnitToMM(dX), xpsUnitToMM(dY), 0, 0, 0);
if (arrElements.at(nIndex).size() >= 2)
{
dX += GetDouble(arrElements.at(nIndex).at(1)) * dFontSize / 100.0;
}
else
{
m_pFontManager->LoadString1(wsChar, 0, 0);
TBBox oBox = m_pFontManager->MeasureString2();
dX += (oBox.fMaxX - oBox.fMinX);
}
wsChar = wsText.substr(nIndex + 1, 1);
}
if (nTextLen > 0)
{
pRenderer->CommandDrawText(wsChar, xpsUnitToMM(dX), xpsUnitToMM(dY), 0, 0, 0);
return true;
}
if (bTransform)
ResetTransform(pRenderer, pState);
return false;
}
void Page::DrawGlyph(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState)
{
......@@ -797,10 +227,10 @@ namespace XPS
std::wstring wsFontName = GetFileName(wsFontPath);
wsFontPath = m_wsRootPath + L"/" + wsFontPath;
std::wstring wsExt = GetFileExtension(wsFontPath);
NSString::ToLower(wsExt);
NSStringExt::ToLower(wsExt);
if (L"odttf" == wsExt)
{
NSString::ToLower(wsFontName);
NSStringExt::ToLower(wsFontName);
m_pFontList->Check(wsFontName, wsFontPath);
}
wsFontPath = NormalizePath(wsFontPath);
......@@ -808,7 +238,6 @@ namespace XPS
}
else if (L"Fill" == wsAttrName)
{
int nBgr, nAlpha;
std::wstring wsFontColor = oReader.GetText();
ReadAttribute(oReader, L"Fill", wsFontColor);
GetBgra(wsFontColor, nBgr, nAlpha);
......@@ -833,14 +262,11 @@ namespace XPS
std::wstring wsTransform = oReader.GetText();
if (!wsTransform.empty())
{
TransformToRenderer(wsTransform, pRenderer, pState);
bTransform = true;
bTransform = TransformToRenderer(wsTransform.c_str(), pState);
if (dFontSize < 5)
{
double dDet = pState->NormalizeTransform();
dFontSize *= dDet;
pState->SetTransformToRenderer(pRenderer);
}
}
}
......@@ -908,16 +334,9 @@ namespace XPS
}
if (bTransform)
ResetTransform(pRenderer, pState);
}
void Page::CanvasTransform(XmlUtils::CXmlNode& oRootNode, IRenderer* pRenderer, CContextState* pState)
{
XmlUtils::CXmlNode oTransformNode;
oRootNode.GetNode(L"MatrixTransform", oTransformNode);
std::wstring wsMatrix = oTransformNode.GetAttribute(L"Matrix");
TransformToRenderer(wsMatrix, pRenderer, pState);
pState->PopTransform();
}
void Page::CanvasTransform(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState)
bool Page::ReadTransform(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState)
{
std::wstring wsNodeName;
int nCurDepth = oReader.GetDepth();
......@@ -930,92 +349,30 @@ namespace XPS
{
std::wstring wsMatrix;
ReadAttribute(oReader, L"Matrix", wsMatrix);
TransformToRenderer(wsMatrix, pRenderer, pState);
break;
}
}
}
void Page::DrawPath(XmlUtils::CXmlNode& oRootNode, IRenderer* pRenderer, CContextState* pState)
{
bool bTransform = false;
std::wstring wsTransform = oRootNode.GetAttribute(L"RenderTransform", L"");
if (L"" != wsTransform)
{
TransformToRenderer(wsTransform, pRenderer, pState);
bTransform = true;
}
int nAlpha, nBgr;
std::wstring wsStrokeColor = oRootNode.GetAttribute(L"Stroke", L"#00FFFFFF");
std::wstring wsPenSize = oRootNode.GetAttribute(L"StrokeThickness", L"1.0");
GetBgra(wsStrokeColor, nBgr, nAlpha);
pRenderer->put_PenColor(nBgr & 0x00FFFFFF);
pRenderer->put_PenAlpha(nAlpha);
pRenderer->put_PenSize(xpsUnitToMM(GetDouble(wsPenSize)));
std::wstring wsFill = oRootNode.GetAttribute(L"Fill");
if (L"" != wsFill)
{
GetBgra(wsFill, nBgr, nAlpha);
pRenderer->put_BrushType(c_BrushTypeSolid);
pRenderer->put_BrushColor1(nBgr & 0x00FFFFFF);
pRenderer->put_BrushAlpha1(nAlpha);
}
else
{
XmlUtils::CXmlNode oFillNode;
if (oRootNode.GetNode(L"Path.Fill", oFillNode))
FillToRenderer(oFillNode, pRenderer);
else
{
pRenderer->put_BrushAlpha1(0);
pRenderer->put_BrushAlpha2(0);
}
}
std::wstring wsData = oRootNode.GetAttribute(L"Data");
if (L"" == wsData)
{
GetDataFromNode(wsData, oRootNode);
}
if (L'{' == wsData[0])
{
std::wstring wsValue = pState->GetFigure(wsData);
if (L"" != wsValue)
wsData = wsValue;
else
{
if (bTransform)
ResetTransform(pRenderer, pState);
return;
return TransformToRenderer(wsMatrix.c_str(), pState);
}
}
pRenderer->BeginCommand(c_nPathType);
pRenderer->PathCommandStart();
bool bWindingFillMode = false;
if (L'{' != wsData[0])
bWindingFillMode = VmlToRenderer(wsData, pRenderer);
int nFillMode = bWindingFillMode ? c_nWindingFillMode | c_nStroke : c_nEvenOddFillMode | c_nStroke;
pRenderer->DrawPath(nFillMode);
pRenderer->EndCommand(c_nPathType);
pRenderer->PathCommandEnd();
if (bTransform)
ResetTransform(pRenderer, pState);
return false;
}
void Page::DrawPath(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState)
{
bool bTransform = false;
bool bTransform = false, bClip = false;
bool bFillSetted = false;
double dPenSize = 1.0;
std::wstring wsData;
bool bStroke = false;
BYTE nDashCap = Aggplus::LineCapFlat;
BYTE nStartCap = Aggplus::LineCapFlat;
BYTE nEndCap = Aggplus::LineCapFlat;
BYTE nJoinStyle = Aggplus::LineJoinMiter;
double dMiter = 10.0;
double* pDashPattern = NULL;
LONG lDashPatternSize = 0;
double dDashOffset = 0.0;
if (oReader.MoveToFirstAttribute())
{
std::wstring wsAttrName = oReader.GetName();
......@@ -1023,12 +380,11 @@ namespace XPS
{
if (L"RenderTransform" == wsAttrName)
{
std::wstring wsTransform = oReader.GetText();
if (!wsTransform.empty())
{
TransformToRenderer(wsTransform, pRenderer, pState);
bTransform = true;
bTransform = TransformToRenderer(oReader.GetText(), pState);
}
else if (L"Clip" == wsAttrName)
{
bClip = ClipToRenderer(oReader.GetText(), pState);
}
else if (L"Stroke" == wsAttrName)
{
......@@ -1044,6 +400,56 @@ namespace XPS
std::wstring wsPenSize = oReader.GetText();
dPenSize = GetDouble(wsPenSize);
}
else if (L"StrokeDashArray" == wsAttrName)
{
std::wstring wsDashArray = oReader.GetText();
std::vector<std::wstring> arrDashArray = NSStringExt::Split(wsDashArray, ' ');
int nDashArrayCount = arrDashArray.size();
if (nDashArrayCount > 0)
{
pDashPattern = new double[nDashArrayCount];
if (pDashPattern)
{
lDashPatternSize = nDashArrayCount;
for (int nIndex = 0; nIndex < nDashArrayCount; nIndex++)
{
pDashPattern[nIndex] = GetDouble(arrDashArray.at(nIndex));
}
}
}
}
else if (L"StrokeDashOffset" == wsAttrName)
{
std::wstring wsDashOffset = oReader.GetText();
dDashOffset = GetDouble(wsDashOffset);
}
else if (L"StrokeDashCap" == wsAttrName)
{
nDashCap = GetCapStyle(oReader.GetText());
}
else if (L"StrokeEndLineCap" == wsAttrName)
{
nEndCap = GetCapStyle(oReader.GetText());
}
else if (L"StrokeStartLineCap" == wsAttrName)
{
nStartCap = GetCapStyle(oReader.GetText());
}
else if (L"StrokeLineJoin" == wsAttrName)
{
CWString wsJoin = oReader.GetText();
if (wsJoin == L"Miter")
nJoinStyle = Aggplus::LineJoinMiter;
else if (wsJoin == L"Bevel")
nJoinStyle = Aggplus::LineJoinBevel;
else if (wsJoin == L"Round")
nJoinStyle = Aggplus::LineJoinRound;
}
else if (L"StrokeMiterLimit" == wsAttrName)
{
CWString wsMiterLimit = oReader.GetText();
dMiter = GetDouble(wsMiterLimit.c_str());
}
else if (L"Fill" == wsAttrName)
{
bFillSetted = true;
......@@ -1067,6 +473,30 @@ namespace XPS
}
oReader.MoveToElement();
if (pDashPattern)
{
for (LONG lIndex = 0; lIndex < lDashPatternSize; lIndex++)
{
pDashPattern[lIndex] = xpsUnitToMM(pDashPattern[lIndex] * dPenSize);
}
pRenderer->put_PenDashStyle(Aggplus::DashStyleCustom);
pRenderer->PenDashPattern(pDashPattern, lDashPatternSize);
pRenderer->put_PenDashOffset(dDashOffset);
pRenderer->put_PenLineStartCap(nDashCap);
pRenderer->put_PenLineEndCap(nDashCap);
delete[] pDashPattern;
}
else
{
pRenderer->put_PenDashStyle(Aggplus::DashStyleSolid);
pRenderer->put_PenLineStartCap(nStartCap);
pRenderer->put_PenLineEndCap(nEndCap);
}
pRenderer->put_PenLineJoin(nJoinStyle);
if (nJoinStyle == Aggplus::LineJoinMiter)
pRenderer->put_PenMiterLimit(xpsUnitToMM(dMiter));
pRenderer->put_PenSize(xpsUnitToMM(dPenSize));
bool bFill = bFillSetted;
......@@ -1092,26 +522,39 @@ namespace XPS
if (L"" == wsData)
ReadPathData(oReader, wsData);
pRenderer->BeginCommand(c_nPathType);
pRenderer->PathCommandStart();
bool bWindingFillMode = false;
if (L'{' == wsData[0])
{
std::wstring wsValue = pState->GetFigure(wsData);
if (L"" != wsValue)
wsData = wsValue;
const wchar_t* wsValue = NULL;
if (m_pStaticResource)
{
CWString wsKey(((wchar_t*)wsData.c_str() + 16), false, wsData.length() - 17);
wsValue = m_pStaticResource->Get(wsKey);
}
if (NULL != wsValue)
{
bWindingFillMode = VmlToRenderer(wsValue, pRenderer);
}
else
{
pRenderer->EndCommand(c_nPathType);
pRenderer->PathCommandEnd();
if (bClip)
pState->PopClip();
if (bTransform)
ResetTransform(pRenderer, pState);
pState->PopTransform();
return;
}
}
pRenderer->BeginCommand(c_nPathType);
pRenderer->PathCommandStart();
bool bWindingFillMode = false;
if (L'{' != wsData[0])
bWindingFillMode = VmlToRenderer(wsData, pRenderer);
else
bWindingFillMode = VmlToRenderer(wsData.c_str(), pRenderer);
int nMode = bStroke ? c_nStroke : 0;
if (bFill)
......@@ -1122,31 +565,10 @@ namespace XPS
pRenderer->PathCommandEnd();
if (bTransform)
ResetTransform(pRenderer, pState);
}
void Page::FillToRenderer(XmlUtils::CXmlNode& oRootNode, IRenderer* pRenderer)
{
XmlUtils::CXmlNode oBrushNode;
if (oRootNode.GetNode(L"SolidColorBrush", oBrushNode))
{
int nBgr, nAlpha;
std::wstring wsColor = oBrushNode.GetAttribute(L"Color", L"#00FFFFFF");
GetBgra(wsColor, nBgr, nAlpha);
pRenderer->put_BrushType(c_BrushTypeSolid);
pRenderer->put_BrushColor1(nBgr & 0x00FFFFFF);
pRenderer->put_BrushAlpha1(nAlpha);
}
else if (oRootNode.GetNode(L"ImageBrush", oBrushNode))
{
std::wstring wsImageSource = oBrushNode.GetAttribute(L"ImageSource");
pRenderer->put_BrushType(c_BrushTypeTexture);
pRenderer->put_BrushTexturePath(m_wsRootPath + wsImageSource);
}
else
{
pRenderer->put_BrushAlpha1(0);
pRenderer->put_BrushAlpha2(0);
}
pState->PopTransform();
if (bClip)
pState->PopClip();
}
bool Page::FillToRenderer(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer)
{
......@@ -1183,82 +605,6 @@ namespace XPS
return false;
}
void Page::GetDataFromNode(std::wstring& wsString, XmlUtils::CXmlNode& oNode)
{
wsString = L"";
XmlUtils::CXmlNode oPathDataNode;
oNode.GetNode(L"Path.Data", oPathDataNode);
XmlUtils::CXmlNode oGeometryNode;
oPathDataNode.GetNode(_T("PathGeometry"), oGeometryNode);
std::wstring wsFillMode = oGeometryNode.GetAttribute(L"FillRule", L"EvenOdd");
if (L"EvenOdd" == wsFillMode)
wsString += L"F 0 ";
else
wsString += L"F 1 ";
XmlUtils::CXmlNodes arrFigureNodes;
XmlUtils::CXmlNode oFigureNode;
XmlUtils::CXmlNodes arrSegmentNodes;
XmlUtils::CXmlNode oSegmentNode;
oGeometryNode.GetNodes(L"PathFigure", arrFigureNodes);
for (int nFigureIndex = 0, nFiguresCount = arrFigureNodes.GetCount(); nFigureIndex < nFiguresCount; nFigureIndex++)
{
arrFigureNodes.GetAt(nFigureIndex, oFigureNode);
std::wstring wsStartPoint = oFigureNode.GetAttribute(L"StartPoint");
wsString += L" M " + wsStartPoint;
oFigureNode.GetNodes(L"*", arrSegmentNodes);
for (int nSegmentIndex = 0, nSegmentsCount = arrSegmentNodes.GetCount(); nSegmentIndex < nSegmentsCount; nSegmentIndex++)
{
arrSegmentNodes.GetAt(nSegmentIndex, oSegmentNode);
std::wstring wsName = oSegmentNode.GetName();
if (L"PolyLineSegment" == wsName)
{
wsString += L" L ";
wsString += oSegmentNode.GetAttribute(L"Points");
}
else if (L"PolyBezierSegment" == wsName)
{
wsString += L" C ";
wsString += oSegmentNode.GetAttribute(L"Points");
}
else if (L"PolyQuadraticBezierSegment" == wsName)
{
wsString += L" Q ";
wsString += oSegmentNode.GetAttribute(L"Points");
}
else if (L"ArcSegment" == wsName)
{
wsString += L" A ";
wsString += oSegmentNode.GetAttribute(L"Size");
wsString += L" ";
wsString += oSegmentNode.GetAttribute(L"RotationAngle");
wsString += L" ";
std::wstring wsIsLargeArc = oSegmentNode.GetAttribute(L"IsLargeArc");
if (GetBool(wsIsLargeArc))
wsString += L"1 ";
else
wsString += L"0 ";
std::wstring wsSweepDirection = oSegmentNode.GetAttribute(L"SweepDirection");
if (L"Counterclockwise" == wsSweepDirection)
wsString += L"0 ";
else
wsString += L"1 ";
wsString += oSegmentNode.GetAttribute(L"Point");
}
}
std::wstring wsClosed = oFigureNode.GetAttribute(L"IsClosed");
if (GetBool(wsClosed))
wsString += L" Z ";
}
}
void Page::ReadPathData(XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData)
{
wsData = L"";
......
......@@ -12,6 +12,7 @@
namespace XPS
{
class CDocument;
class CStaticResource;
class Page
{
......@@ -24,28 +25,18 @@ namespace XPS
private:
void DrawCanvas(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState, bool* pbBreak);
void DrawCanvas (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState, bool* pbBreak);
void ReadPageResources(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState);
void DrawGlyph(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState);
void CanvasTransform(XmlUtils::CXmlLiteReader& oRNode, IRenderer* pRenderer, CContextState* pState);
void DrawPath(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState);
bool FillToRenderer(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer);
void ReadPathData(XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData);
void ReadPathGeometry(XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData);
void ReadPathFigure(XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData);
void DrawCanvas(XmlUtils::CXmlNode& oNode, IRenderer* pRenderer, CContextState* pState, bool* pbBreak);
void DrawGlyph(XmlUtils::CXmlNode& oNode, IRenderer* pRenderer, CContextState* pState);
void DrawPath(XmlUtils::CXmlNode& oNode, IRenderer* pRenderer, CContextState* pState);
void CanvasTransform(XmlUtils::CXmlNode& oNode, IRenderer* pRenderer, CContextState* pState);
void FillToRenderer(XmlUtils::CXmlNode& oNode, IRenderer* pRenderer);
void GetDataFromNode(std::wstring& wsString, XmlUtils::CXmlNode& oNode);
bool VmlToRenderer(std::wstring& wsValue, IRenderer* pRenderer);
void TransformToRenderer(const std::wstring& wsString, IRenderer* pRenderer, CContextState* pState);
void ResetTransform(IRenderer* pRenderer, CContextState* pState);
void PrepareVmlString(std::wstring& wsString);
void DrawGlyph (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState);
bool ReadTransform (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState);
void DrawPath (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState);
bool FillToRenderer (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer);
void ReadPathData (XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData);
void ReadPathGeometry (XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData);
void ReadPathFigure (XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData);
bool ClipToRenderer (const wchar_t* wsString, CContextState* pState);
bool TransformToRenderer(const wchar_t* wsString, CContextState* pState);
private:
......@@ -54,6 +45,10 @@ namespace XPS
CFontList* m_pFontList;
CFontManager* m_pFontManager;
CDocument* m_pDocument;
CStaticResource* m_pStaticResource;
bool m_bDeleteStaticResource;
int m_nCounter;
};
}
......
......@@ -2,9 +2,445 @@
#include "../../DesktopEditor/common/String.h"
#include "../../DesktopEditor/common/Types.h"
#include "../../Common/DocxFormat/Source/XML/xmlutils.h"
#include "../../DesktopEditor/graphics/IRenderer.h"
#define MAX_STRING_LEN 2147483648
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef xpsUnitToMM
#define xpsUnitToMM(x) ((x) * 25.4 / 96)
#endif
#define IsNumber(X) \
('0' == (X)\
|| '1' == (X)\
|| '2' == (X)\
|| '3' == (X)\
|| '4' == (X)\
|| '5' == (X)\
|| '6' == (X)\
|| '7' == (X)\
|| '8' == (X)\
|| '9' == (X)\
|| '-' == (X)\
|| '.' == (X))
#define GetChar(STRING, POS) STRING[POS++]
#define LookChar(STRING, POS) STRING[POS]
namespace XPS
{
static inline bool SkipWhiteSpaces(const wchar_t* wsString, int& nPos, const int& nLen)
{
while (1)
{
if (nPos >= nLen)
return false;
wchar_t wChar = LookChar(wsString, nPos);
if (' ' == wChar || ',' == wChar)
{
nPos++;
continue;
}
else
break;
}
return true;
}
static inline double GetNumber(const wchar_t* wsString, int& nPos, const int& nLen)
{
if (!SkipWhiteSpaces(wsString, nPos, nLen))
return 0.0;
wchar_t wChar = GetChar(wsString, nPos);
if (IsNumber(wChar))
{
bool bNegative = false;
int nInt = 0;
double dFloat = 0.0, dScale = 0.1;
if ('-' == wChar)
{
bNegative = true;
}
else if ('.' == wChar)
{
goto doReal;
}
else
{
nInt = wChar - '0';
}
while (1)
{
wChar = LookChar(wsString, nPos);
if (isdigit(wChar))
{
nPos++;
nInt = nInt * 10 + (wChar - '0');
}
else if ('.' == wChar)
{
nPos++;
dFloat = (double)nInt;
goto doReal;
}
else
{
break;
}
}
return (bNegative ? (double)(-nInt) : (double)nInt);
doReal:
while (1)
{
wChar = LookChar(wsString, nPos);
if (!isdigit(wChar))
break;
nPos++;
dFloat = dFloat + dScale * (wChar - '0');
dScale *= 0.1;
}
return (bNegative ? (double)(-dFloat) : (double)dFloat);
}
return 0.0;
}
static inline bool GetBool(const wchar_t* wsString, int& nPos, const int& nLen)
{
if (!SkipWhiteSpaces(wsString, nPos, nLen))
return false;
int nBufPos = 0;
wchar_t pBuffer[32];
memset(pBuffer, 0x00, sizeof(wchar_t) * 32);
wchar_t wChar = LookChar(wsString, nPos);
while (' ' != wChar)
{
pBuffer[nBufPos++] = wChar;
nPos++;
if (nPos >= nLen)
break;
wChar = LookChar(wsString, nPos);
}
CWString wsBool(pBuffer, false, nBufPos);
if ((wsBool == L"true") || (wsBool == L"t") || (wsBool == L"1") || (wsBool == L"on"))
return true;
return false;
}
static inline void PageCommandA(const wchar_t* wsString, int& nPos, const int& nLen, double& dCurX, double& dCurY, IRenderer* pRenderer)
{
Aggplus::CMatrix tmatx, rmatx, smatx, itmatx, irmatx, ismatx;
double x_cur_temp = dCurX;
double y_cur_temp = dCurY;
double rx = GetNumber(wsString, nPos, nLen);
double ry = GetNumber(wsString, nPos, nLen);
double angle = GetNumber(wsString, nPos, nLen);
bool isLarge = GetBool(wsString, nPos, nLen);
bool isCCW = !GetBool(wsString, nPos, nLen);
double x_end = GetNumber(wsString, nPos, nLen);
double y_end = GetNumber(wsString, nPos, nLen);
tmatx.Translate(-dCurX, -dCurY);
tmatx.TransformPoint(x_cur_temp, y_cur_temp);
tmatx.TransformPoint(x_end, y_end);
rmatx.Rotate(-angle);
rmatx.TransformPoint(x_cur_temp, y_cur_temp);
rmatx.TransformPoint(x_end, y_end);
smatx.Scale(ry / rx, 1);
smatx.TransformPoint(x_cur_temp, y_cur_temp);
smatx.TransformPoint(x_end, y_end);
double mid_x = (x_cur_temp + x_end) / 2.0, mid_y = (y_cur_temp + y_end) / 2.0;
double vect_x = x_end - x_cur_temp, vect_y = y_end - y_cur_temp;
double length = sqrt(vect_x * vect_x + vect_y * vect_y);
double halfChord = length / 2.0;
double rotated_x, rotated_y;
if (isLarge == isCCW)
{
rotated_x = -vect_y;
rotated_y = vect_x;
}
else
{
rotated_x = vect_y;
rotated_y = -vect_x;
}
rotated_x = rotated_x / length;
rotated_y = rotated_y / length;
double centerDistance = sqrt(max(ry * ry - halfChord * halfChord, 0));
double center_x = mid_x + centerDistance * rotated_x, center_y = mid_y + centerDistance * rotated_y;
double angle1 = atan2(y_cur_temp - center_y, x_cur_temp - center_x);
double angle2 = atan2(y_end - center_y, x_end - center_x);
if ((!isCCW) && (abs(y_end - center_y) < 0.000001) && (x_end - center_x < 0))
angle2 = -M_PI;
if ((isCCW) && (abs(y_cur_temp - center_y) < 0.000001) && (x_cur_temp - center_x < 0))
angle1 = -M_PI;
if (isLarge == (abs(angle2 - angle1) < M_PI))
{
if (angle1 < angle2)
angle1 += 2 * M_PI;
else
angle2 += 2 * M_PI;
}
if (abs(angle2 - angle1) == M_PI)
{
if ((angle1 < angle2) && (isCCW) && (angle1 != -M_PI) && (angle1 != 0.0) && (angle1 != M_PI))
angle1 += 2 * M_PI;
}
itmatx.Translate(dCurX, dCurY);
irmatx.Rotate(angle);
ismatx.Scale(rx / ry, 1);
int max = (int)((4 * (rx + ry) * abs(angle2 - angle1) / (2 * M_PI)) / 1/*tolerance*/);
double x, y;
for (int counter = 0; counter <= max; counter++)
{
double angle_cur = ((max - counter) * angle1 + counter * angle2) / max;
x = center_x + ry * cos(angle_cur);
y = center_y + ry * sin(angle_cur);
// Transform the point back
ismatx.TransformPoint(x, y);
irmatx.TransformPoint(x, y);
itmatx.TransformPoint(x, y);
pRenderer->PathCommandLineTo(xpsUnitToMM(x), xpsUnitToMM(y));
}
dCurX = x;
dCurY = y;
}
}
namespace XPS
{
class CWStringBuffer
{
public:
CWStringBuffer(const wchar_t* wsString, unsigned int unLen)
{
if (unLen)
{
m_pBuffer = new wchar_t[unLen + 1];
m_pBuffer[unLen] = 0x00;
memcpy(m_pBuffer, wsString, sizeof(wchar_t) * unLen);
}
else
{
m_pBuffer = NULL;
}
m_nRefCount = 1;
}
void AddRef()
{
m_nRefCount++;
}
int Release()
{
return --m_nRefCount;
}
void Free()
{
RELEASEARRAYOBJECTS(m_pBuffer);
}
wchar_t operator[](const unsigned int& unIndex) const
{
return m_pBuffer[unIndex];
}
private:
wchar_t* m_pBuffer;
int m_nRefCount;
friend class CWString;
};
CWString::CWString()
{
m_bOwnBuffer = false;
m_pBuffer = NULL;
m_unLen = 0;
}
CWString::CWString(const wchar_t* wsString)
{
m_bOwnBuffer = false;
m_pBuffer = NULL;
m_unLen = 0;
create(wsString, false);
}
CWString::CWString(wchar_t* wsString, bool bCopy, int nLen)
{
m_bOwnBuffer = false;
m_pBuffer = NULL;
m_unLen = 0;
create(wsString, bCopy, nLen);
}
CWString::CWString(const CWString& wsString)
{
m_unLen = wsString.m_unLen;
m_bOwnBuffer = wsString.m_bOwnBuffer;
m_pBuffer = wsString.m_pBuffer;
if (m_bOwnBuffer && m_pBuffer)
((CWStringBuffer*)m_pBuffer)->AddRef();
}
CWString::~CWString()
{
clear();
}
void CWString::create(const wchar_t* wsString, bool bCopy, int nLen)
{
clear();
unsigned int unLen = -1 == nLen ? min(wcslen(wsString), MAX_STRING_LEN) : (unsigned int)nLen;
m_unLen = unLen;
if (bCopy)
{
if (unLen)
{
m_pBuffer = (void*)(new CWStringBuffer(wsString, m_unLen));
m_bOwnBuffer = true;
}
}
else
{
m_pBuffer = (void*)wsString;
m_bOwnBuffer = false;
}
}
void CWString::clear()
{
if (m_bOwnBuffer)
{
CWStringBuffer* pWStringBuffer = (CWStringBuffer*)m_pBuffer;
if (pWStringBuffer && !pWStringBuffer->Release())
delete pWStringBuffer;
}
m_bOwnBuffer = false;
m_pBuffer = NULL;
m_unLen = 0;
}
void CWString::operator=(const wchar_t* wsString)
{
clear();
create(wsString, false);
}
void CWString::operator=(const CWString& wsString)
{
clear();
m_unLen = wsString.m_unLen;
m_bOwnBuffer = wsString.m_bOwnBuffer;
m_pBuffer = wsString.m_pBuffer;
if (m_bOwnBuffer && m_pBuffer)
((CWStringBuffer*)m_pBuffer)->AddRef();
}
const wchar_t* CWString::c_str() const
{
if (m_bOwnBuffer)
{
CWStringBuffer* pWStringBuffer = (CWStringBuffer*)m_pBuffer;
if (pWStringBuffer)
return pWStringBuffer->m_pBuffer;
return NULL;
}
return (const wchar_t*)m_pBuffer;
}
bool CWString::operator<(const CWString& wsString) const
{
const wchar_t* wsLeft = this->c_str();
const wchar_t* wsRight = wsString.c_str();
unsigned int unLen = min(m_unLen, wsString.m_unLen);
for (unsigned int unPos = 0; unPos < unLen; unPos++)
{
if (wsLeft[unPos] < wsRight[unPos])
return true;
else if (wsLeft[unPos] > wsRight[unPos])
return false;
}
return (m_unLen > wsString.m_unLen);
}
bool CWString::operator>(const CWString& wsString) const
{
return !operator<(wsString);
}
bool CWString::operator==(const CWString& wsString) const
{
const wchar_t* wsLeft = this->c_str();
const wchar_t* wsRight = wsString.c_str();
if (m_unLen != wsString.m_unLen)
return false;
for (unsigned int unPos = 0; unPos < m_unLen; unPos++)
{
if (wsLeft[unPos] != wsRight[unPos])
return false;
}
return true;
}
bool CWString::operator==(const wchar_t* wsString) const
{
const wchar_t* wsLeft = this->c_str();
unsigned unLen = min(wcslen(wsString), MAX_STRING_LEN);
if (m_unLen != unLen)
return false;
for (unsigned int unPos = 0; unPos < m_unLen; unPos++)
{
if (wsLeft[unPos] != wsString[unPos])
return false;
}
return true;
}
unsigned int CWString::size() const
{
return m_unLen;
}
wchar_t CWString::operator[](const unsigned int& unIndex) const
{
return this->c_str()[unIndex];
}
bool CWString::empty() const
{
return 0 == m_unLen;
}
int GetDigit(wchar_t wChar)
{
if (wChar >= '0' && wChar <= '9')
......@@ -31,7 +467,7 @@ namespace XPS
bool GetBool(const std::wstring& wsString)
{
std::wstring wsStr = wsString;
NSString::ToLower(wsStr);
NSStringExt::ToLower(wsStr);
if ((wsStr == L"true") || (wsStr == L"t") || (wsStr == L"1") || (wsStr == L"on"))
return true;
......@@ -68,7 +504,7 @@ namespace XPS
else if (L's' == wsString[0] && L'c' == wsString[1] && L'#' == wsString[2])
{
std::wstring wsStr = wsString.substr(3);
std::vector<std::wstring> arrElements = NSString::Split(wsStr, L',');
std::vector<std::wstring> arrElements = NSStringExt::Split(wsStr, L',');
if (3 == arrElements.size())
{
......@@ -84,13 +520,28 @@ namespace XPS
else
return;
}
unsigned char GetCapStyle(const wchar_t* wsCapStyle)
{
BYTE nCapStyle = Aggplus::LineCapFlat;
CWString wsDashCap = wsCapStyle;
if (wsDashCap == L"Flat")
nCapStyle = Aggplus::LineCapFlat;
else if (wsDashCap == L"Round")
nCapStyle = Aggplus::LineCapRound;
else if (wsDashCap == L"Square")
nCapStyle = Aggplus::LineCapSquare;
else if (wsDashCap == L"Triangle")
nCapStyle = Aggplus::LineCapTriangle;
return nCapStyle;
}
std::wstring NormalizePath(const std::wstring& wsPath)
{
std::wstring wsResult = wsPath;
NSString::Replace(wsResult, L"/", L"\\");
NSStringExt::Replace(wsResult, L"/", L"\\");
while (std::wstring::npos != wsResult.find(L"\\\\"))
{
NSString::Replace(wsResult, L"\\\\", L"\\");
NSStringExt::Replace(wsResult, L"\\\\", L"\\");
}
return wsResult;
}
......@@ -141,11 +592,11 @@ namespace XPS
std::vector<std::vector<std::wstring>> Split(const std::wstring& wsString, wchar_t wDelim1, wchar_t wDelim2)
{
std::vector<std::vector<std::wstring>> arrResult;
std::vector<std::wstring> arrStrings = NSString::Split(wsString, wDelim1);
std::vector<std::wstring> arrStrings = NSStringExt::Split(wsString, wDelim1);
int nCount = arrStrings.size();
for (int nIndex = 0; nIndex < nCount; nIndex++)
{
std::vector<std::wstring> arrStr = NSString::Split(arrStrings[nIndex], wDelim2);
std::vector<std::wstring> arrStr = NSStringExt::Split(arrStrings[nIndex], wDelim2);
arrResult.push_back(arrStr);
}
return arrResult;
......@@ -175,4 +626,255 @@ namespace XPS
oReader.MoveToElement();
}
bool VmlToRenderer(const wchar_t* wsString, IRenderer* pRenderer)
{
bool bWinding = false;
int nPos = 0;
int nLen = wcslen(wsString);
double dCurX = 0.0, dCurY = 0.0;
double dCpX = 0.0, dCpY = 0.0;
bool bPrevCommandIsCurve = false;
wchar_t wChar = 0x00;
while (nPos < nLen)
{
if (!SkipWhiteSpaces(wsString, nPos, nLen))
break;
wChar = GetChar(wsString, nPos);
switch (wChar)
{
case 'F':
{
if (!SkipWhiteSpaces(wsString, nPos, nLen))
break;
bWinding = GetBool(wsString, nPos, nLen);
bPrevCommandIsCurve = false;
break;
}
case 'm':
{
dCurX += GetNumber(wsString, nPos, nLen);
dCurY += GetNumber(wsString, nPos, nLen);
pRenderer->PathCommandMoveTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
bPrevCommandIsCurve = false;
break;
}
case 'M':
{
dCurX = GetNumber(wsString, nPos, nLen);
dCurY = GetNumber(wsString, nPos, nLen);
pRenderer->PathCommandMoveTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
bPrevCommandIsCurve = false;
break;
}
case 'L':
case 'l':
case 'H':
case 'h':
case 'V':
case 'v':
{
while (true)
{
if (!SkipWhiteSpaces(wsString, nPos, nLen))
break;
if (IsNumber(LookChar(wsString, nPos)))
{
switch (wChar)
{
case 'L':
{
dCurX = GetNumber(wsString, nPos, nLen);
dCurY = GetNumber(wsString, nPos, nLen);
break;
}
case 'l':
{
dCurX = GetNumber(wsString, nPos, nLen);
dCurY = GetNumber(wsString, nPos, nLen);
break;
}
case 'H':
{
dCurX = GetNumber(wsString, nPos, nLen);
break;
}
case 'h':
{
dCurX += GetNumber(wsString, nPos, nLen);
break;
}
case 'V':
{
dCurY = GetNumber(wsString, nPos, nLen);
break;
}
case 'v':
{
dCurY += GetNumber(wsString, nPos, nLen);
break;
}
}
pRenderer->PathCommandLineTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
}
else
break;
}
bPrevCommandIsCurve = false;
break;
}
case 'A':
case 'a':
{
while (true)
{
if (!SkipWhiteSpaces(wsString, nPos, nLen))
break;
if (IsNumber(LookChar(wsString, nPos)))
PageCommandA(wsString, nPos, nLen, dCurX, dCurY, pRenderer);
else
break;
}
bPrevCommandIsCurve = false;
break;
}
case 'C':
case 'c':
{
while (true)
{
if (!SkipWhiteSpaces(wsString, nPos, nLen))
break;
if (IsNumber(LookChar(wsString, nPos)))
{
double dX1, dY1, dX2, dY2;
if ('c' == wChar)
{
dX1 = dCurX + GetNumber(wsString, nPos, nLen);
dY1 = dCurY + GetNumber(wsString, nPos, nLen);
dX2 = dCurX + GetNumber(wsString, nPos, nLen);
dY2 = dCurY + GetNumber(wsString, nPos, nLen);
dCurX += GetNumber(wsString, nPos, nLen);
dCurY += GetNumber(wsString, nPos, nLen);
}
else
{
dX1 = GetNumber(wsString, nPos, nLen);
dY1 = GetNumber(wsString, nPos, nLen);
dX2 = GetNumber(wsString, nPos, nLen);
dY2 = GetNumber(wsString, nPos, nLen);
dCurX = GetNumber(wsString, nPos, nLen);
dCurY = GetNumber(wsString, nPos, nLen);
}
pRenderer->PathCommandCurveTo(xpsUnitToMM(dX1), xpsUnitToMM(dY1), xpsUnitToMM(dX2), xpsUnitToMM(dY2), xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
dCpX = dX2;
dCpY = dY2;
bPrevCommandIsCurve = true;
}
else
break;
}
break;
}
case 'Q':
case 'q':
{
while (true)
{
if (!SkipWhiteSpaces(wsString, nPos, nLen))
break;
if (IsNumber(LookChar(wsString, nPos)))
{
double dX1, dY1;
if ('q' == wChar)
{
dX1 = dCurX + GetNumber(wsString, nPos, nLen);
dY1 = dCurY + GetNumber(wsString, nPos, nLen);
dCurX += GetNumber(wsString, nPos, nLen);
dCurY += GetNumber(wsString, nPos, nLen);
}
else
{
dX1 = GetNumber(wsString, nPos, nLen);
dY1 = GetNumber(wsString, nPos, nLen);
dCurX = GetNumber(wsString, nPos, nLen);
dCurY = GetNumber(wsString, nPos, nLen);
}
pRenderer->PathCommandCurveTo(xpsUnitToMM(dX1), xpsUnitToMM(dY1), xpsUnitToMM(dX1), xpsUnitToMM(dY1), xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
}
else
break;
}
bPrevCommandIsCurve = false;
break;
}
case 'S':
case 's':
{
while (true)
{
if (!SkipWhiteSpaces(wsString, nPos, nLen))
break;
if (IsNumber(LookChar(wsString, nPos)))
{
double dX1, dY1, dX2, dY2;
if (!bPrevCommandIsCurve)
{
dX1 = dCurX;
dY1 = dCurY;
}
else
{
dX1 = 2 * dCurX - dCpX;
dY1 = 2 * dCurY - dCpY;
}
if ('s' == wChar)
{
dX2 = dCurX + GetNumber(wsString, nPos, nLen);
dY2 = dCurX + GetNumber(wsString, nPos, nLen);
dCurX += GetNumber(wsString, nPos, nLen);
dCurY += GetNumber(wsString, nPos, nLen);
}
else
{
dX2 = GetNumber(wsString, nPos, nLen);
dY2 = GetNumber(wsString, nPos, nLen);
dCurX = GetNumber(wsString, nPos, nLen);
dCurY = GetNumber(wsString, nPos, nLen);
}
pRenderer->PathCommandCurveTo(xpsUnitToMM(dX1), xpsUnitToMM(dY1), xpsUnitToMM(dX2), xpsUnitToMM(dY2), xpsUnitToMM(dCurX), xpsUnitToMM(dCurY));
dCpX = dX2;
dCpY = dY2;
bPrevCommandIsCurve = true;
}
else
break;
}
break;
}
case 'Z':
case 'z':
{
pRenderer->PathCommandClose();
bPrevCommandIsCurve = false;
break;
}
}
}
return bWinding;
}
}
\ No newline at end of file
......@@ -9,14 +9,48 @@ namespace XmlUtils
class CXmlLiteReader;
}
class IRenderer;
namespace XPS
{
class CWStringBuffer;
class CWString
{
public:
CWString();
CWString(const wchar_t* wsString);
CWString(const CWString& wsString);
CWString(wchar_t* wsString, bool bCopy, int nLen = -1);
~CWString();
void create(const wchar_t*, bool bCopy, int nLen = -1);
void operator=(const wchar_t* wsString);
void operator=(const CWString& wsString);
bool operator<(const CWString& wsString) const;
bool operator>(const CWString& wsString) const;
bool operator==(const CWString& wsString) const;
bool operator==(const wchar_t* wsString) const;
unsigned int size() const;
bool empty() const;
wchar_t operator[](const unsigned int& unIndex) const;
const wchar_t* c_str() const;
void clear();
private:
void* m_pBuffer;
unsigned int m_unLen;
bool m_bOwnBuffer;
};
bool IsAlpha(wchar_t wChar);
double GetDouble(const std::wstring& wsString);
int GetInteger(const std::wstring& wsString);
bool GetBool(const std::wstring& wsString);
void GetBgra(const std::wstring& wsString, int& nBgr, int& nAlpha);
unsigned char GetCapStyle(const wchar_t* wsCapStyle);
std::wstring NormalizePath(const std::wstring& wsPath);
std::wstring GetPath(const std::wstring& wsPath);
std::wstring GetFileName(const std::wstring& wsPath);
......@@ -26,6 +60,7 @@ namespace XPS
std::vector<std::vector<std::wstring>> Split(const std::wstring& wsString, wchar_t wDelim1, wchar_t wDelim2);
void ReadAttribute(XmlUtils::CXmlLiteReader& oReader, const wchar_t* wsAttrName, std::wstring& wsAttr);
bool VmlToRenderer(const wchar_t* wsString, IRenderer* pRenderer);
}
#endif // _XPS_XPSLIB_UTILS_H
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment