mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-03-17 21:12:19 +08:00
Compare commits
363 Commits
v99.99.99.
...
feature/so
| Author | SHA1 | Date | |
|---|---|---|---|
| c725eed37d | |||
| 573b85932f | |||
| 52f8640b10 | |||
| 8a1a45f403 | |||
| 2b46e0251f | |||
| 078a58772c | |||
| 3c707ebbf4 | |||
| d54f0326cd | |||
| 269dd9b8bc | |||
| 9da0b82ead | |||
| e3334cbea5 | |||
| 01c928c724 | |||
| e5c1dc4bc3 | |||
| 2c5cd93ac5 | |||
| 1ff1334746 | |||
| de096d4229 | |||
| 6c9d795167 | |||
| 8116322018 | |||
| 5428c28874 | |||
| e389b4d799 | |||
| 8c607a429a | |||
| 00e80b68f6 | |||
| 377317892d | |||
| ef77688ea2 | |||
| eb756fab5c | |||
| 2d2bb7cee7 | |||
| 1abe5b2dcc | |||
| 2b4bdfdc05 | |||
| 007c70bcc0 | |||
| 017b43dd66 | |||
| 88a6760086 | |||
| 98a0551123 | |||
| 49cb1cdbca | |||
| 73e00a5096 | |||
| 462eeda60c | |||
| e1f81b6830 | |||
| d63a6e2ba4 | |||
| b9cf1bd204 | |||
| 81ec569f59 | |||
| 236913f902 | |||
| 2a6d9faaf8 | |||
| 7a78e1bbc6 | |||
| f2db0df9f5 | |||
| c2dfac0d27 | |||
| 902497b299 | |||
| 35aa329619 | |||
| 6ace9b1cc5 | |||
| f6bc46c551 | |||
| 790049d14a | |||
| ccc9f8f91f | |||
| f2eace2b53 | |||
| dfe7a64e1a | |||
| 65f89c1e4b | |||
| ea7ff62816 | |||
| 4ac45f41cb | |||
| 947e5a1f5d | |||
| 3e724e6164 | |||
| 8ef0713adc | |||
| 2f74b3b69b | |||
| 7ce71b6f5d | |||
| 9b5847e653 | |||
| d81e26eff7 | |||
| 67e987e389 | |||
| bc91106ea4 | |||
| d91a19cbc2 | |||
| 970720575a | |||
| f11045c87f | |||
| 70e819c56b | |||
| 5a662b3567 | |||
| 0f920531ac | |||
| 84d3ea7a21 | |||
| 4893ff96fd | |||
| 6a7791ae0a | |||
| 78ac7bb427 | |||
| 8180a20cb8 | |||
| eb51861f39 | |||
| e4cc737c38 | |||
| 6c89a66b3d | |||
| b127bd3ac1 | |||
| 0cca75b662 | |||
| 08dc0c99cf | |||
| d2af89a2f6 | |||
| 836787f151 | |||
| eb78332705 | |||
| f232d0ca51 | |||
| 24d436fb9c | |||
| 1d362cf69a | |||
| 6c0326d660 | |||
| 4400c9d4f4 | |||
| 71c7d25c9e | |||
| ab1dd7a48b | |||
| 6e3d625420 | |||
| ebb0eb8136 | |||
| 10f34fb67d | |||
| 98d2f62f9e | |||
| 096df8fc31 | |||
| a7886c5cd6 | |||
| ee6ea683d1 | |||
| 9343f73818 | |||
| 61aeb6f386 | |||
| 06e8d136bf | |||
| c1d649b506 | |||
| 4386e9c794 | |||
| 4900305b4a | |||
| e1f923c593 | |||
| 07ef2269ac | |||
| cf44441645 | |||
| 7157d209d7 | |||
| 64a560679c | |||
| 2682e49090 | |||
| 7fd4219ff4 | |||
| 4f9c229f77 | |||
| 6d8454c39d | |||
| 58deecba88 | |||
| 1940bc53f7 | |||
| a6ac765676 | |||
| 08624e8334 | |||
| 1f078c8c49 | |||
| e6036b37be | |||
| 04f1c30036 | |||
| 86f84f89de | |||
| 17b80ac96e | |||
| 710bfef301 | |||
| aa75825a73 | |||
| f74caacbd0 | |||
| 4d903b58b8 | |||
| 6434965f09 | |||
| f60f957d00 | |||
| bad5b172d5 | |||
| 7b6f29a5f0 | |||
| b5e1cf9d06 | |||
| 0f73b2aa8b | |||
| e3b5d72ec8 | |||
| 8f8a9ad29b | |||
| 1417b4bbd4 | |||
| 87c9f66c58 | |||
| d0a9d2cfe2 | |||
| 627d5913e6 | |||
| 5ca60f6bcd | |||
| 72f679b649 | |||
| c84c35933e | |||
| 63f160641d | |||
| 7a8ccfdfa0 | |||
| 6091a7b5cd | |||
| 95b4461961 | |||
| ec5afc1f17 | |||
| 9dd13a2f74 | |||
| b850450c25 | |||
| 098d40d44f | |||
| 82769d3c0e | |||
| 5121f74851 | |||
| 6fa8b51541 | |||
| 3b32ba4d14 | |||
| e23acc8881 | |||
| c266ffa85f | |||
| bd2af5f455 | |||
| ec8c0182c3 | |||
| 04ad9d4e47 | |||
| 3261ba0d0c | |||
| 2189934a50 | |||
| e3842c796a | |||
| 7507b6c71f | |||
| 8a406c9612 | |||
| 3a004e8495 | |||
| 404748ec5a | |||
| d4f7767c45 | |||
| f91cc79e7d | |||
| b14e7fd3a2 | |||
| fce8173ce4 | |||
| 8f5bfef6b2 | |||
| f6bf73dfab | |||
| 3b10e1a0f3 | |||
| f7555af6b3 | |||
| 3e09e5ad48 | |||
| 655bc0698f | |||
| e16b85f671 | |||
| 981b8b16a3 | |||
| 70aa8c7e64 | |||
| 4144723822 | |||
| 2663e412ef | |||
| 9a91e8192c | |||
| bff86db600 | |||
| 668804035a | |||
| cb97ee9fdc | |||
| 56b8e41875 | |||
| 565b2ec494 | |||
| a243e60e5a | |||
| 96ce3c22f1 | |||
| 6b58358186 | |||
| 6c95810f63 | |||
| d9260e5eee | |||
| 63510a1fe9 | |||
| 1e05ab9acb | |||
| c1236815a3 | |||
| c822a995c1 | |||
| e612306d75 | |||
| 2d6382e61a | |||
| 2f34fd917e | |||
| 024a5e0192 | |||
| a6183fa4cd | |||
| 13912c93ef | |||
| adcdbc164f | |||
| a48a78c1c5 | |||
| da57bd115c | |||
| 71b21ea79d | |||
| 5fbb998524 | |||
| ea47a90763 | |||
| daefd8744a | |||
| 647327a0c5 | |||
| 58b221f4fa | |||
| 22eaf8241b | |||
| 64c7b7a3fd | |||
| 858c2e14c8 | |||
| 2024302fbe | |||
| 00f4752dda | |||
| 90b329e06c | |||
| d286b8459b | |||
| ff93f1e8b3 | |||
| 65a4fa90a5 | |||
| 4471940b92 | |||
| c4daa0acd4 | |||
| 6df0cf26f3 | |||
| 720d66ad74 | |||
| e6522c6ce4 | |||
| 9b3c2291d8 | |||
| e7cfb67962 | |||
| 8725be55f0 | |||
| 37ae77d0d2 | |||
| 4c6ded76a1 | |||
| 2d8701cd4f | |||
| d5c321d47d | |||
| bddfadabb2 | |||
| 324f7b3933 | |||
| edef6a83c8 | |||
| e7c21fb2cd | |||
| be8ba62c3f | |||
| fda8c8e445 | |||
| d9ebae1724 | |||
| 92ec3d854e | |||
| f4867bd9f9 | |||
| 9b9da90dcc | |||
| cba4bc8085 | |||
| 325c2d3000 | |||
| 3187913c8e | |||
| 8958d13b56 | |||
| 9d13526724 | |||
| 93f70176bc | |||
| e2ad965d7c | |||
| d535aa64ef | |||
| c155a4c53a | |||
| 97cbd8dcc7 | |||
| 5e58298d1e | |||
| d38576085c | |||
| 46dd9efa2e | |||
| 6af52920a2 | |||
| f13baca136 | |||
| 28a91a1519 | |||
| 0e48e65ef1 | |||
| ad1709d4af | |||
| e2c6ecec9b | |||
| ef55594f90 | |||
| 223bbe3347 | |||
| eca0cdb318 | |||
| 4a52368c30 | |||
| 73f4e20c56 | |||
| d53768969b | |||
| 324d6ec0bd | |||
| 767b652ef2 | |||
| 68f2f0760d | |||
| 694282a013 | |||
| e64eeb26af | |||
| 873b2b9351 | |||
| d5ecb00472 | |||
| 2ac6801afa | |||
| 213c65fe54 | |||
| 8269c14207 | |||
| f438a17779 | |||
| 9c8b739d0e | |||
| a9dc790f92 | |||
| 7f0720bb95 | |||
| 846b212882 | |||
| 344a096e24 | |||
| 15eb4793f5 | |||
| 3ce4b4bfe8 | |||
| b8fab6f4df | |||
| 14bb45d2fe | |||
| 347c1f82a9 | |||
| 7ebf12c1e4 | |||
| 1813e09e1f | |||
| e32b48524e | |||
| d2a986c480 | |||
| 73880f6207 | |||
| 24ad4adf6f | |||
| e4ea19ed81 | |||
| 575e379c4b | |||
| 86d8c7bfa3 | |||
| a3e1efb75b | |||
| e1f7feb5c1 | |||
| 2a3f565b44 | |||
| 13008c60e5 | |||
| df69099689 | |||
| 4e6f6e44bd | |||
| 67b54dc371 | |||
| b0c3172ae5 | |||
| 91d21a80ac | |||
| e820a9c936 | |||
| b38b12dfaf | |||
| 39b9e89e77 | |||
| 0b6ea2a399 | |||
| eee3161833 | |||
| fc422bb2e7 | |||
| f359f180bb | |||
| b0338919fe | |||
| 41358e3308 | |||
| 1a29fb1389 | |||
| 2fa048303f | |||
| 79f8e14d07 | |||
| e837479426 | |||
| e8f68e3a40 | |||
| 702987e00c | |||
| 83745da5f3 | |||
| 6b73faac12 | |||
| cab91648ce | |||
| 57b51a8854 | |||
| 4a84b8887f | |||
| 23027e4c2c | |||
| 52c61219dc | |||
| 2c37dac18c | |||
| aa7f104e60 | |||
| 83ea144c16 | |||
| ea6fdc8872 | |||
| bb4ceb14e5 | |||
| ef9f25aa4d | |||
| 0c2a5eac1b | |||
| e2ce58a055 | |||
| cadba798b0 | |||
| 31f274fbc4 | |||
| 58fe8ae679 | |||
| 6e696daa15 | |||
| c4708222c6 | |||
| 116ec89cd2 | |||
| 8133e3f7b7 | |||
| 3081d02c9c | |||
| 91afd3d340 | |||
| 7d06219664 | |||
| 578118380e | |||
| 59f376908c | |||
| 5d6caf8a93 | |||
| e936b0e4e7 | |||
| 6283a68841 | |||
| 50ae7db2f0 | |||
| dd17cb7243 | |||
| b3988b002f | |||
| bb3091b6f1 | |||
| dde96288ed | |||
| c9100737e0 | |||
| a22f0bfb60 | |||
| ea338db68a | |||
| 76f3afc6c0 | |||
| 981df3fce7 | |||
| 85d98daedd | |||
| bcdcfa8bf7 | |||
| dd00be6dce |
@ -6,12 +6,13 @@ import os
|
||||
if not base.is_dir("glm"):
|
||||
base.cmd("git", ["clone", "https://github.com/g-truc/glm.git"])
|
||||
base.cmd_in_dir("glm", "git", ["checkout", "33b4a621a697a305bc3a7610d290677b96beb181", "--quiet"])
|
||||
base.replaceInFile("./glm/glm/detail/func_common.inl", "vec<L, T, Q> v;", "vec<L, T, Q> v{};")
|
||||
|
||||
if not base.is_dir("mdds"):
|
||||
base.cmd("git", ["clone", "https://github.com/kohei-us/mdds.git"])
|
||||
base.cmd_in_dir("mdds", "git", ["checkout", "0783158939c6ce4b0b1b89e345ab983ccb0f0ad0"], "--quiet")
|
||||
|
||||
fix_cpp_version = "#if __cplusplus < 201402L\n"
|
||||
fix_cpp_version = "#if __cplusplus < 201703L\n"
|
||||
fix_cpp_version += "#ifndef _MSC_VER\n"
|
||||
fix_cpp_version += "namespace std {\n"
|
||||
fix_cpp_version += " template<bool __v>\n"
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
|
||||
#include <iostream>
|
||||
#include "../../../../../DesktopEditor/common/File.h"
|
||||
#include "StaticFunctions.h"
|
||||
#include "ConstValues.h"
|
||||
@ -18,14 +17,16 @@ namespace NSCSS
|
||||
{
|
||||
typedef std::map<std::wstring, std::wstring>::const_iterator styles_iterator;
|
||||
|
||||
CCompiledStyle::CCompiledStyle() : m_nDpi(96), m_UnitMeasure(Point), m_dCoreFontSize(DEFAULT_FONT_SIZE)
|
||||
CCompiledStyle::CCompiledStyle()
|
||||
: m_nDpi(96), m_UnitMeasure(Point), m_dCoreFontSize(DEFAULT_FONT_SIZE)
|
||||
{}
|
||||
|
||||
CCompiledStyle::CCompiledStyle(const CCompiledStyle& oStyle) :
|
||||
m_arParentsStyles(oStyle.m_arParentsStyles), m_sId(oStyle.m_sId),
|
||||
m_nDpi(oStyle.m_nDpi), m_UnitMeasure(oStyle.m_UnitMeasure), m_dCoreFontSize(oStyle.m_dCoreFontSize),
|
||||
m_oFont(oStyle.m_oFont), m_oMargin(oStyle.m_oMargin), m_oPadding(oStyle.m_oPadding), m_oBackground(oStyle.m_oBackground),
|
||||
m_oText(oStyle.m_oText), m_oBorder(oStyle.m_oBorder), m_oDisplay(oStyle.m_oDisplay), m_oTransform(oStyle.m_oTransform){}
|
||||
m_oText(oStyle.m_oText), m_oBorder(oStyle.m_oBorder), m_oDisplay(oStyle.m_oDisplay), m_oTransform(oStyle.m_oTransform)
|
||||
{}
|
||||
|
||||
CCompiledStyle::~CCompiledStyle()
|
||||
{
|
||||
@ -34,6 +35,8 @@ namespace NSCSS
|
||||
|
||||
CCompiledStyle& CCompiledStyle::operator+= (const CCompiledStyle &oElement)
|
||||
{
|
||||
m_arParentsStyles.insert(oElement.m_arParentsStyles.begin(), oElement.m_arParentsStyles.end());
|
||||
|
||||
if (oElement.Empty())
|
||||
return *this;
|
||||
|
||||
@ -49,8 +52,6 @@ namespace NSCSS
|
||||
if (!oElement.m_sId.empty())
|
||||
m_sId += L'+' + oElement.m_sId;
|
||||
|
||||
m_arParentsStyles.insert(oElement.m_arParentsStyles.begin(), oElement.m_arParentsStyles.end());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ -15,29 +15,33 @@ inline static std::wstring StringifyValueList(const KatanaArray* oValues);
|
||||
inline static std::wstring StringifyValue(const KatanaValue* oValue);
|
||||
inline static bool IsTableElement(const std::wstring& wsNameTag);
|
||||
|
||||
bool operator<(const std::vector<NSCSS::CNode> &arLeftSelectors, const std::vector<NSCSS::CNode> &arRightSelectors)
|
||||
{
|
||||
const size_t& sizeLeftSelectors = arLeftSelectors.size();
|
||||
const size_t& sizeRightSelectors = arRightSelectors.size();
|
||||
|
||||
if (sizeLeftSelectors < sizeRightSelectors)
|
||||
return true;
|
||||
else if (sizeLeftSelectors > sizeRightSelectors)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < arLeftSelectors.size(); ++i)
|
||||
{
|
||||
if (arLeftSelectors[i] < arRightSelectors[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace NSCSS
|
||||
{
|
||||
bool operator<(const std::vector<NSCSS::CNode> &arLeftSelectors, const std::vector<NSCSS::CNode> &arRightSelectors)
|
||||
{
|
||||
if (arLeftSelectors.size() < arRightSelectors.size())
|
||||
return true;
|
||||
else if (arLeftSelectors.size() > arRightSelectors.size())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < arLeftSelectors.size(); ++i)
|
||||
{
|
||||
if (arLeftSelectors[i] == arRightSelectors[i])
|
||||
continue;
|
||||
|
||||
if (arLeftSelectors[i] < arRightSelectors[i])
|
||||
return true;
|
||||
else if (arRightSelectors[i] < arLeftSelectors[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CStyleStorage::CStyleStorage()
|
||||
{}
|
||||
{
|
||||
InitDefaultStyles();
|
||||
}
|
||||
|
||||
CStyleStorage::~CStyleStorage()
|
||||
{
|
||||
@ -62,6 +66,7 @@ namespace NSCSS
|
||||
m_arEmptyStyleFiles.clear();
|
||||
|
||||
ClearEmbeddedStyles();
|
||||
ClearDefaultStyles();
|
||||
ClearAllowedStyleFiles();
|
||||
|
||||
#ifdef CSS_CALCULATOR_WITH_XHTML
|
||||
@ -208,6 +213,16 @@ namespace NSCSS
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CElement* CStyleStorage::FindDefaultElement(const std::wstring& wsSelector) const
|
||||
{
|
||||
if (wsSelector.empty())
|
||||
return nullptr;
|
||||
|
||||
const CElement* pFoundElement = FindSelectorFromStyleData(wsSelector, m_mDefaultStyleData);
|
||||
|
||||
return (nullptr != pFoundElement) ? pFoundElement : nullptr;
|
||||
}
|
||||
|
||||
void CStyleStorage::AddStyles(const std::string& sStyle, std::map<std::wstring, CElement*>& mStyleData)
|
||||
{
|
||||
if (sStyle.empty())
|
||||
@ -227,6 +242,15 @@ namespace NSCSS
|
||||
m_mEmbeddedStyleData.clear();
|
||||
}
|
||||
|
||||
void CStyleStorage::ClearDefaultStyles()
|
||||
{
|
||||
for (std::map<std::wstring, CElement*>::iterator oIter = m_mDefaultStyleData.begin(); oIter != m_mDefaultStyleData.end(); ++oIter)
|
||||
if (oIter->second != nullptr)
|
||||
delete oIter->second;
|
||||
|
||||
m_mDefaultStyleData.clear();
|
||||
}
|
||||
|
||||
void CStyleStorage::ClearAllowedStyleFiles()
|
||||
{
|
||||
m_arAllowedStyleFiles.clear();
|
||||
@ -480,7 +504,33 @@ namespace NSCSS
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CCssCalculator_Private::CCssCalculator_Private() : m_nDpi(96), m_nCountNodes(0), m_sEncoding(L"UTF-8"){}
|
||||
void CStyleStorage::InitDefaultStyles()
|
||||
{
|
||||
m_mDefaultStyleData[L"b"] = new CElement(L"b", {{L"font-weight", L"bold"}});
|
||||
m_mDefaultStyleData[L"center"] = new CElement(L"center", {{L"text-align", L"center"}});
|
||||
m_mDefaultStyleData[L"i"] = new CElement(L"i", {{L"font-style", L"italic"}});
|
||||
m_mDefaultStyleData[L"code"] = new CElement(L"code", {{L"font-family", L"Courier New"}});
|
||||
m_mDefaultStyleData[L"kbd"] = new CElement(L"kbd", {{L"font-family", L"Courier New"},
|
||||
{L"font_weight", L"bold"}});
|
||||
m_mDefaultStyleData[L"s"] = new CElement(L"s", {{L"text-decoration", L"line-through"}});
|
||||
m_mDefaultStyleData[L"u"] = new CElement(L"u", {{L"text-decoration", L"underline"}});
|
||||
m_mDefaultStyleData[L"mark"] = new CElement(L"mark", {{L"background-color", L"yellow"}});
|
||||
m_mDefaultStyleData[L"sup"] = new CElement(L"sup", {{L"vertical-align", L"top"}});
|
||||
m_mDefaultStyleData[L"sub"] = new CElement(L"sub", {{L"vertical-align", L"bottom"}});
|
||||
m_mDefaultStyleData[L"dd"] = new CElement(L"dd", {{L"margin-left", L"720tw"}});
|
||||
m_mDefaultStyleData[L"pre"] = new CElement(L"pre", {{L"font-family", L"Courier New"},
|
||||
{L"margin-top", L"0"},
|
||||
{L"margin-bottom", L"0"}});
|
||||
m_mDefaultStyleData[L"blockquote"] = new CElement(L"blockquote", {{L"margin", L"0px"}});
|
||||
m_mDefaultStyleData[L"ul"] = new CElement(L"ul", {{L"margin-top", L"100tw"},
|
||||
{L"margin-bottom", L"100tw"}});
|
||||
m_mDefaultStyleData[L"textarea"] = new CElement(L"textarea", {{L"border", L"1px solid black"}});
|
||||
}
|
||||
|
||||
CCssCalculator_Private::CCssCalculator_Private()
|
||||
: m_nDpi(96), m_nCountNodes(0), m_sEncoding(L"UTF-8")
|
||||
{
|
||||
}
|
||||
|
||||
CCssCalculator_Private::~CCssCalculator_Private()
|
||||
{}
|
||||
@ -503,12 +553,17 @@ namespace NSCSS
|
||||
arSelectors.back().m_pCompiledStyle->m_oBorder.Clear();
|
||||
}
|
||||
|
||||
if (arSelectors.size() > 1)
|
||||
arSelectors.back().m_pCompiledStyle->AddParent(arSelectors[arSelectors.size() - 2].m_wsName);
|
||||
|
||||
arSelectors.back().m_pCompiledStyle->SetID(L"text-" + std::to_wstring(++m_nCountNodes));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::map<std::vector<CNode>, CCompiledStyle>::iterator oItem = m_mUsedStyles.find(arSelectors);
|
||||
const std::map<std::vector<CNode>, CCompiledStyle>::const_iterator oItem = m_mUsedStyles.find(arSelectors);
|
||||
|
||||
if (oItem != m_mUsedStyles.end())
|
||||
if (oItem != m_mUsedStyles.cend() && (arSelectors.back().m_wsId.empty() || !HaveStylesById(arSelectors.back().m_wsId)))
|
||||
{
|
||||
arSelectors.back().SetCompiledStyle(new CCompiledStyle(oItem->second));
|
||||
return true;
|
||||
@ -542,7 +597,8 @@ namespace NSCSS
|
||||
if (0 != i)
|
||||
*arSelectors[i].m_pCompiledStyle += *arSelectors[i - 1].m_pCompiledStyle;
|
||||
|
||||
arSelectors[i].m_pCompiledStyle->AddParent(arSelectors[i].m_wsName);
|
||||
if (i != arSelectors.size() - 1)
|
||||
arSelectors[i].m_pCompiledStyle->AddParent(arSelectors[i].m_wsName);
|
||||
|
||||
if (!bInTable)
|
||||
bInTable = IsTableElement(arSelectors[i].m_wsName);
|
||||
@ -615,8 +671,8 @@ namespace NSCSS
|
||||
std::vector<std::wstring> arClasses = NS_STATIC_FUNCTIONS::GetWordsW(oNode->m_wsClass, false, L" ");
|
||||
|
||||
arNodes.push_back(std::accumulate(arClasses.begin(), arClasses.end(), std::wstring(),
|
||||
[](std::wstring sRes, const std::wstring& sClass)
|
||||
{return sRes += L'.' + sClass + L' ';}));
|
||||
[](std::wstring sRes, const std::wstring& sClass)
|
||||
{return sRes += L'.' + sClass + L' ';}));
|
||||
}
|
||||
else
|
||||
arNodes.push_back(L'.' + oNode->m_wsClass);
|
||||
@ -644,6 +700,36 @@ namespace NSCSS
|
||||
arFindedElements.insert(arFindedElements.end(), arTempKins.begin(), arTempKins.end());
|
||||
}
|
||||
|
||||
inline std::wstring GetAlternativeDefaultNodeName(const std::wstring& wsNodeName)
|
||||
{
|
||||
if (L"strong" == wsNodeName)
|
||||
return L"b";
|
||||
|
||||
if (L"cite" == wsNodeName || L"dfn" == wsNodeName || L"em" == wsNodeName ||
|
||||
L"var" == wsNodeName || L"adress" == wsNodeName)
|
||||
return L"i";
|
||||
|
||||
if (L"tt" == wsNodeName || L"samp" == wsNodeName)
|
||||
return L"code";
|
||||
|
||||
if (L"strike" == wsNodeName || L"del" == wsNodeName)
|
||||
return L"s";
|
||||
|
||||
if (L"ins" == wsNodeName)
|
||||
return L"u";
|
||||
|
||||
if (L"xmp" == wsNodeName || L"nobr" == wsNodeName)
|
||||
return L"pre";
|
||||
|
||||
if (L"ol" == wsNodeName)
|
||||
return L"ul";
|
||||
|
||||
if (L"fieldset" == wsNodeName)
|
||||
return L"textarea";
|
||||
|
||||
return wsNodeName;
|
||||
}
|
||||
|
||||
std::vector<const CElement*> CCssCalculator_Private::FindElements(std::vector<std::wstring> &arNodes, std::vector<std::wstring> &arNextNodes)
|
||||
{
|
||||
if (arNodes.empty())
|
||||
@ -702,6 +788,11 @@ namespace NSCSS
|
||||
}
|
||||
}
|
||||
|
||||
const CElement* pFoundDefault = m_oStyleStorage.FindDefaultElement(GetAlternativeDefaultNodeName(wsName));
|
||||
|
||||
if (nullptr != pFoundDefault)
|
||||
arFindedElements.push_back(pFoundDefault);
|
||||
|
||||
const CElement* pFoundName = m_oStyleStorage.FindElement(wsName);
|
||||
|
||||
if (nullptr != pFoundName)
|
||||
|
||||
@ -27,6 +27,7 @@ namespace NSCSS
|
||||
void AddStylesFromFile(const std::wstring& wsFileName);
|
||||
|
||||
void ClearEmbeddedStyles();
|
||||
void ClearDefaultStyles();
|
||||
void ClearAllowedStyleFiles();
|
||||
void ClearStylesFromFile(const std::wstring& wsFileName);
|
||||
|
||||
@ -38,6 +39,7 @@ namespace NSCSS
|
||||
#endif
|
||||
|
||||
const CElement* FindElement(const std::wstring& wsSelector) const;
|
||||
const CElement* FindDefaultElement(const std::wstring& wsSelector) const;
|
||||
private:
|
||||
typedef struct
|
||||
{
|
||||
@ -49,6 +51,7 @@ namespace NSCSS
|
||||
std::set<std::wstring> m_arAllowedStyleFiles;
|
||||
std::vector<TStyleFileData*> m_arStyleFiles;
|
||||
std::map<std::wstring, CElement*> m_mEmbeddedStyleData;
|
||||
std::map<std::wstring, CElement*> m_mDefaultStyleData;
|
||||
|
||||
#ifdef CSS_CALCULATOR_WITH_XHTML
|
||||
typedef struct
|
||||
@ -78,6 +81,8 @@ namespace NSCSS
|
||||
void GetOutputData(KatanaOutput* oOutput, std::map<std::wstring, CElement*>& mStyleData);
|
||||
|
||||
const CElement* FindSelectorFromStyleData(const std::wstring& wsSelector, const std::map<std::wstring, CElement*>& mStyleData) const;
|
||||
|
||||
void InitDefaultStyles();
|
||||
};
|
||||
|
||||
class CCssCalculator_Private
|
||||
|
||||
@ -9,6 +9,13 @@ namespace NSCSS
|
||||
CElement::CElement()
|
||||
{
|
||||
}
|
||||
|
||||
CElement::CElement(const std::wstring& wsSelector, std::map<std::wstring, std::wstring> mStyle)
|
||||
: m_mStyle(mStyle), m_sSelector(wsSelector), m_sFullSelector(wsSelector)
|
||||
{
|
||||
UpdateWeight();
|
||||
}
|
||||
|
||||
CElement::~CElement()
|
||||
{
|
||||
for (CElement* oElement : m_arPrevElements)
|
||||
@ -18,7 +25,6 @@ namespace NSCSS
|
||||
continue;
|
||||
|
||||
m_mStyle.clear();
|
||||
|
||||
}
|
||||
|
||||
std::wstring CElement::GetSelector() const
|
||||
|
||||
@ -22,6 +22,7 @@ namespace NSCSS
|
||||
|
||||
public:
|
||||
CElement();
|
||||
CElement(const std::wstring& wsSelector, std::map<std::wstring, std::wstring> mStyle);
|
||||
~CElement();
|
||||
|
||||
std::wstring GetSelector() const;
|
||||
|
||||
@ -17,8 +17,7 @@ namespace NSCSS
|
||||
m_wsStyle(oNode.m_wsStyle), m_mAttributes(oNode.m_mAttributes)
|
||||
{
|
||||
#ifdef CSS_CALCULATOR_WITH_XHTML
|
||||
m_pCompiledStyle = new CCompiledStyle();
|
||||
*m_pCompiledStyle = *oNode.m_pCompiledStyle;
|
||||
m_pCompiledStyle = new CCompiledStyle(*oNode.m_pCompiledStyle);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -42,6 +41,23 @@ namespace NSCSS
|
||||
return m_wsName.empty() && m_wsClass.empty() && m_wsId.empty() && m_wsStyle.empty();
|
||||
}
|
||||
|
||||
bool CNode::GetAttributeValue(const std::wstring& wsAttributeName, std::wstring& wsAttributeValue) const
|
||||
{
|
||||
const std::map<std::wstring, std::wstring>::const_iterator itFound{m_mAttributes.find(wsAttributeName)};
|
||||
|
||||
if (m_mAttributes.cend() == itFound)
|
||||
return false;
|
||||
|
||||
wsAttributeValue = itFound->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::wstring CNode::GetAttributeValue(const std::wstring& wsAttributeName) const
|
||||
{
|
||||
const std::map<std::wstring, std::wstring>::const_iterator itFound{m_mAttributes.find(wsAttributeName)};
|
||||
return (m_mAttributes.cend() != itFound) ? itFound->second : std::wstring();
|
||||
}
|
||||
|
||||
#ifdef CSS_CALCULATOR_WITH_XHTML
|
||||
void CNode::SetCompiledStyle(CCompiledStyle* pCompiledStyle)
|
||||
{
|
||||
@ -86,6 +102,9 @@ namespace NSCSS
|
||||
if(m_wsStyle != oNode.m_wsStyle)
|
||||
return m_wsStyle < oNode.m_wsStyle;
|
||||
|
||||
if (m_mAttributes.size() != oNode.m_mAttributes.size())
|
||||
return m_mAttributes.size() < oNode.m_mAttributes.size();
|
||||
|
||||
if (m_mAttributes != oNode.m_mAttributes)
|
||||
return m_mAttributes < oNode.m_mAttributes;
|
||||
|
||||
@ -94,10 +113,9 @@ namespace NSCSS
|
||||
|
||||
bool CNode::operator==(const CNode& oNode) const
|
||||
{
|
||||
return((m_wsId == oNode.m_wsId) &&
|
||||
(m_wsName == oNode.m_wsName) &&
|
||||
(m_wsClass == oNode.m_wsClass) &&
|
||||
(m_wsStyle == oNode.m_wsStyle) &&
|
||||
(m_mAttributes == oNode.m_mAttributes));
|
||||
return((m_wsName == oNode.m_wsName) &&
|
||||
(m_wsClass == oNode.m_wsClass) &&
|
||||
(m_wsStyle == oNode.m_wsStyle) &&
|
||||
(m_mAttributes == oNode.m_mAttributes));
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,9 @@ namespace NSCSS
|
||||
|
||||
bool Empty() const;
|
||||
|
||||
bool GetAttributeValue(const std::wstring& wsAttributeName, std::wstring& wsAttributeValue) const;
|
||||
std::wstring GetAttributeValue(const std::wstring& wsAttributeName) const;
|
||||
|
||||
#ifdef CSS_CALCULATOR_WITH_XHTML
|
||||
void SetCompiledStyle(CCompiledStyle* pCompiledStyle);
|
||||
#endif
|
||||
|
||||
@ -70,7 +70,9 @@ namespace NSCSS
|
||||
R_Shd,
|
||||
R_SmallCaps,
|
||||
R_Kern,
|
||||
R_Vanish
|
||||
R_Vanish,
|
||||
R_Strike,
|
||||
R_VertAlign
|
||||
} RunnerProperties;
|
||||
|
||||
typedef enum
|
||||
|
||||
@ -600,12 +600,6 @@ namespace NSCSS
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CColor::SetNone()
|
||||
{
|
||||
Clear();
|
||||
m_oValue.reset();
|
||||
}
|
||||
|
||||
char NormalizeNegativeColorValue(INT nValue)
|
||||
{
|
||||
@ -647,18 +641,21 @@ namespace NSCSS
|
||||
}
|
||||
else if (L"none" == wsNewValue || wsNewValue == L"transparent")
|
||||
{
|
||||
SetNone();
|
||||
Clear();
|
||||
m_oValue = CColorValue();
|
||||
bResult = true;
|
||||
}
|
||||
else if (L"context-stroke" == wsNewValue)
|
||||
{
|
||||
Clear();
|
||||
m_oValue = CColorValueContextStroke();
|
||||
bResult = true;
|
||||
}
|
||||
else if (L"context-fill" == wsNewValue)
|
||||
{
|
||||
Clear();
|
||||
m_oValue = CColorValueContextFill();
|
||||
bResult = true;
|
||||
}
|
||||
else if (10 <= wsNewValue.length() && wsNewValue.substr(0, 3) == L"rgb")
|
||||
{
|
||||
|
||||
@ -343,7 +343,6 @@ namespace NSCSS
|
||||
void SetRGB(const TRGB& oRGB);
|
||||
void SetHEX(const std::wstring& wsValue);
|
||||
bool SetUrl(const std::wstring& wsValue);
|
||||
void SetNone();
|
||||
};
|
||||
|
||||
typedef enum
|
||||
|
||||
@ -22,6 +22,11 @@ namespace NSCSS
|
||||
: m_oStyle(oStyle), m_bIsPStyle(bIsPStyle)
|
||||
{}
|
||||
|
||||
void CStyleUsed::SetFinalId(const std::wstring& wsFinalId)
|
||||
{
|
||||
m_wsFinalId = wsFinalId;
|
||||
}
|
||||
|
||||
bool CheckArrays(const std::vector<std::wstring>& arInitial, const std::set<std::wstring>& arFirst, const std::set<std::wstring>& arSecond)
|
||||
{
|
||||
std::unordered_set<std::wstring> arInitialSet(arInitial.begin(), arInitial.end());
|
||||
@ -57,19 +62,14 @@ namespace NSCSS
|
||||
m_oStyle == oUsedStyle.m_oStyle;
|
||||
}
|
||||
|
||||
std::wstring CStyleUsed::getId()
|
||||
std::wstring CStyleUsed::GetId() const
|
||||
{
|
||||
if (m_bIsPStyle)
|
||||
return m_oStyle.GetId();
|
||||
|
||||
return m_oStyle.GetId() + L"-c";
|
||||
return m_wsFinalId;
|
||||
}
|
||||
|
||||
CDocumentStyle::CDocumentStyle() : m_arStandardStyles(Names_Standard_Styles)
|
||||
{
|
||||
for (const std::wstring& oNameStandardStyle : Names_Standard_Styles)
|
||||
m_arStandardStyles.push_back(oNameStandardStyle + L"-c");
|
||||
}
|
||||
CDocumentStyle::CDocumentStyle()
|
||||
: m_arStandardStyles(Names_Standard_Styles)
|
||||
{}
|
||||
|
||||
CDocumentStyle::~CDocumentStyle()
|
||||
{
|
||||
@ -85,7 +85,7 @@ namespace NSCSS
|
||||
|
||||
std::wstring CDocumentStyle::GetIdAndClear()
|
||||
{
|
||||
std::wstring sId = m_sId;
|
||||
const std::wstring sId = m_sId;
|
||||
Clear();
|
||||
return sId;
|
||||
}
|
||||
@ -110,10 +110,10 @@ namespace NSCSS
|
||||
m_sId = sId;
|
||||
}
|
||||
|
||||
void CDocumentStyle::CombineStandardStyles(const std::vector<std::wstring>& arStandartedStyles, CXmlElement& oElement)
|
||||
bool CDocumentStyle::CombineStandardStyles(const std::vector<std::wstring>& arStandartedStyles, CXmlElement& oElement)
|
||||
{
|
||||
if (arStandartedStyles.empty())
|
||||
return;
|
||||
return false;
|
||||
|
||||
std::vector<std::wstring> arStyles;
|
||||
for (const std::wstring& sStyleName : arStandartedStyles)
|
||||
@ -123,7 +123,7 @@ namespace NSCSS
|
||||
}
|
||||
|
||||
if (arStyles.empty())
|
||||
return;
|
||||
return false;
|
||||
|
||||
std::wstring sId;
|
||||
for (std::vector<std::wstring>::const_reverse_iterator iStyleName = arStyles.rbegin(); iStyleName != arStyles.rend(); ++iStyleName)
|
||||
@ -142,18 +142,25 @@ namespace NSCSS
|
||||
|
||||
oElement.AddBasicProperties(BProperties::B_Name, sId);
|
||||
oElement.AddBasicProperties(BProperties::B_StyleId, sId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDocumentStyle::CreateStandardStyle(const std::wstring& sNameStyle, CXmlElement& oElement)
|
||||
bool CDocumentStyle::CreateStandardStyle(const std::wstring& sNameStyle, CXmlElement& oElement)
|
||||
{
|
||||
if (std::find(m_arStandardStyles.begin(), m_arStandardStyles.end(), sNameStyle) != m_arStandardStyles.end())
|
||||
{
|
||||
oElement.CreateDefaultElement(sNameStyle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CDocumentStyle::ConvertStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oElement, bool bIsPStyle)
|
||||
bool CDocumentStyle::ConvertStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oElement, bool bIsPStyle)
|
||||
{
|
||||
if (oStyle.GetId().empty())
|
||||
return;
|
||||
return false;
|
||||
|
||||
std::wstring sName = oStyle.GetId();
|
||||
const size_t posPoint = sName.find(L'.');
|
||||
@ -183,25 +190,25 @@ namespace NSCSS
|
||||
for (std::wstring& sParentName : arParentsName)
|
||||
sParentName += L"-c";
|
||||
|
||||
bool bResult{false};
|
||||
|
||||
if (!arParentsName.empty())
|
||||
{
|
||||
CombineStandardStyles(arParentsName, oParentStyle);
|
||||
bResult = CombineStandardStyles(arParentsName, oParentStyle);
|
||||
|
||||
if (!oParentStyle.Empty())
|
||||
{
|
||||
oParentStyle.AddBasicProperties(BProperties::B_BasedOn, L"normal");
|
||||
oParentStyle.AddBasicProperties(BProperties::B_StyleId, L"(" + oParentStyle.GetStyleId() + L")");
|
||||
oParentStyle.AddBasicProperties(BProperties::B_StyleId, oParentStyle.GetStyleId());
|
||||
if (!bIsPStyle)
|
||||
{
|
||||
oParentStyle.AddBasicProperties(BProperties::B_StyleId, oParentStyle.GetStyleId() + L"-c");
|
||||
oParentStyle.AddBasicProperties(BProperties::B_Type, L"character");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CXmlElement oStandardXmlElement;
|
||||
if (std::find(m_arStandardStyles.begin(), m_arStandardStyles.end(), sName) != m_arStandardStyles.end())
|
||||
CreateStandardStyle(sName, oStandardXmlElement);
|
||||
if (CreateStandardStyle(sName, oStandardXmlElement))
|
||||
bResult = true;
|
||||
|
||||
if (oStandardXmlElement.Empty() && !oParentStyle.Empty())
|
||||
{
|
||||
@ -221,7 +228,7 @@ namespace NSCSS
|
||||
if (oStyle.Empty())
|
||||
{
|
||||
m_sId = sParentsStyleID;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
oElement.AddBasicProperties(BProperties::B_BasedOn, sParentsStyleID);
|
||||
@ -234,7 +241,7 @@ namespace NSCSS
|
||||
if (oStyle.Empty())
|
||||
{
|
||||
m_sId = sStandPlusParent;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
oElement.AddBasicProperties(BProperties::B_BasedOn, sStandPlusParent);
|
||||
}
|
||||
@ -258,7 +265,7 @@ namespace NSCSS
|
||||
if (oStyle.Empty())
|
||||
{
|
||||
m_sId = sStandPlusParent;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
oElement.AddBasicProperties(BProperties::B_BasedOn, oTempElement.GetStyleId());
|
||||
}
|
||||
@ -281,7 +288,7 @@ namespace NSCSS
|
||||
if (oStyle.Empty())
|
||||
{
|
||||
m_sId = sStandartStyleID;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
oElement.AddBasicProperties(BProperties::B_BasedOn, sStandartStyleID);
|
||||
}
|
||||
@ -289,7 +296,7 @@ namespace NSCSS
|
||||
if (oStyle.Empty() && oElement.Empty())
|
||||
{
|
||||
m_sId = L"normal";
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_sId = oStyle.GetId();
|
||||
@ -302,15 +309,19 @@ namespace NSCSS
|
||||
oElement.AddBasicProperties(BProperties::B_Name, m_sId);
|
||||
oElement.AddBasicProperties(BProperties::B_Type, bIsPStyle ? L"paragraph" : L"character");
|
||||
oElement.AddBasicProperties(BProperties::B_CustomStyle, L"1");
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
void CDocumentStyle::SetPStyle (const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement, bool bIsLite)
|
||||
bool CDocumentStyle::SetPStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement, bool bIsLite)
|
||||
{
|
||||
bool bResult{false};
|
||||
|
||||
if (!bIsLite)
|
||||
ConvertStyle(oStyle, oXmlElement, true);
|
||||
bResult = ConvertStyle(oStyle, oXmlElement, true);
|
||||
|
||||
if (oStyle.Empty())
|
||||
return;
|
||||
return bResult;
|
||||
|
||||
const bool bInTable{oStyle.HaveThisParent(L"table")};
|
||||
|
||||
@ -390,6 +401,8 @@ namespace NSCSS
|
||||
SetBorderStyle(oStyle, oXmlElement, PProperties::P_LeftBorder);
|
||||
}
|
||||
}
|
||||
|
||||
return bResult || !oXmlElement.Empty();
|
||||
}
|
||||
|
||||
void CDocumentStyle::SetBorderStyle(const CCompiledStyle &oStyle, CXmlElement &oXmlElement, const PProperties &enBorderProperty)
|
||||
@ -473,13 +486,15 @@ namespace NSCSS
|
||||
return L"w:val=\"" + wsStyle + L"\" w:sz=\"" + std::to_wstring(nWidth) + + L"\" w:space=\"" + std::to_wstring(nSpace) + L"\" w:color=\"" + wsColor + L"\"";
|
||||
}
|
||||
|
||||
void CDocumentStyle::SetRStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement, bool bIsLite)
|
||||
bool CDocumentStyle::SetRStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement, bool bIsLite)
|
||||
{
|
||||
bool bResult{false};
|
||||
|
||||
if (!bIsLite)
|
||||
ConvertStyle(oStyle, oXmlElement, false);
|
||||
bResult = ConvertStyle(oStyle, oXmlElement, false);
|
||||
|
||||
if (oStyle.Empty() && oXmlElement.Empty())
|
||||
return;
|
||||
return bResult;
|
||||
|
||||
if (!oStyle.m_oFont.GetSize().Empty())
|
||||
oXmlElement.AddPropertiesInR(RProperties::R_Sz, std::to_wstring(static_cast<int>(oStyle.m_oFont.GetSize().ToDouble(NSCSS::Point) * 2. * oStyle.m_oTransform.GetMatrix().GetFinalValue().sy() + 0.5))); // Значения шрифта увеличивает на 2
|
||||
@ -516,6 +531,18 @@ namespace NSCSS
|
||||
oXmlElement.AddPropertiesInR(RProperties::R_I, oStyle.m_oFont.GetStyle().ToWString());
|
||||
oXmlElement.AddPropertiesInR(RProperties::R_B, oStyle.m_oFont.GetWeight().ToWString());
|
||||
oXmlElement.AddPropertiesInR(RProperties::R_SmallCaps, oStyle.m_oFont.GetVariant().ToWString());
|
||||
|
||||
if (oStyle.m_oText.LineThrough())
|
||||
{
|
||||
if (L"double" == oStyle.m_oText.GetDecoration().m_oStyle.ToWString())
|
||||
oXmlElement.AddPropertiesInR(RProperties::R_Strike, L"dstrike");
|
||||
else
|
||||
oXmlElement.AddPropertiesInR(RProperties::R_Strike, L"strike");
|
||||
}
|
||||
|
||||
oXmlElement.AddPropertiesInR(RProperties::R_VertAlign, oStyle.m_oDisplay.GetVAlign().ToWString());
|
||||
|
||||
return bResult || !oXmlElement.Empty();
|
||||
}
|
||||
|
||||
bool CDocumentStyle::WriteRStyle(const NSCSS::CCompiledStyle& oStyle)
|
||||
@ -531,16 +558,16 @@ namespace NSCSS
|
||||
|
||||
if (oItem != m_arStyleUsed.end())
|
||||
{
|
||||
m_sId = (*oItem).getId();
|
||||
m_sId = (*oItem).GetId();
|
||||
return true;
|
||||
}
|
||||
|
||||
CXmlElement oXmlElement;
|
||||
SetRStyle(oStyle, oXmlElement);
|
||||
|
||||
if (oXmlElement.Empty())
|
||||
if (!SetRStyle(oStyle, oXmlElement))
|
||||
return false;
|
||||
|
||||
structStyle.SetFinalId(m_sId);
|
||||
m_arStyleUsed.push_back(structStyle);
|
||||
m_sStyle += oXmlElement.GetRStyle();
|
||||
|
||||
@ -593,16 +620,16 @@ namespace NSCSS
|
||||
|
||||
if (oItem != m_arStyleUsed.end())
|
||||
{
|
||||
m_sId = (*oItem).getId();
|
||||
m_sId = (*oItem).GetId();
|
||||
return true;
|
||||
}
|
||||
|
||||
CXmlElement oXmlElement;
|
||||
SetPStyle(oStyle, oXmlElement);
|
||||
|
||||
if (oXmlElement.Empty())
|
||||
if (!SetPStyle(oStyle, oXmlElement))
|
||||
return false;
|
||||
|
||||
structStyle.SetFinalId(m_sId);
|
||||
m_arStyleUsed.push_back(structStyle);
|
||||
m_sStyle += oXmlElement.GetPStyle();
|
||||
|
||||
|
||||
@ -12,16 +12,19 @@ namespace NSCSS
|
||||
{
|
||||
CCompiledStyle m_oStyle;
|
||||
bool m_bIsPStyle;
|
||||
std::wstring m_wsFinalId;
|
||||
|
||||
public:
|
||||
CStyleUsed(const CCompiledStyle& oStyle, bool bIsPStyle);
|
||||
|
||||
void SetFinalId(const std::wstring& wsFinalId);
|
||||
|
||||
bool operator==(const CStyleUsed& oUsedStyle) const;
|
||||
|
||||
std::wstring getId();
|
||||
std::wstring GetId() const;
|
||||
};
|
||||
|
||||
static const std::vector<std::wstring> Names_Standard_Styles = {L"a", L"li", L"h1", L"h2", L"h3", L"h4", L"h5", L"h6",L"p", L"div"};
|
||||
static const std::vector<std::wstring> Names_Standard_Styles = {L"a", L"a-c", L"li", L"h1", L"h2", L"h3", L"h4", L"h5", L"h6", L"h1-c", L"h2-c", L"h3-c", L"h4-c", L"h5-c", L"h6-c"};
|
||||
|
||||
class CSSCALCULATOR_EXPORT CDocumentStyle
|
||||
{
|
||||
@ -36,12 +39,12 @@ namespace NSCSS
|
||||
std::wstring m_sStyle;
|
||||
std::wstring m_sId;
|
||||
|
||||
void CombineStandardStyles(const std::vector<std::wstring>& arStandartedStyles, CXmlElement& oElement);
|
||||
void CreateStandardStyle (const std::wstring& sNameStyle, CXmlElement& oElement);
|
||||
void ConvertStyle (const NSCSS::CCompiledStyle& oStyle, CXmlElement& oElement, bool bIsPStyle);
|
||||
bool CombineStandardStyles(const std::vector<std::wstring>& arStandartedStyles, CXmlElement& oElement);
|
||||
bool CreateStandardStyle (const std::wstring& sNameStyle, CXmlElement& oElement);
|
||||
bool ConvertStyle (const NSCSS::CCompiledStyle& oStyle, CXmlElement& oElement, bool bIsPStyle);
|
||||
|
||||
void SetRStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement, bool bIsLite = false);
|
||||
void SetPStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement, bool bIsLite = false);
|
||||
bool SetRStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement, bool bIsLite = false);
|
||||
bool SetPStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement, bool bIsLite = false);
|
||||
|
||||
void SetBorderStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement, const PProperties& enBorderProperty);
|
||||
public:
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
#include <cwctype>
|
||||
#include <functional>
|
||||
|
||||
#include <iostream>
|
||||
#include "../ConstValues.h"
|
||||
|
||||
#define DEFAULTFONTNAME L"Times New Roman"
|
||||
@ -67,7 +66,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h1-c");
|
||||
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"0");
|
||||
// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
}
|
||||
else if (sNameDefaultElement == L"h2")
|
||||
{
|
||||
@ -78,7 +77,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h2-c");
|
||||
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"1");
|
||||
// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
}
|
||||
else if (sNameDefaultElement == L"h3")
|
||||
{
|
||||
@ -89,7 +88,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h3-c");
|
||||
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"2");
|
||||
// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
}
|
||||
else if (sNameDefaultElement == L"h4")
|
||||
{
|
||||
@ -100,7 +99,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h4-c");
|
||||
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"3");
|
||||
// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
}
|
||||
else if (sNameDefaultElement == L"h5")
|
||||
{
|
||||
@ -111,7 +110,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h5-c");
|
||||
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"4");
|
||||
// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
|
||||
}
|
||||
else if (sNameDefaultElement == L"h6")
|
||||
@ -123,13 +122,13 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h6-c");
|
||||
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"5");
|
||||
// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
|
||||
}
|
||||
else if (sNameDefaultElement == L"h1-c")
|
||||
{
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Type, L"character");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_StyleId, L"h1-c");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Title 1 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Heading 1 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_CustomStyle, L"1");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_UiPriority, L"9");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h1");
|
||||
@ -142,7 +141,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
|
||||
{
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Type, L"character");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_StyleId, L"h2-c");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Title 2 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Heading 2 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_CustomStyle, L"1");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_UiPriority, L"9");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
|
||||
@ -155,7 +154,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
|
||||
{
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Type, L"character");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_StyleId, L"h3-c");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Title 3 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Heading 3 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_CustomStyle, L"1");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_UiPriority, L"9");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
|
||||
@ -168,7 +167,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
|
||||
{
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Type, L"character");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_StyleId, L"h4-c");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Title 4 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Heading 4 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_CustomStyle, L"1");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_UiPriority, L"9");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
|
||||
@ -181,7 +180,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
|
||||
{
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Type, L"character");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_StyleId, L"h5-c");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Title 5 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Heading 5 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_CustomStyle, L"1");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_UiPriority, L"9");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
|
||||
@ -194,7 +193,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
|
||||
{
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Type, L"character");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_StyleId, L"h6-c");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Title 6 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Heading 6 Sign");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_CustomStyle, L"1");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_UiPriority, L"9");
|
||||
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
|
||||
@ -479,6 +478,19 @@ std::wstring CXmlElement::ConvertRStyle(bool bIsLite) const
|
||||
sRStyle += L"<w:vanish/>";
|
||||
break;
|
||||
}
|
||||
case CSSProperties::RunnerProperties::R_Strike:
|
||||
{
|
||||
sRStyle += L"<w:" + oItem.second + L"/>";
|
||||
break;
|
||||
}
|
||||
case CSSProperties::RunnerProperties::R_VertAlign:
|
||||
{
|
||||
if (L"top" == oItem.second)
|
||||
sRStyle += L"<w:vertAlign w:val=\"superscript\"/>";
|
||||
else if (L"bottom" == oItem.second)
|
||||
sRStyle += L"<w:vertAlign w:val=\"subscript\"/>";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -7,4 +7,5 @@ core_windows:INCLUDEPATH += $$PWD/gumbo-parser/visualc/include
|
||||
HEADERS += $$files($$PWD/gumbo-parser/src/*.h, true) \
|
||||
$$PWD/htmltoxhtml.h
|
||||
|
||||
SOURCES += $$files($$PWD/gumbo-parser/src/*.c, true)
|
||||
SOURCES += $$files($$PWD/gumbo-parser/src/*.c, true) \
|
||||
$$PWD/htmltoxhtml.cpp
|
||||
|
||||
657
Common/3dParty/html/htmltoxhtml.cpp
Normal file
657
Common/3dParty/html/htmltoxhtml.cpp
Normal file
@ -0,0 +1,657 @@
|
||||
#include "htmltoxhtml.h"
|
||||
|
||||
#include <map>
|
||||
#include <cctype>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "gumbo-parser/src/gumbo.h"
|
||||
#include "../../../DesktopEditor/common/File.h"
|
||||
#include "../../../DesktopEditor/common/Directory.h"
|
||||
#include "../../../DesktopEditor/common/StringBuilder.h"
|
||||
#include "../../../UnicodeConverter/UnicodeConverter.h"
|
||||
#include "../../../HtmlFile2/src/StringFinder.h"
|
||||
|
||||
namespace HTML
|
||||
{
|
||||
#if defined(CreateDirectory)
|
||||
#undef CreateDirectory
|
||||
#endif
|
||||
|
||||
static std::string nonbreaking_inline = "|a|abbr|acronym|b|bdo|big|cite|code|dfn|em|font|i|img|kbd|nobr|s|small|span|strike|strong|sub|sup|tt|";
|
||||
static std::string empty_tags = "|area|base|basefont|bgsound|br|command|col|embed|event-source|frame|hr|image|img|input|keygen|link|menuitem|meta|param|source|spacer|track|wbr|";
|
||||
static std::string preserve_whitespace = "|pre|textarea|script|style|";
|
||||
static std::string special_handling = "|html|body|";
|
||||
static std::string treat_like_inline = "|p|";
|
||||
|
||||
static std::vector<std::string> html_tags = {"div","span","a","img","p","h1","h2","h3","h4","h5","h6",
|
||||
"ul", "ol", "li","td","tr","table","thead","tbody","tfoot","th",
|
||||
"br","form","input","button","section","nav","header","footer",
|
||||
"main","figure","figcaption","strong","em","i", "b", "u","pre",
|
||||
"code","blockquote","hr","script","link","meta","style","title",
|
||||
"head","body","html","legend","optgroup","option","select","dl",
|
||||
"dt","dd","time","data","abbr","address","area","base","bdi",
|
||||
"bdo","cite","col","iframe","video","source","track","textarea",
|
||||
"label","fieldset","colgroup","del","ins","details","summary",
|
||||
"dialog","embed","kbd","map","mark","menu","meter","object",
|
||||
"output","param","progress","q","samp","small","sub","sup","var",
|
||||
"wbr","acronym","applet","article","aside","audio","basefont",
|
||||
"bgsound","big","blink","canvas","caption","center","command",
|
||||
"comment","datalist","dfn","dir","font","frame","frameset",
|
||||
"hgroup","isindex","keygen","marquee","nobr","noembed","noframes",
|
||||
"noscript","plaintext","rp","rt","ruby","s","strike","tt","xmp"};
|
||||
|
||||
static std::vector<std::string> unchecked_nodes_new = {"svg"};
|
||||
|
||||
static void replace_all(std::string& s, const std::string& s1, const std::string& s2)
|
||||
{
|
||||
size_t pos = s.find(s1);
|
||||
while(pos != std::string::npos)
|
||||
{
|
||||
s.replace(pos, s1.length(), s2);
|
||||
pos = s.find(s1, pos + s2.length());
|
||||
}
|
||||
}
|
||||
|
||||
static bool NodeIsUnprocessed(const std::string& sTagName)
|
||||
{
|
||||
return "xml" == sTagName;
|
||||
}
|
||||
|
||||
static bool IsUnckeckedNodes(const std::string& sValue)
|
||||
{
|
||||
return unchecked_nodes_new.end() != std::find(unchecked_nodes_new.begin(), unchecked_nodes_new.end(), sValue);
|
||||
}
|
||||
|
||||
static std::string Base64ToString(const std::string& sContent, const std::string& sCharset)
|
||||
{
|
||||
std::string sRes;
|
||||
int nSrcLen = (int)sContent.length();
|
||||
int nDecodeLen = NSBase64::Base64DecodeGetRequiredLength(nSrcLen);
|
||||
BYTE* pData = new BYTE[nDecodeLen];
|
||||
if (TRUE == NSBase64::Base64Decode(sContent.c_str(), nSrcLen, pData, &nDecodeLen))
|
||||
{
|
||||
std::wstring sConvert;
|
||||
if(!sCharset.empty() && NSStringFinder::Equals<std::string>("utf-8", sCharset))
|
||||
{
|
||||
NSUnicodeConverter::CUnicodeConverter oConverter;
|
||||
sConvert = oConverter.toUnicode(reinterpret_cast<char *>(pData), (unsigned)nDecodeLen, sCharset.data());
|
||||
}
|
||||
sRes = sConvert.empty() ? std::string(reinterpret_cast<char *>(pData), nDecodeLen) : U_TO_UTF8(sConvert);
|
||||
}
|
||||
RELEASEARRAYOBJECTS(pData);
|
||||
return sRes;
|
||||
}
|
||||
|
||||
static std::string QuotedPrintableDecode(const std::string& sContent, std::string& sCharset)
|
||||
{
|
||||
NSStringUtils::CStringBuilderA sRes;
|
||||
size_t ip = 0;
|
||||
size_t i = sContent.find('=');
|
||||
|
||||
if(i == 0)
|
||||
{
|
||||
size_t nIgnore = 12;
|
||||
std::string charset = sContent.substr(0, nIgnore);
|
||||
if(charset == "=00=00=FE=FF")
|
||||
sCharset = "UTF-32BE";
|
||||
else if(charset == "=FF=FE=00=00")
|
||||
sCharset = "UTF-32LE";
|
||||
else if(charset == "=2B=2F=76=38" || charset == "=2B=2F=76=39" ||
|
||||
charset == "=2B=2F=76=2B" || charset == "=2B=2F=76=2F")
|
||||
sCharset = "UTF-7";
|
||||
else if(charset == "=DD=73=66=73")
|
||||
sCharset = "UTF-EBCDIC";
|
||||
else if(charset == "=84=31=95=33")
|
||||
sCharset = "GB-18030";
|
||||
else
|
||||
{
|
||||
nIgnore -= 3;
|
||||
charset.erase(nIgnore);
|
||||
if(charset == "=EF=BB=BF")
|
||||
sCharset = "UTF-8";
|
||||
else if(charset == "=F7=64=4C")
|
||||
sCharset = "UTF-1";
|
||||
else if(charset == "=0E=FE=FF")
|
||||
sCharset = "SCSU";
|
||||
else if(charset == "=FB=EE=28")
|
||||
sCharset = "BOCU-1";
|
||||
else
|
||||
{
|
||||
nIgnore -= 3;
|
||||
charset.erase(nIgnore);
|
||||
if(charset == "=FE=FF")
|
||||
sCharset = "UTF-16BE";
|
||||
else if(charset == "=FF=FE")
|
||||
sCharset = "UTF-16LE";
|
||||
else
|
||||
nIgnore -= 6;
|
||||
}
|
||||
}
|
||||
|
||||
ip = nIgnore;
|
||||
i = sContent.find('=', ip);
|
||||
}
|
||||
|
||||
while(i != std::string::npos && i + 2 < sContent.length())
|
||||
{
|
||||
sRes.WriteString(sContent.c_str() + ip, i - ip);
|
||||
std::string str = sContent.substr(i + 1, 2);
|
||||
if(str.front() == '\n' || str.front() == '\r')
|
||||
{
|
||||
char ch = str[1];
|
||||
if(ch != '\n' && ch != '\r')
|
||||
sRes.WriteString(&ch, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
char* err;
|
||||
char ch = (int)strtol(str.data(), &err, 16);
|
||||
if(*err)
|
||||
sRes.WriteString('=' + str);
|
||||
else
|
||||
sRes.WriteString(&ch, 1);
|
||||
}
|
||||
ip = i + 3;
|
||||
i = sContent.find('=', ip);
|
||||
}
|
||||
if(ip != std::string::npos)
|
||||
sRes.WriteString(sContent.c_str() + ip);
|
||||
return sRes.GetData();
|
||||
}
|
||||
|
||||
static std::string mhtTohtml(const std::string& sFileContent);
|
||||
|
||||
static void ReadMht(const std::string& sMhtContent, std::map<std::string, std::string>& sRes, NSStringUtils::CStringBuilderA& oRes)
|
||||
{
|
||||
size_t unContentPosition = 0, unCharsetBegin = 0, unCharsetEnd = std::string::npos;
|
||||
|
||||
NSStringFinder::TFoundedData<char> oData;
|
||||
|
||||
// Content-Type
|
||||
oData = NSStringFinder::FindProperty(sMhtContent, "content-type", {":"}, {";", "\\n", "\\r"});
|
||||
const std::string sContentType{oData.m_sValue};
|
||||
|
||||
if (sContentType.empty())
|
||||
return;
|
||||
|
||||
if (NSStringFinder::Equals(sContentType, "multipart/alternative"))
|
||||
{
|
||||
oRes.WriteString(mhtTohtml(sMhtContent.substr(oData.m_unEndPosition, sMhtContent.length() - oData.m_unEndPosition)));
|
||||
return;
|
||||
}
|
||||
|
||||
unContentPosition = std::max(unContentPosition, oData.m_unEndPosition);
|
||||
unCharsetBegin = oData.m_unEndPosition;
|
||||
|
||||
// name
|
||||
// std::string sName = NSStringFinder::FindProperty(sMhtContent, "name", {"="}, {";", "\\n", "\\r"}, 0, unLastPosition);
|
||||
// unContentPosition = std::max(unContentPosition, unLastPosition);
|
||||
|
||||
// Content-Location
|
||||
oData = NSStringFinder::FindProperty(sMhtContent, "content-location", {":"}, {";", "\\n", "\\r"});
|
||||
std::string sContentLocation{oData.m_sValue};
|
||||
|
||||
if (!oData.Empty())
|
||||
unContentPosition = std::max(unContentPosition, oData.m_unEndPosition);
|
||||
|
||||
// Content-ID
|
||||
oData = NSStringFinder::FindProperty(sMhtContent, "content-id", {":"}, {";", "\\n", "\\r"});
|
||||
std::string sContentID{oData.m_sValue};
|
||||
|
||||
if (!oData.Empty())
|
||||
{
|
||||
unContentPosition = std::max(unContentPosition, oData.m_unEndPosition);
|
||||
unCharsetEnd = std::min(unCharsetEnd, oData.m_unBeginPosition);
|
||||
NSStringFinder::CutInside<std::string>(sContentID, "<", ">");
|
||||
}
|
||||
|
||||
if (sContentLocation.empty() && !sContentID.empty())
|
||||
sContentLocation = "cid:" + sContentID;
|
||||
|
||||
// Content-Transfer-Encoding
|
||||
oData = NSStringFinder::FindProperty(sMhtContent, "content-transfer-encoding", {":"}, {";", "\\n", "\\r"});
|
||||
const std::string sContentEncoding{oData.m_sValue};
|
||||
|
||||
if (!oData.Empty())
|
||||
{
|
||||
unContentPosition = std::max(unContentPosition, oData.m_unEndPosition);
|
||||
unCharsetEnd = std::min(unCharsetEnd, oData.m_unBeginPosition);
|
||||
}
|
||||
|
||||
// charset
|
||||
std::string sCharset = "utf-8";
|
||||
|
||||
if (std::string::npos != unCharsetEnd && unCharsetBegin < unCharsetEnd)
|
||||
{
|
||||
sCharset = NSStringFinder::FindProperty(sMhtContent.substr(unCharsetBegin, unCharsetEnd - unCharsetBegin), "charset", {"="}, {";", "\\n", "\\r"}).m_sValue;
|
||||
NSStringFinder::CutInside<std::string>(sCharset, "\"");
|
||||
}
|
||||
|
||||
// Content
|
||||
std::string sContent = sMhtContent.substr(unContentPosition, sMhtContent.length() - unContentPosition);
|
||||
|
||||
// std::wstring sExtention = NSFile::GetFileExtention(UTF8_TO_U(sName));
|
||||
// std::transform(sExtention.begin(), sExtention.end(), sExtention.begin(), tolower);
|
||||
// Основной документ
|
||||
if (NSStringFinder::Equals(sContentType, "multipart/alternative"))
|
||||
oRes.WriteString(mhtTohtml(sContent));
|
||||
else if ((NSStringFinder::Find(sContentType, "text") /*&& (sExtention.empty() || NSStringFinder::EqualOf(sExtention, {L"htm", L"html", L"xhtml", L"css"}))*/)
|
||||
|| (NSStringFinder::Equals(sContentType, "application/octet-stream") && NSStringFinder::Find(sContentLocation, "css")))
|
||||
{
|
||||
// Стили заключаются в тэг <style>
|
||||
const bool bAddTagStyle = NSStringFinder::Equals(sContentType, "text/css") /*|| NSStringFinder::Equals(sExtention, L"css")*/ || NSStringFinder::Find(sContentLocation, "css");
|
||||
|
||||
if (bAddTagStyle)
|
||||
oRes.WriteString("<style>");
|
||||
|
||||
if (NSStringFinder::Equals(sContentEncoding, "base64"))
|
||||
sContent = Base64ToString(sContent, sCharset);
|
||||
else if (NSStringFinder::EqualOf(sContentEncoding, {"8bit", "7bit"}) || sContentEncoding.empty())
|
||||
{
|
||||
if (!NSStringFinder::Equals(sCharset, "utf-8") && !sCharset.empty())
|
||||
{
|
||||
NSUnicodeConverter::CUnicodeConverter oConverter;
|
||||
sContent = U_TO_UTF8(oConverter.toUnicode(sContent, sCharset.data()));
|
||||
}
|
||||
}
|
||||
else if (NSStringFinder::Equals(sContentEncoding, "quoted-printable"))
|
||||
{
|
||||
sContent = QuotedPrintableDecode(sContent, sCharset);
|
||||
if (!NSStringFinder::Equals(sCharset, "utf-8") && !sCharset.empty())
|
||||
{
|
||||
NSUnicodeConverter::CUnicodeConverter oConverter;
|
||||
sContent = U_TO_UTF8(oConverter.toUnicode(sContent, sCharset.data()));
|
||||
}
|
||||
}
|
||||
|
||||
if (NSStringFinder::Equals(sContentType, "text/html"))
|
||||
sContent = U_TO_UTF8(htmlToXhtml(sContent, false));
|
||||
|
||||
oRes.WriteString(sContent);
|
||||
|
||||
if(bAddTagStyle)
|
||||
oRes.WriteString("</style>");
|
||||
}
|
||||
// Картинки
|
||||
else if ((NSStringFinder::Find(sContentType, "image") /*|| NSStringFinder::Equals(sExtention, L"gif")*/ || NSStringFinder::Equals(sContentType, "application/octet-stream")) &&
|
||||
NSStringFinder::Equals(sContentEncoding, "base64"))
|
||||
{
|
||||
// if (NSStringFinder::Equals(sExtention, L"ico") || NSStringFinder::Find(sContentType, "ico"))
|
||||
// sContentType = "image/jpg";
|
||||
// else if(NSStringFinder::Equals(sExtention, L"gif"))
|
||||
// sContentType = "image/gif";
|
||||
int nSrcLen = (int)sContent.length();
|
||||
int nDecodeLen = NSBase64::Base64DecodeGetRequiredLength(nSrcLen);
|
||||
BYTE* pData = new BYTE[nDecodeLen];
|
||||
if (TRUE == NSBase64::Base64Decode(sContent.c_str(), nSrcLen, pData, &nDecodeLen))
|
||||
sRes.insert(std::make_pair(sContentLocation, "data:" + sContentType + ";base64," + sContent));
|
||||
RELEASEARRAYOBJECTS(pData);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string mhtTohtml(const std::string& sFileContent)
|
||||
{
|
||||
std::map<std::string, std::string> sRes;
|
||||
NSStringUtils::CStringBuilderA oRes;
|
||||
|
||||
// Поиск boundary
|
||||
NSStringFinder::TFoundedData<char> oData{NSStringFinder::FindProperty(sFileContent, "boundary", {"="}, {"\\r", "\\n", "\""})};
|
||||
|
||||
size_t nFound{oData.m_unEndPosition};
|
||||
std::string sBoundary{oData.m_sValue};
|
||||
|
||||
if (sBoundary.empty())
|
||||
{
|
||||
size_t nFoundEnd = sFileContent.length();
|
||||
nFound = 0;
|
||||
ReadMht(sFileContent.substr(nFound, nFoundEnd), sRes, oRes);
|
||||
return oRes.GetData();
|
||||
}
|
||||
|
||||
NSStringFinder::CutInside<std::string>(sBoundary, "\"");
|
||||
|
||||
size_t nFoundEnd{nFound};
|
||||
|
||||
sBoundary = "--" + sBoundary;
|
||||
size_t nBoundaryLength = sBoundary.length();
|
||||
|
||||
nFound = sFileContent.find(sBoundary, nFound) + nBoundaryLength;
|
||||
|
||||
// Цикл по boundary
|
||||
while(nFound != std::string::npos)
|
||||
{
|
||||
nFoundEnd = sFileContent.find(sBoundary, nFound + nBoundaryLength);
|
||||
if(nFoundEnd == std::string::npos)
|
||||
break;
|
||||
|
||||
ReadMht(sFileContent.substr(nFound, nFoundEnd - nFound), sRes, oRes);
|
||||
|
||||
nFound = sFileContent.find(sBoundary, nFoundEnd);
|
||||
}
|
||||
|
||||
std::string sFile = oRes.GetData();
|
||||
for(const std::pair<std::string, std::string>& item : sRes)
|
||||
{
|
||||
std::string sName = item.first;
|
||||
size_t found = sFile.find(sName);
|
||||
size_t sfound = sName.rfind('/');
|
||||
if(found == std::string::npos && sfound != std::string::npos)
|
||||
found = sFile.find(sName.erase(0, sfound + 1));
|
||||
while(found != std::string::npos)
|
||||
{
|
||||
size_t fq = sFile.find_last_of("\"\'>=", found);
|
||||
|
||||
if (std::string::npos == fq)
|
||||
break;
|
||||
|
||||
char ch = sFile[fq];
|
||||
if(ch != '\"' && ch != '\'')
|
||||
fq++;
|
||||
size_t tq = sFile.find_first_of("\"\'<> ", found) + 1;
|
||||
|
||||
if (std::string::npos == tq)
|
||||
break;
|
||||
|
||||
if(sFile[tq] != '\"' && sFile[tq] != '\'')
|
||||
tq--;
|
||||
if(ch != '>')
|
||||
{
|
||||
std::string is = '\"' + item.second + '\"';
|
||||
sFile.replace(fq, tq - fq, is);
|
||||
found = sFile.find(sName, fq + is.length());
|
||||
}
|
||||
else
|
||||
found = sFile.find(sName, tq);
|
||||
}
|
||||
}
|
||||
|
||||
return sFile;
|
||||
}
|
||||
|
||||
// Заменяет сущности &,<,> в text
|
||||
static void substitute_xml_entities_into_text(std::string& text)
|
||||
{
|
||||
// replacing & must come first
|
||||
replace_all(text, "&", "&");
|
||||
replace_all(text, "<", "<");
|
||||
replace_all(text, ">", ">");
|
||||
}
|
||||
|
||||
// After running through Gumbo, the values of type "" are replaced with the corresponding code '0x01'
|
||||
// Since the attribute value does not use control characters (value <= 0x09),
|
||||
// then just delete them, otherwise XmlUtils::CXmlLiteReader crashes on them.
|
||||
// bug#73486
|
||||
static void remove_control_symbols(std::string& text)
|
||||
{
|
||||
std::string::iterator itFound = std::find_if(text.begin(), text.end(), [](unsigned char chValue){ return chValue <= 0x09; });
|
||||
|
||||
while (itFound != text.end())
|
||||
{
|
||||
itFound = text.erase(itFound);
|
||||
itFound = std::find_if(itFound, text.end(), [](unsigned char chValue){ return chValue <= 0x09; });
|
||||
}
|
||||
}
|
||||
|
||||
// Заменяет сущности " в text
|
||||
static void substitute_xml_entities_into_attributes(std::string& text)
|
||||
{
|
||||
remove_control_symbols(text);
|
||||
substitute_xml_entities_into_text(text);
|
||||
replace_all(text, "\"", """);
|
||||
}
|
||||
|
||||
static std::string handle_unknown_tag(GumboStringPiece* text)
|
||||
{
|
||||
if (text->data == NULL)
|
||||
return "";
|
||||
GumboStringPiece gsp = *text;
|
||||
gumbo_tag_from_original_text(&gsp);
|
||||
std::string sAtr = std::string(gsp.data, gsp.length);
|
||||
size_t found = sAtr.find_first_of("-'+,./=?;!*#@$_%<>&;\"\'()[]{}");
|
||||
while(found != std::string::npos)
|
||||
{
|
||||
sAtr.erase(found, 1);
|
||||
found = sAtr.find_first_of("-'+,./=?;!*#@$_%<>&;\"\'()[]{}", found);
|
||||
}
|
||||
return sAtr;
|
||||
}
|
||||
|
||||
static std::string get_tag_name(GumboNode* node)
|
||||
{
|
||||
std::string tagname = (node->type == GUMBO_NODE_DOCUMENT ? "document" : gumbo_normalized_tagname(node->v.element.tag));
|
||||
if (tagname.empty())
|
||||
tagname = handle_unknown_tag(&node->v.element.original_tag);
|
||||
return tagname;
|
||||
}
|
||||
|
||||
static void build_doctype(GumboNode* node, NSStringUtils::CStringBuilderA& oBuilder)
|
||||
{
|
||||
if (node->v.document.has_doctype)
|
||||
{
|
||||
oBuilder.WriteString("<!DOCTYPE ");
|
||||
oBuilder.WriteString(node->v.document.name);
|
||||
std::string pi(node->v.document.public_identifier);
|
||||
remove_control_symbols(pi);
|
||||
if ((node->v.document.public_identifier != NULL) && !pi.empty())
|
||||
{
|
||||
oBuilder.WriteString(" PUBLIC \"");
|
||||
oBuilder.WriteString(pi);
|
||||
oBuilder.WriteString("\" \"");
|
||||
oBuilder.WriteString(node->v.document.system_identifier);
|
||||
oBuilder.WriteString("\"");
|
||||
}
|
||||
oBuilder.WriteString(">");
|
||||
}
|
||||
}
|
||||
|
||||
static void build_attributes(const GumboVector* attribs, NSStringUtils::CStringBuilderA& atts)
|
||||
{
|
||||
std::vector<std::string> arrRepeat;
|
||||
for (size_t i = 0; i < attribs->length; ++i)
|
||||
{
|
||||
GumboAttribute* at = static_cast<GumboAttribute*>(attribs->data[i]);
|
||||
std::string sVal(at->value);
|
||||
std::string sName(at->name);
|
||||
|
||||
remove_control_symbols(sVal);
|
||||
remove_control_symbols(sName);
|
||||
|
||||
atts.WriteString(" ");
|
||||
|
||||
bool bCheck = false;
|
||||
size_t nBad = sName.find_first_of("+,.=?#%<>&;\"\'()[]{}");
|
||||
while(nBad != std::string::npos)
|
||||
{
|
||||
sName.erase(nBad, 1);
|
||||
nBad = sName.find_first_of("+,.=?#%<>&;\"\'()[]{}", nBad);
|
||||
if(sName.empty())
|
||||
break;
|
||||
bCheck = true;
|
||||
}
|
||||
if(sName.empty())
|
||||
continue;
|
||||
while(sName.front() >= '0' && sName.front() <= '9')
|
||||
{
|
||||
sName.erase(0, 1);
|
||||
if(sName.empty())
|
||||
break;
|
||||
bCheck = true;
|
||||
}
|
||||
if(bCheck)
|
||||
{
|
||||
GumboAttribute* check = gumbo_get_attribute(attribs, sName.c_str());
|
||||
if(check || std::find(arrRepeat.begin(), arrRepeat.end(), sName) != arrRepeat.end())
|
||||
continue;
|
||||
else
|
||||
arrRepeat.push_back(sName);
|
||||
}
|
||||
|
||||
if(sName.empty())
|
||||
continue;
|
||||
atts.WriteString(sName);
|
||||
|
||||
// determine original quote character used if it exists
|
||||
std::string qs ="\"";
|
||||
atts.WriteString("=");
|
||||
atts.WriteString(qs);
|
||||
substitute_xml_entities_into_attributes(sVal);
|
||||
atts.WriteString(sVal);
|
||||
atts.WriteString(qs);
|
||||
}
|
||||
}
|
||||
|
||||
static void prettyprint(GumboNode* node, NSStringUtils::CStringBuilderA& oBuilder, bool bCheckValidNode = true);
|
||||
|
||||
static void prettyprint_contents(GumboNode* node, NSStringUtils::CStringBuilderA& contents, bool bCheckValidNode)
|
||||
{
|
||||
std::string key = "|" + get_tag_name(node) + "|";
|
||||
bool keep_whitespace = preserve_whitespace.find(key) != std::string::npos;
|
||||
bool is_inline = nonbreaking_inline.find(key) != std::string::npos;
|
||||
bool is_like_inline = treat_like_inline.find(key) != std::string::npos;
|
||||
|
||||
GumboVector* children = &node->v.element.children;
|
||||
|
||||
for (size_t i = 0; i < children->length; i++)
|
||||
{
|
||||
GumboNode* child = static_cast<GumboNode*> (children->data[i]);
|
||||
|
||||
if (child->type == GUMBO_NODE_TEXT)
|
||||
{
|
||||
std::string val(child->v.text.text);
|
||||
remove_control_symbols(val);
|
||||
substitute_xml_entities_into_text(val);
|
||||
|
||||
// Избавление от FF
|
||||
size_t found = val.find_first_of("\014");
|
||||
while(found != std::string::npos)
|
||||
{
|
||||
val.erase(found, 1);
|
||||
found = val.find_first_of("\014", found);
|
||||
}
|
||||
|
||||
contents.WriteString(val);
|
||||
}
|
||||
else if ((child->type == GUMBO_NODE_ELEMENT) || (child->type == GUMBO_NODE_TEMPLATE))
|
||||
prettyprint(child, contents, bCheckValidNode);
|
||||
else if (child->type == GUMBO_NODE_WHITESPACE)
|
||||
{
|
||||
if (keep_whitespace || is_inline || is_like_inline)
|
||||
contents.WriteString(child->v.text.text);
|
||||
}
|
||||
else if (child->type != GUMBO_NODE_COMMENT)
|
||||
{
|
||||
// Сообщение об ошибке
|
||||
// Does this actually exist: (child->type == GUMBO_NODE_CDATA)
|
||||
// fprintf(stderr, "unknown element of type: %d\n", child->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void prettyprint(GumboNode* node, NSStringUtils::CStringBuilderA& oBuilder, bool bCheckValidNode)
|
||||
{
|
||||
// special case the document node
|
||||
if (node->type == GUMBO_NODE_DOCUMENT)
|
||||
{
|
||||
build_doctype(node, oBuilder);
|
||||
prettyprint_contents(node, oBuilder, bCheckValidNode);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string tagname = get_tag_name(node);
|
||||
remove_control_symbols(tagname);
|
||||
|
||||
if (NodeIsUnprocessed(tagname))
|
||||
return;
|
||||
|
||||
if (bCheckValidNode)
|
||||
bCheckValidNode = !IsUnckeckedNodes(tagname);
|
||||
|
||||
if (bCheckValidNode && html_tags.end() == std::find(html_tags.begin(), html_tags.end(), tagname))
|
||||
{
|
||||
prettyprint_contents(node, oBuilder, bCheckValidNode);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string close = "";
|
||||
std::string closeTag = "";
|
||||
std::string key = "|" + tagname + "|";
|
||||
bool is_empty_tag = empty_tags.find(key) != std::string::npos;
|
||||
|
||||
// determine closing tag type
|
||||
if (is_empty_tag)
|
||||
close = "/";
|
||||
else
|
||||
closeTag = "</" + tagname + ">";
|
||||
|
||||
// build results
|
||||
oBuilder.WriteString("<" + tagname);
|
||||
|
||||
// build attr string
|
||||
const GumboVector* attribs = &node->v.element.attributes;
|
||||
build_attributes(attribs, oBuilder);
|
||||
oBuilder.WriteString(close + ">");
|
||||
|
||||
// prettyprint your contents
|
||||
prettyprint_contents(node, oBuilder, bCheckValidNode);
|
||||
oBuilder.WriteString(closeTag);
|
||||
}
|
||||
|
||||
std::wstring htmlToXhtml(std::string& sFileContent, bool bNeedConvert)
|
||||
{
|
||||
if (bNeedConvert)
|
||||
{ // Определение кодировки
|
||||
std::string sEncoding = NSStringFinder::FindProperty(sFileContent, "charset", {"="}, {";", "\\n", "\\r", " ", "\"", "'"}).m_sValue;
|
||||
|
||||
if (sEncoding.empty())
|
||||
sEncoding = NSStringFinder::FindProperty(sFileContent, "encoding", {"="}, {";", "\\n", "\\r", " "}).m_sValue;
|
||||
|
||||
if (!sEncoding.empty() && !NSStringFinder::Equals("utf-8", sEncoding))
|
||||
{
|
||||
NSUnicodeConverter::CUnicodeConverter oConverter;
|
||||
sFileContent = U_TO_UTF8(oConverter.toUnicode(sFileContent, sEncoding.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// Избавляемся от лишних символов до <...
|
||||
boost::regex oRegex("<[a-zA-Z]");
|
||||
boost::match_results<typename std::string::const_iterator> oResult;
|
||||
|
||||
if (boost::regex_search(sFileContent, oResult, oRegex))
|
||||
sFileContent.erase(0, oResult.position());
|
||||
|
||||
//Избавление от <a ... />
|
||||
while (NSStringFinder::RemoveEmptyTag(sFileContent, "a"));
|
||||
//Избавление от <title ... />
|
||||
while (NSStringFinder::RemoveEmptyTag(sFileContent, "title"));
|
||||
//Избавление от <script ... />
|
||||
while (NSStringFinder::RemoveEmptyTag(sFileContent, "script"));
|
||||
|
||||
// Gumbo
|
||||
GumboOptions options = kGumboDefaultOptions;
|
||||
GumboOutput* output = gumbo_parse_with_options(&options, sFileContent.data(), sFileContent.length());
|
||||
|
||||
// prettyprint
|
||||
NSStringUtils::CStringBuilderA oBuilder;
|
||||
prettyprint(output->document, oBuilder);
|
||||
|
||||
// Конвертирование из string utf8 в wstring
|
||||
return UTF8_TO_U(oBuilder.GetData());
|
||||
}
|
||||
|
||||
std::wstring mhtToXhtml(std::string& sFileContent)
|
||||
{
|
||||
sFileContent = mhtTohtml(sFileContent);
|
||||
|
||||
// Gumbo
|
||||
GumboOptions options = kGumboDefaultOptions;
|
||||
GumboOutput* output = gumbo_parse_with_options(&options, sFileContent.data(), sFileContent.length());
|
||||
|
||||
// prettyprint
|
||||
NSStringUtils::CStringBuilderA oBuilder;
|
||||
prettyprint(output->document, oBuilder);
|
||||
|
||||
// Конвертирование из string utf8 в wstring
|
||||
return UTF8_TO_U(oBuilder.GetData());
|
||||
}
|
||||
}
|
||||
@ -2,658 +2,11 @@
|
||||
#define HTMLTOXHTML_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <cctype>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "gumbo-parser/src/gumbo.h"
|
||||
#include "../../../DesktopEditor/common/File.h"
|
||||
#include "../../../DesktopEditor/common/Directory.h"
|
||||
#include "../../../DesktopEditor/common/StringBuilder.h"
|
||||
#include "../../../DesktopEditor/xml/include/xmlutils.h"
|
||||
#include "../../../UnicodeConverter/UnicodeConverter.h"
|
||||
#include "../../../HtmlFile2/src/StringFinder.h"
|
||||
|
||||
#if defined(CreateDirectory)
|
||||
#undef CreateDirectory
|
||||
#endif
|
||||
|
||||
static std::string nonbreaking_inline = "|a|abbr|acronym|b|bdo|big|cite|code|dfn|em|font|i|img|kbd|nobr|s|small|span|strike|strong|sub|sup|tt|";
|
||||
static std::string empty_tags = "|area|base|basefont|bgsound|br|command|col|embed|event-source|frame|hr|image|img|input|keygen|link|menuitem|meta|param|source|spacer|track|wbr|";
|
||||
static std::string preserve_whitespace = "|pre|textarea|script|style|";
|
||||
static std::string special_handling = "|html|body|";
|
||||
static std::string treat_like_inline = "|p|";
|
||||
|
||||
static std::vector<std::string> html_tags = {"div","span","a","img","p","h1","h2","h3","h4","h5","h6",
|
||||
"ul", "ol", "li","td","tr","table","thead","tbody","tfoot","th",
|
||||
"br","form","input","button","section","nav","header","footer",
|
||||
"main","figure","figcaption","strong","em","i", "b", "u","pre",
|
||||
"code","blockquote","hr","script","link","meta","style","title",
|
||||
"head","body","html","legend","optgroup","option","select","dl",
|
||||
"dt","dd","time","data","abbr","address","area","base","bdi",
|
||||
"bdo","cite","col","iframe","video","source","track","textarea",
|
||||
"label","fieldset","colgroup","del","ins","details","summary",
|
||||
"dialog","embed","kbd","map","mark","menu","meter","object",
|
||||
"output","param","progress","q","samp","small","sub","sup","var",
|
||||
"wbr","acronym","applet","article","aside","audio","basefont",
|
||||
"bgsound","big","blink","canvas","caption","center","command",
|
||||
"comment","datalist","dfn","dir","font","frame","frameset",
|
||||
"hgroup","isindex","keygen","marquee","nobr","noembed","noframes",
|
||||
"noscript","plaintext","rp","rt","ruby","s","strike","tt","xmp"};
|
||||
|
||||
static std::vector<std::string> unchecked_nodes_new = {"svg"};
|
||||
|
||||
static void prettyprint(GumboNode*, NSStringUtils::CStringBuilderA& oBuilder, bool bCheckValidNode = true);
|
||||
static std::string mhtTohtml(const std::string &sFileContent);
|
||||
|
||||
// Заменяет в строке s все символы s1 на s2
|
||||
static void replace_all(std::string& s, const std::string& s1, const std::string& s2)
|
||||
namespace HTML
|
||||
{
|
||||
size_t pos = s.find(s1);
|
||||
while(pos != std::string::npos)
|
||||
{
|
||||
s.replace(pos, s1.length(), s2);
|
||||
pos = s.find(s1, pos + s2.length());
|
||||
}
|
||||
}
|
||||
|
||||
static bool NodeIsUnprocessed(const std::string& wsTagName)
|
||||
{
|
||||
return "xml" == wsTagName;
|
||||
}
|
||||
|
||||
static bool IsUnckeckedNodes(const std::string& sValue)
|
||||
{
|
||||
return unchecked_nodes_new.end() != std::find(unchecked_nodes_new.begin(), unchecked_nodes_new.end(), sValue);
|
||||
}
|
||||
|
||||
static std::wstring htmlToXhtml(std::string& sFileContent, bool bNeedConvert)
|
||||
{
|
||||
if (bNeedConvert)
|
||||
{ // Определение кодировки
|
||||
std::string sEncoding = NSStringFinder::FindProperty(sFileContent, "charset", {"="}, {";", "\\n", "\\r", " ", "\"", "'"}).m_sValue;
|
||||
|
||||
if (sEncoding.empty())
|
||||
sEncoding = NSStringFinder::FindProperty(sFileContent, "encoding", {"="}, {";", "\\n", "\\r", " "}).m_sValue;
|
||||
|
||||
if (!sEncoding.empty() && !NSStringFinder::Equals("utf-8", sEncoding))
|
||||
{
|
||||
NSUnicodeConverter::CUnicodeConverter oConverter;
|
||||
sFileContent = U_TO_UTF8(oConverter.toUnicode(sFileContent, sEncoding.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// Избавляемся от лишних символов до <...
|
||||
boost::regex oRegex("<[a-zA-Z]");
|
||||
boost::match_results<typename std::string::const_iterator> oResult;
|
||||
|
||||
if (boost::regex_search(sFileContent, oResult, oRegex))
|
||||
sFileContent.erase(0, oResult.position());
|
||||
|
||||
//Избавление от <a ... />
|
||||
while (NSStringFinder::RemoveEmptyTag(sFileContent, "a"));
|
||||
//Избавление от <title ... />
|
||||
while (NSStringFinder::RemoveEmptyTag(sFileContent, "title"));
|
||||
//Избавление от <script ... />
|
||||
while (NSStringFinder::RemoveEmptyTag(sFileContent, "script"));
|
||||
|
||||
// Gumbo
|
||||
GumboOptions options = kGumboDefaultOptions;
|
||||
GumboOutput* output = gumbo_parse_with_options(&options, sFileContent.data(), sFileContent.length());
|
||||
|
||||
// prettyprint
|
||||
NSStringUtils::CStringBuilderA oBuilder;
|
||||
prettyprint(output->document, oBuilder);
|
||||
|
||||
// Конвертирование из string utf8 в wstring
|
||||
return UTF8_TO_U(oBuilder.GetData());
|
||||
}
|
||||
|
||||
static std::string Base64ToString(const std::string& sContent, const std::string& sCharset)
|
||||
{
|
||||
std::string sRes;
|
||||
int nSrcLen = (int)sContent.length();
|
||||
int nDecodeLen = NSBase64::Base64DecodeGetRequiredLength(nSrcLen);
|
||||
BYTE* pData = new BYTE[nDecodeLen];
|
||||
if (TRUE == NSBase64::Base64Decode(sContent.c_str(), nSrcLen, pData, &nDecodeLen))
|
||||
{
|
||||
std::wstring sConvert;
|
||||
if(!sCharset.empty() && NSStringFinder::Equals<std::string>("utf-8", sCharset))
|
||||
{
|
||||
NSUnicodeConverter::CUnicodeConverter oConverter;
|
||||
sConvert = oConverter.toUnicode(reinterpret_cast<char *>(pData), (unsigned)nDecodeLen, sCharset.data());
|
||||
}
|
||||
sRes = sConvert.empty() ? std::string(reinterpret_cast<char *>(pData), nDecodeLen) : U_TO_UTF8(sConvert);
|
||||
}
|
||||
RELEASEARRAYOBJECTS(pData);
|
||||
return sRes;
|
||||
}
|
||||
|
||||
static std::string QuotedPrintableDecode(const std::string& sContent, std::string& sCharset)
|
||||
{
|
||||
NSStringUtils::CStringBuilderA sRes;
|
||||
size_t ip = 0;
|
||||
size_t i = sContent.find('=');
|
||||
|
||||
if(i == 0)
|
||||
{
|
||||
size_t nIgnore = 12;
|
||||
std::string charset = sContent.substr(0, nIgnore);
|
||||
if(charset == "=00=00=FE=FF")
|
||||
sCharset = "UTF-32BE";
|
||||
else if(charset == "=FF=FE=00=00")
|
||||
sCharset = "UTF-32LE";
|
||||
else if(charset == "=2B=2F=76=38" || charset == "=2B=2F=76=39" ||
|
||||
charset == "=2B=2F=76=2B" || charset == "=2B=2F=76=2F")
|
||||
sCharset = "UTF-7";
|
||||
else if(charset == "=DD=73=66=73")
|
||||
sCharset = "UTF-EBCDIC";
|
||||
else if(charset == "=84=31=95=33")
|
||||
sCharset = "GB-18030";
|
||||
else
|
||||
{
|
||||
nIgnore -= 3;
|
||||
charset.erase(nIgnore);
|
||||
if(charset == "=EF=BB=BF")
|
||||
sCharset = "UTF-8";
|
||||
else if(charset == "=F7=64=4C")
|
||||
sCharset = "UTF-1";
|
||||
else if(charset == "=0E=FE=FF")
|
||||
sCharset = "SCSU";
|
||||
else if(charset == "=FB=EE=28")
|
||||
sCharset = "BOCU-1";
|
||||
else
|
||||
{
|
||||
nIgnore -= 3;
|
||||
charset.erase(nIgnore);
|
||||
if(charset == "=FE=FF")
|
||||
sCharset = "UTF-16BE";
|
||||
else if(charset == "=FF=FE")
|
||||
sCharset = "UTF-16LE";
|
||||
else
|
||||
nIgnore -= 6;
|
||||
}
|
||||
}
|
||||
|
||||
ip = nIgnore;
|
||||
i = sContent.find('=', ip);
|
||||
}
|
||||
|
||||
while(i != std::string::npos && i + 2 < sContent.length())
|
||||
{
|
||||
sRes.WriteString(sContent.c_str() + ip, i - ip);
|
||||
std::string str = sContent.substr(i + 1, 2);
|
||||
if(str.front() == '\n' || str.front() == '\r')
|
||||
{
|
||||
char ch = str[1];
|
||||
if(ch != '\n' && ch != '\r')
|
||||
sRes.WriteString(&ch, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
char* err;
|
||||
char ch = (int)strtol(str.data(), &err, 16);
|
||||
if(*err)
|
||||
sRes.WriteString('=' + str);
|
||||
else
|
||||
sRes.WriteString(&ch, 1);
|
||||
}
|
||||
ip = i + 3;
|
||||
i = sContent.find('=', ip);
|
||||
}
|
||||
if(ip != std::string::npos)
|
||||
sRes.WriteString(sContent.c_str() + ip);
|
||||
return sRes.GetData();
|
||||
}
|
||||
|
||||
static void ReadMht(const std::string& sMhtContent, std::map<std::string, std::string>& sRes, NSStringUtils::CStringBuilderA& oRes)
|
||||
{
|
||||
size_t unContentPosition = 0, unCharsetBegin = 0, unCharsetEnd = std::string::npos;
|
||||
|
||||
NSStringFinder::TFoundedData<char> oData;
|
||||
|
||||
// Content-Type
|
||||
oData = NSStringFinder::FindProperty(sMhtContent, "content-type", {":"}, {";", "\\n", "\\r"});
|
||||
const std::string sContentType{oData.m_sValue};
|
||||
|
||||
if (sContentType.empty())
|
||||
return;
|
||||
|
||||
if (NSStringFinder::Equals(sContentType, "multipart/alternative"))
|
||||
{
|
||||
oRes.WriteString(mhtTohtml(sMhtContent.substr(oData.m_unEndPosition, sMhtContent.length() - oData.m_unEndPosition)));
|
||||
return;
|
||||
}
|
||||
|
||||
unContentPosition = std::max(unContentPosition, oData.m_unEndPosition);
|
||||
unCharsetBegin = oData.m_unEndPosition;
|
||||
|
||||
// name
|
||||
// std::string sName = NSStringFinder::FindProperty(sMhtContent, "name", {"="}, {";", "\\n", "\\r"}, 0, unLastPosition);
|
||||
// unContentPosition = std::max(unContentPosition, unLastPosition);
|
||||
|
||||
// Content-Location
|
||||
oData = NSStringFinder::FindProperty(sMhtContent, "content-location", {":"}, {";", "\\n", "\\r"});
|
||||
std::string sContentLocation{oData.m_sValue};
|
||||
|
||||
if (!oData.Empty())
|
||||
unContentPosition = std::max(unContentPosition, oData.m_unEndPosition);
|
||||
|
||||
// Content-ID
|
||||
oData = NSStringFinder::FindProperty(sMhtContent, "content-id", {":"}, {";", "\\n", "\\r"});
|
||||
std::string sContentID{oData.m_sValue};
|
||||
|
||||
if (!oData.Empty())
|
||||
{
|
||||
unContentPosition = std::max(unContentPosition, oData.m_unEndPosition);
|
||||
unCharsetEnd = std::min(unCharsetEnd, oData.m_unBeginPosition);
|
||||
NSStringFinder::CutInside<std::string>(sContentID, "<", ">");
|
||||
}
|
||||
|
||||
if (sContentLocation.empty() && !sContentID.empty())
|
||||
sContentLocation = "cid:" + sContentID;
|
||||
|
||||
// Content-Transfer-Encoding
|
||||
oData = NSStringFinder::FindProperty(sMhtContent, "content-transfer-encoding", {":"}, {";", "\\n", "\\r"});
|
||||
const std::string sContentEncoding{oData.m_sValue};
|
||||
|
||||
if (!oData.Empty())
|
||||
{
|
||||
unContentPosition = std::max(unContentPosition, oData.m_unEndPosition);
|
||||
unCharsetEnd = std::min(unCharsetEnd, oData.m_unBeginPosition);
|
||||
}
|
||||
|
||||
// charset
|
||||
std::string sCharset = "utf-8";
|
||||
|
||||
if (std::string::npos != unCharsetEnd && unCharsetBegin < unCharsetEnd)
|
||||
{
|
||||
sCharset = NSStringFinder::FindProperty(sMhtContent.substr(unCharsetBegin, unCharsetEnd - unCharsetBegin), "charset", {"="}, {";", "\\n", "\\r"}).m_sValue;
|
||||
NSStringFinder::CutInside<std::string>(sCharset, "\"");
|
||||
}
|
||||
|
||||
// Content
|
||||
std::string sContent = sMhtContent.substr(unContentPosition, sMhtContent.length() - unContentPosition);
|
||||
|
||||
// std::wstring sExtention = NSFile::GetFileExtention(UTF8_TO_U(sName));
|
||||
// std::transform(sExtention.begin(), sExtention.end(), sExtention.begin(), tolower);
|
||||
// Основной документ
|
||||
if (NSStringFinder::Equals(sContentType, "multipart/alternative"))
|
||||
oRes.WriteString(mhtTohtml(sContent));
|
||||
else if ((NSStringFinder::Find(sContentType, "text") /*&& (sExtention.empty() || NSStringFinder::EqualOf(sExtention, {L"htm", L"html", L"xhtml", L"css"}))*/)
|
||||
|| (NSStringFinder::Equals(sContentType, "application/octet-stream") && NSStringFinder::Find(sContentLocation, "css")))
|
||||
{
|
||||
// Стили заключаются в тэг <style>
|
||||
const bool bAddTagStyle = NSStringFinder::Equals(sContentType, "text/css") /*|| NSStringFinder::Equals(sExtention, L"css")*/ || NSStringFinder::Find(sContentLocation, "css");
|
||||
|
||||
if (bAddTagStyle)
|
||||
oRes.WriteString("<style>");
|
||||
|
||||
if (NSStringFinder::Equals(sContentEncoding, "base64"))
|
||||
sContent = Base64ToString(sContent, sCharset);
|
||||
else if (NSStringFinder::EqualOf(sContentEncoding, {"8bit", "7bit"}) || sContentEncoding.empty())
|
||||
{
|
||||
if (!NSStringFinder::Equals(sCharset, "utf-8") && !sCharset.empty())
|
||||
{
|
||||
NSUnicodeConverter::CUnicodeConverter oConverter;
|
||||
sContent = U_TO_UTF8(oConverter.toUnicode(sContent, sCharset.data()));
|
||||
}
|
||||
}
|
||||
else if (NSStringFinder::Equals(sContentEncoding, "quoted-printable"))
|
||||
{
|
||||
sContent = QuotedPrintableDecode(sContent, sCharset);
|
||||
if (!NSStringFinder::Equals(sCharset, "utf-8") && !sCharset.empty())
|
||||
{
|
||||
NSUnicodeConverter::CUnicodeConverter oConverter;
|
||||
sContent = U_TO_UTF8(oConverter.toUnicode(sContent, sCharset.data()));
|
||||
}
|
||||
}
|
||||
|
||||
if (NSStringFinder::Equals(sContentType, "text/html"))
|
||||
sContent = U_TO_UTF8(htmlToXhtml(sContent, false));
|
||||
|
||||
oRes.WriteString(sContent);
|
||||
|
||||
if(bAddTagStyle)
|
||||
oRes.WriteString("</style>");
|
||||
}
|
||||
// Картинки
|
||||
else if ((NSStringFinder::Find(sContentType, "image") /*|| NSStringFinder::Equals(sExtention, L"gif")*/ || NSStringFinder::Equals(sContentType, "application/octet-stream")) &&
|
||||
NSStringFinder::Equals(sContentEncoding, "base64"))
|
||||
{
|
||||
// if (NSStringFinder::Equals(sExtention, L"ico") || NSStringFinder::Find(sContentType, "ico"))
|
||||
// sContentType = "image/jpg";
|
||||
// else if(NSStringFinder::Equals(sExtention, L"gif"))
|
||||
// sContentType = "image/gif";
|
||||
int nSrcLen = (int)sContent.length();
|
||||
int nDecodeLen = NSBase64::Base64DecodeGetRequiredLength(nSrcLen);
|
||||
BYTE* pData = new BYTE[nDecodeLen];
|
||||
if (TRUE == NSBase64::Base64Decode(sContent.c_str(), nSrcLen, pData, &nDecodeLen))
|
||||
sRes.insert(std::make_pair(sContentLocation, "data:" + sContentType + ";base64," + sContent));
|
||||
RELEASEARRAYOBJECTS(pData);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string mhtTohtml(const std::string& sFileContent)
|
||||
{
|
||||
std::map<std::string, std::string> sRes;
|
||||
NSStringUtils::CStringBuilderA oRes;
|
||||
|
||||
// Поиск boundary
|
||||
NSStringFinder::TFoundedData<char> oData{NSStringFinder::FindProperty(sFileContent, "boundary", {"="}, {"\\r", "\\n", "\""})};
|
||||
|
||||
size_t nFound{oData.m_unEndPosition};
|
||||
std::string sBoundary{oData.m_sValue};
|
||||
|
||||
if (sBoundary.empty())
|
||||
{
|
||||
size_t nFoundEnd = sFileContent.length();
|
||||
nFound = 0;
|
||||
ReadMht(sFileContent.substr(nFound, nFoundEnd), sRes, oRes);
|
||||
return oRes.GetData();
|
||||
}
|
||||
|
||||
NSStringFinder::CutInside<std::string>(sBoundary, "\"");
|
||||
|
||||
size_t nFoundEnd{nFound};
|
||||
|
||||
sBoundary = "--" + sBoundary;
|
||||
size_t nBoundaryLength = sBoundary.length();
|
||||
|
||||
nFound = sFileContent.find(sBoundary, nFound) + nBoundaryLength;
|
||||
|
||||
// Цикл по boundary
|
||||
while(nFound != std::string::npos)
|
||||
{
|
||||
nFoundEnd = sFileContent.find(sBoundary, nFound + nBoundaryLength);
|
||||
if(nFoundEnd == std::string::npos)
|
||||
break;
|
||||
|
||||
ReadMht(sFileContent.substr(nFound, nFoundEnd - nFound), sRes, oRes);
|
||||
|
||||
nFound = sFileContent.find(sBoundary, nFoundEnd);
|
||||
}
|
||||
|
||||
std::string sFile = oRes.GetData();
|
||||
for(const std::pair<std::string, std::string>& item : sRes)
|
||||
{
|
||||
std::string sName = item.first;
|
||||
size_t found = sFile.find(sName);
|
||||
size_t sfound = sName.rfind('/');
|
||||
if(found == std::string::npos && sfound != std::string::npos)
|
||||
found = sFile.find(sName.erase(0, sfound + 1));
|
||||
while(found != std::string::npos)
|
||||
{
|
||||
size_t fq = sFile.find_last_of("\"\'>=", found);
|
||||
|
||||
if (std::string::npos == fq)
|
||||
break;
|
||||
|
||||
char ch = sFile[fq];
|
||||
if(ch != '\"' && ch != '\'')
|
||||
fq++;
|
||||
size_t tq = sFile.find_first_of("\"\'<> ", found) + 1;
|
||||
|
||||
if (std::string::npos == tq)
|
||||
break;
|
||||
|
||||
if(sFile[tq] != '\"' && sFile[tq] != '\'')
|
||||
tq--;
|
||||
if(ch != '>')
|
||||
{
|
||||
std::string is = '\"' + item.second + '\"';
|
||||
sFile.replace(fq, tq - fq, is);
|
||||
found = sFile.find(sName, fq + is.length());
|
||||
}
|
||||
else
|
||||
found = sFile.find(sName, tq);
|
||||
}
|
||||
}
|
||||
|
||||
return sFile;
|
||||
}
|
||||
|
||||
static std::wstring mhtToXhtml(std::string& sFileContent)
|
||||
{
|
||||
sFileContent = mhtTohtml(sFileContent);
|
||||
|
||||
// Gumbo
|
||||
GumboOptions options = kGumboDefaultOptions;
|
||||
GumboOutput* output = gumbo_parse_with_options(&options, sFileContent.data(), sFileContent.length());
|
||||
|
||||
// prettyprint
|
||||
NSStringUtils::CStringBuilderA oBuilder;
|
||||
prettyprint(output->document, oBuilder);
|
||||
|
||||
// Конвертирование из string utf8 в wstring
|
||||
return UTF8_TO_U(oBuilder.GetData());
|
||||
}
|
||||
|
||||
// Заменяет сущности &,<,> в text
|
||||
static void substitute_xml_entities_into_text(std::string& text)
|
||||
{
|
||||
// replacing & must come first
|
||||
replace_all(text, "&", "&");
|
||||
replace_all(text, "<", "<");
|
||||
replace_all(text, ">", ">");
|
||||
}
|
||||
|
||||
// After running through Gumbo, the values of type "" are replaced with the corresponding code '0x01'
|
||||
// Since the attribute value does not use control characters (value <= 0x09),
|
||||
// then just delete them, otherwise XmlUtils::CXmlLiteReader crashes on them.
|
||||
// bug#73486
|
||||
static void remove_control_symbols(std::string& text)
|
||||
{
|
||||
std::string::iterator itFound = std::find_if(text.begin(), text.end(), [](unsigned char chValue){ return chValue <= 0x09; });
|
||||
|
||||
while (itFound != text.end())
|
||||
{
|
||||
itFound = text.erase(itFound);
|
||||
itFound = std::find_if(itFound, text.end(), [](unsigned char chValue){ return chValue <= 0x09; });
|
||||
}
|
||||
}
|
||||
|
||||
// Заменяет сущности " в text
|
||||
static void substitute_xml_entities_into_attributes(std::string& text)
|
||||
{
|
||||
remove_control_symbols(text);
|
||||
substitute_xml_entities_into_text(text);
|
||||
replace_all(text, "\"", """);
|
||||
}
|
||||
|
||||
static std::string handle_unknown_tag(GumboStringPiece* text)
|
||||
{
|
||||
if (text->data == NULL)
|
||||
return "";
|
||||
GumboStringPiece gsp = *text;
|
||||
gumbo_tag_from_original_text(&gsp);
|
||||
std::string sAtr = std::string(gsp.data, gsp.length);
|
||||
size_t found = sAtr.find_first_of("-'+,./=?;!*#@$_%<>&;\"\'()[]{}");
|
||||
while(found != std::string::npos)
|
||||
{
|
||||
sAtr.erase(found, 1);
|
||||
found = sAtr.find_first_of("-'+,./=?;!*#@$_%<>&;\"\'()[]{}", found);
|
||||
}
|
||||
return sAtr;
|
||||
}
|
||||
|
||||
static std::string get_tag_name(GumboNode* node)
|
||||
{
|
||||
std::string tagname = (node->type == GUMBO_NODE_DOCUMENT ? "document" : gumbo_normalized_tagname(node->v.element.tag));
|
||||
if (tagname.empty())
|
||||
tagname = handle_unknown_tag(&node->v.element.original_tag);
|
||||
return tagname;
|
||||
}
|
||||
|
||||
static void build_doctype(GumboNode* node, NSStringUtils::CStringBuilderA& oBuilder)
|
||||
{
|
||||
if (node->v.document.has_doctype)
|
||||
{
|
||||
oBuilder.WriteString("<!DOCTYPE ");
|
||||
oBuilder.WriteString(node->v.document.name);
|
||||
std::string pi(node->v.document.public_identifier);
|
||||
remove_control_symbols(pi);
|
||||
if ((node->v.document.public_identifier != NULL) && !pi.empty())
|
||||
{
|
||||
oBuilder.WriteString(" PUBLIC \"");
|
||||
oBuilder.WriteString(pi);
|
||||
oBuilder.WriteString("\" \"");
|
||||
oBuilder.WriteString(node->v.document.system_identifier);
|
||||
oBuilder.WriteString("\"");
|
||||
}
|
||||
oBuilder.WriteString(">");
|
||||
}
|
||||
}
|
||||
|
||||
static void build_attributes(const GumboVector* attribs, NSStringUtils::CStringBuilderA& atts)
|
||||
{
|
||||
std::vector<std::string> arrRepeat;
|
||||
for (size_t i = 0; i < attribs->length; ++i)
|
||||
{
|
||||
GumboAttribute* at = static_cast<GumboAttribute*>(attribs->data[i]);
|
||||
std::string sVal(at->value);
|
||||
std::string sName(at->name);
|
||||
|
||||
remove_control_symbols(sVal);
|
||||
remove_control_symbols(sName);
|
||||
|
||||
atts.WriteString(" ");
|
||||
|
||||
bool bCheck = false;
|
||||
size_t nBad = sName.find_first_of("+,.=?#%<>&;\"\'()[]{}");
|
||||
while(nBad != std::string::npos)
|
||||
{
|
||||
sName.erase(nBad, 1);
|
||||
nBad = sName.find_first_of("+,.=?#%<>&;\"\'()[]{}", nBad);
|
||||
if(sName.empty())
|
||||
break;
|
||||
bCheck = true;
|
||||
}
|
||||
if(sName.empty())
|
||||
continue;
|
||||
while(sName.front() >= '0' && sName.front() <= '9')
|
||||
{
|
||||
sName.erase(0, 1);
|
||||
if(sName.empty())
|
||||
break;
|
||||
bCheck = true;
|
||||
}
|
||||
if(bCheck)
|
||||
{
|
||||
GumboAttribute* check = gumbo_get_attribute(attribs, sName.c_str());
|
||||
if(check || std::find(arrRepeat.begin(), arrRepeat.end(), sName) != arrRepeat.end())
|
||||
continue;
|
||||
else
|
||||
arrRepeat.push_back(sName);
|
||||
}
|
||||
|
||||
if(sName.empty())
|
||||
continue;
|
||||
atts.WriteString(sName);
|
||||
|
||||
// determine original quote character used if it exists
|
||||
std::string qs ="\"";
|
||||
atts.WriteString("=");
|
||||
atts.WriteString(qs);
|
||||
substitute_xml_entities_into_attributes(sVal);
|
||||
atts.WriteString(sVal);
|
||||
atts.WriteString(qs);
|
||||
}
|
||||
}
|
||||
|
||||
static void prettyprint_contents(GumboNode* node, NSStringUtils::CStringBuilderA& contents, bool bCheckValidNode)
|
||||
{
|
||||
std::string key = "|" + get_tag_name(node) + "|";
|
||||
bool keep_whitespace = preserve_whitespace.find(key) != std::string::npos;
|
||||
bool is_inline = nonbreaking_inline.find(key) != std::string::npos;
|
||||
bool is_like_inline = treat_like_inline.find(key) != std::string::npos;
|
||||
|
||||
GumboVector* children = &node->v.element.children;
|
||||
|
||||
for (size_t i = 0; i < children->length; i++)
|
||||
{
|
||||
GumboNode* child = static_cast<GumboNode*> (children->data[i]);
|
||||
|
||||
if (child->type == GUMBO_NODE_TEXT)
|
||||
{
|
||||
std::string val(child->v.text.text);
|
||||
remove_control_symbols(val);
|
||||
substitute_xml_entities_into_text(val);
|
||||
|
||||
// Избавление от FF
|
||||
size_t found = val.find_first_of("\014");
|
||||
while(found != std::string::npos)
|
||||
{
|
||||
val.erase(found, 1);
|
||||
found = val.find_first_of("\014", found);
|
||||
}
|
||||
|
||||
contents.WriteString(val);
|
||||
}
|
||||
else if ((child->type == GUMBO_NODE_ELEMENT) || (child->type == GUMBO_NODE_TEMPLATE))
|
||||
prettyprint(child, contents, bCheckValidNode);
|
||||
else if (child->type == GUMBO_NODE_WHITESPACE)
|
||||
{
|
||||
if (keep_whitespace || is_inline || is_like_inline)
|
||||
contents.WriteString(child->v.text.text);
|
||||
}
|
||||
else if (child->type != GUMBO_NODE_COMMENT)
|
||||
{
|
||||
// Сообщение об ошибке
|
||||
// Does this actually exist: (child->type == GUMBO_NODE_CDATA)
|
||||
// fprintf(stderr, "unknown element of type: %d\n", child->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void prettyprint(GumboNode* node, NSStringUtils::CStringBuilderA& oBuilder, bool bCheckValidNode)
|
||||
{
|
||||
// special case the document node
|
||||
if (node->type == GUMBO_NODE_DOCUMENT)
|
||||
{
|
||||
build_doctype(node, oBuilder);
|
||||
prettyprint_contents(node, oBuilder, bCheckValidNode);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string tagname = get_tag_name(node);
|
||||
remove_control_symbols(tagname);
|
||||
|
||||
if (NodeIsUnprocessed(tagname))
|
||||
return;
|
||||
|
||||
if (bCheckValidNode)
|
||||
bCheckValidNode = !IsUnckeckedNodes(tagname);
|
||||
|
||||
if (bCheckValidNode && html_tags.end() == std::find(html_tags.begin(), html_tags.end(), tagname))
|
||||
{
|
||||
prettyprint_contents(node, oBuilder, bCheckValidNode);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string close = "";
|
||||
std::string closeTag = "";
|
||||
std::string key = "|" + tagname + "|";
|
||||
bool is_empty_tag = empty_tags.find(key) != std::string::npos;
|
||||
|
||||
// determine closing tag type
|
||||
if (is_empty_tag)
|
||||
close = "/";
|
||||
else
|
||||
closeTag = "</" + tagname + ">";
|
||||
|
||||
// build results
|
||||
oBuilder.WriteString("<" + tagname);
|
||||
|
||||
// build attr string
|
||||
const GumboVector* attribs = &node->v.element.attributes;
|
||||
build_attributes(attribs, oBuilder);
|
||||
oBuilder.WriteString(close + ">");
|
||||
|
||||
// prettyprint your contents
|
||||
prettyprint_contents(node, oBuilder, bCheckValidNode);
|
||||
oBuilder.WriteString(closeTag);
|
||||
std::wstring htmlToXhtml(std::string& sFileContent, bool bNeedConvert);
|
||||
std::wstring mhtToXhtml(std::string& sFileContent);
|
||||
}
|
||||
|
||||
#endif // HTMLTOXHTML_H
|
||||
|
||||
@ -72,6 +72,10 @@ extern NSString *const SRHTTPResponseErrorKey;
|
||||
// Optional array of cookies (NSHTTPCookie objects) to apply to the connections
|
||||
@property (nonatomic, readwrite) NSArray * requestCookies;
|
||||
|
||||
// Optional proxy configuration dictionary (kCFStreamPropertyHTTPProxy format).
|
||||
// Set before calling -open. Example: Proxyman at 127.0.0.1:9090.
|
||||
@property (nonatomic, strong) NSDictionary *proxyDictionary;
|
||||
|
||||
// This returns the negotiated protocol.
|
||||
// It will be nil until after the handshake completes.
|
||||
@property (nonatomic, readonly, copy) NSString *protocol;
|
||||
|
||||
@ -619,7 +619,16 @@ static __strong NSData *CRLFCRLF;
|
||||
|
||||
_inputStream.delegate = self;
|
||||
_outputStream.delegate = self;
|
||||
|
||||
|
||||
if (self.proxyDictionary) {
|
||||
CFReadStreamSetProperty((__bridge CFReadStreamRef)_inputStream,
|
||||
kCFStreamPropertyHTTPProxy,
|
||||
(__bridge CFDictionaryRef)self.proxyDictionary);
|
||||
CFWriteStreamSetProperty((__bridge CFWriteStreamRef)_outputStream,
|
||||
kCFStreamPropertyHTTPProxy,
|
||||
(__bridge CFDictionaryRef)self.proxyDictionary);
|
||||
}
|
||||
|
||||
[self setupNetworkServiceType:_urlRequest.networkServiceType];
|
||||
}
|
||||
|
||||
|
||||
@ -188,7 +188,7 @@ namespace NSNetwork
|
||||
else
|
||||
{
|
||||
NSURL* url = [NSURL URLWithString:escapedURL];
|
||||
NSData* urlData = [NSData dataWithContentsOfURL:url];
|
||||
NSData* urlData = [[NSData alloc] initWithContentsOfURL:url];
|
||||
if ( urlData )
|
||||
{
|
||||
NSString* filePath = StringWToNSString(m_sDownloadFilePath);
|
||||
|
||||
@ -38,6 +38,8 @@
|
||||
#include <memory>
|
||||
#include "../../../../../DesktopEditor/graphics/BaseThread.h"
|
||||
|
||||
#define _LOGGER_SOCKETS
|
||||
|
||||
namespace NSNetwork
|
||||
{
|
||||
namespace NSWebSocket
|
||||
@ -124,6 +126,10 @@ namespace NSNetwork
|
||||
}
|
||||
|
||||
//webSocket.connect(url, queryDst, sio::string_message::create(sAuth));
|
||||
#ifdef _LOGGER_SOCKETS
|
||||
m_socket->set_proxy_basic_auth("http://127.0.0.1:9090", "", "");
|
||||
#endif
|
||||
|
||||
m_connecting_in_process = true;
|
||||
m_socket->connect(m_base->url, queryDst, objAuth);
|
||||
|
||||
|
||||
@ -42,6 +42,8 @@
|
||||
#include <memory>
|
||||
#include "../../../../../DesktopEditor/graphics/BaseThread.h"
|
||||
|
||||
#define _LOGGER_SOCKETS
|
||||
|
||||
namespace NSNetwork
|
||||
{
|
||||
namespace NSWebSocket
|
||||
@ -113,6 +115,10 @@ namespace NSNetwork
|
||||
}
|
||||
|
||||
//webSocket.connect(url, queryDst, sio_no_tls::string_message::create(sAuth));
|
||||
#ifdef _LOGGER_SOCKETS
|
||||
m_socket->set_proxy_basic_auth("http://127.0.0.1:9090", "", "");
|
||||
#endif
|
||||
|
||||
m_connecting_in_process = true;
|
||||
m_socket->connect(m_base->url, queryDst, objAuth);
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@
|
||||
}
|
||||
|
||||
- (void)open
|
||||
{
|
||||
{
|
||||
if (m_url && m_url.length)
|
||||
{
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:m_url]];
|
||||
@ -58,6 +58,19 @@
|
||||
protocols:nil
|
||||
allowsUntrustedSSLCertificates:YES];
|
||||
self.socket.delegate = self;
|
||||
|
||||
#ifdef _LOGGER_SOCKETS
|
||||
self.socket.proxyDictionary = @{
|
||||
(NSString *)kCFNetworkProxiesHTTPEnable: @YES,
|
||||
(NSString *)kCFNetworkProxiesHTTPProxy: @"127.0.0.1",
|
||||
(NSString *)kCFNetworkProxiesHTTPPort: @9090,
|
||||
(NSString *)kCFNetworkProxiesHTTPSEnable: @YES,
|
||||
(NSString *)kCFNetworkProxiesHTTPSProxy: @"127.0.0.1",
|
||||
(NSString *)kCFNetworkProxiesHTTPSPort: @9090
|
||||
};
|
||||
NSLog(@"[SocketRocket] Proxyman proxy enabled: 127.0.0.1:9090");
|
||||
#endif
|
||||
|
||||
[self.socket open];
|
||||
}
|
||||
}
|
||||
@ -65,7 +78,7 @@
|
||||
|
||||
- (void)send:(NSString*)message
|
||||
{
|
||||
#if _LOGGER_SOCKETS
|
||||
#ifdef _LOGGER_SOCKETS
|
||||
|
||||
NSLog(@"------------------- SEND TO SOCKET -------------------");
|
||||
NSLog(@"%@", message);
|
||||
@ -101,7 +114,7 @@
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message
|
||||
{
|
||||
#if _LOGGER_SOCKETS
|
||||
#ifdef _LOGGER_SOCKETS
|
||||
|
||||
NSLog(@"------------------- SOCKET RECEIVE MESSAGE -------------------");
|
||||
NSLog(@"%@", message);
|
||||
@ -119,7 +132,7 @@
|
||||
{
|
||||
m_listener->onOpen();
|
||||
|
||||
#if _LOGGER_SOCKETS
|
||||
#ifdef _LOGGER_SOCKETS
|
||||
|
||||
NSLog(@"------------------- SOCKET OPEN -------------------");
|
||||
NSLog(@"URL : %@", webSocket.url);
|
||||
@ -134,7 +147,7 @@
|
||||
{
|
||||
m_listener->onError(error.localizedDescription.stdstring);
|
||||
|
||||
#if _LOGGER_SOCKETS
|
||||
#ifdef _LOGGER_SOCKETS
|
||||
|
||||
NSLog(@"---------------------------------------------------------");
|
||||
NSLog(@"------------------- SOCKET ERROR : %@ ------------", error);
|
||||
@ -147,7 +160,7 @@
|
||||
{
|
||||
m_listener->onClose(code, reason.stdstring);
|
||||
|
||||
#if _LOGGER_SOCKETS
|
||||
#ifdef _LOGGER_SOCKETS
|
||||
|
||||
NSLog(@"---------------------------------------------------------");
|
||||
NSLog(@"------------------- SOCKET CLOSE : %@ -----------", reason);
|
||||
@ -158,7 +171,7 @@
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload
|
||||
{
|
||||
#if _LOGGER_SOCKETS
|
||||
#ifdef _LOGGER_SOCKETS
|
||||
|
||||
NSString *str = [[NSString alloc] initWithData:pongPayload encoding:NSUTF8StringEncoding];
|
||||
|
||||
|
||||
@ -967,7 +967,12 @@ bool COfficeFileFormatChecker::isOfficeFile(const std::wstring &_fileName)
|
||||
nFileType = AVS_OFFICESTUDIO_FILE_DOCUMENT_MHT;
|
||||
else if (0 == sExt.compare(L".md"))
|
||||
nFileType = AVS_OFFICESTUDIO_FILE_DOCUMENT_MD;
|
||||
else if (0 == sExt.compare(L".csv") || 0 == sExt.compare(L".tsv") || 0 == sExt.compare(L".xls") || 0 == sExt.compare(L".xlsx") || 0 == sExt.compare(L".xlsb"))
|
||||
else if (0 == sExt.compare(L".tsv"))
|
||||
nFileType = AVS_OFFICESTUDIO_FILE_SPREADSHEET_TSV;
|
||||
else if (0 == sExt.compare(L".scsv"))
|
||||
nFileType = AVS_OFFICESTUDIO_FILE_SPREADSHEET_SCSV;
|
||||
else if (0 == sExt.compare(L".csv") || 0 == sExt.compare(L".tsv") || 0 == sExt.compare(L".dsv") || 0 == sExt.compare(L".cssv")
|
||||
|| 0 == sExt.compare(L".xls") || 0 == sExt.compare(L".xlsx") || 0 == sExt.compare(L".xlsb"))
|
||||
nFileType = AVS_OFFICESTUDIO_FILE_SPREADSHEET_CSV;
|
||||
else if (0 == sExt.compare(L".html") || 0 == sExt.compare(L".htm"))
|
||||
nFileType = AVS_OFFICESTUDIO_FILE_DOCUMENT_HTML;
|
||||
@ -1799,6 +1804,10 @@ std::wstring COfficeFileFormatChecker::GetExtensionByType(int type)
|
||||
return L".ods";
|
||||
case AVS_OFFICESTUDIO_FILE_SPREADSHEET_CSV:
|
||||
return L".csv";
|
||||
case AVS_OFFICESTUDIO_FILE_SPREADSHEET_TSV:
|
||||
return L".tsv";
|
||||
case AVS_OFFICESTUDIO_FILE_SPREADSHEET_SCSV:
|
||||
return L".scsv";
|
||||
case AVS_OFFICESTUDIO_FILE_SPREADSHEET_ODS_FLAT:
|
||||
return L".fods";
|
||||
case AVS_OFFICESTUDIO_FILE_SPREADSHEET_OTS:
|
||||
@ -1988,7 +1997,11 @@ int COfficeFileFormatChecker::GetFormatByExtension(const std::wstring &sExt)
|
||||
return AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLSB;
|
||||
if (L".xls" == ext)
|
||||
return AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLS;
|
||||
if (L".csv" == ext)
|
||||
if (L".tsv" == ext)
|
||||
return AVS_OFFICESTUDIO_FILE_SPREADSHEET_TSV;
|
||||
if (L".scsv" == ext)
|
||||
return AVS_OFFICESTUDIO_FILE_SPREADSHEET_SCSV;
|
||||
if (L".csv" == ext || L".dsv" == ext)
|
||||
return AVS_OFFICESTUDIO_FILE_SPREADSHEET_CSV;
|
||||
if (L".fods" == ext)
|
||||
return AVS_OFFICESTUDIO_FILE_SPREADSHEET_ODS_FLAT;
|
||||
|
||||
@ -87,13 +87,14 @@
|
||||
#define AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLSM AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0005
|
||||
#define AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLTX AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0006
|
||||
#define AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLTM AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0007
|
||||
|
||||
#define AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLSB AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0008
|
||||
#define AVS_OFFICESTUDIO_FILE_SPREADSHEET_ODS_FLAT AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0009
|
||||
#define AVS_OFFICESTUDIO_FILE_SPREADSHEET_OTS AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x000a
|
||||
#define AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLSX_FLAT AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x000b
|
||||
#define AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLSX_PACKAGE AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x000c
|
||||
#define AVS_OFFICESTUDIO_FILE_SPREADSHEET_NUMBERS AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x000d
|
||||
#define AVS_OFFICESTUDIO_FILE_SPREADSHEET_TSV AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0014
|
||||
#define AVS_OFFICESTUDIO_FILE_SPREADSHEET_SCSV AVS_OFFICESTUDIO_FILE_SPREADSHEET + 0x0024
|
||||
|
||||
#define AVS_OFFICESTUDIO_FILE_CROSSPLATFORM 0x0200
|
||||
#define AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0001
|
||||
|
||||
138
Common/base.pri
138
Common/base.pri
@ -199,6 +199,13 @@ core_win_64 {
|
||||
DEFINES += WIN64 _WIN64
|
||||
}
|
||||
|
||||
defineTest(startsWith) {
|
||||
tmp = $$2
|
||||
tmp ~= s,^$$re_escape($$1),,
|
||||
!equals(tmp, $$2): return(true)
|
||||
return(false)
|
||||
}
|
||||
|
||||
core_linux {
|
||||
DEFINES += LINUX _LINUX
|
||||
|
||||
@ -213,7 +220,7 @@ core_linux {
|
||||
}
|
||||
QMAKE_CUSTOM_SYSROOT_BIN = $$join(QMAKE_CUSTOM_SYSROOT_BIN, , , /)
|
||||
|
||||
contains(QMAKE_CUSTOM_SYSROOT_BIN, $$QMAKE_CUSTOM_SYSROOT) {
|
||||
startsWith($$QMAKE_CUSTOM_SYSROOT, $$QMAKE_CUSTOM_SYSROOT_BIN) {
|
||||
message("Using compilers from same sysroot")
|
||||
QMAKE_CC = $$join(QMAKE_CUSTOM_SYSROOT_BIN, , , "gcc")
|
||||
QMAKE_CXX = $$join(QMAKE_CUSTOM_SYSROOT_BIN, , , "g++")
|
||||
@ -471,6 +478,15 @@ core_android {
|
||||
!core_android_no_unistd {
|
||||
DEFINES += HAVE_UNISTD_H HAVE_FCNTL_H
|
||||
}
|
||||
|
||||
core_release {
|
||||
QMAKE_CFLAGS += -g0
|
||||
QMAKE_CXXFLAGS += -g0
|
||||
QMAKE_LFLAGS += -Wl,-s
|
||||
|
||||
QMAKE_CFLAGS -= -fno-limit-debug-info
|
||||
QMAKE_CXXFLAGS -= -fno-limit-debug-info
|
||||
}
|
||||
}
|
||||
|
||||
core_debug {
|
||||
@ -701,54 +717,98 @@ ADD_INC_PATH = $$(ADDITIONAL_INCLUDE_PATH)
|
||||
SWIFT_SOURCES=
|
||||
defineTest(UseSwift) {
|
||||
isEmpty(SWIFT_SOURCES): return(false)
|
||||
|
||||
bridging_header = $$1
|
||||
|
||||
SWIFT_GEN_HEADERS_PATH = $$PWD_ROOT_DIR/core_build/$$CORE_BUILDS_PLATFORM_PREFIX/$$CORE_BUILDS_CONFIGURATION_PREFIX
|
||||
|
||||
swift_compiler.name = SwiftCompiler
|
||||
swift_compiler.input = SWIFT_MAIN_FILE
|
||||
swift_compiler.output = $$SWIFT_GEN_HEADERS_PATH/swift_module.o
|
||||
swift_cmd = swiftc -c $$SWIFT_SOURCES \
|
||||
-module-name SwiftModule \
|
||||
-whole-module-optimization \
|
||||
-emit-objc-header \
|
||||
-emit-objc-header-path $$SWIFT_GEN_HEADERS_PATH/SwiftModule-Swift.h \
|
||||
-emit-object \
|
||||
-sdk /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk \
|
||||
-target arm64-apple-ios15.0 \
|
||||
-o $$SWIFT_GEN_HEADERS_PATH/swift_module.o \
|
||||
-framework UIKit
|
||||
|
||||
!empty(bridging_header) {
|
||||
swift_cmd += -import-objc-header $$bridging_header
|
||||
# work only on ios and mac
|
||||
!core_ios:!core_mac {
|
||||
return(false)
|
||||
}
|
||||
|
||||
swift_compiler.commands = $$swift_cmd
|
||||
swift_compiler.CONFIG = target_predeps no_link
|
||||
swift_compiler.variable_out = OBJECTS
|
||||
# path to the bridging header that exposes Objective-C code to Swift
|
||||
BRIDGING_HEADER = $$1
|
||||
# sdk and toolchain (set from environment variables)
|
||||
SDK_PATH = $$(SDK_PATH)
|
||||
XCODE_TOOLCHAIN_PATH = $$(XCODE_TOOLCHAIN_PATH)
|
||||
|
||||
export(swift_compiler.name)
|
||||
export(swift_compiler.input)
|
||||
export(swift_compiler.output)
|
||||
export(swift_compiler.commands)
|
||||
export(swift_compiler.CONFIG)
|
||||
export(swift_compiler.variable_out)
|
||||
IOS_TARGET_PLATFORM = apple-ios11.0
|
||||
SWIFT_GEN_HEADERS_PATH = $$PWD_ROOT_DIR/core_build/$$CORE_BUILDS_PLATFORM_PREFIX/$$CORE_BUILDS_CONFIGURATION_PREFIX
|
||||
ARCHS = arm64
|
||||
# simulator
|
||||
xcframework_platform_ios_simulator {
|
||||
IOS_TARGET_PLATFORM = $${IOS_TARGET_PLATFORM}-simulator
|
||||
SWIFT_GEN_HEADERS_PATH = $$SWIFT_GEN_HEADERS_PATH/simulator
|
||||
ARCHS += x86_64
|
||||
}
|
||||
|
||||
# add swift compiler for each architecture
|
||||
SWIFT_COMPILERS_OUT =
|
||||
for(ARCH, ARCHS) {
|
||||
COMPILER_NAME = swift_compiler_$${ARCH}
|
||||
COMPILER_OUTPUT = $$SWIFT_GEN_HEADERS_PATH/swift_module_$${ARCH}.o
|
||||
SWIFT_COMPILERS_OUT += $$COMPILER_OUTPUT
|
||||
|
||||
$${COMPILER_NAME}.name = SwiftCompiler_$${ARCH}
|
||||
$${COMPILER_NAME}.input = SWIFT_SOURCES
|
||||
$${COMPILER_NAME}.output = $$COMPILER_OUTPUT
|
||||
SWIFT_CMD = swiftc -c $$SWIFT_SOURCES \
|
||||
-module-name SwiftModule \
|
||||
-whole-module-optimization \
|
||||
-emit-objc-header \
|
||||
-emit-objc-header-path $$SWIFT_GEN_HEADERS_PATH/SwiftModule-Swift.h \
|
||||
-emit-object \
|
||||
-sdk $$SDK_PATH \
|
||||
-target $${ARCH}-$${IOS_TARGET_PLATFORM} \
|
||||
-o $$COMPILER_OUTPUT \
|
||||
-framework UIKit
|
||||
|
||||
!isEmpty(BRIDGING_HEADER) {
|
||||
SWIFT_CMD += -import-objc-header $$BRIDGING_HEADER
|
||||
}
|
||||
|
||||
$${COMPILER_NAME}.commands = $$SWIFT_CMD
|
||||
$${COMPILER_NAME}.CONFIG = combine target_predeps no_link
|
||||
|
||||
export($${COMPILER_NAME}.name)
|
||||
export($${COMPILER_NAME}.input)
|
||||
export($${COMPILER_NAME}.output)
|
||||
export($${COMPILER_NAME}.commands)
|
||||
export($${COMPILER_NAME}.CONFIG)
|
||||
QMAKE_EXTRA_COMPILERS += $${COMPILER_NAME}
|
||||
}
|
||||
|
||||
# add lipo tool execution to form universal binary
|
||||
LIPO_OUT = $$SWIFT_GEN_HEADERS_PATH/swift_module.o
|
||||
lipo_tool.name = LipoTool
|
||||
# as input for lipo_tool we set SWIFT_SOURCES (not SWIFT_COMPILERS_OUT as it won't be executed otherwise!)
|
||||
lipo_tool.input = SWIFT_SOURCES
|
||||
# compiled swift sources go into depends
|
||||
lipo_tool.depends = $$SWIFT_COMPILERS_OUT
|
||||
lipo_tool.output = $$LIPO_OUT
|
||||
lipo_tool.commands = lipo -create $$SWIFT_COMPILERS_OUT -output $$LIPO_OUT
|
||||
lipo_tool.CONFIG = combine target_predeps no_link
|
||||
lipo_tool.variable_out = OBJECTS
|
||||
|
||||
export(lipo_tool.name)
|
||||
export(lipo_tool.input)
|
||||
export(lipo_tool.depends)
|
||||
export(lipo_tool.output)
|
||||
export(lipo_tool.commands)
|
||||
export(lipo_tool.CONFIG)
|
||||
export(lipo_tool.variable_out)
|
||||
QMAKE_EXTRA_COMPILERS += lipo_tool
|
||||
|
||||
QMAKE_EXTRA_COMPILERS += swift_compiler
|
||||
export(QMAKE_EXTRA_COMPILERS)
|
||||
|
||||
SWIFT_MAIN_FILE = $$first(SWIFT_SOURCES)
|
||||
export(SWIFT_MAIN_FILE)
|
||||
|
||||
INCLUDEPATH += $$SWIFT_GEN_HEADERS_PATH
|
||||
export(INCLUDEPATH)
|
||||
|
||||
core_ios|core_mac {
|
||||
LIBS += -lswiftCore -lswiftFoundation -lswiftObjectiveC
|
||||
LIBS += -framework UIKit
|
||||
export(LIBS)
|
||||
# link with libs from toolchain
|
||||
SWIFT_LIB_PATH = $$XCODE_TOOLCHAIN_PATH/usr/lib/swift/iphoneos
|
||||
xcframework_platform_ios_simulator {
|
||||
SWIFT_LIB_PATH = $$XCODE_TOOLCHAIN_PATH/usr/lib/swift/iphonesimulator
|
||||
}
|
||||
LIBS += -L$$SWIFT_LIB_PATH
|
||||
LIBS += -lswiftCore -lswiftFoundation -lswiftObjectiveC
|
||||
|
||||
export(LIBS)
|
||||
|
||||
OTHER_FILES += $$SWIFT_SOURCES
|
||||
export(OTHER_FILES)
|
||||
|
||||
@ -195,6 +195,16 @@ namespace NSStringUtils
|
||||
m_pDataCur = m_pData;
|
||||
m_lSizeCur = m_lSize;
|
||||
}
|
||||
|
||||
CStringBuilder::CStringBuilder(size_t nSize)
|
||||
{
|
||||
m_lSize = nSize;
|
||||
m_pData = (wchar_t*)malloc(m_lSize * sizeof(wchar_t));
|
||||
|
||||
m_lSizeCur = 0;
|
||||
m_pDataCur = m_pData;
|
||||
return;
|
||||
}
|
||||
CStringBuilder::~CStringBuilder()
|
||||
{
|
||||
if (NULL != m_pData)
|
||||
|
||||
@ -86,6 +86,7 @@ namespace NSStringUtils
|
||||
|
||||
public:
|
||||
CStringBuilder();
|
||||
CStringBuilder(size_t nSize);
|
||||
virtual ~CStringBuilder();
|
||||
|
||||
virtual void AddSize(size_t nSize);
|
||||
|
||||
@ -347,11 +347,11 @@ bool CV8RealTimeWorker::OpenFile(const std::wstring& sBasePath, const std::wstri
|
||||
}
|
||||
|
||||
if (!bIsBreak)
|
||||
bIsBreak = !this->ExecuteCommand(L"Api.asc_nativeInitBuilder();");
|
||||
bIsBreak = !this->ExecuteCommand(L"Asc.editor.asc_nativeInitBuilder();");
|
||||
if (!bIsBreak)
|
||||
bIsBreak = !this->ExecuteCommand(L"Api.asc_SetSilentMode(true);");
|
||||
bIsBreak = !this->ExecuteCommand(L"Asc.editor.asc_SetSilentMode(true);");
|
||||
if (!bIsBreak)
|
||||
bIsBreak = !this->ExecuteCommand(L"Api.asc_showComments();");
|
||||
bIsBreak = !this->ExecuteCommand(L"Asc.editor.asc_showComments();");
|
||||
|
||||
LOGGER_SPEED_LAP("open");
|
||||
|
||||
@ -425,7 +425,7 @@ bool CV8RealTimeWorker::SaveFileWithChanges(int type, const std::wstring& _path,
|
||||
bIsSilentMode = true;
|
||||
|
||||
if (bIsSilentMode)
|
||||
this->ExecuteCommand(L"Api.asc_SetSilentMode(false);", NULL, isEnterContext);
|
||||
this->ExecuteCommand(L"Asc.editor.asc_SetSilentMode(false);", NULL, isEnterContext);
|
||||
|
||||
std::wstring strError;
|
||||
bool bIsError = Doct_renderer_SaveFile_ForBuilder(_formatDst,
|
||||
@ -437,7 +437,7 @@ bool CV8RealTimeWorker::SaveFileWithChanges(int type, const std::wstring& _path,
|
||||
sJsonParams);
|
||||
|
||||
if (bIsSilentMode)
|
||||
this->ExecuteCommand(L"Api.asc_SetSilentMode(true);", NULL, isEnterContext);
|
||||
this->ExecuteCommand(L"Asc.editor.asc_SetSilentMode(true);", NULL, isEnterContext);
|
||||
|
||||
if (isEnterContext)
|
||||
m_context->Exit();
|
||||
@ -1507,7 +1507,7 @@ namespace NSDoctRenderer
|
||||
if (m_pInternal->m_oParams.m_bSaveWithDoctrendererMode)
|
||||
{
|
||||
// перед сохранением в такой схеме нужно скинуть изменения
|
||||
this->ExecuteCommand(L"Api.asc_Save();");
|
||||
this->ExecuteCommand(L"Asc.editor.asc_Save();");
|
||||
}
|
||||
|
||||
const wchar_t* sParams = NULL;
|
||||
|
||||
@ -287,7 +287,10 @@ namespace NSDoctRenderer
|
||||
|
||||
JSSmart<CJSObject> js_objectApi = api_js_maybe_null;
|
||||
if (!js_objectApi.IsInit() || js_objectApi->isUndefined())
|
||||
js_objectApi = global_js->get("Api")->toObject();
|
||||
{
|
||||
JSSmart<CJSObject> js_objectAsc = global_js->get("Asc")->toObject();
|
||||
js_objectApi = js_objectAsc->get("editor")->toObject();
|
||||
}
|
||||
|
||||
bool bIsBreak = false;
|
||||
if (js_objectApi->isUndefined() || !js_objectApi->isObject())
|
||||
@ -687,7 +690,8 @@ namespace NSDoctRenderer
|
||||
bIsBreak = true;
|
||||
}
|
||||
|
||||
js_objectApi = global_js->get("Api")->toObject();
|
||||
JSSmart<CJSObject> js_objectAsc = global_js->get("Asc")->toObject();
|
||||
js_objectApi = js_objectAsc->get("editor")->toObject();
|
||||
if (try_catch->Check())
|
||||
{
|
||||
strError = L"code=\"open\"";
|
||||
|
||||
@ -120,7 +120,7 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
bool OpenFile(const std::wstring& sFile, const std::wstring& sPassword)
|
||||
bool OpenFile(const std::wstring& sFile, const wchar_t* sPassword)
|
||||
{
|
||||
CloseFile();
|
||||
|
||||
@ -171,7 +171,7 @@ public:
|
||||
|
||||
return m_pFile ? true : false;
|
||||
}
|
||||
bool OpenFile(BYTE* data, LONG size, const std::wstring& sPassword)
|
||||
bool OpenFile(BYTE* data, LONG size, const wchar_t* sPassword)
|
||||
{
|
||||
CloseFile();
|
||||
|
||||
@ -245,7 +245,7 @@ public:
|
||||
|
||||
return 0;
|
||||
}
|
||||
bool CheckOwnerPassword(const std::wstring& sPassword)
|
||||
bool CheckOwnerPassword(const wchar_t* sPassword)
|
||||
{
|
||||
if (m_nType == 0)
|
||||
return ((CPdfFile*)m_pFile)->CheckOwnerPassword(sPassword);
|
||||
@ -602,6 +602,12 @@ public:
|
||||
std::wstring sFontName = UTF8_TO_U(sPathA);
|
||||
return ((CPdfFile*)m_pFile)->GetGIDByUnicode(sFontName);
|
||||
}
|
||||
BYTE* GetGIDByUnicode(const std::wstring& wsPathA)
|
||||
{
|
||||
if (m_nType != 0)
|
||||
return NULL;
|
||||
return ((CPdfFile*)m_pFile)->GetGIDByUnicode(wsPathA);
|
||||
}
|
||||
|
||||
std::wstring GetFontBinaryNative(const std::wstring& sName)
|
||||
{
|
||||
|
||||
@ -26,7 +26,8 @@ CDrawingFileEmbed::~CDrawingFileEmbed()
|
||||
|
||||
JSSmart<CJSValue> CDrawingFileEmbed::OpenFile(JSSmart<CJSValue> sFile, JSSmart<CJSValue> sPassword)
|
||||
{
|
||||
bool bResult = m_pFile->OpenFile(sFile->toStringW(), sPassword->isString() ? sPassword->toStringW() : L"");
|
||||
std::wstring wsPassword = sPassword->isString() ? sPassword->toStringW() : L"";
|
||||
bool bResult = m_pFile->OpenFile(sFile->toStringW(), sPassword->isString() ? wsPassword.c_str() : NULL);
|
||||
return CJSContext::createBool(bResult);
|
||||
}
|
||||
JSSmart<CJSValue> CDrawingFileEmbed::CloseFile()
|
||||
@ -136,6 +137,10 @@ JSSmart<CJSValue> CDrawingFileEmbed::DestroyTextInfo()
|
||||
m_pFile->DestroyTextInfo();
|
||||
return CJSContext::createUndefined();
|
||||
}
|
||||
JSSmart<CJSValue> CDrawingFileEmbed::GetGIDByUnicode(JSSmart<CJSValue> sId)
|
||||
{
|
||||
return WasmMemoryToJS(m_pFile->GetGIDByUnicode(sId->toStringW()));
|
||||
}
|
||||
JSSmart<CJSValue> CDrawingFileEmbed::IsNeedCMap()
|
||||
{
|
||||
return CJSContext::createBool(false);
|
||||
@ -144,6 +149,11 @@ JSSmart<CJSValue> CDrawingFileEmbed::ScanPage(JSSmart<CJSValue> nPageIndex, JSSm
|
||||
{
|
||||
return WasmMemoryToJS(m_pFile->ScanPage(nPageIndex->toInt32(), mode->toInt32()));
|
||||
}
|
||||
JSSmart<CJSValue> CDrawingFileEmbed::SetScanPageFonts(JSSmart<CJSValue> nPageIndex)
|
||||
{
|
||||
m_pFile->SetScanPageFonts(nPageIndex->toInt32());
|
||||
return CJSContext::createUndefined();
|
||||
}
|
||||
|
||||
JSSmart<CJSValue> CDrawingFileEmbed::GetImageBase64(JSSmart<CJSValue> rId)
|
||||
{
|
||||
@ -242,6 +252,17 @@ JSSmart<CJSValue> CDrawingFileEmbed::UndoRedact()
|
||||
return CJSContext::createBool(false);
|
||||
}
|
||||
|
||||
JSSmart<CJSValue> CDrawingFileEmbed::CheckOwnerPassword(JSSmart<CJSValue> sPassword)
|
||||
{
|
||||
std::wstring wsPassword = sPassword->isString() ? sPassword->toStringW() : L"";
|
||||
bool bResult = m_pFile->CheckOwnerPassword(sPassword->isString() ? wsPassword.c_str() : NULL);
|
||||
return CJSContext::createBool(bResult);
|
||||
}
|
||||
JSSmart<CJSValue> CDrawingFileEmbed::CheckPerm(JSSmart<CJSValue> nPerm)
|
||||
{
|
||||
return CJSContext::createBool(m_pFile->CheckPerm(nPerm->toInt32()));
|
||||
}
|
||||
|
||||
bool EmbedDrawingFile(JSSmart<NSJSBase::CJSContext>& context, IOfficeDrawingFile* pFile)
|
||||
{
|
||||
CJSContext::Embed<CDrawingFileEmbed>(false);
|
||||
|
||||
@ -43,9 +43,11 @@ public:
|
||||
JSSmart<CJSValue> GetFontBinary(JSSmart<CJSValue> Id);
|
||||
JSSmart<CJSValue> GetGlyphs(JSSmart<CJSValue> nPageIndex);
|
||||
JSSmart<CJSValue> DestroyTextInfo();
|
||||
JSSmart<CJSValue> GetGIDByUnicode(JSSmart<CJSValue> sId);
|
||||
|
||||
JSSmart<CJSValue> IsNeedCMap();
|
||||
JSSmart<CJSValue> ScanPage(JSSmart<CJSValue> nPageIndex, JSSmart<CJSValue> mode);
|
||||
JSSmart<CJSValue> SetScanPageFonts(JSSmart<CJSValue> nPageIndex);
|
||||
|
||||
JSSmart<CJSValue> GetImageBase64(JSSmart<CJSValue> rId);
|
||||
|
||||
@ -57,6 +59,9 @@ public:
|
||||
JSSmart<CJSValue> RedactPage(JSSmart<CJSValue> nPageIndex, JSSmart<CJSValue> arrRedactBox, JSSmart<CJSValue> dataFiller);
|
||||
JSSmart<CJSValue> UndoRedact();
|
||||
|
||||
JSSmart<CJSValue> CheckOwnerPassword(JSSmart<CJSValue> sPassword);
|
||||
JSSmart<CJSValue> CheckPerm(JSSmart<CJSValue> nPerm);
|
||||
|
||||
DECLARE_EMBED_METHODS
|
||||
};
|
||||
|
||||
|
||||
@ -23,8 +23,10 @@
|
||||
-(JSValue*) GetFontBinary : (JSValue*)Id;
|
||||
-(JSValue*) GetGlyphs : (JSValue*)nPageIndex;
|
||||
-(JSValue*) DestroyTextInfo;
|
||||
-(JSValue*) GetGIDByUnicode : (JSValue*)sId;
|
||||
-(JSValue*) IsNeedCMap;
|
||||
-(JSValue*) ScanPage : (JSValue*)nPageIndex : (JSValue*)mode;
|
||||
-(JSValue*) SetScanPageFonts : (JSValue*)nPageIndex;
|
||||
-(JSValue*) GetImageBase64 : (JSValue*)rId;
|
||||
-(JSValue*) FreeWasmData : (JSValue*)typedArray;
|
||||
-(JSValue*) SplitPages : (JSValue*)arrPageIndexes : (JSValue*)data;
|
||||
@ -32,6 +34,8 @@
|
||||
-(JSValue*) UnmergePages;
|
||||
-(JSValue*) RedactPage : (JSValue*)nPageIndex : (JSValue*)arrRedactBox : (JSValue*)dataFiller;
|
||||
-(JSValue*) UndoRedact;
|
||||
-(JSValue*) CheckOwnerPassword : (JSValue*)sPassword;
|
||||
-(JSValue*) CheckPerm : (JSValue*)nPerm;
|
||||
@end
|
||||
|
||||
@interface CJSCDrawingFileEmbed : NSObject<IJSCDrawingFileEmbed, JSEmbedObjectProtocol>
|
||||
@ -62,8 +66,10 @@ FUNCTION_WRAPPER_JS_6(GetAnnotationsAP, GetAnnotationsAP)
|
||||
FUNCTION_WRAPPER_JS_1(GetFontBinary, GetFontBinary)
|
||||
FUNCTION_WRAPPER_JS_1(GetGlyphs, GetGlyphs)
|
||||
FUNCTION_WRAPPER_JS_0(DestroyTextInfo, DestroyTextInfo)
|
||||
FUNCTION_WRAPPER_JS_1(GetGIDByUnicode, GetGIDByUnicode)
|
||||
FUNCTION_WRAPPER_JS_0(IsNeedCMap, IsNeedCMap)
|
||||
FUNCTION_WRAPPER_JS_2(ScanPage, ScanPage)
|
||||
FUNCTION_WRAPPER_JS_1(SetScanPageFonts, SetScanPageFonts)
|
||||
FUNCTION_WRAPPER_JS_1(GetImageBase64, GetImageBase64)
|
||||
FUNCTION_WRAPPER_JS_1(FreeWasmData, FreeWasmData)
|
||||
FUNCTION_WRAPPER_JS_2(SplitPages, SplitPages)
|
||||
@ -71,6 +77,8 @@ FUNCTION_WRAPPER_JS_3(MergePages, MergePages)
|
||||
FUNCTION_WRAPPER_JS_0(UnmergePages, UnmergePages)
|
||||
FUNCTION_WRAPPER_JS_3(RedactPage, RedactPage)
|
||||
FUNCTION_WRAPPER_JS_0(UndoRedact, UndoRedact)
|
||||
FUNCTION_WRAPPER_JS_1(CheckOwnerPassword, CheckOwnerPassword)
|
||||
FUNCTION_WRAPPER_JS_1(CheckPerm, CheckPerm)
|
||||
@end
|
||||
|
||||
class CDrawingFileEmbedAdapter : public CJSEmbedObjectAdapterJSC
|
||||
|
||||
@ -26,8 +26,10 @@ namespace NSDrawingFileEmbed
|
||||
FUNCTION_WRAPPER_V8_1(_GetFontBinary, GetFontBinary)
|
||||
FUNCTION_WRAPPER_V8_1(_GetGlyphs, GetGlyphs)
|
||||
FUNCTION_WRAPPER_V8_0(_DestroyTextInfo, DestroyTextInfo)
|
||||
FUNCTION_WRAPPER_V8_1(_GetGIDByUnicode, GetGIDByUnicode)
|
||||
FUNCTION_WRAPPER_V8_0(_IsNeedCMap, IsNeedCMap)
|
||||
FUNCTION_WRAPPER_V8_2(_ScanPage, ScanPage)
|
||||
FUNCTION_WRAPPER_V8_1(_SetScanPageFonts, SetScanPageFonts)
|
||||
FUNCTION_WRAPPER_V8_1(_GetImageBase64, GetImageBase64)
|
||||
FUNCTION_WRAPPER_V8_1(_FreeWasmData, FreeWasmData)
|
||||
FUNCTION_WRAPPER_V8_2(_SplitPages, SplitPages)
|
||||
@ -35,6 +37,8 @@ namespace NSDrawingFileEmbed
|
||||
FUNCTION_WRAPPER_V8_0(_UnmergePages, UnmergePages)
|
||||
FUNCTION_WRAPPER_V8_3(_RedactPage, RedactPage)
|
||||
FUNCTION_WRAPPER_V8_0(_UndoRedact, UndoRedact)
|
||||
FUNCTION_WRAPPER_V8_1(_CheckOwnerPassword, CheckOwnerPassword)
|
||||
FUNCTION_WRAPPER_V8_1(_CheckPerm, CheckPerm)
|
||||
|
||||
v8::Handle<v8::ObjectTemplate> CreateTemplate(v8::Isolate* isolate)
|
||||
{
|
||||
@ -60,8 +64,10 @@ namespace NSDrawingFileEmbed
|
||||
NSV8Objects::Template_Set(result, "GetFontBinary", _GetFontBinary);
|
||||
NSV8Objects::Template_Set(result, "GetGlyphs", _GetGlyphs);
|
||||
NSV8Objects::Template_Set(result, "DestroyTextInfo", _DestroyTextInfo);
|
||||
NSV8Objects::Template_Set(result, "GetGIDByUnicode", _GetGIDByUnicode);
|
||||
NSV8Objects::Template_Set(result, "IsNeedCMap", _IsNeedCMap);
|
||||
NSV8Objects::Template_Set(result, "ScanPage", _ScanPage);
|
||||
NSV8Objects::Template_Set(result, "SetScanPageFonts", _SetScanPageFonts);
|
||||
NSV8Objects::Template_Set(result, "GetImageBase64", _GetImageBase64);
|
||||
NSV8Objects::Template_Set(result, "FreeWasmData", _FreeWasmData);
|
||||
NSV8Objects::Template_Set(result, "SplitPages", _SplitPages);
|
||||
@ -69,6 +75,8 @@ namespace NSDrawingFileEmbed
|
||||
NSV8Objects::Template_Set(result, "UnmergePages", _UnmergePages);
|
||||
NSV8Objects::Template_Set(result, "RedactPage", _RedactPage);
|
||||
NSV8Objects::Template_Set(result, "UndoRedact", _UndoRedact);
|
||||
NSV8Objects::Template_Set(result, "CheckOwnerPassword", _CheckOwnerPassword);
|
||||
NSV8Objects::Template_Set(result, "CheckPerm", _CheckPerm);
|
||||
|
||||
return handle_scope.Escape(result);
|
||||
}
|
||||
|
||||
@ -85,6 +85,13 @@ bool Segment::IsEmpty() const noexcept
|
||||
return Id == 0 && Index == -1 && P.IsZero() && HI.IsZero() && HO.IsZero();
|
||||
}
|
||||
|
||||
bool Segment::Equals(const Segment& other) const noexcept
|
||||
{
|
||||
return isZero(P.X - other.P.X) && isZero(P.Y - other.P.Y) &&
|
||||
isZero(HI.X - other.HI.X) && isZero(HI.Y - other.HI.Y) &&
|
||||
isZero(HO.X - other.HO.X) && isZero(HO.Y - other.HO.Y);
|
||||
}
|
||||
|
||||
bool Segment::operator==(const Segment& other) const noexcept
|
||||
{
|
||||
return (Index == other.Index) && (Id == other.Id);
|
||||
@ -690,6 +697,12 @@ bool Curve::IsStraight() const noexcept
|
||||
return !Segment2.IsCurve;
|
||||
}
|
||||
|
||||
bool Curve::Equals(const Curve& other) const noexcept
|
||||
{
|
||||
return Segment1.Equals(other.Segment1) &&
|
||||
Segment2.Equals(other.Segment2);
|
||||
}
|
||||
|
||||
bool Curve::operator==(const Curve& other) const noexcept
|
||||
{
|
||||
return Segment1 == other.Segment1 &&
|
||||
@ -830,7 +843,7 @@ void CBooleanOperations::TraceBoolean()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Locations.empty())
|
||||
if (!Locations.empty() && !IsOnlyEnds())
|
||||
{
|
||||
int length = static_cast<int>(Locations.size());
|
||||
for (int i = 0; i < length; i++)
|
||||
@ -1845,7 +1858,7 @@ void CBooleanOperations::GetCurveIntersection(const Curve& curve1, const Curve&
|
||||
AddCurveIntersection(flip ? curve2 : curve1, flip ? curve1 : curve2,
|
||||
flip ? curve2 : curve1, flip ? curve1 : curve2, flip);
|
||||
|
||||
if (Locations.size() == before && (!straight || Locations.empty()))
|
||||
if (Locations.size() == before && (!straight /*|| Locations.empty()*/))
|
||||
{
|
||||
double t = curve2.GetTimeOf(curve1.Segment1.P);
|
||||
if (t != -1.0)
|
||||
@ -2058,17 +2071,27 @@ bool CBooleanOperations::IsInside(const Segment& segment) const
|
||||
|
||||
void CBooleanOperations::SetWinding()
|
||||
{
|
||||
if (Locations.empty() || (Locations.size() == 2 && Locations[0]->Ends))
|
||||
if (Locations.empty() || (Locations.size() == 2 && Locations[0]->Ends) || IsOnlyEnds())
|
||||
{
|
||||
Segment s1, s2;
|
||||
Segment s1 = Segments1[0], s2 = Segments2[0];
|
||||
|
||||
for (const auto& s : Segments1)
|
||||
if (!s.Inters)
|
||||
{
|
||||
bool skip = false;
|
||||
for (const auto& ss : Segments2)
|
||||
skip = skip || !s.Equals(ss);
|
||||
if (!s.Inters && !skip)
|
||||
s1 = s;
|
||||
}
|
||||
|
||||
for (const auto& s : Segments2)
|
||||
if (!s.Inters)
|
||||
{
|
||||
bool skip = false;
|
||||
for (const auto& ss : Segments1)
|
||||
skip = skip || !s.Equals(ss);
|
||||
if (!s.Inters && !skip)
|
||||
s2 = s;
|
||||
}
|
||||
|
||||
bool winding = IsInside(s1);
|
||||
|
||||
@ -2285,8 +2308,8 @@ bool CBooleanOperations::IsOneCurvePath(int pathIndex) const noexcept
|
||||
void CBooleanOperations::AddLocation(Curve curve1, Curve curve2, double t1,
|
||||
double t2, bool overlap, bool filter, bool ends)
|
||||
{
|
||||
bool excludeStart = !overlap && GetPreviousCurve(curve1) == curve2,
|
||||
excludeEnd = !overlap && curve1 != curve2 && GetNextCurve(curve1) == curve2;
|
||||
bool excludeStart = !overlap && GetPreviousCurve(curve1).Equals(curve2),
|
||||
excludeEnd = !overlap && curve1 != curve2 && GetNextCurve(curve1).Equals(curve2);
|
||||
double tMin = CURVETIME_EPSILON,
|
||||
tMax = 1 - tMin;
|
||||
|
||||
@ -2345,6 +2368,18 @@ bool CBooleanOperations::CheckLocation(std::shared_ptr<Location> loc, bool start
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CBooleanOperations::IsOnlyEnds() const noexcept
|
||||
{
|
||||
bool onlyEnds1 = true;
|
||||
bool onlyEnds2 = true;
|
||||
for (const auto& l : Locations)
|
||||
{
|
||||
onlyEnds1 = onlyEnds1 && l->Ends;
|
||||
onlyEnds2 = onlyEnds2 && l->Inters->Ends;
|
||||
}
|
||||
return onlyEnds1 || onlyEnds2;
|
||||
}
|
||||
|
||||
CGraphicsPath CalcBooleanOperation(const CGraphicsPath& path1,
|
||||
const CGraphicsPath& path2,
|
||||
BooleanOpType op,
|
||||
|
||||
@ -37,6 +37,7 @@ namespace Aggplus
|
||||
|
||||
bool IsValid(const BooleanOpType& op) const noexcept;
|
||||
bool IsEmpty() const noexcept;
|
||||
bool Equals(const Segment& other) const noexcept;
|
||||
bool operator==(const Segment& other) const noexcept;
|
||||
bool operator!=(const Segment& other) const noexcept;
|
||||
};
|
||||
@ -82,6 +83,7 @@ namespace Aggplus
|
||||
void Flip() noexcept;
|
||||
|
||||
bool IsStraight() const noexcept;
|
||||
bool Equals(const Curve& other) const noexcept;
|
||||
bool operator==(const Curve& other) const noexcept;
|
||||
bool operator!=(const Curve& other) const noexcept;
|
||||
};
|
||||
@ -159,6 +161,7 @@ namespace Aggplus
|
||||
bool IsOneCurvePath(int pathIndex) const noexcept;
|
||||
void AddOffsets(std::vector<double>& offsets, const Curve& curve, bool end);
|
||||
bool CheckLocation(std::shared_ptr<Location> loc, bool start) const noexcept;
|
||||
bool IsOnlyEnds() const noexcept;
|
||||
|
||||
private:
|
||||
BooleanOpType Op = Intersection;
|
||||
|
||||
@ -1007,16 +1007,18 @@ namespace Aggplus
|
||||
bool CGraphicsPath::operator==(const CGraphicsPath& other) noexcept
|
||||
{
|
||||
unsigned pointsCount = GetPointCount(),
|
||||
otherPointsCount = other.GetPointCount();
|
||||
otherPointsCount = other.GetPointCount();
|
||||
|
||||
if (pointsCount != otherPointsCount)
|
||||
return false;
|
||||
|
||||
std::vector<PointD> points = GetPoints(0, pointsCount),
|
||||
otherPoints = other.GetPoints(0, otherPointsCount);
|
||||
otherPoints = other.GetPoints(0, otherPointsCount);
|
||||
|
||||
bool reverse = IsClockwise() ^ other.IsClockwise();
|
||||
|
||||
for (unsigned i = 0; i < pointsCount; i++)
|
||||
if (!points[i].Equals(otherPoints[i]))
|
||||
if (!points[i].Equals(otherPoints[reverse ? pointsCount - i - 1 : i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@ -481,6 +481,8 @@ namespace NSOnlineOfficeBinToPdf
|
||||
double m3 = oReader.ReadDouble();
|
||||
double m4 = oReader.ReadDouble();
|
||||
|
||||
clipRect = Aggplus::RectF_T<double>(m1, m2, m3, m4);
|
||||
|
||||
long type;
|
||||
pRenderer->get_BrushTextureMode(&type);
|
||||
if (type != c_BrushTextureModeStretch)
|
||||
@ -489,7 +491,6 @@ namespace NSOnlineOfficeBinToPdf
|
||||
m2 = 0.0;
|
||||
}
|
||||
|
||||
clipRect = Aggplus::RectF_T<double>(m1, m2, m3, m4);
|
||||
pRenderer->BrushRect(bIsEnableBrushRect ? 1 : 0, m1, m2, m3, m4);
|
||||
break;
|
||||
}
|
||||
@ -498,7 +499,10 @@ namespace NSOnlineOfficeBinToPdf
|
||||
bIsEnableBrushRect = oReader.ReadBool();
|
||||
|
||||
if (!bIsEnableBrushRect)
|
||||
{
|
||||
pRenderer->BrushRect(bIsEnableBrushRect ? 1 : 0, 0, 0, 1, 1);
|
||||
clipRect = Aggplus::RectF_T<double>();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ctBrushTexturePathOld:
|
||||
@ -770,7 +774,6 @@ namespace NSOnlineOfficeBinToPdf
|
||||
|
||||
clipPath.AddRectangle(clipRect.X, clipRect.Y, clipRect.Width, clipRect.Height);
|
||||
path = Aggplus::CalcBooleanOperation(drawPath, clipPath, Aggplus::Intersection);
|
||||
clipRect = Aggplus::RectF_T<double>();
|
||||
}
|
||||
|
||||
pRenderer->AddPath(path);
|
||||
|
||||
@ -70,7 +70,7 @@ CAnnotFieldInfo::CActionFieldPr* ReadAction(NSOnlineOfficeBinToPdf::CBufferReade
|
||||
case 6:
|
||||
case 7:
|
||||
{
|
||||
pRes->nFlags = pReader->ReadByte();
|
||||
pRes->nFlags = pReader->ReadInt();
|
||||
if (pRes->nFlags & (1 << 0))
|
||||
pRes->dD[0] = pReader->ReadDouble();
|
||||
if (pRes->nFlags & (1 << 1))
|
||||
|
||||
@ -197,7 +197,7 @@
|
||||
},
|
||||
{
|
||||
"folder": "../../../../PdfFile/SrcReader/",
|
||||
"files": ["Adaptors.cpp", "GfxClip.cpp", "RendererOutputDev.cpp", "JPXStream2.cpp", "PdfAnnot.cpp"]
|
||||
"files": ["Adaptors.cpp", "GfxClip.cpp", "RendererOutputDev.cpp", "JPXStream2.cpp", "PdfAnnot.cpp", "PdfFont.cpp"]
|
||||
},
|
||||
{
|
||||
"folder": "../../../../PdfFile/SrcWriter/",
|
||||
|
||||
@ -639,6 +639,7 @@ SOURCES += \
|
||||
$$PDF_ROOT_DIR/SrcReader/Adaptors.cpp \
|
||||
$$PDF_ROOT_DIR/SrcReader/GfxClip.cpp \
|
||||
$$PDF_ROOT_DIR/SrcReader/PdfAnnot.cpp \
|
||||
$$PDF_ROOT_DIR/SrcReader/PdfFont.cpp \
|
||||
$$PDF_ROOT_DIR/Resources/BaseFonts.cpp \
|
||||
$$PDF_ROOT_DIR/Resources/CMapMemory/cmap_memory.cpp
|
||||
|
||||
@ -664,6 +665,7 @@ HEADERS +=\
|
||||
$$PDF_ROOT_DIR/SrcReader/MemoryUtils.h \
|
||||
$$PDF_ROOT_DIR/SrcReader/GfxClip.h \
|
||||
$$PDF_ROOT_DIR/SrcReader/FontsWasm.h \
|
||||
$$PDF_ROOT_DIR/SrcReader/PdfFont.h \
|
||||
$$PDF_ROOT_DIR/SrcReader/PdfAnnot.h
|
||||
|
||||
DEFINES += CRYPTOPP_DISABLE_ASM
|
||||
|
||||
@ -364,7 +364,22 @@ CFile.prototype["getFontByID"] = function(ID)
|
||||
|
||||
CFile.prototype["getGIDByUnicode"] = function(ID)
|
||||
{
|
||||
return this._getGIDByUnicode(ID);
|
||||
let ptr = this._getGIDByUnicode(ID);
|
||||
let reader = ptr.getReader();
|
||||
if (!reader)
|
||||
return {};
|
||||
|
||||
let res = {};
|
||||
let nFontLength = reader.readInt();
|
||||
for (let i = 0; i < nFontLength; i++)
|
||||
{
|
||||
let np1 = reader.readInt();
|
||||
let np2 = reader.readInt();
|
||||
res[np2] = np1;
|
||||
}
|
||||
|
||||
ptr.free();
|
||||
return res;
|
||||
};
|
||||
|
||||
CFile.prototype["setCMap"] = function(memoryBuffer)
|
||||
@ -414,7 +429,7 @@ function readAction(reader, rec, readDoubleFunc, readStringFunc)
|
||||
case 6:
|
||||
case 7:
|
||||
{
|
||||
let nFlag = reader.readByte();
|
||||
let nFlag = reader.readInt();
|
||||
if (nFlag & (1 << 0))
|
||||
rec["left"] = readDoubleFunc.call(reader);
|
||||
if (nFlag & (1 << 1))
|
||||
@ -1047,11 +1062,15 @@ function readAnnotType(reader, rec, readDoubleFunc, readDouble2Func, readStringF
|
||||
if (flags & (1 << 0))
|
||||
{
|
||||
rec["A"] = {};
|
||||
if (isRead)
|
||||
readStringFunc.call(reader);
|
||||
readAction(reader, rec["A"], readDoubleFunc, readStringFunc);
|
||||
}
|
||||
if (flags & (1 << 1))
|
||||
{
|
||||
rec["PA"] = {};
|
||||
if (isRead)
|
||||
readStringFunc.call(reader);
|
||||
readAction(reader, rec["PA"], readDoubleFunc, readStringFunc);
|
||||
}
|
||||
// Selection mode - H
|
||||
|
||||
@ -106,7 +106,7 @@ CFile.prototype._openFile = function(buffer, password)
|
||||
}
|
||||
|
||||
let passwordPtr = 0;
|
||||
if (password)
|
||||
if (password !== undefined)
|
||||
{
|
||||
let passwordBuf = password.toUtf8();
|
||||
passwordPtr = Module["_malloc"](passwordBuf.length);
|
||||
@ -227,7 +227,7 @@ CFile.prototype._UndoRedact = function()
|
||||
CFile.prototype._CheckOwnerPassword = function(password)
|
||||
{
|
||||
let passwordPtr = 0;
|
||||
if (password)
|
||||
if (password !== undefined)
|
||||
{
|
||||
let passwordBuf = password.toUtf8();
|
||||
passwordPtr = Module["_malloc"](passwordBuf.length);
|
||||
@ -296,22 +296,7 @@ CFile.prototype._getGIDByUnicode = function(ID)
|
||||
Module["HEAP8"].set(idBuffer, idPointer);
|
||||
g_module_pointer.ptr = Module["_GetGIDByUnicode"](this.nativeFile, idPointer);
|
||||
Module["_free"](idPointer);
|
||||
|
||||
let reader = g_module_pointer.getReader();
|
||||
if (!reader)
|
||||
return null;
|
||||
|
||||
let res = {};
|
||||
let nFontLength = reader.readInt();
|
||||
for (let i = 0; i < nFontLength; i++)
|
||||
{
|
||||
let np1 = reader.readInt();
|
||||
let np2 = reader.readInt();
|
||||
res[np2] = np1;
|
||||
}
|
||||
|
||||
g_module_pointer.free();
|
||||
return res;
|
||||
return g_module_pointer;
|
||||
}
|
||||
|
||||
CFile.prototype._getInteractiveFormsFonts = function(type)
|
||||
|
||||
@ -80,7 +80,7 @@ WASM_EXPORT CDrawingFile* Open(BYTE* data, LONG size, const char* password)
|
||||
std::wstring sPassword = L"";
|
||||
if (NULL != password)
|
||||
sPassword = NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)password, strlen(password));
|
||||
pFile->OpenFile(data, size, sPassword);
|
||||
pFile->OpenFile(data, size, password ? sPassword.c_str() : NULL);
|
||||
return pFile;
|
||||
}
|
||||
WASM_EXPORT int GetType(CDrawingFile* pFile)
|
||||
@ -204,7 +204,7 @@ WASM_EXPORT int CheckOwnerPassword(CDrawingFile* pFile, const char* password)
|
||||
std::wstring sPassword = L"";
|
||||
if (NULL != password)
|
||||
sPassword = NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)password, strlen(password));
|
||||
return pFile->CheckOwnerPassword(sPassword) ? 1 : 0;
|
||||
return pFile->CheckOwnerPassword(password ? sPassword.c_str() : NULL) ? 1 : 0;
|
||||
}
|
||||
WASM_EXPORT int CheckPerm(CDrawingFile* pFile, int nPermFlag)
|
||||
{
|
||||
|
||||
@ -958,7 +958,7 @@ void ReadInteractiveFormsFonts(CDrawingFile* pGrFile, int nType)
|
||||
if (pFont)
|
||||
free(pFont);
|
||||
|
||||
if (false)
|
||||
if (true)
|
||||
continue;
|
||||
|
||||
pFont = GetGIDByUnicode(pGrFile, (char*)sFontName.c_str());
|
||||
@ -1072,7 +1072,7 @@ int main(int argc, char* argv[])
|
||||
if (!NSFile::CFileBinary::ReadAllBytes(sFilePath, &pFileData, nFileDataLen))
|
||||
return 1;
|
||||
|
||||
CDrawingFile* pGrFile = Open(pFileData, (LONG)nFileDataLen, "");
|
||||
CDrawingFile* pGrFile = Open(pFileData, (LONG)nFileDataLen, NULL);
|
||||
int nError = GetErrorCode(pGrFile);
|
||||
|
||||
if (nError != 0)
|
||||
@ -1080,7 +1080,7 @@ int main(int argc, char* argv[])
|
||||
Close(pGrFile);
|
||||
if (nError == 4)
|
||||
{
|
||||
std::string sPassword = "123456";
|
||||
std::string sPassword = "";
|
||||
pGrFile = Open(pFileData, nFileDataLen, sPassword.c_str());
|
||||
}
|
||||
else
|
||||
@ -1175,7 +1175,7 @@ int main(int argc, char* argv[])
|
||||
// OWNER PASSWORD
|
||||
if (false)
|
||||
{
|
||||
std::string sPassword = "gfhjkmgfhjkm";
|
||||
std::string sPassword = "";
|
||||
std::cout << "CheckPerm 4 Edit " << CheckPerm(pGrFile, 4) << std::endl;
|
||||
std::cout << "CheckPerm 4 Print " << CheckPerm(pGrFile, 3) << std::endl;
|
||||
|
||||
@ -1194,7 +1194,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
// RASTER
|
||||
if (true)
|
||||
if (false)
|
||||
{
|
||||
int i = nTestPage;
|
||||
//for (int i = 0; i < nPagesCount; ++i)
|
||||
@ -2252,7 +2252,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
// SCAN PAGE Fonts
|
||||
if (true)
|
||||
if (false)
|
||||
{
|
||||
SetScanPageFonts(pGrFile, nTestPage);
|
||||
|
||||
|
||||
@ -63,9 +63,9 @@ public:
|
||||
|
||||
// Open
|
||||
virtual bool LoadFromFile(const std::wstring& file, const std::wstring& options = L"",
|
||||
const std::wstring& owner_password = L"", const std::wstring& user_password = L"") = 0;
|
||||
const wchar_t* owner_password = NULL, const wchar_t* user_password = NULL) = 0;
|
||||
virtual bool LoadFromMemory(unsigned char* data, unsigned long length, const std::wstring& options = L"",
|
||||
const std::wstring& owner_password = L"", const std::wstring& user_password = L"") = 0;
|
||||
const wchar_t* owner_password = NULL, const wchar_t* user_password = NULL) = 0;
|
||||
|
||||
// Close
|
||||
virtual void Close() = 0;
|
||||
|
||||
@ -349,7 +349,7 @@ bool CImageFileFormatChecker::isSvgFile(BYTE* pBuffer,DWORD dwBytes)
|
||||
{
|
||||
if (eFileType)return false;
|
||||
|
||||
if ( (6 <= dwBytes) &&(0x3C == pBuffer[0] && 0x3F == pBuffer[1] && 0x78 == pBuffer[2] && 0x6D == pBuffer[3]
|
||||
if ( (6 <= dwBytes) && (0x3C == pBuffer[0] && 0x3F == pBuffer[1] && 0x78 == pBuffer[2] && 0x6D == pBuffer[3]
|
||||
&& 0x6C == pBuffer[4] && 0x20 == pBuffer[5]))
|
||||
{
|
||||
std::string sXml_part = std::string((char*)pBuffer, dwBytes);
|
||||
@ -358,6 +358,11 @@ bool CImageFileFormatChecker::isSvgFile(BYTE* pBuffer,DWORD dwBytes)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if ( (6 <= dwBytes) && (0x3C == pBuffer[0] && 's' == pBuffer[1] && 'v' == pBuffer[2] && 'g' == pBuffer[3]
|
||||
&& 0x20 == pBuffer[4]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -74,7 +74,7 @@ namespace MetaFile
|
||||
virtual void EndClipPath(unsigned int unMode) = 0;
|
||||
|
||||
virtual void UpdateDC() = 0;
|
||||
virtual void SetTransform(double& dM11, double& dM12, double& dM21, double& dM22, double& dX, double& dY) = 0;
|
||||
virtual void SetTransform(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY) = 0;
|
||||
virtual void GetTransform(double* pdM11, double* pdM12, double* pdM21, double* pdM22, double* pdX, double* pdY) = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -914,7 +914,7 @@ namespace MetaFile
|
||||
|
||||
m_bStartedPath = false;
|
||||
}
|
||||
void SetTransform(double& dM11, double& dM12, double& dM21, double& dM22, double& dX, double& dY)
|
||||
void SetTransform(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY)
|
||||
{
|
||||
double dKoefX = m_dScaleX;
|
||||
double dKoefY = m_dScaleY;
|
||||
@ -1270,19 +1270,6 @@ namespace MetaFile
|
||||
|
||||
if ((NULL != pDataDash && 0 != unSizeDash) || PS_SOLID != ulPenStyle)
|
||||
{
|
||||
// Дублированный код из Graphics
|
||||
// Без этого используется оригинальный код в Graphics, который отрисовывает уже неверно
|
||||
double dDashWidth{dWidth};
|
||||
|
||||
if (!Equals(dWidthMinSize, dWidth))
|
||||
{
|
||||
double dDet = oMatrix.Determinant();
|
||||
|
||||
if (fabs(dDet) < 0.0001)
|
||||
dDashWidth *= dSqrtDet;
|
||||
}
|
||||
// -----------------------------
|
||||
|
||||
if (NULL != pDataDash && 0 != unSizeDash)
|
||||
{
|
||||
m_pRenderer->put_PenDashOffset(pPen->GetDashOffset());
|
||||
@ -1290,7 +1277,7 @@ namespace MetaFile
|
||||
std::vector<double> arDashes(unSizeDash);
|
||||
|
||||
for (unsigned int unIndex = 0; unIndex < unSizeDash; ++unIndex)
|
||||
arDashes[unIndex] = pDataDash[unIndex] * dDashWidth;
|
||||
arDashes[unIndex] = pDataDash[unIndex] * dWidth;
|
||||
|
||||
m_pRenderer->PenDashPattern(arDashes.data(), unSizeDash);
|
||||
|
||||
@ -1304,35 +1291,35 @@ namespace MetaFile
|
||||
{
|
||||
case PS_DASH:
|
||||
{
|
||||
arDashPattern.push_back(9 * dDashWidth);
|
||||
arDashPattern.push_back(3 * dDashWidth);
|
||||
arDashPattern.push_back(9 * dWidth);
|
||||
arDashPattern.push_back(3 * dWidth);
|
||||
|
||||
break;
|
||||
}
|
||||
case PS_DOT:
|
||||
{
|
||||
arDashPattern.push_back(3 * dDashWidth);
|
||||
arDashPattern.push_back(3 * dDashWidth);
|
||||
arDashPattern.push_back(3 * dWidth);
|
||||
arDashPattern.push_back(3 * dWidth);
|
||||
|
||||
break;
|
||||
}
|
||||
case PS_DASHDOT:
|
||||
{
|
||||
arDashPattern.push_back(9 * dDashWidth);
|
||||
arDashPattern.push_back(6 * dDashWidth);
|
||||
arDashPattern.push_back(3 * dDashWidth);
|
||||
arDashPattern.push_back(6 * dDashWidth);
|
||||
arDashPattern.push_back(9 * dWidth);
|
||||
arDashPattern.push_back(6 * dWidth);
|
||||
arDashPattern.push_back(3 * dWidth);
|
||||
arDashPattern.push_back(6 * dWidth);
|
||||
|
||||
break;
|
||||
}
|
||||
case PS_DASHDOTDOT:
|
||||
{
|
||||
arDashPattern.push_back(9 * dDashWidth);
|
||||
arDashPattern.push_back(6 * dDashWidth);
|
||||
arDashPattern.push_back(3 * dDashWidth);
|
||||
arDashPattern.push_back(6 * dDashWidth);
|
||||
arDashPattern.push_back(3 * dDashWidth);
|
||||
arDashPattern.push_back(6 * dDashWidth);
|
||||
arDashPattern.push_back(9 * dWidth);
|
||||
arDashPattern.push_back(6 * dWidth);
|
||||
arDashPattern.push_back(3 * dWidth);
|
||||
arDashPattern.push_back(6 * dWidth);
|
||||
arDashPattern.push_back(3 * dWidth);
|
||||
arDashPattern.push_back(6 * dWidth);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -239,7 +239,7 @@ namespace MetaFile
|
||||
void EndClipPath(unsigned int unMode) override {};
|
||||
|
||||
void UpdateDC() override {};
|
||||
void SetTransform(double& dM11, double& dM12, double& dM21, double& dM22, double& dX, double& dY) override {};
|
||||
void SetTransform(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY) override {};
|
||||
void GetTransform(double* pdM11, double* pdM12, double* pdM21, double* pdM22, double* pdX, double* pdY) override {};
|
||||
};
|
||||
}
|
||||
|
||||
@ -182,7 +182,7 @@ namespace MetaFile
|
||||
pInterpretator->UpdateDC();
|
||||
}
|
||||
|
||||
void CEmfInterpretatorArray::SetTransform(double &dM11, double &dM12, double &dM21, double &dM22, double &dX, double &dY)
|
||||
void CEmfInterpretatorArray::SetTransform(const double &dM11, const double &dM12, const double &dM21, const double &dM22, const double &dX, const double &dY)
|
||||
{
|
||||
for (CEmfInterpretatorBase* pInterpretator : m_arInterpretators)
|
||||
pInterpretator->SetTransform(dM11, dM12, dM21, dM22, dX, dY);
|
||||
|
||||
@ -57,7 +57,7 @@ namespace MetaFile
|
||||
void EndClipPath(unsigned int unMode) override;
|
||||
|
||||
void UpdateDC() override;
|
||||
void SetTransform(double& dM11, double& dM12, double& dM21, double& dM22, double& dX, double& dY) override;
|
||||
void SetTransform(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY) override;
|
||||
void GetTransform(double* pdM11, double* pdM12, double* pdM21, double* pdM22, double* pdX, double* pdY) override;
|
||||
|
||||
void HANDLE_EMR_HEADER(const TEmfHeader& oTEmfHeader) override;
|
||||
|
||||
@ -18,8 +18,8 @@ namespace MetaFile
|
||||
|
||||
void CEmfInterpretatorRender::ChangeConditional()
|
||||
{
|
||||
if (NULL != m_pMetaFileRenderer)
|
||||
m_pMetaFileRenderer->ChangeConditional();
|
||||
if (NULL != m_pMetaFileRenderer)
|
||||
m_pMetaFileRenderer->ChangeConditional();
|
||||
}
|
||||
|
||||
void CEmfInterpretatorRender::Begin()
|
||||
@ -143,7 +143,7 @@ namespace MetaFile
|
||||
m_pMetaFileRenderer->UpdateDC();
|
||||
}
|
||||
|
||||
void CEmfInterpretatorRender::SetTransform(double &dM11, double &dM12, double &dM21, double &dM22, double &dX, double &dY)
|
||||
void CEmfInterpretatorRender::SetTransform(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY)
|
||||
{
|
||||
if (NULL != m_pMetaFileRenderer)
|
||||
m_pMetaFileRenderer->SetTransform(dM11, dM12, dM21, dM22, dX, dY);
|
||||
|
||||
@ -43,7 +43,7 @@ namespace MetaFile
|
||||
void EndClipPath(unsigned int unMode) override;
|
||||
|
||||
void UpdateDC() override;
|
||||
void SetTransform(double& dM11, double& dM12, double& dM21, double& dM22, double& dX, double& dY) override;
|
||||
void SetTransform(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY) override;
|
||||
void GetTransform(double* pdM11, double* pdM12, double* pdM21, double* pdM22, double* pdX, double* pdY) override;
|
||||
|
||||
CMetaFileRenderer* GetRenderer() const;
|
||||
|
||||
@ -223,7 +223,7 @@ namespace MetaFile
|
||||
void EndPath() override {};
|
||||
|
||||
void UpdateDC() override {};
|
||||
void SetTransform(double& dM11, double& dM12, double& dM21, double& dM22, double& dX, double& dY) override {};
|
||||
void SetTransform(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY) override {};
|
||||
void GetTransform(double* pdM11, double* pdM12, double* pdM21, double* pdM22, double* pdX, double* pdY) override {};
|
||||
|
||||
void SwapClips(CSvgClip& oFirstClip, CSvgClip& oSecondClip);
|
||||
|
||||
@ -237,7 +237,7 @@ namespace MetaFile
|
||||
void EndClipPath(unsigned int unMode) override {};
|
||||
|
||||
void UpdateDC() override {};
|
||||
void SetTransform(double& dM11, double& dM12, double& dM21, double& dM22, double& dX, double& dY) override {};
|
||||
void SetTransform(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY) override {};
|
||||
void GetTransform(double* pdM11, double* pdM12, double* pdM21, double* pdM22, double* pdX, double* pdY) override {};
|
||||
};
|
||||
}
|
||||
|
||||
@ -1264,7 +1264,11 @@ namespace MetaFile
|
||||
|
||||
if (NULL != m_pPath)
|
||||
{
|
||||
m_pDC->GetClip()->SetPath(*m_pPath, unRegionMode, m_pDC->GetFinalTransform(GM_ADVANCED));
|
||||
TEmfXForm oTransform{m_pDC->GetFinalTransform(GM_ADVANCED)};
|
||||
oTransform.Dx -= GetDCBounds().Left;
|
||||
oTransform.Dy -= GetDCBounds().Top;
|
||||
|
||||
m_pDC->GetClip()->SetPath(*m_pPath, unRegionMode, oTransform);
|
||||
RELEASEOBJECT(m_pPath);
|
||||
UpdateOutputDC();
|
||||
}
|
||||
|
||||
@ -3284,6 +3284,10 @@ namespace MetaFile
|
||||
void CEmfPlusParser::Read_EMFPLUS_SETCLIPRECT(unsigned short unShFlags)
|
||||
{
|
||||
short shCM = ExpressValue(unShFlags, 8, 11);
|
||||
|
||||
if (0 == shCM)
|
||||
shCM = RGN_COPY;
|
||||
|
||||
TEmfPlusRectF oRect;
|
||||
|
||||
m_oStream >> oRect;
|
||||
|
||||
@ -627,15 +627,13 @@ namespace MetaFile
|
||||
|
||||
void CInterpretatorSvgBase::PathClip(const CPath &oPath, int nClipMode, TXForm *pTransform)
|
||||
{
|
||||
std::wstring wsPath = CreatePath(oPath, pTransform);
|
||||
const std::wstring wsPath = CreatePath(oPath, pTransform);
|
||||
|
||||
if (wsPath.empty())
|
||||
return;
|
||||
|
||||
const std::wstring wsClipId = L"PATHCLIP_" + ConvertToWString(++m_unNumberDefs, 0);
|
||||
const std::wstring wsValue = L"<path d=\"" + wsPath + L"\"/>";
|
||||
|
||||
m_oClip.AddClipValue(wsClipId, wsValue, nClipMode);
|
||||
m_oClip.AddClipValue(L"PATHCLIP_" + ConvertToWString(++m_unNumberDefs, 0),
|
||||
L"<path d=\"" + wsPath + L"\"/>", nClipMode);
|
||||
}
|
||||
|
||||
void CInterpretatorSvgBase::AddStroke(NodeAttributes &arAttributes) const
|
||||
|
||||
@ -131,7 +131,7 @@ namespace MetaFile
|
||||
m_pMetaFileRenderer->UpdateDC();
|
||||
}
|
||||
|
||||
void CWmfInterpretatorRender::SetTransform(double &dM11, double &dM12, double &dM21, double &dM22, double &dX, double &dY)
|
||||
void CWmfInterpretatorRender::SetTransform(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY)
|
||||
{
|
||||
if (NULL != m_pMetaFileRenderer)
|
||||
m_pMetaFileRenderer->SetTransform(dM11, dM12, dM21, dM22, dX, dY);
|
||||
|
||||
@ -40,7 +40,7 @@ namespace MetaFile
|
||||
void EndClipPath(unsigned int unMode) override;
|
||||
|
||||
void UpdateDC() override;
|
||||
void SetTransform(double& dM11, double& dM12, double& dM21, double& dM22, double& dX, double& dY) override;
|
||||
void SetTransform(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY) override;
|
||||
void GetTransform(double* pdM11, double* pdM12, double* pdM21, double* pdM22, double* pdX, double* pdY) override;
|
||||
|
||||
CMetaFileRenderer* GetRenderer() const;
|
||||
|
||||
@ -130,7 +130,7 @@ namespace MetaFile
|
||||
void EndClipPath(unsigned int unMode) override {};
|
||||
|
||||
void UpdateDC() override {};
|
||||
void SetTransform(double& dM11, double& dM12, double& dM21, double& dM22, double& dX, double& dY) override {};
|
||||
void SetTransform(const double& dM11, const double& dM12, const double& dM21, const double& dM22, const double& dX, const double& dY) override {};
|
||||
void GetTransform(double* pdM11, double* pdM12, double* pdM21, double* pdM22, double* pdX, double* pdY) override {};
|
||||
};
|
||||
|
||||
|
||||
@ -358,7 +358,7 @@ namespace SVG
|
||||
|
||||
bool CRenderedObject::ApplyStroke(IRenderer *pRenderer, const TStroke *pStroke, bool bUseDefault, const CRenderedObject* pContextObject) const
|
||||
{
|
||||
if (NULL == pRenderer || NULL == pStroke || NSCSS::NSProperties::EColorType::ColorNone == pStroke->m_oColor.GetType() || (!bUseDefault && ((pStroke->m_oWidth.Empty() || pStroke->m_oWidth.Zero()) && pStroke->m_oColor.Empty())))
|
||||
if (NULL == pRenderer || NULL == pStroke || pStroke->m_oColor.None() || (!bUseDefault && ((pStroke->m_oWidth.Empty() || pStroke->m_oWidth.Zero()) && pStroke->m_oColor.Empty())))
|
||||
{
|
||||
pRenderer->put_PenSize(0);
|
||||
return false;
|
||||
@ -401,7 +401,7 @@ namespace SVG
|
||||
|
||||
bool CRenderedObject::ApplyFill(IRenderer *pRenderer, const NSCSS::NSProperties::CColor *pFill, const CSvgFile *pFile, bool bUseDefault, const CRenderedObject* pContextObject) const
|
||||
{
|
||||
if (NULL == pRenderer || NULL == pFill || NSCSS::NSProperties::EColorType::ColorNone == pFill->GetType() || (!bUseDefault && pFill->Empty()))
|
||||
if (NULL == pRenderer || NULL == pFill || pFill->None() || (!bUseDefault && pFill->Empty()))
|
||||
{
|
||||
pRenderer->put_BrushType(c_BrushTypeNoFill);
|
||||
return false;
|
||||
|
||||
@ -40,13 +40,14 @@
|
||||
CPictFile::CPictFile()
|
||||
{
|
||||
m_pRenderer = NSGraphics::Create();
|
||||
m_pFontManager = NSFonts::NSFontManager::Create();
|
||||
m_pRenderer->SetFontManager(m_pFontManager);
|
||||
}
|
||||
|
||||
CPictFile::~CPictFile()
|
||||
{
|
||||
RELEASEINTERFACE(m_pFontManager);
|
||||
if (m_pAppFonts)
|
||||
RELEASEINTERFACE(m_pAppFonts);
|
||||
if (m_pFontManager)
|
||||
RELEASEINTERFACE(m_pFontManager);
|
||||
RELEASEINTERFACE(m_pRenderer);
|
||||
}
|
||||
|
||||
@ -984,6 +985,8 @@ bool CPictFile::DecodeData()
|
||||
m_oImgData.m_pPixelData = (BYTE*)malloc(4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth);
|
||||
if (m_oFrame.get_Data())
|
||||
memcpy(m_oImgData.m_pPixelData, m_oFrame.get_Data(), 4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth);
|
||||
else
|
||||
memset(m_oImgData.m_pPixelData, 255, m_oImgData.m_nWidth * m_oImgData.m_nHeight * 4);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1671,6 +1674,7 @@ void CPictFile::DrawArc()
|
||||
void CPictFile::ReadAndDrawText(int x, int y)
|
||||
{
|
||||
InitializeRenderer();
|
||||
InitializeFonts();
|
||||
|
||||
char text[256];
|
||||
char byte_len = fgetc(m_pFile);
|
||||
@ -1695,12 +1699,32 @@ void CPictFile::ReadAndDrawText(int x, int y)
|
||||
m_pRenderer->EndCommand(c_nTextGraphicType);
|
||||
}
|
||||
|
||||
void CPictFile::InitializeFonts()
|
||||
{
|
||||
if (m_pAppFonts)
|
||||
return;
|
||||
|
||||
m_pAppFonts = NSFonts::NSApplication::Create();
|
||||
m_pAppFonts->Initialize();
|
||||
m_pFontManager = m_pAppFonts->GenerateFontManager();
|
||||
NSFonts::IFontsCache* fonts_cache = NSFonts::NSFontCache::Create();
|
||||
fonts_cache->SetStreams(m_pAppFonts->GetStreams());
|
||||
m_pFontManager->SetOwnerCache(fonts_cache);
|
||||
m_pRenderer->SetFontManager(m_pFontManager);
|
||||
}
|
||||
|
||||
void CPictFile::InitializeRenderer()
|
||||
{
|
||||
if (m_pFrameData)
|
||||
return;
|
||||
|
||||
m_pFrameData = new BYTE[4 * m_oImgData.m_nWidth * m_oImgData.m_nHeight];
|
||||
unsigned int back = 0xffffff;
|
||||
unsigned int *pData32 = (unsigned int*)m_pFrameData;
|
||||
unsigned int *pData32End = pData32 + m_oImgData.m_nWidth * m_oImgData.m_nHeight;
|
||||
while (pData32 < pData32End)
|
||||
*pData32++ = back;
|
||||
|
||||
m_oFrame.put_Data(m_pFrameData);
|
||||
m_oFrame.put_Width(m_oImgData.m_nWidth);
|
||||
m_oFrame.put_Height(m_oImgData.m_nHeight);
|
||||
|
||||
@ -247,6 +247,7 @@ private:
|
||||
void DrawArc();
|
||||
void ReadAndDrawText(int x, int y);
|
||||
|
||||
void InitializeFonts();
|
||||
void InitializeRenderer();
|
||||
|
||||
private:
|
||||
@ -257,8 +258,8 @@ private:
|
||||
CBgraFrame m_oFrame{};
|
||||
BYTE* m_pFrameData{nullptr};
|
||||
|
||||
size_t m_nPenHeight{0};
|
||||
size_t m_nPenWidth{0};
|
||||
size_t m_nPenHeight{1};
|
||||
size_t m_nPenWidth{1};
|
||||
|
||||
int m_nFontStyle{0};
|
||||
int m_nFontSize{0};
|
||||
@ -275,6 +276,7 @@ private:
|
||||
std::vector<Aggplus::Point> m_arLastPolygon{};
|
||||
|
||||
NSGraphics::IGraphicsRenderer* m_pRenderer{nullptr};
|
||||
NSFonts::IApplicationFonts* m_pAppFonts{nullptr};
|
||||
NSFonts::IFontManager* m_pFontManager{nullptr};
|
||||
};
|
||||
|
||||
|
||||
@ -105,13 +105,13 @@ namespace NSHeif {
|
||||
|
||||
inline bool CHeifFile::Decode(heif_context* ctx, CBgraFrame* frame, bool isRGBA)
|
||||
{
|
||||
heif_image_handle* handle;
|
||||
heif_image_handle* handle = nullptr;
|
||||
defer(heif_image_handle_release(handle););
|
||||
|
||||
if (IsError(heif_context_get_primary_image_handle(ctx, &handle)))
|
||||
return false;
|
||||
|
||||
heif_image* img;
|
||||
heif_image* img = nullptr;
|
||||
defer(heif_image_release(img););
|
||||
|
||||
if (IsError(heif_decode_image(handle, &img, heif_colorspace_RGB, heif_chroma_444, nullptr)))
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@ -604,6 +605,12 @@ public:
|
||||
evp = EVP_sha512();
|
||||
else if (m_alg == OOXML_HASH_ALG_ECDSA_384)
|
||||
evp = EVP_sha384();
|
||||
else if (m_alg == OOXML_HASH_ALG_SHA256)
|
||||
evp = EVP_sha256();
|
||||
else if (m_alg == OOXML_HASH_ALG_SHA384)
|
||||
evp = EVP_sha384();
|
||||
else if (m_alg == OOXML_HASH_ALG_SHA512)
|
||||
evp = EVP_sha512();
|
||||
|
||||
if (!PKCS7_sign_add_signer(pkcs7, m_cert, m_key, evp, 0))
|
||||
{
|
||||
|
||||
@ -42,7 +42,7 @@ CDjVuFile::~CDjVuFile()
|
||||
delete m_pImplementation;
|
||||
}
|
||||
bool CDjVuFile::LoadFromFile(const std::wstring& file, const std::wstring& options,
|
||||
const std::wstring& owner_password, const std::wstring& user_password)
|
||||
const wchar_t* owner_password, const wchar_t* user_password)
|
||||
{
|
||||
if (m_pImplementation)
|
||||
return m_pImplementation->LoadFromFile(file, options);
|
||||
@ -50,7 +50,7 @@ bool CDjVuFile::LoadFromFile(const std::wstring& file, const std::wstring& optio
|
||||
return false;
|
||||
}
|
||||
bool CDjVuFile::LoadFromMemory(BYTE* data, DWORD length, const std::wstring& options,
|
||||
const std::wstring& owner_password, const std::wstring& user_password)
|
||||
const wchar_t* owner_password, const wchar_t* user_password)
|
||||
{
|
||||
if (m_pImplementation)
|
||||
return m_pImplementation->LoadFromMemory(data, length, options);
|
||||
|
||||
@ -55,9 +55,9 @@ public:
|
||||
virtual ~CDjVuFile();
|
||||
|
||||
virtual bool LoadFromFile(const std::wstring& file, const std::wstring& options = L"",
|
||||
const std::wstring& owner_password = L"", const std::wstring& user_password = L"");
|
||||
const wchar_t* owner_password = NULL, const wchar_t* user_password = NULL);
|
||||
virtual bool LoadFromMemory(BYTE* data, DWORD length, const std::wstring& options = L"",
|
||||
const std::wstring& owner_password = L"", const std::wstring& user_password = L"");
|
||||
const wchar_t* owner_password = NULL, const wchar_t* user_password = NULL);
|
||||
|
||||
virtual void Close();
|
||||
virtual NSFonts::IApplicationFonts* GetFonts();
|
||||
|
||||
@ -93,6 +93,7 @@ int CDocxRenderer::Convert(IOfficeDrawingFile* pFile, const std::wstring& sDst,
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bWriteStyleRaw = false;
|
||||
m_pInternal->m_bIsSupportShapeCommands = false;
|
||||
m_pInternal->m_oDocument.m_bIsRecord = true;
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bFirstParagraphLineCorrection = true;
|
||||
|
||||
if (bIsOutCompress)
|
||||
m_pInternal->m_oDocument.m_strTempDirectory = NSDirectory::CreateDirectoryWithUniqueName(m_pInternal->m_sTempDirectory);
|
||||
@ -130,6 +131,7 @@ std::vector<std::wstring> CDocxRenderer::ScanPage(IOfficeDrawingFile* pFile, siz
|
||||
m_pInternal->m_oDocument.Init(false);
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bUseDefaultFont = true;
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bWriteStyleRaw = true;
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bFirstParagraphLineCorrection = true;
|
||||
m_pInternal->m_bIsSupportShapeCommands = false;
|
||||
m_pInternal->m_oDocument.m_bIsRecord = false;
|
||||
|
||||
@ -147,6 +149,7 @@ std::vector<std::wstring> CDocxRenderer::ScanPagePptx(IOfficeDrawingFile* pFile,
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bUseDefaultFont = true;
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bWriteStyleRaw = true;
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bCollectMetaInfo = true;
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bFirstParagraphLineCorrection = true;
|
||||
m_pInternal->m_bIsSupportShapeCommands = true;
|
||||
m_pInternal->m_oDocument.m_bIsRecord = false;
|
||||
|
||||
@ -165,7 +168,11 @@ NSWasm::CData CDocxRenderer::ScanPageBin(IOfficeDrawingFile* pFile, size_t nPage
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bUseDefaultFont = true;
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bWriteStyleRaw = true;
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bCollectMetaInfo = true;
|
||||
m_pInternal->m_oDocument.m_oCurrentPage.m_bFirstParagraphLineCorrection = true;
|
||||
m_pInternal->m_oDocument.m_bIsRecord = false;
|
||||
m_pInternal->m_bIsSupportShapeCommands = true;
|
||||
m_pInternal->m_oDocument.m_oFontStyleManager.Clear();
|
||||
m_pInternal->m_oDocument.m_oFontSelector.ClearCache();
|
||||
|
||||
DrawPage(pFile, nPage);
|
||||
|
||||
|
||||
@ -648,11 +648,15 @@ namespace NSDocxRenderer
|
||||
if ((nType > 0xFF) && (c_BrushTypeTexture == m_oCurrentPage.m_oBrush.Type))
|
||||
{
|
||||
double x = 0, y = 0, w = 0, h = 0;
|
||||
if (m_oCurrentPage.IsCurrVectorClockwise())
|
||||
h = -1; // to flip image later
|
||||
|
||||
if (m_oCurrentPage.m_oBrush.Image)
|
||||
pInfo = m_oImageManager.WriteImage(m_oCurrentPage.m_oBrush.Image, x, y, w, h);
|
||||
else
|
||||
pInfo = m_oImageManager.WriteImage(m_oCurrentPage.m_oBrush.TexturePath, x, y, w, h);
|
||||
pInfo = m_oImageManager.WriteImage(m_oCurrentPage.m_oBrush.TexturePath);
|
||||
}
|
||||
|
||||
m_oCurrentPage.DrawPath(nType, pInfo);
|
||||
return S_OK;
|
||||
}
|
||||
@ -712,7 +716,7 @@ namespace NSDocxRenderer
|
||||
}
|
||||
HRESULT CDocument::DrawImageFromFile(const std::wstring& sVal, double fX, double fY, double fWidth, double fHeight)
|
||||
{
|
||||
m_oCurrentPage.WriteImage(m_oImageManager.WriteImage(sVal, fX, fY, fWidth, fHeight), fX, fY, fWidth, fHeight);
|
||||
m_oCurrentPage.WriteImage(m_oImageManager.WriteImage(sVal), fX, fY, fWidth, fHeight);
|
||||
return S_OK;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
@ -70,6 +70,8 @@ namespace NSDocxRenderer
|
||||
m_oContBuilder.Clear();
|
||||
m_arCompleteObjectsXml.clear();
|
||||
m_arLuminosityShapes.clear();
|
||||
|
||||
m_bFontSubstitution = false;
|
||||
}
|
||||
|
||||
CPage::~CPage()
|
||||
@ -193,12 +195,14 @@ namespace NSDocxRenderer
|
||||
|
||||
if (!m_arShapes.empty())
|
||||
{
|
||||
auto& last_shape = m_arShapes.back();
|
||||
if (last_shape->IsEqual(top, bot, left, right) && rotation == last_shape->m_dRotation && lType != m_lLastType && m_lLastType != 0)
|
||||
auto& last_shape = m_arShapes.back();
|
||||
bool is_type_diff = lType == c_nStroke && (m_lLastType == c_nWindingFillMode || m_lLastType == c_nEvenOddFillMode);
|
||||
is_type_diff = is_type_diff || (m_lLastType == c_nStroke && (lType == c_nWindingFillMode || m_lLastType == c_nEvenOddFillMode));
|
||||
if (last_shape->IsEqual(top, bot, left, right) && rotation == last_shape->m_dRotation && is_type_diff && m_lLastType != 0)
|
||||
{
|
||||
set_fill_mode(last_shape);
|
||||
// Reset stroke/fill logic
|
||||
m_lLastType = 0;
|
||||
if (pInfo) DrawImage(last_shape, pInfo, image_vector);
|
||||
m_lLastType = 0; // reset stroke/fill logic
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -275,6 +279,10 @@ namespace NSDocxRenderer
|
||||
m_arShapes.push_back(shape);
|
||||
}
|
||||
}
|
||||
bool CPage::IsCurrVectorClockwise() const
|
||||
{
|
||||
return m_oCurrVectorGraphics.IsClockwise();
|
||||
}
|
||||
|
||||
void CPage::AddText(
|
||||
const PUINT pUnicodes,
|
||||
@ -331,14 +339,11 @@ namespace NSDocxRenderer
|
||||
m_oManagers.pFontManager->MeasureStringGids(pUnicodes, nCount, dTextX, dTextY, _x, _y, _w, _h, CFontManager::mtPosition);
|
||||
}
|
||||
_h = m_oManagers.pFontManager->GetFontHeight();
|
||||
|
||||
double baseline = dTextY + fBaseLineOffset;
|
||||
|
||||
double top = baseline - _h;
|
||||
double left = dTextX;
|
||||
double right = dTextR;
|
||||
|
||||
if (left == right) // XPS
|
||||
right = left + _w;
|
||||
double right = left + _w;
|
||||
|
||||
// use forced fold option
|
||||
const auto& oParams = m_oManagers.pFontManager->GetFontSelectParams();
|
||||
@ -511,7 +516,7 @@ namespace NSDocxRenderer
|
||||
cont->CalculateSpace() * c_dSPACE_WIDTH_COEF;
|
||||
|
||||
if (curr_line && fabs(curr_line->m_dBot - cont->m_dBot) <= c_dTHE_SAME_STRING_Y_PRECISION_MM &&
|
||||
fabs(curr_line->m_dRight - cont->m_dLeft) <= 3 * space_width)
|
||||
fabs(curr_line->m_dRight - cont->m_dLeft) <= 4 * space_width)
|
||||
{
|
||||
curr_line->AddCont(cont);
|
||||
continue;
|
||||
@ -575,7 +580,7 @@ namespace NSDocxRenderer
|
||||
shape_ref_ptr_t val = m_arShapes[i];
|
||||
shape_ref_ptr_t next_val = m_arShapes[i + 1];
|
||||
|
||||
if (!val.get() || ! next_val.get())
|
||||
if (!val.get() || !next_val.get() || next_val.get()->m_nOrder - val.get()->m_nOrder != 1)
|
||||
continue;
|
||||
|
||||
next_val.get()->TryMergeShape(val.get());
|
||||
@ -760,6 +765,19 @@ namespace NSDocxRenderer
|
||||
if (line && line->m_arConts.empty())
|
||||
line = nullptr;
|
||||
|
||||
for (auto& line : m_arTextLines)
|
||||
if (line)
|
||||
{
|
||||
bool is_remove = true;
|
||||
for(auto& cont : line->m_arConts)
|
||||
if (cont && !cont->IsOnlySpaces())
|
||||
is_remove = false;
|
||||
|
||||
if (is_remove)
|
||||
line = nullptr;
|
||||
}
|
||||
|
||||
|
||||
auto right = MoveNullptr(m_arTextLines.begin(), m_arTextLines.end());
|
||||
m_arTextLines.erase(right, m_arTextLines.end());
|
||||
|
||||
@ -891,7 +909,9 @@ namespace NSDocxRenderer
|
||||
pNextLine->m_pLine = pCurrLine;
|
||||
}
|
||||
}
|
||||
else if (!is_font_effect && pCurrCont->IsDuplicate(pNextCont.get(), eVType, eHType))
|
||||
else if (!is_font_effect && pCurrCont->IsDuplicate(pNextCont.get(), eVType, eHType)
|
||||
&& (fabs(pCurrCont->m_dLeft - pNextCont->m_dLeft) < c_dTHE_STRING_X_PRECISION_MM ||
|
||||
fabs(pCurrCont->m_dRight - pNextCont->m_dRight) < c_dTHE_STRING_X_PRECISION_MM))
|
||||
{
|
||||
pNextCont = nullptr;
|
||||
pCurrCont->m_iNumDuplicates++;
|
||||
@ -1345,6 +1365,21 @@ namespace NSDocxRenderer
|
||||
|
||||
return IsHorizontalLineTrough(dummy_cont);
|
||||
}
|
||||
bool CPage::IsTextLineBetween(text_line_ptr_t pFirst, text_line_ptr_t pSecond) const noexcept
|
||||
{
|
||||
double left = std::min(pFirst->m_dLeft, pSecond->m_dLeft);
|
||||
double right = std::max(pFirst->m_dRight, pSecond->m_dRight);
|
||||
double top = std::min(pFirst->m_dBotWithMaxDescent, pSecond->m_dBotWithMaxDescent);
|
||||
double bot = std::max(pFirst->m_dTopWithMaxAscent, pSecond->m_dTopWithMaxAscent);
|
||||
|
||||
auto dummy_cont = std::make_shared<CContText>();
|
||||
dummy_cont->m_dLeft = left - c_dGRAPHICS_ERROR_MM;
|
||||
dummy_cont->m_dRight = right + c_dGRAPHICS_ERROR_MM;
|
||||
dummy_cont->m_dTop = top - c_dGRAPHICS_ERROR_MM;
|
||||
dummy_cont->m_dBot = bot + c_dGRAPHICS_ERROR_MM;
|
||||
|
||||
return IsTextLineTrough(dummy_cont);
|
||||
}
|
||||
|
||||
bool CPage::IsVerticalLineTrough(base_item_ptr_t pFirst) const noexcept
|
||||
{
|
||||
@ -1372,6 +1407,16 @@ namespace NSDocxRenderer
|
||||
|
||||
return false;
|
||||
}
|
||||
bool CPage::IsTextLineTrough(base_item_ptr_t pFirst) const noexcept
|
||||
{
|
||||
for (const auto& text_line : m_arShapes)
|
||||
if (text_line && text_line->m_eType == CShape::eShapeType::stTextBox && text_line->m_dBot > pFirst->m_dTop &&
|
||||
text_line->m_dBot < pFirst->m_dBot && !(
|
||||
text_line->m_dRight < pFirst->m_dLeft || text_line->m_dLeft > pFirst->m_dRight))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPage::SplitLines()
|
||||
{
|
||||
@ -1441,7 +1486,7 @@ namespace NSDocxRenderer
|
||||
|
||||
for (const auto& line : m_arTextLines)
|
||||
{
|
||||
if (fabs(line->m_dBotWithMaxDescent - curr_bot) < 4 * c_dTHE_SAME_STRING_Y_PRECISION_MM)
|
||||
if (fabs(line->m_dBot - curr_bot) < 4 * c_dTHE_SAME_STRING_Y_PRECISION_MM)
|
||||
{
|
||||
bot_aligned_text_lines.back().push_back(line);
|
||||
}
|
||||
@ -1449,7 +1494,7 @@ namespace NSDocxRenderer
|
||||
{
|
||||
bot_aligned_text_lines.push_back({});
|
||||
bot_aligned_text_lines.back().push_back(line);
|
||||
curr_bot = line->m_dBotWithMaxDescent;
|
||||
curr_bot = line->m_dBot;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1604,9 +1649,9 @@ namespace NSDocxRenderer
|
||||
// lamda to setup and add paragpraph
|
||||
auto add_paragraph = [this, &max_right, &min_left, &ar_paragraphs] (paragraph_ptr_t& paragraph) {
|
||||
|
||||
double additional_bottom = paragraph->m_arTextLines.front()->m_dTopWithMaxAscent - paragraph->m_arTextLines.front()->m_dTop;
|
||||
paragraph->m_dBot = paragraph->m_arTextLines.back()->m_dBot + additional_bottom;
|
||||
paragraph->m_dTop = paragraph->m_arTextLines.front()->m_dTopWithMaxAscent;
|
||||
std::shared_ptr<CTextLine>& firstLine = paragraph->m_arTextLines.front();
|
||||
paragraph->m_dBot = paragraph->m_arTextLines.back()->m_dBotWithMaxDescent;
|
||||
paragraph->m_dTop = firstLine->m_dTopWithMaxAscent;
|
||||
paragraph->m_dRight = max_right;
|
||||
paragraph->m_dLeft = min_left;
|
||||
|
||||
@ -1616,13 +1661,36 @@ namespace NSDocxRenderer
|
||||
paragraph->m_dRightBorder = m_dWidth - paragraph->m_dRight;
|
||||
paragraph->m_dLeftBorder = min_left;
|
||||
|
||||
paragraph->m_dLineHeight = paragraph->m_dHeight / paragraph->m_arTextLines.size();
|
||||
if (paragraph->m_arTextLines.size() == 1)
|
||||
paragraph->m_dLineHeight = paragraph->m_dHeight;
|
||||
else
|
||||
paragraph->m_dLineHeight = (paragraph->m_dBot - firstLine->m_dBotWithMaxDescent) / (paragraph->m_arTextLines.size() - 1);
|
||||
|
||||
paragraph->m_bIsNeedFirstLineIndent = false;
|
||||
paragraph->m_dFirstLine = 0;
|
||||
paragraph->m_wsStyleId = m_oManagers.pParagraphStyleManager->GetDefaultParagraphStyleId(*paragraph);
|
||||
|
||||
paragraph->MergeLines();
|
||||
|
||||
// Correct first line position
|
||||
if (m_bFirstParagraphLineCorrection)
|
||||
{
|
||||
double firstLine_height = firstLine->m_dBotWithMaxDescent - firstLine->m_dTopWithMaxAscent;
|
||||
if (paragraph->m_dLineHeight > firstLine_height)
|
||||
{
|
||||
double offset = paragraph->m_dLineHeight - firstLine_height;
|
||||
paragraph->m_dTop -= offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
double ascent = firstLine->m_dBot - firstLine->m_dTopWithMaxAscent;
|
||||
double newAscent = ascent * paragraph->m_dLineHeight / firstLine_height;
|
||||
double offset = ascent - newAscent;
|
||||
paragraph->m_dTop += offset;
|
||||
}
|
||||
paragraph->m_dHeight = paragraph->m_dBot - paragraph->m_dTop;
|
||||
}
|
||||
|
||||
// setting TextAlignmentType
|
||||
if (paragraph->m_arTextLines.size() > 1)
|
||||
{
|
||||
@ -1868,6 +1936,9 @@ namespace NSDocxRenderer
|
||||
|
||||
double curr_max_right = text_lines[0]->m_dRight;
|
||||
double curr_min_left = text_lines[0]->m_dLeft;
|
||||
|
||||
double line_with_first_right_min = std::numeric_limits<double>::max();
|
||||
double line_with_first_left_max = std::numeric_limits<double>::lowest();
|
||||
for (size_t index = 0; index < ar_positions.size() - 1; ++index)
|
||||
{
|
||||
Position position = ar_positions[index];
|
||||
@ -1878,6 +1949,10 @@ namespace NSDocxRenderer
|
||||
{
|
||||
curr_max_right = line_bot->m_dRight;
|
||||
curr_min_left = line_bot->m_dLeft;
|
||||
|
||||
line_with_first_right_min = std::numeric_limits<double>::max();
|
||||
line_with_first_left_max = std::numeric_limits<double>::lowest();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1885,17 +1960,18 @@ namespace NSDocxRenderer
|
||||
double line_with_first_right = line_top->m_dRight + line_bot->m_dFirstWordWidth;
|
||||
double line_with_first_left = line_top->m_dLeft - line_bot->m_dFirstWordWidth;
|
||||
|
||||
line_with_first_right_min = std::min(line_with_first_right_min, line_with_first_right);
|
||||
line_with_first_left_max = std::max(line_with_first_left_max, line_with_first_left);
|
||||
|
||||
curr_max_right = std::max(curr_max_right, line_bot->m_dRight);
|
||||
curr_min_left = std::min(curr_min_left, line_bot->m_dLeft);
|
||||
|
||||
double diff = 0;
|
||||
|
||||
if (position.right && !position.left)
|
||||
diff = line_with_first_left - curr_min_left;
|
||||
else if (position.left || ar_indents[index])
|
||||
diff = curr_max_right - line_with_first_right;
|
||||
else if (position.center)
|
||||
continue;
|
||||
diff = line_with_first_left_max - curr_min_left;
|
||||
else if (position.left || ar_indents[index] || position.center)
|
||||
diff = curr_max_right - line_with_first_right_min;
|
||||
|
||||
if (diff <= 0)
|
||||
continue;
|
||||
@ -1904,6 +1980,8 @@ namespace NSDocxRenderer
|
||||
ar_delims[index] = true;
|
||||
curr_max_right = line_bot->m_dRight;
|
||||
curr_min_left = line_bot->m_dLeft;
|
||||
line_with_first_right_min = std::numeric_limits<double>::max();
|
||||
line_with_first_left_max = std::numeric_limits<double>::lowest();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1920,6 +1998,8 @@ namespace NSDocxRenderer
|
||||
{
|
||||
if (IsHorizontalLineBetween(text_lines[index], text_lines[index + 1]))
|
||||
ar_delims[index] = true;
|
||||
if (IsTextLineBetween(text_lines[index], text_lines[index + 1]))
|
||||
ar_delims[index] = true;
|
||||
}
|
||||
|
||||
// на основе ar_delims разбиваем на параграфы
|
||||
@ -2553,9 +2633,9 @@ namespace NSDocxRenderer
|
||||
pParagraph->m_arTextLines.push_back(pLine);
|
||||
pParagraph->m_dLeft = pLine->m_dLeft;
|
||||
pParagraph->m_dTop = pLine->m_dTopWithMaxAscent;
|
||||
pParagraph->m_dBot = pLine->m_dBot + (pLine->m_dTopWithMaxAscent - pLine->m_dTop);
|
||||
pParagraph->m_dWidth = pLine->m_dWidth * 1.05;
|
||||
pParagraph->m_dHeight = pLine->m_dHeight;
|
||||
pParagraph->m_dBot = pLine->m_dBotWithMaxDescent;
|
||||
pParagraph->m_dWidth = pLine->m_dWidth;
|
||||
pParagraph->m_dHeight = pLine->m_dBotWithMaxDescent - pLine->m_dTopWithMaxAscent;
|
||||
pParagraph->m_dRight = pLine->m_dRight;
|
||||
pParagraph->m_dLineHeight = pParagraph->m_dHeight;
|
||||
pParagraph->m_nOrder = pLine->m_nOrder;
|
||||
@ -2572,11 +2652,11 @@ namespace NSDocxRenderer
|
||||
pShape->m_eType = CShape::eShapeType::stTextBox;
|
||||
|
||||
pShape->m_dLeft = pParagraph->m_dLeft;
|
||||
pShape->m_dRight = pParagraph->m_dRight * 1.025;
|
||||
pShape->m_dTop = pParagraph->m_dTop;
|
||||
pShape->m_dBot = pParagraph->m_dBot;
|
||||
pShape->m_dWidth = pParagraph->m_dWidth;
|
||||
pShape->m_dWidth = pShape->m_dRight - pShape->m_dLeft;
|
||||
pShape->m_dHeight = pParagraph->m_dHeight;
|
||||
pShape->m_dRight = pParagraph->m_dRight;
|
||||
pShape->m_nOrder = pParagraph->m_nOrder;
|
||||
pShape->m_bIsBehindDoc = false;
|
||||
|
||||
@ -2588,11 +2668,12 @@ namespace NSDocxRenderer
|
||||
auto pShape = std::make_shared<CShape>();
|
||||
|
||||
pShape->m_dLeft = pParagraph->m_dLeft;
|
||||
pShape->m_dTop = pParagraph->m_dTop;
|
||||
pShape->m_dRight = pParagraph->m_dRight;
|
||||
if (pParagraph->m_arTextLines.size() == 1) pShape->m_dRight *= 1.025;
|
||||
pShape->m_dTop = pParagraph->m_dTop;
|
||||
pShape->m_dBot = pParagraph->m_dBot;
|
||||
pShape->m_dHeight = pParagraph->m_dHeight;
|
||||
pShape->m_dWidth = pParagraph->m_dWidth;
|
||||
pShape->m_dWidth = pShape->m_dRight - pShape->m_dLeft;
|
||||
pShape->m_nOrder = pParagraph->m_nOrder;
|
||||
|
||||
if (pParagraph->m_bIsNeedFirstLineIndent && pParagraph->m_dFirstLine < 0)
|
||||
|
||||
@ -50,6 +50,7 @@ namespace NSDocxRenderer
|
||||
bool m_bIsBuildTables {false};
|
||||
bool m_bIsLuminosityShapesFiled{false};
|
||||
bool m_bFontSubstitution {false};
|
||||
bool m_bFirstParagraphLineCorrection{false};
|
||||
|
||||
CPage(NSFonts::IApplicationFonts* pAppFonts, const CManagers& oManagers);
|
||||
~CPage();
|
||||
@ -68,6 +69,7 @@ namespace NSDocxRenderer
|
||||
void PathEnd();
|
||||
void PathClose();
|
||||
void DrawPath(LONG lType, const std::shared_ptr<CImageInfo> pInfo);
|
||||
bool IsCurrVectorClockwise() const;
|
||||
|
||||
void AddText(
|
||||
const PUINT pUnicodes,
|
||||
@ -194,9 +196,11 @@ namespace NSDocxRenderer
|
||||
|
||||
bool IsVerticalLineBetween(text_line_ptr_t pFirst, text_line_ptr_t pSecond) const noexcept;
|
||||
bool IsHorizontalLineBetween(text_line_ptr_t pFirst, text_line_ptr_t pSecond) const noexcept;
|
||||
bool IsTextLineBetween(text_line_ptr_t pFirst, text_line_ptr_t pSecond) const noexcept;
|
||||
|
||||
bool IsVerticalLineTrough(base_item_ptr_t pFirst) const noexcept;
|
||||
bool IsHorizontalLineTrough(base_item_ptr_t pFirst) const noexcept;
|
||||
bool IsTextLineTrough(base_item_ptr_t pFirst) const noexcept;
|
||||
|
||||
void ToXml(NSStringUtils::CStringBuilder& oWriter) const noexcept;
|
||||
void WriteSectionToFile(bool bLastPage, NSStringUtils::CStringBuilder& oWriter) const noexcept;
|
||||
|
||||
@ -208,34 +208,34 @@ namespace NSDocxRenderer
|
||||
return eVerticalCrossingType::vctCurrentInsideNext;
|
||||
|
||||
else if (this_top < other_top && this_bot > other_bot)
|
||||
return eVerticalCrossingType::vctCurrentOutsideNext;
|
||||
return eVerticalCrossingType::vctCurrentOutsideNext;
|
||||
|
||||
else if (this_top < other_top && this_bot < other_bot &&
|
||||
(this_bot >= other_top || fabs(this_bot - other_top) < c_dTHE_SAME_STRING_Y_PRECISION_MM))
|
||||
return eVerticalCrossingType::vctCurrentAboveNext;
|
||||
else if (this_top < other_top && this_bot < other_bot && this_bot > other_top &&
|
||||
this_bot - other_top > c_dOVERLAP_TEXT_LINE_ERROR_MM)
|
||||
return eVerticalCrossingType::vctCurrentAboveNext;
|
||||
|
||||
else if (this_top > other_top && this_bot > other_bot &&
|
||||
(this_top <= other_bot || fabs(this_top - other_bot) < c_dTHE_SAME_STRING_Y_PRECISION_MM))
|
||||
return eVerticalCrossingType::vctCurrentBelowNext;
|
||||
else if (this_top > other_top && this_bot > other_bot && this_top < other_bot &&
|
||||
other_bot - this_top > c_dOVERLAP_TEXT_LINE_ERROR_MM)
|
||||
return eVerticalCrossingType::vctCurrentBelowNext;
|
||||
|
||||
else if (this_top == other_top && this_bot == other_bot)
|
||||
return eVerticalCrossingType::vctDublicate;
|
||||
|
||||
else if (fabs(this_top - other_top) < c_dTHE_SAME_STRING_Y_PRECISION_MM &&
|
||||
fabs(this_bot - other_bot) < c_dTHE_SAME_STRING_Y_PRECISION_MM)
|
||||
return eVerticalCrossingType::vctTopAndBottomBordersMatch;
|
||||
return eVerticalCrossingType::vctTopAndBottomBordersMatch;
|
||||
|
||||
else if (fabs(this_top - other_top) < c_dTHE_SAME_STRING_Y_PRECISION_MM)
|
||||
return eVerticalCrossingType::vctTopBorderMatch;
|
||||
return eVerticalCrossingType::vctTopBorderMatch;
|
||||
|
||||
else if (fabs(this_bot - other_bot) < c_dTHE_SAME_STRING_Y_PRECISION_MM)
|
||||
return eVerticalCrossingType::vctBottomBorderMatch;
|
||||
return eVerticalCrossingType::vctBottomBorderMatch;
|
||||
|
||||
else if (this_bot < other_top)
|
||||
return eVerticalCrossingType::vctNoCrossingCurrentAboveNext;
|
||||
else if (other_top - this_bot > -c_dOVERLAP_TEXT_LINE_ERROR_MM)
|
||||
return eVerticalCrossingType::vctNoCrossingCurrentAboveNext;
|
||||
|
||||
else if (this_top > other_bot)
|
||||
return eVerticalCrossingType::vctNoCrossingCurrentBelowNext;
|
||||
else if (this_top - other_bot > -c_dOVERLAP_TEXT_LINE_ERROR_MM)
|
||||
return eVerticalCrossingType::vctNoCrossingCurrentBelowNext;
|
||||
|
||||
else
|
||||
return eVerticalCrossingType::vctUnknown;
|
||||
@ -555,6 +555,9 @@ namespace NSDocxRenderer
|
||||
std::wstring origin_lefts{};
|
||||
for (auto& l : m_arOriginLefts)
|
||||
origin_lefts += std::to_wstring(static_cast<int>(l * c_dMMToEMU)) + L";";
|
||||
// add offset for last symbol
|
||||
if (!m_arSymWidths.empty())
|
||||
origin_lefts += std::to_wstring(static_cast<int>((m_arOriginLefts.back() + m_arSymWidths.back()) * c_dMMToEMU)) + L";";
|
||||
|
||||
oWriter.WriteBYTE(5); oWriter.WriteStringUtf16(origin_lefts); // Origin lefts
|
||||
oWriter.WriteBYTE(6); oWriter.WriteBool(m_bFontSubstitution); // Font Substitution (just pass from pdf)
|
||||
@ -658,6 +661,7 @@ namespace NSDocxRenderer
|
||||
|
||||
bool CContText::IsEqual(const CContText *pCont) const noexcept
|
||||
{
|
||||
bool bIf0 = IsFontsEqual(m_oSelectedFont, pCont->m_oSelectedFont);
|
||||
bool bIf1 = m_pFontStyle->wsFontStyleId == pCont->m_pFontStyle->wsFontStyleId;
|
||||
bool bIf2 = m_bIsStrikeoutPresent == pCont->m_bIsStrikeoutPresent;
|
||||
bool bIf3 = m_bIsDoubleStrikeout == pCont->m_bIsDoubleStrikeout;
|
||||
@ -674,7 +678,7 @@ namespace NSDocxRenderer
|
||||
bool bIf14 = m_eVertAlignType == eVertAlignType::vatUnknown && pCont->m_eVertAlignType == eVertAlignType::vatBase;
|
||||
bool bIf15 = m_eVertAlignType == eVertAlignType::vatBase && pCont->m_eVertAlignType == eVertAlignType::vatUnknown;
|
||||
|
||||
return (bIf1 && bIf2 && bIf3 && bIf4 && bIf5 && bIf6 && bIf7 &&
|
||||
return (bIf0 && bIf1 && bIf2 && bIf3 && bIf4 && bIf5 && bIf6 && bIf7 &&
|
||||
bIf8 && bIf9 && bIf10 && bIf11 && bIf12 && (bIf13 || bIf14 || bIf15));
|
||||
}
|
||||
|
||||
@ -894,12 +898,12 @@ namespace NSDocxRenderer
|
||||
eHorizontalCrossingType eHType)
|
||||
{
|
||||
//Условие пересечения по вертикали
|
||||
bool bIf1 = eVType == eVerticalCrossingType::vctCurrentAboveNext; //текущий cont выше
|
||||
bool bIf2 = eVType == eVerticalCrossingType::vctCurrentBelowNext; //текущий cont ниже
|
||||
bool bIf1 = eVType == eVerticalCrossingType::vctCurrentAboveNext;
|
||||
bool bIf2 = eVType == eVerticalCrossingType::vctCurrentBelowNext;
|
||||
|
||||
//Условие пересечения по горизонтали
|
||||
bool bIf3 = eHType == eHorizontalCrossingType::hctCurrentLeftOfNext; //текущий cont левее
|
||||
bool bIf4 = eHType == eHorizontalCrossingType::hctCurrentRightOfNext; //текущий cont правее
|
||||
bool bIf3 = eHType == eHorizontalCrossingType::hctCurrentLeftOfNext;
|
||||
bool bIf4 = eHType == eHorizontalCrossingType::hctCurrentRightOfNext;
|
||||
|
||||
//Размеры шрифта и текст должны бать одинаковыми
|
||||
bool bIf5 = pFirstCont->m_pFontStyle->dFontSize == pSecondCont->m_pFontStyle->dFontSize;
|
||||
@ -915,9 +919,7 @@ namespace NSDocxRenderer
|
||||
bool bIf11 = pFirstCont->m_pFontStyle->oBrush.Color1 == c_iGreyColor2;
|
||||
bool bIf12 = pSecondCont->m_pFontStyle->oBrush.Color1 == c_iGreyColor2;
|
||||
|
||||
//note Каждый символ с Emboss или Engrave разбиваются на 3 символа с разными цветами
|
||||
//note Логика подобрана для конкретного примера - возможно нужно будет ее обобщить.
|
||||
//todo существует проблема неправильного определением FontEffects с физически пересекаемыми строчками - файл generaltest.pdf p.14
|
||||
// каждый символ с Emboss или Engrave разбиваются на 3 символа с разными цветами
|
||||
if (bIf5 && bIf6)
|
||||
{
|
||||
if (bIf12 && pFirstCont->m_bIsEmbossPresent)
|
||||
@ -977,18 +979,20 @@ namespace NSDocxRenderer
|
||||
eHorizontalCrossingType eHType)
|
||||
{
|
||||
|
||||
double first_height = pFirstCont->m_dBotWithDescent - pFirstCont->m_dTopWithAscent;
|
||||
bool bIf1 = eVType == eVerticalCrossingType::vctCurrentAboveNext ||
|
||||
eVType == eVerticalCrossingType::vctCurrentInsideNext;
|
||||
eVType == eVerticalCrossingType::vctCurrentInsideNext &&
|
||||
pSecondCont->m_dBotWithDescent - pFirstCont->m_dBotWithDescent > first_height * 0.2;
|
||||
|
||||
bool bIf2 = eVType == eVerticalCrossingType::vctCurrentBelowNext;
|
||||
|
||||
bool bIf3 = (eHType == eHorizontalCrossingType::hctNoCrossingCurrentLeftOfNext ||
|
||||
eHType == eHorizontalCrossingType::hctCurrentLeftOfNext) &&
|
||||
fabs(pFirstCont->m_dRight - pSecondCont->m_dLeft) < c_dTHE_STRING_X_PRECISION_MM * 3;
|
||||
fabs(pFirstCont->m_dRight - pSecondCont->m_dLeft) < c_dTHE_STRING_X_PRECISION_MM;
|
||||
|
||||
bool bIf4 = (eHType == eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext ||
|
||||
eHType == eHorizontalCrossingType::hctCurrentRightOfNext) &&
|
||||
fabs(pFirstCont->m_dLeft - pSecondCont->m_dRight) < c_dTHE_STRING_X_PRECISION_MM * 3;
|
||||
fabs(pFirstCont->m_dLeft - pSecondCont->m_dRight) < c_dTHE_STRING_X_PRECISION_MM;
|
||||
|
||||
//Размеры шрифта должны бать разными
|
||||
bool bIf5 = pFirstCont->m_pFontStyle->dFontSize * 0.8 > pSecondCont->m_pFontStyle->dFontSize;
|
||||
@ -1090,6 +1094,19 @@ namespace NSDocxRenderer
|
||||
{
|
||||
return 0x0300 <= cSym && 0x036F >= cSym;
|
||||
}
|
||||
bool CContText::IsFontsEqual(const NSStructures::CFont& oFont1, const NSStructures::CFont& oFont2)
|
||||
{
|
||||
bool res = oFont1.Name == oFont2.Name;
|
||||
res = res && oFont1.Path == oFont2.Path;
|
||||
res = res && oFont1.FaceIndex == oFont2.FaceIndex;
|
||||
res = res && oFont1.StringGID == oFont2.StringGID;
|
||||
res = res && oFont1.Size == oFont2.Size;
|
||||
res = res && oFont1.Bold == oFont2.Bold;
|
||||
res = res && oFont1.Italic == oFont2.Italic;
|
||||
res = res && oFont1.Underline == oFont2.Underline;
|
||||
res = res && oFont1.Strikeout == oFont2.Strikeout;
|
||||
return res;
|
||||
}
|
||||
|
||||
double CContText::CalculateSpace() const noexcept
|
||||
{
|
||||
@ -1245,12 +1262,11 @@ namespace NSDocxRenderer
|
||||
pCont->m_dWidth = dWidth;
|
||||
pCont->m_dRight = dRight;
|
||||
|
||||
double font_size = oFont.Size;
|
||||
double em_height = oMetrics.dEmHeight;
|
||||
double ratio = font_size / em_height * c_dPtToMM;
|
||||
double ascent = pFontManager->GetFontAscent();
|
||||
double descent = pFontManager->GetFontDescent();
|
||||
|
||||
pCont->m_dTopWithAscent = pCont->m_dBot - (oMetrics.dAscent * ratio);
|
||||
pCont->m_dBotWithDescent = pCont->m_dBot + (oMetrics.dDescent * ratio);
|
||||
pCont->m_dTopWithAscent = pCont->m_dBot - ascent;
|
||||
pCont->m_dBotWithDescent = pCont->m_dBot + fabs(descent);
|
||||
pCont->m_dSpaceWidthMM = pFontManager->GetSpaceWidthMM();
|
||||
|
||||
pCont->m_wsOriginFontName = oFont.Name;
|
||||
|
||||
@ -159,6 +159,8 @@ namespace NSDocxRenderer
|
||||
static bool IsUnicodeSymbol(uint32_t symbol);
|
||||
static bool IsUnicodeDiacriticalMark(uint32_t symbol);
|
||||
|
||||
static bool IsFontsEqual(const NSStructures::CFont& oFont1, const NSStructures::CFont& oFont2);
|
||||
|
||||
private:
|
||||
NSStringUtils::CStringUTF32 m_oText{};
|
||||
std::vector<double> m_arSymWidths{};
|
||||
|
||||
@ -1311,8 +1311,8 @@ namespace NSDocxRenderer
|
||||
{
|
||||
oWriter.StartRecord(2);
|
||||
oWriter.WriteBYTE(kBin_g_nodeAttributeStart);
|
||||
oWriter.WriteBYTE(0); oWriter.AddInt(100);
|
||||
oWriter.WriteBYTE(1); oWriter.AddInt(100);
|
||||
oWriter.WriteBYTE(0); oWriter.AddInt(100 * 1000);
|
||||
oWriter.WriteBYTE(1); oWriter.AddInt(100 * 1000);
|
||||
oWriter.WriteBYTE(kBin_g_nodeAttributeEnd);
|
||||
oWriter.EndRecord();
|
||||
}
|
||||
@ -1343,7 +1343,7 @@ namespace NSDocxRenderer
|
||||
// WriteRecord WriteBodyPr
|
||||
oWriter.StartRecord(0);
|
||||
oWriter.WriteBYTE(kBin_g_nodeAttributeStart);
|
||||
oWriter.WriteBYTE(1); oWriter.WriteBYTE(1); // anchor
|
||||
oWriter.WriteBYTE(1); oWriter.WriteBYTE(4); // anchor
|
||||
oWriter.WriteBYTE(2); oWriter.WriteBool(false); // anchorCtr
|
||||
oWriter.WriteBYTE(3); oWriter.AddInt(0); // bIns
|
||||
oWriter.WriteBYTE(4); oWriter.WriteBool(true); // compatLnSpc
|
||||
|
||||
@ -66,6 +66,8 @@ namespace NSDocxRenderer
|
||||
std::sort(m_arConts.begin(), m_arConts.end(), [] (const cont_ptr_t& a, const cont_ptr_t& b) {
|
||||
if (!a) return false;
|
||||
if (!b) return true;
|
||||
if (fabs(a->m_dLeft - b->m_dLeft) < c_dTHE_SAME_STRING_X_PRECISION_MM)
|
||||
return a->m_dRight < b->m_dRight;
|
||||
return a->m_dLeft < b->m_dLeft;
|
||||
});
|
||||
|
||||
@ -243,15 +245,15 @@ namespace NSDocxRenderer
|
||||
return eVerticalCrossingType::vctCurrentInsideNext;
|
||||
|
||||
else if (this_top < other_top && this_bot > other_bot)
|
||||
return eVerticalCrossingType::vctCurrentOutsideNext;
|
||||
return eVerticalCrossingType::vctCurrentOutsideNext;
|
||||
|
||||
else if (this_top < other_top && this_bot < other_bot &&
|
||||
(this_bot >= other_top || fabs(this_bot - other_top) < c_dTHE_SAME_STRING_Y_PRECISION_MM))
|
||||
return eVerticalCrossingType::vctCurrentAboveNext;
|
||||
else if (this_top < other_top && this_bot < other_bot && this_bot > other_top &&
|
||||
this_bot - other_top > c_dOVERLAP_TEXT_LINE_ERROR_MM)
|
||||
return eVerticalCrossingType::vctCurrentAboveNext;
|
||||
|
||||
else if (this_top > other_top && this_bot > other_bot &&
|
||||
(this_top <= other_bot || fabs(this_top - other_bot) < c_dTHE_SAME_STRING_Y_PRECISION_MM))
|
||||
return eVerticalCrossingType::vctCurrentBelowNext;
|
||||
else if (this_top > other_top && this_bot > other_bot && this_top < other_bot &&
|
||||
other_bot - this_top > c_dOVERLAP_TEXT_LINE_ERROR_MM)
|
||||
return eVerticalCrossingType::vctCurrentBelowNext;
|
||||
|
||||
else if (this_top == other_top && this_bot == other_bot &&
|
||||
m_dLeft == pLine->m_dLeft && m_dRight == pLine->m_dRight)
|
||||
@ -259,31 +261,33 @@ namespace NSDocxRenderer
|
||||
|
||||
else if (fabs(this_top - other_top) < c_dTHE_SAME_STRING_Y_PRECISION_MM &&
|
||||
fabs(this_bot - other_bot) < c_dTHE_SAME_STRING_Y_PRECISION_MM)
|
||||
return eVerticalCrossingType::vctTopAndBottomBordersMatch;
|
||||
return eVerticalCrossingType::vctTopAndBottomBordersMatch;
|
||||
|
||||
else if (fabs(this_top - other_top) < c_dTHE_SAME_STRING_Y_PRECISION_MM)
|
||||
return eVerticalCrossingType::vctTopBorderMatch;
|
||||
return eVerticalCrossingType::vctTopBorderMatch;
|
||||
|
||||
else if (fabs(this_bot - other_bot) < c_dTHE_SAME_STRING_Y_PRECISION_MM)
|
||||
return eVerticalCrossingType::vctBottomBorderMatch;
|
||||
return eVerticalCrossingType::vctBottomBorderMatch;
|
||||
|
||||
else if (this_bot < other_top)
|
||||
return eVerticalCrossingType::vctNoCrossingCurrentAboveNext;
|
||||
else if (other_top - this_bot > -c_dOVERLAP_TEXT_LINE_ERROR_MM)
|
||||
return eVerticalCrossingType::vctNoCrossingCurrentAboveNext;
|
||||
|
||||
else if (this_top > other_bot)
|
||||
return eVerticalCrossingType::vctNoCrossingCurrentBelowNext;
|
||||
else if (this_top - other_bot > -c_dOVERLAP_TEXT_LINE_ERROR_MM)
|
||||
return eVerticalCrossingType::vctNoCrossingCurrentBelowNext;
|
||||
|
||||
else
|
||||
return eVerticalCrossingType::vctUnknown;
|
||||
return eVerticalCrossingType::vctUnknown;
|
||||
}
|
||||
|
||||
void CTextLine::RecalcWithNewItem(const CContText* pCont)
|
||||
{
|
||||
CBaseItem::RecalcWithNewItem(pCont);
|
||||
if (m_dTopWithMaxAscent == 0.0) m_dTopWithMaxAscent = pCont->m_dTopWithAscent;
|
||||
else m_dTopWithMaxAscent = std::min(m_dTopWithMaxAscent, pCont->m_dTopWithAscent);
|
||||
|
||||
m_dBotWithMaxDescent = std::max(m_dBotWithMaxDescent, pCont->m_dBotWithDescent);
|
||||
if (!pCont->IsOnlySpaces())
|
||||
{
|
||||
if (m_dTopWithMaxAscent == 0.0) m_dTopWithMaxAscent = pCont->m_dTopWithAscent;
|
||||
else m_dTopWithMaxAscent = std::min(m_dTopWithMaxAscent, pCont->m_dTopWithAscent);
|
||||
m_dBotWithMaxDescent = std::max(m_dBotWithMaxDescent, pCont->m_dBotWithDescent);
|
||||
}
|
||||
}
|
||||
|
||||
void CTextLine::SetVertAlignType(const eVertAlignType& oType)
|
||||
|
||||
@ -581,6 +581,16 @@ namespace NSDocxRenderer
|
||||
{
|
||||
return c_dPtToMM * (m_oFontMetrics.dLineSpacing * m_oFont.Size) / m_oFontMetrics.dEmHeight;
|
||||
}
|
||||
double CFontManager::GetFontAscent() const
|
||||
{
|
||||
//double tmp = m_oFontMetrics.dAscent;
|
||||
double tmp = m_oFontMetrics.dLineSpacing - fabs(m_oFontMetrics.dDescent);
|
||||
return c_dPtToMM * (tmp * m_oFont.Size) / m_oFontMetrics.dEmHeight;
|
||||
}
|
||||
double CFontManager::GetFontDescent() const
|
||||
{
|
||||
return c_dPtToMM * (m_oFontMetrics.dDescent * m_oFont.Size) / m_oFontMetrics.dEmHeight;
|
||||
}
|
||||
double CFontManager::GetSpaceWidthMM() const
|
||||
{
|
||||
double dSpaceWidthMM = 0.0;
|
||||
|
||||
@ -124,6 +124,9 @@ namespace NSDocxRenderer
|
||||
const CFontMetrics& GetFontMetrics() const noexcept;
|
||||
|
||||
double GetFontHeight() const;
|
||||
double GetFontAscent() const;
|
||||
double GetFontDescent() const;
|
||||
|
||||
double GetSpaceWidthMM() const;
|
||||
|
||||
void SetStringGid(const LONG& lGid);
|
||||
|
||||
@ -147,7 +147,7 @@ namespace NSDocxRenderer
|
||||
return GenerateImageID(pImage);
|
||||
}
|
||||
|
||||
std::shared_ptr<CImageInfo> CImageManager::WriteImage(const std::wstring& strFile, double& x, double& y, double& width, double& height)
|
||||
std::shared_ptr<CImageInfo> CImageManager::WriteImage(const std::wstring& strFile)
|
||||
{
|
||||
Aggplus::CImage image(strFile);
|
||||
return GenerateImageID(&image);
|
||||
|
||||
@ -20,14 +20,14 @@ namespace NSDocxRenderer
|
||||
void Clear();
|
||||
|
||||
std::shared_ptr<CImageInfo> WriteImage(Aggplus::CImage* pImage, double& x, double& y, double& width, double& height);
|
||||
std::shared_ptr<CImageInfo> WriteImage(const std::wstring& strFile, double& x, double& y, double& width, double& height);
|
||||
std::shared_ptr<CImageInfo> WriteImage(const std::wstring& strFile);
|
||||
std::shared_ptr<CImageInfo> GenerateImageID(Aggplus::CImage* pImage);
|
||||
|
||||
static CImageInfo::ImageType GetImageType(Aggplus::CImage* pFrame);
|
||||
static void FlipY(Aggplus::CImage* pImage);
|
||||
|
||||
private:
|
||||
std::shared_ptr<CImageInfo> GenerateImageID(const std::wstring& strFileName);
|
||||
void FlipY(Aggplus::CImage* pImage);
|
||||
|
||||
int m_lMaxSizeImage {1200};
|
||||
int m_lNextIDImage {0};
|
||||
CCalculatorCRC32 m_oCRC;
|
||||
|
||||
@ -24,10 +24,11 @@ constexpr double c_dPtToEMU = 12700.0;
|
||||
constexpr double c_dDegreeToAngle = 60000.0;
|
||||
|
||||
const double c_dSTANDART_STRING_HEIGHT_MM = 4.2333333333333334;
|
||||
const double c_dTHE_SAME_STRING_Y_PRECISION_MM = 0.03;
|
||||
const double c_dTHE_SAME_STRING_Y_PRECISION_MM = 0.015;
|
||||
const double c_dTHE_SAME_STRING_X_PRECISION_MM = 0.03;
|
||||
const double c_dTHE_SAME_SPACING_ERROR = 0.1;
|
||||
const double c_dLINE_DISTANCE_ERROR_MM = 0.3;
|
||||
const double c_dOVERLAP_TEXT_LINE_ERROR_MM = 0.7;
|
||||
const double c_dERROR_OF_PARAGRAPH_BORDERS_MM = 1.0;
|
||||
const double c_dCENTER_POSITION_ERROR_MM = 1.5;
|
||||
const double c_dTHE_STRING_X_PRECISION_MM = 0.5;
|
||||
|
||||
@ -195,7 +195,7 @@ namespace NSDocxRenderer
|
||||
double x0 = m_arData.back().points.back().x;
|
||||
double y0 = m_arData.back().points.back().y;
|
||||
|
||||
std::list<Point> points = {{x1, y1}, {x2, y2}, {x3, y3}};
|
||||
std::vector<Point> points = {{x1, y1}, {x2, y2}, {x3, y3}};
|
||||
ePathCommandType type = ePathCommandType::pctCurve;
|
||||
m_arData.push_back({type, points});
|
||||
|
||||
@ -308,6 +308,45 @@ namespace NSDocxRenderer
|
||||
}
|
||||
}
|
||||
}
|
||||
bool CVectorGraphics::IsClockwise() const
|
||||
{
|
||||
if (m_arData.empty())
|
||||
return false;
|
||||
|
||||
double area = 0;
|
||||
double last_x = 0;
|
||||
double last_y = 0;
|
||||
bool is_first = true;
|
||||
for (const auto& command : m_arData)
|
||||
{
|
||||
if (is_first)
|
||||
{
|
||||
is_first = false;
|
||||
last_x = command.points.back().x;
|
||||
last_y = command.points.back().y;
|
||||
continue;
|
||||
}
|
||||
if (command.type == ePathCommandType::pctClose)
|
||||
break;
|
||||
|
||||
const auto& points = command.points;
|
||||
if (command.type == ePathCommandType::pctCurve)
|
||||
{
|
||||
area += 3.0 * ((points[2].y - last_y) * (points[0].x + points[1].x)
|
||||
- (points[2].x - last_x) * (points[0].y + points[1].y)
|
||||
+ points[0].y * (last_x - points[1].x)
|
||||
- points[0].x * (last_y - points[1].y)
|
||||
+ points[2].y * (points[1].x + last_x / 3.0)
|
||||
- points[2].x * (points[1].y + last_y / 3.0)) / 20.0;
|
||||
}
|
||||
else
|
||||
area += (points[0].y * last_x - points[0].x * last_y) / 2.0;
|
||||
|
||||
last_x = command.points.back().x;
|
||||
last_y = command.points.back().y;
|
||||
}
|
||||
return area >= 0;
|
||||
}
|
||||
|
||||
// ClipRegionTypeWinding = 0x0000;
|
||||
// ClipRegionTypeEvenOdd = 0x0001;
|
||||
|
||||
@ -31,7 +31,7 @@ namespace NSDocxRenderer
|
||||
struct CPathCommand
|
||||
{
|
||||
ePathCommandType type;
|
||||
std::list<Point> points;
|
||||
std::vector<Point> points;
|
||||
};
|
||||
|
||||
CVectorGraphics() noexcept;
|
||||
@ -79,6 +79,7 @@ namespace NSDocxRenderer
|
||||
void Rotate(const double& rotation);
|
||||
void Transform(const Aggplus::CMatrix& matrix);
|
||||
void DrawOnRenderer(IRenderer* renderer) const noexcept;
|
||||
bool IsClockwise() const;
|
||||
|
||||
static CVectorGraphics CalcBoolean(const CVectorGraphics& vg1, const CVectorGraphics& vg2, long clipType, long fillType = c_nWindingFillMode, bool isLuminosity = false);
|
||||
|
||||
|
||||
@ -142,7 +142,7 @@ HRESULT CEpubFile::Convert(const std::wstring& sInputFile, const std::wstring& s
|
||||
*/
|
||||
|
||||
CHtmlFile2 oFile;
|
||||
CHtmlParams oFileParams;
|
||||
HTML::THTMLParameters oFileParams;
|
||||
|
||||
oFileParams.SetAuthors (m_oBookInfo.GetCreators());
|
||||
oFileParams.SetGenres (m_oBookInfo.GetSubjects());
|
||||
@ -155,7 +155,7 @@ HRESULT CEpubFile::Convert(const std::wstring& sInputFile, const std::wstring& s
|
||||
|
||||
std::wstring sDocxFileTempDir = m_sTempDir + L"/tmp";
|
||||
NSDirectory::CreateDirectory(sDocxFileTempDir);
|
||||
oFile.SetTmpDirectory(sDocxFileTempDir);
|
||||
oFile.SetTempDirectory(sDocxFileTempDir);
|
||||
oFile.SetCoreDirectory(NSFile::GetDirectoryName(sContent));
|
||||
|
||||
std::vector<std::wstring> arFiles;
|
||||
@ -182,7 +182,7 @@ HRESULT CEpubFile::Convert(const std::wstring& sInputFile, const std::wstring& s
|
||||
sOutputDir = sOutputFile;
|
||||
|
||||
NSDirectory::CreateDirectory(sOutputDir);
|
||||
HRESULT hRes = oFile.OpenBatchHtml(arFiles, sOutputDir, &oFileParams);
|
||||
HRESULT hRes = oFile.ConvertHTML2OOXML(arFiles, sOutputDir, &oFileParams);
|
||||
if (bIsOutCompress && S_OK == hRes)
|
||||
hRes = oOfficeUtils.CompressFileOrDirectory(sOutputDir, sOutputFile);
|
||||
|
||||
|
||||
@ -2170,7 +2170,7 @@ HRESULT CFb2File::FromHtml(const std::wstring& sHtmlFile, const std::wstring& sD
|
||||
RELEASEARRAYOBJECTS(pData);
|
||||
|
||||
//XmlUtils::CXmlLiteReader oIndexHtml;
|
||||
std::wstring xhtml = htmlToXhtml(sContent, bNeedConvert);
|
||||
std::wstring xhtml = HTML::htmlToXhtml(sContent, bNeedConvert);
|
||||
|
||||
if (!m_internal->m_oLightReader.FromString(xhtml))
|
||||
return S_FALSE;
|
||||
|
||||
64
HtmlFile2/Common.h
Normal file
64
HtmlFile2/Common.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <string>
|
||||
#include "../DesktopEditor/common/StringBuilder.h"
|
||||
|
||||
namespace HTML
|
||||
{
|
||||
#define MAX_STRING_BLOCK_SIZE (size_t)10485760
|
||||
|
||||
using XmlString = NSStringUtils::CStringBuilder;
|
||||
|
||||
inline void replace_all(std::wstring& s, const std::wstring& s1, const std::wstring& s2)
|
||||
{
|
||||
size_t pos = s.find(s1);
|
||||
size_t l = s2.length();
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
if (!(s1 == L"&" && s2 == L"&" && s.length() > pos + 4 && s[pos] == L'&' && s[pos + 1] == L'a' && s[pos + 2] == L'm' && s[pos + 3] == L'p' && s[pos + 4] == L';'))
|
||||
s.replace(pos, s1.length(), s2);
|
||||
pos = s.find(s1, pos + l);
|
||||
}
|
||||
}
|
||||
|
||||
inline std::wstring EncodeXmlString(const std::wstring& s)
|
||||
{
|
||||
std::wstring sRes = s;
|
||||
|
||||
replace_all(sRes, L"&", L"&");
|
||||
replace_all(sRes, L"<", L"<");
|
||||
replace_all(sRes, L">", L">");
|
||||
replace_all(sRes, L"\"", L""");
|
||||
replace_all(sRes, L"\'", L"'");
|
||||
replace_all(sRes, L"\n", L"
");
|
||||
replace_all(sRes, L"\r", L"
");
|
||||
replace_all(sRes, L"\t", L"	");
|
||||
|
||||
return sRes;
|
||||
}
|
||||
|
||||
inline void WriteToStringBuilder(NSStringUtils::CStringBuilder& oSrcStringBuilder, NSStringUtils::CStringBuilder& oDstStringBuilder)
|
||||
{
|
||||
if (oSrcStringBuilder.GetCurSize() < MAX_STRING_BLOCK_SIZE)
|
||||
{
|
||||
oDstStringBuilder.Write(oSrcStringBuilder);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t ulSize = oSrcStringBuilder.GetCurSize();
|
||||
size_t ulCurrentBlockSize = 0, ulPosition = 0;
|
||||
|
||||
while (ulSize > 0)
|
||||
{
|
||||
ulCurrentBlockSize = std::min(ulSize, MAX_STRING_BLOCK_SIZE);
|
||||
oDstStringBuilder.WriteString(oSrcStringBuilder.GetSubData(ulPosition, ulCurrentBlockSize));
|
||||
|
||||
ulSize -= ulCurrentBlockSize;
|
||||
ulPosition += ulCurrentBlockSize;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // COMMON_H
|
||||
69
HtmlFile2/HTMLParameters.h
Normal file
69
HtmlFile2/HTMLParameters.h
Normal file
@ -0,0 +1,69 @@
|
||||
#ifndef HTMLPARAMETERS_H
|
||||
#define HTMLPARAMETERS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace HTML
|
||||
{
|
||||
struct THTMLParameters
|
||||
{
|
||||
std::wstring m_sGenres; // Жанры
|
||||
std::wstring m_sAuthors; // Авторы
|
||||
std::wstring m_sBookTitle; // Название
|
||||
std::wstring m_sDate; // Дата
|
||||
std::wstring m_sDescription; // описание
|
||||
std::wstring m_sLanguage; // Язык
|
||||
bool m_bNeedPageBreakBefore; // Новый html с новой страницы
|
||||
std::wstring m_sdocDefaults; // Стиль docDefaults
|
||||
std::wstring m_sNormal; // Стиль normal
|
||||
|
||||
THTMLParameters() : m_bNeedPageBreakBefore(false) {}
|
||||
|
||||
void SetNormal(const std::wstring& sStyle)
|
||||
{
|
||||
m_sNormal = sStyle;
|
||||
}
|
||||
|
||||
void SetDocDefaults(const std::wstring& sStyle)
|
||||
{
|
||||
m_sdocDefaults = sStyle;
|
||||
}
|
||||
|
||||
void SetPageBreakBefore(bool bNeed)
|
||||
{
|
||||
m_bNeedPageBreakBefore = bNeed;
|
||||
}
|
||||
|
||||
void SetDate(const std::wstring& sDate)
|
||||
{
|
||||
m_sDate = sDate;
|
||||
}
|
||||
|
||||
void SetDescription(const std::wstring& sDescription)
|
||||
{
|
||||
m_sDescription = sDescription;
|
||||
}
|
||||
|
||||
void SetGenres(const std::wstring& sGenres)
|
||||
{
|
||||
m_sGenres = sGenres;
|
||||
}
|
||||
|
||||
void SetAuthors(const std::wstring& sAuthors)
|
||||
{
|
||||
m_sAuthors = sAuthors;
|
||||
}
|
||||
|
||||
void SetTitle(const std::wstring& sTitle)
|
||||
{
|
||||
m_sBookTitle = sTitle;
|
||||
}
|
||||
|
||||
void SetLanguage(const std::wstring& sLanguage)
|
||||
{
|
||||
m_sLanguage = sLanguage;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // HTMLPARAMETERS_H
|
||||
1533
HtmlFile2/HTMLReader.cpp
Normal file
1533
HtmlFile2/HTMLReader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
93
HtmlFile2/HTMLReader.h
Normal file
93
HtmlFile2/HTMLReader.h
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef HTMLREADER_H
|
||||
#define HTMLREADER_H
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "../Common/3dParty/html/css/src/CCssCalculator.h"
|
||||
#include "../DesktopEditor/xml/include/xmlutils.h"
|
||||
|
||||
#include "HTMLParameters.h"
|
||||
#include "MarkdownParameters.h"
|
||||
|
||||
#include "Writers/IWriter.h"
|
||||
#include "Tags/HTMLTags.h"
|
||||
#include "Table.h"
|
||||
|
||||
namespace HTML
|
||||
{
|
||||
class CHTMLReader
|
||||
{
|
||||
XmlUtils::CXmlLiteReader m_oLightReader; // SAX Reader
|
||||
NSCSS::CCssCalculator m_oCSSCalculator; // Css калькулятор
|
||||
|
||||
bool m_bIsTempDirOwner;
|
||||
std::wstring m_wsTempDirectory; // Temp папка
|
||||
std::wstring m_wsSrcDirectory; // Директория источника
|
||||
std::wstring m_wsDstDirectory; // Директория назначения
|
||||
std::wstring m_wsBaseDirectory; // Полный базовый адрес
|
||||
std::wstring m_wsCoreDirectory; // Путь до корневого файла (используется для работы с Epub)
|
||||
|
||||
IWriter *m_pWriter;
|
||||
|
||||
std::unordered_map<UINT, std::shared_ptr<ITag>> m_mTags;
|
||||
public:
|
||||
CHTMLReader();
|
||||
~CHTMLReader();
|
||||
|
||||
void SetTempDirectory(const std::wstring& wsPath);
|
||||
void SetCoreDirectory(const std::wstring& wsPath);
|
||||
|
||||
HRESULT ConvertHTML2OOXML (const std::wstring& wsPath, const std::wstring& wsDirectory, THTMLParameters* pParameters = nullptr);
|
||||
HRESULT ConvertHTML2Markdown(const std::wstring& wsPath, const std::wstring& wsFinalFile, TMarkdownParameters* pParameters = nullptr);
|
||||
|
||||
HRESULT ConvertHTML2OOXML (const std::vector<std::wstring>& arPaths, const std::wstring& wsDirectory, THTMLParameters* pParameters = nullptr);
|
||||
HRESULT ConvertHTML2Markdown(const std::vector<std::wstring>& arPaths, const std::wstring& wsFinalFile, TMarkdownParameters* pParameters = nullptr);
|
||||
|
||||
HRESULT ConvertMHT2OOXML (const std::wstring& wsPath, const std::wstring& wsDirectory, THTMLParameters* pParameters = nullptr);
|
||||
HRESULT ConvertMHT2Markdown (const std::wstring& wsPath, const std::wstring& wsFinalFile, TMarkdownParameters* pParameters = nullptr);
|
||||
|
||||
HRESULT ConvertMHT2OOXML (const std::vector<std::wstring>& arPaths, const std::wstring& wsDirectory, THTMLParameters* pParameters = nullptr);
|
||||
HRESULT ConvertMHT2Markdown (const std::vector<std::wstring>& arPaths, const std::wstring& wsFinalFile, TMarkdownParameters* pParameters = nullptr);
|
||||
|
||||
NSCSS::CCssCalculator* GetCSSCalculator();
|
||||
private:
|
||||
void Clear();
|
||||
void InitOOXMLTags(THTMLParameters* pParametrs = nullptr);
|
||||
void InitMDTags(TMarkdownParameters* pParametrs = nullptr);
|
||||
|
||||
bool IsHTML();
|
||||
|
||||
typedef std::function<bool(const std::wstring&, XmlUtils::CXmlLiteReader&)> Convert_Func;
|
||||
|
||||
HRESULT InitAndConvert2OOXML(const std::vector<std::wstring>& arPaths, const std::wstring& wsDirectory, Convert_Func Convertation, THTMLParameters* pParameters = nullptr);
|
||||
HRESULT InitAndConvert2Markdown(const std::vector<std::wstring>& arPaths, const std::wstring& wsFinalFile, Convert_Func Convertation, TMarkdownParameters* pParameters = nullptr);
|
||||
|
||||
bool Convert(const std::wstring& wsPath, Convert_Func Convertation);
|
||||
|
||||
void ReadStyle();
|
||||
void ReadStyle2();
|
||||
void ReadStyleFromNetwork();
|
||||
|
||||
void ReadDocument();
|
||||
void ReadHead();
|
||||
void ReadBody();
|
||||
|
||||
bool ReadStream(std::vector<NSCSS::CNode>& arSelectors, bool bInsertEmptyP = false);
|
||||
bool ReadInside(std::vector<NSCSS::CNode>& arSelectors);
|
||||
|
||||
bool ReadText(std::vector<NSCSS::CNode>& arSelectors);
|
||||
|
||||
bool ReadSVG(const std::vector<NSCSS::CNode>& arSelectors);
|
||||
bool ReadEmptyTag(UINT unTag, const std::vector<NSCSS::CNode>& arSelectors);
|
||||
bool ReadDefaultTag(UINT unTag, std::vector<NSCSS::CNode>& arSelectors);
|
||||
|
||||
bool ReadTable(std::vector<NSCSS::CNode>& arSelectors);
|
||||
void ReadTableCaption(CStorageTable& oTable, std::vector<NSCSS::CNode>& arSelectors);
|
||||
void ReadTableRows(CStorageTable& oTable, std::vector<NSCSS::CNode>& arSelectors, ERowParseMode eMode);
|
||||
void ReadTableColspan(CStorageTable& oTable);
|
||||
|
||||
void GetSubClass(std::vector<NSCSS::CNode>& arSelectors);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // HTMLREADER_H
|
||||
@ -13,6 +13,7 @@ DEFINES += CSSCALCULATOR_LIBRARY_STATIC
|
||||
DEFINES += CSS_CALCULATOR_WITH_XHTML
|
||||
DEFINES += DISABLE_RUBY_SUPPORT
|
||||
DEFINES += MDCONVERTER_DECL_EXPORT
|
||||
DEFINES += HTML_NORMALIZER_DECL_EXPORT
|
||||
|
||||
CORE_ROOT_DIR = $$PWD/..
|
||||
PWD_ROOT_DIR = $$PWD
|
||||
@ -31,8 +32,25 @@ include($$CORE_ROOT_DIR/Common/3dParty/boost/boost.pri)
|
||||
|
||||
ADD_DEPENDENCY(kernel, UnicodeConverter, graphics, kernel_network)
|
||||
|
||||
SOURCES += htmlfile2.cpp
|
||||
SOURCES += htmlfile2.cpp \
|
||||
./Writers/OOXMLWriter.cpp \
|
||||
HTMLReader.cpp \
|
||||
Tags/MDTags.cpp \
|
||||
Writers/MDWriter.cpp \
|
||||
Table.cpp \
|
||||
Tags/OOXMLTags.cpp
|
||||
|
||||
HEADERS += htmlfile2.h \
|
||||
./src/StringFinder.h \
|
||||
./src/Languages.h
|
||||
./src/Languages.h \
|
||||
Common.h \
|
||||
./Writers/OOXMLWriter.h \
|
||||
./Writers/IWriter.h \
|
||||
HTMLParameters.h \
|
||||
HTMLReader.h \
|
||||
./Tags/HTMLTags.h \
|
||||
MarkdownParameters.h \
|
||||
Tags/MDTags.h \
|
||||
Writers/MDWriter.h \
|
||||
Table.h \
|
||||
Tags/OOXMLTags.h
|
||||
|
||||
14
HtmlFile2/MarkdownParameters.h
Normal file
14
HtmlFile2/MarkdownParameters.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef MARKDOWNPARAMETERS_H
|
||||
#define MARKDOWNPARAMETERS_H
|
||||
|
||||
namespace HTML
|
||||
{
|
||||
struct TMarkdownParameters
|
||||
{
|
||||
bool m_bUseAlternativeHTMLTags = false; //Использовать html теги там, где нет стандартной реализации в md(например для подчеркиваний)
|
||||
wchar_t m_wchUnorderedList = L'-'; // Возможные варианты в md: -, +, *
|
||||
wchar_t m_wchOrderedList = L'.'; // Возможные варианты в md: ., )
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MARKDOWNPARAMETERS_H
|
||||
715
HtmlFile2/Table.cpp
Normal file
715
HtmlFile2/Table.cpp
Normal file
@ -0,0 +1,715 @@
|
||||
#include "Table.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "src/StringFinder.h"
|
||||
|
||||
namespace HTML
|
||||
{
|
||||
#define MAX_STRING_BLOCK_SIZE (size_t)10485760
|
||||
|
||||
#define RELEASE_VECTOR_PTR(vector_object, object_type) \
|
||||
for (object_type* pElement : vector_object) \
|
||||
RELEASEOBJECT(pElement)
|
||||
|
||||
#define FIRST_ELEMENT 0x00000001
|
||||
#define LAST_ELEMENT 0x00000002
|
||||
#define MID_ELEMENT 0x00000004
|
||||
|
||||
#define PARSE_MODE_HEADER 0x00000100
|
||||
#define PARSE_MODE_BODY 0x00000200
|
||||
#define PARSE_MODE_FOOTHER 0x00000400
|
||||
|
||||
#define COL_POSITION_MASK 0x0000000F
|
||||
#define ROW_POSITION_MASK 0x000000F0
|
||||
#define PARSE_MODE_MASK 0x00000F00
|
||||
|
||||
#define DEFAULT_PAGE_WIDTH 12240 // Значение в Twips
|
||||
#define DEFAULT_PAGE_HEIGHT 15840 // Значение в Twips
|
||||
|
||||
TTableRowStyle::TTableRowStyle()
|
||||
: m_unMaxIndex(0), m_unMaxHeight(0), m_bIsHeader(false)
|
||||
{}
|
||||
|
||||
bool TTableRowStyle::Empty() const
|
||||
{
|
||||
return 0 == m_unMaxHeight && false == m_bIsHeader;
|
||||
}
|
||||
|
||||
TTableCellStyle::TTableCellStyle()
|
||||
{}
|
||||
|
||||
bool TTableCellStyle::Empty()
|
||||
{
|
||||
return m_oWidth.Empty() && m_oHeight.Empty() && m_oBorder.Empty() && m_oPadding.Empty() && m_wsVAlign.empty() && m_wsVAlign.empty();
|
||||
}
|
||||
|
||||
void TTableCellStyle::Copy(const TTableCellStyle* pTableCellStyle)
|
||||
{
|
||||
if (NULL == pTableCellStyle)
|
||||
return;
|
||||
|
||||
m_oWidth = pTableCellStyle->m_oWidth;
|
||||
m_oHeight = pTableCellStyle->m_oHeight;
|
||||
m_oBorder = pTableCellStyle->m_oBorder;
|
||||
m_oPadding = pTableCellStyle->m_oPadding;
|
||||
m_oBackground = pTableCellStyle->m_oBackground;
|
||||
|
||||
m_wsHAlign = pTableCellStyle->m_wsHAlign;
|
||||
m_wsVAlign = pTableCellStyle->m_wsVAlign;
|
||||
}
|
||||
|
||||
TTableCellStyle& TTableCellStyle::operator+=(const TTableCellStyle* pCellStyle)
|
||||
{
|
||||
if (NULL == pCellStyle)
|
||||
return *this;
|
||||
|
||||
m_oWidth += pCellStyle->m_oWidth;
|
||||
m_oHeight += pCellStyle->m_oHeight;
|
||||
m_oBorder += pCellStyle->m_oBorder;
|
||||
m_oPadding += pCellStyle->m_oPadding;
|
||||
m_oBackground += pCellStyle->m_oBackground;
|
||||
|
||||
if (m_wsHAlign.empty())
|
||||
m_wsHAlign = pCellStyle->m_wsHAlign;
|
||||
|
||||
if (m_wsVAlign.empty())
|
||||
m_wsVAlign = pCellStyle->m_wsVAlign;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CStorageTableCell::CStorageTableCell()
|
||||
: m_unColspan(1), m_unRowSpan(1), m_bIsMerged(false), m_bIsEmpty(false), m_oData(30)
|
||||
{}
|
||||
|
||||
CStorageTableCell::CStorageTableCell(UINT unColspan, UINT unRowspan, bool bIsMerged, bool bIsEmpty)
|
||||
: m_unColspan(unColspan), m_unRowSpan(unRowspan), m_bIsMerged(bIsMerged),
|
||||
m_bIsEmpty(bIsEmpty)
|
||||
{}
|
||||
|
||||
CStorageTableCell::CStorageTableCell(CStorageTableCell& oCell)
|
||||
: m_unColspan(oCell.m_unColspan), m_unRowSpan(oCell.m_unRowSpan), m_bIsMerged(oCell.m_bIsMerged),
|
||||
m_bIsEmpty(oCell.m_bIsEmpty), m_oStyles(oCell.m_oStyles)
|
||||
{
|
||||
WriteToStringBuilder(oCell.m_oData, m_oData);
|
||||
}
|
||||
|
||||
bool CStorageTableCell::Empty() const
|
||||
{
|
||||
return m_bIsEmpty;
|
||||
}
|
||||
|
||||
bool CStorageTableCell::Merged() const
|
||||
{
|
||||
return m_bIsMerged;
|
||||
}
|
||||
|
||||
CStorageTableCell* CStorageTableCell::Copy()
|
||||
{
|
||||
return new CStorageTableCell(*this);
|
||||
}
|
||||
|
||||
CStorageTableCell* CStorageTableCell::CreateEmpty(UINT unColspan, bool m_bIsMerged, const TTableCellStyle* pStyle)
|
||||
{
|
||||
CStorageTableCell *pCell = new CStorageTableCell(unColspan, 1, m_bIsMerged, true);
|
||||
|
||||
pCell->m_oStyles.Copy(pStyle);
|
||||
|
||||
return pCell;
|
||||
}
|
||||
|
||||
CStorageTableCell* CStorageTableCell::CreateEmpty(const TTableCellStyle* pStyle)
|
||||
{
|
||||
CStorageTableCell *pCell = new CStorageTableCell(1, 1, false, true);
|
||||
|
||||
pCell->m_oStyles.Copy(pStyle);
|
||||
|
||||
return pCell;
|
||||
}
|
||||
|
||||
void CStorageTableCell::SetColspan(UINT unColspan, UINT unCurrentIndex)
|
||||
{
|
||||
if (MAXCOLUMNSINTABLE - 1 != unCurrentIndex)
|
||||
m_unColspan = std::min(MAXCOLUMNSINTABLE - 1 - unCurrentIndex, unColspan);
|
||||
else
|
||||
m_unColspan = 1;
|
||||
}
|
||||
|
||||
UINT CStorageTableCell::GetColspan() const
|
||||
{
|
||||
return m_unColspan;
|
||||
}
|
||||
|
||||
void CStorageTableCell::SetRowspan(UINT unRowspan)
|
||||
{
|
||||
m_unRowSpan = unRowspan;
|
||||
}
|
||||
|
||||
UINT CStorageTableCell::GetRowspan() const
|
||||
{
|
||||
return m_unRowSpan;
|
||||
}
|
||||
|
||||
NSStringUtils::CStringBuilder* CStorageTableCell::GetData()
|
||||
{
|
||||
return &m_oData;
|
||||
}
|
||||
|
||||
const TTableCellStyle* CStorageTableCell::GetStyles() const
|
||||
{
|
||||
return &m_oStyles;
|
||||
}
|
||||
|
||||
TTableCellStyle* CStorageTableCell::GetStyles()
|
||||
{
|
||||
return &m_oStyles;
|
||||
}
|
||||
|
||||
void CStorageTableCell::SetWidth(const NSCSS::NSProperties::CDigit& oWidth)
|
||||
{
|
||||
m_oStyles.m_oWidth = oWidth;
|
||||
}
|
||||
|
||||
void CStorageTableCell::SetHeight(const NSCSS::NSProperties::CDigit& oHeight)
|
||||
{
|
||||
m_oStyles.m_oHeight = oHeight;
|
||||
}
|
||||
|
||||
UINT CStorageTableCell::GetWidth() const
|
||||
{
|
||||
return m_oStyles.m_oWidth.ToInt(NSCSS::Twips, DEFAULT_PAGE_WIDTH);
|
||||
}
|
||||
|
||||
UINT CStorageTableCell::GetHeight() const
|
||||
{
|
||||
return m_oStyles.m_oHeight.ToInt(NSCSS::Twips, DEFAULT_PAGE_HEIGHT);
|
||||
}
|
||||
|
||||
void CStorageTableCell::SetBorder(const NSCSS::NSProperties::CBorder& oBorder)
|
||||
{
|
||||
m_oStyles.m_oBorder = oBorder;
|
||||
}
|
||||
|
||||
void CStorageTableCell::ClearTopBorder()
|
||||
{
|
||||
m_oStyles.m_oBorder.SetTopSide(L"none", 0, true);
|
||||
}
|
||||
|
||||
void CStorageTableCell::ClearLeftBorder()
|
||||
{
|
||||
m_oStyles.m_oBorder.SetLeftSide(L"none", 0, true);
|
||||
}
|
||||
|
||||
void CStorageTableCell::ClearBottomBorder()
|
||||
{
|
||||
m_oStyles.m_oBorder.SetBottomSide(L"none", 0, true);
|
||||
}
|
||||
|
||||
void CStorageTableCell::ClearRightBorder()
|
||||
{
|
||||
m_oStyles.m_oBorder.SetRightSide(L"none", 0, true);
|
||||
}
|
||||
|
||||
void CStorageTableCell::SetPadding(const NSCSS::NSProperties::CIndent& oPadding)
|
||||
{
|
||||
m_oStyles.m_oPadding = oPadding;
|
||||
}
|
||||
|
||||
void CStorageTableCell::SetHAlign(const std::wstring& wsAlign)
|
||||
{
|
||||
m_oStyles.m_wsHAlign = wsAlign;
|
||||
}
|
||||
|
||||
void CStorageTableCell::SetVAlign(const std::wstring& wsAlign)
|
||||
{
|
||||
m_oStyles.m_wsVAlign = wsAlign;
|
||||
}
|
||||
|
||||
void CStorageTableCell::SetBackground(const NSCSS::NSProperties::CColor& oColor)
|
||||
{
|
||||
m_oStyles.m_oBackground = oColor;
|
||||
}
|
||||
|
||||
CStorageTableRow::CStorageTableRow()
|
||||
{}
|
||||
|
||||
CStorageTableRow::~CStorageTableRow()
|
||||
{
|
||||
for (CStorageTableCell* pCell : m_arCells)
|
||||
RELEASEOBJECT(pCell);
|
||||
}
|
||||
|
||||
void CStorageTableRow::AddCell(CStorageTableCell* pCell)
|
||||
{
|
||||
InsertCell(pCell, -1);
|
||||
}
|
||||
|
||||
void CStorageTableRow::InsertCell(CStorageTableCell* pCell, int nPosition)
|
||||
{
|
||||
if (NULL == pCell)
|
||||
return;
|
||||
|
||||
if (nPosition < 0)
|
||||
{
|
||||
std::vector<CStorageTableCell*>::iterator itFoundEmpty = std::find_if(m_arCells.begin(), m_arCells.end(), [](CStorageTableCell* pCell) { return pCell->Empty() && !pCell->Merged(); });
|
||||
|
||||
if (m_arCells.end() != itFoundEmpty)
|
||||
{
|
||||
--m_oStyles.m_unMaxIndex;
|
||||
delete *itFoundEmpty;
|
||||
*itFoundEmpty = pCell;
|
||||
|
||||
if (1 != pCell->GetColspan())
|
||||
{
|
||||
++itFoundEmpty;
|
||||
UINT unColspan = pCell->GetColspan() - 1;
|
||||
|
||||
while (m_arCells.end() != itFoundEmpty && (*itFoundEmpty)->Empty() && unColspan > 0)
|
||||
{
|
||||
--m_oStyles.m_unMaxIndex;
|
||||
--unColspan;
|
||||
delete (*itFoundEmpty);
|
||||
itFoundEmpty = m_arCells.erase(itFoundEmpty);
|
||||
}
|
||||
|
||||
if (unColspan != 0)
|
||||
pCell->SetColspan(pCell->GetColspan() - unColspan, MAXCOLUMNSINTABLE);
|
||||
}
|
||||
}
|
||||
else
|
||||
m_arCells.push_back(pCell);
|
||||
}
|
||||
else if (nPosition >= m_arCells.size())
|
||||
{
|
||||
const UINT unMissingCount = nPosition - m_arCells.size();
|
||||
|
||||
for (UINT unIndex = 0; unIndex < unMissingCount; ++unIndex)
|
||||
m_arCells.push_back(CStorageTableCell::CreateEmpty());
|
||||
|
||||
m_oStyles.m_unMaxIndex += unMissingCount;
|
||||
|
||||
m_arCells.push_back(pCell);
|
||||
}
|
||||
else if (m_arCells[nPosition]->Empty())
|
||||
{
|
||||
delete m_arCells[nPosition];
|
||||
--m_oStyles.m_unMaxIndex;
|
||||
m_arCells[nPosition] = pCell;
|
||||
|
||||
if (1 != pCell->GetColspan())
|
||||
{
|
||||
++nPosition;
|
||||
UINT unDeleteCount = pCell->GetColspan() - 1;
|
||||
while (nPosition < m_arCells.size() && m_arCells[nPosition]->Empty() && !m_arCells[nPosition]->Merged() && unDeleteCount > 0)
|
||||
{
|
||||
delete m_arCells[nPosition];
|
||||
--m_oStyles.m_unMaxIndex;
|
||||
m_arCells.erase(m_arCells.begin() + nPosition);
|
||||
--unDeleteCount;
|
||||
}
|
||||
|
||||
if (0 != unDeleteCount)
|
||||
pCell->SetColspan(pCell->GetColspan() - unDeleteCount, MAXCOLUMNSINTABLE);
|
||||
}
|
||||
}
|
||||
else
|
||||
m_arCells.insert(m_arCells.begin() + nPosition, pCell);
|
||||
|
||||
m_oStyles.m_unMaxIndex += pCell->GetColspan();
|
||||
|
||||
if (1 == pCell->GetColspan() && 1 == pCell->GetRowspan())
|
||||
m_oStyles.m_unMaxHeight = std::max(m_oStyles.m_unMaxHeight, pCell->GetHeight());
|
||||
}
|
||||
|
||||
UINT CStorageTableRow::GetIndex() const
|
||||
{
|
||||
return m_oStyles.m_unMaxIndex;
|
||||
}
|
||||
|
||||
UINT CStorageTableRow::GetCount() const
|
||||
{
|
||||
return m_arCells.size();
|
||||
}
|
||||
|
||||
CStorageTableCell* CStorageTableRow::operator[](UINT unIndex)
|
||||
{
|
||||
if (unIndex >= m_arCells.size())
|
||||
return NULL;
|
||||
|
||||
return m_arCells[unIndex];
|
||||
}
|
||||
|
||||
bool CStorageTableRow::Empty() const
|
||||
{
|
||||
return m_arCells.empty();
|
||||
}
|
||||
|
||||
const TTableRowStyle& CStorageTableRow::GetStyles() const
|
||||
{
|
||||
return m_oStyles;
|
||||
}
|
||||
|
||||
const std::vector<CStorageTableCell*>& CStorageTableRow::GetCells() const
|
||||
{
|
||||
return m_arCells;
|
||||
}
|
||||
|
||||
CTableCol::CTableCol(UINT unSpan)
|
||||
: m_unSpan(unSpan)
|
||||
{}
|
||||
|
||||
CTableCol::CTableCol(const NSCSS::CNode& oTableColNode)
|
||||
: m_unSpan(1)
|
||||
{
|
||||
m_unSpan = NSStringFinder::ToInt(oTableColNode.GetAttributeValue(L"span"));
|
||||
}
|
||||
|
||||
UINT CTableCol::GetSpan() const
|
||||
{
|
||||
return m_unSpan;
|
||||
}
|
||||
|
||||
TTableCellStyle* CTableCol::GetStyle()
|
||||
{
|
||||
return &m_oStyle;
|
||||
}
|
||||
|
||||
const TTableCellStyle* CTableCol::GetStyle() const
|
||||
{
|
||||
return &m_oStyle;
|
||||
}
|
||||
|
||||
CTableColgroup::CTableColgroup(NSCSS::CNode& oTableColgroupNode)
|
||||
: m_unWidth(0)
|
||||
{
|
||||
m_unWidth = NSStringFinder::ToInt(oTableColgroupNode.GetAttributeValue(L"width"), 0);
|
||||
}
|
||||
|
||||
CTableColgroup::~CTableColgroup()
|
||||
{
|
||||
RELEASE_VECTOR_PTR(m_arCols, CTableCol)
|
||||
}
|
||||
|
||||
bool CTableColgroup::Empty() const
|
||||
{
|
||||
return m_arCols.empty();
|
||||
}
|
||||
|
||||
void CTableColgroup::AddCol(CTableCol* pCol)
|
||||
{
|
||||
if (NULL != pCol)
|
||||
m_arCols.push_back(pCol);
|
||||
}
|
||||
|
||||
const std::vector<CTableCol*>& CTableColgroup::GetCols() const
|
||||
{
|
||||
return m_arCols;
|
||||
}
|
||||
|
||||
TTableStyles::TTableStyles()
|
||||
: m_nCellSpacing(-1), m_enRules(None)
|
||||
{}
|
||||
|
||||
bool TTableStyles::Empty() const
|
||||
{
|
||||
return m_oPadding.Empty() && m_oMargin.Empty() && m_oBorder.Empty() && m_oWidth.Empty() && -1 == m_nCellSpacing && m_wsAlign.empty();
|
||||
}
|
||||
|
||||
CStorageTable::CStorageTable()
|
||||
: m_unMaxColumns(0)
|
||||
{}
|
||||
|
||||
CStorageTable::~CStorageTable()
|
||||
{
|
||||
for (std::vector<CStorageTableRow*>& arHeaders : m_arHeaders)
|
||||
RELEASE_VECTOR_PTR(arHeaders, CStorageTableRow)
|
||||
|
||||
RELEASE_VECTOR_PTR(m_arFoother, CStorageTableRow)
|
||||
RELEASE_VECTOR_PTR(m_arRows, CStorageTableRow)
|
||||
RELEASE_VECTOR_PTR(m_arColgroups, CTableColgroup)
|
||||
}
|
||||
|
||||
CStorageTableRow* CStorageTable::operator[](UINT unIndex)
|
||||
{
|
||||
if (unIndex < m_arRows.size())
|
||||
return m_arRows[unIndex];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CStorageTable::Empty() const
|
||||
{
|
||||
return m_arHeaders.empty() && m_arRows.empty() && m_arFoother.empty();
|
||||
}
|
||||
|
||||
bool CStorageTable::HaveCaption()
|
||||
{
|
||||
return 0 != m_oCaption.GetCurSize();
|
||||
}
|
||||
|
||||
bool CStorageTable::HaveColgroups() const
|
||||
{
|
||||
return !m_arColgroups.empty();
|
||||
}
|
||||
|
||||
bool CStorageTable::HaveHeader() const
|
||||
{
|
||||
return !m_arHeaders.empty();
|
||||
}
|
||||
|
||||
UINT CStorageTable::GetRowCount() const
|
||||
{
|
||||
return m_arRows.size();
|
||||
}
|
||||
|
||||
const TTableStyles& CStorageTable::GetTableStyles() const
|
||||
{
|
||||
return m_oStyles;
|
||||
}
|
||||
|
||||
const TTableCellStyle* CStorageTable::GetColStyle(UINT unColumnNumber) const
|
||||
{
|
||||
if (m_arColgroups.empty())
|
||||
return NULL;
|
||||
|
||||
UINT unCurrentNumber = 0;
|
||||
|
||||
for (const CTableColgroup* pColgroup : m_arColgroups)
|
||||
{
|
||||
for (const CTableCol* pCol : pColgroup->GetCols())
|
||||
{
|
||||
unCurrentNumber += pCol->GetSpan();
|
||||
|
||||
if (unCurrentNumber >= unColumnNumber)
|
||||
return pCol->GetStyle();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CStorageTable::AddRows(std::vector<CStorageTableRow*>& arRows, ERowParseMode eParseMode)
|
||||
{
|
||||
if (arRows.empty())
|
||||
return;
|
||||
|
||||
if (ERowParseMode::Foother == eParseMode && !m_arFoother.empty())
|
||||
eParseMode = ERowParseMode::Header;
|
||||
|
||||
if (ERowParseMode::Header == eParseMode)
|
||||
m_arHeaders.push_back({});
|
||||
|
||||
for (CStorageTableRow* pRow : arRows)
|
||||
AddRow(pRow, eParseMode);
|
||||
}
|
||||
|
||||
void CStorageTable::AddRow(CStorageTableRow* pRow, ERowParseMode eParseMode)
|
||||
{
|
||||
if (NULL == pRow)
|
||||
return;
|
||||
|
||||
for (UINT unIndex = 0; unIndex < pRow->GetCount(); ++unIndex)
|
||||
{
|
||||
if (unIndex >= m_arMinColspan.size())
|
||||
m_arMinColspan.push_back((*pRow)[unIndex]->GetColspan());
|
||||
else if ((*pRow)[unIndex]->GetColspan() < m_arMinColspan[unIndex])
|
||||
m_arMinColspan[unIndex] = (*pRow)[unIndex]->GetColspan();
|
||||
}
|
||||
|
||||
switch (eParseMode)
|
||||
{
|
||||
default:
|
||||
case ERowParseMode::Body:
|
||||
{
|
||||
m_arRows.push_back(pRow);
|
||||
break;
|
||||
}
|
||||
case ERowParseMode::Header:
|
||||
{
|
||||
if (m_arHeaders.empty())
|
||||
m_arHeaders.push_back({});
|
||||
|
||||
m_arHeaders.back().push_back(pRow);
|
||||
break;
|
||||
}
|
||||
case ERowParseMode::Foother:
|
||||
{
|
||||
m_arFoother.push_back(pRow);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSStringUtils::CStringBuilder* CStorageTable::GetCaptionData()
|
||||
{
|
||||
return &m_oCaption;
|
||||
}
|
||||
|
||||
void CStorageTable::SetPadding(const NSCSS::NSProperties::CIndent& oPadding)
|
||||
{
|
||||
m_oStyles.m_oPadding = oPadding;
|
||||
}
|
||||
|
||||
const NSCSS::NSProperties::CIndent& CStorageTable::GetPadding() const
|
||||
{
|
||||
return m_oStyles.m_oPadding;
|
||||
}
|
||||
|
||||
void CStorageTable::SetMargin(const NSCSS::NSProperties::CIndent& oMargin)
|
||||
{
|
||||
m_oStyles.m_oMargin = oMargin;
|
||||
}
|
||||
|
||||
void CStorageTable::SetBorder(const NSCSS::NSProperties::CBorder& oBorder)
|
||||
{
|
||||
m_oStyles.m_oBorder = oBorder;
|
||||
}
|
||||
|
||||
void CStorageTable::SetWidth(const NSCSS::NSProperties::CDigit& oWidth)
|
||||
{
|
||||
m_oStyles.m_oWidth = oWidth;
|
||||
}
|
||||
|
||||
void CStorageTable::SetCellSpacing(int nCellSpacing)
|
||||
{
|
||||
m_oStyles.m_nCellSpacing = nCellSpacing;
|
||||
}
|
||||
|
||||
void CStorageTable::SetAlign(const std::wstring& wsValue)
|
||||
{
|
||||
m_oStyles.m_wsAlign = wsValue;
|
||||
}
|
||||
|
||||
void CStorageTable::SetRules(const std::wstring& wsValue)
|
||||
{
|
||||
if (wsValue.empty())
|
||||
return;
|
||||
|
||||
if (NSStringFinder::Equals(wsValue, L"all"))
|
||||
m_oStyles.m_enRules = TTableStyles::ETableRules::All;
|
||||
else if (NSStringFinder::Equals(wsValue, L"groups"))
|
||||
m_oStyles.m_enRules = TTableStyles::ETableRules::Groups;
|
||||
else if (NSStringFinder::Equals(wsValue, L"cols"))
|
||||
m_oStyles.m_enRules = TTableStyles::ETableRules::Cols;
|
||||
else if (NSStringFinder::Equals(wsValue, L"none"))
|
||||
m_oStyles.m_enRules = TTableStyles::ETableRules::None;
|
||||
else if (NSStringFinder::Equals(wsValue, L"rows"))
|
||||
m_oStyles.m_enRules = TTableStyles::ETableRules::Rows;
|
||||
}
|
||||
|
||||
void CStorageTable::AddColgroup(CTableColgroup* pElement)
|
||||
{
|
||||
if (NULL != pElement)
|
||||
m_arColgroups.push_back(pElement);
|
||||
}
|
||||
|
||||
void CStorageTable::RecalculateMaxColumns()
|
||||
{
|
||||
for (const std::vector<CStorageTableRow*>& arHeaders : m_arHeaders)
|
||||
for (const CStorageTableRow* pHeader : arHeaders)
|
||||
m_unMaxColumns = std::max(m_unMaxColumns, pHeader->GetIndex());
|
||||
|
||||
for (const CStorageTableRow* pRow : m_arRows)
|
||||
m_unMaxColumns = std::max(m_unMaxColumns, pRow->GetIndex());
|
||||
|
||||
for (const CStorageTableRow* pFoother : m_arFoother)
|
||||
m_unMaxColumns = std::max(m_unMaxColumns, pFoother->GetIndex());
|
||||
}
|
||||
|
||||
void CStorageTable::Shorten()
|
||||
{
|
||||
UINT unIndex = 0;
|
||||
CStorageTableCell* pCell = NULL;
|
||||
|
||||
UINT unMaxIndex = 0; //Максимальный индекс без учета строк, где имеется только 1 ячейка
|
||||
|
||||
for (const CStorageTableRow* pRow : m_arRows)
|
||||
{
|
||||
if (1 < pRow->GetCount())
|
||||
unMaxIndex = std::max(unMaxIndex, pRow->GetIndex());
|
||||
}
|
||||
|
||||
while (unIndex < m_arMinColspan.size())
|
||||
{
|
||||
for (CStorageTableRow* pRow : m_arRows)
|
||||
{
|
||||
if (0 != unMaxIndex && 1 == pRow->GetCount() && pRow->GetIndex() > unMaxIndex)
|
||||
{
|
||||
pCell = (*pRow)[unIndex];
|
||||
|
||||
if (NULL == pCell)
|
||||
continue;
|
||||
|
||||
pCell->SetColspan(unMaxIndex, MAXCOLUMNSINTABLE);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (1 == m_arMinColspan[unIndex])
|
||||
break;
|
||||
|
||||
pCell = (*pRow)[unIndex];
|
||||
|
||||
if (NULL == pCell)
|
||||
continue;
|
||||
|
||||
if (1 < pCell->GetColspan() && pCell->GetColspan() > m_arMinColspan[unIndex])
|
||||
{
|
||||
pCell->SetColspan(m_arMinColspan[unIndex], MAXCOLUMNSINTABLE);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((*pRow)[unIndex]->GetColspan() == m_arMinColspan[unIndex] + 1)
|
||||
(*pRow)[unIndex]->SetColspan(2, MAXCOLUMNSINTABLE);
|
||||
else if ((*pRow)[unIndex]->GetColspan() > m_arMinColspan[unIndex])
|
||||
(*pRow)[unIndex]->SetColspan((*pRow)[unIndex]->GetColspan() - m_arMinColspan[unIndex], MAXCOLUMNSINTABLE);
|
||||
}
|
||||
|
||||
++unIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void CStorageTable::CompleteTable()
|
||||
{
|
||||
UINT unMaxIndex = 0;
|
||||
|
||||
for (CStorageTableRow* pRow : m_arRows)
|
||||
unMaxIndex = std::max(unMaxIndex, pRow->GetIndex());
|
||||
|
||||
for (CStorageTableRow* pRow : m_arRows)
|
||||
{
|
||||
if (NULL == pRow || 0 == pRow->GetCount())
|
||||
continue;
|
||||
|
||||
for (UINT unIndex = pRow->GetIndex(); unIndex < unMaxIndex; ++unIndex)
|
||||
pRow->InsertCell(CStorageTableCell::CreateEmpty(), unIndex);
|
||||
}
|
||||
|
||||
RecalculateMaxColumns();
|
||||
}
|
||||
|
||||
const std::vector<std::vector<CStorageTableRow*>>& CStorageTable::GetHeaders() const
|
||||
{
|
||||
return m_arHeaders;
|
||||
}
|
||||
|
||||
const std::vector<CStorageTableRow*>& CStorageTable::GetFoothers() const
|
||||
{
|
||||
return m_arFoother;
|
||||
}
|
||||
|
||||
const std::vector<CStorageTableRow*>& CStorageTable::GetRows() const
|
||||
{
|
||||
return m_arRows;
|
||||
}
|
||||
|
||||
const std::vector<CTableColgroup*> CStorageTable::GetColgroups() const
|
||||
{
|
||||
return m_arColgroups;
|
||||
}
|
||||
|
||||
UINT CStorageTable::GetMaxColumns() const
|
||||
{
|
||||
return m_unMaxColumns;
|
||||
}
|
||||
|
||||
}
|
||||
255
HtmlFile2/Table.h
Normal file
255
HtmlFile2/Table.h
Normal file
@ -0,0 +1,255 @@
|
||||
#ifndef TABLE_H
|
||||
#define TABLE_H
|
||||
|
||||
#include "../DesktopEditor/common/StringBuilder.h"
|
||||
#include "../Common/3dParty/html/css/src/StyleProperties.h"
|
||||
#include "../Common/3dParty/html/css/src/CNode.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace HTML
|
||||
{
|
||||
#define MAXCOLUMNSINTABLE 63
|
||||
#define MAXROWSINTABLE 32767
|
||||
|
||||
enum class ERowParseMode
|
||||
{
|
||||
Header,
|
||||
Body,
|
||||
Foother
|
||||
};
|
||||
|
||||
enum class ERowPosition
|
||||
{
|
||||
First,
|
||||
Middle,
|
||||
Last
|
||||
};
|
||||
|
||||
struct TTableRowStyle
|
||||
{
|
||||
UINT m_unMaxIndex;
|
||||
UINT m_unMaxHeight;
|
||||
bool m_bIsHeader;
|
||||
|
||||
TTableRowStyle();
|
||||
|
||||
bool Empty() const;
|
||||
};
|
||||
|
||||
struct TTableCellStyle
|
||||
{
|
||||
NSCSS::NSProperties::CDigit m_oWidth;
|
||||
NSCSS::NSProperties::CDigit m_oHeight;
|
||||
NSCSS::NSProperties::CBorder m_oBorder;
|
||||
NSCSS::NSProperties::CIndent m_oPadding;
|
||||
NSCSS::NSProperties::CColor m_oBackground;
|
||||
|
||||
std::wstring m_wsHAlign;
|
||||
std::wstring m_wsVAlign;
|
||||
|
||||
TTableCellStyle();
|
||||
|
||||
bool Empty();
|
||||
void Copy(const TTableCellStyle* pTableCellStyle);
|
||||
|
||||
TTableCellStyle& operator+=(const TTableCellStyle* pCellStyle);
|
||||
};
|
||||
|
||||
class CStorageTable;
|
||||
|
||||
class CStorageTableCell
|
||||
{
|
||||
public:
|
||||
CStorageTableCell();
|
||||
CStorageTableCell(UINT unColspan, UINT unRowspan, bool bIsMerged, bool bIsEmpty);
|
||||
CStorageTableCell(CStorageTableCell& oCell);
|
||||
|
||||
bool Empty() const;
|
||||
bool Merged() const;
|
||||
|
||||
CStorageTableCell* Copy();
|
||||
|
||||
static CStorageTableCell* CreateEmpty(UINT unColspan = 1, bool m_bIsMerged = false, const TTableCellStyle* pStyle = NULL);
|
||||
static CStorageTableCell* CreateEmpty(const TTableCellStyle* pStyle);
|
||||
|
||||
void SetColspan(UINT unColspan, UINT unCurrentIndex);
|
||||
UINT GetColspan() const;
|
||||
|
||||
void SetRowspan(UINT unRowspan);
|
||||
UINT GetRowspan() const;
|
||||
|
||||
NSStringUtils::CStringBuilder* GetData();
|
||||
|
||||
const TTableCellStyle* GetStyles() const;
|
||||
TTableCellStyle* GetStyles();
|
||||
|
||||
void SetWidth(const NSCSS::NSProperties::CDigit& oWidth);
|
||||
void SetHeight(const NSCSS::NSProperties::CDigit& oHeight);
|
||||
|
||||
UINT GetWidth() const;
|
||||
UINT GetHeight() const;
|
||||
|
||||
void SetBorder(const NSCSS::NSProperties::CBorder& oBorder);
|
||||
|
||||
void ClearTopBorder();
|
||||
void ClearLeftBorder();
|
||||
void ClearBottomBorder();
|
||||
void ClearRightBorder();
|
||||
|
||||
void SetPadding(const NSCSS::NSProperties::CIndent& oPadding);
|
||||
void SetHAlign(const std::wstring& wsAlign);
|
||||
void SetVAlign(const std::wstring& wsAlign);
|
||||
void SetBackground(const NSCSS::NSProperties::CColor& oColor);
|
||||
private:
|
||||
UINT m_unColspan;
|
||||
UINT m_unRowSpan;
|
||||
|
||||
bool m_bIsMerged;
|
||||
bool m_bIsEmpty;
|
||||
|
||||
TTableCellStyle m_oStyles;
|
||||
NSStringUtils::CStringBuilder m_oData;
|
||||
};
|
||||
|
||||
class CStorageTableRow
|
||||
{
|
||||
public:
|
||||
CStorageTableRow();
|
||||
~CStorageTableRow();
|
||||
|
||||
void AddCell(CStorageTableCell* pCell);
|
||||
void InsertCell(CStorageTableCell *pCell, int nPosition);
|
||||
|
||||
UINT GetIndex() const;
|
||||
UINT GetCount() const;
|
||||
|
||||
CStorageTableCell* operator[](UINT unIndex);
|
||||
|
||||
bool Empty() const;
|
||||
const TTableRowStyle& GetStyles() const;
|
||||
const std::vector<CStorageTableCell*>& GetCells() const;
|
||||
private:
|
||||
TTableRowStyle m_oStyles;
|
||||
std::vector<CStorageTableCell*> m_arCells;
|
||||
};
|
||||
|
||||
class CTableCol
|
||||
{
|
||||
public:
|
||||
CTableCol(UINT unSpan);
|
||||
CTableCol(const NSCSS::CNode& oTableColNode);
|
||||
|
||||
UINT GetSpan() const;
|
||||
TTableCellStyle* GetStyle();
|
||||
const TTableCellStyle* GetStyle() const;
|
||||
private:
|
||||
UINT m_unSpan;
|
||||
TTableCellStyle m_oStyle;
|
||||
};
|
||||
|
||||
class CTableColgroup
|
||||
{
|
||||
public:
|
||||
CTableColgroup(NSCSS::CNode& oTableColgroupNode);
|
||||
~CTableColgroup();
|
||||
|
||||
bool Empty() const;
|
||||
|
||||
void AddCol(CTableCol* pCol);
|
||||
|
||||
const std::vector<CTableCol*>& GetCols() const;
|
||||
private:
|
||||
std::vector<CTableCol*> m_arCols;
|
||||
UINT m_unWidth;
|
||||
};
|
||||
|
||||
//Необходимые стили таблицы
|
||||
struct TTableStyles
|
||||
{
|
||||
NSCSS::NSProperties::CIndent m_oPadding;
|
||||
NSCSS::NSProperties::CIndent m_oMargin;
|
||||
NSCSS::NSProperties::CBorder m_oBorder;
|
||||
NSCSS::NSProperties::CDigit m_oWidth;
|
||||
|
||||
int m_nCellSpacing;
|
||||
|
||||
std::wstring m_wsAlign;
|
||||
|
||||
enum ETableRules
|
||||
{
|
||||
All,
|
||||
Groups,
|
||||
Cols,
|
||||
None,
|
||||
Rows
|
||||
} m_enRules;
|
||||
|
||||
TTableStyles();
|
||||
|
||||
bool Empty() const;
|
||||
};
|
||||
|
||||
class CStorageTable
|
||||
{
|
||||
public:
|
||||
CStorageTable();
|
||||
~CStorageTable();
|
||||
|
||||
CStorageTableRow* operator[](UINT unIndex);
|
||||
|
||||
bool Empty() const;
|
||||
bool HaveCaption();
|
||||
bool HaveColgroups() const;
|
||||
bool HaveHeader() const;
|
||||
UINT GetRowCount() const;
|
||||
const TTableStyles& GetTableStyles() const;
|
||||
const TTableCellStyle* GetColStyle(UINT unColumnNumber) const;
|
||||
|
||||
void AddRows(std::vector<CStorageTableRow*>& m_arRows, ERowParseMode eParseMode = ERowParseMode::Body);
|
||||
void AddRow(CStorageTableRow* pRow, ERowParseMode eParseMode = ERowParseMode::Body);
|
||||
|
||||
NSStringUtils::CStringBuilder* GetCaptionData();
|
||||
|
||||
void SetPadding(const NSCSS::NSProperties::CIndent& oPadding);
|
||||
const NSCSS::NSProperties::CIndent& GetPadding() const;
|
||||
|
||||
void SetMargin(const NSCSS::NSProperties::CIndent& oMargin);
|
||||
void SetBorder(const NSCSS::NSProperties::CBorder& oBorder);
|
||||
|
||||
void SetWidth(const NSCSS::NSProperties::CDigit& oWidth);
|
||||
void SetCellSpacing(int nCellSpacing);
|
||||
void SetAlign(const std::wstring& wsValue);
|
||||
void SetRules(const std::wstring& wsValue);
|
||||
|
||||
void AddColgroup(CTableColgroup* pElement);
|
||||
|
||||
void RecalculateMaxColumns();
|
||||
void Shorten();
|
||||
void CompleteTable();
|
||||
|
||||
//TODO:: переделать на const std::vector<const T*> Get...() const;
|
||||
const std::vector<std::vector<CStorageTableRow*>>& GetHeaders() const;
|
||||
const std::vector<CStorageTableRow*>& GetFoothers() const;
|
||||
const std::vector<CStorageTableRow*>& GetRows() const;
|
||||
const std::vector<CTableColgroup*> GetColgroups() const;
|
||||
|
||||
UINT GetMaxColumns() const;
|
||||
private:
|
||||
std::vector<std::vector<CStorageTableRow*>> m_arHeaders;
|
||||
std::vector<CStorageTableRow*> m_arFoother;
|
||||
std::vector<CStorageTableRow*> m_arRows;
|
||||
|
||||
std::vector<UINT> m_arMinColspan;
|
||||
|
||||
NSStringUtils::CStringBuilder m_oCaption;
|
||||
|
||||
std::vector<CTableColgroup*> m_arColgroups;
|
||||
|
||||
TTableStyles m_oStyles;
|
||||
|
||||
UINT m_unMaxColumns;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TABLE_H
|
||||
90
HtmlFile2/Tags/HTMLTags.h
Normal file
90
HtmlFile2/Tags/HTMLTags.h
Normal file
@ -0,0 +1,90 @@
|
||||
#ifndef HTMLTAGS_H
|
||||
#define HTMLTAGS_H
|
||||
|
||||
#include "../Common/3dParty/html/css/src/CNode.h"
|
||||
#include <boost/any.hpp>
|
||||
|
||||
namespace HTML
|
||||
{
|
||||
class ITag
|
||||
{
|
||||
public:
|
||||
virtual ~ITag() = default;
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) = 0;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) = 0;
|
||||
};
|
||||
|
||||
class CEmptyTag : public ITag
|
||||
{
|
||||
public:
|
||||
virtual ~CEmptyTag() = default;
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any())
|
||||
{
|
||||
return true;
|
||||
};
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) {};
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class CTag : public ITag
|
||||
{
|
||||
protected:
|
||||
T* m_pWriter;
|
||||
public:
|
||||
CTag(T* pWriter)
|
||||
: m_pWriter(pWriter)
|
||||
{}
|
||||
virtual ~CTag() = default;
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) = 0;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) = 0;
|
||||
|
||||
bool ValidWriter() const
|
||||
{
|
||||
return nullptr != m_pWriter;
|
||||
}
|
||||
};
|
||||
|
||||
#define CREATE_TAG(tag_name)\
|
||||
template<class T>\
|
||||
class tag_name : public CTag<T>\
|
||||
{\
|
||||
public:\
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) = 0;\
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) = 0;\
|
||||
}
|
||||
|
||||
CREATE_TAG(CAnchor);
|
||||
CREATE_TAG(CAbbr);
|
||||
CREATE_TAG(CBold);
|
||||
CREATE_TAG(CBidirectional);
|
||||
CREATE_TAG(CBreak);
|
||||
CREATE_TAG(CCenter);
|
||||
CREATE_TAG(CItalic);
|
||||
CREATE_TAG(CKbd);
|
||||
CREATE_TAG(CStrike);
|
||||
CREATE_TAG(CUnderline);
|
||||
CREATE_TAG(CMark);
|
||||
CREATE_TAG(CQuotation);
|
||||
CREATE_TAG(CSup);
|
||||
CREATE_TAG(CSpan);
|
||||
CREATE_TAG(CDD);
|
||||
CREATE_TAG(CPreformatted);
|
||||
CREATE_TAG(CHeader);
|
||||
CREATE_TAG(CDivision);
|
||||
CREATE_TAG(CImage);
|
||||
CREATE_TAG(CFont);
|
||||
CREATE_TAG(CInput);
|
||||
CREATE_TAG(CBaseFont);
|
||||
CREATE_TAG(CBlockquote);
|
||||
CREATE_TAG(CHorizontalRule);
|
||||
CREATE_TAG(CList);
|
||||
CREATE_TAG(CListElement);
|
||||
CREATE_TAG(CCaption);
|
||||
CREATE_TAG(CTable);
|
||||
CREATE_TAG(CTableRow);
|
||||
CREATE_TAG(CTableCell);
|
||||
CREATE_TAG(CCode);
|
||||
CREATE_TAG(CHTML);
|
||||
|
||||
}
|
||||
#endif // HTMLTAGS_H
|
||||
520
HtmlFile2/Tags/MDTags.cpp
Normal file
520
HtmlFile2/Tags/MDTags.cpp
Normal file
@ -0,0 +1,520 @@
|
||||
#include "MDTags.h"
|
||||
|
||||
#include "../src/StringFinder.h"
|
||||
#include "../Table.h"
|
||||
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
namespace HTML
|
||||
{
|
||||
CAnchor<CMDWriter>::CAnchor(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CAnchor<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
m_pWriter->WriteString(L"[");
|
||||
return true;
|
||||
}
|
||||
|
||||
void CAnchor<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return;
|
||||
|
||||
m_pWriter->WriteString(L"]");
|
||||
|
||||
std::wstring wsHref, wsTitle;
|
||||
|
||||
arSelectors.back().GetAttributeValue(L"href", wsHref);
|
||||
arSelectors.back().GetAttributeValue(L"title", wsTitle);
|
||||
|
||||
m_pWriter->WriteString(L'(' + wsHref);
|
||||
|
||||
if (!wsTitle.empty())
|
||||
m_pWriter->WriteString(L" \"" + wsTitle + L'"');
|
||||
|
||||
m_pWriter->WriteString(L")");
|
||||
}
|
||||
|
||||
CBold<CMDWriter>::CBold(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CBold<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
if (m_pWriter->IsBold())
|
||||
return true;
|
||||
|
||||
m_pWriter->WriteOpenSpecialString(L"**");
|
||||
m_pWriter->EnteredBold();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBold<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter() || !m_pWriter->IsBold())
|
||||
return;
|
||||
|
||||
m_pWriter->WriteCloseSpecialString(L"**");
|
||||
m_pWriter->OutBold();
|
||||
}
|
||||
|
||||
CBreak<CMDWriter>::CBreak(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CBreak<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
m_pWriter->WriteBreakLine();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBreak<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{}
|
||||
|
||||
CItalic<CMDWriter>::CItalic(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CItalic<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
if (m_pWriter->IsItalic())
|
||||
return true;
|
||||
|
||||
m_pWriter->WriteOpenSpecialString(L"*");
|
||||
m_pWriter->EnteredItalic();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CItalic<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter() || !m_pWriter->IsItalic())
|
||||
return;
|
||||
|
||||
m_pWriter->WriteCloseSpecialString(L"*");
|
||||
m_pWriter->OutItalic();
|
||||
}
|
||||
|
||||
CStrike<CMDWriter>::CStrike(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CStrike<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
if (m_pWriter->IsStrike())
|
||||
return true;
|
||||
|
||||
m_pWriter->WriteOpenSpecialString(L"~~");
|
||||
m_pWriter->EnteredStrike();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CStrike<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter() || !m_pWriter->IsStrike())
|
||||
return;
|
||||
|
||||
m_pWriter->WriteCloseSpecialString(L"~~");
|
||||
m_pWriter->OutStrike();
|
||||
}
|
||||
|
||||
CQuotation<CMDWriter>::CQuotation(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CQuotation<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CQuotation<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{}
|
||||
|
||||
CPreformatted<CMDWriter>::CPreformatted(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CPreformatted<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
m_pWriter->WriteOpenSpecialString(L"```");
|
||||
m_pWriter->EnteredPreformatted();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPreformatted<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return;
|
||||
|
||||
bool bNeedBreakLine{false};
|
||||
|
||||
for (std::vector<NSCSS::CNode>::const_reverse_iterator itElement{arSelectors.crbegin()}; itElement < arSelectors.crend(); ++itElement)
|
||||
{
|
||||
if (L"pre" == itElement->m_wsName)
|
||||
{
|
||||
bNeedBreakLine = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bNeedBreakLine && !m_pWriter->InTable())
|
||||
m_pWriter->WriteBreakLine();
|
||||
|
||||
m_pWriter->WriteCloseSpecialString(L"```");
|
||||
m_pWriter->OutPreformatted();
|
||||
|
||||
if (bNeedBreakLine && !m_pWriter->InTable())
|
||||
m_pWriter->WriteBreakLine(false);
|
||||
}
|
||||
|
||||
CHeader<CMDWriter>::CHeader(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CHeader<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
switch(arSelectors.back().m_wsName[1])
|
||||
{
|
||||
case L'1' : m_pWriter->WriteString(L"# ", true); break;
|
||||
case L'2' : m_pWriter->WriteString(L"## ", true); break;
|
||||
case L'3' : m_pWriter->WriteString(L"### ", true); break;
|
||||
case L'4' : m_pWriter->WriteString(L"#### ", true); break;
|
||||
case L'5' : m_pWriter->WriteString(L"##### ", true); break;
|
||||
case L'6' : m_pWriter->WriteString(L"###### ", true); break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CHeader<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return;
|
||||
}
|
||||
|
||||
CImage<CMDWriter>::CImage(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CImage<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
std::wstring wsAlt, wsSrc, wsTitle;
|
||||
|
||||
if (!arSelectors.back().GetAttributeValue(L"src", wsSrc) &&
|
||||
!arSelectors.back().GetAttributeValue(L"alt", wsAlt))
|
||||
return false;
|
||||
|
||||
arSelectors.back().GetAttributeValue(L"title", wsTitle);
|
||||
|
||||
m_pWriter->WriteString(L";
|
||||
|
||||
if (!wsTitle.empty())
|
||||
m_pWriter->WriteString(L" \"" + wsTitle + L'"');
|
||||
|
||||
m_pWriter->WriteString(L")");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CImage<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return;
|
||||
|
||||
m_pWriter->WriteBreakLine();
|
||||
}
|
||||
|
||||
CHorizontalRule<CMDWriter>::CHorizontalRule(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CHorizontalRule<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
m_pWriter->WriteBreakLine(false);
|
||||
m_pWriter->WriteString(L"---");
|
||||
m_pWriter->WriteBreakLine(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CHorizontalRule<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{}
|
||||
|
||||
CBlockquote<CMDWriter>::CBlockquote(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CBlockquote<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
m_pWriter->WriteBreakLine();
|
||||
m_pWriter->EnteredBlockquote();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBlockquote<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return;
|
||||
|
||||
m_pWriter->OutBlockquote();
|
||||
m_pWriter->WriteBreakLine();
|
||||
m_pWriter->WriteBreakLine(false);
|
||||
}
|
||||
|
||||
CTable<CMDWriter>::CTable(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CTable<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter() /*|| m_pWriter->InTable()*/) //В MD не поддерживаются вложенные таблицы (пока разруливаем в парсере)
|
||||
return false;
|
||||
|
||||
m_pWriter->WriteBreakLine();
|
||||
m_pWriter->EnteredTable();
|
||||
|
||||
if (m_pWriter->InCode())
|
||||
{
|
||||
if (!m_pWriter->InPreformatted())
|
||||
m_pWriter->WriteCloseSpecialString(L"`");
|
||||
|
||||
m_pWriter->OutCode();
|
||||
}
|
||||
|
||||
if (m_pWriter->InPreformatted())
|
||||
{
|
||||
m_pWriter->WriteBreakLine();
|
||||
m_pWriter->WriteCloseSpecialString(L"```");
|
||||
m_pWriter->WriteBreakLine(false);
|
||||
m_pWriter->OutPreformatted();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTable<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return;
|
||||
|
||||
m_pWriter->OutTable();
|
||||
m_pWriter->WriteBreakLine();
|
||||
}
|
||||
|
||||
CTableRow<CMDWriter>::CTableRow(CMDWriter* pWriter)
|
||||
: CTag(pWriter), m_unLastRowType(static_cast<UINT>(ERowParseMode::Foother))
|
||||
{}
|
||||
|
||||
bool CTableRow<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
using DataForRow = boost::tuple<const TTableRowStyle*, const CStorageTable&, ERowParseMode, ERowPosition>;
|
||||
|
||||
if (!ValidWriter() || oExtraData.empty() || typeid(DataForRow) != oExtraData.type())
|
||||
return false;
|
||||
|
||||
m_pWriter->EnteredTable();
|
||||
|
||||
const DataForRow& oDataForRow(boost::any_cast<DataForRow>(oExtraData));
|
||||
const CStorageTable& oStorageTable{boost::get<1>(oDataForRow)};
|
||||
|
||||
if (nullptr == boost::get<0>(oDataForRow) && ERowParseMode::Header == boost::get<2>(oDataForRow))
|
||||
{
|
||||
for (UINT unIndex = 0; unIndex < oStorageTable.GetMaxColumns(); ++unIndex)
|
||||
m_pWriter->WriteOpenSpecialString(L"| ");
|
||||
|
||||
m_pWriter->WriteOpenSpecialString(L"|");
|
||||
m_pWriter->WriteBreakLine();
|
||||
m_unLastRowType = static_cast<UINT>(ERowParseMode::Header);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_unLastRowType == static_cast<UINT>(ERowParseMode::Header))
|
||||
{
|
||||
for (UINT unIndex = 0; unIndex < oStorageTable.GetMaxColumns(); ++unIndex)
|
||||
m_pWriter->WriteString(L"|-");
|
||||
|
||||
m_pWriter->WriteOpenSpecialString(L"|");
|
||||
m_pWriter->WriteBreakLine(false);
|
||||
}
|
||||
|
||||
m_pWriter->WriteOpenSpecialString(L"| ");
|
||||
m_unLastRowType = static_cast<UINT>(boost::get<2>(oDataForRow));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTableRow<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return;
|
||||
|
||||
m_pWriter->WriteBreakLine(false);
|
||||
}
|
||||
|
||||
CTableCell<CMDWriter>::CTableCell(CMDWriter* pWriter)
|
||||
: CTag(pWriter), m_unNeedEmptyCells(0)
|
||||
{}
|
||||
|
||||
bool CTableCell<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
using DataForCell = boost::tuple<const CStorageTableCell&, const CStorageTable&, UINT, ERowParseMode, ERowPosition>;
|
||||
|
||||
if (!ValidWriter() || oExtraData.empty() || typeid(DataForCell) != oExtraData.type())
|
||||
return false;
|
||||
|
||||
const DataForCell& oDataForCell{boost::any_cast<const DataForCell>(oExtraData)};
|
||||
|
||||
m_unNeedEmptyCells = boost::get<0>(oDataForCell).GetColspan() - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTableCell<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return;
|
||||
|
||||
for (UINT unIndex = 0; unIndex < m_unNeedEmptyCells; ++unIndex)
|
||||
m_pWriter->WriteOpenSpecialString(L" |");
|
||||
|
||||
m_unNeedEmptyCells = 0;
|
||||
m_pWriter->WriteOpenSpecialString(L" | ");
|
||||
}
|
||||
|
||||
CList<CMDWriter>::CList(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CList<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
m_pWriter->WriteBreakLine();
|
||||
m_pWriter->EnteredList(L"ol" == arSelectors.back().m_wsName);
|
||||
|
||||
if (!m_pWriter->InOrederedList())
|
||||
return true;
|
||||
|
||||
std::wstring wsIndex;
|
||||
|
||||
if (arSelectors.back().GetAttributeValue(L"start", wsIndex))
|
||||
m_pWriter->SetIndexOrderedList(NSStringFinder::ToInt(wsIndex, 1));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CList<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return;
|
||||
|
||||
m_pWriter->OutList();
|
||||
}
|
||||
|
||||
CListElement<CMDWriter>::CListElement(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CListElement<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
if (0 != m_pWriter->GetLevelList())
|
||||
{
|
||||
for (UINT unLevelList = 0; unLevelList < m_pWriter->GetLevelList() - 1; ++unLevelList)
|
||||
m_pWriter->WriteString(L" ");
|
||||
}
|
||||
|
||||
if (m_pWriter->InOrederedList())
|
||||
{
|
||||
m_pWriter->WriteString(std::to_wstring(m_pWriter->GetIndexOrderedList()) + m_pWriter->GetParametrs().m_wchOrderedList + L' ');
|
||||
m_pWriter->IncreaseIndexOrderedList();
|
||||
}
|
||||
else
|
||||
m_pWriter->WriteString({m_pWriter->GetParametrs().m_wchUnorderedList, L' '});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CListElement<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{}
|
||||
|
||||
CCode<CMDWriter>::CCode(CMDWriter* pWriter)
|
||||
: CTag(pWriter)
|
||||
{}
|
||||
|
||||
bool CCode<CMDWriter>::Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return false;
|
||||
|
||||
m_pWriter->EnteredCode();
|
||||
|
||||
if (m_pWriter->InPreformatted())
|
||||
{
|
||||
if (!arSelectors.back().m_wsClass.empty() && arSelectors.back().m_wsClass.size() >= 9 &&
|
||||
0 == arSelectors.back().m_wsClass.compare(0, 9, L"language-"))
|
||||
m_pWriter->WriteString(arSelectors.back().m_wsClass.substr(9, arSelectors.back().m_wsClass.size() - 9));
|
||||
m_pWriter->WriteBreakLine(false);
|
||||
}
|
||||
else
|
||||
m_pWriter->WriteOpenSpecialString(L"`");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCode<CMDWriter>::Close(const std::vector<NSCSS::CNode>& arSelectors)
|
||||
{
|
||||
if (!ValidWriter())
|
||||
return;
|
||||
|
||||
if (!m_pWriter->InPreformatted())
|
||||
m_pWriter->WriteCloseSpecialString(L"`");
|
||||
|
||||
m_pWriter->OutCode();
|
||||
}
|
||||
}
|
||||
165
HtmlFile2/Tags/MDTags.h
Normal file
165
HtmlFile2/Tags/MDTags.h
Normal file
@ -0,0 +1,165 @@
|
||||
#ifndef MDTAGS_H
|
||||
#define MDTAGS_H
|
||||
|
||||
#include "HTMLTags.h"
|
||||
#include "../Writers/MDWriter.h"
|
||||
|
||||
namespace HTML
|
||||
{
|
||||
template<>
|
||||
class CAnchor<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CAnchor(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CBold<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CBold(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CBreak<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CBreak(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CItalic<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CItalic(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CStrike<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CStrike(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CQuotation<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CQuotation(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CPreformatted<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CPreformatted(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CHeader<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CHeader(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CImage<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CImage(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CHorizontalRule<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CHorizontalRule(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CBlockquote<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CBlockquote(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CTable<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CTable(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CTableRow<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
UINT m_unLastRowType;
|
||||
public:
|
||||
CTableRow(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CTableCell<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
UINT m_unNeedEmptyCells;
|
||||
public:
|
||||
CTableCell(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CList<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CList(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CListElement<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CListElement(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CCode<CMDWriter> : public CTag<CMDWriter>
|
||||
{
|
||||
public:
|
||||
CCode(CMDWriter* pWriter);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MDTAGS_H
|
||||
1492
HtmlFile2/Tags/OOXMLTags.cpp
Normal file
1492
HtmlFile2/Tags/OOXMLTags.cpp
Normal file
File diff suppressed because it is too large
Load Diff
167
HtmlFile2/Tags/OOXMLTags.h
Normal file
167
HtmlFile2/Tags/OOXMLTags.h
Normal file
@ -0,0 +1,167 @@
|
||||
#ifndef OOXMLTAGS_H
|
||||
#define OOXMLTAGS_H
|
||||
|
||||
#include "HTMLTags.h"
|
||||
#include "../Writers/OOXMLWriter.h"
|
||||
|
||||
namespace HTML
|
||||
{
|
||||
template<>
|
||||
class CAnchor<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CAnchor(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CAbbr<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CAbbr(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CBreak<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CBreak(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CDivision<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
std::stack<UINT> m_arFootnoteIDs;
|
||||
public:
|
||||
CDivision(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CImage<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
std::vector<std::wstring> m_arrImages;
|
||||
public:
|
||||
CImage(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CFont<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CFont(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CInput<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CInput(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CBaseFont<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CBaseFont(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CBlockquote<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
std::map<std::wstring, UINT> m_mDivs;
|
||||
public:
|
||||
CBlockquote(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CHorizontalRule<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
UINT m_unShapeId;
|
||||
public:
|
||||
CHorizontalRule(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CList<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CList(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CListElement<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CListElement(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CCaption<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CCaption(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CTable<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CTable(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CTableRow<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CTableRow(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CTableCell<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CTableCell(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
|
||||
template<>
|
||||
class CHTML<COOXMLWriter> : public CTag<COOXMLWriter>
|
||||
{
|
||||
public:
|
||||
CHTML(COOXMLWriter* pInterpretator);
|
||||
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors, const boost::any& oExtraData = boost::any()) override;
|
||||
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OOXMLTAGS_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user