Added reading of custom fonts in svg

This commit is contained in:
Kirill Polyakov
2024-06-25 15:51:04 +03:00
parent 2f45e0952e
commit 6ae6c37ef1
16 changed files with 452 additions and 243 deletions

View File

@ -141,7 +141,9 @@ namespace NS_STATIC_FUNCTIONS
while (std::wstring::npos != unEnd)
{
arWords.emplace_back(wsLine.data() + unStart, unEnd - unStart + ((bWithSigns) ? 1 : 0));
if (unStart != unEnd)
arWords.emplace_back(wsLine.data() + unStart, unEnd - unStart + ((bWithSigns) ? 1 : 0));
unStart = wsLine.find_first_not_of(wsDelimiters, unEnd);
unEnd = wsLine.find_first_of(wsDelimiters, unStart);
}

View File

@ -459,37 +459,88 @@ namespace NSCSS
return std::wstring(arTemp, 6);
}
std::wstring CColor::CutURL(const std::wstring &wsValue)
{
if (wsValue.length() < 6)
return std::wstring();
CColor::CColor()
: CValue(NULL, 0, false), m_oOpacity(1.)
{}
size_t unBegin = wsValue.find(L"(#");
if (std::wstring::npos == unBegin || unBegin < 3 || wsValue.length() - unBegin < 2)
return std::wstring();
std::wstring wsCopyValue(wsValue);
std::transform(wsCopyValue.begin(), wsCopyValue.begin() + unBegin, wsCopyValue.begin(), std::towlower);
if (std::wstring::npos == wsCopyValue.find(L"url(#"))
return std::wstring();
return wsCopyValue.substr(unBegin + 2, wsCopyValue.find(L')') - unBegin - 2);
}
void CColor::SetEmpty(unsigned int unLevel)
{
m_oValue.Clear();
m_oValue.m_enType = ColorEmpty;
Clear();
m_enType = ColorEmpty;
m_unLevel = unLevel;
m_bImportant = false;
}
void CColor::SetRGB(unsigned char uchR, unsigned char uchG, unsigned char uchB)
{
Clear();
CColor::CColor()
: CValue({}, 0, false), m_oOpacity(1.)
{}
m_oValue = new TRGB{uchR, uchG, uchB};
if (NULL == m_oValue)
return;
m_enType = ColorRGB;
}
void CColor::SetRGB(const TRGB &oRGB)
{
Clear();
m_oValue = new TRGB{oRGB};
if (NULL == m_oValue)
return;
m_enType = ColorRGB;
}
void CColor::SetHEX(const std::wstring &wsValue)
{
Clear();
if (6 != wsValue.length() && 3 != wsValue.length())
return;
if (6 == wsValue.length())
m_oValue = new std::wstring(wsValue);
else
m_oValue = new std::wstring({wsValue[0], wsValue[0], wsValue[1], wsValue[1], wsValue[2], wsValue[2]});
if (NULL == m_oValue)
return;
m_enType = ColorHEX;
}
void CColor::SetUrl(const std::wstring &wsValue)
{
Clear();
if (wsValue.empty())
return;
CURL *pURL = new CURL();
if (NULL == pURL)
return;
if (!pURL->SetValue(wsValue))
{
delete pURL;
return;
}
m_oValue = pURL;
m_enType = ColorUrl;
}
void CColor::SetNone()
{
Clear();
m_enType = ColorNone;
}
bool CColor::SetValue(const std::wstring &wsValue, unsigned int unLevel, bool bHardMode)
{
@ -513,21 +564,21 @@ namespace NSCSS
if (wsNewValue[0] == L'#')
{
m_oValue.SetHEX(wsNewValue.substr(1, wsNewValue.length() - 1));
SetHEX(wsNewValue.substr(1, wsNewValue.length() - 1));
m_unLevel = unLevel;
m_bImportant = bImportant;
return true;
}
else if (L"none" == wsNewValue)
{
m_oValue.SetNone();
SetNone();
m_unLevel = unLevel;
m_bImportant = bImportant;
return true;
}
else if (wsNewValue == L"transparent")
{
m_oValue.SetNone();
SetNone();
m_unLevel = unLevel;
m_bImportant = bImportant;
return true;
@ -558,7 +609,7 @@ namespace NSCSS
if (255 < nGreen) nGreen = 255;
if (255 < nBlue) nBlue = 255;
m_oValue.SetRGB(nRed, nGreen, nBlue);
SetRGB(nRed, nGreen, nBlue);
if (wsNewValue.substr(0, 4) == L"rgba" && 4 == arValues.size())
m_oOpacity.SetValue(arValues[3], unLevel, bHardMode);
@ -570,9 +621,9 @@ namespace NSCSS
if (5 <= wsNewValue.length())
{
m_oValue.SetUrl(CutURL(wsValue));
SetUrl(wsValue);
if (m_oValue.m_enType == ColorUrl)
if (m_enType == ColorUrl)
{
m_unLevel = unLevel;
m_bImportant = bImportant;;
@ -583,7 +634,7 @@ namespace NSCSS
const std::map<std::wstring, std::wstring>::const_iterator oHEX = NSConstValues::COLORS.find(wsNewValue);
if (oHEX != NSConstValues::COLORS.end())
{
m_oValue.SetHEX(oHEX->second);
SetHEX(oHEX->second);
m_unLevel = unLevel;
m_bImportant = bImportant;
return true;
@ -602,29 +653,53 @@ namespace NSCSS
bool CColor::Empty() const
{
return m_oValue.Empty();
return ColorEmpty == m_enType;
}
bool CColor::None() const
{
return ColorNone == m_oValue.m_enType;
return ColorNone == m_enType;
}
bool CColor::Url() const
{
return ColorUrl == m_oValue.m_enType;
return ColorUrl == m_enType;
}
void CColor::Clear()
{
m_oValue.Clear();
switch (m_enType)
{
case ColorRGB:
{
TRGB *pRGB = static_cast<TRGB*>(m_oValue);
RELEASEOBJECT(pRGB);
break;
}
case ColorHEX:
{
std::wstring* pValue = static_cast<std::wstring*>(m_oValue);
RELEASEOBJECT(pValue);
break;
}
case ColorUrl:
{
CURL *pURL = static_cast<CURL*>(m_oValue);
RELEASEOBJECT(pURL);
break;
}
default:
break;
}
m_enType = ColorEmpty;
m_unLevel = NULL;
m_bImportant = false;
}
ColorType CColor::GetType() const
{
return m_oValue.m_enType;
return m_enType;
}
double CColor::GetOpacity() const
@ -643,16 +718,16 @@ namespace NSCSS
int CColor::ToInt() const
{
switch(m_oValue.m_enType)
switch(m_enType)
{
case ColorRGB:
{
TRGB* pRGB = static_cast<TRGB*>(m_oValue.m_pColor);
TRGB* pRGB = static_cast<TRGB*>(m_oValue);
return RGB_TO_INT(pRGB->uchRed, pRGB->uchGreen, pRGB->uchBlue);
}
case ColorHEX:
{
std::wstring *pValue = static_cast<std::wstring*>(m_oValue.m_pColor);
std::wstring *pValue = static_cast<std::wstring*>(m_oValue);
TRGB oRGB = ConvertHEXtoRGB(*pValue);
return RGB_TO_INT(oRGB.uchRed, oRGB.uchGreen, oRGB.uchBlue);
}
@ -668,10 +743,11 @@ namespace NSCSS
std::wstring CColor::ToWString() const
{
switch(m_oValue.m_enType)
switch(m_enType)
{
case ColorRGB: return ConvertRGBtoHEX(*static_cast<TRGB*>(m_oValue.m_pColor));
case ColorHEX: case ColorUrl: return *static_cast<std::wstring*>(m_oValue.m_pColor);
case ColorRGB: return ConvertRGBtoHEX(*static_cast<TRGB*>(m_oValue));
case ColorHEX: return *static_cast<std::wstring*>(m_oValue);
case ColorUrl: return static_cast<CURL*>(m_oValue)->GetValue();
default: return std::wstring();
}
}
@ -683,10 +759,10 @@ namespace NSCSS
TRGB oCurrentColor;
switch(m_oValue.m_enType)
switch(m_enType)
{
case ColorRGB: oCurrentColor = *static_cast<TRGB*>(m_oValue.m_pColor); break;
case ColorHEX: oCurrentColor = ConvertHEXtoRGB(*static_cast<std::wstring*>(m_oValue.m_pColor)); break;
case ColorRGB: oCurrentColor = *static_cast<TRGB*>(m_oValue); break;
case ColorHEX: oCurrentColor = ConvertHEXtoRGB(*static_cast<std::wstring*>(m_oValue)); break;
default: return L"none";
}
@ -710,10 +786,10 @@ namespace NSCSS
TRGB CColor::ToRGB() const
{
switch(m_oValue.m_enType)
switch(m_enType)
{
case ColorRGB: return *static_cast<TRGB*>(m_oValue.m_pColor);
case ColorHEX: return ConvertHEXtoRGB(*static_cast<std::wstring*>(m_oValue.m_pColor));
case ColorRGB: return *static_cast<TRGB*>(m_oValue);
case ColorHEX: return ConvertHEXtoRGB(*static_cast<std::wstring*>(m_oValue));
default: return TRGB();
}
}
@ -2421,175 +2497,48 @@ namespace NSCSS
m_oWeight == oFont.m_oWeight;
}
CColorValue::CColorValue()
: m_enType(ColorEmpty), m_pColor(NULL)
CURL::CURL()
{}
CColorValue::CColorValue(const CColorValue &oColorValue)
: m_enType()
bool CURL::Empty() const
{
switch(oColorValue.m_enType)
{
case ColorRGB: SetRGB(*static_cast<TRGB*>(oColorValue.m_pColor)); break;
case ColorHEX: SetHEX(*static_cast<std::wstring*>(oColorValue.m_pColor)); break;
case ColorUrl: SetUrl(*static_cast<std::wstring*>(oColorValue.m_pColor)); break;
default: m_enType = oColorValue.m_enType; break;
}
return m_wsValue.empty();
}
CColorValue::~CColorValue()
bool CURL::LinkToId() const
{
Clear();
return m_wsValue.length() > 1 && L'#' == m_wsValue.front();
}
void CURL::Clear()
{
m_wsValue.clear();
}
void CColorValue::SetRGB(unsigned char uchR, unsigned char uchG, unsigned char uchB)
bool CURL::SetValue(const std::wstring &wsValue)
{
Clear();
m_pColor = new TRGB{uchR, uchG, uchB};
if (NULL == m_pColor)
{
m_enType = ColorEmpty;
return;
}
m_enType = ColorRGB;
}
void CColorValue::SetRGB(const TRGB &oRGB)
{
Clear();
m_pColor = new TRGB{oRGB};
if (NULL == m_pColor)
{
m_enType = ColorEmpty;
return;
}
m_enType = ColorRGB;
}
void CColorValue::SetHEX(const std::wstring &wsValue)
{
Clear();
if (6 != wsValue.length() && 3 != wsValue.length())
{
m_enType = ColorEmpty;
return;
}
if (6 == wsValue.length())
m_pColor = new std::wstring(wsValue);
else
m_pColor = new std::wstring({wsValue[0], wsValue[0], wsValue[1], wsValue[1], wsValue[2], wsValue[2]});
if (NULL == m_pColor)
{
m_enType = ColorEmpty;
return;
}
m_enType = ColorHEX;
}
void CColorValue::SetUrl(const std::wstring &wsValue)
{
Clear();
m_pColor = new std::wstring(wsValue);
if (NULL == m_pColor || ((std::wstring*)m_pColor)->empty())
{
m_enType = ColorEmpty;
return;
}
m_enType = ColorUrl;
}
void CColorValue::SetNone()
{
Clear();
m_enType = ColorNone;
}
bool CColorValue::Empty() const
{
return ColorEmpty == m_enType;
}
std::wstring CColorValue::GetColor() const
{
return *(std::wstring*)m_pColor;
}
bool CColorValue::operator==(const CColorValue &oColorValue) const
{
if (m_enType != oColorValue.m_enType)
if (wsValue.empty())
return false;
if (ColorEmpty == m_enType ||
ColorNone == m_enType)
return true;
std::wregex oRegex(L"url\\s*\\(\\s*(?:'|\"|)([#]?[^'\"()]+)(?:'|\"|)\\s*\\)");
std::wsmatch oMatch;
switch (m_enType)
{
case ColorRGB:
return *static_cast<TRGB*>(m_pColor) == *static_cast<TRGB*>(oColorValue.m_pColor);
case ColorHEX:
case ColorUrl:
return *static_cast<std::wstring*>(m_pColor) == *static_cast<std::wstring*>(oColorValue.m_pColor);
default:
break;
}
if (!std::regex_search(wsValue.cbegin(), wsValue.cend(), oMatch, oRegex) || oMatch[1].str().empty())
return false;
return false;
m_wsValue = oMatch[1].str();
NS_STATIC_FUNCTIONS::RemoveSpaces(m_wsValue);
return true;
}
CColorValue &CColorValue::operator=(const CColorValue &oColorValue)
std::wstring CURL::GetValue() const
{
switch(oColorValue.m_enType)
{
case ColorRGB: SetRGB(*static_cast<TRGB*>(oColorValue.m_pColor)); break;
case ColorHEX: SetHEX(*static_cast<std::wstring*>(oColorValue.m_pColor)); break;
case ColorUrl: SetUrl(*static_cast<std::wstring*>(oColorValue.m_pColor)); break;
default: m_enType = oColorValue.m_enType; break;
}
return *this;
}
void CColorValue::Clear()
{
switch (m_enType)
{
case ColorRGB:
{
TRGB *pRGB = static_cast<TRGB*>(m_pColor);
RELEASEOBJECT(pRGB);
break;
}
case ColorHEX: case ColorUrl:
{
std::wstring* pValue = static_cast<std::wstring*>(m_pColor);
RELEASEOBJECT(pValue);
break;
}
default:
break;
}
m_enType = ColorEmpty;
return m_wsValue;
}
CEnum::CEnum()
: CValue(INT_MAX, 0, false){}
: CValue(INT_MAX, 0, false){}
bool CEnum::SetValue(const std::wstring &wsValue, unsigned int unLevel, bool bHardMode)
{
@ -2726,5 +2675,6 @@ namespace NSCSS
{
return m_oHeader;
}
}
}

View File

@ -21,6 +21,7 @@ namespace NSCSS
friend class CDigit;
friend class CColor;
friend class CEnum;
friend class CURL;
T m_oValue;
unsigned int m_unLevel;
@ -180,6 +181,22 @@ namespace NSCSS
bool operator==(const TRGB& oRGB) const;
};
class CURL
{
public:
CURL();
bool Empty() const;
bool LinkToId() const;
void Clear();
bool SetValue(const std::wstring& wsValue);
std::wstring GetValue() const;
private:
std::wstring m_wsValue;
};
typedef enum
{
ColorEmpty,
@ -189,39 +206,8 @@ namespace NSCSS
ColorUrl
} ColorType;
class Q_DECL_EXPORT CColorValue
class CColor : public CValue<void*>
{
public:
CColorValue();
CColorValue(const CColorValue& oColorValue);
~CColorValue();
void SetRGB(unsigned char uchR, unsigned char uchG, unsigned char uchB);
void SetRGB(const TRGB& oRGB);
void SetHEX(const std::wstring& wsValue);
void SetUrl(const std::wstring& wsValue);
void SetNone();
void Clear();
bool Empty() const;
ColorType m_enType;
void* m_pColor = NULL;
std::wstring GetColor() const;
bool operator==(const CColorValue& oColorValue) const;
CColorValue& operator= (const CColorValue& oColorValue);
};
class CColor : public CValue<CColorValue>
{
CDigit m_oOpacity;
static TRGB ConvertHEXtoRGB(const std::wstring& wsValue);
static std::wstring ConvertRGBtoHEX(const TRGB& oValue);
static std::wstring CutURL(const std::wstring& wsValue);
void SetEmpty(unsigned int unLevel = 0);
public:
CColor();
@ -242,6 +228,19 @@ namespace NSCSS
std::wstring ToWString() const override;
std::wstring EquateToColor(const std::vector<std::pair<TRGB, std::wstring>>& arColors) const;
TRGB ToRGB() const;
static TRGB ConvertHEXtoRGB(const std::wstring& wsValue);
static std::wstring ConvertRGBtoHEX(const TRGB& oValue);
private:
CDigit m_oOpacity;
ColorType m_enType;
void SetEmpty(unsigned int unLevel = 0);
void SetRGB(unsigned char uchR, unsigned char uchG, unsigned char uchB);
void SetRGB(const TRGB& oRGB);
void SetHEX(const std::wstring& wsValue);
void SetUrl(const std::wstring& wsValue);
void SetNone();
};
typedef enum

View File

@ -116,6 +116,7 @@ METAFILE_PATH = $$PWD/../../raster/Metafile
$$METAFILE_PATH/svg/SvgObjects/CText.h \
$$METAFILE_PATH/svg/SvgObjects/CUse.h \
$$METAFILE_PATH/svg/SvgObjects/CPolyline.h \
$$METAFILE_PATH/svg/SvgObjects/CFont.h \
$$METAFILE_PATH/svg/SvgObjects/CStyle.h \
$$METAFILE_PATH/svg/SvgObjects/CObjectBase.h \
$$METAFILE_PATH/svg/SvgUtils.h
@ -139,6 +140,7 @@ METAFILE_PATH = $$PWD/../../raster/Metafile
$$METAFILE_PATH/svg/SvgObjects/CText.cpp \
$$METAFILE_PATH/svg/SvgObjects/CUse.cpp \
$$METAFILE_PATH/svg/SvgObjects/CPolyline.cpp \
$$METAFILE_PATH/svg/SvgObjects/CFont.cpp \
$$METAFILE_PATH/svg/SvgObjects/CObjectBase.cpp \
$$METAFILE_PATH/svg/SvgObjects/CStyle.cpp

View File

@ -1,6 +1,7 @@
#include "CSvgFile.h"
#include "SvgObjects/CContainer.h"
#include "SvgObjects/CFont.h"
#define SVG_FILE_WIDTH 300
#define SVG_FILE_HEIGHT 150
@ -132,6 +133,16 @@ SVG::CObject *CSvgFile::GetMarkedObject(const std::wstring &wsId) const
return NULL;
}
SVG::CFont *CSvgFile::GetFont(const std::wstring &wsFontFamily) const
{
FontsFaceMap::const_iterator itFound = std::find_if(m_mFontsFace.cbegin(), m_mFontsFace.cend(), [&wsFontFamily](const std::pair<std::wstring, std::wstring>& oValue){ return wsFontFamily == oValue.first; });
if (m_mFontsFace.cend() == itFound)
return NULL;
return dynamic_cast<SVG::CFont*>(GetMarkedObject(itFound->second));
}
std::wstring CSvgFile::GetWorkingDirectory() const
{
return m_wsWorkingDirectory;
@ -142,6 +153,11 @@ void CSvgFile::AddStyles(const std::wstring &wsStyles)
m_oSvgCalculator.AddStyles(wsStyles);
}
void CSvgFile::AddFontFace(const SVG::TFontArguments& oArguments, const std::wstring &wsId)
{
m_mFontsFace.insert(std::make_pair(oArguments.m_wsFontFamily, wsId));
}
bool CSvgFile::Draw(IRenderer *pRenderer, double dX, double dY, double dWidth, double dHeight)
{
if (NULL == pRenderer || m_oContainer.Empty())

View File

@ -9,6 +9,12 @@
#define SVG_DECL_IMPORT Q_DECL_IMPORT
namespace SVG
{
struct TFontArguments;
class CFont;
}
class SVG_DECL_IMPORT CSvgFile
{
public:
@ -28,9 +34,12 @@ class SVG_DECL_IMPORT CSvgFile
bool MarkObject(SVG::CObject* pObject);
SVG::CObject* GetMarkedObject(const std::wstring& wsId) const;
SVG::CFont* GetFont(const std::wstring& wsFontFamily) const;
std::wstring GetWorkingDirectory() const;
void AddStyles(const std::wstring& wsStyles);
void AddFontFace(const SVG::TFontArguments& oArguments, const std::wstring& wsId);
bool Draw(IRenderer* pRenderer, double dX, double dY, double dWidth, double dHeight);
private:
@ -44,6 +53,9 @@ class SVG_DECL_IMPORT CSvgFile
MarkedMap m_mMarkedObjects;
std::wstring m_wsWorkingDirectory;
typedef std::map<std::wstring, std::wstring> FontsFaceMap;
FontsFaceMap m_mFontsFace;
};
#endif // CSVGFILE_H

View File

@ -6,7 +6,6 @@
#include "CSvgFile.h"
#include "SvgObjects/CContainer.h"
#include "SvgObjects/CPolyline.h"
#include "SvgObjects/CGradient.h"
#include "SvgObjects/CClipPath.h"
@ -20,6 +19,7 @@
#include "SvgObjects/CRect.h"
#include "SvgObjects/CLine.h"
#include "SvgObjects/CPath.h"
#include "SvgObjects/CFont.h"
#include "SvgObjects/CText.h"
#include "SvgObjects/CMask.h"
#include "SvgObjects/CUse.h"
@ -94,7 +94,7 @@ namespace SVG
if (L"style" == wsElementName)
{
pFile->AddStyles(oElement.GetText());
ParseStyles(oElement.GetText(), pFile);
return true;
}
@ -115,6 +115,61 @@ namespace SVG
return bScanResult;
}
void CSvgParser::ParseStyles(const std::wstring &wsStyles, CSvgFile *pFile) const
{
if (NULL == pFile)
return;
pFile->AddStyles(wsStyles);
std::wregex oRegex(L"@font-face\\s*(\\{[^}]*\\})");
std::wsmatch oMatch;
std::wstring::const_iterator oSearchStart(wsStyles.cbegin());
while (std::regex_search(oSearchStart, wsStyles.cend(), oMatch, oRegex))
{
if (oMatch[1].str().empty())
continue;
std::wstring wsValue{oMatch[1].str()};
std::wstring::const_iterator itStart = std::find_if(wsValue.cbegin(), wsValue.cend(), [](const wchar_t& wChar) { return !std::iswspace(wChar) && L'{' != wChar; });
std::wstring::const_reverse_iterator itEnd = std::find_if(wsValue.crbegin(), wsValue.crend(), [](const wchar_t& wChar) { return !std::iswspace(wChar) && L'}' != wChar; });
if (wsValue.cend() != itStart && wsValue.crend() != itEnd)
wsValue = std::wstring(itStart, itEnd.base());
const std::vector<std::wstring> arWords{NSCSS::NS_STATIC_FUNCTIONS::GetWordsW(wsValue, true, L":;")};
SvgURL oURL;
TFontArguments m_oArguments;
for (unsigned int unIndex = 0; unIndex < arWords.size(); ++unIndex)
{
if (arWords[unIndex].length() > 3 && L"src" == arWords[unIndex].substr(0, 3) && L':' == arWords[unIndex].back() &&
unIndex + 1 < arWords.size() && oURL.SetValue(arWords[++unIndex]))
{
continue;
}
else if (arWords[unIndex].length() > 11 && L"font-family" == arWords[unIndex].substr(0, 11) && L':' == arWords[unIndex].back() &&
unIndex + 1 < arWords.size())
{
const std::vector<std::wstring> arFontFamily{NSCSS::NS_STATIC_FUNCTIONS::GetWordsW(arWords[++unIndex], false, L"\"\',;")};
if (arFontFamily.empty())
continue;
m_oArguments.m_wsFontFamily = arFontFamily.back();
}
}
if (!oURL.Empty() && !m_oArguments.m_wsFontFamily.empty())
pFile->AddFontFace(m_oArguments, oURL.GetValue());
oSearchStart = oMatch.suffix().first;
}
}
template <class ObjectType>
bool CSvgParser::ReadObject(XmlUtils::CXmlNode &oElement, CContainer<ObjectType> *pContainer, CSvgFile *pFile, CRenderedObject *pParent) const
@ -223,6 +278,10 @@ namespace SVG
else
RELEASEOBJECT(pObject);
}
else if (L"font" == wsElementName)
{
pObject = new CFont(oElement);
}
if (NULL != pObject)
{

View File

@ -2,6 +2,7 @@
#define CSVGPARSER_H
#include "../../../common/Directory.h"
#include "../../../graphics/pro/Fonts.h"
#include "../../../xml/include/xmlutils.h"
#include "SvgObjects/CContainer.h"
@ -29,6 +30,7 @@ namespace SVG
bool ReadChildrens(XmlUtils::CXmlNode& oElement, CContainer<ObjectType>* pContainer, CSvgFile* pFile, CRenderedObject* pParent = NULL) const;
bool ScanStyles(XmlUtils::CXmlNode& oElement, CSvgFile* pFile) const;
void ParseStyles(const std::wstring& wsStyles, CSvgFile *pFile) const;
void UpdateStyles(CObject* pObject, CSvgFile* pFile) const;
bool MarkObject(CObject* pObject, CSvgFile* pFile) const;

View File

@ -3,8 +3,6 @@
#include "CObjectBase.h"
#include "../../../../graphics/pro/Fonts.h"
class CSvgFile;
namespace SVG

View File

@ -0,0 +1,90 @@
#include "CFont.h"
namespace SVG
{
CGlyph::CGlyph(XmlUtils::CXmlNode &oNode)
: CPath(oNode)
{
std::wstring wsUnicode(oNode.GetAttribute(L"unicode"));
if (!wsUnicode.empty())
m_wchUnicode = wsUnicode[0];
}
wchar_t CGlyph::GetUnicode() const
{
return m_wchUnicode;
}
CFontFace::CFontFace(XmlUtils::CXmlNode &oNode)
{
}
CFont::CFont(XmlUtils::CXmlNode &oNode)
: CAppliedObject(oNode), m_pMissingGlyph(NULL)
{
ParseGlyphs(oNode);
m_oArguments.m_wsFontVariant = oNode.GetAttribute(L"font-variant");
m_oArguments.m_wsFontStyle = oNode.GetAttribute(L"font-style");
m_oArguments.m_wsFontWidght = oNode.GetAttribute(L"font-weight");
}
CFont::~CFont()
{
for (std::pair<wchar_t, CGlyph*> oElement : m_mGlyphs)
RELEASEOBJECT(oElement.second);
RELEASEOBJECT(m_pMissingGlyph);
}
void CFont::SetData(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
}
bool CFont::Apply(IRenderer *pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds)
{
return true;
}
void CFont::ParseGlyphs(XmlUtils::CXmlNode &oNode)
{
std::vector<XmlUtils::CXmlNode> arChilds;
if (!oNode.GetChilds(arChilds) || arChilds.empty())
return;
for (XmlUtils::CXmlNode& oChild : arChilds)
{
if (L"glyph" == oChild.GetName())
{
CGlyph *pGlyph = new CGlyph(oChild);
if (NULL == pGlyph)
continue;
if (m_mGlyphs.end() == m_mGlyphs.find(pGlyph->GetUnicode()))
m_mGlyphs.insert(std::make_pair(pGlyph->GetUnicode(), pGlyph));
else
delete pGlyph;
}
else if (L"missing-glyph" == oChild.GetName())
{
std::vector<XmlUtils::CXmlNode> arMissingGlyphChilds;
if (!oChild.GetChilds(arMissingGlyphChilds) || arMissingGlyphChilds.empty())
continue;
for (XmlUtils::CXmlNode& oChildMissingGlyph : arMissingGlyphChilds)
{
if (L"path" == oChildMissingGlyph.GetName())
{
m_pMissingGlyph = new CPath(oChildMissingGlyph);
if (NULL != m_pMissingGlyph)
break;
}
}
}
}
}
}

View File

@ -0,0 +1,53 @@
#ifndef CFONT_H
#define CFONT_H
#include "CPath.h"
namespace SVG
{
class CGlyph : public CPath
{
public:
CGlyph(XmlUtils::CXmlNode& oNode);
wchar_t GetUnicode() const;
private:
wchar_t m_wchUnicode;
};
class CFontFace
{
public:
CFontFace(XmlUtils::CXmlNode& oNode);
private:
std::wstring m_wsSrcFaceName;
};
struct TFontArguments
{
std::wstring m_wsFontFamily;
std::wstring m_wsFontVariant;
std::wstring m_wsFontStyle;
std::wstring m_wsFontWidght;
};
class CFont : public CAppliedObject
{
public:
CFont(XmlUtils::CXmlNode& oNode);
~CFont();
void SetData(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode) override;
bool Apply(IRenderer* pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds) override;
private:
void ParseGlyphs(XmlUtils::CXmlNode& oNode);
TFontArguments m_oArguments;
std::map<wchar_t, CGlyph*> m_mGlyphs;
CPath *m_pMissingGlyph;
};
}
#endif // CFONT_H

View File

@ -2,6 +2,7 @@
#define CPATTERN_H
#include "CContainer.h"
#include "../../../../graphics/pro/Fonts.h"
namespace SVG
{

View File

@ -2,6 +2,7 @@
#define CSYMBOL_H
#include "CContainer.h"
#include "../../../graphics/pro/Fonts.h"
namespace SVG
{

View File

@ -152,12 +152,15 @@ namespace SVG
double dX, dY;
CalculatePosition(dX, dY);
ApplyFont(pRenderer, dX, dY);
pRenderer->CommandDrawText(m_wsText, dX, dY, 0, 0);
for (const CRenderedObject* pTSpan : m_arObjects)
pTSpan->Draw(pRenderer, pFile, oMode, pOtherStyles);
if (!UseExternalFont(pFile))
{
ApplyFont(pRenderer, dX, dY);
pRenderer->CommandDrawText(m_wsText, dX, dY, 0, 0);
for (const CRenderedObject* pTSpan : m_arObjects)
pTSpan->Draw(pRenderer, pFile, oMode, pOtherStyles);
}
EndPath(pRenderer, pFile, oOldMatrix, oMode, pOtherStyles);
@ -292,6 +295,24 @@ namespace SVG
pRenderer->put_BrushColor1(m_oStyles.m_oFill.ToInt());
pRenderer->put_BrushAlpha1(255);
}
bool CTSpan::UseExternalFont(const CSvgFile *pFile) const
{
std::wstring wsFontFamily = DefaultFontFamily;
if (!m_oFont.GetFamily().Empty())
{
wsFontFamily = m_oFont.GetFamily().ToWString();
CorrectFontFamily(wsFontFamily);
}
CFont *pFont = pFile->GetFont(wsFontFamily);
if (NULL == pFont)
return false;
return true;
}
TBounds CTSpan::GetBounds() const
{

View File

@ -31,6 +31,8 @@ namespace SVG
void ApplyStyle(IRenderer* pRenderer, const TSvgStyles* pStyles, const CSvgFile* pFile, int& nTypePath) const override;
void ApplyFont(IRenderer* pRenderer, double& dX, double& dY) const;
bool UseExternalFont(const CSvgFile* pFile) const;
TBounds GetBounds() const override;
double GetWidth() const;

View File

@ -14,6 +14,7 @@ namespace SVG
#define SvgDigit NSCSS::NSProperties::CDigit
#define SvgString NSCSS::NSProperties::CString
#define SvgColor NSCSS::NSProperties::CColor
#define SvgURL NSCSS::NSProperties::CURL
#define SvgEnum NSCSS::NSProperties::CEnum
#define SvgTransform NSCSS::NSProperties::CTransform