Files
core/ASCHTMLRenderer/Writer/Text.h

1102 lines
29 KiB
C++
Raw Blame History

#pragma once
#include "..\stdafx.h"
#include "Const.h"
#include "StringWriter.h"
#include "..\Graphics\Structures.h"
#include "..\Graphics\Matrix.h"
#include "FontManager.h"
namespace NSHtmlRenderer
{
static wchar_t g_wc_amp = wchar_t('&');
static wchar_t g_wc_apos = wchar_t('\'');
static wchar_t g_wc_lt = wchar_t('<');
static wchar_t g_wc_qt = wchar_t('>');
static wchar_t g_wc_quot = wchar_t('\"');
static _bstr_t g_bstr_amp = L"&amp;";
static _bstr_t g_bstr_apos = L"&apos;";
static _bstr_t g_bstr_lt = L"&lt;";
static _bstr_t g_bstr_qt = L"&gt;";
static _bstr_t g_bstr_quot = L"\"";
class CStyles
{
private:
CAtlMap<CString, LONG> m_mapStyles;
LONG m_lNexrID;
public:
NSStrings::CStringWriter m_oWriterCSS;
double m_dDpiY;
public:
CStyles() : m_mapStyles(), m_lNexrID(0)
{
}
~CStyles()
{
m_mapStyles.RemoveAll();
}
public:
void NewDocument()
{
m_mapStyles.RemoveAll();
m_lNexrID = 0;
m_oWriterCSS.Clear();
CString strCSS =
_T(".blockpage { position: relative; background: #FFFFFF; padding: 0; float: none; margin: 0px auto; overflow: hidden; box-shadow: 0 0 10px rgba(0,0,0,0.5); -moz-box-shadow: 0 0 10px rgba(0,0,0,0.5); -webkit-box-shadow: 0 0 10px rgba(0,0,0,0.5); }\n\
.blockpagebetween { width: 100%; height: 20px; background: #FEFEFE; padding: 0px; float: none; text-align: center; }\n\
.bt { position: absolute; margin-top: 0px; padding: 0px; float: none; }\n\
.bs { margin-top: 0px; padding: 0px; float: none; }\n\
.rt { position: absolute; font-size: 0; padding: 0px; margin-left: 0px; margin-top: 0px; border-style: solid; }\n\
._svg { -moz-user-select: none;-khtml-user-select: none;user-select: none; width:100%; height:100%;}\n\
v\\:vmlframe { behavior:url(#default#VML); display: block; width: 100%; height: 100%; position: absolute; padding: 0px; margin-left:0px;margin-top:0px; }\n\
v\\:*{behavior:url(#default#VML)}\n");
m_oWriterCSS.WriteString(strCSS);
}
void CloseDocument()
{
m_mapStyles.RemoveAll();
m_lNexrID = 0;
m_oWriterCSS.Clear();
}
void WriteStylesForDiffBrowsers(const CString& strDir)
{
CString strIE = _T(".bp { position: absolute; z-index:100; margin-left: 0px; margin-top: 0px; padding: 0px; float: none; text-align: justify; text-align-last: justify; }");
CString strOp = _T(".bp { position: absolute; z-index:100; margin-left: 0px; margin-top: 0px; padding: 0px; float: none; display:inline-table; text-align: justify; text-align-last: justify; }\
.bp:after { content:\"\"; display:inline-block; width:100%; font-size: 0px; height:0; overflow:hidden; }");
CString strOt = _T(".bp { position: absolute; z-index:100; margin-left: 0px; margin-top: 0px; padding: 0px; float: none; display:inline-table; white-space:pre-line; text-align: justify; text-align-last: justify; }\
.bp:after { content:\"\"; display:inline-block; width:100%; font-size: 0px; height:0; overflow:hidden; }");
CDirectory::SaveToFile(strDir + _T("\\css_ie.css"), strIE);
CDirectory::SaveToFile(strDir + _T("\\css_opera.css"), strOp);
CDirectory::SaveToFile(strDir + _T("\\css_other.css"), strOt);
}
LONG GetClassID(NSStructures::CFont* pFont, NSStructures::CBrush* pBrush)
{
CString strFormat = _T("");
int nSize = round(m_dDpiY * pFont->Size / 72);
if (nSize >= 10)
--nSize;
if (pFont->Italic && pFont->Bold)
{
strFormat.Format(g_string_text_css_ib, pFont->Name, nSize, ConvertColor(pBrush->Color1));
}
else if (pFont->Italic)
{
strFormat.Format(g_string_text_css_i, pFont->Name, nSize, ConvertColor(pBrush->Color1));
}
else if (pFont->Bold)
{
strFormat.Format(g_string_text_css_b, pFont->Name, nSize, ConvertColor(pBrush->Color1));
}
else
{
strFormat.Format(g_string_text_css, pFont->Name, nSize, ConvertColor(pBrush->Color1));
}
CAtlMap<CString, LONG>::CPair* pPair = m_mapStyles.Lookup(strFormat);
if (NULL == pPair)
{
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
++m_lNexrID;
m_mapStyles.SetAt(strFormat, m_lNexrID);
CString strCSS = _T("");
strCSS.Format(g_string_style_name, m_lNexrID);
m_oWriterCSS.WriteString(strCSS);
m_oWriterCSS.WriteString(strFormat);
m_oWriterCSS.WriteString(g_bstr_script_close);
return m_lNexrID;
}
return pPair->m_value;
}
};
class CWord
{
public:
NSStructures::CFont m_oFont;
NSStructures::CBrush m_oBrush;
NSStrings::CTextItem m_oText;
double m_dX;
double m_dY;
double m_dWidth;
double m_dHeight;
double m_dBaseLinePos;
double m_dWidthWithoutSpaces;
public:
CWord() : m_oFont(), m_oBrush(), m_oText(10)
{
m_dX = 0;
m_dY = 0;
m_dWidth = 0;
m_dHeight = 0;
m_dBaseLinePos = 0;
m_dWidthWithoutSpaces = 0;
}
CWord(CFontManager* pFontManager, NSStructures::CBrush* pBrush, NSStrings::CTextItem& oText,
double& x, double& y, double& width, double& height, double& baseoffset) : m_oFont(pFontManager->m_oFont.m_oFont), m_oBrush(*pBrush), m_oText(oText),
m_dX(x), m_dY(y), m_dWidth(width), m_dHeight(height), m_dBaseLinePos(baseoffset), m_dWidthWithoutSpaces(width)
{
if (GetCountSpaceLast() == m_oText.GetCurSize())
m_dWidthWithoutSpaces = 0;
if (_T("") != pFontManager->m_strCurrentPickFont)
{
m_oFont.Name = pFontManager->m_strCurrentPickFont;
m_oFont.SetStyle(pFontManager->m_lCurrentPictFontStyle);
}
}
CWord(const CWord& oSrc)
{
*this = oSrc;
}
CWord& operator=(const CWord& oSrc)
{
m_oFont = oSrc.m_oFont;
m_oBrush = oSrc.m_oBrush;
m_oText = oSrc.m_oText;
m_dX = oSrc.m_dX;
m_dY = oSrc.m_dY;
m_dWidth = oSrc.m_dWidth;
m_dHeight = oSrc.m_dHeight;
m_dBaseLinePos = oSrc.m_dBaseLinePos;
m_dWidthWithoutSpaces = oSrc.m_dWidthWithoutSpaces;
return *this;
}
long GetCountSpaceLast()
{
LONG lCount = (LONG)m_oText.GetCurSize();
wchar_t* pData = m_oText.GetBuffer();
LONG lCur = 0;
while (lCount > 0)
{
if (((WCHAR)' ') == pData[lCount - 1])
++lCur;
else
break;
--lCount;
}
return lCur;
}
long GetCountLastPoints()
{
LONG lCount = (LONG)m_oText.GetCurSize();
wchar_t* pData = m_oText.GetBuffer() + lCount - 1;
LONG lCur = 0;
while (lCount > 0)
{
if (((WCHAR)'.') == *pData)
++lCur;
else
break;
--lCount;
}
return lCur;
}
AVSINLINE void GetCorrectString(CString& strText)
{
strText.Replace(_T("&"), _T("&amp;"));
strText.Replace(_T("'"), _T("&apos;"));
strText.Replace(_T("<"), _T("&lt;"));
strText.Replace(_T(">"), _T("&gt;"));
strText.Replace(_T("\""), _T("&quot;"));
}
AVSINLINE void WriteToStringWriter(NSStrings::CStringWriter& oWriter)
{
size_t nCurrent = 0;
size_t nCount = m_oText.GetCurSize();
size_t nCurrentOld = nCurrent;
wchar_t* pData = m_oText.GetBuffer();
wchar_t* pStartData = pData;
while (nCurrent < nCount)
{
wchar_t c = *pData++;
if (g_wc_amp == c)
{
if (nCurrentOld != nCurrent)
oWriter.WriteString(pStartData, nCurrent - nCurrentOld);
oWriter.WriteString(g_bstr_amp);
++nCurrent;
nCurrentOld = nCurrent;
pStartData = pData;
}
/*else if (g_wc_apos == c)
{
if (nCurrentOld != nCurrent)
oWriter.WriteString(pStartData, nCurrent - nCurrentOld);
oWriter.WriteString(g_bstr_apos);
++nCurrent;
nCurrentOld = nCurrent;
pStartData = pData;
}*/
else if (g_wc_lt == c)
{
if (nCurrentOld != nCurrent)
oWriter.WriteString(pStartData, nCurrent - nCurrentOld);
oWriter.WriteString(g_bstr_lt);
++nCurrent;
nCurrentOld = nCurrent;
pStartData = pData;
}
else if (g_wc_qt == c)
{
if (nCurrentOld != nCurrent)
oWriter.WriteString(pStartData, nCurrent - nCurrentOld);
oWriter.WriteString(g_bstr_qt);
++nCurrent;
nCurrentOld = nCurrent;
pStartData = pData;
}
else if (g_wc_quot == c)
{
if (nCurrentOld != nCurrent)
oWriter.WriteString(pStartData, nCurrent - nCurrentOld);
oWriter.WriteString(g_bstr_quot);
++nCurrent;
nCurrentOld = nCurrent;
pStartData = pData;
}
else
{
++nCurrent;
}
}
if (nCurrentOld != nCurrent)
oWriter.WriteString(pStartData, nCurrent - nCurrentOld);
}
};
class CTextLine
{
public:
NSStrings::CStringWriter* m_pTextMeasurer;
CAtlList<CWord*> m_arWords;
LONG m_lNextID;
double m_dMinTop;
LONG m_lIndexZ;
public:
CTextLine() : m_arWords(), m_lIndexZ(0)
{
}
CTextLine(const CTextLine& oSrc)
{
*this = oSrc;
}
CTextLine& operator=(const CTextLine& oSrc)
{
Clear();
POSITION pos = oSrc.m_arWords.GetHeadPosition();
while (NULL != pos)
{
CWord* pWord = oSrc.m_arWords.GetNext(pos);
CWord* pWordNew = new CWord(*pWord);
m_arWords.AddTail(pWordNew);
}
return *this;
}
public:
void Clear()
{
POSITION pos = m_arWords.GetHeadPosition();
while (NULL != pos)
{
CWord* pWord = m_arWords.GetNext(pos);
RELEASEOBJECT(pWord);
}
m_arWords.RemoveAll();
m_dMinTop = 10000000;
}
void AddWord(CWord* pWord)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>. <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>?? <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
POSITION pos = m_arWords.GetTailPosition();
if (NULL != pos)
{
CWord* pTail = m_arWords.GetNext(pos);
if (pTail->GetCountSpaceLast() == pTail->m_oText.GetCurSize())
{
m_arWords.RemoveTail();
RELEASEOBJECT(pTail);
}
}
if (m_dMinTop > pWord->m_dY)
m_dMinTop = pWord->m_dY;
m_arWords.AddTail(pWord);
}
CWord* GetLast()
{
return m_arWords.GetTail();
}
CWord* GetHead()
{
return m_arWords.GetHead();
}
size_t GetCount()
{
return m_arWords.GetCount();
}
public:
inline void Write(NSStrings::CStringWriter* pWriter, double& dDpiX, double& dDpiY, CStyles* pStyles, const LONG& lIndexZ)
{
return Write3(pWriter, dDpiX, dDpiY, pStyles, lIndexZ);
}
void Write1(NSStrings::CStringWriter* pWriter, double& dDpiX, double& dDpiY, CStyles* pStyles)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//return Write2(pWriter, dDpiX, dDpiY);
size_t nCountWords = m_arWords.GetCount();
if (0 == nCountWords)
return;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CWord* pWord = m_arWords.GetTail();
NSStructures::CFont* pFont0 = &pWord->m_oFont;
NSStructures::CBrush* pBrush0 = &pWord->m_oBrush;
CString strPar = _T("");
strPar.Format(g_string_paragraph2, pWord->m_oFont.Name, (int)(dDpiY * pWord->m_oFont.Size / 72), ConvertColor(pWord->m_oBrush.Color1));
pWriter->WriteString(strPar);
POSITION pos = m_arWords.GetHeadPosition();
POSITION posOld = m_arWords.GetTailPosition();
while (NULL != pos)
{
pWord = m_arWords.GetNext(pos);
if (pWord->m_oFont.IsEqual(pFont0) && (pWord->m_oBrush.IsEqual(pBrush0)))
{
CString strSpan = _T("");
strSpan.Format(g_string_span1, (int)pWord->m_dX, (int)pWord->m_dY);
pWriter->WriteString(strSpan);
}
else
{
CString strSpan = _T("");
strSpan.Format(g_string_span3, pWord->m_oFont.Name, (int)(dDpiY * pWord->m_oFont.Size / 72), ConvertColor(pWord->m_oBrush.Color1));
pWriter->WriteString(strSpan);
}
//pWriter->WriteString(pWord->m_strText);
pWord->WriteToStringWriter(*pWriter);
if (pos != posOld)
{
pWriter->WriteString(g_bstr_space);
}
pWriter->WriteString(g_bstr_span_end);
}
pWriter->WriteString(g_bstr_paragraph_end);
}
void Write2(NSStrings::CStringWriter* pWriter, double& dDpiX, double& dDpiY, CStyles* pStyles)
{
size_t nCountWords = m_arWords.GetCount();
if (0 == nCountWords)
return;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CWord* pWord = m_arWords.GetHead();
NSStructures::CFont* pFont0 = &pWord->m_oFont;
NSStructures::CBrush* pBrush0 = &pWord->m_oBrush;
CString strPar = _T("");
strPar.Format(g_string_paragraph3, (int)pWord->m_dX, (int)pWord->m_dY, pWord->m_oFont.Name, (int)(dDpiY * pWord->m_oFont.Size / 72), ConvertColor(pWord->m_oBrush.Color1));
pWriter->WriteString(strPar);
CString strText = _T("");
POSITION pos = m_arWords.GetHeadPosition();
while (NULL != pos)
{
pWord = m_arWords.GetNext(pos);
strText += pWord->m_oText.GetCString();
if (NULL != pos)
strText += _T(" ");
}
pWriter->WriteString(strText);
pWriter->WriteString(g_bstr_paragraph_end);
}
void Write3(NSStrings::CStringWriter* pWriter, double& dDpiX, double& dDpiY, CStyles* pStyles, const LONG& lIndexZ)
{
DeleteEmptyWords();
size_t nCountWords = m_arWords.GetCount();
if (0 == nCountWords)
return;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CWord* pWord = m_arWords.GetHead();
NSStructures::CFont* pFont0 = &pWord->m_oFont;
NSStructures::CBrush* pBrush0 = &pWord->m_oBrush;
pWord->m_dWidth = pWord->m_dWidthWithoutSpaces;
int nLeft = (int)pWord->m_dX;
int nRight = (int)(pWord->m_dX + pWord->m_dWidthWithoutSpaces);
double dRight = pWord->m_dX + pWord->m_dWidthWithoutSpaces;
POSITION pos = m_arWords.GetHeadPosition();
m_arWords.GetNext(pos);
while (NULL != pos)
{
pWord = m_arWords.GetNext(pos);
pWord->m_dWidth = pWord->m_dWidthWithoutSpaces;
nRight = (int)(pWord->m_dX + pWord->m_dWidth);
}
pos = m_arWords.GetHeadPosition();
pWord = m_arWords.GetHead();
pStyles->m_dDpiY = dDpiY;
LONG lID = pStyles->GetClassID(&pWord->m_oFont, &pWord->m_oBrush);
LONG lDecoration = pWord->m_oFont.GetTextDecorationStyle();
CString strPar = _T("");
strPar.Format(g_string_paragraph_style, lID, (int)pWord->m_dX, (int)m_dMinTop, nRight - nLeft);
pWriter->WriteString(strPar);
pWriter->WriteString(g_bstr_nobr_start);
if ((0 == lDecoration) || (3 < lDecoration))
{
//pWriter->WriteString(pWord->GetCorrectString());
pWord->WriteToStringWriter(*pWriter);
}
else
{
switch (lDecoration)
{
case 1:
pWriter->WriteString(g_string_span_style_underline2);
break;
case 2:
pWriter->WriteString(g_string_span_style_strike2);
break;
case 3:
pWriter->WriteString(g_string_span_style_underline_strike2);
break;
default:
break;
}
//pWriter->WriteString(pWord->GetCorrectString());
pWord->WriteToStringWriter(*pWriter);
pWriter->WriteString(g_bstr_span_end);
}
m_arWords.GetNext(pos);
bool bSpanClose = false;
while (NULL != pos)
{
pWord = m_arWords.GetNext(pos);
if (1.0 < (pWord->m_dX - dRight))
{
pWriter->WriteString(g_bstr_space2);
}
dRight = pWord->m_dX + pWord->m_dWidthWithoutSpaces;
if (bSpanClose)
pWriter->WriteString(g_bstr_span_end);
bSpanClose = true;
lID = pStyles->GetClassID(&pWord->m_oFont, &pWord->m_oBrush);
CString strSpan = _T("");
lDecoration = pWord->m_oFont.GetTextDecorationStyle();
switch (lDecoration)
{
case 0:
strSpan.Format(g_string_span_style, lID);
break;
case 1:
strSpan.Format(g_string_span_style_underline, lID);
break;
case 2:
strSpan.Format(g_string_span_style_strike, lID);
break;
case 3:
strSpan.Format(g_string_span_style_underline_strike, lID);
break;
default:
strSpan.Format(g_string_span_style, lID);
break;
}
pWriter->WriteString(strSpan);
//pWriter->WriteString(pWord->GetCorrectString());
pWord->WriteToStringWriter(*pWriter);
}
if (bSpanClose)
pWriter->WriteString(g_bstr_span_end);
pWriter->WriteString(g_bstr_nobr_end);
pWriter->WriteString(g_bstr_paragraph_end);
//CString strLine = _T("");
//strLine.Format(g_string_lineFunc, m_lNextID++, nRight - nLeft);
//m_pTextMeasurer->WriteString(strLine);
}
void DeleteEmptyWords()
{
POSITION pos = m_arWords.GetHeadPosition();
CWord* pWord = NULL;
while (NULL != pos)
{
POSITION posOld = pos;
pWord = m_arWords.GetNext(pos);
if (pWord->GetCountSpaceLast() == pWord->m_oText.GetCurSize())
{
m_arWords.RemoveAt(posOld);
RELEASEOBJECT(pWord);
}
}
if (0 != m_arWords.GetCount())
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>.
pWord = m_arWords.GetTail();
pWord->m_oText.RemoveLastSpaces();
}
}
void Merge()
{
POSITION pos = m_arWords.GetHeadPosition();
if (NULL == pos)
return;
POSITION posCur = pos;
CWord* pWordPrev = m_arWords.GetNext(posCur);
double dRightPos = pWordPrev->m_dX + pWordPrev->m_dWidth;
while (NULL != posCur)
{
POSITION posCurOld = posCur;
CWord* pWord = m_arWords.GetNext(posCur);
bool bNextWord = true;
if (FABS(pWord->m_dX - dRightPos) < 0.1)
{
// <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
bNextWord = false;
}
dRightPos = pWord->m_dX + pWord->m_dWidth;
if ((pWord->m_oFont.IsEqual(&pWordPrev->m_oFont)) && (pWord->m_oBrush.IsEqual(&pWordPrev->m_oBrush)))
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if (bNextWord)
{
pWordPrev->m_oText.AddSpace();
}
pWordPrev->m_oText += pWord->m_oText;
m_arWords.RemoveAt(posCurOld);
RELEASEOBJECT(pWord);
}
else
{
if (bNextWord)
pWordPrev->m_oText.AddSpace();
pos = posCur;
pWordPrev = pWord;
}
}
}
};
class CText
{
public:
CFontManager m_oFontManager;
CTextLine m_oCurrentLine;
NSStrings::CStringWriter* m_pWriter;
//NSStrings::CStringWriter m_oTextMeasurer;
CStyles* m_pStyles;
double m_dDpiX;
double m_dDpiY;
NSStructures::CPen* m_pPen;
NSStructures::CBrush* m_pBrush;
NSStructures::CFont* m_pFont;
NSHtmlRenderer::CMatrix* m_pTransform;
LONG m_lIndexZ;
bool m_bIsNewLine;
bool m_bIsPDFTextStyle;
NSStrings::CTextItem m_oTextItem;
private:
double m_dEpsX;
double m_dEpsY;
public:
CText() : m_oFontManager(), m_oCurrentLine(), m_oTextItem(10)//, m_oTextMeasurer()
{
m_pWriter = NULL;
m_dEpsX = 0.5;
m_dEpsY = 0.5;
m_pPen = NULL;
m_pBrush = NULL;
m_pFont = NULL;
//m_oCurrentLine.m_pTextMeasurer = &m_oTextMeasurer;
m_pStyles = NULL;
m_pTransform = NULL;
m_lIndexZ = 0;
m_bIsNewLine = false;
m_bIsPDFTextStyle = false;
}
void SetParams(NSStructures::CPen* pPen, NSStructures::CBrush* pBrush, NSStructures::CFont* pFont, CStyles* pStyles, NSHtmlRenderer::CMatrix* pTransform)
{
m_pPen = pPen;
m_pBrush = pBrush;
m_pFont = pFont;
m_oFontManager.m_pFont = pFont;
m_oFontManager.m_pTransform = pTransform;
m_pStyles = pStyles;
m_pTransform = pTransform;
}
~CText()
{
}
void NewPage(double& dDpiX, double& dDpiY)
{
m_dDpiX = dDpiX;
m_dDpiY = dDpiY;
m_pPen->SetDefaultParams();
m_pBrush->SetDefaultParams();
m_pFont->SetDefaultParams();
}
void ClosePage()
{
m_oCurrentLine.Write(m_pWriter, m_dDpiX, m_dDpiY, m_pStyles, m_lIndexZ);
}
void NewDocument()
{
m_oCurrentLine.m_lNextID = 1;
m_oCurrentLine.m_dMinTop = 1000000;
m_pPen->SetDefaultParams();
m_pBrush->SetDefaultParams();
m_pFont->SetDefaultParams();
}
protected:
AVSINLINE bool GetIsNewLine()
{
if (m_bIsNewLine)
{
m_bIsNewLine = false;
return true;
}
return false;
}
void CommandText1(double& x, double& y, double& width, double& height, double& baselineoffset)
{
double dScaleFont = ((m_pTransform->m_agg_mtx.sx + m_pTransform->m_agg_mtx.sy) / 2);
BOOL bIsFontChanged = !m_oFontManager.m_oFont.m_oFont.IsEqual2(m_pFont, dScaleFont);
BOOL bIsTextDecorationChanged = ((m_oFontManager.m_oFont.m_oFont.Underline != m_pFont->Underline) ||
(m_oFontManager.m_oFont.m_oFont.Strikeout != m_pFont->Strikeout));
if (bIsFontChanged)
{
m_oFontManager.m_oFont.m_oFont = *m_pFont;
m_oFontManager.m_oFont.m_oFont.Size *= dScaleFont;
}
else if (bIsTextDecorationChanged)
{
m_oFontManager.m_oFont.m_oFont.Underline = m_pFont->Underline;
m_oFontManager.m_oFont.m_oFont.Strikeout = m_pFont->Strikeout;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> m_pFont
m_oFontManager.m_strCurrentPickFont = _T("");
bool bIsNewLine = GetIsNewLine();
if (0 == width)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>?? <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>??
m_oFontManager.LoadCurrentFont();
double dOffset = m_oFontManager.m_oFont.m_dBaselineOffsetHTML;
dOffset *= (m_dDpiY / 72.0);
y -= dOffset;
baselineoffset = dOffset;
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double _x = 0;
double _y = 0;
double _w = 0;
double _h = 0;
LONG lGid = m_oFontManager.GetStringGid();
m_oFontManager.SetStringGid(0);
m_oFontManager.MeasureStringPix(m_oTextItem.GetCString(), x, y, _x, _y, _w, _h, CFontManager::MeasureTypePosition);
m_oFontManager.SetStringGid(lGid);
width = _w;
height = _h;
}
double dYPos = y + baselineoffset;
LONG lCountWords = (LONG)m_oCurrentLine.GetCount();
if (0 == lCountWords)
{
// <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
CWord* pWord = new CWord(&m_oFontManager, m_pBrush, m_oTextItem, x, y, width, height, dYPos);
m_oCurrentLine.AddWord(pWord);
return;
}
CWord* pTail = m_oCurrentLine.GetLast();
double dYPosLine = pTail->m_dBaseLinePos;
if (FABS(dYPos - dYPosLine) > m_dEpsY)
{
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
m_oCurrentLine.Write(m_pWriter, m_dDpiX, m_dDpiY, m_pStyles, m_lIndexZ);
m_oCurrentLine.Clear();
CWord* pWord = new CWord(&m_oFontManager, m_pBrush, m_oTextItem, x, y, width, height, dYPos);
m_oCurrentLine.AddWord(pWord);
return;
}
double dRight = pTail->m_dX + pTail->m_dWidth;
if ((x + 0.5 < dRight) || (((x - dRight) * c_ag_Inch_to_MM / m_dDpiX) > g_lNewNoJustifySpace) || (bIsNewLine))
{
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
m_oCurrentLine.Write(m_pWriter, m_dDpiX, m_dDpiY, m_pStyles, m_lIndexZ);
m_oCurrentLine.Clear();
CWord* pWord = new CWord(&m_oFontManager, m_pBrush, m_oTextItem, x, y, width, height, dYPos);
m_oCurrentLine.AddWord(pWord);
return;
}
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!bIsFontChanged && pTail->m_oBrush.IsEqual(m_pBrush) && !bIsTextDecorationChanged)
{
if (1.0 < FABS(pTail->m_dX + pTail->m_dWidth - x))
{
// <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>!!!
pTail->m_oText.AddSpace();
}
pTail->m_oText += m_oTextItem;
pTail->m_dWidth = (x + width - pTail->m_dX);
pTail->m_dWidthWithoutSpaces = pTail->m_dWidth;
}
else
{
CWord* pWord = new CWord(&m_oFontManager, m_pBrush, m_oTextItem, x, y, width, height, dYPos);
m_oCurrentLine.AddWord(pWord);
}
}
void CommandText2(BSTR bsGid, double& x, double& y, double& width, double& height, double& baselineoffset)
{
bool bIsNewLine = GetIsNewLine();
double dScaleFont = ((m_pTransform->m_agg_mtx.sx + m_pTransform->m_agg_mtx.sy) / 2);
BOOL bIsFontChanged = !m_oFontManager.m_oFont.m_oFont.IsEqual2(m_pFont, dScaleFont);
if (bIsFontChanged)
{
m_oFontManager.m_oFont.m_oFont = *m_pFont;
m_oFontManager.m_oFont.m_oFont.Size *= dScaleFont;
m_oFontManager.LoadCurrentFont();
m_oFontManager.CalculateSpace();
m_pFont->SetStyle(m_oFontManager.m_oFont.m_oFont.GetStyle());
m_oFontManager.GenerateFontName(m_oTextItem, true);
}
else
{
m_oFontManager.GenerateFontName(m_oTextItem, false);
}
double dOffset = m_oFontManager.m_oFont.m_dBaselineOffsetHTML;
dOffset *= (m_dDpiY / 72.0);
y -= dOffset;
baselineoffset = dOffset;
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double _x = 0;
double _y = 0;
double _w = 0;
double _h = 0;
bool bIsMeasuring = false;
if (0 >= width)
{
if (NULL == bsGid)
{
m_oFontManager.SetStringGid(0);
BSTR bsText = m_oTextItem.GetCString().AllocSysString();
m_oFontManager.MeasureStringPix(bsText, x, y, _x, _y, _w, _h, CFontManager::MeasureTypePosition);
SysFreeString(bsText);
}
else
{
m_oFontManager.SetStringGid(1);
m_oFontManager.MeasureStringPix(bsGid, x, y, _x, _y, _w, _h, CFontManager::MeasureTypePosition);
}
width = _w;
height = _h;
bIsMeasuring = true;
}
double dYPos = y + baselineoffset;
LONG lCountWords = (LONG)m_oCurrentLine.GetCount();
if (0 == lCountWords)
{
// <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
CWord* pWord = new CWord(&m_oFontManager, m_pBrush, m_oTextItem, x, y, width, height, dYPos);
m_oCurrentLine.AddWord(pWord);
return;
}
double dYPosLine = m_oCurrentLine.GetHead()->m_dBaseLinePos;
if (FABS(dYPos - dYPosLine) > m_dEpsY)
{
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
m_oCurrentLine.Write(m_pWriter, m_dDpiX, m_dDpiY, m_pStyles, m_lIndexZ);
m_oCurrentLine.Clear();
CWord* pWord = new CWord(&m_oFontManager, m_pBrush, m_oTextItem, x, y, width, height, dYPos);
m_oCurrentLine.AddWord(pWord);
return;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>
//double dSpace = MMToPX(m_oFontManager.m_dSpaceWidthMM, m_dDpiX) / 2.0;
double dSpace = 0.5 * m_dDpiX / c_dInchToMM;
if (bIsMeasuring)
{
dSpace = m_oFontManager.m_dSpaceWidthMM * m_dDpiX / 25.4;
}
CWord* pWordLast = m_oCurrentLine.GetLast();
double dRight = pWordLast->m_dX + pWordLast->m_dWidthWithoutSpaces;
if ((x + 10 < dRight) || (((x - dRight) * c_ag_Inch_to_MM / m_dDpiX) > g_lNewNoJustifySpace) || (bIsNewLine))
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
m_oCurrentLine.Write(m_pWriter, m_dDpiX, m_dDpiY, m_pStyles, m_lIndexZ);
m_oCurrentLine.Clear();
CWord* pWord = new CWord(&m_oFontManager, m_pBrush, m_oTextItem, x, y, width, height, dYPos);
m_oCurrentLine.AddWord(pWord);
return;
}
bool bIsBrushChanged = !pWordLast->m_oBrush.IsEqual(m_pBrush);
double dDelta = (x - (pWordLast->m_dX + pWordLast->m_dWidth));
if ((dDelta > dSpace) || bIsFontChanged || bIsBrushChanged)
{
if (m_oTextItem.IsSpace())
{
if (0 == pWordLast->GetCountSpaceLast())
{
pWordLast->m_oText += m_oTextItem;
pWordLast->m_dWidth = x + width - pWordLast->m_dX;
}
return;
}
if (dDelta > dSpace)
pWordLast->m_oText.AddSpace();
if (bIsFontChanged || bIsBrushChanged)
{
CWord* pWord = new CWord(&m_oFontManager, m_pBrush, m_oTextItem, x, y, width, height, dYPos);
m_oCurrentLine.AddWord(pWord);
}
else
{
pWordLast->m_oText += m_oTextItem;
pWordLast->m_dWidth = x + width - pWordLast->m_dX;
pWordLast->m_dWidthWithoutSpaces = pWordLast->m_dWidth;
}
}
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (pWordLast->GetCountSpaceLast() == pWordLast->m_oText.GetCurSize())
{
pWordLast->m_oText = m_oTextItem;
pWordLast->m_dX = x;
pWordLast->m_dWidth = width;
}
else
{
pWordLast->m_oText += m_oTextItem;
pWordLast->m_dWidth = x + width - pWordLast->m_dX; // <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if (5 < pWordLast->GetCountLastPoints())
m_bIsNewLine = true;
}
if (!m_oTextItem.IsSpace())
pWordLast->m_dWidthWithoutSpaces = pWordLast->m_dWidth;
}
}
public:
AVSINLINE void CommandText(BSTR& bsText, BSTR& bsGid, double& x, double& y, double& width, double& height, double& baselineoffset, LONG& lIndexZ)
{
if (NULL == bsText)
return;
m_lIndexZ = lIndexZ;
m_oTextItem.SetText(bsText);
if (0 == m_oTextItem.GetCurSize())
return;
if (bsGid != NULL)
{
m_oTextItem.CorrectUnicode(m_oFontManager.m_mapUnicode);
return CommandText2(bsGid, x, y, width, height, baselineoffset);
}
if (m_bIsPDFTextStyle)
{
return CommandText2(bsGid, x, y, width, height, baselineoffset);
}
return CommandText1(x, y, width, height, baselineoffset);
}
};
}