#pragma once #ifdef _DEBUG //#define TME_DEBUG //#define TME_DEBUG_VSXML //#define TME_LOG(msg, offset) MeasurerLogger::log3(msg, offset) //#define TME_SHOW_TABS //#define TME_EMPTY_DRAWING //#define TME_DONT_OUTPUT_HEADER_FOOTER //#define TME_NODE_XML //#define TME_DRAW_SYMBOL_BORDER //#define TME_DRAW_LINE_BORDER //#define TME_DRAW_LETTER_BORDER //#define TME_TEXT_BLACK //#define TME_RENDERER_COMMAND_DEBUG #endif #include #include "Structures.h" #include "Wrap.h" namespace ImageStudio { namespace Serialize { namespace Paint { namespace Common { #include "Numeration.h" #include "RendererCommands.h" #include "Settings.h" class MeasurerLogger { public: static void log3(CString text, const int& offset) { log2(text, offset); } static void log3(float value, const int& offset) { CString text; text.Format(_T("%f\n"), value); log2(text, offset, false); } static void log3(int value, const int& offset) { CString text; text.Format(_T("%d\n"), value); log2(text, offset, false); } private: static void log2(CString text, const int& offset, const bool& applyLevel = true) { static int level = 0; if (text != _T("")) { if (applyLevel) for (int i = 0; i < level; ++i) text = _T("\t") + text; log(text); } level += offset; } static void log(const CString& text) { static const char logFilePath[] = "c:\\temp\\measurerLog.xml"; FILE* logFile; fopen_s(&logFile, logFilePath, "a+"); fwprintf_s(logFile, L"%s", text); fclose(logFile); } }; class CDrawGraphicPath; class ITextPainter { public: virtual void CommandText(BSTR bsText, double fX, double fY, double fWidth, double fHeight, double fBaseLineOffset, IAVSRenderer *pRenderer) = 0; }; class IWorker { // Methods public: virtual void IWorker_Resume() = 0; virtual void IWorker_Pause() = 0; virtual void IWorker_Stop() = 0; // Events public: virtual void IWorker_OnNewPage(double dWidthMm, double dHeightMm) = 0; virtual void IWorker_OnCompletePage() = 0; public: virtual void IWorker_OnProgress(double dCompleteness) = 0; }; class CTextMeasurer : public IWorker { protected: // ### ### ### static enum CAlignHorizontal { NoneAlign = 0, LeftAlign, CenterAlign, RightAlign, WideAlign }; static enum CAlignVertical { NoneAlignVert = 0, FarAlignVert, CenterAlignVert, NearAlignVert }; static enum CRelativeFrom { FromCharacter = 0, FromLine, FromColumn, FromParagraph, FromPage, FromMargin, FromInsideMargin, FromOutsideMargin, FromLeftMargin, FromRightMargin, FromBottomMargin, FromTopMargin }; static enum CItemType { Symbols = 0, Space, LineEnd, TabStop, Bullet, Word, Alternate, Footnote, None }; // ### ### ### class CDocumentManager; class CGraphicLine { public: REAL m_fStartX; REAL m_fStartY; REAL m_fFinishX; REAL m_fFinishY; CPen m_oPen; public: // --- CGraphicLine() : m_fStartX(0.0f), m_fStartY(0.0f), m_fFinishX(0.0f), m_fFinishY(0.0f) { } // --- void Clear() { m_fStartX = 0.0f; m_fStartY = 0.0f; m_fFinishX = 0.0f; m_fFinishY = 0.0f; } // --- void SetStartPoint(const REAL &fStartX, const REAL &fStartY) { m_fStartX = fStartX; m_fStartY = fStartY; } void SetFinishPoint(const REAL &fFinishX, const REAL &fFinishY) { m_fFinishX = fFinishX; m_fFinishY = fFinishY; } void SetPen(const CPen &oPen) { m_oPen = oPen; } void MoveOn(const REAL &fDeltaX, const REAL &fDeltaY) { m_fStartX += fDeltaX; m_fStartY += fDeltaY; m_fFinishX += fDeltaX; m_fFinishY += fDeltaY; } // --- void Draw(IAVSRenderer *pRenderer, const REAL &fCompleteness) { m_oPen.SetToRenderer(pRenderer); pRenderer->BeginCommand(c_nPathType); //pRenderer->BeginCommand(c_nTextGraphicType); pRenderer->PathCommandStart(); pRenderer->PathCommandMoveTo(m_fStartX, m_fStartY); pRenderer->PathCommandLineTo(m_fFinishX, m_fFinishY); pRenderer->PathCommandClose(); pRenderer->DrawPath(0x01); pRenderer->PathCommandEnd(); //pRenderer->EndCommand(c_nTextGraphicType); pRenderer->EndCommand(c_nPathType); /*pRenderer->PathCommandStart(); SAFEARRAYBOUND rgsab; rgsab.lLbound = 0; rgsab.cElements = 4; SAFEARRAY* pArray = SafeArrayCreate(VT_R4, 1, &rgsab); FLOAT* pBuffer = (FLOAT*)(pArray->pvData); memset(pBuffer, 0, rgsab.cElements * sizeof(float)); const float fPtToMm = *pBuffer = m_fStartX; ++pBuffer; *pBuffer = m_fStartY; ++pBuffer; *pBuffer = m_fFinishX; ++pBuffer; *pBuffer = m_fFinishY; ++pBuffer; pRenderer->PathCommandLinesTo(pArray); RELEASEARRAY(pArray); pRenderer->PathCommandClose(); pRenderer->DrawPath(0x01); pRenderer->PathCommandEnd();*/ } }; class CBackgroundRect { public: REAL m_fX; REAL m_fY; REAL m_fWidth; REAL m_fHeight; CBrush m_oBrush; public: // --- CBackgroundRect() : m_fX(0.0f), m_fY(0.0f), m_fWidth(0.0f), m_fHeight(0.0f) { } // --- void Clear() { m_fX = 0.0f; m_fY = 0.0f; m_fWidth = 0.0f; m_fHeight = 0.0f; } // --- void SetStartPoint(const REAL &fStartX, const REAL &fStartY) { m_fX = fStartX; m_fY = fStartY; } void SetSize(const REAL &fWidth, const REAL &fHeight) { m_fWidth = fWidth; m_fHeight = fHeight; } void SetBrush(const CBrush &oBrush) { m_oBrush = oBrush; } void MoveOn(const REAL &fDeltaX, const REAL &fDeltaY) { m_fX += fDeltaX; m_fY += fDeltaY; } // --- void Draw(IAVSRenderer *pRenderer, const REAL &fCompleteness) { if (m_oBrush.m_oBrush.Alpha1 != 0) { pRenderer->put_PenColor(m_oBrush.m_oBrush.Color1); pRenderer->put_PenSize(0); /*pRenderer->PathCommandStart(); pRenderer->PathCommandMoveTo(m_fX + m_fWidth, m_fY); pRenderer->PathCommandLineTo(m_fX + m_fWidth, m_fY + m_fHeight); pRenderer->PathCommandLineTo(m_fX, m_fY + m_fHeight); pRenderer->DrawPath(c_nStroke); pRenderer->PathCommandEnd();*/ m_oBrush.SetToRenderer(pRenderer); pRenderer->BeginCommand(c_nPathType); //pRenderer->BeginCommand(c_nTextGraphicType); pRenderer->PathCommandStart(); pRenderer->PathCommandMoveTo(m_fX, m_fY); pRenderer->PathCommandLineTo(m_fX + m_fWidth, m_fY); pRenderer->PathCommandLineTo(m_fX + m_fWidth, m_fY + m_fHeight); pRenderer->PathCommandLineTo(m_fX, m_fY + m_fHeight); pRenderer->PathCommandClose(); pRenderer->DrawPath(c_nWindingFillMode); pRenderer->PathCommandEnd(); //pRenderer->EndCommand(c_nTextGraphicType); pRenderer->EndCommand(c_nPathType); } } }; class CBulletProperties { public: CString m_strChar; REAL m_fSize; LONG m_iColor; public: // --- CBulletProperties() : m_strChar(_T("")), m_fSize(1.0f), m_iColor(0) { } // --- ~CBulletProperties() { Clear(); } // --- void Clear() { m_strChar = _T(""); m_fSize = 1.0f; m_iColor = 0; } // --- void FromXmlNode(XmlUtils::CXmlNode &oXmlNode) { m_strChar = oXmlNode.GetAttributeOrValue(_T("bulletchar"), _T("")); m_fSize = oXmlNode.ReadAttributeOrValueFloat(_T("bulletsize"), 100) / 100.0f; if (m_fSize <= 0) { m_fSize = 1.0f; } m_iColor = oXmlNode.ReadAttributeOrValueInt(_T("bulletcolor"), 0); } }; class CLinkProperties { public: BYTE nMode; CString strTarget; public: // --- CLinkProperties() : nMode(0), strTarget(_T("")) { } // --- void Clear() { nMode = 0; strTarget = _T(""); } // --- void FromXmlNode2(XmlUtils::CXmlNode& oXmlNode) { strTarget = oXmlNode.GetAttribute(_T("external-destination"), _T("")); if (strTarget != _T("")) { nMode = 2; } else { strTarget = oXmlNode.GetAttribute(_T("internal-destination"), _T("")); if (strTarget != _T("")) { nMode = 1; } } } }; class CBreakProperties : protected CXmlAttributeReader { public: int m_nBreakBeforeType; public: CBreakProperties() : m_nBreakBeforeType(0) { } void Clear() { m_nBreakBeforeType = 0; } public: void FromXmlNode2(XmlUtils::CXmlNode &oXmlNode) { CString strDefaultValue; strDefaultValue.Format(_T("%s"), GetBreakType(m_nBreakBeforeType)); SetBreakType(m_nBreakBeforeType, oXmlNode.GetAttributeOrValue(_T("break-before"), strDefaultValue)); } }; class CBorderProperties : private CXmlAttributeReader { public: class CSide { public: CPen m_oPen; public: CSide() : m_oPen() { } public: CGraphicLine* GetGraphicLine(const REAL &fStartX, const REAL &fStartY, const REAL &fFinishX, const REAL &fFinishY) { CGraphicLine *pGraphicLine = new CGraphicLine(); pGraphicLine->SetPen(m_oPen); pGraphicLine->SetStartPoint(fStartX * (25.4f / 72.0f), fStartY * (25.4f / 72.0f)); pGraphicLine->SetFinishPoint(fFinishX * (25.4f / 72.0f), fFinishY * (25.4f / 72.0f)); return pGraphicLine; } }; public: CSide *m_pLeftSide; CSide *m_pRightSide; CSide *m_pTopSide; CSide *m_pBottomSide; public: CBorderProperties() : m_pLeftSide(NULL), m_pRightSide(NULL), m_pTopSide(NULL), m_pBottomSide(NULL) { } CBorderProperties& operator=(const CBorderProperties& oSrc) { if (oSrc.m_pLeftSide != NULL) { m_pLeftSide = new CSide(); *m_pLeftSide = *oSrc.m_pLeftSide; } if (oSrc.m_pRightSide != NULL) { m_pRightSide = new CSide(); *m_pRightSide = *oSrc.m_pRightSide; } if (oSrc.m_pTopSide != NULL) { m_pTopSide = new CSide(); *m_pTopSide = *oSrc.m_pTopSide; } if (oSrc.m_pBottomSide != NULL) { m_pBottomSide = new CSide(); *m_pBottomSide = *oSrc.m_pBottomSide; } return *this; } int GetBorderType() { int res = 0; if (m_pLeftSide != NULL) res += 1; if (m_pRightSide != NULL) res += 2; if (m_pTopSide != NULL) res += 4; if (m_pBottomSide != NULL) res += 8; return res; } public: void Clear() { RELEASEOBJECT(m_pLeftSide); RELEASEOBJECT(m_pRightSide); RELEASEOBJECT(m_pTopSide); RELEASEOBJECT(m_pBottomSide); } void FromXmlNode2(XmlUtils::CXmlNode &oXmlNode) { LoadSide(oXmlNode, _T("left"), &m_pLeftSide); LoadSide(oXmlNode, _T("right"), &m_pRightSide); LoadSide(oXmlNode, _T("top"), &m_pTopSide); LoadSide(oXmlNode, _T("bottom"), &m_pBottomSide); } private: void LoadSide(XmlUtils::CXmlNode &oXmlNode, const CString &strSideName, CSide** ppSide) { CSide* pSide = *ppSide; CString strStyle = oXmlNode.GetAttributeOrValue(_T("border-") + strSideName + _T("-style"), _T("")); if (strStyle != _T("")) { if (strStyle == _T("none")) { RELEASEOBJECT(pSide); *ppSide = NULL; } else { if (pSide == NULL) { *ppSide = new CSide(); pSide = *ppSide; } CXmlAttributeReader::SetPenStyle(pSide->m_oPen.m_oPen, strStyle); REAL fWidth = oXmlNode.ReadAttributeOrValueFloat(_T("border-") + strSideName + _T("-width"), -1); if (fWidth > 0) { if (fWidth > 6) { fWidth = 1; } pSide->m_oPen.m_oPen.Size = fWidth * 0.3528f; } else { RELEASEOBJECT(pSide); *ppSide = NULL; return; } LONG iColor = CXmlAttributeReader::LongAttributeHexFromXml(oXmlNode, _T("border-") + strSideName + _T("-color"), -1); if (iColor >= 0) { if (iColor != 0xFFFFFF) pSide->m_oPen.m_oPen.Color = BGRToRGB(iColor); else pSide->m_oPen.m_oPen.Color = 0xFFFFFF; } } } } }; class CBackgroundProperties : private CXmlAttributeReader { public: CBackgroundRect* m_pRect; CBrush m_oBrush; public: CBackgroundProperties() : m_pRect(NULL) { } CBackgroundProperties& operator=(const CBackgroundProperties& oSrc) { if (oSrc.m_pRect != NULL) { m_pRect = new CBackgroundRect(); *m_pRect = *oSrc.m_pRect; } return *this; } CBackgroundRect* GetBackgroundRect(const REAL &fStartX, const REAL &fStartY, const REAL &fWidth, const REAL &fHeight) { CBackgroundRect *pBackgroundRect = new CBackgroundRect(); pBackgroundRect->SetBrush(m_oBrush); pBackgroundRect->SetStartPoint(fStartX * (25.4f / 72.0f), fStartY * (25.4f / 72.0f)); pBackgroundRect->SetSize(fWidth * (25.4f / 72.0f), fHeight * (25.4f / 72.0f)); return pBackgroundRect; } CBackgroundRect* GetBackgroundRect2(const REAL &fStartX, const REAL &fStartY, const REAL &fWidth, const REAL &fHeight) { CBackgroundRect *pBackgroundRect = new CBackgroundRect(); pBackgroundRect->SetBrush(m_oBrush); pBackgroundRect->SetStartPoint(fStartX , fStartY); pBackgroundRect->SetSize(fWidth, fHeight); return pBackgroundRect; } public: void Clear() { RELEASEOBJECT(m_pRect); } void PageBGFromXml(XmlUtils::CXmlNode & oXmlNode) { LONG iColor = CXmlAttributeReader::LongAttributeHexFromXml(oXmlNode, _T("w:color"), -1); if (iColor >= 0 && iColor != 0x00FFFFFF) { if (m_pRect == NULL) { CBackgroundRect* ppRect = new CBackgroundRect(); m_pRect = ppRect; } m_oBrush.m_oBrush.Color1 = BGRToRGB(iColor); m_oBrush.m_oBrush.Alpha1 = 255; } else { m_oBrush.m_oBrush.Alpha1 = 0; } } void FromXmlNode2(XmlUtils::CXmlNode &oXmlNode) { LONG iColor = CXmlAttributeReader::LongAttributeHexFromXml(oXmlNode, _T("background-color"), -1); if (iColor >= 0) { if (m_pRect == NULL) { CBackgroundRect* ppRect = new CBackgroundRect(); m_pRect = ppRect; } if (iColor != 0x00FFFFFF) m_oBrush.m_oBrush.Color1 = BGRToRGB(iColor); else m_oBrush.m_oBrush.Color1 = 0xFFFFFF; m_oBrush.m_oBrush.Alpha1 = 255; } else { m_oBrush.m_oBrush.Alpha1 = 0; } } bool HasColor() { //if () return !(m_pRect->m_oBrush.m_oBrush.Alpha1 == 0); } }; class CPaddingProperties : private CXmlAttributeReader { public: REAL m_fPaddingLeft; REAL m_fPaddingRight; REAL m_fPaddingTop; REAL m_fPaddingBottom; public: // --- CPaddingProperties() : m_fPaddingLeft(1.8f), m_fPaddingRight(1.8f), m_fPaddingTop(1.8f), m_fPaddingBottom(1.8f) { } // --- void Clear() { m_fPaddingLeft = 18.0f; m_fPaddingRight = 18.0f; m_fPaddingTop = 18.0f; m_fPaddingBottom = 18.0f; } // --- void FromXmlNode(XmlUtils::CXmlNode &oXmlNode) { m_fPaddingLeft = FloatPtAttributeFromXml(oXmlNode, _T("padding-left"), m_fPaddingLeft); if (m_fPaddingLeft < 0) m_fPaddingLeft = 1.8f; m_fPaddingRight = FloatPtAttributeFromXml(oXmlNode, _T("padding-right"), m_fPaddingRight); if (m_fPaddingLeft < 0) m_fPaddingLeft = 1.8f; m_fPaddingTop = FloatPtAttributeFromXml(oXmlNode, _T("padding-top"), m_fPaddingTop); if (m_fPaddingLeft < 0) m_fPaddingLeft = 1.8f; m_fPaddingBottom = FloatPtAttributeFromXml(oXmlNode, _T("padding-bottom"), m_fPaddingBottom); if (m_fPaddingLeft < 0) m_fPaddingLeft = 1.8f; } }; class CMarginProperties : protected CXmlAttributeReader { public: REAL m_nSpaceBefore; REAL m_nSpaceAfter; REAL m_nLineSpacing; // xsl-fo line-height.minimum REAL m_fLineHeight; REAL m_fStartIndent; REAL m_fEndIndent; REAL m_fTextIndent; public: CMarginProperties() : m_nSpaceBefore(0.0f), m_nSpaceAfter(0.0f), m_nLineSpacing(0.0f), m_fLineHeight(0.0f), m_fStartIndent(0.0f), m_fEndIndent(0.0f), m_fTextIndent(0.0f) { } public: void Clear() { m_nSpaceBefore = 0; m_nSpaceAfter = 0; m_nLineSpacing = 0; m_fLineHeight = 0; m_fStartIndent = 0; m_fEndIndent = 0; m_fTextIndent = 0; } void FromXmlNode(XmlUtils::CXmlNode &oXmlNode, CDocumentManager& documentManager) { m_nLineSpacing = -oXmlNode.ReadAttributeOrValueFloat(_T("linespacing"), 0); m_nSpaceBefore = -oXmlNode.ReadAttributeOrValueFloat(_T("spacebefore"), 0); m_nSpaceAfter = -oXmlNode.ReadAttributeOrValueFloat(_T("spaceafter"), 0); m_fStartIndent = oXmlNode.ReadAttributeOrValueFloat(_T("leftmargin"), 0) * documentManager.m_ItemManager.GetMultiplierX(); m_fEndIndent = oXmlNode.ReadAttributeOrValueFloat(_T("rightmargin"), 0) * documentManager.m_ItemManager.GetMultiplierX(); m_fTextIndent = oXmlNode.ReadAttributeOrValueFloat(_T("indent"), 0) * documentManager.m_ItemManager.GetMultiplierX(); if (m_fStartIndent + m_fTextIndent < 0) { m_fTextIndent = -m_fStartIndent; } } void FromXmlNode2(XmlUtils::CXmlNode &oXmlNode, const bool& bAndVerctical = true) { m_nSpaceBefore = FloatPtAttributeFromXml(oXmlNode, _T("space-before"), m_nSpaceBefore); m_nSpaceAfter = FloatPtAttributeFromXml(oXmlNode, _T("space-after"), m_nSpaceAfter); m_fLineHeight = FloatPtAttributeFromXml(oXmlNode, _T("line-height"), m_fLineHeight); if (m_fLineHeight < -4.0f) { m_fLineHeight = -1.0f; } m_nLineSpacing = FloatPtAttributeFromXml(oXmlNode, _T("line-height.minimum"), 0); if (m_nLineSpacing < -4.0f) { m_nLineSpacing = -1.0f; } if (bAndVerctical) { m_fStartIndent = FloatPtAttributeFromXml(oXmlNode, _T("start-indent"), m_fStartIndent); m_fEndIndent = FloatPtAttributeFromXml(oXmlNode, _T("end-indent"), m_fEndIndent); m_fTextIndent = FloatPtAttributeFromXml(oXmlNode, _T("text-indent"), m_fTextIndent); } } }; class CTabParams: CXmlAttributeReader { private: float m_fTabPosition; byte m_bLeader; byte m_bType; public: CTabParams() : m_fTabPosition(0), m_bLeader(0), m_bType(0) {} CTabParams(float fPos, byte bLeader, byte bType) : m_fTabPosition(fPos), m_bLeader(bLeader), m_bType(bType) {} CTabParams(float fPos, CString strLeader, CString strType) : m_fTabPosition(fPos) { m_bLeader = SetLeaderTab(strLeader); m_bType = SetTypeTab(strType); } ~CTabParams() {} friend bool operator>(const CTabParams& a, const CTabParams& b) { return (a.m_fTabPosition > b.m_fTabPosition) ? true : false; } friend bool operator<(const CTabParams& a, const CTabParams& b) { return (a.m_fTabPosition < b.m_fTabPosition) ? true : false; } friend bool operator>=(const CTabParams& a, const CTabParams& b) { return (a.m_fTabPosition >= b.m_fTabPosition) ? true : false; } friend bool operator<=(const CTabParams& a, const CTabParams& b) { return (a.m_fTabPosition <= b.m_fTabPosition) ? true : false; } public: float GetPosition() { return m_fTabPosition; } void SetPosition(float fPos) { m_fTabPosition = fPos; } byte GetLeader() { return m_bLeader; } void SetLeader(byte bLeader) { m_bLeader = bLeader; } byte GetType() { return m_bType; } void SetType(byte bType) { m_bType = bType; } }; class CTabProperties : protected CXmlAttributeReader { public: CArray m_arrTabs; float m_fDefaultTabSize; public: CTabProperties() : m_arrTabs(), m_fDefaultTabSize(0.0f) { } public: void Clear() { m_arrTabs.RemoveAll(); m_fDefaultTabSize = 0.0f; } void FromXmlNode(XmlUtils::CXmlNode &oXmlNode) { m_fDefaultTabSize = (REAL)oXmlNode.ReadAttributeOrValueInt(_T("defaulttabsize"), 0) * 72.0f / (36000.0f*25.4f); if (m_fDefaultTabSize < 0) m_fDefaultTabSize = -m_fDefaultTabSize; } void FromXmlNode2(XmlUtils::CXmlNode &oXmlNode) { m_fDefaultTabSize = FloatPtAttributeFromXml(oXmlNode, _T("default-tab-size"), 0); XmlUtils::CXmlNodes oTabsNodes; XmlUtils::CXmlNode oTabsNode; if (oXmlNode.GetNodes(_T("fo:tabs"), oTabsNodes)) { for(int i = 0; i < oTabsNodes.GetCount(); i++ ) if (oTabsNodes.GetAt(i, oTabsNode)) { XmlUtils::CXmlNodes oTabNodes; oTabsNode.GetNodes(_T("fo:tab"), oTabNodes); int iCount = oTabNodes.GetCount(); for (int iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oNode; oTabNodes.GetAt(iIndex, oNode); float fTabPosition = oNode.ReadAttributeOrValueFloat(_T("position"), -1); if (fTabPosition >= 0.0f) { CString tabLeader = oNode.GetAttributeOrValue(_T("leader")); CString tabType = oNode.GetAttributeOrValue(_T("val"), _T("left")); m_arrTabs.Add(CTabParams(fTabPosition, tabLeader, tabType)); } } } m_arrTabs.Sort(); Replace(); } } // left, num, void Replace() { size_t nSize = m_arrTabs.GetCount(); bool hasLeftInThisPosition = false; for(size_t i = 0; i < nSize; i++) { if (m_arrTabs[i].GetType() == 0) hasLeftInThisPosition = true; if (m_arrTabs[i].GetType() == 2) { if (i>0 && m_arrTabs[i].GetPosition() == m_arrTabs[i - 1].GetPosition() && hasLeftInThisPosition == true) { m_arrTabs[i].SetType(0); } else { size_t j = i; while (j < nSize - 1 && m_arrTabs[j].GetPosition() == m_arrTabs[j + 1].GetPosition() ) { j++; if (m_arrTabs[j].GetType() == 0) { m_arrTabs[i].SetType(0); break; } } } } } } }; class CBlockAttributes : public CMarginProperties, public CBreakProperties, public CTabProperties, public CBorderProperties, public CBackgroundProperties { public: BOOL m_bIsFirst; LONG m_lCount; WORD m_nTextAlignment; WORD m_nWrapFlags; BYTE m_nKeepTogether; BYTE m_nKeepNext; bool _oneLine; CString m_pStyle; CString m_contextualSpacing; CBulletProperties *m_pBulletProperties; public: CBlockAttributes() : CMarginProperties(), CBreakProperties(), m_bIsFirst(FALSE), m_lCount(0), m_nTextAlignment(0), m_nWrapFlags(0), m_nKeepTogether(0), m_nKeepNext(0), m_pBulletProperties(NULL), m_pStyle(), m_contextualSpacing(), _oneLine(false) { } ~CBlockAttributes() { Clear(); } public: void Clear() { CMarginProperties::Clear(); CBreakProperties::Clear(); CTabProperties::Clear(); m_lCount = 0; m_nTextAlignment = 0; m_nWrapFlags = 1; m_nKeepTogether = 0; m_nKeepNext = 0; RELEASEOBJECT(m_pBulletProperties); _oneLine = false; } void FromXmlNode(XmlUtils::CXmlNode &oXmlNode, CDocumentManager& documentManager) { m_lCount = oXmlNode.ReadAttributeOrValueInt(_T("count"), 0); int nTextAlignment = (WORD)oXmlNode.ReadAttributeOrValueInt(_T("textalignment"), -1); if (nTextAlignment >= 0) { m_nTextAlignment = nTextAlignment; } m_nWrapFlags = (WORD)oXmlNode.ReadAttributeOrValueInt(_T("wrapflags"), 0); WORD nBulletFlag = (WORD)oXmlNode.ReadAttributeOrValueInt(_T("bulletflag"), 0); if (nBulletFlag & 1) { RELEASEOBJECT(m_pBulletProperties); m_pBulletProperties = new CBulletProperties(); m_pBulletProperties->FromXmlNode(oXmlNode); } CMarginProperties::FromXmlNode(oXmlNode, documentManager); CTabProperties::FromXmlNode(oXmlNode); if (oXmlNode.GetAttribute(_T("oneline")) == _T("1")) _oneLine = true; else _oneLine = false; } void FromXmlNode2(XmlUtils::CXmlNode &oXmlNode, const bool &bMarginSet = true) { CMarginProperties::FromXmlNode2(oXmlNode, bMarginSet); m_arrTabs.Add(CTabParams((float)m_fStartIndent - 0.001, _T("leader"), _T("num"))); CBreakProperties::FromXmlNode2(oXmlNode); CTabProperties::FromXmlNode2(oXmlNode); CBorderProperties::FromXmlNode2(oXmlNode); CBackgroundProperties::FromXmlNode2(oXmlNode); m_pStyle = oXmlNode.GetAttributeOrValue(_T("fo:pStyle"), _T("usualStyle")); m_contextualSpacing = oXmlNode.GetAttributeOrValue(_T("fo:contextualSpacing"), _T("false")); CString strDefaultValue; strDefaultValue.Format(_T("%s"), GetTextAlignment(m_nTextAlignment)); SetTextAlignment(m_nTextAlignment, oXmlNode.GetAttributeOrValue(_T("text-align"), strDefaultValue)); SetKeepTogether(m_nKeepTogether, oXmlNode.GetAttributeOrValue(_T("keep-together.within-page"))); SetKeepNext(m_nKeepNext, oXmlNode.GetAttributeOrValue(_T("keep-with-next"))); } }; class CBlockFrameAttributes : private CXmlAttributeReader { public: CString m_dropCap; int m_lines; public: double m_vSpace; double m_hSpace; public: CString m_vAnchor; CString m_hAnchor; CString m_xAlign; CString m_yAlign; public: double m_x; double m_y; double m_width; double m_height; public: CString m_wrap; public: CBlockFrameAttributes() : m_dropCap(_T("")), m_lines(0), m_vSpace(0), m_hSpace(0), m_vAnchor(_T("")), m_hAnchor(_T("")), m_wrap(_T("")), m_x(-1), m_y(-1), m_width(0), m_height(0) { } public: void FromXmlNode(XmlUtils::CXmlNode &oXmlNode) { #ifdef AVS_LOG_DEBUG CString p = oXmlNode.GetXml(); #endif m_dropCap = oXmlNode.GetAttributeOrValue(_T("w:dropCap"), _T("")); m_lines = oXmlNode.ReadAttributeOrValueInt(_T("w:lines"), 0); m_vSpace = oXmlNode.ReadAttributeOrValueDouble(_T("w:vSpace"), 0) / 20; m_hSpace = oXmlNode.ReadAttributeOrValueDouble(_T("w:hSpace"), 0) / 20; m_vAnchor = oXmlNode.GetAttributeOrValue(_T("w:vAnchor"), _T("")); m_hAnchor = oXmlNode.GetAttributeOrValue(_T("w:hAnchor"), _T("")); m_xAlign = oXmlNode.GetAttributeOrValue(_T("w:xAlign"), _T("")); m_yAlign = oXmlNode.GetAttributeOrValue(_T("w:yAlign"), _T("")); m_x = oXmlNode.ReadAttributeOrValueDouble(_T("w:x"), -1)/20; m_y = oXmlNode.ReadAttributeOrValueDouble(_T("w:y"), -1)/20; m_width = oXmlNode.ReadAttributeOrValueDouble(_T("w:w"), 0)/20; m_height = oXmlNode.ReadAttributeOrValueDouble(_T("w:h"), 0)/20; m_wrap = oXmlNode.GetAttributeOrValue(_T("w:wrap"), _T("")); } }; class CListBlockAttributes : public CBreakProperties { public: CListBlockAttributes() : CBreakProperties() { } ~CListBlockAttributes() { Clear(); } public: void Clear() { CBreakProperties::Clear(); } void FromXmlNode2(XmlUtils::CXmlNode &oXmlNode) { XmlUtils::CXmlNode oItemNode; oXmlNode.GetNode(_T("fo:list-item"), oItemNode); CBreakProperties::FromXmlNode2(oItemNode); } }; class CTextAttributes : private CXmlAttributeReader { public: enum ETextTransform { NoneTransform = 0, CapsTransform, SmallCapsTransform }; public: CFont m_oFont; CString m_FontFamilyEA; CString _fontFamilyCS; CBrush m_oBrush; CShadow m_oShadow; CBackground m_oBackground; CEdge m_oEdge; WORD m_nTextAlignmentVertical; WORD m_nTextAlignmentHorizontal; BOOL m_bAntiAliasText; WORD m_nBaselineShift; REAL m_fBaselineShift; public: CTextAttributes() : m_oFont(), m_FontFamilyEA(_T("")), _fontFamilyCS(_T("")), m_oBrush(), m_oShadow(), m_oBackground(), m_oEdge(), m_nTextAlignmentVertical(0), m_nTextAlignmentHorizontal(0), m_bAntiAliasText(TRUE), m_nBaselineShift(0), m_fBaselineShift(0.0f), m_TextTransform(NoneTransform) { } CTextAttributes& operator=(const CTextAttributes& oSrc) { m_oFont = oSrc.m_oFont; m_FontFamilyEA = oSrc.m_FontFamilyEA; _fontFamilyCS = oSrc._fontFamilyCS; m_oBrush = oSrc.m_oBrush; m_oShadow = oSrc.m_oShadow; m_oBackground = oSrc.m_oBackground; m_oEdge = oSrc.m_oEdge; m_nTextAlignmentVertical = oSrc.m_nTextAlignmentVertical; m_nTextAlignmentHorizontal = oSrc.m_nTextAlignmentHorizontal; m_bAntiAliasText = oSrc.m_bAntiAliasText; m_nBaselineShift = oSrc.m_nBaselineShift; m_fBaselineShift = oSrc.m_fBaselineShift; m_TextTransform = oSrc.m_TextTransform; return *this; } public: void FromXmlNode(XmlUtils::CXmlNode &oXmlNode) { m_oFont.FromXmlNode(oXmlNode); m_oBrush.FromXmlNode(oXmlNode); m_oShadow.FromXmlNode(oXmlNode); m_oBackground.FromXmlNode(oXmlNode); m_oEdge.FromXmlNode(oXmlNode); m_nTextAlignmentVertical = 1 + (WORD)oXmlNode.ReadAttributeOrValueInt(_T("font-stringalignmentvertical"), 0); m_nTextAlignmentHorizontal = (WORD)oXmlNode.ReadAttributeOrValueInt(_T("font-stringalignmenthorizontal"), 0); m_bAntiAliasText = (BOOL)oXmlNode.ReadAttributeOrValueInt(_T("font-antialiastext"), -1); m_fBaselineShift = oXmlNode.ReadAttributeOrValueFloat(_T("baseline-shift"), 0) / 100.0f; if (m_fBaselineShift != 0) { m_fBaselineShift *= (REAL)m_oFont.m_oFont.Size; m_oFont.m_oFont.Size = m_oFont.m_oFont.Size * 0.667f; } } void FromXmlNode2(XmlUtils::CXmlNode &oXmlNode) { FromXmlAttributes(oXmlNode); } void FromXmlNode3(XmlUtils::CXmlNode &oXmlNode, bool IsInTOC) { if (IsInTOC == false) { XmlUtils::CXmlNode oXmlComplete; oXmlNode.GetNode(_T("style-complete"), oXmlComplete); FromXmlAttributes(oXmlComplete); } else { XmlUtils::CXmlNode oXmlReduce; oXmlNode.GetNode(_T("style-reduce"), oXmlReduce); FromXmlAttributes(oXmlReduce); } } public: const ETextTransform& TextTransform() const { return m_TextTransform; } public: void ProcessFontProperties(XmlUtils::CXmlNode& character, CDocumentManager& documentManager) { XmlUtils::CXmlNode fontProperties; if (character.GetNode(_T("FontProperties"), fontProperties)) documentManager.AddFont(m_oFont, fontProperties.GetXml()); } private: ETextTransform m_TextTransform; private: void FromXmlAttributes(XmlUtils::CXmlNode &oXmlNode) { XML::IXMLDOMNamedNodeMapPtr pAttributes = oXmlNode.GetAttributes(); if (NULL == pAttributes) return; m_oFont.FromXmlAttributes(pAttributes); BSTR value = GetAttribute(pAttributes, g_cpszXML_Font_Family_EA); if (value != NULL) { m_FontFamilyEA = value; SysFreeString(value); } value = GetAttribute(pAttributes, g_cpszXML_Font_Family_CS); if (value != NULL) { _fontFamilyCS = value; SysFreeString(value); } m_oBrush.FromXmlAttributes(pAttributes); m_oShadow.FromXmlAttributes(pAttributes); m_oBackground.FromXmlAttributes(pAttributes); BSTR bsValue = GetAttribute(pAttributes, g_cpszXML_Text_Align); if (NULL != bsValue) { m_nTextAlignmentHorizontal = (WORD)XmlUtils::GetInteger(bsValue); SysFreeString(bsValue); } else m_nTextAlignmentHorizontal = 0; bsValue = GetAttribute(pAttributes, g_cpszXML_Text_BaselineShift); if (NULL != bsValue) { CString strValue = (CString)bsValue; SetBaselineShift(m_nBaselineShift, m_fBaselineShift, strValue); SysFreeString(bsValue); } if (m_nBaselineShift != 0) m_oFont.m_oFont.Size = m_oFont.m_oFont.Size * 0.667f; value = GetAttribute(pAttributes, g_cpszXML_Text_Transform); if (value != NULL) { CString transform = value; SysFreeString(value); if (transform == _T("caps")) m_TextTransform = CapsTransform; } else m_TextTransform = NoneTransform; } void LoadBaseline(XmlUtils::CXmlNode &oXmlNode) { CString strDefaultValue = _T(""); strDefaultValue.Format(_T("%s"), GetBaselineShift(m_nBaselineShift)); SetBaselineShift(m_nBaselineShift, m_fBaselineShift, oXmlNode.GetAttributeOrValue(_T("baseline-shift"), strDefaultValue)); if (m_nBaselineShift != 0) m_oFont.m_oFont.Size = m_oFont.m_oFont.Size * 0.667f; } public: void checkFontRange(CString& text) { if (text.GetLength() < 1) return; WCHAR symbol = text[0]; if ((0x2e80 <= symbol) && (symbol <= 0x9fff) && (m_FontFamilyEA != _T(""))) m_oFont.SetName(m_FontFamilyEA); else if ((0x0590 <= symbol) && (symbol <= 0x05ff) && (_fontFamilyCS != _T(""))) m_oFont.SetName(_fontFamilyCS); } }; class CCharacter { private: bool _isLabel; public: LONG m_lCount; CTextAttributes m_oAttributes; CLinkProperties m_oLink; BYTE m_nAdditionalParam; public: CCharacter() : m_oAttributes(), m_lCount(0), m_oLink(), m_nAdditionalParam(0), _isLabel(false) { } CCharacter(const CCharacter& src) { m_lCount = src.m_lCount; m_oAttributes = src.m_oAttributes; m_oLink = src.m_oLink; m_nAdditionalParam = src.m_nAdditionalParam; _isLabel = src._isLabel; } ~CCharacter() { } public: void FromXmlNode(XmlUtils::CXmlNode& oXmlNode) { m_lCount = oXmlNode.ReadAttributeOrValueInt(_T("count"), 0); XmlUtils::CXmlNode oAttributeNode; if (oXmlNode.GetNode(_T("Attributes"), oAttributeNode)) m_oAttributes.FromXmlNode(oAttributeNode); } void FromXmlNode(XmlUtils::CXmlNode& oXmlNode, CDocumentManager& documentManager) { FromXmlNode(oXmlNode); m_oAttributes.ProcessFontProperties(oXmlNode, documentManager); } void FromXmlNode2(XmlUtils::CXmlNode &oXmlNode, CLinkProperties& oLink) { if (oXmlNode.GetName() == _T("fo:inline")) { CString strText = oXmlNode.GetTextExt(); m_lCount = strText.GetLength(); } m_oLink = oLink; m_oAttributes.FromXmlNode2(oXmlNode); } void FromXmlNode3(XmlUtils::CXmlNode &oXmlNode, CLinkProperties& oLink, bool IsInTOC) { if (oXmlNode.GetName() == _T("fo:inline")) { CString strText = oXmlNode.GetTextExt(); m_lCount = strText.GetLength(); } m_oLink = oLink; m_oAttributes.FromXmlNode3(oXmlNode, IsInTOC); } void FromXmlNode2(XmlUtils::CXmlNode &oXmlNode) { if (oXmlNode.GetName() != _T("text")) { m_oAttributes.FromXmlNode2(oXmlNode); m_lCount = 0; } else { CString strText = oXmlNode.GetTextExt(); m_lCount = strText.GetLength(); } } void FromXmlNode3(XmlUtils::CXmlNode &oXmlNode, bool IsInTOC) { if (oXmlNode.GetName() != _T("text")) { m_oAttributes.FromXmlNode3(oXmlNode, IsInTOC); m_lCount = 0; } else { CString strText = oXmlNode.GetTextExt(); m_lCount = strText.GetLength(); } } public: inline bool getIsLabel() const { return _isLabel; } inline void setIsLabel(const bool& value) { _isLabel = value; } public: void Transform(CString& text) { try { if (m_oAttributes.TextTransform() == CTextAttributes::CapsTransform) CharUpper(text.GetBuffer()); } catch (...) { } } void CheckFontRange(CString& text) { m_oAttributes.checkFontRange(text); } }; // ### ### ### class CPage; class CRegion; class CAlternate2; class CItem; class CSymbols; class CBullet; class CTabStop; class CFootnote; class CGrapher; class CFontTable { public: class CFontProperties { public: CFontProperties() : m_Name(_T("")), m_AltName(_T("")), m_Charset(0), m_Family(_T("")), m_Panose(_T("")), m_Fixed(_T("1")), m_SigUsb0(_T("00000000")), m_SigUsb1(_T("00000000")), m_SigUsb2(_T("00000000")), m_SigUsb3(_T("00000000")), m_SigCsb0(_T("00000000")), m_SigCsb1(_T("00000000")) { } public: byte FromXml(XmlUtils::CXmlNode& font, const CString& name, IAVSFontManager* fontManager) { m_Name = name; FromXml(font); CString params = _T(""); CString charset; charset.Format(_T("%x"), m_Charset); params += _T(""); params += _T(""); params += _T(""); params += _T(""); params += _T(""); params += _T(""); params += _T(""); params += _T(""); BSTR bstrFontPath; long index = 0; BSTR bstrParams = params.AllocSysString(); fontManager->GetWinFontByParams(bstrParams, &bstrFontPath, &index); SysFreeString(bstrParams); int status = fontManager->LoadFontFromFile(bstrFontPath, 12, 72, 72, index); SysFreeString(bstrFontPath); if (!CheckRange(fontManager)) { params = _T(""); CString charset; charset.Format(_T("%x"), m_Charset); params += _T(""); params += _T(""); params += _T(""); params += _T(""); index = 0; bstrParams = params.AllocSysString(); fontManager->GetWinFontByParams(bstrParams, &bstrFontPath, &index); SysFreeString(bstrParams); status = fontManager->LoadFontFromFile(bstrFontPath, 12, 72, 72, index); SysFreeString(bstrFontPath); } BSTR bstrFamilyName; fontManager->GetFamilyName(&bstrFamilyName); m_Name = CString(bstrFamilyName); SysFreeString(bstrFamilyName); return 0; } byte FromXml(const CFont& font, const CString& properties, IAVSFontManager* fontManager) { BSTR bstrFontPath; long index = 0; BSTR bstrParams = properties.AllocSysString(); fontManager->GetWinFontByParams(bstrParams, &bstrFontPath, &index); SysFreeString(bstrParams); int status = fontManager->LoadFontFromFile(bstrFontPath, 12, 72, 72, index); BSTR bstrFamilyName; fontManager->GetFamilyName(&bstrFamilyName); m_Name = CString(bstrFamilyName); SysFreeString(bstrFamilyName); return 0; } public: CString Name() const { return m_Name; } void Name(const CString& name) { m_Name = name; } CString AltName() const { return m_AltName; } void AltName(const CString& altName) { m_AltName = altName; } public: bool CheckRange(IAVSFontManager* fontManager) const { unsigned char charset = (unsigned char)m_Charset; unsigned long bit; unsigned int index; GetCodePageByCharset(charset, &bit, &index); VARIANT_BOOL rangeSuits = VARIANT_FALSE; fontManager->IsUnicodeRangeAvailable(bit, index, &rangeSuits); return (rangeSuits == VARIANT_TRUE); } private: CString m_Name; CString m_AltName; int m_Charset; CString m_Family; CString m_Panose; CString m_Fixed; CString m_SigUsb0; CString m_SigUsb1; CString m_SigUsb2; CString m_SigUsb3; CString m_SigCsb0; CString m_SigCsb1; private: byte FromXml(XmlUtils::CXmlNode& font) { XmlUtils::CXmlNode altName; if (font.GetNode(_T("altName"), altName)) m_AltName = altName.GetText(); XmlUtils::CXmlNode charset; if (font.GetNode(_T("charset"), charset)) m_Charset = HexToInt(charset.GetText()); XmlUtils::CXmlNode family; if (font.GetNode(_T("family"), family)) m_Family = family.GetText(); XmlUtils::CXmlNode panose; if (font.GetNode(_T("panose"), panose)) m_Panose = panose.GetText(); XmlUtils::CXmlNode fixed; if (font.GetNode(_T("fixed"), fixed)) m_Fixed = fixed.GetText(); XmlUtils::CXmlNode sig; if (font.GetNode(_T("sig"), sig)) { m_SigUsb0 = sig.GetAttribute(_T("usb0"), _T("00000000")); m_SigUsb1 = sig.GetAttribute(_T("usb1"), _T("00000000")); m_SigUsb2 = sig.GetAttribute(_T("usb2"), _T("00000000")); m_SigUsb3 = sig.GetAttribute(_T("usb3"), _T("00000000")); m_SigCsb0 = sig.GetAttribute(_T("csb0"), _T("00000000")); m_SigCsb1 = sig.GetAttribute(_T("csb1"), _T("00000000")); } return 0; } private: static int HexToInt(int hex) { if ( hex >= '0' && hex <= '9' ) return (hex - '0'); if ( hex >= 'a' && hex <= 'f' ) return (hex - 'a' + 10); if ( hex >= 'A' && hex <= 'F' ) return (hex - 'A' + 10); return 0; } static int HexToInt(CString hex) { int result = 0; int mult = 1; for (int i = hex.GetLength() - 1; i >= 0; --i ) { result += HexToInt(hex.GetAt(i)) * mult; mult <<= 4; } return result; } }; private: std::map m_Fonts; public: CFontTable() : m_Fonts() { } public: byte FromXml(XmlUtils::CXmlNode& fontTable, IAVSFontManager* fontManager) { XmlUtils::CXmlNodes fonts; if (!fontTable.GetNodes(_T("font"), fonts)) return 1; int fontCount = fonts.GetCount(); for (int index = 0; index < fontCount; ++index) { XmlUtils::CXmlNode font; fonts.GetAt(index, font); std::pair fontPair; fontPair.first = font.GetAttribute(_T("name")); if (fontPair.second.FromXml(font, fontPair.first, fontManager)) continue; m_Fonts.insert(fontPair); } return 0; } public: CString SetFont(const CFont& font, IAVSFontManager* fontManager) { bool contains = Contains(font.Name()); if (!contains) AddFont(font, fontManager); CFontProperties& properties = m_Fonts[font.Name()]; if (LoadFont(font, properties.Name(), fontManager) != S_OK) { BSTR fontName; fontManager->GetFamilyName(&fontName); properties.Name(fontName); SysFreeString(fontName); } return properties.Name(); } void AddFont(const CFont& font, const CString& properties, IAVSFontManager* fontManager) { std::pair fontPair; fontPair.first = font.Name(); fontPair.second.FromXml(font, properties, fontManager); m_Fonts.insert(fontPair); } public: CString GetName(const CFont& font) { return m_Fonts[font.Name()].Name(); } private: int LoadFont(const CFont& font, IAVSFontManager* fontManager) { return LoadFont(font, font.Name(), fontManager); } int LoadFont(const CFont& font, const CString& name, IAVSFontManager* fontManager) { BSTR bstrName = name.AllocSysString(); float size = (float)font.Size(); LONG style = font.Style(); int status = fontManager->LoadFontByName(bstrName, size, style, 72, 72); SysFreeString(bstrName); return status; } private: bool Contains(const CString& name) { return (m_Fonts.find(name) != m_Fonts.end()); } void AddFont(const CFont& font, IAVSFontManager* fontManager) { std::pair fontPair; fontPair.first = font.Name(); fontPair.second.Name(fontPair.first); m_Fonts.insert(fontPair); } }; class CLinker { private: struct CChain { CString m_strID; INT m_nID; RectF m_oRect; WORD m_nPageNumber; CChain(const CString& strID, const RectF& oRect, const WORD nPageNumber, const INT& nID = -1) : m_strID(strID), m_nID(nID), m_oRect(oRect), m_nPageNumber(nPageNumber) { } CChain() : m_strID(_T("")), m_nID(-1), m_oRect(), m_nPageNumber(0) { } }; CArray m_arrSources; CArray m_arrTargets; public: CLinker() : m_arrSources(), m_arrTargets() { } void Clear() { m_arrSources.RemoveAll(); m_arrTargets.RemoveAll(); } public: void AddTarget(const CString& strID, const RectF& oRect, const CDocumentManager& documentManager) { WORD pageIndex = documentManager.getPageIndex(); CChain oChain(strID, oRect, pageIndex); m_arrTargets.Add(oChain); } void AddSource(const CString& strID, const RectF& oRect, const CDocumentManager& documentManager, const bool& bIsExtern = true) { WORD nPageNumber = documentManager.getPageIndex() - 1; CChain oChain(strID, oRect, nPageNumber); m_arrSources.Add(oChain); } BSTR GenerateXml() { CString strXml; strXml += _T(""); size_t nCount = m_arrSources.GetCount(); for (size_t nIndex = 0; nIndex < nCount; ++nIndex) { strXml += _T(""); CChain* pChain = &m_arrSources[nIndex]; CString strSource; strSource.Format(_T(""), pChain->m_oRect.X, pChain->m_oRect.Y, pChain->m_oRect.Width, pChain->m_oRect.Height, pChain->m_nPageNumber); strXml += strSource; CChain* pChain2 = FindTarget(pChain->m_strID); if (pChain2 != 0) { strSource.Format(_T(""), pChain2->m_oRect.X, pChain2->m_oRect.Y, pChain2->m_nPageNumber); } else { strSource.Format(_T(""), pChain->m_strID); } strXml += strSource; strXml += _T(""); } strXml += _T(""); strXml.Replace(_T("&"), _T("&")); return strXml.AllocSysString(); } private: bool IsContains() { return NULL; } CChain* FindTarget(const CString& strID) { CChain* pTarget = NULL; size_t nCount = m_arrTargets.GetCount(); for (size_t nIndex = 0; nIndex < nCount; ++nIndex) { CString strTarget = m_arrTargets[nIndex].m_strID; INT iPos = 0; while (iPos != -1) { CString strToken = strTarget.Tokenize(_T(";"), iPos); if (strToken == strID) { iPos = 0; break; } } if (iPos == 0) { pTarget = &m_arrTargets[nIndex]; } } return pTarget; } }; class CItemManager { private: REAL m_fPrevLineHeight; REAL m_fMultiplierX; REAL m_fMultiplierY; REAL m_fWidthL; REAL m_fHeightL; bool m_bWrapFlags; bool m_bIsFo; public: CItemManager() : m_fPrevLineHeight(0), m_fMultiplierX(0), m_fMultiplierY(0), m_fWidthL(6000), m_fHeightL(6000), m_bWrapFlags(true), m_bIsFo(false) { } public: void SetMultiplierY(const REAL &fMultiplierY) { m_fMultiplierY = fMultiplierY / m_fHeightL; } REAL GetMultiplierY() { return m_fMultiplierY; } void SetMultiplierX(const REAL &fMultiplierX) { m_fMultiplierX = fMultiplierX / m_fWidthL; } REAL GetMultiplierX() { return m_fMultiplierX; } void SetWidthL(const REAL &fWidthL) { m_fWidthL = fWidthL; } void SetHeightL(const REAL &fHeightL) { m_fHeightL = fHeightL; } bool WrapBySymbol() { return m_bWrapFlags; } BYTE GetWrapFlags() { return m_bWrapFlags; } void SetWrapFlags(const WORD &nWrapFlags) { if (nWrapFlags & 1) { m_bWrapFlags = TRUE; } else { m_bWrapFlags = FALSE; } } void SetIsFo(const bool &bIsFo) { m_bIsFo = bIsFo; } bool IsFo() { return m_bIsFo; } public: void PrepareItems(const CString &strText, CBlockAttributes *pParagraph, CAtlArray &arrCharacters, CAtlArray &arrAlternates, CAtlArray &anchors, CAtlArray& arrFootnotes, CAtlArray& arrItems, CGrapher* pGrapher) { size_t nCharacterIndex = 0; size_t nCharacterCount = arrCharacters.GetCount(); if (nCharacterCount == 0) { INT iIndexContent = GetNextInline(arrAlternates, -1); INT iIndexFootnote = GetNextFootnote(arrFootnotes, -1); int indexAnchor = GetNextAnchor(anchors, -1); while (iIndexContent != -1) { arrItems.Add(arrAlternates[iIndexContent]); iIndexContent = GetNextInline(arrAlternates, iIndexContent); } while (indexAnchor != -1) { anchors[indexAnchor]->InlinePosition((int) arrItems.GetCount()); indexAnchor = GetNextAnchor(anchors, indexAnchor); } while (iIndexFootnote != -1) { arrItems.Add(arrFootnotes[iIndexFootnote]); iIndexFootnote = GetNextFootnote(arrFootnotes, iIndexFootnote); } return; } // add bullet symbol if (pParagraph->m_pBulletProperties != NULL) { CBullet *pBullet = CreateBullet(pParagraph->m_pBulletProperties, arrCharacters[nCharacterIndex], pGrapher); if (fabs(pParagraph->m_fTextIndent) > pBullet->GetRect().Width) { pBullet->GetRect().Width = fabs(pParagraph->m_fTextIndent); if (pParagraph->m_fTextIndent < -pParagraph->m_fStartIndent) pParagraph->m_fTextIndent = -pParagraph->m_fStartIndent; } arrItems.Add(pBullet); arrCharacters.InsertAt(nCharacterIndex, pBullet->GetCharacter()); ++nCharacterIndex; ++nCharacterCount; } CCharacter *pCurrentCharacter = arrCharacters[nCharacterIndex]; size_t nMaxLength = pCurrentCharacter->m_lCount; INT iIndexInStr = 0; INT iIndexContent = GetNextInline(arrAlternates, -1); int indexAnchor = GetNextAnchor(anchors, -1); INT iIndexFootnote = GetNextFootnote(arrFootnotes, -1); // process text string CString strTextCopy = strText; while (strTextCopy.GetLength() != 0) { // add inline alternate content to item array if (iIndexContent != -1) { while (iIndexInStr == arrAlternates[iIndexContent]->InlinePosition()) { arrItems.Add(arrAlternates[iIndexContent]); iIndexContent = GetNextInline(arrAlternates, iIndexContent); if (iIndexContent == -1) break; } } if (indexAnchor != -1) { while (iIndexInStr == anchors[indexAnchor]->InlinePosition()) { anchors[indexAnchor]->InlinePosition((int) arrItems.GetCount()); indexAnchor = GetNextAnchor(anchors, indexAnchor); if (indexAnchor == -1) break; } } if (iIndexFootnote != -1) { if (iIndexInStr == arrFootnotes[iIndexFootnote]->GetInilinePosition()) { arrItems.Add(arrFootnotes[iIndexFootnote]); iIndexFootnote = GetNextFootnote(arrFootnotes, iIndexFootnote); } } // get next syllable CSymbols *pSyllable = GetNextSyllable(strTextCopy, nMaxLength, pParagraph, pCurrentCharacter, pGrapher); if (pSyllable != 0) { iIndexInStr += pSyllable->GetLength(); arrItems.Add(pSyllable); } else { break; } // check is current character end if (nMaxLength == 0) { if (nCharacterIndex != nCharacterCount - 1) { ++nCharacterIndex; pCurrentCharacter = arrCharacters[nCharacterIndex]; nMaxLength = pCurrentCharacter->m_lCount; } else { break; } } } // add remaining alternate content while (iIndexContent != -1) { arrItems.Add(arrAlternates[iIndexContent]); iIndexContent = GetNextInline(arrAlternates, iIndexContent); } while (indexAnchor != -1) { anchors[indexAnchor]->InlinePosition((int) arrItems.GetCount()); indexAnchor = GetNextAnchor(anchors, indexAnchor); } while (iIndexFootnote != -1) { arrItems.Add(arrFootnotes[iIndexFootnote]); iIndexFootnote = GetNextFootnote(arrFootnotes, iIndexFootnote); } } // --- INT GetNextInline(CAtlArray &arrAlternateContent, INT iPreviousIndex) { if (iPreviousIndex < (INT)arrAlternateContent.GetCount() - 1) return ++iPreviousIndex; else return -1; } int GetNextAnchor(CAtlArray& anchors, const int& prevIndex) { if (prevIndex < (int)anchors.GetCount() - 1) return prevIndex + 1; else return -1; } INT GetNextFootnote(CAtlArray &arrFootnotes, INT iPreviousIndex) { if (iPreviousIndex < (INT)arrFootnotes.GetCount() - 1) { return ++iPreviousIndex; } else { return -1; } } // --- REAL GetPlcOrPxl(const REAL &iValue, const REAL &fHeight, const byte& nType = 0) { if (m_bIsFo == TRUE) { REAL fResult = 0.0f; if (iValue >= 0) { fResult = iValue; } else { fResult = iValue * (-fHeight); } //*/ if (nType == 1) { if (fResult < fHeight) { fResult = fHeight; } } //*/ return fResult; } else if (iValue < 0) { return ((-iValue)/100.0f)*fHeight; } else { return iValue*m_fMultiplierY; } } protected: CSymbols* GetNextSyllable(CString &strText, size_t &nMaxCount, CBlockAttributes *pParagraph, CCharacter *pCharacter, CGrapher* pGrapher) { int iMaxLength = (int)nMaxCount; if (iMaxLength <= 0) return NULL; //if (iMaxLength > 20) // iMaxLength = 20; if (iMaxLength > strText.GetLength()) iMaxLength = strText.GetLength(); CSymbols *pSyllable = NULL; if (iMaxLength == 0) return pSyllable; int iIndex = 0; if (strText[(int)iIndex] == _T('\t')) { ++iIndex; pSyllable = CreateTabStop(pCharacter, pGrapher); } else if (strText[(int)iIndex] == _T(' ')) { for (iIndex = 1; iIndex < iMaxLength; ++iIndex) if (strText[(int)iIndex] != _T(' ')) break; pSyllable = new CSpace(iIndex, pCharacter, pGrapher); ((CSpace*)pSyllable)->SetOriginWidth(); } else if (strText[(int)iIndex] == _T('\n')) { iIndex = 1; pSyllable = new CLineEnd(iIndex, pCharacter, pGrapher); } else { for (iIndex = 1; iIndex < iMaxLength; ++iIndex) if ((strText[(int)iIndex] == _T(' ')) || (strText[(int)iIndex] == _T('\n')) || (strText[(int)iIndex] == _T('\t'))) break; CString strSyllableText = strText.Mid(0, (int)iIndex); pSyllable = new CSymbols(strSyllableText, pCharacter, pGrapher); } strText.Delete(0, (int)iIndex); nMaxCount -= iIndex; return pSyllable; } CBullet* CreateBullet(CBulletProperties *pBulletProperties, CCharacter *pCharacter, CGrapher* pGrapher) { CCharacter *pBulletCharacter = new CCharacter(); pBulletCharacter->m_lCount = pBulletProperties->m_strChar.GetLength(); pBulletCharacter->m_oAttributes = pCharacter->m_oAttributes; double dFontSize = pBulletCharacter->m_oAttributes.m_oFont.m_oFont.Size; pBulletCharacter->m_oAttributes.m_oFont.m_oFont.Size = dFontSize * pBulletProperties->m_fSize; XmlUtils::CXmlNode oXmlBulletFontSettings; oXmlBulletFontSettings.FromXmlString(CString(_T(""))); pBulletCharacter->m_oAttributes.m_oFont.FromXmlNode(oXmlBulletFontSettings); CBullet *pBullet = new CBullet(pBulletProperties->m_strChar, pBulletCharacter, pGrapher); return pBullet; } CTabStop* CreateTabStop(CCharacter *pCharacter, CGrapher* pGrapher) { CCharacter *pTabStopCharacter = new CCharacter(); pTabStopCharacter->m_lCount = 1; pTabStopCharacter->m_oAttributes = pCharacter->m_oAttributes; XmlUtils::CXmlNode oXmlTabFontSettings; pTabStopCharacter->m_oAttributes.m_oFont.FromXmlNode(oXmlTabFontSettings); CTabStop *pTabStop = new CTabStop(pTabStopCharacter, pGrapher); return pTabStop; } }; class CDocumentManager { private: int m_iPageCount; int m_iCurrentPageNumber; int m_iBlocksCount; int m_iBlockIndex; bool m_bStaticProcessing; CArray m_arrTabs; float m_fDefaultTabSize; float _lastTab; float m_fLeftBorder; float m_fRightBorder; bool m_bTabReady; ListNumeration _listNum; PageNumeration _pageNum; float m_fWidthMm; float m_fHeightMm; CFontTable m_FontTable; bool m_UseHtmlSpacing; bool m_RendererHtml; public: CItemManager m_ItemManager; CLinker m_Linker; IAVSFontManager* m_FontManager; ITextPainter* m_TextPainter; public: CDocumentManager() : m_iCurrentPageNumber(0), m_iBlocksCount(0), m_iBlockIndex(0), m_bStaticProcessing(false), m_arrTabs(), m_fDefaultTabSize(0.0f), _lastTab(0), m_fLeftBorder(0.0f), m_fRightBorder(0.0f), m_bTabReady(false), _listNum(), m_fWidthMm(0.0f), m_fHeightMm(0.0f), m_FontTable(), m_UseHtmlSpacing(true), m_ItemManager(), m_Linker(), m_FontManager(NULL), m_TextPainter(NULL), m_RendererHtml(false) { } public: void loadFromXml(XmlUtils::CXmlNode& docInfoXml) { XmlUtils::CXmlNode listNumSettingsXml; if (docInfoXml.GetNode(_T("listSettings"), listNumSettingsXml)) _listNum.loadFromXml(listNumSettingsXml); XmlUtils::CXmlNode pageListNumSettingsXml; if (docInfoXml.GetNode(_T("pageNumSettings"), pageListNumSettingsXml)) _pageNum.loadFromXml(pageListNumSettingsXml); } void Clear() { m_iCurrentPageNumber = 0; m_iBlocksCount = 0; m_iBlockIndex = 0; m_bStaticProcessing = false; m_arrTabs.RemoveAll(); m_fDefaultTabSize = 0.0f; _lastTab = 0; m_fLeftBorder = 0.0f; m_fRightBorder = 0.0f; m_bTabReady = false; _listNum.clear(); _pageNum.clear(); m_UseHtmlSpacing = true; m_Linker.Clear(); m_TextPainter = NULL; m_RendererHtml = false; } public: void BlockCreated() { if (m_bStaticProcessing) return; ++m_iBlocksCount; } void BlockProcessed() { if (m_bStaticProcessing) return; if (m_iBlocksCount > 0) { ++m_iBlockIndex; if (m_iBlockIndex >= m_iBlocksCount - 2) m_iBlockIndex = m_iBlocksCount; } } void SetStaticProcessing(const bool bSet) { m_bStaticProcessing = bSet; } bool GetStaticProcessing() const { return m_bStaticProcessing; } float GetCompleteness() { if (m_iBlocksCount != 0) { float fProgress = (float)m_iBlockIndex / m_iBlocksCount; if (fProgress >= 0.99f) fProgress = 0.99f; return fProgress; } else return 0.99f; } public: void SetDefaultTab(const float& fDefaultTabSize, const float& fLeftBorder, const float& fRightBorder) { m_arrTabs.RemoveAll(); if (fDefaultTabSize != 0) m_fDefaultTabSize = fDefaultTabSize; else m_fDefaultTabSize = 35.433f; _lastTab = fLeftBorder; m_fLeftBorder = fLeftBorder; m_fRightBorder = fRightBorder; m_bTabReady = false; } void AddTab(CTabParams& Tab) { m_arrTabs.Add(CTabParams(m_fLeftBorder + Tab.GetPosition(), Tab.GetLeader(), Tab.GetType())); } CTabParams GetTabSize(const float& fCurrentPosition) { if (!m_bTabReady) { m_bTabReady = true; if (m_fDefaultTabSize != 0) { float fTabPosition = m_fLeftBorder; int iCount = (int)m_arrTabs.GetCount(); if (iCount) { _lastTab = m_arrTabs[iCount - 1].GetPosition(); while (fTabPosition < _lastTab) fTabPosition += m_fDefaultTabSize; } while (fTabPosition < m_fRightBorder) { m_arrTabs.Add(CTabParams(fTabPosition, 0, 0)); fTabPosition += m_fDefaultTabSize; } if (_lastTab < fTabPosition) _lastTab = fTabPosition; //m_arrTabs.Add(CTabParams(m_fRightBorder, 0, 0)); } } /*/ feature : ïîäñ÷¸ò ðàçìåðà òàáóëÿöèè çà ïðåäåëàìè ðàçìåòêè ñòðàíèöû if (fCurrentPosition > _lastTab) { do { _lastTab += m_fDefaultTabSize; m_arrTabs.Add(CTabParams(_lastTab, 0, 0)); } while (_lastTab < fCurrentPosition); } //*/ for (size_t nIndex = 0; nIndex < m_arrTabs.GetCount(); ++nIndex) { if (fCurrentPosition < m_arrTabs[nIndex].GetPosition() || (fCurrentPosition == m_arrTabs[nIndex].GetPosition() && m_arrTabs[nIndex].GetType() == 2)) { return CTabParams(m_arrTabs[nIndex].GetPosition() - fCurrentPosition + 0.001, m_arrTabs[nIndex].GetLeader(), m_arrTabs[nIndex].GetType()); } } if (fCurrentPosition <= m_fRightBorder) { return CTabParams(m_fRightBorder - fCurrentPosition - 0.001, 0, 0); } else return CTabParams(); } public: CString getListElement(const CString& id, const CString& numId, const int& level) { return _listNum.getElement(id, numId, level); } public: void setPageNumbering(const PageNumbering& numbering) { _pageNum.setNumbering(numbering); } void nextPage() { _pageNum.nextPage(); } int getPageIndex() const { return _pageNum.getPageIndex(); } CString getPageIndexString() const { return _pageNum.getPageIndexElement(); } int getPageCount() const { return _pageNum.getPageCount(); } CString getPageCountString() const { return _pageNum.getPageCountElement(); } public: void SetPage(const CPage& oPage) { m_fWidthMm = oPage.GetWidthMm(); m_fHeightMm = oPage.GetHeightMm(); } void SetBorders(const CRegion& oRegion) { m_fLeftBorder = oRegion.GetRectPt().GetLeft(); m_fRightBorder = oRegion.GetRectPt().GetRight(); } float GetPageWidthMm() { return m_fWidthMm; } float GetPageHeightMm() { return m_fHeightMm; } float GetPageLeftBorderMm() { return m_fLeftBorder; } float GetPageRightBorderMm() { return m_fRightBorder; } public: void FontTableFromXml(XmlUtils::CXmlNode& fontTable) { m_FontTable.FromXml(fontTable, m_FontManager); } void AddFont(const CFont& font, const CString& properties) { m_FontTable.AddFont(font, properties, m_FontManager); } CString SetFont(const CFont& font) { return m_FontTable.SetFont(font, m_FontManager); } CString GetFontName(const CFont& font) { return m_FontTable.GetName(font); } public: bool UseHtmlSpacing() { return m_UseHtmlSpacing; } void UseHtmlSpacing(const bool& useHtmlSpacing) { m_UseHtmlSpacing = useHtmlSpacing; } public: bool RendererHtml() const { return m_RendererHtml; } void RendererType(IAVSRenderer* renderer) { LONG rendererType; renderer->get_Type(&rendererType); if (rendererType == c_nHtmlRendrerer) m_RendererHtml = true; else m_RendererHtml = false; } }; class CGrapher { private: class CFontMetrics { private: float m_fLineSpacing; float m_fEmHeight; float m_fAscent; float m_fDescent; float m_fFontSize; public: CFontMetrics() : m_fLineSpacing(0), m_fEmHeight(0), m_fAscent(0), m_fDescent(0), m_fFontSize(0) { } public: void FromFontManager(IAVSFontManager* m_pFontManager) { unsigned short iTemp = 0; m_pFontManager->GetCellAscent(&iTemp); m_fAscent = iTemp; m_pFontManager->GetCellDescent(&iTemp); m_fDescent = iTemp; m_pFontManager->GetLineSpacing(&iTemp); m_fLineSpacing = iTemp; m_pFontManager->GetEmHeight(&iTemp); m_fEmHeight = iTemp; } void FontSize(const float& fFontSize) { m_fFontSize = fFontSize; } public: void ApplyToRect(RectF& oRect) { oRect.X = 0; oRect.Height = m_fLineSpacing * m_fFontSize / m_fEmHeight; oRect.Y = m_fDescent * m_fFontSize / m_fEmHeight - oRect.Height; } float GetDescent() { return (m_fDescent * m_fFontSize / m_fEmHeight); } }; private: IAVSFontManager* m_pFontManager; CFontMetrics m_oFontMetrics; NSStructuresGDI::CFont m_oldFont; bool m_FontSubstitute; public: CDocumentManager* m_DocumentManager; public: CGrapher() : m_pFontManager(NULL), m_oFontMetrics(), m_oldFont(), m_FontSubstitute(false), m_DocumentManager(NULL) { m_oldFont.Size = -1; } ~CGrapher() { Clear(); } void Clear() { RELEASEINTERFACE(m_pFontManager); m_oldFont.Size = -1; m_DocumentManager = NULL; } public: void FontManager(IAVSFontManager* pFontManager) { RELEASEINTERFACE(m_pFontManager); m_pFontManager = pFontManager; ADDREFINTERFACE(m_pFontManager); } void DocumentManager(CDocumentManager* documentManager) { assert(documentManager !=NULL); m_DocumentManager = documentManager; } public: float GetDescent(CCharacter* pCharacter) { return m_oFontMetrics.GetDescent(); } RectF GetRectForString(const CString& strText, CCharacter *pCharacter) { SetFont(pCharacter); BSTR bstrText = strText.AllocSysString(); m_pFontManager->LoadString(bstrText, 0, 0); SysFreeString(bstrText); RectF oRect; m_pFontManager->MeasureString2(&oRect.X, &oRect.Y, &oRect.Width, &oRect.Height); m_oFontMetrics.ApplyToRect(oRect); return oRect; } float* GetWidths(const CString& text, CCharacter* character) { SetFont(character); int length = text.GetLength(); float* widths = new float[length]; float temp = 0; float width = 0; float sumWidth = 0; for (int index = 0; index < length; ++index) { BSTR sysText = CString(text[index]).AllocSysString(); m_pFontManager->LoadString(sysText, 0, 0); SysFreeString(sysText); m_pFontManager->MeasureString2(&temp, &temp, &width, &temp); widths[index] = width + sumWidth; sumWidth += width; } return widths; } double GetStrikePosition(CCharacter *m_pCharacter) { BOOL bAvailible; m_pFontManager->IsCharAvailable(121, &bAvailible); if (bAvailible) { CString strText = _T("x"); BSTR bstrText = strText.AllocSysString(); m_pFontManager->LoadString(bstrText, 0, 0); SysFreeString(bstrText); RectF oRect; m_pFontManager->MeasureString(&oRect.X, &oRect.Y, &oRect.Width, &oRect.Height); float fFontSize = m_pCharacter->m_oAttributes.m_oFont.m_oFont.Size; double dStrike = fabs((double)(oRect.Y + oRect.Height / 2)); return dStrike; } else { return 0; } } double GetUnderlinePosition(CCharacter *m_pCharacter, double& dSize) { float fX1, fY1, fX2, fY2, fSize; m_pFontManager->GetUnderline(&fX1, &fY1, &fX2, &fY2, &fSize); float fFontSize = m_pCharacter->m_oAttributes.m_oFont.m_oFont.Size; double dUnderline = (double) (fY1); dSize = (double) fSize * 25.4 / 72.0 / 2.0; return dUnderline; } public: static IAVSFontManager* GenerateFontManager() { IAVSFontManager* pFontManager = NULL; CoCreateInstance(__uuidof(CAVSFontManager), NULL, CLSCTX_INPROC, __uuidof(IAVSFontManager), (void**)&pFontManager); pFontManager->Initialize(L""); CString strDefaultFontName = _T("Arial"); BSTR bstrDefaultFontName = strDefaultFontName.AllocSysString(); float fFontSize = 12; LONG iFontStyle = 0; pFontManager->SetDefaultFont(bstrDefaultFontName); SysFreeString(bstrDefaultFontName); return pFontManager; } private: void SetFont(CCharacter *pCharacter) { assert(m_DocumentManager != NULL); NSStructuresGDI::CFont& oFont = pCharacter->m_oAttributes.m_oFont.m_oFont; if (!oFont.IsEqual(&m_oldFont)) { m_FontSubstitute = false; m_oldFont = oFont; CString name = m_DocumentManager->SetFont(pCharacter->m_oAttributes.m_oFont); if (oFont.Name != name) { oFont.Name = m_DocumentManager->GetFontName(pCharacter->m_oAttributes.m_oFont); m_FontSubstitute = true; } m_oFontMetrics.FromFontManager(m_pFontManager); m_oFontMetrics.FontSize((float)oFont.Size); } else { if (m_FontSubstitute) oFont.Name = m_DocumentManager->GetFontName(pCharacter->m_oAttributes.m_oFont); } m_pFontManager->SetCharSpacing(oFont.CharSpace * (72.0f / 25.4f)); } }; class CAreaManager { private: CWrapRegion m_oWrapRegion; bool m_bHasWrap; public: CAreaManager() : m_oWrapRegion(), m_bHasWrap(false) { } ~CAreaManager() { Clear(); } public: void Clear() { m_oWrapRegion.RemoveAll(); m_bHasWrap = false; } public: void AddWrapPolygon(const CArray& arrPoints, const REAL& fDistanceLeft, const REAL& fDistanceRight) { if (arrPoints.GetCount() == 0) return; m_bHasWrap = true; CWrapPolygon oWrapPolygon; oWrapPolygon.SetPoints(arrPoints); m_oWrapRegion.Add(oWrapPolygon, fDistanceLeft, fDistanceRight); } REAL GetArea(const RectF& oLineRect, CArray& arrRects) { if (m_bHasWrap) { m_oWrapRegion.Calculate(oLineRect, arrRects); return 0; } else { arrRects.RemoveAll(); arrRects.Add(oLineRect); return -1; } } }; // ### ### ### class CItem { protected: RectF m_oRect; REAL m_fDescent; public: CItem() : m_oRect(), m_fDescent(0.0f) { } virtual ~CItem() { Clear(); } void Clear() { m_oRect = RectF(); m_fDescent = 0.0f; } public: virtual RectF& GetRect() { return m_oRect; } virtual REAL GetHeightPt() { return m_oRect.Height; } virtual REAL GetWidthPt() { return m_oRect.Width; } virtual REAL GetDescent() { return m_fDescent; } virtual void RestoreRect() { m_oRect.X = 0.0f; m_oRect.Y = -m_oRect.Height + m_fDescent; } virtual CItemType GetType() { return None; } public: virtual bool IsOneSymbol() { return false; } virtual bool CanRupture() { return false; } virtual bool CanRupture(CGrapher* grapher, const float& maxWidth) { return false; } virtual CItem* Rupture(const float& maxWidth, CGrapher* grapher, const bool& bySymbol = false , const bool& firstSymbolAlways = false) { return NULL; } virtual void SetOnBaseline(const bool& inited = true) { if (inited) MoveTo(0, m_fDescent - m_oRect.Height); else MoveTo(m_oRect.X, m_fDescent - m_oRect.Height); } virtual void Draw(IAVSRenderer *pRenderer, CDocumentManager& documentManager, const float &fCompleteness) = 0; virtual void MoveTo(const REAL &fNewX) { m_oRect.X = fNewX; } virtual void MoveTo(const REAL &fNewX, const REAL &fNewY) { m_oRect.X = fNewX; m_oRect.Y = fNewY; } virtual void MoveOn(const REAL &fDeltaX, const REAL &fDeltaY) { m_oRect.X += fDeltaX; m_oRect.Y += fDeltaY; } public: static void drawRect(IAVSRenderer* renderer, RectF rect) { static const float ptToMm = 25.4f / 72.0f; rect.X *= ptToMm; rect.Y *= ptToMm; rect.Width *= ptToMm; rect.Height *= ptToMm; renderer->put_PenColor(0x0000ff); renderer->put_PenSize(0.1); renderer->put_PenAlpha(255); renderer->BeginCommand(c_nPathType); renderer->BeginCommand(c_nTextGraphicType); renderer->PathCommandStart(); renderer->PathCommandMoveTo(rect.X, rect.Y); renderer->PathCommandLineTo(rect.X + rect.Width, rect.Y); renderer->PathCommandLineTo(rect.X + rect.Width, rect.Y + rect.Height); renderer->PathCommandLineTo(rect.X, rect.Y + rect.Height); renderer->PathCommandClose(); renderer->DrawPath(0x01); renderer->PathCommandEnd(); renderer->EndCommand(c_nPathType); renderer->EndCommand(c_nTextGraphicType); } }; class CSymbols : public CItem { protected: CString m_strText; CCharacter *m_pCharacter; public: double m_size; double m_underlinePosition; double m_strikePosition; public: CSymbols() : CItem(), m_strText(_T("")), m_pCharacter(NULL) { } CSymbols(CCharacter* pCharacter) : CItem(), m_strText(_T("")), m_pCharacter(pCharacter) { } CSymbols(const CString &strText, CCharacter* pCharacter, CGrapher* pGrapher) : CItem(), m_strText(strText), m_pCharacter(pCharacter) { m_oRect = pGrapher->GetRectForString(m_strText, pCharacter); m_fDescent = pGrapher->GetDescent(pCharacter); SetOnBaseline(); m_strikePosition = GetStrikePosition(pGrapher); m_underlinePosition = GetUnderlinePosition(pGrapher, m_size); } public: CCharacter* GetCharacter() { return m_pCharacter; } int GetLength() { return m_strText.GetLength(); } inline CItemType GetType() { return Symbols; } double GetStrikePosition( CGrapher* pGrapher) { double dPos = pGrapher->GetStrikePosition(m_pCharacter); if (dPos != 0) m_strikePosition = dPos; else m_strikePosition = GetDescent(); return dPos; } double GetUnderlinePosition( CGrapher* pGrapher, double& dSize) { double dPos = pGrapher->GetUnderlinePosition(m_pCharacter, dSize); return dPos; } bool CanRupture() { return (m_strText.FindOneOf(_T("-")) != -1); } bool CanRupture(CGrapher* grapher, const float& maxWidth) { if (m_strText.GetLength() == 0) return false; float* firstSymbolWidth = grapher->GetWidths((CString) m_strText[0], m_pCharacter); bool canRupture = false; if (firstSymbolWidth[0] <= maxWidth) canRupture = true; return canRupture; } public: bool IsOneSymbol() { return (m_strText.GetLength() == 1); } CItem* Rupture(const float& maxWidth, CGrapher* grapher, const bool& bySymbol = false , const bool& firstSymbolAlways = false) { float* widths = grapher->GetWidths(m_strText, m_pCharacter); int length = m_strText.GetLength(); int lastSuitItem = -1; CArray rupPositions; RupturePositions(rupPositions); int rupPositionsCount = (int)rupPositions.GetCount(); if (rupPositionsCount > 0) { int rupPos = rupPositionsCount - 1; while (rupPos >= 0) if (widths[rupPositions[rupPos]] > maxWidth) --rupPos; else break; if (rupPos >= 0) lastSuitItem = rupPositions[rupPos]; } if (lastSuitItem < 0 && bySymbol) { lastSuitItem = length - 1; while (lastSuitItem >= 0) if (widths[lastSuitItem] > maxWidth) --lastSuitItem; else break; } RELEASEARRAYOBJECTS(widths); if (lastSuitItem == -1 && firstSymbolAlways) ++lastSuitItem; CSymbols* newItem = NULL; if (lastSuitItem >= 0) { CString newItemText = m_strText.Mid(0, lastSuitItem + 1); m_strText.Delete(0, lastSuitItem + 1); newItem = new CSymbols(newItemText, m_pCharacter, grapher); m_oRect = grapher->GetRectForString(m_strText, m_pCharacter); m_oRect.Y = newItem->m_oRect.Y; } return newItem; } void SetOnBaseline(const bool& bIsInit = true) { if (bIsInit) { MoveTo(0, m_fDescent - m_oRect.Height); } else { MoveTo(m_oRect.X, m_fDescent - m_oRect.Height); } if (m_pCharacter->m_oAttributes.m_nBaselineShift == 1) { MoveOn(0, -2 * m_fDescent); } else if (m_pCharacter->m_oAttributes.m_nBaselineShift == 2) { MoveOn(0, m_fDescent); } else if (m_pCharacter->m_oAttributes.m_fBaselineShift != 0) { MoveOn(0, -m_pCharacter->m_oAttributes.m_fBaselineShift); } } void Draw(IAVSRenderer *pRenderer, CDocumentManager& documentManager, const float &fCompleteness) { if (m_oRect.Width == 0) return; if (m_pCharacter->m_oLink.strTarget != _T("")) documentManager.m_Linker.AddSource(m_pCharacter->m_oLink.strTarget, m_oRect, documentManager); BSTR bstrText = m_strText.AllocSysString(); m_pCharacter->m_oAttributes.m_oFont.SetToRenderer(pRenderer); m_pCharacter->m_oAttributes.m_oBrush.SetToRenderer(pRenderer, fCompleteness); m_pCharacter->m_oAttributes.m_oShadow.SetToRenderer(pRenderer); m_pCharacter->m_oAttributes.m_oEdge.SetToRenderer(pRenderer); sendBaselineShiftToRenderer(pRenderer); #ifdef TME_TEXT_BLACK pRenderer->put_BrushColor1(0xff000000); #endif const float fPtToMm = 25.4f / 72.0f; if (m_pCharacter->getIsLabel()) pRenderer->BeginCommand(c_nNumberingMarker); if (NULL == documentManager.m_TextPainter) pRenderer->CommandDrawText(bstrText, m_oRect.X * fPtToMm, m_oRect.Y * fPtToMm, m_oRect.Width * fPtToMm, m_oRect.Height * fPtToMm, (m_oRect.Height - m_fDescent) * fPtToMm); else documentManager.m_TextPainter->CommandText(bstrText, m_oRect.X * fPtToMm, m_oRect.Y * fPtToMm, m_oRect.Width * fPtToMm, m_oRect.Height * fPtToMm, (m_oRect.Height - m_fDescent) * fPtToMm, pRenderer); SysFreeString(bstrText); if (m_pCharacter->getIsLabel()) pRenderer->EndCommand(c_nNumberingMarker); #ifdef TME_DRAW_SYMBOL_BORDER CItem::drawRect(pRenderer, m_oRect); #endif } private: void RupturePositions(CArray& rupturePositions) { CString rupSymbols = _T("-"); int index = 0; int length = m_strText.GetLength(); while (index < length) { if (rupSymbols.Find(m_strText[index]) != -1) rupturePositions.Add(index); ++index; } } private: void sendBaselineShiftToRenderer(IAVSRenderer* renderer) { IAVSRenderer2* renderer2 = NULL; if (SUCCEEDED(renderer->QueryInterface(__UUIDOF__IAVSRENDERER2, (void**)&renderer2)) && (NULL != renderer2)) { byte baselineShiftPos = m_pCharacter->m_oAttributes.m_nBaselineShift; float baselineShift = m_pCharacter->m_oAttributes.m_fBaselineShift; if (baselineShiftPos != 0) renderer2->CommandLong2(c_nBaselineShift, baselineShiftPos); else if (baselineShift != 0) { if (baselineShift > 0) renderer2->CommandLong2(c_nBaselineShift, 1); else renderer2->CommandLong2(c_nBaselineShift, 2); } } } }; class CSpace : public CSymbols { private: double m_originWidth; public: CSpace() : CSymbols() { m_originWidth = 0; } CSpace(const size_t &nCount, CCharacter* pCharacter, CGrapher* pGrapher) : CSymbols() { m_strText = _T(""); for (size_t i = 0; i < nCount; ++i) { m_strText += _T(" "); } m_pCharacter = pCharacter; m_oRect = pGrapher->GetRectForString(m_strText, pCharacter); m_fDescent = pGrapher->GetDescent(pCharacter); m_strikePosition = GetStrikePosition(pGrapher); m_underlinePosition = GetUnderlinePosition(pGrapher, m_size); SetOnBaseline(); } public: inline CItemType GetType() { return Space; } void RestoreRect() { m_oRect.X = 0.0f; m_oRect.Y = -m_oRect.Height + m_fDescent; m_originWidth; m_oRect.Width = m_originWidth; } void SetOriginWidth() { m_originWidth = m_oRect.Width; } public: CItem* Rupture(const float& maxWidth, CGrapher* grapher, const bool& bySymbol = false , const bool& firstSymbolAlways = false) { CItem* newItem = CSymbols::Rupture(maxWidth, grapher, bySymbol, firstSymbolAlways); if (newItem != NULL) { CSymbols* symbolsItem = (CSymbols*) newItem; int length = (int) symbolsItem->GetLength(); CCharacter* character = symbolsItem->GetCharacter(); CSpace* spaceItem = new CSpace(length, character, grapher); RELEASEOBJECT(newItem); return spaceItem; } else return newItem; } void Draw(IAVSRenderer *pRenderer, CDocumentManager& documentManager, const float &fCompleteness) { } }; class CLineEnd : public CSymbols { public: CLineEnd() : CSymbols() { } CLineEnd(const size_t &nCount, CCharacter *pCharacter, CGrapher* pGrapher) : CSymbols() { m_strText = _T(""); for (size_t i = 0; i < nCount; ++i) { m_strText += _T("\n"); } m_pCharacter = pCharacter; m_oRect = pGrapher->GetRectForString(m_strText, pCharacter); m_fDescent = pGrapher->GetDescent(pCharacter); SetOnBaseline(); m_oRect.Width = 0.0f; } public: inline CItemType GetType() { return LineEnd; } public: void Draw(IAVSRenderer *pRenderer, CDocumentManager& documentManager, const float &fCompleteness) { } }; class CBullet : public CSymbols { public: CBullet() : CSymbols() { m_pCharacter->setIsLabel(true); } CBullet(const CString &strBullet, CCharacter *pCharacter, CGrapher* pGrapher) : CSymbols(strBullet, pCharacter, pGrapher) { m_strikePosition = GetStrikePosition(pGrapher); m_underlinePosition = GetUnderlinePosition(pGrapher, m_size); m_pCharacter->setIsLabel(true); } ~CBullet() { } public: inline CItemType GetType() { return Bullet; } }; class CTabStop : public CSymbols { public: byte m_bType; byte m_bLeader; public: CTabStop() : CSymbols() { } CTabStop(CCharacter *pCharacter, CGrapher* pGrapher) { m_strText = _T("x"); m_pCharacter = pCharacter; m_oRect = pGrapher->GetRectForString(m_strText, pCharacter); m_fDescent = pGrapher->GetDescent(pCharacter); m_strikePosition = GetStrikePosition(pGrapher); m_underlinePosition = GetUnderlinePosition(pGrapher, m_size); SetOnBaseline(); } public: inline CItemType GetType() { return TabStop; } public: void Draw(IAVSRenderer *pRenderer, CDocumentManager& documentManager, const float& completeness) { #ifdef TME_SHOW_TABS CSymbols::Draw(pRenderer, documentManager, completeness); #endif const float fPtToMm = 25.4f / 72.0f; if (m_bLeader != 0 && (m_bLeader == 1 || m_bLeader == 2 || m_bLeader == 3)) { double lineY; if (m_bLeader == 1) { lineY = GetRect().GetBottom() - GetDescent(); pRenderer->put_PenSize(2 * m_size); pRenderer->put_PenDashStyle(Aggplus::DashStyleCustom); SAFEARRAYBOUND rgsab; rgsab.lLbound = 0; rgsab.cElements = 2; SAFEARRAY* pArray = SafeArrayCreate(VT_R8, 1, &rgsab); double* pData = (double*)pArray->pvData; pData[0] = 1; pData[1] = 2; pRenderer->PenDashPattern(pArray); RELEASEARRAY(pArray); } else if (m_bLeader == 2) { lineY = GetRect().GetBottom() - GetDescent() - m_strikePosition; pRenderer->put_PenSize(m_size); pRenderer->put_PenDashStyle(Aggplus::DashStyleCustom); SAFEARRAYBOUND rgsab; rgsab.lLbound = 0; rgsab.cElements = 2; SAFEARRAY* pArray = SafeArrayCreate(VT_R8, 1, &rgsab); double* pData = (double*)pArray->pvData; pData[0] = 2; pData[1] = 2; pRenderer->PenDashPattern(pArray); RELEASEARRAY(pArray); } else if (m_bLeader == 3) { lineY = GetRect().GetBottom() - GetDescent() + m_underlinePosition / 2; pRenderer->put_PenSize(m_size); pRenderer->put_PenDashStyle(Aggplus::DashStyleCustom); SAFEARRAYBOUND rgsab; rgsab.lLbound = 0; rgsab.cElements = 2; SAFEARRAY* pArray = SafeArrayCreate(VT_R8, 1, &rgsab); double* pData = (double*)pArray->pvData; pData[0] = 5; pData[1] = 1; pRenderer->PenDashPattern(pArray); RELEASEARRAY(pArray); } if ((GetRect().GetRight() - GetRect().GetLeft()) * fPtToMm > 10) { pRenderer->put_PenColor(GetCharacter()->m_oAttributes.m_oBrush.m_oBrush.Color1); pRenderer->BeginCommand(c_nPathType); //pRenderer->BeginCommand(c_nTextGraphicType); pRenderer->PathCommandStart(); pRenderer->PathCommandMoveTo(GetRect().GetLeft() * fPtToMm + 1, lineY * fPtToMm); pRenderer->PathCommandLineTo(GetRect().GetRight() * fPtToMm, lineY * fPtToMm); pRenderer->DrawPath(c_nStroke); pRenderer->PathCommandEnd(); //pRenderer->EndCommand(c_nTextGraphicType); pRenderer->EndCommand(c_nPathType); } } } }; class CRect { private: RectF m_rect; long m_color; byte m_underline; byte m_alpha; public: CRect() : m_rect(), m_color(0xFFFFFF), m_underline() { } CRect(RectF rect, long color, byte alpha,byte underline) : m_rect(rect), m_color(color), m_alpha(alpha), m_underline(underline) { } CRect(RectF rect, long color) : m_rect(rect), m_color(color), m_underline() { } double GetLeft() { return m_rect.GetLeft(); } double GetRight() { return m_rect.GetRight(); } double GetTop() { return m_rect.GetTop(); } double GetBottom() { return m_rect.GetBottom(); } long GetColor() { return m_color; } byte GetAlpha() { return m_alpha; } byte GetUnderline() { return m_underline; } }; class CWord : public CItem { protected: CAtlArray m_arrItems; size_t m_nItemsCount; float _originDescent; public: CWord() : CItem(), m_nItemsCount(0), _originDescent(0) { } ~CWord() { Clear(); } void Clear() { for (size_t nIndex = 0; nIndex < m_nItemsCount; ++nIndex) { RELEASEOBJECT(m_arrItems[nIndex]); } m_arrItems.RemoveAll(); m_nItemsCount = 0; _originDescent = 0; } public: void RemoveAllItems() { m_arrItems.RemoveAll(); m_nItemsCount = 0; } inline CItemType GetType() { return Word; } inline float getOriginDescent() const { return _originDescent; } public: void AddItem(CItem *pItem) { pItem->MoveTo(m_oRect.X + m_oRect.Width, pItem->GetRect().Y); m_oRect.Width += pItem->GetRect().Width; updateAscent(pItem); updateDescent(pItem); m_fDescent = m_oRect.GetBottom(); m_arrItems.Add(pItem); ++m_nItemsCount; } private: void updateAscent(CItem* item) { float itemAscent = item->GetHeightPt() - item->GetDescent(); float itemTop = item->GetRect().GetTop(); if (itemTop > -itemAscent) itemTop = -itemAscent; float lineTop = m_oRect.GetTop(); if (lineTop > itemTop) { m_oRect.Height += lineTop - itemTop; m_oRect.Y = itemTop; } } void updateDescent(CItem* item) { float itemDescent = item->GetDescent(); if (itemDescent > _originDescent) _originDescent = itemDescent; float itemBottom = item->GetRect().GetBottom(); if (itemBottom < itemDescent) itemBottom = itemDescent; if (m_oRect.GetBottom() < itemBottom) m_oRect.Height = itemBottom - m_oRect.GetTop(); } public: size_t GetItemsCount() { return m_nItemsCount; } void RearrangeItems() { REAL fCurrentX = m_oRect.X; for (size_t nIndex = 0; nIndex < m_nItemsCount; ++nIndex) { CItem *pItem = m_arrItems[nIndex]; pItem->MoveTo(fCurrentX); fCurrentX += pItem->GetRect().Width; } } CWord* Rupture(REAL &fPersistWidth, CGrapher* pGrapher) { REAL fCurrentWidth = 0; CItem *pItem = NULL; size_t nItemIndex = 0; for (; nItemIndex < m_nItemsCount; ++nItemIndex) { pItem = m_arrItems[nItemIndex]; if (fCurrentWidth + pItem->GetRect().Width > fPersistWidth) { break; } fCurrentWidth += pItem->GetRect().Width; } CWord *pNewWord = new CWord(); for (size_t nIndex = 0; nIndex < nItemIndex; ++nIndex) { pNewWord->AddItem(m_arrItems[nIndex]); } m_arrItems.RemoveAt(0, nItemIndex); m_nItemsCount -= nItemIndex; fPersistWidth -= fCurrentWidth; CItem *pNewItem = pItem->Rupture(fPersistWidth, pGrapher); if (pNewItem != NULL) { pNewWord->AddItem(pNewItem); } if (pNewWord->m_nItemsCount != 0) { m_oRect.Width -= pNewWord->m_oRect.Width; RearrangeItems(); } else { RELEASEOBJECT(pNewWord); } return pNewWord; } public: void Draw(IAVSRenderer *pRenderer, CDocumentManager& documentManager, const float &fCompleteness) { RectF underlineRect; RectF shadingRect; RectF strikeRect; double descent = 0; double dSizeUnderline = 0.25; double dSizeStrike = 0.25; const float fPtToMm = 25.4f / 72.0f; CAtlArray arrShadings; CAtlArray arrUnderlines; for (size_t nIndex = 0; nIndex < m_nItemsCount; ++nIndex) { #ifdef _DEBUG CItemType p = m_arrItems[nIndex]->GetType(); #endif if (m_arrItems[nIndex]->GetType() != Word && m_arrItems[nIndex]->GetType() != Alternate && m_arrItems[nIndex]->GetType() != Footnote) { CSymbols* item = (CSymbols*)m_arrItems[nIndex]; //SHADING if (item->GetCharacter()->m_oAttributes.m_oBackground.m_oBackground.Alpha) { if (IsLastInEquallyShading(nIndex - 1)) { shadingRect.X = item->GetRect().GetLeft(); shadingRect.Y = item->GetRect().GetTop(); } shadingRect.Width += item->GetWidthPt(); if (IsLastInEquallyShading(nIndex)) { long color = item->GetCharacter()->m_oAttributes.m_oBackground.m_oBackground.Color; arrShadings.Add(CRect(RectF(shadingRect.X * fPtToMm, shadingRect.Y * fPtToMm, shadingRect.Width * fPtToMm, shadingRect.Height * fPtToMm), color)); shadingRect.Width = 0; } } } } //drawShading for(size_t nIndex = 0; nIndex < arrShadings.GetCount(); ++nIndex) { CRect rect = arrShadings[nIndex]; DrawShading(pRenderer, rect.GetLeft(), GetRect().GetTop() * fPtToMm, rect.GetRight() - rect.GetLeft(), GetRect().Height * fPtToMm, rect.GetColor()); //DrawShading(pRenderer, rect.GetLeft(), (shadingRect.Y + descent - shadingRect.Height) * fPtToMm, rect.GetRight() - rect.GetLeft(), shadingRect.Height * fPtToMm, rect.GetColor()); } for(size_t nIndex = 0; nIndex < m_nItemsCount; ++nIndex) { #ifdef AVS_LOG_DEBUG CItemType p = m_arrItems[nIndex]->GetType(); #endif if (m_arrItems[nIndex]->GetType() != Word && m_arrItems[nIndex]->GetType() != Alternate && m_arrItems[nIndex]->GetType() != Footnote) { CSymbols* item = (CSymbols*)m_arrItems[nIndex]; CTextAttributes textAttrs = item->GetCharacter()->m_oAttributes; //item->m_strikePosition = item->GetStrikePosition(pGrapher); //item->m_underlinePosition = item->GetUnderlinePosition(pGrapher, item->m_size); double dHeightLine = item->GetHeightPt(); //STRIKE if (textAttrs.m_oFont.m_oFont.Strikeout != 0) { strikeRect.Width = item->GetWidthPt(); dSizeStrike = item->m_size; strikeRect.X = item->GetRect().GetLeft(); if (item->m_strikePosition != 0) strikeRect.Y = item->GetRect().GetBottom() - item->GetDescent() - item->m_strikePosition; else strikeRect.Y = item->GetRect().GetBottom() - 2 * item->GetDescent(); DrawStrike(pRenderer, strikeRect.X * fPtToMm, strikeRect.Y * fPtToMm, (strikeRect.X + strikeRect.Width) * fPtToMm, strikeRect.Y * fPtToMm, textAttrs.m_oBrush.m_oBrush.Color1, textAttrs.m_oBrush.m_oBrush.Alpha1, textAttrs.m_oFont.m_oFont.Strikeout, dSizeStrike); } //UNDERLINE if (textAttrs.m_oFont.m_oFont.Underline != 0) { /*if (textAttrs.m_oFont.m_oFont.Strikeout == 0) ;item->m_underlinePosition = item->GetUnderlinePosition(pGrapher, item->m_size);*/ if (dHeightLine > underlineRect.Height) underlineRect.Height = dHeightLine; if (IsLastInEquallyUnder(nIndex - 1)) { underlineRect.X = item->GetRect().GetLeft(); underlineRect.Y = 0; underlineRect.Width = 0; underlineRect.Height = 0; dSizeUnderline = 0; } double size = item->m_size;//dHeightLine / 50; double width = item->GetWidthPt(); double dUnderlinePos = item->m_underlinePosition / 2 * fPtToMm + item->GetRect().GetBottom() * fPtToMm - item->GetDescent() * fPtToMm; if ((underlineRect.Width + width) != 0 ) { dSizeUnderline = (width * size + underlineRect.Width * dSizeUnderline) / (underlineRect.Width + width); underlineRect.Y = (width * dUnderlinePos + underlineRect.Width * underlineRect.Y) / (underlineRect.Width + width); } underlineRect.Width += width; if (IsLastInEquallyUnder(nIndex)) { arrUnderlines.Add(CRect(RectF(underlineRect.X * fPtToMm, underlineRect.Y * fPtToMm, underlineRect.Width * fPtToMm, 0), textAttrs.m_oBrush.m_oBrush.Color1, textAttrs.m_oBrush.m_oBrush.Alpha1, textAttrs.m_oFont.m_oFont.Underline)); underlineRect.Width = 0; if (IsLastInEquallyTypeUnder(nIndex) && nIndex != m_nItemsCount - 1) { for(size_t nIndex = 0; nIndex < arrUnderlines.GetCount(); ++nIndex) { CRect rect = arrUnderlines[nIndex]; DrawUnderline(pRenderer, rect.GetLeft(), (underlineRect.Y), rect.GetRight(), (underlineRect.Y), rect.GetColor(), rect.GetAlpha(), rect.GetUnderline(), dSizeUnderline); } arrUnderlines.RemoveAll(); underlineRect.Height = 0; dSizeUnderline = 0; } } } } m_arrItems[nIndex]->Draw(pRenderer, documentManager, fCompleteness); } //drawUnderline for(size_t nIndex = 0; nIndex < arrUnderlines.GetCount(); ++nIndex) { CRect rect = arrUnderlines[nIndex]; DrawUnderline(pRenderer, rect.GetLeft(), (underlineRect.Y), rect.GetRight(), (underlineRect.Y), rect.GetColor(), rect.GetAlpha(), rect.GetUnderline(), dSizeUnderline); } } public: bool IsLastInEquallyUnder(size_t num) { if (num == m_nItemsCount - 1 || num == -1) return true; CItemType type1 = m_arrItems[num]->GetType(); CItemType type2 = m_arrItems[num + 1]->GetType(); if (type1 == Word || type2 == Word || type1 == Alternate || type2 == Alternate || type1 == Footnote || type2 == Footnote) return true; CTextAttributes cur = ((CSymbols*)m_arrItems[num])->GetCharacter()->m_oAttributes; CTextAttributes next = ((CSymbols*)m_arrItems[num + 1])->GetCharacter()->m_oAttributes; byte under1 = cur.m_oFont.m_oFont.Underline; byte under2 = next.m_oFont.m_oFont.Underline; long color1 = cur.m_oBrush.m_oBrush.Color1; long color2 = next.m_oBrush.m_oBrush.Color1; if ((under1 == under2) != 0 && color1 == color2) return false; else return true; } bool IsLastInEquallyTypeUnder(size_t num) { if (num == m_nItemsCount - 1 || num == -1) return true; CItemType type1 = m_arrItems[num]->GetType(); CItemType type2 = m_arrItems[num + 1]->GetType(); if (type1 == Word || type2 == Word || type1 == Alternate || type2 == Alternate || type1 == Footnote || type2 == Footnote) return true; CTextAttributes cur = ((CSymbols*)m_arrItems[num])->GetCharacter()->m_oAttributes; CTextAttributes next = ((CSymbols*)m_arrItems[num + 1])->GetCharacter()->m_oAttributes; byte under1 = cur.m_oFont.m_oFont.Underline; byte under2 = next.m_oFont.m_oFont.Underline; if ((under1 == under2) != 0) return false; else return true; } bool IsLastInEquallyShading(size_t num) { if (num == m_nItemsCount - 1 || num == -1) return true; CItemType type1 = m_arrItems[num]->GetType(); CItemType type2 = m_arrItems[num + 1]->GetType(); if (type1 == Word || type2 == Word || type1 == Alternate || type2 == Alternate || type1 == Footnote || type2 == Footnote) return true; CSymbols* cur = (CSymbols*)m_arrItems[num]; CSymbols* next = (CSymbols*)m_arrItems[num + 1]; CCharacter* curCharacter = cur->GetCharacter(); CCharacter* nextCharacter = next->GetCharacter(); if (curCharacter == NULL || nextCharacter == NULL) return false; long shadow1 = curCharacter->m_oAttributes.m_oBackground.m_oBackground.Color; long shadow2 = nextCharacter->m_oAttributes.m_oBackground.m_oBackground.Color; byte alpha1 = curCharacter->m_oAttributes.m_oBackground.m_oBackground.Alpha; byte alpha2 = nextCharacter->m_oAttributes.m_oBackground.m_oBackground.Alpha; if ((shadow1 == shadow2) && (alpha1 == alpha2) ) return false; else return true; } void DrawUnderline(IAVSRenderer *pRenderer, double dX1, double dY1, double dX2, double dY2, long lColor, byte bAlpha, byte bUnderline, double dSize) { if (bUnderline != 0) { pRenderer->put_PenAlpha(bAlpha); pRenderer->put_PenSize(dSize); pRenderer->put_PenColor(lColor); pRenderer->BeginCommand(c_nTextGraphicType); if (bUnderline == 1 || bUnderline == 3 || bUnderline == 4 || bUnderline == 5 || bUnderline == 6 || bUnderline == 7 || bUnderline == 8 || bUnderline == 9 || bUnderline == 10 || bUnderline == 11 || bUnderline == 12 || bUnderline == 13) { //Type if (bUnderline == 1) pRenderer->put_PenDashStyle(DashStyleSolid); else if (bUnderline == 6 || bUnderline == 7 || bUnderline == 8 || bUnderline == 9) pRenderer->put_PenDashStyle(DashStyleDash); else if (bUnderline == 4 || bUnderline == 5) pRenderer->put_PenDashStyle(DashStyleDot); else if (bUnderline == 10 || bUnderline == 11) pRenderer->put_PenDashStyle(DashStyleDashDot); else if (bUnderline == 12 || bUnderline == 13) pRenderer->put_PenDashStyle(DashStyleDashDotDot); //Size if (bUnderline == 3 || bUnderline == 5 || bUnderline == 7 || bUnderline == 9 || bUnderline == 11 || bUnderline == 13) pRenderer->put_PenSize(2 * dSize); else pRenderer->put_PenSize(dSize); DrawLine(pRenderer, dX1, dY1 - dSize, dX2, dY2 - dSize); } else if (bUnderline == 2) { pRenderer->put_PenDashStyle(DashStyleSolid); DrawLine(pRenderer, dX1, dY1 - dSize, dX2, dY2 - dSize); DrawLine(pRenderer, dX1, dY1 + dSize, dX2, dY2 + dSize); } else if (bUnderline == 14 || bUnderline == 15 || bUnderline == 16) { pRenderer->put_PenDashStyle(DashStyleSolid); if (bUnderline == 14) { pRenderer->put_PenSize(dSize / 2); DrawWave(pRenderer, dX1, dY1, dX2, dY2, dSize); } else if (bUnderline == 15) { pRenderer->put_PenSize(dSize); DrawWave(pRenderer, dX1, dY1, dX2, dY2, 3 * dSize / 2); } else if (bUnderline == 16) { pRenderer->put_PenSize(dSize / 2); DrawWave(pRenderer, dX1, dY1 - dSize / 2, dX2, dY2 - dSize / 2, dSize / 2); DrawWave(pRenderer, dX1, dY1 + dSize / 2, dX2, dY2 + dSize / 2, dSize / 2); } } pRenderer->EndCommand(c_nTextGraphicType); } } void DrawStrike(IAVSRenderer *pRenderer, double dX1, double dY1, double dX2, double dY2, long lColor, byte bAlpha, byte bStrike, double dSize) { if (bStrike != 0) { pRenderer->BeginCommand(c_nTextGraphicType); pRenderer->put_PenDashStyle(DashStyleSolid); pRenderer->put_PenSize(dSize); pRenderer->put_PenColor(lColor); pRenderer->put_PenAlpha(bAlpha); if (bStrike == 1) { DrawLine(pRenderer, dX1, dY1, dX2, dY2); } if (bStrike == 2) { DrawLine(pRenderer, dX1, dY1 - dSize, dX2, dY2 - dSize); DrawLine(pRenderer, dX1, dY1 + 3 * dSize / 2, dX2, dY2 + 3 * dSize / 2); } pRenderer->EndCommand(c_nTextGraphicType); } } void DrawShading(IAVSRenderer *pRenderer, double dX, double dY, double dWidth, double dHeight, long lColor) { pRenderer->put_BrushColor1(lColor); pRenderer->BeginCommand(c_nPathType); //pRenderer->BeginCommand(c_nTextGraphicType); pRenderer->PathCommandStart(); pRenderer->PathCommandMoveTo(dX, dY); pRenderer->PathCommandLineTo(dX + dWidth, dY); pRenderer->PathCommandLineTo(dX + dWidth, dY + dHeight); pRenderer->PathCommandLineTo(dX, dY + dHeight); pRenderer->PathCommandClose(); pRenderer->DrawPath(c_nWindingFillMode); //pRenderer->DrawPath(1); pRenderer->PathCommandEnd(); //pRenderer->EndCommand(c_nTextGraphicType); pRenderer->EndCommand(c_nPathType); } void DrawWave(IAVSRenderer *pRenderer, double dX1, double dY1, double dX2, double dY2, double dSize) { pRenderer->BeginCommand(c_nPathType); pRenderer->BeginCommand(c_nTextGraphicType); pRenderer->PathCommandStart(); pRenderer->PathCommandMoveTo(dX1, dY1); //2.29 - double lenghtWave = 2.3; int dev = (int)((dX2 - dX1) / lenghtWave); if (dev == 0) dev = 1; double dStep = (dX2 - dX1) / dev; for(double dX3 = dX1, dY3 = dY1; dX3 + 3 * dStep / 4 < dX2; dX3 += dStep ) { pRenderer->PathCommandCurveTo(dX3, dY3, dX3 + dStep / 4, dY3 - dSize, dX3 + dStep / 2, dY3 ); pRenderer->PathCommandCurveTo(dX3 + dStep / 2, dY3, dX3 + 3 * dStep / 4, dY3 + dSize, dX3 + dStep, dY3 ); } pRenderer->DrawPath(c_nStroke); pRenderer->PathCommandEnd(); pRenderer->EndCommand(c_nTextGraphicType); pRenderer->EndCommand(c_nPathType); } void DrawLine(IAVSRenderer *pRenderer, double dX1, double dY1, double dX2, double dY2) { pRenderer->BeginCommand(c_nPathType); pRenderer->BeginCommand(c_nTextGraphicType); pRenderer->PathCommandStart(); pRenderer->PathCommandMoveTo(dX1, dY1); pRenderer->PathCommandLineTo(dX2, dY2); pRenderer->DrawPath(c_nStroke); pRenderer->PathCommandEnd(); pRenderer->EndCommand(c_nTextGraphicType); pRenderer->EndCommand(c_nPathType); } public: void MoveTo(const REAL &fNewX) { REAL fDeltaX = fNewX - m_oRect.X; MoveOn(fDeltaX, 0); } void MoveTo(const REAL &fNewX, const REAL &fNewY) { REAL fDeltaX = fNewX - m_oRect.X; REAL fDeltaY = fNewY - m_oRect.Y; MoveOn(fDeltaX, fDeltaY); } void MoveOn(const REAL &fDeltaX, const REAL &fDeltaY) { m_oRect.X += fDeltaX; m_oRect.Y += fDeltaY; for (size_t i = 0; i < m_arrItems.GetCount(); ++i) { m_arrItems[i]->MoveOn(fDeltaX, fDeltaY); } } }; class CLine : public CWord, public RendererCommandSender { protected: REAL m_fPersistWidth; REAL m_fTextHeight; size_t m_nSpacesCount; bool m_bIsContainsAlternate; INT m_iFootnoteCount; bool _startCell; bool _finishCell; bool _dummy; public: CLine() : CWord(), RendererCommandSender() , m_fPersistWidth(0.0f), m_fTextHeight(11*1.147f) , m_nSpacesCount(0), m_bIsContainsAlternate(false) , m_iFootnoteCount(0) , _startCell(false), _finishCell(false) , _dummy(false) { } ~CLine() { Clear(); } void Clear() { m_fPersistWidth = 0.0f; m_fTextHeight = 11 * 1.147f; m_arrItems.RemoveAll(); m_nItemsCount = 0; m_nSpacesCount = 0; m_bIsContainsAlternate = false; m_iFootnoteCount = 0; _startCell = false; _finishCell = false; } public: virtual void AddItem(CItem *pItem) { if (pItem->GetType() == Alternate) { m_bIsContainsAlternate = true; } else { if (pItem->GetType() == Space) { ++m_nSpacesCount; } else if (pItem->GetType() == Footnote) { ++m_iFootnoteCount; } if (pItem->GetRect().Height > m_fTextHeight) { m_fTextHeight = pItem->GetRect().Height; } } CWord::AddItem(pItem); } void SetPersistWidth(const REAL &fPersistWidth) { m_fPersistWidth = fPersistWidth; } REAL GetPersistWidth() { return m_fPersistWidth; } virtual void SetAlign(const CAlignHorizontal& align, const bool& first = false, const bool& last = false) { if (m_nItemsCount != 0) { AbsentLastSpaces(); if (!first) AbsentFormerSpaces(); switch(align) { case LeftAlign : break; case CenterAlign : MoveOn(m_fPersistWidth/2, 0); break; case RightAlign : MoveOn(m_fPersistWidth, 0); break; case WideAlign : if (last ) break; float deltaSpace = (m_nSpacesCount != 0) ? m_fPersistWidth / m_nSpacesCount : 0; if (deltaSpace != 0) { for (int i = 0; i < (int) m_nItemsCount; ++i) { CItem* item = m_arrItems[i]; if (item->GetType() == Space) if (item->GetRect().Width != 0) item->GetRect().Width += deltaSpace; } } break; } RearrangeItems(); } } REAL GetTextHeight() { return m_fTextHeight; } void setStartCell(const bool& value = true) { _startCell = value; } void setFinishCell(const bool& value = true) { _finishCell = value; } void setDummy(const bool& dummy) { _dummy = dummy; } bool isDummy() const { return _dummy; } public: CAtlArray* GetItems() { return &m_arrItems; } virtual void RestoreItems() { size_t nItemsCount = m_arrItems.GetCount(); for (size_t nIndex = 0; nIndex < nItemsCount; ++nIndex) { m_arrItems[nIndex]->RestoreRect(); } } virtual void SetOnBaseline(const bool& bIsInit = true) { m_oRect.Y = m_fDescent - m_oRect.Height; size_t nItemsCount = m_arrItems.GetCount(); for (size_t nIndex = 0; nIndex < nItemsCount; ++nIndex) { m_arrItems[nIndex]->SetOnBaseline(false); } } REAL GetAscent() { return m_oRect.Height - m_fDescent; } inline BOOL IsContainsAlternate() { return m_bIsContainsAlternate; } inline INT GetFootnoteCount() { return m_iFootnoteCount; } public: void Draw(IAVSRenderer* renderer, CDocumentManager& documentManager, const float& completeness) { sendRendererCommands(renderer, RendererCommand::BEGIN); if (_startCell) renderer->BeginCommand(c_nTableCell); renderer->BeginCommand(c_nLine); CWord::Draw(renderer, documentManager, completeness); renderer->EndCommand(c_nLine); if (_finishCell) renderer->EndCommand(c_nTableCell); sendRendererCommands(renderer, RendererCommand::END); #ifdef TME_DRAW_LINE_BORDER CItem::drawRect(renderer, m_oRect); #endif } private: void AbsentLastSpaces() { for (int nIndex = (int)m_nItemsCount - 1; nIndex >= 0; --nIndex) { CItem *pItem = m_arrItems[nIndex]; REAL fWidth = pItem->GetRect().Width; switch (pItem->GetType()) { case Space : ((CSpace*)pItem)->SetOriginWidth(); m_fPersistWidth += fWidth; m_oRect.Width -= fWidth; pItem->GetRect().Width = 0.0f; --m_nSpacesCount; break; case LineEnd : pItem->GetRect() = RectF(); break; default : return; } } } void AbsentFormerSpaces() { for (size_t nIndex = 0; nIndex < m_nItemsCount; ++nIndex) { CItem *pItem = m_arrItems[nIndex]; REAL fWidth = pItem->GetRect().Width; switch (pItem->GetType()) { case Space : ((CSpace*)pItem)->SetOriginWidth(); m_fPersistWidth += fWidth; m_oRect.Width -= fWidth; pItem->GetRect().Width = 0; --m_nSpacesCount; break; default : return; } } } }; class CCompositeLine : public CLine { public: CCompositeLine() : CLine() { } ~CCompositeLine() { Clear(); } void Clear() { for (size_t nIndex = 0; nIndex < m_nItemsCount; ++nIndex) { RELEASEOBJECT(m_arrItems[nIndex]); } m_arrItems.RemoveAll(); m_nItemsCount = 0; } public: void AddItem(CItem *pItem) { if (pItem->GetType() == Word) { m_iFootnoteCount += ((CLine*)pItem)->GetFootnoteCount(); } if (m_oRect.GetTop() > pItem->GetRect().GetTop()) { m_oRect.Height += m_oRect.GetTop() - pItem->GetRect().GetTop(); m_oRect.Y = pItem->GetRect().GetTop(); } if (m_oRect.GetBottom() < pItem->GetRect().GetBottom()) { m_oRect.Height = pItem->GetRect().GetBottom() - m_oRect.GetTop(); } m_fDescent = m_oRect.GetBottom(); m_arrItems.Add(pItem); ++m_nItemsCount; } void RestoreItems() { size_t nItemsCount = m_arrItems.GetCount(); for (size_t nIndex = 0; nIndex < nItemsCount; ++nIndex) { ((CLine*)(m_arrItems[nIndex]))->RestoreItems(); } } virtual void SetAlign(const CAlignHorizontal& eAlign, const bool& bIsFirstLine = false, const bool& last = false) { switch(eAlign) { case LeftAlign : break; case CenterAlign : for (size_t iIndex = 1; iIndex < m_arrItems.GetCount() - 2; ++iIndex) { ((CLine*)(m_arrItems[iIndex]))->SetAlign(CenterAlign, false); } if (m_arrItems.GetCount() > 1) { ((CLine*)(m_arrItems[0]))->SetAlign(RightAlign, bIsFirstLine); ((CLine*)(m_arrItems[m_arrItems.GetCount() - 1]))->SetAlign(LeftAlign); } else { ((CLine*)(m_arrItems[0]))->SetAlign(CenterAlign, bIsFirstLine); } break; case RightAlign : for (size_t iIndex = 0; iIndex < m_arrItems.GetCount() - 1; ++iIndex) { ((CLine*)(m_arrItems[iIndex]))->SetAlign(RightAlign, bIsFirstLine && (iIndex == 0)); } break; case WideAlign : if (last) break; for (size_t iIndex = 0; iIndex < m_arrItems.GetCount(); ++iIndex) { ((CLine*)(m_arrItems[iIndex]))->SetAlign(WideAlign, bIsFirstLine && (iIndex == 0)); } break; } } }; // ### ### ### class CFlowMap; class CSimplePageMaster; class CPageSequenceMaster; class CLayoutMasterSet; class CFlow; class CBounds : private CXmlAttributeReader { private: bool m_bIsMargin; RectF m_oRectPt; public: CBounds() : m_bIsMargin(TRUE), m_oRectPt() { } ~CBounds() { Clear(); } public: void Clear() { m_bIsMargin = TRUE; m_oRectPt = RectF(); } void FromXmlNodeFo(XmlUtils::CXmlNode& oXmlNode, const bool& withPaddings = false) { m_oRectPt.X = FloatPtAttributeFromXml(oXmlNode, _T("margin-left")); m_oRectPt.Y = FloatPtAttributeFromXml(oXmlNode, _T("margin-top")); m_oRectPt.Width = FloatPtAttributeFromXml(oXmlNode, _T("margin-right")); m_oRectPt.Height = FloatPtAttributeFromXml(oXmlNode, _T("margin-bottom")); if (withPaddings) ReadMarginsFromPaddings(oXmlNode); m_bIsMargin = TRUE; } void FromXmlNodeFo2(XmlUtils::CXmlNode& oXmlNode, const bool& withPaddings = false) { m_oRectPt.X = FloatPtAttributeFromXml(oXmlNode, _T("margin-left"), 85.0f); m_oRectPt.Y = FloatPtAttributeFromXml(oXmlNode, _T("margin-top"), 56.7f); m_oRectPt.Width = FloatPtAttributeFromXml(oXmlNode, _T("margin-right"), 42.5f); m_oRectPt.Height = FloatPtAttributeFromXml(oXmlNode, _T("margin-bottom"), 56.7f); if (withPaddings) ReadMarginsFromPaddings(oXmlNode); m_bIsMargin = TRUE; } public: void SetAsMarginPt(const REAL& fLeftMarginPt, const REAL& fTopMarginPt, const REAL& fRightMarginPt, const REAL& fBottommarginPt) { m_oRectPt.X = fLeftMarginPt; m_oRectPt.Y = fTopMarginPt; m_oRectPt.Width = fRightMarginPt; m_oRectPt.Height = fBottommarginPt; m_bIsMargin = TRUE; } void SetAsMarginMm(const REAL& fLeftMarginMm, const REAL& fTopMarginMm, const REAL& fRightMarginMm, const REAL& fBottommarginMm) { static const REAL fMmToPt = 72.0f / 25.4f; m_oRectPt.X = fLeftMarginMm * fMmToPt; m_oRectPt.Y = fTopMarginMm * fMmToPt; m_oRectPt.Width = fRightMarginMm * fMmToPt; m_oRectPt.Height = fBottommarginMm * fMmToPt; m_bIsMargin = TRUE; } void AddMarginPt(const REAL& fLeftMarginPt, const REAL& fTopMarginPt, const REAL& fRightMarginPt, const REAL& fBottomMarginPt) { assert(m_bIsMargin); m_oRectPt.X += fLeftMarginPt; m_oRectPt.Y += fTopMarginPt; m_oRectPt.Width += fRightMarginPt; m_oRectPt.Height += fBottomMarginPt; } public: void SetAsRect(const CBounds& oBounds) { REAL fLeftMarginPt = m_oRectPt.X; REAL fTopMarginPt = m_oRectPt.Y; m_oRectPt.X = oBounds.m_oRectPt.X + fLeftMarginPt; m_oRectPt.Y = oBounds.m_oRectPt.Y + fTopMarginPt; m_oRectPt.Width = oBounds.m_oRectPt.Width - fLeftMarginPt - m_oRectPt.Width; m_oRectPt.Height = oBounds.m_oRectPt.Height - fTopMarginPt - m_oRectPt.Height; m_bIsMargin = FALSE; } void SetAsRectPt(const RectF& oRectPt) { if (m_bIsMargin) { REAL fLeftMarginPt = m_oRectPt.X; REAL fTopMarginPt = m_oRectPt.Y; m_oRectPt.X = oRectPt.X + fLeftMarginPt; m_oRectPt.Y = oRectPt.Y + fTopMarginPt; m_oRectPt.Width = oRectPt.Width - fLeftMarginPt - m_oRectPt.Width; m_oRectPt.Height = oRectPt.Height - fTopMarginPt - m_oRectPt.Height; m_bIsMargin = FALSE; } else { m_oRectPt = oRectPt; } } void SetAsRectPt(const REAL& fWidthPt, const REAL& fHeightPt) { m_oRectPt.Width = fWidthPt - m_oRectPt.X - m_oRectPt.Width; m_oRectPt.Height = fHeightPt - m_oRectPt.Y - m_oRectPt.Height; m_bIsMargin = FALSE; } void SetAsRectMm(const RectF& oRectMm) { if (m_bIsMargin) { static const REAL fMmToPt = 72.0f / 25.4f; REAL fLeftMarginPt = m_oRectPt.X; REAL fTopMarginPt = m_oRectPt.Y; m_oRectPt.X = oRectMm.X * fMmToPt + fLeftMarginPt; m_oRectPt.Y = oRectMm.Y * fMmToPt + fTopMarginPt; m_oRectPt.Width = oRectMm.Width * fMmToPt - fLeftMarginPt - m_oRectPt.Width; m_oRectPt.Height = oRectMm.Height * fMmToPt - fTopMarginPt - m_oRectPt.Height; m_bIsMargin = FALSE; } } void SetAsRectMm(const REAL& fWidthMm, const REAL& fHeightMm) { static const REAL fMmToPt = 72.0f / 25.4f; m_oRectPt.Width = fWidthMm * fMmToPt - m_oRectPt.X - m_oRectPt.Width; m_oRectPt.Height = fHeightMm * fMmToPt - m_oRectPt.Y - m_oRectPt.Height; m_bIsMargin = FALSE; } // --- void SetAfter(const RectF& oRectPt) { m_oRectPt.Y = oRectPt.GetBottom(); } // --- RectF GetRectPt() const { if (!m_bIsMargin) return m_oRectPt; else return m_oRectPt; } private: void ReadMarginsFromPaddings(XmlUtils::CXmlNode& paddings) { m_oRectPt.X += FloatPtAttributeFromXml(paddings, _T("padding-left")); m_oRectPt.Y += FloatPtAttributeFromXml(paddings, _T("padding-top")); m_oRectPt.Width += FloatPtAttributeFromXml(paddings, _T("padding-right")); m_oRectPt.Height += FloatPtAttributeFromXml(paddings, _T("padding-bottom")); } }; class CRegion : private CXmlAttributeReader { private: CString m_strName; CBounds m_oBounds; RectF m_oRectPt; BYTE m_nIsFilled; bool m_bIsColumn; byte m_BreakType; public: CRegion() : m_strName(_T("")), m_oBounds(), m_oRectPt(), m_nIsFilled(1), m_bIsColumn(false), m_BreakType(0) { } ~CRegion() { Clear(); } public: void Clear() { m_strName = _T(""); m_oBounds.Clear(); m_oRectPt = RectF(); m_nIsFilled = 1; m_bIsColumn = false; m_BreakType = 0; } void FromXmlNodeFo(XmlUtils::CXmlNode& oXmlNode, const bool& withPaddings = false) { m_strName = oXmlNode.GetAttributeOrValue(_T("region-name"), _T("")); if (m_strName == _T("")) { LoadStandartRegionName(oXmlNode); } m_oBounds.FromXmlNodeFo(oXmlNode, withPaddings); ReadDisplayAlign(oXmlNode); } void FromRectMm(const RectF& rect, const bool& asMargin = false) { CString m_strName = _T("from-rect"); m_oBounds.Clear(); if (asMargin) m_oBounds.SetAsMarginMm(rect.X, rect.Y, rect.Width, rect.Height); else m_oBounds.SetAsRectMm(rect); SetComplete(); CheckRect(); } public: inline void SetReady() { m_nIsFilled = 0; } inline void SetComplete() { m_nIsFilled = 1; } inline void SetProcessing() { m_nIsFilled = 2; } inline bool IsReady() { return (m_nIsFilled == 0); } inline BOOL IsComplete() { return (m_nIsFilled == 1); } inline BOOL IsEqualName(const CString& strName) { return (m_strName == strName); } inline byte BreakType() { return m_BreakType; } inline void BreakType(const byte& breakType) { m_BreakType = breakType; } public: inline const RectF& GetRectPt() const { return m_oRectPt; } inline CBounds GetBounds() { return m_oBounds; } inline RectF GetOriginalRectPt() const { return m_oBounds.GetRectPt(); } RectF GetFilledRectPt() const { RectF boundsRect = m_oBounds.GetRectPt(); return RectF(boundsRect.GetLeft(), boundsRect.GetTop(), m_oRectPt.GetRight() - m_oRectPt.GetLeft(), m_oRectPt.GetTop() - boundsRect.GetTop()); } inline REAL GetRegionHeightPt() const { return m_oRectPt.Height; } inline void SetIsColumn() { m_bIsColumn = true; } inline bool IsColumn() { return m_bIsColumn; } double GetFilledHeight() { RectF originRect = GetOriginalRectPt(); RectF rect = GetRectPt(); double originHeight = originRect.GetBottom() - originRect.GetTop(); double height = rect.GetBottom() - rect.GetTop(); return (originHeight - height); } double GetFilledWidth() { RectF originRect = GetOriginalRectPt(); double originWidth = originRect.GetRight() - originRect.GetLeft(); return originWidth; } void CheckRect() { if (IsComplete()) { m_oRectPt = m_oBounds.GetRectPt(); SetReady(); } } inline void TrancateRectPt(const REAL &fHeightPt) { m_oRectPt.Y += fHeightPt; m_oRectPt.Height -= fHeightPt; } inline void TruncateHeightPt(const REAL &fHeightPt) { m_oRectPt.Height -= fHeightPt; } inline void TruncateLeftPt(const float& delta) { m_oRectPt.X += delta; m_oRectPt.Width += delta; } void ChangeRect(CBounds oBoundsPt) { oBoundsPt.SetAsRectPt(m_oRectPt); m_oBounds = oBoundsPt; m_oRectPt = m_oBounds.GetRectPt(); } void SetRect(RectF &oRectPt) { m_oBounds.SetAsRectPt(oRectPt); m_oRectPt = m_oBounds.GetRectPt(); } public: void SetBounds(const CBounds& oBounds) { m_oBounds.SetAsRect(oBounds); } void AddBounds(const REAL& fLeftMarginPt, const REAL& fTopMarginPt, const REAL& fRightMarginPt, const REAL& fBottommarginPt) { m_oBounds.AddMarginPt(fLeftMarginPt, fTopMarginPt, fRightMarginPt, fBottommarginPt); } public: void ApplyDisplayAlign(RectF& oRectPt) { if (m_strName == _T("xsl-region-body")) { oRectPt = m_oBounds.GetRectPt(); } if (m_nIsFilled == 4) { m_oBounds.SetAfter(oRectPt); } } private: void LoadStandartRegionName(XmlUtils::CXmlNode& oXmlNode) { CString strNodeName = oXmlNode.GetName(); if (strNodeName == _T("fo:region-body")) { m_strName = _T("xsl-region-body"); } } void ReadDisplayAlign(XmlUtils::CXmlNode& oXmlNode) { CString strDisplayAlign = oXmlNode.GetAttributeOrValue(_T("display-align"), _T("")); if (strDisplayAlign == _T("after")) { m_nIsFilled = 4; } else { m_nIsFilled = 3; } } }; // ### ### ### class CBlock; class CContent; class CPictureC; class CShapeC; class CBlockC; class CTextC; class CPageNumberC; class CAlternate2 : public CItem, private CXmlAttributeReader { public: class CAreaWrap; enum EWrapType { WrapRuntime = 0, WrapInline, WrapNone, WrapTopAndBottom, WrapSquare, WrapThrough, WrapTight }; struct SSidesF { float m_fTop; float m_fBottom; float m_fLeft; float m_fRight; SSidesF() : m_fTop(0), m_fBottom(0), m_fLeft(0), m_fRight(0) { } }; class CAreaProperties : private CXmlAttributeReader2 { enum EActual { ActualComplete = 0, ActualPartial, ActualNone }; public: class GeometryProperties : private CXmlAttributeReader2 { private: bool _horizontalFlip; bool _verticalFlip; float _rotate; bool _anchored; public: GeometryProperties() { _horizontalFlip = false; _verticalFlip = false; _rotate = 0; _anchored = false; } public: void loadFromTransformXml(XmlUtils::CXmlNode& transformXml) { setRotate(transformXml.GetAttribute(_T("rotate"))); setHFlip(transformXml.GetAttribute(_T("hFlip"))); setVFlip(transformXml.GetAttribute(_T("vFlip"))); if (_horizontalFlip != _verticalFlip) _rotate *= -1; } void loadFromBoundsXml(XmlUtils::CXmlNode& boundsXml) { setRotate(AttrToStr(boundsXml, _T("rotation"), _T("val"))); setFlips(AttrToStr(boundsXml, _T("flip"), _T("val"))); if (_horizontalFlip != _verticalFlip) _rotate *= -1; } private: void setFlips(const CString& flip) { if (flip.Find(_T('x')) != -1) _horizontalFlip = true; if (flip.Find(_T('y')) != -1) _verticalFlip = true; } void setHFlip(const CString& flip) { _horizontalFlip = XmlUtils::GetBoolean(flip) == TRUE; } void setVFlip(const CString& flip) { _verticalFlip = XmlUtils::GetBoolean(flip) == TRUE; } void setRotate(const CString& rotate) { if (rotate != _T("")) _rotate = XmlUtils::GetFloat(rotate) * M_PI / 180; } public: void setRotationAngle(const float& rotate) { _rotate = rotate; } void changeHFlip() { _horizontalFlip = !_horizontalFlip; _rotate *= -1; } void changeVFlip() { _verticalFlip = !_verticalFlip; _rotate *= -1; } public: const bool& getHorzFlip() const { return _horizontalFlip; } const bool& getVertFlip() const { return _verticalFlip; } const float& getRotationAngle() const { return _rotate; } public: void setAnchored(const bool& anchored) { _anchored = anchored; } bool isAnchored() const { return _anchored; } }; private: CRelativeFrom m_eRelHorz; CRelativeFrom m_eRelVert; PointF m_oRelPoint; RectF m_oArea; SSidesF _stretch; PointF _contraint; RectF m_oRect; EActual m_eActualOfRect; CAlignHorizontal m_eAlignHorz; CAlignVertical m_eAlignVert; GeometryProperties _geometryProperties; float _zIndex; private: bool ReadIsRuntime(XmlUtils::CXmlNode& oPropertyNode) { CString strType = oPropertyNode.GetAttribute(_T("type")); if (strType == _T("runtime")) return true; else return false; } void ReadArea(RectF& area, XmlUtils::CXmlNode& propertyXml) { area.X = TextToPt(propertyXml, _T("fo:position-x")); area.Y = TextToPt(propertyXml, _T("fo:position-y")); area.Width = TextToPt(propertyXml, _T("fo:extent-x")); area.Height = TextToPt(propertyXml, _T("fo:extent-y")); XmlUtils::CXmlNode transformXml; if (propertyXml.GetNode(_T("transform"), transformXml)) _geometryProperties.loadFromTransformXml(transformXml); } CRelativeFrom ReadRelHorz(XmlUtils::CXmlNode& propertyXml) { CString relative = AttrToStr(propertyXml, _T("fo:position-x"), _T("relative-from")); return GetRelHorz(relative); } CRelativeFrom ReadRelVert(XmlUtils::CXmlNode& propertyXml) { CString relative = AttrToStr(propertyXml, _T("fo:position-y"), _T("relative-from")); return GetRelVert(relative); } CRelativeFrom GetRelHorz(const CString& relativeHorz) { if (relativeHorz == _T("page")) return FromPage; else if (relativeHorz == _T("margin")) return FromMargin; else return FromColumn; } CRelativeFrom GetRelVert(const CString& relativeVert) { if (relativeVert == _T("page")) return FromPage; else if (relativeVert == _T("margin")) return FromMargin; else if (relativeVert == _T("line")) return FromLine; else return FromParagraph; } void readStretch(XmlUtils::CXmlNode& propertyXml) { XmlUtils::CXmlNode stretchXml; if (propertyXml.GetNode(_T("stretch"), stretchXml)) { _stretch.m_fTop = stretchXml.ReadAttributeFloat(_T("top"), 0) / 100; _stretch.m_fBottom = stretchXml.ReadAttributeFloat(_T("bottom"), 0) / 100; _stretch.m_fLeft = stretchXml.ReadAttributeFloat(_T("left"), 0) / 100; _stretch.m_fRight = stretchXml.ReadAttributeFloat(_T("right"), 0) / 100; } } void readAlign(XmlUtils::CXmlNode& propertyXml) { CString align = AttrToStr(propertyXml, _T("fo:position-x"), _T("align")); m_eAlignHorz = GetAlignHorz(align); align = AttrToStr(propertyXml, _T("fo:position-y"), _T("align")); m_eAlignVert = GetAlignVert(align); } void FromContentXml(XmlUtils::CXmlNode& contentNode) { XmlUtils::CXmlNode intContentNode = contentNode; XmlUtils::CXmlNode alternateNode; if (contentNode.GetNode(_T("fo:alternate-content"), alternateNode)) if (!alternateNode.GetNode(_T("fo:content"), intContentNode)) intContentNode = contentNode; bool nodeRead = true; XmlUtils::CXmlNode oShapeNode; if (!intContentNode.GetNode(_T("shape"), oShapeNode)) if (!intContentNode.GetNode(_T("group"), oShapeNode)) nodeRead = false; if (nodeRead) { ReadAreaFromContentBounds(m_oArea, oShapeNode); ReadAlignFromContentBounds(m_eAlignHorz, m_eAlignVert, oShapeNode); ReadRelFromContentBounds(m_eRelHorz, m_eRelVert, oShapeNode); ReadZIndexFromContentBounds(_zIndex, oShapeNode); } } void ReadAreaFromContentBounds(RectF& oArea, XmlUtils::CXmlNode& oShapeNode) { XmlUtils::CXmlNode oBoundsNode; if (oShapeNode.GetNode(_T("bounds"), oBoundsNode)) { float left = AttrToPt(oBoundsNode, _T("left"), _T("val")); oArea.X = AttrToPt(oBoundsNode, _T("marginLeft"), _T("val"), left); float top = AttrToPt(oBoundsNode, _T("top"), _T("val")); oArea.Y = AttrToPt(oBoundsNode, _T("marginTop"), _T("val"), top); oArea.Width = AttrToPt(oBoundsNode, _T("width"), _T("val")); oArea.Height = AttrToPt(oBoundsNode, _T("height"), _T("val")); _geometryProperties.loadFromBoundsXml(oBoundsNode); } } void ReadAlignFromContentBounds(CAlignHorizontal& eAlignHorz, CAlignVertical& eAlignVert, XmlUtils::CXmlNode& oShapeNode) { XmlUtils::CXmlNode oBoundsNode; if (oShapeNode.GetNode(_T("bounds"), oBoundsNode)) { CString strAlign = AttrToStr(oBoundsNode, _T("PosHor"), _T("val")); m_eAlignHorz = GetAlignHorz(strAlign); strAlign = AttrToStr(oBoundsNode, _T("PosVert"), _T("val")); m_eAlignVert = GetAlignVert(strAlign); } } void ReadRelFromContentBounds(CRelativeFrom& relHorz, CRelativeFrom& relVert, XmlUtils::CXmlNode& shape) { XmlUtils::CXmlNode bounds; if (shape.GetNode(_T("bounds"), bounds)) { relHorz = GetRelHorz(AttrToStr(bounds, _T("PosHorRel"), _T("val"))); relVert = GetRelVert(AttrToStr(bounds, _T("PosVertRel"), _T("val"))); } } void ReadZIndexFromContentBounds(float& zIndex, XmlUtils::CXmlNode& shape) { XmlUtils::CXmlNode bounds; if (shape.GetNode(_T("bounds"), bounds)) zIndex = XmlUtils::GetFloat(AttrToStr(bounds, _T("z-index"), _T("val"))); } CAlignHorizontal GetAlignHorz(const CString& strAlignHorz) { CAlignHorizontal eAlignHorz = NoneAlign; if (strAlignHorz == _T("left")) eAlignHorz = LeftAlign; else if (strAlignHorz == _T("center")) eAlignHorz = CenterAlign; else if (strAlignHorz == _T("right")) eAlignHorz = RightAlign; return eAlignHorz; } CAlignVertical GetAlignVert(const CString& strAlignVert) { CAlignVertical eAlignVert = NoneAlignVert; if (strAlignVert == _T("top")) eAlignVert = FarAlignVert; else if (strAlignVert == _T("center")) eAlignVert = CenterAlignVert; else if (strAlignVert == _T("bottom")) eAlignVert = NearAlignVert; return eAlignVert; } private: void UpdatePosition(EActual actual) { if (m_eActualOfRect == ActualNone && (actual == ActualPartial || actual == ActualComplete)) { m_oRect = m_oArea; SetRectFromRelPoint(m_oRect); m_eActualOfRect = ActualPartial; } if (m_eActualOfRect == ActualPartial && actual == ActualComplete) { m_oRect.X += _contraint.X; m_oRect.Y += _contraint.Y; m_eActualOfRect = ActualComplete; } } void SetRelPoint(const CPage& oPage, const CRegion& oRegion, const RectF& line) { SetRelPointHorz(oRegion); SetRelPointVert(oRegion, line); } void SetRelPointHorz(const CRegion& oRegion) { if (m_eRelHorz == FromColumn) m_oRelPoint.X = oRegion.GetRectPt().X; else m_oRelPoint.X = 0; } void SetRelPointVert(const CRegion& oRegion, const RectF& line) { if (FromParagraph == m_eRelVert) m_oRelPoint.Y = oRegion.GetRectPt().Y; else if (FromLine == m_eRelVert) m_oRelPoint.Y = line.GetBottom(); else m_oRelPoint.Y = 0; } void Align(const CPage& page, const CRegion& region, const RectF& line) { AlignHorz(page, region); AlignVert(page, region, line); } void AlignHorz(const CPage& page, const CRegion& oRegion) { if (m_eAlignHorz == NoneAlign) return; else if (m_eAlignHorz == LeftAlign) { if (m_eRelHorz == FromPage) m_oRelPoint.X = 0; else m_oRelPoint.X = oRegion.GetRectPt().X; m_oArea.X = 0; } else if (m_eAlignHorz == CenterAlign) { if (m_eRelHorz == FromPage) m_oRelPoint.X = page.GetWidthPt()/2; else m_oRelPoint.X = oRegion.GetRectPt().X + oRegion.GetRectPt().Width/2; m_oArea.X = -m_oArea.Width/2; } else if (m_eAlignHorz == RightAlign) { if (m_eRelHorz == FromPage) m_oRelPoint.X = page.GetWidthPt(); else m_oRelPoint.X = oRegion.GetRectPt().GetRight(); m_oArea.X = -m_oArea.Width; } } void AlignVert(const CPage& page, const CRegion& oRegion, const RectF& line) { if (NoneAlignVert == m_eAlignVert) return; if (FarAlignVert == m_eAlignVert) { if (FromPage == m_eRelVert) m_oRelPoint.Y = 0; else if (FromLine == m_eRelVert) m_oRelPoint.Y = line.GetBottom(); else m_oRelPoint.Y = oRegion.GetOriginalRectPt().GetTop(); m_oArea.Y = 0; } else if (m_eAlignVert == CenterAlignVert) { if (m_eRelVert == FromPage) m_oRelPoint.Y = page.GetHeightPt()/2; else m_oRelPoint.Y = oRegion.GetOriginalRectPt().Y + oRegion.GetOriginalRectPt().Height/2; m_oArea.Y = -m_oArea.Height/2; } else if (m_eAlignVert == NearAlignVert) { if (FromPage == m_eRelVert) m_oRelPoint.Y = page.GetHeightPt(); else if (FromLine == m_eRelVert) m_oRelPoint.Y = line.GetBottom(); else m_oRelPoint.Y = oRegion.GetOriginalRectPt().GetBottom(); m_oArea.Y = -m_oArea.Height; } } private: void SetRectFromRelPoint(RectF& oRect) { oRect.X += m_oRelPoint.X; oRect.Y += m_oRelPoint.Y; } public: CAreaProperties() : m_eRelHorz(FromPage), m_eRelVert(FromPage) , m_eActualOfRect(ActualNone) , m_eAlignHorz(NoneAlign), m_eAlignVert(NoneAlignVert) , _zIndex(0) {} public: void SetAreaRect(RectF& rect, const bool& onlySize = false) { if (onlySize) { m_oArea.Width = rect.Width; m_oArea.Height = rect.Height; } else m_oArea = rect; } void SetRect(RectF& oRect) { m_oRect = oRect; } public: byte FromXml(XmlUtils::CXmlNode& alternateNode) { XmlUtils::CXmlNode propertyNode; if (!alternateNode.GetNode(_T("fo:property"), propertyNode)) return 1; XmlUtils::CXmlNode contentNode; if (!alternateNode.GetNode(_T("fo:content"), contentNode)) return 1; return FromXml(propertyNode, contentNode); } byte FromXml(XmlUtils::CXmlNode& oPropertyNode, XmlUtils::CXmlNode& oContentNode) { ReadArea(m_oArea, oPropertyNode); m_eRelHorz = ReadRelHorz(oPropertyNode); m_eRelVert = ReadRelVert(oPropertyNode); readStretch(oPropertyNode); readAlign(oPropertyNode); //bool bIsRuntime = ReadIsRuntime(oPropertyNode); //if (bIsRuntime) FromContentXml(oContentNode); return 0; } void Relate(const CPage& oPage, const CRegion& oRegion, const RectF& line) { SetRelPoint(oPage, oRegion, line); Align(oPage, oRegion, line); m_eActualOfRect = ActualNone; } bool checkContraints(const CPage& page ) { UpdatePosition(ActualPartial); if (m_oRect.X < 0) _contraint.X = -m_oRect.X; if (m_oRect.Y < 0) _contraint.Y = -m_oRect.Y; float deltaX = m_oRect.GetRight() - page.GetWidthPt(); if (deltaX > 0) _contraint.X = -deltaX; if (m_oRect.GetBottom() > page.GetHeightPt()) return false; return true; } public: const RectF& RectPt() { UpdatePosition(ActualComplete); return m_oRect; } const RectF& AreaRectPt() { return m_oArea; } const PointF& RelPointPt() { return m_oRelPoint; } CRelativeFrom RelHorz() const { return m_eRelHorz; } CRelativeFrom RelVert() const { return m_eRelVert; } float getZIndex() const { return _zIndex; } RectF getDrawingRect(const RectF& rect) const { RectF drawingRect(rect); float offsetTop = rect.Height * _stretch.m_fTop; float offsetBottom = rect.Height * _stretch.m_fBottom; drawingRect.Y += offsetTop; drawingRect.Height -= offsetTop + offsetBottom; float offsetLeft = rect.Width * _stretch.m_fLeft; float offsetRight = rect.Width * _stretch.m_fRight; drawingRect.X += offsetLeft; drawingRect.Width -= offsetLeft + offsetRight; return drawingRect; } const GeometryProperties& getGeomPr() const { return _geometryProperties; } void setAnchored(const EWrapType& wrapType) { _geometryProperties.setAnchored(wrapType == WrapInline); } }; class CAreaWrap : private CXmlAttributeReader2 { private: EWrapType m_eWrapType; int m_iInlinePosition; CArray m_arrPointsOrigin; CArray m_arrPoints; SSidesF m_oDistanceOrigin; SSidesF m_oDistance; private: bool ReadIsRuntime(XmlUtils::CXmlNode& oPropertyNode) { CString strType = oPropertyNode.GetAttribute(_T("type")); if (strType == _T("runtime")) return true; else return false; } byte FromContentXml(XmlUtils::CXmlNode& oContentNode) { bool nodeRead = true; XmlUtils::CXmlNode oShapeNode; if (!oContentNode.GetNode(_T("shape"), oShapeNode)) if (!oContentNode.GetNode(_T("group"), oShapeNode)) nodeRead = false; if (nodeRead) { m_eWrapType = ReadContentWrapType(oShapeNode); ReadDistanceFromContentBounds(m_oDistance, oShapeNode); return 0; } return 1; } EWrapType ReadWrapType(XmlUtils::CXmlNode& oPropertyNode) { CString strWrapType = oPropertyNode.GetAttribute(_T("type")); XmlUtils::CXmlNode oWrapNode; if (oPropertyNode.GetNode(_T("fo:wrap"), oWrapNode)) strWrapType = oWrapNode.GetAttribute(_T("type")); return GetWrapType(strWrapType); } EWrapType ReadContentWrapType(XmlUtils::CXmlNode& oShapeNode) { CString strWrapType = _T("none"); XmlUtils::CXmlNode oWrapNode; if (oShapeNode.GetNode(_T("w10:wrap"), oWrapNode)) { strWrapType = oWrapNode.GetAttribute(_T("type")); if (strWrapType == _T("")) { CString anchorX = oWrapNode.GetAttribute(_T("anchorx")); CString anchorY = oWrapNode.GetAttribute(_T("anchory")); bool wrapNoneX = false; if ((anchorX == _T("page")) || (anchorX == _T("margin"))) wrapNoneX = true; bool wrapNoneY = false; if ((anchorY == _T("page")) || (anchorY == _T("margin"))) wrapNoneY = true; if (wrapNoneX && wrapNoneY) return WrapNone; } } if (strWrapType == _T("none")) { XmlUtils::CXmlNode oBoundsNode; if (oShapeNode.GetNode(_T("bounds"), oBoundsNode)) { CString pos = AttrToStr(oBoundsNode, _T("Pos"), _T("val")); if ((pos == _T("")) || (pos == _T("static"))) strWrapType = _T("inline"); } } return GetWrapType(strWrapType); } void ReadDistance(SSidesF& oDistance, XmlUtils::CXmlNode& oPropertyNode) { XmlUtils::CXmlNode anchorNode; if (oPropertyNode.GetNode(_T("fo:anchor"), anchorNode)) { oDistance.m_fLeft = AttrToPt(anchorNode, _T(""), _T("distance-left"), 0); oDistance.m_fRight = AttrToPt(anchorNode, _T(""), _T("distance-right"), 0); oDistance.m_fTop = AttrToPt(anchorNode, _T(""), _T("distance-top"), 0); oDistance.m_fBottom = AttrToPt(anchorNode, _T(""), _T("distance-bottom"), 0); } } void ReadDistanceFromContentBounds(SSidesF& oDistance, XmlUtils::CXmlNode& oShapeNode) { XmlUtils::CXmlNode oBoundsNode; if (oShapeNode.GetNode(_T("bounds"), oBoundsNode)) { oDistance.m_fLeft = AttrToPt(oBoundsNode, _T("wrapDistLeft"), _T("val"), 9); oDistance.m_fRight = AttrToPt(oBoundsNode, _T("wrapDistRight"), _T("val"), 9); oDistance.m_fTop = AttrToPt(oBoundsNode, _T("wrapDistTop"), _T("val")); oDistance.m_fBottom = AttrToPt(oBoundsNode, _T("wrapDistBottom"), _T("val")); } } private: void Points(const RectF& oRect) { m_arrPoints.RemoveAll(); m_arrPoints.Add(PointF(oRect.GetLeft(), oRect.GetTop())); m_arrPoints.Add(PointF(oRect.GetRight(), oRect.GetTop())); m_arrPoints.Add(PointF(oRect.GetRight(), oRect.GetBottom())); m_arrPoints.Add(PointF(oRect.GetLeft(), oRect.GetBottom())); m_arrPoints.Add(PointF(oRect.GetLeft(), oRect.GetTop())); } void Points(const CArray& arrPoints) { m_arrPoints.RemoveAll(); m_arrPoints.Copy(arrPoints); } EWrapType GetWrapType(const CString strWrapType) { EWrapType eReturnWrapType = WrapInline; if (strWrapType == _T("none")) eReturnWrapType = WrapNone; else if (strWrapType == _T("topAndBottom")) eReturnWrapType = WrapTopAndBottom; else if (strWrapType == _T("square")) eReturnWrapType = WrapSquare; else if (strWrapType == _T("through")) eReturnWrapType = WrapThrough; else if (strWrapType == _T("tight")) eReturnWrapType = WrapTight; else if (strWrapType == _T("inline")) eReturnWrapType = WrapInline; return eReturnWrapType; } private: void ApplyTopAndBottom(CAreaProperties& oAreaProperties, const CRegion& oRegion) { RectF& oRegionRect = oRegion.GetOriginalRectPt(); RectF oAreaRect = oAreaProperties.RectPt(); float distLeft = oAreaRect.GetLeft() - oRegionRect.GetLeft(); float distRight = oRegionRect.GetRight() - oAreaRect.GetRight(); if ((distLeft >= 0) && (distRight >= 0)) { m_oDistance.m_fLeft = distLeft; m_oDistance.m_fRight = distRight; Points(oAreaRect); } else ApplySquare(oAreaProperties, oRegion); } void ApplySquare(CAreaProperties& oAreaProperties, const CRegion& oRegion) { RectF oAreaRect = oAreaProperties.RectPt(); oAreaRect.Y -= m_oDistance.m_fTop; oAreaRect.Height += m_oDistance.m_fTop + m_oDistance.m_fBottom; Points(oAreaRect); } void ApplyTight(CAreaProperties& oAreaProperties, const CRegion& oRegion) { RectF oAreaRect = oAreaProperties.RectPt(); oAreaRect.Y -= m_oDistance.m_fTop; oAreaRect.Height += m_oDistance.m_fTop + m_oDistance.m_fBottom; Points(oAreaRect); } public: CAreaWrap() : m_eWrapType(WrapNone), m_iInlinePosition(0), m_arrPointsOrigin(), m_arrPoints(), m_oDistanceOrigin(), m_oDistance() { } ~CAreaWrap() { } public: byte FromXml(XmlUtils::CXmlNode& oPropertyNode, XmlUtils::CXmlNode& oContentNode) { m_eWrapType = ReadWrapType(oPropertyNode); ReadDistance(m_oDistance, oPropertyNode); bool bIsRuntime = ReadIsRuntime(oPropertyNode); if (bIsRuntime) FromContentXml(oContentNode); return 0; } int InlinePosition() { return m_iInlinePosition; } void InlinePosition(const int& iPosition) { m_iInlinePosition = iPosition; } EWrapType WrapType() { return m_eWrapType; } const CArray& Points() { return m_arrPoints; } const SSidesF& Distance() const { return m_oDistance; } public: bool Inline() { return (m_eWrapType == WrapInline); } void Inline(const bool& bIsInline) { if (bIsInline == true) m_eWrapType = WrapInline; else assert(false); } public: void Wrap(CAreaProperties& areaProperties, const CRegion& region) { areaProperties.setAnchored(m_eWrapType); if (m_eWrapType == WrapTopAndBottom) ApplyTopAndBottom(areaProperties, region); else if (m_eWrapType == WrapSquare) ApplySquare(areaProperties, region); else if (m_eWrapType == WrapTight) ApplyTight(areaProperties, region); } }; class CAltContent { private: enum EContentType { ContentShape = 0, ContentPicture, ContentGroup, ContentLargeLetter, ContentNone }; private: CContent* m_pContent; CTextC* _Text; EContentType m_eType; bool m_bPlaced; private: byte FromPropertyXml(XmlUtils::CXmlNode& oPropertyNode) { XmlUtils::CXmlNode graphicsNode; if (oPropertyNode.GetNode(_T("fo:graphic"), graphicsNode)) m_eType = ReadContentType(graphicsNode); if (m_eType == ContentPicture) if (!PictureFromXml(graphicsNode)) return 0; return 1; } EContentType ReadContentType(XmlUtils::CXmlNode& graphicsNode) { CString strContentType = graphicsNode.GetAttribute(_T("type")); if (strContentType == _T("shape")) return ContentShape; else if (strContentType == _T("picture")) return ContentPicture; else if (strContentType == _T("LargeLetter")) return ContentLargeLetter; else if (strContentType == _T("group")) return ContentGroup; return ContentNone; } byte FromContentXml(XmlUtils::CXmlNode& oContentNode, CDocumentManager& documentManager) { if (m_eType == ContentShape) return ShapeFromXml(oContentNode, documentManager); else if (m_eType == ContentLargeLetter) return LargeLetterFromXml(oContentNode, documentManager); else if (m_eType == ContentGroup) return GroupFromXml(oContentNode, documentManager); return 1; } byte ReadContentTypeFromContent(XmlUtils::CXmlNode& alternateNode) { XmlUtils::CXmlNode contentNode; if (alternateNode.GetNode(_T("fo:content"), contentNode)) { XmlUtils::CXmlNode innerAlternateNode; if (contentNode.GetNode(_T("fo:alternate-content"), innerAlternateNode)) { XmlUtils::CXmlNode propertyNode; if (innerAlternateNode.GetNode(_T("fo:property"), propertyNode)) return FromPropertyXml(propertyNode); } } return 1; } byte PictureFromXml(XmlUtils::CXmlNode& oContentNode) { CPictureC* pPicture = new CPictureC(); if (!pPicture->FromXml(oContentNode)) { m_pContent = pPicture; return 0; } return 1; } byte ShapeFromXml(XmlUtils::CXmlNode& oContentNode, CDocumentManager& documentManager) { XmlUtils::CXmlNode oIntContentNode = oContentNode; XmlUtils::CXmlNode oAlternateNode; if (oContentNode.GetNode(_T("fo:alternate-content"), oAlternateNode)) if (!oAlternateNode.GetNode(_T("fo:content"), oIntContentNode)) oIntContentNode = oContentNode; CShapeC* pShape = new CShapeC(); if (!pShape->FromXml(oIntContentNode)) { m_pContent = pShape; TextFromXml(oIntContentNode, documentManager); } return (m_pContent != NULL) ? 0 : 1; } byte LargeLetterFromXml(XmlUtils::CXmlNode& oContentNode, CDocumentManager& documentManager) { XmlUtils::CXmlNode oIntContentNode = oContentNode; XmlUtils::CXmlNode oAlternateNode; if (oContentNode.GetNode(_T("fo:alternate-content"), oAlternateNode)) if (!oAlternateNode.GetNode(_T("fo:content"), oIntContentNode)) oIntContentNode = oContentNode; CBlockC* pBlock = new CBlockC(); if (!pBlock->FromXml(oIntContentNode, documentManager)) m_pContent = pBlock; return (m_pContent != NULL) ? 0 : 1; } byte GroupFromXml(XmlUtils::CXmlNode& contentNode, CDocumentManager& documentManager) { XmlUtils::CXmlNode intContentNode = contentNode; XmlUtils::CXmlNode alternateNode; if (contentNode.GetNode(_T("fo:alternate-content"), alternateNode)) if (!alternateNode.GetNode(_T("fo:content"), intContentNode)) intContentNode = contentNode; CGroupC* group = new CGroupC(); if (!group->FromXml(intContentNode, documentManager)) m_pContent = group; return (m_pContent != NULL) ? 0 : 1; } byte TextFromXml(XmlUtils::CXmlNode& contentNode, CDocumentManager& documentManager) { XmlUtils::CXmlNode shapeNode; if (contentNode.GetNode(_T("shape"), shapeNode)) { XmlUtils::CXmlNode textBoxNode; if (shapeNode.GetNode(_T("textBox"), textBoxNode)) { _Text = new CTextC(); if (_Text->FromXml(textBoxNode, documentManager)) RELEASEOBJECT(_Text); } } return 0; } public: CAltContent() : m_pContent(NULL), _Text(NULL), m_eType(ContentNone), m_bPlaced(false) { } ~CAltContent() { RELEASEOBJECT(m_pContent); RELEASEOBJECT(_Text); } public: byte FromXml(XmlUtils::CXmlNode& oAlternateNode, CDocumentManager& documentManager) { RELEASEOBJECT(m_pContent); RELEASEOBJECT(_Text); bool bIsLoaded = false; XmlUtils::CXmlNode oPropertyNode; if (oAlternateNode.GetNode(_T("fo:property"), oPropertyNode)) if (!FromPropertyXml(oPropertyNode)) bIsLoaded = true; if (m_eType == ContentNone) ReadContentTypeFromContent(oAlternateNode); if (!bIsLoaded) { if (m_eType != ContentNone) { XmlUtils::CXmlNode oContentNode; if (oAlternateNode.GetNode(_T("fo:content"), oContentNode)) if (!FromContentXml(oContentNode, documentManager)) bIsLoaded = true; } } return (bIsLoaded) ? 0 : 1; } void Update(CGrapher* pGrapher, RectF& oRect, float& fDescent, CAlternate2::CAreaProperties& m_oAreaProperties) { assert(m_pContent != NULL); m_pContent->Update(pGrapher, oRect, fDescent, m_oAreaProperties); if (_Text) _Text->Update(pGrapher, oRect, fDescent, m_oAreaProperties); } void CalculateRect(CAlternate2::CAreaProperties& m_oAreaProperties) { m_pContent->CalculateRect(m_oAreaProperties); if (_Text) _Text->fitRegionIfNecessary(m_oAreaProperties); } public: void Set(CContent* pContent) { RELEASEOBJECT(m_pContent); m_pContent = pContent; } bool Placed() { return m_bPlaced; } void Placed(const bool& bPlaced) { m_bPlaced = bPlaced; } bool isLetter() const { return dynamic_cast(m_pContent) != NULL; } public: void Draw(IAVSRenderer *pRenderer, CDocumentManager& documentManager, const RectF& oRect, const float& fDescent, const CAreaProperties::GeometryProperties& geomPr, const float& fCompleteness) { if (m_pContent != NULL) { IAVSRenderer2* renderer2 = NULL; if (!SUCCEEDED(pRenderer->QueryInterface(__UUIDOF__IAVSRENDERER2, (void**)&renderer2))) renderer2 = NULL; if (renderer2 != NULL) m_pContent->sendBeginCommand(renderer2, geomPr); m_pContent->transform(geomPr.getRotationAngle(), geomPr.getHorzFlip(), geomPr.getVertFlip()); m_pContent->Draw(pRenderer, documentManager, oRect, fDescent, fCompleteness); m_pContent->clearTransform(); if (renderer2 != NULL) m_pContent->sendEndCommand(renderer2, geomPr); RELEASEINTERFACE(renderer2); } if (_Text) _Text->Draw(pRenderer, documentManager, oRect, fDescent, fCompleteness); } void MoveOn(const float& deltaX, const float& deltaY) { if (m_pContent) m_pContent->MoveOn(deltaX, deltaY); if (_Text) _Text->MoveOn(deltaX, deltaY); } }; class CInlineProperties { public: CInlineProperties() : m_VertPosition(0) { } ~CInlineProperties() { Clear(); } void Clear() { m_VertPosition = 0; } public: void FromXml(XmlUtils::CXmlNode& alternateProperty) { XmlUtils::CXmlNode inlineProperty; if (alternateProperty.GetNode(_T("inline"), inlineProperty)) m_VertPosition = XmlUtils::GetFloat(inlineProperty.GetAttribute(_T("vert-pos"), _T("0"))); } public: float VertPos() const { return m_VertPosition; } private: float m_VertPosition; }; private: CAreaProperties m_oAreaProperties; CAreaWrap m_oAreaWrap; CAltContent m_oAltContent; CInlineProperties m_oInlineProperties; bool m_Related; bool _inHeader; private: void UpdateRect() { m_oRect = m_oAreaProperties.RectPt(); if (m_oAreaWrap.Inline()) SetOnBaseline(); } public: CAlternate2() : CItem() , m_oAreaProperties(), m_oAreaWrap() , m_oAltContent(), m_oInlineProperties() , m_Related(false), _inHeader(false) {} virtual ~CAlternate2() {} public: byte FromXml(XmlUtils::CXmlNode& alternateNode, CDocumentManager& documentManager, const bool& bUpdate = false) { #ifdef TME_NODE_XML CString xml = alternateNode.GetXml(); #endif XmlUtils::CXmlNode oPropertyNode; if (!alternateNode.GetNode(_T("fo:property"), oPropertyNode)) return 1; XmlUtils::CXmlNode oContentNode; if (!alternateNode.GetNode(_T("fo:content"), oContentNode)) return 1; if (m_oAreaWrap.FromXml(oPropertyNode, oContentNode)) return 2; if (m_oAreaProperties.FromXml(oPropertyNode, oContentNode)) return 3; if (m_oAltContent.FromXml(alternateNode, documentManager)) return 4; m_oInlineProperties.FromXml(oPropertyNode); m_fDescent = -m_oInlineProperties.VertPos(); UpdateRect(); return 0; } void SetContent(CContent* pContent, const int& iInlinePosition = 0) { assert(pContent != NULL); m_oAltContent.Set(pContent); m_oAreaWrap.InlinePosition(iInlinePosition); } void UpdateContent(CGrapher* pGrapher) { m_oAltContent.Update(pGrapher, m_oRect, m_fDescent, m_oAreaProperties); if (Inline()) SetOnBaseline(); } bool relate(CPage& page, CRegion& region, const RectF& line) { m_oAreaProperties.Relate(page, region, line); m_oAltContent.CalculateRect(m_oAreaProperties); /*if (!m_oAreaProperties.checkContraints(page)) return false;*/ UpdateRect(); m_oAreaWrap.Wrap(m_oAreaProperties, region); return true; } public: int InlinePosition() { return m_oAreaWrap.InlinePosition(); } void InlinePosition(const int& iInlinePosition) { assert(iInlinePosition >= 0); m_oAreaWrap.InlinePosition(iInlinePosition); } bool Placed() { return m_oAltContent.Placed(); } void Placed(const bool& bPlaced) { m_oAltContent.Placed(bPlaced); } bool Related() const { return m_Related; } void Related(const bool& related) { m_Related = related; } bool AnchoredToRegion() const { if (m_oAreaProperties.RelVert() == FromParagraph) return true; else return false; } const CArray& Points() { return m_oAreaWrap.Points(); } float DistanceLeft() const { return m_oAreaWrap.Distance().m_fLeft; } float DistanceRight() const { return m_oAreaWrap.Distance().m_fRight; } float getZIndex() const { return m_oAreaProperties.getZIndex(); } void setInHeader(const bool& inHeader) { _inHeader = inHeader; } public: bool Inline() { return m_oAreaWrap.Inline(); } void Inline(const bool& bIsInline) { m_oAreaWrap.Inline(bIsInline); } public: bool isLetter() const { return m_oAltContent.isLetter(); } CItemType GetType() { return Alternate; } void Draw(IAVSRenderer* renderer, CDocumentManager& documentManager, const float& completeness) { if (_inHeader) renderer->BeginCommand(c_nHeader); RectF drawingRect = m_oAreaProperties.getDrawingRect(m_oRect); m_oAltContent.Draw(renderer, documentManager, drawingRect, m_fDescent, m_oAreaProperties.getGeomPr(), completeness); //CItem::drawRect(renderer, m_oRect); if (_inHeader) renderer->EndCommand(c_nHeader); } void MoveOn(const float& deltaX, const float& deltaY) { CItem::MoveOn(deltaX, deltaY); m_oAltContent.MoveOn(deltaX, deltaY); } }; class CContent { protected: class ContentTransformer { private: bool _enabled; float _rotate; bool _horzFlip; bool _vertFlip; public: ContentTransformer() : _enabled(false) , _rotate(0) , _horzFlip(false), _vertFlip(false) { } public: void setTransform(const float& rotate, const bool& horzFlip, const bool& vertFlip) { assert(!isEnabled()); if (rotate != 0 || horzFlip || vertFlip) { _rotate = rotate; _horzFlip = horzFlip; _vertFlip = vertFlip; setEnabled(true); } } void clearTransform() { setEnabled(false); } private: void setEnabled(const bool& enabled) { _enabled = enabled; } protected: bool isEnabled() const { return _enabled; } float getRotate() const { return _rotate; } float getFlipXCoeff() const { return _horzFlip ? -1 : 1; } float getFlipYCoeff() const { return _vertFlip ? -1 : 1; } }; public: CArray m_arrPoints; public: virtual ~CContent() { Clear(); } public: void Clear() { m_arrPoints.RemoveAll(); } virtual bool FromXmlNode(XmlUtils::CXmlNode& oXmlNode) { return false; } virtual void Update(CGrapher* pGrapher, RectF& oRect, REAL& fDescent, CAlternate2::CAreaProperties& m_oAreaProperties) { oRect.Y = -oRect.Height + fDescent; } virtual BYTE GetType() { return 0; } virtual void CalculateRect(CAlternate2::CAreaProperties& m_oAreaProperties) {} public: void SetPoints(const CArray& arrPoints) { m_arrPoints.RemoveAll(); m_arrPoints.Copy(arrPoints); } void SetPoints(const REAL& fPositionX, const REAL& fPositionY) { for (size_t nIndex = 0; nIndex < m_arrPoints.GetCount(); ++nIndex) { m_arrPoints[nIndex].X += fPositionX; m_arrPoints[nIndex].Y += fPositionY; } } CArray& GetPoints() { return m_arrPoints; } public: virtual void Draw(IAVSRenderer* renderer, CDocumentManager& documentManager, const RectF& rect, const float& descent, const float& completeness) { } public: virtual void MoveOn(const float& deltaX, const float& deltaY) {} public: virtual void transform(const float& angle, const bool& horzFlip, const bool& vertFlip) {} virtual void clearTransform() {} public: virtual void sendBeginCommand(IAVSRenderer2* renderer , const CAlternate2::CAreaProperties::GeometryProperties& geomPr) {} virtual void sendEndCommand(IAVSRenderer2* renderer , const CAlternate2::CAreaProperties::GeometryProperties& geomPr) {} protected: static inline RectF convertFromPtToMm(const RectF& rect) { static const float multPtToMm = 25.4f / 72.0f;; return RectF(rect.X * multPtToMm, rect.Y * multPtToMm , rect.Width * multPtToMm, rect.Height * multPtToMm); } }; class CPictureC : public CContent { private: class PictureTransformer : public ContentTransformer { protected: IAVSRenderer* _renderer; public: PictureTransformer() : ContentTransformer() { } public: void applyTransform(IAVSRenderer* renderer, RectF& rectMm) { if (isEnabled()) { _renderer = renderer; float rotate = -getRotate(); float cosA = cos(rotate); float sinA = sin(rotate); _renderer->SetTransform(getFlipXCoeff() * cosA, -getFlipXCoeff() * sinA , getFlipYCoeff() * sinA, getFlipYCoeff() * cosA , rectMm.X + rectMm.Width / 2, rectMm.Y + rectMm.Height / 2); rectMm.X = -rectMm.Width / 2; rectMm.Y = -rectMm.Height / 2; } } void clearTransform() { if (isEnabled()) _renderer->ResetTransform(); ContentTransformer::clearTransform(); } } _transformer; public: CString m_strSourceFilePath; public: CPictureC() : m_strSourceFilePath(_T("")) { } ~CPictureC() { Clear(); } public: void Clear() { m_strSourceFilePath = _T(""); } byte FromXml(XmlUtils::CXmlNode &oContentNode) { XmlUtils::CXmlNode oSourceNode; oContentNode.GetNode(_T("fo:source"), oSourceNode); m_strSourceFilePath = oSourceNode.GetTextExt(); if ((m_strSourceFilePath == _T("")) && (m_strSourceFilePath == _T("NULL"))) { m_strSourceFilePath = _T(""); return 1; } CString strTempDirectoryPath = oSourceNode.GetAttributeOrValue(_T("dir"), _T("")); strTempDirectoryPath = ConvertToLongPathName(strTempDirectoryPath); m_strSourceFilePath.Replace( _T('/'), _T('\\')); m_strSourceFilePath = strTempDirectoryPath + _T("\\word\\") + m_strSourceFilePath; return 0; } BYTE GetType() { return 1; } void CalculateRect(CAlternate2::CAreaProperties& m_oAreaProperties) { } public: void Draw(IAVSRenderer* renderer, CDocumentManager &documentManager, const RectF& rect, const REAL& descent, const REAL &completeness) { RectF rectMm = convertFromPtToMm(rect); _transformer.applyTransform(renderer, rectMm); if (m_strSourceFilePath != _T("")) { BSTR bstrSourceFilePath = m_strSourceFilePath.AllocSysString(); renderer->DrawImageFromFile(bstrSourceFilePath, rectMm.X, rectMm.Y, rectMm.Width, rectMm.Height); SysFreeString(bstrSourceFilePath); } else DrawBorder(renderer, rect, descent, completeness); } public: virtual void transform(const float& angle, const bool& horzFlip, const bool& vertFlip) { _transformer.setTransform(angle, horzFlip, vertFlip); } virtual void clearTransform() { _transformer.clearTransform(); } private: CString ConvertToLongPathName(const CString &strShortPath) { DWORD nLength = GetLongPathName(strShortPath, NULL, 0); TCHAR *pLongPath = new TCHAR[nLength]; GetLongPathName(strShortPath, pLongPath, nLength); CString strLongPath = CString(pLongPath); delete[] pLongPath; return strLongPath; } private: void DrawBorder(IAVSRenderer* renderer, const RectF& rect, const float& descent, const float &completeness) { const float ptToMm = 25.4f / 72.0f; renderer->put_PenColor(0x00); renderer->put_PenSize(0.1); renderer->put_PenAlpha(255); renderer->PathCommandStart(); renderer->PathCommandMoveTo(rect.X * ptToMm, rect.Y * ptToMm); renderer->PathCommandLineTo(rect.X * ptToMm + rect.Width * ptToMm, rect.Y * ptToMm); renderer->PathCommandLineTo(rect.X * ptToMm + rect.Width * ptToMm, rect.Y * ptToMm + rect.Height * ptToMm); renderer->PathCommandLineTo(rect.X * ptToMm, rect.Y * ptToMm + rect.Height * ptToMm); renderer->PathCommandLineTo(rect.X * ptToMm, rect.Y * ptToMm); renderer->PathCommandClose(); renderer->DrawPath(0x01); renderer->PathCommandEnd(); } }; class CShapeC : public CContent { public: CString m_strSourceXml; XmlUtils::CXmlNode m_oXmlNode; CGeomShapeInfo _info; public: CShapeC() : m_strSourceXml(_T("")) { } ~CShapeC() { Clear(); } public: void Clear() { m_strSourceXml = _T(""); } byte FromXml(XmlUtils::CXmlNode& oContentNode) { XmlUtils::CXmlNode oShapeNode; if (oContentNode.GetNode(_T("shape"), oShapeNode)) { m_oXmlNode = oShapeNode; return 0; } return 1; } BYTE GetType() { return 2; } public: void Draw(IAVSRenderer *pRenderer, CDocumentManager& documentManager, const RectF& oRect , const REAL& fDescent, const REAL &fCompleteness) { const REAL fPtToMm = 25.4f / 72.0f; RectF oRectMm; oRectMm.X = oRect.X * fPtToMm; oRectMm.Y = oRect.Y * fPtToMm; oRectMm.Width = oRect.Width * fPtToMm; oRectMm.Height = oRect.Height * fPtToMm; CShape oShape(NSBaseShape::ppt, 0); CMetricInfo oMetric; oMetric.m_lMillimetresHor = (DWORD)documentManager.GetPageWidthMm(); oMetric.m_lMillimetresVer = (DWORD)documentManager.GetPageHeightMm(); oShape.LoadFromXML(m_oXmlNode); SetInfo(_info, oRectMm); #ifdef PPT_DEF oShape.ToRenderer(pRenderer, _info, oMetric, 0.0, 1.0); #else DrawNonPPTShape(pRenderer, oShape, _info, oMetric); #endif } private: void SetInfo(CGeomShapeInfo& oInfo, RectF oRectMm) { oInfo.m_dLeft = (double)(oRectMm.X); oInfo.m_dTop = (double)(oRectMm.Y); oInfo.m_dWidth = (double)(oRectMm.Width); oInfo.m_dHeight = (double)(oRectMm.Height); } void DrawNonPPTShape(IAVSRenderer* renderer, CShape& shape, CGeomShapeInfo& info, CMetricInfo& metric) { CString strXml = shape.ToXml(info, metric, 0.0, 1.0); strXml = _T("") + strXml + _T(""); XmlUtils::CXmlNode oXmlNode; if (oXmlNode.FromXmlString(strXml)) { XmlUtils::CXmlNodes oListGraphics; if (oXmlNode.GetNodes(_T("ImagePaint-DrawGraphicPath"), oListGraphics)) { LONG lCount = oListGraphics.GetCount(); for (LONG i = 0; i < lCount; ++i) { XmlUtils::CXmlNode oNode; oListGraphics.GetAt(i, oNode); CDrawGraphicPath oGraphicPath; oGraphicPath.InternalFromXmlNode(oNode); oGraphicPath.Draw(renderer); renderer->PathCommandEnd(); } } } } public: virtual void transform(const float& angle, const bool& horzFlip, const bool& vertFlip) { CContent::transform(angle, horzFlip, vertFlip); _info.m_dRotate = angle * 180 / M_PI; _info.m_bFlipH = horzFlip; _info.m_bFlipV = vertFlip; } virtual void clearTransform() { CContent::clearTransform(); _info.m_dRotate = 0; _info.m_bFlipH = false; _info.m_bFlipV = false; } public: virtual void sendBeginCommand(IAVSRenderer2* renderer , const CAlternate2::CAreaProperties::GeometryProperties& geomPr) { IAVSRenderer* pRend = NULL; renderer->QueryInterface(__uuidof(IAVSRenderer), (void**)&pRend); pRend->BeginCommand(c_nShape); RELEASEINTERFACE(pRend); renderer->CommandLong2(c_nShapeWrap, geomPr.isAnchored()); } virtual void sendEndCommand(IAVSRenderer2* renderer , const CAlternate2::CAreaProperties::GeometryProperties& geomPr) { IAVSRenderer* pRend = NULL; renderer->QueryInterface(__uuidof(IAVSRenderer), (void**)&pRend); pRend->EndCommand(c_nShape); RELEASEINTERFACE(pRend); } }; class CBlockC : public CContent { public: CBlock* m_Block; private: double m_dHeightRegion; double m_dWidthRegion; private: double m_dHeightPage; double m_dWidthPage; double m_dLeftBorder; double m_dRightBorder; public: CAtlArray m_lines; CBlockFrameAttributes* m_pBlockFrameAttributes; public: CBlockC() :m_dHeightRegion(0), m_dWidthRegion(0), m_pBlockFrameAttributes(NULL) { m_Block = new CBlock(); m_pBlockFrameAttributes = new CBlockFrameAttributes(); } ~CBlockC() { Clear(); } public: void Clear() { delete m_Block; size_t nFLinesCount = m_lines.GetCount(); for (size_t nIndex = 0; nIndex < nFLinesCount; ++nIndex) { RELEASEOBJECT(m_lines[nIndex]); } RELEASEOBJECT(m_pBlockFrameAttributes); } void Update(CGrapher* pGrapher, RectF& oRect, REAL& fDescent, CAlternate2::CAreaProperties& m_oAreaProperties) { m_dHeightPage = (double)pGrapher->m_DocumentManager->GetPageHeightMm(); m_dWidthPage = (double)pGrapher->m_DocumentManager->GetPageWidthMm(); m_dLeftBorder = (double)pGrapher->m_DocumentManager->GetPageLeftBorderMm(); m_dRightBorder= (double)pGrapher->m_DocumentManager->GetPageRightBorderMm(); /*m_dHeightPage = (double)CDocumentManager::GetPageHeightMm() * 72 / 25.4; m_dWidthPage = (double)CDocumentManager::GetPageWidthMm() * 72 / 25.4; m_dLeftBorder = (double)CDocumentManager::GetPageLeftBorderPt(); m_dRightBorder= (double)CDocumentManager::GetPageRightBorderPt();*/ double dWidth = 0; if (m_pBlockFrameAttributes->m_width > 0) dWidth = min((m_dRightBorder - m_dLeftBorder), m_pBlockFrameAttributes->m_width); else dWidth = m_dRightBorder - m_dLeftBorder; RectF rect(0, 0, dWidth * 25.4 / 72 , m_dHeightPage* 25.4 / 72); //RectF rect(0, 0, (m_dRightBorder - m_dLeftBorder) * 25.4 / 72, m_dHeightPage); CRegion textRegion; textRegion.FromRectMm(rect); CPage page; page.StartPrintingFlow(); m_Block->IgnoreAnchors(true); m_Block->FillRegion(textRegion, page, true, pGrapher); page.GetLines(m_lines); m_dHeightRegion = textRegion.GetFilledHeight(); m_dWidthRegion = GetFillWidth(dWidth); oRect.X = 0; oRect.Y = 0; oRect.Width = max(m_dWidthRegion, m_pBlockFrameAttributes->m_width) + m_pBlockFrameAttributes->m_hSpace; oRect.Height = max(m_dHeightRegion, m_pBlockFrameAttributes->m_height) + m_pBlockFrameAttributes->m_vSpace; m_oAreaProperties.SetAreaRect(oRect); } byte FromXml(XmlUtils::CXmlNode& contentNode, CDocumentManager& documentManager) { #ifdef TME_NODE_XML CString xml = contentNode.GetXml(); #endif XmlUtils::CXmlNode oBlockNode; contentNode.GetNode(_T("fo:block"), oBlockNode); m_Block->InTable(false); CAtlArray curCommands; bool inCommandField = false; m_Block->FromXmlNode(oBlockNode, documentManager, false, inCommandField, curCommands); m_pBlockFrameAttributes->FromXmlNode(oBlockNode); m_Block->m_pBlockAttributes->m_nSpaceAfter = 0; m_Block->m_pBlockAttributes->m_nSpaceBefore = 0; return 0; } BYTE GetType() { return 3; } public: void CalculateRect(CAlternate2::CAreaProperties& m_oAreaProperties) { RectF oRect = m_oAreaProperties.AreaRectPt(); PointF oPoint = m_oAreaProperties.RelPointPt(); double dX = 0; if (m_pBlockFrameAttributes->m_xAlign == _T("right")) { if (m_pBlockFrameAttributes->m_hAnchor == _T("margin")) dX = m_dRightBorder - m_dWidthRegion - oPoint.X; else if (m_pBlockFrameAttributes->m_hAnchor == _T("page")) dX = m_dWidthPage - m_dWidthRegion - oPoint.X; } else if (m_pBlockFrameAttributes->m_xAlign == _T("left")) { if (m_pBlockFrameAttributes->m_hAnchor == _T("margin")) dX = 0; else if (m_pBlockFrameAttributes->m_hAnchor == _T("page")) dX = -oPoint.X; } else if (m_pBlockFrameAttributes->m_x > 0) { dX = m_pBlockFrameAttributes->m_x; if (m_pBlockFrameAttributes->m_hAnchor == _T("page")) dX -= oPoint.X; } else if (m_pBlockFrameAttributes->m_dropCap == _T("drop")) { dX = oRect.GetLeft(); } else if (m_dWidthRegion < m_dLeftBorder) { dX = m_dLeftBorder - m_dWidthRegion - oPoint.X; } double dY = 0; if (m_pBlockFrameAttributes->m_y > 0) { dY = m_pBlockFrameAttributes->m_y; if (m_pBlockFrameAttributes->m_vAnchor == _T("page")) dY -= oPoint.Y; } else { dY = oRect.GetTop(); } oRect.X = dX; oRect.Y = dY; m_oAreaProperties.SetAreaRect(oRect); dX = dX + oPoint.X; dY = dY + oPoint.Y; double dDeltaX = 0; double dDeltaY = 0; size_t nCount = m_lines.GetCount(); if (nCount > 0) { CLine* pFirstLine = m_lines[0]; dDeltaX = dX;// - pFirstLine->GetRect().GetLeft(); dDeltaY = dY;// - pFirstLine->GetRect().GetTop(); } for (size_t i = 0; i < nCount; ++i) { m_lines[i]->MoveOn(dDeltaX, dDeltaY); } } void Draw(IAVSRenderer* renderer, CDocumentManager& documentManager, const RectF& rect, const float& descent, const float& completeness) { #ifdef TME_DRAW_LETTER_BORDER CItem::drawRect(renderer, rect); #endif size_t nCount = m_lines.GetCount(); for (size_t i = 0; i < nCount; ++i) m_lines[i]->Draw(renderer, documentManager, completeness); } public: void MoveOn(const float& deltaX, const float& deltaY) { for (size_t i = 0; i < m_lines.GetCount(); ++i) m_lines[i]->MoveOn(deltaX, deltaY); } private: double GetFillWidth(double dWidth) { //double widthRegion = (m_dRightBorder - m_dLeftBorder)/* * 72.0f / 25.4f */; size_t size = m_lines.GetCount(); double minPersist = dWidth; for( size_t i = 0; i < size; ++i) { double dCurrentPersist = (double)m_lines[i]->GetPersistWidth(); if (minPersist > dCurrentPersist) minPersist = dCurrentPersist; } return (dWidth - minPersist); } }; class CPageNumberC : public CContent { private: CString m_strText; bool m_bIsPageCount; CCharacter* m_pCharacter; public: CPageNumberC() : m_strText(_T("")), m_bIsPageCount(false), m_pCharacter(NULL) { } CPageNumberC(CCharacter *pCharacter, bool bIsPageCount = false) : m_strText(_T("")), m_bIsPageCount(bIsPageCount), m_pCharacter(pCharacter) { } ~CPageNumberC() { RELEASEOBJECT(m_pCharacter); } public: void Update(CGrapher* pGrapher, RectF& oRect, REAL& fDescent, CAlternate2::CAreaProperties& m_oAreaProperties) { if (!m_bIsPageCount) m_strText = pGrapher->m_DocumentManager->getPageIndexString(); else m_strText = pGrapher->m_DocumentManager->getPageCountString(); oRect = pGrapher->GetRectForString(m_strText, m_pCharacter); fDescent = pGrapher->GetDescent(m_pCharacter); SetOnBaseline(oRect, fDescent); } void CalculateRect(CAlternate2::CAreaProperties& m_oAreaProperties) { } public: void Draw(IAVSRenderer *pRenderer, CDocumentManager& documentManager, const RectF& oRect , const REAL& fDescent, const REAL &fCompleteness) { if (oRect.Width == 0) { return; } BSTR bstrText = m_strText.AllocSysString(); m_pCharacter->m_oAttributes.m_oFont.SetToRenderer(pRenderer); m_pCharacter->m_oAttributes.m_oBrush.SetToRenderer(pRenderer); m_pCharacter->m_oAttributes.m_oShadow.SetToRenderer(pRenderer); m_pCharacter->m_oAttributes.m_oEdge.SetToRenderer(pRenderer); const float fPtToMm = 25.4f / 72.0f; pRenderer->CommandDrawText(bstrText, oRect.X * fPtToMm, oRect.Y * fPtToMm, oRect.Width * fPtToMm, oRect.Height * fPtToMm, (oRect.Height - fDescent) * fPtToMm); SysFreeString(bstrText); } private: void SetOnBaseline(RectF& oRect, REAL& fDescent) { MoveTo(oRect, 0, fDescent - oRect.Height); if (m_pCharacter->m_oAttributes.m_nBaselineShift == 1) { MoveOn(oRect, -2 * fDescent); } else if (m_pCharacter->m_oAttributes.m_nBaselineShift == 2) { MoveOn(oRect, fDescent); } } void MoveTo(RectF& oRect, const REAL &fNewX, const REAL &fNewY) { oRect.X = fNewX; oRect.Y = fNewY; } void MoveOn(RectF& oRect, const REAL &fDeltaY) { oRect.Y += fDeltaY; } }; class CGroupC : public CContent { class GroupTransformer : public ContentTransformer { public: void applyTransformToChild(const RectF& parentRect, RectF& childRect , CAlternate2::CAreaProperties::GeometryProperties& geomPr) { PointF parentCenter(parentRect.X + parentRect.Width / 2 , parentRect.Y + parentRect.Height / 2); PointF childCenter(childRect.X + childRect.Width / 2 , childRect.Y + childRect.Height / 2); PointF childCenterRight(childCenter.X + childRect.Width , childCenter.Y); float oldDx = childCenterRight.X - childCenter.X; float oldDy = childCenterRight.Y - childCenter.Y; float oldR = sqrt(pow(oldDx, 2) + pow(oldDy, 2)); transformPoint(parentCenter, childCenter); transformPoint(parentCenter, childCenterRight); float newDx = childCenterRight.X - childCenter.X; float newDy = childCenterRight.Y - childCenter.Y; float newR = sqrt(pow(newDx, 2) + pow(newDy, 2)); float angle = 0; float r = oldR * newR; if (r != 0) { angle = acos((oldDx * newDx + oldDy * newDy) / (oldR * newR)); if (oldDx * newDy - oldDy * newDx < 0) angle *= -1; } if (getFlipXCoeff() == -1) geomPr.changeHFlip(); if (getFlipYCoeff() == -1) geomPr.changeVFlip(); childRect.X = childCenter.X - childRect.Width / 2; childRect.Y = childCenter.Y - childRect.Height / 2; geomPr.setRotationAngle(geomPr.getRotationAngle() + angle); } private: void transformPoint(const PointF& center, PointF& point) { float x = point.X - center.X; float y = point.Y - center.Y; float rotate = getRotate(); float cosA = cos(rotate); float sinA = sin(rotate); point.X = cosA * x - sinA * y + center.X; point.Y = sinA * x + cosA * y + center.Y; } } _transformer; public: CGroupC() { } ~CGroupC() { Clear(true); } public: void Clear(const bool& complete = false) { if (!complete) _Alternates.RemoveAll(); } byte FromXml(XmlUtils::CXmlNode& contentNode, CDocumentManager& documentManager) { XmlUtils::CXmlNode groupNode; if (contentNode.GetNode(_T("group"), groupNode)) { ReadArea(groupNode); ReadAlternates(groupNode, documentManager); } return 0; } void Update(CGrapher* grapher, RectF& rect, float& descent, CAlternate2::CAreaProperties& areaProperties) { int alternatesCount = (int) _Alternates.GetCount(); for (int i = 0; i < alternatesCount; ++i) { RectF relatedRect = RelatedRect(_Alternates[i], _AreaProperties[i], rect); _Alternates[i].Update(grapher, relatedRect, descent, areaProperties); } } void Draw(IAVSRenderer* renderer, CDocumentManager& documentManager, const RectF& rect , const float& descent, const float &completeness) { int alternatesCount = (int) _Alternates.GetCount(); for (int i = 0; i < alternatesCount; ++i) { RectF relatedRect = RelatedRect(_Alternates[i], _AreaProperties[i], rect); CAlternate2::CAreaProperties::GeometryProperties geomPr(_AreaProperties[i].getGeomPr()); _transformer.applyTransformToChild(rect, relatedRect, geomPr); _Alternates[i].Draw(renderer, documentManager, relatedRect, descent, geomPr, completeness); } } public: virtual void transform(const float& rotate, const bool& horzFlip, const bool& vertFlip) { _transformer.setTransform(rotate, horzFlip, vertFlip); } virtual void clearTransform() { _transformer.clearTransform(); } public: virtual void sendBeginCommand(IAVSRenderer2* renderer , const CAlternate2::CAreaProperties::GeometryProperties& geomPr) { IAVSRenderer* pRend = NULL; renderer->QueryInterface(__uuidof(IAVSRenderer), (void**)&pRend); pRend->BeginCommand(c_nShapeGroup); RELEASEINTERFACE(pRend); } virtual void sendEndCommand(IAVSRenderer2* renderer , const CAlternate2::CAreaProperties::GeometryProperties& geomPr) { IAVSRenderer* pRend = NULL; renderer->QueryInterface(__uuidof(IAVSRenderer), (void**)&pRend); pRend->EndCommand(c_nShapeGroup); RELEASEINTERFACE(pRend); } private: RectF _OriginArea; CArray _Alternates; CArray _AreaProperties; private: void ReadArea(XmlUtils::CXmlNode& groupNode) { XmlUtils::CXmlNode node; if (groupNode.GetNode(_T("originX"), node)) _OriginArea.X = XmlUtils::GetFloat(node.GetAttribute(_T("val"))); if (groupNode.GetNode(_T("originY"), node)) _OriginArea.Y = XmlUtils::GetFloat(node.GetAttribute(_T("val"))); if (groupNode.GetNode(_T("originWidth"), node)) _OriginArea.Width = XmlUtils::GetFloat(node.GetAttribute(_T("val"))); if (groupNode.GetNode(_T("originHeight"), node)) _OriginArea.Height = XmlUtils::GetFloat(node.GetAttribute(_T("val"))); } void ReadAlternates(XmlUtils::CXmlNode& groupNode, CDocumentManager& documentManager) { XmlUtils::CXmlNodes alternateNodes; if (groupNode.GetNodes(_T("fo:alternate-content"), alternateNodes)) { int alternatesCount = (int) alternateNodes.GetCount(); for (int i = 0; i < alternatesCount; ++i) { XmlUtils::CXmlNode alternateNode; alternateNodes.GetAt(i, alternateNode); _Alternates.Add(); _Alternates[_Alternates.GetCount() - 1].FromXml(alternateNode, documentManager); _AreaProperties.Add(); _AreaProperties[_AreaProperties.GetCount() - 1].FromXml(alternateNode); } } } private: RectF RelatedRect(CAlternate2::CAltContent& alternate, CAlternate2::CAreaProperties& areaProperty, const RectF& rect) { float xOriginToPt = rect.Width / _OriginArea.Width; float yOriginToPt = rect.Height / _OriginArea.Height; RectF relatedRect = areaProperty.AreaRectPt(); relatedRect.X = (relatedRect.X*20 - _OriginArea.X)*xOriginToPt + rect.X; relatedRect.Y = (relatedRect.Y*20 - _OriginArea.Y)*yOriginToPt + rect.Y; relatedRect.Width *= xOriginToPt*20; relatedRect.Height *= yOriginToPt*20; return relatedRect; } }; class CTextC { private: CFlow* _Flow; CArray _Lines; RectF _filledRect; bool _mustFit; public: CTextC() : _mustFit(false) { _Flow = NULL; } ~CTextC() { Clear(true); } public: void Clear(const bool& complete = false) { if (_Flow != NULL) RELEASEOBJECT(_Flow); int linesCount = (int) _Lines.GetCount(); for (int i = 0; i < linesCount; ++i) RELEASEOBJECT(_Lines[i]); if (!complete) _Lines.RemoveAll(); } byte FromXml(XmlUtils::CXmlNode& contentNode, CDocumentManager& documentManager) { Clear(); _Flow = new CFlow(); _Flow->FromXmlNode(contentNode, documentManager); _Flow->Static(true); readMustFit(contentNode); return 0; } void readMustFit(XmlUtils::CXmlNode& contentNode) { CString mustFit = contentNode.GetAttribute(_T("mustFit")); _mustFit = mustFit == _T("t"); } void Update(CGrapher* grapher, RectF& rect, float& descent, CAlternate2::CAreaProperties& areaProperties) { const float ptToMm = 25.4f / 72.0f; RectF rectMm(0, 0, rect.Width*ptToMm, rect.Height*ptToMm); CRegion region; region.FromRectMm(rectMm); CPage page; page.StartPrintingFlow(); _Flow->FillRegion(region, page, grapher); _filledRect = region.GetFilledRectPt(); page.GetLines(_Lines); page.FinishPrintingFlow(); } public: void MoveOn(const float& deltaX, const float& deltaY) { int linesCount = (int) _Lines.GetCount(); for (int i = 0; i < linesCount; ++i) _Lines[i]->MoveOn(deltaX, deltaY); } public: void Draw(IAVSRenderer* renderer, CDocumentManager& documentManager, const RectF& rect, const float& descent, const float& completeness) { clipOn(renderer, rect); MoveOn(rect.X, rect.Y); int linesCount = (int) _Lines.GetCount(); for (int i = 0; i < linesCount; ++i) _Lines[i]->Draw(renderer, documentManager, completeness); clipOff(renderer); } public: void fitRegionIfNecessary(CAlternate2::CAreaProperties& areaPr) { if (_mustFit) areaPr.SetAreaRect(_filledRect, true); } private: void clipOn(IAVSRenderer* renderer, const RectF& rectPt) { RectF rect = toMm(rectPt); renderer->BeginCommand(c_nClipType); renderer->BeginCommand(c_nPathType); renderer->PathCommandMoveTo(rect.X, rect.Y); renderer->PathCommandLineTo(rect.X + rect.Width, rect.Y); renderer->PathCommandLineTo(rect.X + rect.Width, rect.Y + rect.Height); renderer->PathCommandLineTo(rect.X, rect.Y + rect.Height); renderer->PathCommandClose(); renderer->EndCommand(c_nPathType); renderer->EndCommand(c_nClipType); renderer->PathCommandEnd(); } void clipOff(IAVSRenderer* renderer) { renderer->BeginCommand(c_nResetClipType); renderer->EndCommand(c_nResetClipType); } RectF toMm(const RectF& rect) { const float ptToMm = 25.4f / 72.0f; RectF rectMm(rect); rectMm.X *= ptToMm; rectMm.Y *= ptToMm; rectMm.Width *= ptToMm; rectMm.Height *= ptToMm; return rectMm; } }; // ### ### ### class CBlockInputParameters { private: float m_SpaceBefore; public: CBlockInputParameters() : m_SpaceBefore(0.0f) { } void Clear() { m_SpaceBefore = 0.0f; } public: float SpaceBefore() { return m_SpaceBefore; } void SpaceBefore(const float& spaceBefore) { m_SpaceBefore = spaceBefore; } }; class CCommonBlock { public: CCommonBlock() : m_InTable(false), m_InColumn(false) { } virtual ~CCommonBlock() { } public: virtual bool Empty() const { return true; } virtual bool Complete() const { return true; } virtual bool AtBeginning() const { return false; } virtual bool AtEnd() const { return true; } virtual bool UsualBlock() const { return true; } virtual byte KeepNext() const { return 0; } bool InTable() const { return m_InTable; } void InTable(const bool& inTable) { m_InTable = inTable; } void InColumn(const bool& inColumn) { m_InColumn = inColumn; } virtual bool transferToNextPage(CGrapher* grapher) { Renew(grapher); return true; } public: virtual void InputParams(CBlockInputParameters& inputParams, CDocumentManager& documentManager, const bool& update = false) { inputParams.Clear(); } virtual void estimateWidth(CGrapher* grapher, float& widthMin, float& widthScore) { widthMin = 0; widthScore = 0; } virtual void Renew(CGrapher* grapher, const bool& full = true) { } public: virtual bool FillRegion(CRegion &oRegion, CPage &oPage, const bool& bIsMustRenew, CGrapher* pGrapher) { return false; } protected: bool m_InTable; bool m_InColumn; protected: void addCommandToPage(CPage& page, SharedPtr& command , const bool& toLast = false) { if (!command.isEmpty() && !command->isAdded()) { page.addRendererCommand(command, toLast); command->setAdded(true); } } }; // ### ### class CBlock : public CCommonBlock, private CXmlAttributeReader { private: class CAlternates { private: CAtlArray m_Inlines; CAtlArray m_Anchors; float m_RegionOffset; bool m_Added; public: CAlternates() : m_Inlines(), m_Anchors(), m_Added(false), m_RegionOffset(0.0f) { } ~CAlternates() { Clear(); } void Clear() { m_Inlines.RemoveAll(); for (int index = 0; index < (int)m_Anchors.GetCount(); ++index) RELEASEOBJECT((m_Anchors[index])); m_Anchors.RemoveAll(); m_Added = false; m_RegionOffset = 0.0f; } public: CAtlArray& Inlines() { return m_Inlines; } CAtlArray& Anchors() { return m_Anchors; } public: bool HasInlines() { return (m_Inlines.GetCount() != 0); } bool HasAnchors() { return (m_Anchors.GetCount() != 0); } bool isOnlyOneLetter() const { if (m_Anchors.GetCount() != 1) return false; return m_Anchors[0]->isLetter(); } bool Added() const { return m_Added; } public: void Add(CAlternate2* alternate) { if (alternate->Inline()) m_Inlines.Add(alternate); else m_Anchors.Add(alternate); } void Update(CGrapher* grapher) { for (int index = 0; index < (int)m_Inlines.GetCount(); ++index) m_Inlines[index]->UpdateContent(grapher); for (int index = 0; index < (int)m_Anchors.GetCount(); ++index) m_Anchors[index]->UpdateContent(grapher); } bool Place(CPage& page, CRegion region, const CBlockAttributes* blockAttrs , const RectF& line, const int& position = -1) { if (!HasAnchors()) return true; if (m_RegionOffset > 0) region.TruncateLeftPt(m_RegionOffset); else if (blockAttrs->m_fStartIndent != 0) region.TruncateLeftPt(blockAttrs->m_fStartIndent); bool fullRelate = true; for (int index = 0; index < (int)m_Anchors.GetCount(); ++index) { m_Anchors[index]->Related(false); if (!m_Anchors[index]->Placed()) { int anchorPosition = m_Anchors[index]->InlinePosition(); if ((position < 0) || (anchorPosition <= position)) { m_Anchors[index]->relate(page, region, line); m_Anchors[index]->Related(true); } } } page.AddAnchorContent(m_Anchors); return fullRelate; } void Renew() { m_Added = false; for (int index = 0; index < (int)m_Anchors.GetCount(); ++index) m_Anchors[index]->Placed(false); } void RegionSettings(CPage& page, CRegion& region) { CAreaManager* area = page.GetAreaManager(); RectF firstLine = region.GetRectPt(); firstLine.Height = 2.0; CArray rects; area->GetArea(firstLine, rects); if (rects.GetCount() != 0) { m_RegionOffset = rects[0].X - firstLine.X; } } }; class CItems { public: enum ENumProcess; private: enum EPartState { EmptyPart = 0, SymbolsInPart, WordInPart }; class CBlockState { private: ENumProcess m_NumProcess; public: CBlockState() : m_NumProcess(NumNone) { } public: void Renew() { m_NumProcess = NumProcessed; } public: bool NumProcess(const ENumProcess& numProcess) { if (m_NumProcess == NumProcessed) return true; if ((m_NumProcess == NumAddedWithTab) && (numProcess == NumNone)) { m_NumProcess = NumProcessed; return false; } if (numProcess == NumProcessed) { m_NumProcess = NumProcessed; return true; } if ((m_NumProcess == NumNone) && (numProcess == NumAdded)) { m_NumProcess = NumAdded; return true; } if ((m_NumProcess == NumAdded) && (numProcess == NumAddedWithTab)) { m_NumProcess = NumAddedWithTab; return true; } return true; } }; public: enum EBreakType { NoneBreak = 0, LineBreak,PageBreak, ColumnBreak }; enum ENumProcess { NumNone = 0, NumAdded, NumAddedWithTab, NumProcessed }; struct SPartProperties { bool m_BreakBefore; bool m_HeightChanged; bool m_WrapBySymbol; bool m_Force; bool m_Single; int _items; bool m_RuptureIfSingle; EPartState m_State; bool m_Tab; bool _limitTabs; EBreakType m_Break; bool _isPpt; bool _ignoreWidthLimit; bool _firstLine; SPartProperties() : m_BreakBefore(false), m_HeightChanged(false), m_WrapBySymbol(false), m_Force(false), m_Single(false), _items(0), m_RuptureIfSingle(false), m_State(EmptyPart), m_Tab(false), _limitTabs(false), m_Break(NoneBreak), _isPpt(false), _ignoreWidthLimit(false), _firstLine(false) { } }; private: CString m_Text; CArray m_Items; CArray m_Characters; CBlockState m_BlockState; int m_CurrentItem; int m_CurrentItemFill; std::stack m_CurrentItemsSaved; bool m_Prepared; // ################## friend class CTextMeasurer; private: void Text(const CString& text) { m_Text = text; } CString& Text() { return m_Text; } CArray& Items() { return m_Items; } CArray& Characters() { return m_Characters; } void AddText(const CString& text) { m_Text += text; } void AddCharacter(CCharacter* character) { m_Characters.Add(character); } CCharacter* GetCharacter(const int& index) { return m_Characters[index]; } int CountCharacters() { return (int)m_Characters.GetCount(); } // ################## private: bool RuptureAndAddToPart(CItem* item, RectF& area, CArray& items, SPartProperties& properties, CGrapher* grapher) { CItem* newItem = NULL; if (item->CanRupture()) newItem = item->Rupture(area.Width, grapher, properties.m_WrapBySymbol); if ((newItem == NULL) && properties.m_WrapBySymbol) newItem = item->Rupture(area.Width, grapher, true); if (newItem) { m_Items.InsertAt(m_CurrentItem, newItem); AddToPart(newItem, area, items, properties); properties.m_State = WordInPart; if (newItem->GetType() != Space) return true; else return false; } else if (properties.m_Single) { if (properties.m_RuptureIfSingle && item->CanRupture(grapher, area.Width)) { newItem = item->Rupture(area.Width, grapher, true); if (newItem != NULL) { m_Items.InsertAt(m_CurrentItem, newItem); AddToPart(newItem, area, items, properties); properties.m_State = WordInPart; return (newItem->GetType() != Space); } } else if (properties.m_RuptureIfSingle && properties._items != 0) { return false; } else if (properties.m_Force || item->GetType() == Alternate || item->IsOneSymbol()) { AddToPart(item, area, items, properties); properties.m_State = WordInPart; return true; } else if (properties.m_RuptureIfSingle) { newItem = item->Rupture(area.Width, grapher, true, true); if (newItem != NULL) { m_Items.InsertAt(m_CurrentItem, newItem); AddToPart(newItem, area, items, properties); properties.m_State = WordInPart; return (newItem->GetType() != Space); } } } return false; } void AddToPart(CItem* item, RectF& area, CArray& items, SPartProperties& properties) { assert(!properties.m_HeightChanged); if (area.Height == 0) { AddToPart(item, area, items); ++properties._items; } else { float height = item->GetHeightPt(); if (height <= area.Height) { ++properties._items; AddToPart(item, area, items); } else { area.Height = height; properties.m_HeightChanged = true; } } } void AddToPart(CItem* item, RectF& area, CArray& items) { float width = item->GetWidthPt(); area.Width -= width; area.X += width; items.Add(item); ++m_CurrentItem; } void RemoveLastItemFromPart(RectF& area, CArray& items) { int lastItem = (int)items.GetCount() - 1; float width = items[lastItem]->GetWidthPt(); area.Width += width; area.X -= width; items.RemoveAt(lastItem); --m_CurrentItem; } void UpdatePartState(const CItemType& itemType, SPartProperties& properties, CArray& items) { if (!properties.m_Single) return; if (itemType == Alternate) { properties.m_State = WordInPart; properties.m_Single = false; return; } else if (itemType == LineEnd) { properties.m_State = WordInPart; properties.m_Single = false; return; } if (properties.m_State == EmptyPart) { if (itemType == Symbols) properties.m_State = SymbolsInPart; } else if (properties.m_State == SymbolsInPart) { if (itemType == Space) { properties.m_State = WordInPart; properties.m_Single = false; } } } bool ProcessItem(CItem* item, RectF& area, SPartProperties& properties, CGrapher* grapher) { bool mustBreak = false; CItemType itemType = item->GetType(); if (itemType == TabStop) { CTabParams tab = grapher->m_DocumentManager->GetTabSize(area.X); ((CTabStop*)item)->GetRect().Width = tab.GetPosition(); ((CTabStop*)item)->m_bLeader = tab.GetLeader(); ((CTabStop*)item)->m_bType = tab.GetType(); float width = item->GetWidthPt(); if (width == 0) mustBreak = true; if (width > area.Width) properties.m_Tab = true; } else if (itemType == LineEnd) { if (((CLineEnd*)item)->GetCharacter()->m_nAdditionalParam == 1) properties.m_Break = PageBreak; else if (((CLineEnd*)item)->GetCharacter()->m_nAdditionalParam == 2) properties.m_Break = ColumnBreak; else properties.m_Break = LineBreak; } return mustBreak; } bool CheckBreak(CItem* item, RectF& area, CArray& items, SPartProperties& properties) { if (properties.m_Break == NoneBreak) return false; else if (properties.m_Break == LineBreak) { if (properties._isPpt) AddToPart(item, area, items, properties); else if (items.GetCount() == 0) { //AddToPart(item, area, items, properties); properties.m_Break = NoneBreak; return false; } } else AddToPart(item, area, items, properties); properties.m_State = WordInPart; return true; } void RuptureOrRemoveLastSymbolItemsInPart(CItem* item, RectF& area, CArray& items, SPartProperties& properties, CGrapher* grapher) { CItemType itemType = item->GetType(); if (itemType != Space && itemType != Alternate) { int lastItem = (int)items.GetCount() - 1; int lastItemInPart = lastItem; while (lastItemInPart >= 0) { CItem* currItem = items[lastItemInPart]; itemType = currItem->GetType(); if (itemType != Space && itemType != Alternate && itemType != TabStop && itemType != LineEnd) --lastItemInPart; else break; } if (lastItemInPart > 0) for (int i = 0; i < lastItem - lastItemInPart; ++i) RemoveLastItemFromPart(area, items); } else { while (!AtEnd()) { CItem* currItem = m_Items[m_CurrentItem]; itemType = currItem->GetType(); if (itemType == Space) ++m_CurrentItem; else break; } } } bool ProcessIfRightTab(CItem* itemTab, RectF& area, CArray& items, SPartProperties& properties, CGrapher* grapher) { CItemType itemType = itemTab->GetType(); if (itemType == TabStop) { if (((CTabStop*)itemTab)->m_bType != 1) return false; RectF areaTmp = area; float tabWidth = ((CTabStop*)itemTab)->GetRect().Width; areaTmp.Width = tabWidth; ((CTabStop*)itemTab)->GetRect().Width = 0; AddToPart(itemTab, area, items, properties); while (!AtEnd()) { CItem* item = m_Items[m_CurrentItem]; float width = item->GetWidthPt(); if (width < areaTmp.Width) { AddToPart(item, areaTmp, items, properties); if (properties.m_HeightChanged) break; } else break; } ((CTabStop*)itemTab)->GetRect().Width = areaTmp.Width; area.X += tabWidth; area.Width -= tabWidth; area.Height = areaTmp.Height; return true; } return false; } public: CItems() : m_Text(_T("")), m_Items(), m_Characters(), m_BlockState(), m_CurrentItem(0), m_CurrentItemFill(0), m_CurrentItemsSaved(), m_IgnoreNegativeWidth(false), m_Prepared(false) { } ~CItems() { Clear(); } void Clear() { m_Text = _T(""); for (int index = 0; index < (int)m_Items.GetCount(); ++index) RELEASEOBJECT(m_Items[index]); m_Items.RemoveAll(); for (int index = 0; index < (int)m_Characters.GetCount(); ++index) RELEASEOBJECT(m_Characters[index]); m_Characters.RemoveAll(); m_CurrentItem = 0; m_CurrentItemFill = 0; assert(m_CurrentItemsSaved.empty()); m_IgnoreNegativeWidth = false; m_Prepared = false; } public: bool m_IgnoreNegativeWidth; public: bool IsEmpty() const { return ((m_Characters.GetCount() == 0) || (m_Text == _T(""))); } bool IsReady() const { return (m_Items.GetCount() != 0); } bool AtBeginning() const { return (m_CurrentItem == 0); } bool AtEnd() const { return m_CurrentItem >= (int)m_Items.GetCount() && (IsEmpty() || m_Prepared); } bool Prepared() const { return m_Prepared; } void InlineAdded() { m_BlockState.NumProcess(NumProcessed); } public: void CurrentItem(const int& currentItem) { if (!Prepared()) assert(Prepared()); m_CurrentItem = currentItem; } int CurrentItem() { assert(Prepared()); return m_CurrentItem; } int Count() { assert(Prepared()); return (int)m_Items.GetCount(); } CItem* operator[](const int& index) { assert(Prepared()); return m_Items[index]; } public: void SaveCurrentItem() { assert(Prepared()); m_CurrentItemsSaved.push(m_CurrentItem); } void RemoveCurrentItem() { assert(Prepared()); assert(!m_CurrentItemsSaved.empty()); m_CurrentItemsSaved.pop(); } void RestoreCurrentItem() { assert(Prepared()); assert(!m_CurrentItemsSaved.empty()); m_CurrentItem = m_CurrentItemsSaved.top(); m_CurrentItemsSaved.pop(); } bool EmptySaves() { return m_CurrentItemsSaved.empty(); } void SaveCurrentItemFill() { m_CurrentItemFill = m_CurrentItem; } void Renew(const bool& full = true) { if (!Prepared()) return; //assert(Prepared()); for (int index = 0; index < Count(); ++index) { m_Items[index]->RestoreRect(); m_Items[index]->SetOnBaseline(); } if (full) { m_CurrentItem = 0; m_CurrentItemFill = 0; m_BlockState.Renew(); } else m_CurrentItem = m_CurrentItemFill; } public: void AddItem(const CString& text, CCharacter* character, const ENumProcess& numProcess = NumProcessed) { assert(!Prepared()); CString text2 = text; character->Transform(text2); character->CheckFontRange(text2); if (m_BlockState.NumProcess(numProcess)) { m_Text += text2; m_Characters.Add(character); } else { m_Text = text2 + m_Text; m_Characters.InsertAt(0, character); } } void Prepare(CGrapher* grapher, CBlockAttributes* blockAttributes, CAtlArray& inlines, CAtlArray& anchors, CAtlArray& footnotes) { if (Prepared()) return; grapher->m_DocumentManager->m_ItemManager.PrepareItems(m_Text, blockAttributes, m_Characters, inlines, anchors, footnotes, m_Items, grapher); m_Prepared = true; } public: void FillArea(RectF& area, CArray& items, SPartProperties& properties, CGrapher* grapher) { bool first = AtBeginning(); assert(!properties.m_HeightChanged); properties.m_State = EmptyPart; while (!AtEnd()) { CItem* item = m_Items[m_CurrentItem]; if (ProcessItem(item, area, properties, grapher)) break; if (ProcessIfRightTab(item, area, items, properties, grapher)) { if (properties.m_HeightChanged) break; continue; } if (CheckBreak(item, area, items, properties)) break; float width = item->GetWidthPt(); if (m_IgnoreNegativeWidth) { m_IgnoreNegativeWidth = false; area.Width = width; } if (width <= area.Width || properties.m_Tab || properties._ignoreWidthLimit) { CItemType itemType = item->GetType(); UpdatePartState(itemType, properties, items); AddToPart(item, area, items, properties); if (properties.m_HeightChanged) break; } else { if (!RuptureAndAddToPart(item, area, items, properties, grapher)) RuptureOrRemoveLastSymbolItemsInPart(item, area, items, properties, grapher); break; } } if (!first && properties.m_State == EmptyPart) items.RemoveAll(); } }; class State { public: static enum EStopPrintReason { AnyReason = 0, NotEnoughWidthReason }; public: EStopPrintReason _stopPrintReason; bool _transferedToNextPage; public: State() : _stopPrintReason(AnyReason), _transferedToNextPage(false) { } public: void reset() { _stopPrintReason = AnyReason; _transferedToNextPage = false; } }; private: class CComplexFieldChar { private: class CParam { private: CString m_strName; CString m_strValue; public: CParam(const CString& strName = _T(""), const CString& strValue = _T("")) : m_strName(strName), m_strValue(strValue) { } CParam(const CParam& oSrc) { m_strName = oSrc.m_strName; m_strValue = oSrc.m_strValue; } public: CString& Name() { return m_strName; } CString& Value() { return m_strValue; } }; class CCode { private: CString m_strName; CArray m_arrParams; bool m_bIsContent; public: CCode(const CString& strName, const bool& bIsContent) : m_strName(strName), m_arrParams(), m_bIsContent(bIsContent) { } CCode(const CCode& oSrc) { m_strName = oSrc.m_strName; m_arrParams.Copy(oSrc.m_arrParams); m_bIsContent = oSrc.m_bIsContent; } public: CString& Name() { return m_strName; } void AddParam(const CString& strName, const CString& strValue = _T("")) { CParam oParam(strName, strValue); m_arrParams.Add(oParam); } int FindParam(const CString& strName) { int iParamsCount = (int)m_arrParams.GetCount(); for (int iIndex = 0; iIndex < iParamsCount; ++iIndex) if (m_arrParams[iIndex].Name() == strName) return iIndex; return -1; } void SetParam(const int& iIndex, const CString& strValue) { if (iIndex < 0) AddParam(_T("input"), strValue); else if (iIndex < (int)m_arrParams.GetCount()) m_arrParams[iIndex].Value() = strValue; } CString GetParam(const int& iIndex) { if ((iIndex >= 0) && (iIndex < (int)m_arrParams.GetCount())) return m_arrParams[iIndex].Value(); else return _T(""); } bool IsOnlyString() { return !m_bIsContent; } }; class CDateTime { private: SYSTEMTIME m_oSystemTime; public: CDateTime() { GetSystemTime(&m_oSystemTime); } public: CString GetDateAndTime(const CString& strFormat) { CString strDateTime = _T(" "); DWORD nLength = GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL, strFormat, NULL, 0); if (nLength > 0) { TCHAR *pstrDateTime = new TCHAR[nLength]; GetDateFormat(LOCALE_USER_DEFAULT, 0, &m_oSystemTime, strFormat, pstrDateTime, nLength); strDateTime = CString(pstrDateTime); RELEASEARRAYOBJECTS(pstrDateTime); } return strDateTime; } }; private: CArray m_arrCodes; bool m_isInTOC; public: byte m_nState; public: CString m_strCommand; CString m_strResult; int m_iCodeIndex; CAtlArray m_arrCommands; CCharacter *m_pCharacter; public: CComplexFieldChar() : m_arrCodes(), m_nState(0), m_strCommand(_T("")), m_strResult(_T("")), m_iCodeIndex(-1), m_pCharacter(NULL) { InitCodes(); } ~CComplexFieldChar() { if (m_pCharacter != NULL) delete m_pCharacter; } public: bool ProcessFieldCharNode(XmlUtils::CXmlNode& oFieldCharNode) { CString strType = oFieldCharNode.GetAttribute(_T("type")); if (strType == _T("begin")) { Begin(); } else if (strType == _T("separate")) { Separate(); /*m_arrCommands.Add(m_strCommand); RecountPositionInTOC();*/ } else if (strType == _T("end")) { End(); /*size_t nCount = m_arrCommands.GetCount(); if (nCount > 0) { m_arrCommands.RemoveAt(nCount - 1); } m_strCommand = _T(""); RecountPositionInTOC();*/ } return (m_nState == 0); } void ProcessFieldChar() { if (IsSeparate()) { int spaces = 0; for (; spaces < m_strCommand.GetLength(); ++spaces) if (m_strCommand[spaces] != _T(' ')) break; m_arrCommands.Add(m_strCommand.Right(m_strCommand.GetLength() - spaces)); RecountPositionInTOC(); } else if (IsEnd()) { size_t nCount = m_arrCommands.GetCount(); if (nCount > 0) { m_arrCommands.RemoveAt(nCount - 1); } m_strCommand = _T(""); RecountPositionInTOC(); //Parse(); } } void RecountPositionInTOC() { m_isInTOC = IsIn(_T("TOC")); } bool IsIn(CString nameCommand) { size_t nCount = m_arrCommands.GetCount(); for (size_t i = 0; i < nCount; ++i) { if (m_arrCommands[i].Find(nameCommand) != -1) return true; } return false; } bool LastIs(CString nameCommand) { size_t nCount = m_arrCommands.GetCount(); if (nCount == 0) return false; return (m_arrCommands[nCount - 1].Find(nameCommand) == 0); } bool IsInTOC() { return m_isInTOC; } void ProcessInstructionText(XmlUtils::CXmlNode& oInstructionTextNode) { AddText(oInstructionTextNode.GetTextExt()); } bool IsInProcess() { return (m_nState != 0); } bool IsInCommandProcess() { return (m_nState == 1); } bool IsInContentProcess() { return (m_nState == 2); } void InCommandProcess() { m_nState = 1; } void InContentProcess() { m_nState = 2; } bool CanFillContent() { return !(IsIn(_T("PAGE")) && !IsIn(_T("PAGEREF"))); } bool IsOnlyString() { if (m_iCodeIndex == -1) return true; else return m_arrCodes[m_iCodeIndex].IsOnlyString(); } CContent* GetContent(CCharacter* pCharacter) { if (m_iCodeIndex == 0) return CreatePage(pCharacter); return NULL; } CString GetString(CCharacter* pCharacter) { if (m_iCodeIndex == 1) return CreateMacrobutton(pCharacter); else if (m_iCodeIndex == 2) return CreateHyperlink(pCharacter); else if (m_iCodeIndex == 3) return CreateDate(pCharacter); pCharacter->m_lCount = 1; return _T(" "); } void Interrupt() { m_strCommand = _T(""); m_strResult = _T(""); End(); } private: void Begin() { m_nState = 1; } bool IsBegin() { return (m_nState == 1); } void Separate() { m_nState = 2; } bool IsSeparate() { return (m_nState == 2); } void End() { m_nState = 0; } bool IsEnd() { return (m_nState == 0); } private: void AddText(const CString& strText) { if (IsBegin()) m_strCommand += strText; else if (IsSeparate()) m_strResult += strText; } void Parse() { CString strCode = _T(""); CString strParams = _T(""); DetachCodeFromParams(m_strCommand, strCode, strParams); m_iCodeIndex = FindCode(strCode); if (m_iCodeIndex != -1) { ParseParams(strParams); } } void ParseParams(const CString& strParams) { int iParamIndex = -1; int iStartPos = 0; bool bNameNotValue = true; bool bCopyTheRest = false; int iLength = strParams.GetLength(); while (iStartPos < iLength) { if (bNameNotValue) { int iPrevStartPos = iStartPos; iStartPos = FindFirstNotSpace(strParams, iStartPos); int iFinishPos = strParams.Find(_T(' '), iStartPos); CString strName = strParams.Mid(iStartPos, iFinishPos - iStartPos); iParamIndex = m_arrCodes[m_iCodeIndex].FindParam(strName); if (iParamIndex != -1) { iStartPos = iFinishPos; bNameNotValue = false; } else { iStartPos = iPrevStartPos; bNameNotValue = false; bCopyTheRest = true; } } else { if (bCopyTheRest) { CString strValue = strParams.Mid(iStartPos, iLength - iStartPos); m_arrCodes[m_iCodeIndex].SetParam(iParamIndex, strValue); break; } else { for (; iStartPos < iLength; ++iStartPos) { if (strParams[iStartPos] != _T(' ')) break; } int iFinishPos = iStartPos; if (strParams[iStartPos] == _T('"')) { if (iStartPos == iLength - 1) { bCopyTheRest = true; continue; } CString strValue; iFinishPos = strParams.Find(_T('"'), ++iStartPos); if (iFinishPos == 0) { --iStartPos; iFinishPos = iLength; strValue = strParams.Mid(iStartPos, iFinishPos - iStartPos); } else { strValue = strParams.Mid(iStartPos, iFinishPos - iStartPos); ++iFinishPos; } m_arrCodes[m_iCodeIndex].SetParam(iParamIndex, strValue); iStartPos = iFinishPos; } else { for (; iFinishPos < iLength; ++iFinishPos) { if (strParams[iFinishPos] == _T(' ')) break; } CString strValue = strParams.Mid(iStartPos, iFinishPos - iStartPos); m_arrCodes[m_iCodeIndex].SetParam(iParamIndex, strValue); iStartPos = iFinishPos; } bNameNotValue = true; } } } } bool IsParsed() { return (m_nState != 0); } private: int FindFirstNotSpace(const CString& strText, int iStartIndex = 0) { int iIndex = iStartIndex; for (; iIndex < strText.GetLength(); ++iIndex) if (strText[iIndex] != _T(' ')) break; return iIndex; } void DetachCodeFromParams(CString strText, CString& strCode, CString& strParams) { int iCodeStartPosition = FindFirstNotSpace(strText); int iFirstAfterCodePosition = strText.Find(_T(" "), iCodeStartPosition); bool bCodeWithParams = true; if (iFirstAfterCodePosition == -1) { iFirstAfterCodePosition = strText.GetLength(); bCodeWithParams = false; } strCode = strText.Mid(iCodeStartPosition, iFirstAfterCodePosition - iCodeStartPosition); if (bCodeWithParams) { int iParamsStartPosition = FindFirstNotSpace(strText, iFirstAfterCodePosition); strParams = strText.Mid(iParamsStartPosition, strText.GetLength() - iParamsStartPosition); } else strParams = _T(""); } int FindCode(const CString& strCode) { int iCodesCount = (int)m_arrCodes.GetCount(); for (int iIndex = 0; iIndex < iCodesCount; ++iIndex) if (m_arrCodes[iIndex].Name() == strCode) return iIndex; return -1; } private: void InitCodes() { m_arrCodes.Add(Page()); m_arrCodes.Add(Macrobutton()); m_arrCodes.Add(Hyperlink()); m_arrCodes.Add(Date()); } CCode Page() { CCode oPage(_T("PAGE"), true); return oPage; } CContent* CreatePage(CCharacter* pCharacter) { CPageNumberC* pPageNumberC = new CPageNumberC(pCharacter); return pPageNumberC; } CCode Macrobutton() { CCode oMacrobutton(_T("MACROBUTTON"), false); oMacrobutton.AddParam(_T("NoMacro")); return oMacrobutton; } CString CreateMacrobutton(CCharacter* pCharacter) { CString strText = _T(""); int iParamNoMacroIndex = m_arrCodes[m_iCodeIndex].FindParam(_T("NoMacro")); if (iParamNoMacroIndex != -1) { strText += m_arrCodes[m_iCodeIndex].GetParam(iParamNoMacroIndex); } int iInputParamIndex = m_arrCodes[m_iCodeIndex].FindParam(_T("input")); if (iInputParamIndex != -1) { strText += m_arrCodes[m_iCodeIndex].GetParam(iInputParamIndex); } pCharacter->m_lCount = strText.GetLength(); return strText; } CCode Hyperlink() { CCode oHyperlink(_T("HYPERLINK"), false); return oHyperlink; } CString CreateHyperlink(CCharacter* pCharacter) { CString strText = _T(""); int iInputParamIndex = m_arrCodes[m_iCodeIndex].FindParam(_T("input")); if (iInputParamIndex != -1) { strText = m_arrCodes[m_iCodeIndex].GetParam(iInputParamIndex); } pCharacter->m_oLink.nMode = 2; pCharacter->m_oLink.strTarget = strText; pCharacter->m_oLink.strTarget.Remove('"'); pCharacter->m_lCount = m_strResult.GetLength(); return m_strResult; } CCode Date() { CCode oDate(_T("DATE"), false); oDate.AddParam(_T("\\@")); return oDate; } CString CreateDate(CCharacter* pCharacter) { CDateTime oDateTime; CString strFormat; int iParamFormatIndex = m_arrCodes[m_iCodeIndex].FindParam(_T("\\@")); if (iParamFormatIndex != -1) { strFormat = m_arrCodes[m_iCodeIndex].GetParam(iParamFormatIndex); } CString strDateTime = oDateTime.GetDateAndTime(strFormat); pCharacter->m_lCount = strDateTime.GetLength(); return strDateTime; } }; CComplexFieldChar m_oComplexFieldChar; byte m_nCharState; public: CBlockAttributes* m_pBlockAttributes; CAlternates m_Alternates; CItems m_Items; State _state; CAtlArray m_arrFootnotes; int m_iFootnoteIndex; CString m_strID; bool m_mergeBordersWithNextBlock; bool m_mergeBordersWithPrevBlock; bool m_removeSpaceBefore; bool m_removeSpaceAfter; bool m_IgnoreAnchors; private: BlockPr _blockPr; RCommand _blockStartCommand; RCommand _blockEndCommand; RCommand pageBreakCommand; public: CBlock() : CCommonBlock(), m_pBlockAttributes(NULL), m_Alternates(), m_Items(), m_arrFootnotes(), m_iFootnoteIndex(0), m_strID(_T("")), m_oComplexFieldChar(), m_nCharState(0), m_IgnoreAnchors(false) { m_mergeBordersWithNextBlock = false; m_mergeBordersWithPrevBlock = false; m_removeSpaceBefore = false; m_removeSpaceAfter = false; } ~CBlock() { Clear(); } void Clear() { RELEASEOBJECT(m_pBlockAttributes); m_Items.Clear(); m_Alternates.Clear(); m_arrFootnotes.RemoveAll(); m_iFootnoteIndex = 0; m_strID = _T(""); m_nCharState = 0; m_mergeBordersWithNextBlock = false; m_mergeBordersWithPrevBlock = false; m_removeSpaceBefore = false; m_removeSpaceAfter = false; m_IgnoreAnchors = false; } public: void FromXmlNode(XmlUtils::CXmlNode& oXmlNode, CDocumentManager& documentManager, CBlockAttributes* pBlockAttributes = NULL, CCharacter* pCharacter = NULL) { Clear(); documentManager.BlockCreated(); readHeadingLevel(oXmlNode); LoadID(oXmlNode); if (pBlockAttributes == NULL) m_pBlockAttributes = new CBlockAttributes(); else m_pBlockAttributes = pBlockAttributes; m_pBlockAttributes->FromXmlNode2(oXmlNode); CCharacter *pDefaultCharacter = NULL; if (pCharacter == NULL) pDefaultCharacter = new CCharacter(); else { pDefaultCharacter = new CCharacter(); *pDefaultCharacter = *pCharacter; } m_oComplexFieldChar.RecountPositionInTOC(); pDefaultCharacter->FromXmlNode2(oXmlNode); ProcessNodesWithReader(oXmlNode, pDefaultCharacter, documentManager); RELEASEOBJECT(pDefaultCharacter); initCommands(); } void FromXmlNode(XmlUtils::CXmlNode& oXmlNode, CDocumentManager& documentManager, const bool& bIsFirst, bool& inCommandField, CAtlArray& curCommands) { if (inCommandField == true) m_oComplexFieldChar.InCommandProcess(); m_oComplexFieldChar.m_arrCommands.Copy(curCommands); m_oComplexFieldChar.RecountPositionInTOC(); FromXmlNode(oXmlNode, documentManager); if (bIsFirst) { m_pBlockAttributes->m_nBreakBeforeType = 0; } if (m_oComplexFieldChar.IsInCommandProcess()) inCommandField = true; else inCommandField = false; curCommands.Copy(m_oComplexFieldChar.m_arrCommands); } void FromString(const CString& text, CGrapher* grapher, const NSStructures::CFont& font, const NSStructures::CBrush& brush, const NSStructures::CFormat& format) { int length = text.GetLength(); m_pBlockAttributes = new CBlockAttributes(); m_pBlockAttributes->m_lCount = length; m_pBlockAttributes->m_nTextAlignment = format.StringAlignmentHorizontal; CCharacter* character = new CCharacter(); character->m_lCount = length; character->m_oAttributes.m_oFont.FromFont(font); character->m_oAttributes.m_oBrush.FromBrush(brush); m_Items.AddItem(text, character); PrepareItems(grapher); } public: inline bool Empty() const { return m_Items.IsEmpty(); } inline bool Complete() const { return AtEnd() || (Empty() && m_Alternates.Added()) || (_state._stopPrintReason == State::NotEnoughWidthReason); } inline bool AtBeginning() const { return m_Items.AtBeginning(); } inline bool AtEnd() const { return m_Items.AtEnd(); } inline bool UsualBlock() const { return true; } inline byte KeepNext() const { return m_pBlockAttributes->m_nKeepNext; } inline void IgnoreAnchors(const bool& ignoreAnchors) { m_IgnoreAnchors = ignoreAnchors; } void estimateWidth(CGrapher* pGrapher, float& widthMin, float& widthScore) { if (!m_Items.IsReady()) PrepareItems(pGrapher); float widthMinEstimate = 0; float widthMinAddition = 0; float indentEstimate = 0; float& startIndent = m_pBlockAttributes->m_fStartIndent; float& endIndent = m_pBlockAttributes->m_fEndIndent; float& textIndent = m_pBlockAttributes->m_fTextIndent; if (startIndent > 0) { indentEstimate += startIndent; widthMinAddition += startIndent; } if (endIndent > 0) { indentEstimate += endIndent; widthMinAddition += endIndent; } widthScore = 0; if (textIndent > 0) { widthMinEstimate = textIndent; widthScore += textIndent; } int itemsCount = (int) m_Items.Count(); for (int i = 0; i < itemsCount; ++i) { float itemWidth = m_Items[i]->GetRect().Width; if (itemWidth > widthMinEstimate) widthMinEstimate = itemWidth; widthScore += itemWidth; } widthMin = widthMinEstimate + widthMinAddition; widthScore += indentEstimate; } inline bool transferToNextPage(CGrapher* grapher) { if (!_state._transferedToNextPage) { Renew(grapher); _state._transferedToNextPage = true; return true; } else return false; } public: void InputParams(CBlockInputParameters& inputParams, CDocumentManager& documentManager, const bool& update = false) { if (!documentManager.UseHtmlSpacing()) return; if (update) { m_pBlockAttributes->m_nSpaceBefore += inputParams.SpaceBefore(); inputParams.SpaceBefore(m_pBlockAttributes->m_nSpaceAfter); } else { // TODO: ppt - if (inputParams.SpaceBefore() >= m_pBlockAttributes->m_nSpaceBefore) { inputParams.SpaceBefore(0.0f); m_pBlockAttributes->m_nSpaceBefore = 0.0f; } else { m_pBlockAttributes->m_nSpaceBefore -= inputParams.SpaceBefore(); } } } void Renew(CGrapher* grapher, const bool& full = true) { m_Alternates.Renew(); m_Items.Renew(full); for (size_t nIndex = 0; nIndex < m_arrFootnotes.GetCount(); ++nIndex) m_arrFootnotes[nIndex]->Static(true); m_iFootnoteIndex = 0; m_Alternates.Update(grapher); if (full && m_pBlockAttributes->m_nBreakBeforeType < 0) m_pBlockAttributes->m_nBreakBeforeType *= -1; initCommands(); } public: bool FillRegion(CRegion &oRegion, CPage &oPage, const bool& bIsMustRenew, CGrapher* pGrapher) { CRegion origRegion = oRegion; RectF rectBefore = oRegion.GetFilledRectPt(); if (m_removeSpaceBefore && m_pBlockAttributes->m_contextualSpacing == _T("true")) if (m_removeSpaceBefore) m_pBlockAttributes->m_nSpaceBefore = 0; if (m_removeSpaceAfter && m_pBlockAttributes->m_contextualSpacing == _T("true")) m_pBlockAttributes->m_nSpaceAfter = 0; if (CheckBreakBefore(oRegion, oPage)) return true; if (bIsMustRenew) m_Alternates.Renew(); PrepareItems(pGrapher); m_Alternates.Update(pGrapher); if (AtBeginning()) m_Alternates.RegionSettings(oPage, oRegion); oPage.StartBlock(); if (m_Items.Prepared()) addAnchors(oPage, origRegion, m_Items.CurrentItem()); else addAnchors(oPage, origRegion, 0); if (m_Items.IsEmpty() && !m_Alternates.HasInlines()) { return m_Alternates.HasAnchors(); } if (bIsMustRenew && m_Items.Prepared()) Renew(pGrapher); SetTabStops(oRegion, *pGrapher->m_DocumentManager); if (m_InColumn) m_Items.SaveCurrentItemFill(); bool atBeginning = m_Items.AtBeginning(); bool disableRemoveLastAnchors = pGrapher->m_DocumentManager->GetStaticProcessing(); bool somePrinted = false; preparePrinting(); if (m_pBlockAttributes->m_pTopSide != NULL && !m_mergeBordersWithPrevBlock) oRegion.TrancateRectPt(m_pBlockAttributes->m_pTopSide->m_oPen.m_oPen.Size / 0.3528f); if (AtBeginning() && !InTable()) addCommandToPage(oPage, _blockStartCommand); do { CLine* line = getLine(oRegion, oPage, pGrapher); bool lineBefore = (line != NULL); if (lineBefore) lineBefore = (line->GetItemsCount() > 1); if (CheckBreakBefore(oRegion, oPage, lineBefore)) { if (line) { oPage.AddLine(line); addAnchors(oPage, origRegion, line->GetRect(), m_Items.CurrentItem()); somePrinted = true; disableRemoveLastAnchors = true; } break; } if (line == NULL) { if (!Complete()) { oRegion.SetComplete(); if ((m_pBlockAttributes->m_nKeepTogether) && atBeginning) if (somePrinted) { oPage.DeleteBlocks(1); Renew(pGrapher); disableRemoveLastAnchors = true; } if (!oPage.isWithNonDummyLines()) disableRemoveLastAnchors = true; } break; } oPage.AddLine(line); addAnchors(oPage, origRegion, line->GetRect(),m_Items.CurrentItem()); oRegion.SetProcessing(); somePrinted = true; } while (true); if (AtEnd() && !InTable()) addCommandToPage(oPage, _blockEndCommand, true); if (!AtEnd() && !disableRemoveLastAnchors) oPage.RemoveAnchorContent(m_Items.CurrentItem()); RectF rectAfter = oRegion.GetFilledRectPt(); RectF rectMetrics(rectAfter.GetLeft(), rectBefore.GetBottom(), rectAfter.GetRight() - rectAfter.GetLeft(), rectAfter.GetBottom() - rectBefore.GetBottom()); RectF rect = GetRectInRegion(rectMetrics); if (!oPage.InFootnoteProcess()) { DrawBorder(oPage, rect); DrawBackground(oPage, rect); } return somePrinted; } private: inline bool Prepared() { return m_Items.Prepared(); } private: RectF GetRectInRegion(RectF rect) { double dStartIndent = (double)m_pBlockAttributes->m_fStartIndent; double dEndIndent = (double)m_pBlockAttributes->m_fEndIndent; double dTextIndent = (double)m_pBlockAttributes->m_fTextIndent; double dSpaceAfter = (double)m_pBlockAttributes->m_nSpaceAfter; double dSpaceBefore = (double)m_pBlockAttributes->m_nSpaceBefore; if (dTextIndent < 0) dStartIndent += dTextIndent; //TODO double dLeft = rect.GetLeft() + dStartIndent - 4; double dRight = rect.GetRight(); double dTop = rect.GetTop(); double dBottom = rect.GetBottom();// + 4; if (m_mergeBordersWithPrevBlock == false) dTop += dSpaceBefore; if (m_mergeBordersWithNextBlock == false) dBottom -= dSpaceAfter; return RectF(dLeft, dTop, dRight - dLeft, dBottom - dTop); } void DrawBorder(CPage &oPage, RectF rect) { if (m_pBlockAttributes->m_pLeftSide != NULL) { oPage.AddGraphicLine(m_pBlockAttributes->m_pLeftSide->GetGraphicLine(rect.X, rect.Y, rect.X, rect.Y + rect.Height)); } if (m_pBlockAttributes->m_pRightSide != NULL) { oPage.AddGraphicLine(m_pBlockAttributes->m_pRightSide->GetGraphicLine(rect.X + rect.Width, rect.Y, rect.X + rect.Width, rect.Y + rect.Height)); } if ((m_pBlockAttributes->m_pTopSide != NULL) && !m_mergeBordersWithPrevBlock) { oPage.AddGraphicLine(m_pBlockAttributes->m_pTopSide->GetGraphicLine(rect.X, rect.Y, rect.X + rect.Width, rect.Y)); } if (m_pBlockAttributes->m_pBottomSide != NULL && !m_mergeBordersWithNextBlock) { oPage.AddGraphicLine(m_pBlockAttributes->m_pBottomSide->GetGraphicLine(rect.X, rect.Y + rect.Height, rect.X + rect.Width, rect.Y + rect.Height)); } } void DrawBackground(CPage &oPage, RectF rect) { if (m_pBlockAttributes->m_pRect != NULL) { oPage.AddBackgroundRect(m_pBlockAttributes->GetBackgroundRect(rect.X, rect.Y, rect.Width, rect.Height)); } } private: CLine* getLine(CRegion& region, CPage& page, CGrapher* grapher) { bool firstLine = false; if (AtBeginning()) { PrepareItems(grapher); firstLine = true; } else if (m_Items.AtBeginning()) firstLine = true; if (m_Items.AtEnd()) return NULL; grapher->m_DocumentManager->m_ItemManager.SetWrapFlags(m_pBlockAttributes->m_nWrapFlags); CAreaManager* areaManager = page.GetAreaManager(); RectF lineArea = GetRectWithMargins(region.GetRectPt(), firstLine); if (!checkArea(lineArea)) return NULL; if (!IgnoreNegativeWidth(lineArea)) return NULL; m_Items.SaveCurrentItem(); CLine* resultLine = CreateLine(lineArea, areaManager, firstLine, grapher); if (resultLine != NULL) { ApplyLineHeight(lineArea, resultLine, &grapher->m_DocumentManager->m_ItemManager); if (resultLine->IsContainsAlternate() && resultLine->GetHeightPt() > lineArea.Height) lineArea.Height = resultLine->GetHeightPt(); float lineHeight = lineArea.Height; float lineHeightDelta = lineArea.Height - resultLine->GetHeightPt(); float truncatedHeight = lineArea.Height + (lineArea.Y - region.GetRectPt().Y); if (AtEnd()) ApplySpaceAfter(lineArea, &grapher->m_DocumentManager->m_ItemManager); if (region.GetRectPt().Height >= truncatedHeight || page.IsEmptyBody() || !grapher->m_DocumentManager->m_ItemManager.IsFo()) { if (lineHeightDelta < 0) { float newDescent = lineHeight * (resultLine->getOriginDescent() / resultLine->GetHeightPt()); float offset = lineHeightDelta + resultLine->GetDescent() - newDescent; resultLine->MoveOn(0, offset); } region.TrancateRectPt(lineArea.Height + (lineArea.Y - region.GetRectPt().Y)); m_Items.RemoveCurrentItem(); if (firstLine && m_strID != _T("")) grapher->m_DocumentManager->m_Linker.AddTarget(m_strID, resultLine->GetRect() , *grapher->m_DocumentManager); if (resultLine->GetFootnoteCount() > 0) { CRegion footnoteRegion = region; page.StartFootnote(); for (int i = 0; i < resultLine->GetFootnoteCount(); ++i) { if (m_iFootnoteIndex >= (int) m_arrFootnotes.GetCount()) break; m_arrFootnotes[m_iFootnoteIndex]->FillRegion(footnoteRegion, page, grapher); ++m_iFootnoteIndex; } page.FinishFootnote(); float footnoteHeight = region.GetRegionHeightPt() - footnoteRegion.GetRegionHeightPt(); region.TruncateHeightPt(footnoteHeight); page.changeFootnoteHeight(footnoteHeight); } } else { resultLine->RestoreItems(); RELEASEOBJECT(resultLine); m_Items.RestoreCurrentItem(); } } else m_Items.RemoveCurrentItem(); return resultLine; } CLine* CreateLine(RectF& oLineArea, CAreaManager* pAreaManager, const bool& bIsFirstLine, CGrapher* pGrapher) { CLine* pResultLine = NULL; RectF areaOrigin = oLineArea; InitLineArea(oLineArea); if (bIsFirstLine) ApplySpaceBefore(oLineArea, &pGrapher->m_DocumentManager->m_ItemManager); CArray arrRests; REAL fAvaliableHeight = pAreaManager->GetArea(oLineArea, arrRests); if (arrRests.GetCount() == 0) { CLine* line = new CLine(); line->setDummy(true); line->GetRect().Height = oLineArea.Height; return line; } if (fAvaliableHeight < 0) pResultLine = CreateLineInAreaNotWrap(oLineArea, bIsFirstLine, pGrapher); else pResultLine = CreateLineInAreaWrap2(oLineArea, areaOrigin, bIsFirstLine, pAreaManager, pGrapher); if (pResultLine != NULL) pResultLine->MoveOn(arrRests[0].X, oLineArea.Y - pResultLine->GetRect().Y); return pResultLine; } private: CLine* CreateLineInAreaWrap2(RectF& area, const RectF& areaOrigin, const bool& first, CAreaManager* areaManager, CGrapher* grapher) { CItemManager* itemManager = &grapher->m_DocumentManager->m_ItemManager; do { bool wrap = false; CArray areas; areaManager->GetArea(area, areas); int areasCount = (int)areas.GetCount(); if (areasCount > 0) { float wrapDelta = areas[0].Width - area.Width; if ((wrapDelta > 1) || (wrapDelta < -1)) wrap = true; float offsetX = areas[0].X; CArray* itemsInAreas = new CArray[areasCount]; CItems::SPartProperties properties; properties.m_WrapBySymbol = itemManager->WrapBySymbol(); properties.m_RuptureIfSingle = (areasCount == 1); properties.m_Force = m_InTable; m_Items.SaveCurrentItem(); for (int index = 0; index < areasCount; ++index) { /*if (areas[index].Width <= 9) continue;*/ properties.m_Single = true; FillArea(areas[index], itemsInAreas[index], properties, first, grapher); if (properties.m_HeightChanged) { area.Y = areaOrigin.Y; area.Height = areas[index].Height; area.Width = areaOrigin.Width; if (first) ApplySpaceBefore(area, itemManager); m_Items.RestoreCurrentItem(); break; } } if (properties.m_HeightChanged) { properties.m_HeightChanged = false; continue; } m_Items.RemoveCurrentItem(); if (properties.m_Break == CItems::PageBreak) m_pBlockAttributes->m_nBreakBeforeType = 1; else if ((properties.m_Break == CItems::ColumnBreak)) m_pBlockAttributes->m_nBreakBeforeType = 2; if (areasCount == 1) { CArray& items = itemsInAreas[0]; int itemsCount = (int)items.GetCount(); CLine* line = new CLine(); for (int index = 0; index < itemsCount; ++index) line->AddItem(items[index]); if (areas[0].Width > 0) line->SetPersistWidth(areas[0].Width); line->SetAlign(GetTextAlign(), first, m_Items.AtEnd()); return line; } else { CCompositeLine* compositeLine = new CCompositeLine(); for (int index = 0; index < areasCount; ++index) { CArray& items = itemsInAreas[index]; int itemsCount = (int)items.GetCount(); CLine* line = new CLine(); for (int index2 = 0; index2 < itemsCount; ++index2) line->AddItem(items[index2]); line->SetPersistWidth(areas[index].Width); line->MoveOn(areas[index].X - offsetX, 0.0f); compositeLine->AddItem(line); } compositeLine->SetAlign(GetTextAlign(), first, m_Items.AtEnd()); return compositeLine; } } else return NULL; } while (true); } CLine* CreateLineInAreaNotWrap(RectF& area, const bool& first, CGrapher* grapher) { CArray items; RectF areaTmp = area; areaTmp.Height = 0; CItems::SPartProperties properties; properties.m_WrapBySymbol = grapher->m_DocumentManager->m_ItemManager.WrapBySymbol(); properties.m_Force = m_InTable | !grapher->m_DocumentManager->m_ItemManager.IsFo(); properties.m_Single = true; properties._limitTabs = m_InTable; properties.m_RuptureIfSingle = true; properties._isPpt = !grapher->m_DocumentManager->m_ItemManager.IsFo(); properties._ignoreWidthLimit = properties._isPpt && m_pBlockAttributes->_oneLine; properties._firstLine = AtBeginning(); m_Items.FillArea(areaTmp, items, properties, grapher); int itemsCount = (int)items.GetCount(); if (itemsCount != 0) { if (properties.m_Break == CItems::PageBreak) m_pBlockAttributes->m_nBreakBeforeType = 1; else if ((properties.m_Break == CItems::ColumnBreak)) m_pBlockAttributes->m_nBreakBeforeType = 2; CLine* line = new CLine(); for (int index = 0; index < itemsCount; ++index) line->AddItem(items[index]); area.Height = line->GetHeightPt(); if (areaTmp.Width > 0 || properties._ignoreWidthLimit) line->SetPersistWidth(areaTmp.Width); line->SetAlign(GetTextAlign(), first, m_Items.AtEnd()); return line; } else return NULL; } private: void FillArea(RectF& area, CArray& items, CItems::SPartProperties& properties, const bool& first, CGrapher* grapher) { RectF areaTmp = area; m_Items.FillArea(areaTmp, items, properties, grapher); area.Width = areaTmp.Width; area.Height = areaTmp.Height; } void InitLineArea(RectF& oLineArea) { oLineArea.Height = m_Items[m_Items.CurrentItem()]->GetHeightPt(); } void SetTabStops(CRegion& oRegion, CDocumentManager& documentManager) { float fLeftBorder = oRegion.GetRectPt().X; float fRightBorder = fLeftBorder + oRegion.GetRectPt().Width; documentManager.SetDefaultTab(m_pBlockAttributes->m_fDefaultTabSize, fLeftBorder, fRightBorder); for (size_t nIndex = 0; nIndex < m_pBlockAttributes->m_arrTabs.GetCount(); ++nIndex) documentManager.AddTab(m_pBlockAttributes->m_arrTabs[nIndex]); } RectF GetRectWithMargins(const RectF &oRectF, const bool &bIsFirstLine) { RectF oRectFWithMargins = oRectF; if (bIsFirstLine == true) if ((m_pBlockAttributes->m_pBulletProperties == NULL) || (m_pBlockAttributes->m_fTextIndent < 0)) { oRectFWithMargins.X += m_pBlockAttributes->m_fTextIndent; oRectFWithMargins.Width -= m_pBlockAttributes->m_fTextIndent; } oRectFWithMargins.X += m_pBlockAttributes->m_fStartIndent; oRectFWithMargins.Width -= m_pBlockAttributes->m_fStartIndent + m_pBlockAttributes->m_fEndIndent; return oRectFWithMargins; } private: void PrepareItems(CGrapher* grapher) { //m_Alternates.Update(grapher); m_Items.Prepare(grapher, m_pBlockAttributes, m_Alternates.Inlines(), m_Alternates.Anchors(), m_arrFootnotes); } private: void ProcessNodesWithReader(XmlUtils::CXmlNode& oXmlNode, CCharacter* pDefaultCharacter, CDocumentManager& documentManager) { XmlUtils::CXmlNodes oNodes; if (oXmlNode.GetNodes(_T("*"), oNodes)) { INT iListLength = oNodes.GetCount(); for (INT iIndex = 0; iIndex < iListLength; ++iIndex) { XmlUtils::CXmlNode oNode; oNodes.GetAt(iIndex, oNode); ProcessNode(oNode, pDefaultCharacter, documentManager); } } if (m_Alternates.HasAnchors() && !m_Alternates.isOnlyOneLetter() && m_Items.IsEmpty()) { CCharacter* settings = new CCharacter(*pDefaultCharacter); settings->m_lCount = 1; m_Items.AddItem(_T(" "), settings); } } void ProcessNode(XmlUtils::CXmlNode& oNode, CCharacter* pDefaultCharacter, CDocumentManager& documentManager, const bool &bAsInline = false) { CString strNodeName = oNode.GetName(); if (m_Alternates.HasInlines()) m_Items.InlineAdded(); if (strNodeName == _T("field-char")) { if (m_oComplexFieldChar.ProcessFieldCharNode(oNode)) { if (m_oComplexFieldChar.LastIs(_T("PAGE")) && !m_oComplexFieldChar.LastIs(_T("PAGEREF"))) { CCharacter *pCharacter; if (m_oComplexFieldChar.m_pCharacter != NULL) pCharacter = new CCharacter(*m_oComplexFieldChar.m_pCharacter); else pCharacter = new CCharacter(*pDefaultCharacter); CPageNumberC* pPageNumber = new CPageNumberC(pCharacter, false); CAlternate2* pAlternate = new CAlternate2(); pAlternate->Inline(true); pAlternate->SetContent(pPageNumber, m_pBlockAttributes->m_lCount); m_Alternates.Add(pAlternate); if (m_oComplexFieldChar.m_pCharacter != NULL) { delete m_oComplexFieldChar.m_pCharacter; m_oComplexFieldChar.m_pCharacter = NULL; } } else if (m_oComplexFieldChar.LastIs(_T("NUMPAGES"))) { CCharacter *pCharacter; if (m_oComplexFieldChar.m_pCharacter != NULL) pCharacter = new CCharacter(*m_oComplexFieldChar.m_pCharacter); else pCharacter = new CCharacter(*pDefaultCharacter); CPageNumberC* pPageNumber = new CPageNumberC(pCharacter, true); CAlternate2* pAlternate = new CAlternate2(); pAlternate->Inline(true); pAlternate->SetContent(pPageNumber, m_pBlockAttributes->m_lCount); m_Alternates.Add(pAlternate); if (m_oComplexFieldChar.m_pCharacter != NULL) { delete m_oComplexFieldChar.m_pCharacter; m_oComplexFieldChar.m_pCharacter = NULL; } } } m_oComplexFieldChar.ProcessFieldChar(); /*if (m_oComplexFieldChar.IsInContentProcess() && (m_oComplexFieldChar.LastIs(_T("PAGE")) && !m_oComplexFieldChar.LastIs(_T("PAGEREF")))) { CCharacter *pCharacter = new CCharacter(*pDefaultCharacter); CPageNumberC* pPageNumber = new CPageNumberC(pCharacter, false); CAlternate2* pAlternate = new CAlternate2(); pAlternate->Inline(true); pAlternate->SetContent(pPageNumber, m_pBlockAttributes->m_lCount); m_Alternates.Add(pAlternate); } */ } else if (strNodeName == _T("fo:inline")) { CCharacter *pCharacter = new CCharacter(*pDefaultCharacter); pCharacter->FromXmlNode3(oNode, m_oComplexFieldChar.IsInTOC()); if (m_oComplexFieldChar.m_pCharacter == NULL) m_oComplexFieldChar.m_pCharacter = new CCharacter(*pCharacter); if (!m_oComplexFieldChar.IsInContentProcess() || m_oComplexFieldChar.CanFillContent()) { ProcessNodesWithReader(oNode, pCharacter, documentManager); RELEASEOBJECT(pCharacter); } } else if (strNodeName == _T("text")) { /*if (m_oComplexFieldChar.IsInProcess()) m_oComplexFieldChar.ProcessInstructionText(oNode);*/ if (m_oComplexFieldChar.IsInCommandProcess()) m_oComplexFieldChar.ProcessInstructionText(oNode); else if (!m_oComplexFieldChar.IsInContentProcess() || m_oComplexFieldChar.CanFillContent()) { CCharacter *pCharacter = new CCharacter(*pDefaultCharacter); pCharacter->FromXmlNode3(oNode, m_oComplexFieldChar.IsInTOC()); if (pCharacter->m_lCount != 0) { m_pBlockAttributes->m_lCount += pCharacter->m_lCount; m_Items.AddItem(oNode.GetTextExt(), pCharacter); } else RELEASEOBJECT(pCharacter); } } else if (strNodeName == _T("fo:numbering")) { CString id = oNode.GetAttribute(_T("id")); CString numId = oNode.GetAttribute(_T("numId")); int level = oNode.ReadAttributeOrValueInt(_T("level"), -1); if (id == _T("") || level == -1) return; CCharacter* character = new CCharacter(*pDefaultCharacter); character->FromXmlNode2(oNode); CString numbering = documentManager.getListElement(id, numId, level); character->m_lCount = numbering.GetLength(); if (character->m_lCount != 0) { _blockPr.setNumberingLevel(level); character->setIsLabel(true); m_pBlockAttributes->m_lCount += character->m_lCount; m_Items.AddItem(numbering, character, CItems::NumAdded); } else RELEASEOBJECT(character); } else if (strNodeName == _T("fo:tab")) { CCharacter *pCharacter = new CCharacter(*pDefaultCharacter); pCharacter->m_lCount = 1; m_pBlockAttributes->m_lCount += pCharacter->m_lCount; m_Items.AddItem(_T("\t"), pCharacter, CItems::NumAddedWithTab); } else if (strNodeName == _T("fo:leader")) { if (!m_oComplexFieldChar.IsInCommandProcess()) { CCharacter *pCharacter = new CCharacter(*pDefaultCharacter); pCharacter->FromXmlNode3(oNode, m_oComplexFieldChar.IsInTOC()); pCharacter->m_lCount = 1; m_pBlockAttributes->m_lCount += 1; m_Items.AddItem(_T(" "), pCharacter); } } else if (strNodeName == _T("fo:basic-link")) { m_oComplexFieldChar.Interrupt(); CLinkProperties oLink; oLink.FromXmlNode2(oNode); if (oLink.nMode != 0) { CLinkProperties oPrevLink = pDefaultCharacter->m_oLink; pDefaultCharacter->m_oLink = oLink; ProcessNodesWithReader(oNode, pDefaultCharacter, documentManager); pDefaultCharacter->m_oLink = oPrevLink; } } else if (strNodeName == _T("fo:break")) { CCharacter *pCharacter = new CCharacter(*pDefaultCharacter); pCharacter->m_lCount = 1; CString strBreak = oNode.GetAttributeOrValue(_T("break-before"), _T("")); if (strBreak == _T("page")) pCharacter->m_nAdditionalParam = 1; else if (strBreak == _T("column")) pCharacter->m_nAdditionalParam = 2; if (m_InTable) pCharacter->m_nAdditionalParam = 0; m_pBlockAttributes->m_lCount += 1; m_Items.AddItem(_T("\n"), pCharacter, CItems::NumNone); } else if (strNodeName == _T("fo:alternate-content")) { CAlternate2 *pAlternate = new CAlternate2(); if (!pAlternate->FromXml(oNode, documentManager)) { pAlternate->InlinePosition(m_pBlockAttributes->m_lCount); m_Alternates.Add(pAlternate); } else RELEASEOBJECT(pAlternate); } else if (strNodeName == _T("fo:footnote")) { ProcessNodesWithReader(oNode, pDefaultCharacter, documentManager); } else if (strNodeName == _T("fo:footnote-body")) { CFootnote* pFootnote = new CFootnote(); pFootnote->FromXmlNode(oNode, documentManager); pFootnote->SetInlinePosition(m_pBlockAttributes->m_lCount); m_arrFootnotes.Add(pFootnote); } else if (strNodeName == _T("fo:page-number")) { CCharacter *pCharacter = new CCharacter(*pDefaultCharacter); CPageNumberC* pPageNumber = new CPageNumberC(pCharacter, false); CAlternate2* pAlternate = new CAlternate2(); pAlternate->Inline(true); pAlternate->SetContent(pPageNumber, m_pBlockAttributes->m_lCount); m_Alternates.Add(pAlternate); } else if (strNodeName == _T("fo:page-number-citation")) { CCharacter *pCharacter = new CCharacter(*pDefaultCharacter); CPageNumberC* pPageNumber = new CPageNumberC(pCharacter, true); CAlternate2* pAlternate = new CAlternate2(); pAlternate->Inline(true); pAlternate->SetContent(pPageNumber, m_pBlockAttributes->m_lCount); m_Alternates.Add(pAlternate); } } void LoadID(XmlUtils::CXmlNode& oXmlNode) { m_strID = oXmlNode.GetAttributeOrValue(_T("id"), _T("")); } void readHeadingLevel(XmlUtils::CXmlNode& blockXml) { _blockPr.setHeadingLevel(blockXml.ReadAttributeInt(_T("headingLvl"), 0)); } bool CreateHyperlink(XmlUtils::CXmlNode& oXmlNode, CLinkProperties& oLink) { static CString strHyperlink = _T("HYPERLINK"); CString strText = oXmlNode.GetText(); INT iIndex = 0; while (strText[iIndex] == _T(' ')) { ++iIndex; } INT iIndex2 = 0; for (; iIndex2 < 9; ++iIndex2) { if (strText[iIndex + iIndex2] != strHyperlink[iIndex2]) { break; } } if (iIndex2 == 9) { INT iPosL = strText.Find(_T('"'), 0); INT iPosR = -1; if (iPosL >= 0) { ++iPosL; iPosR = strText.Find(_T('"'), iPosL); } if (iPosR >= 0) { CString strID = strText.Mid(iPosL, iPosR - iPosL); oLink.strTarget = strID; } return true; } else { return false; } } void addAnchors(CPage& page, CRegion& region, const int& position = -1) { RectF line = region.GetRectPt(); line.Height = 0; addAnchors(page, region, line, position); } void addAnchors(CPage& page, CRegion& region, const RectF& line, const int& position = -1) { if (!m_IgnoreAnchors) m_Alternates.Place(page, region, m_pBlockAttributes, line, position); } private: void preparePrinting() { _state._stopPrintReason = State::AnyReason; } private: bool checkArea(const RectF& area) { if (area.Width <= 0) { _state._stopPrintReason = State::NotEnoughWidthReason; return false; } return true; } bool CheckBreakBefore(CRegion& oRegion, CPage &oPage, const bool& lineBefore = false) { if ((m_pBlockAttributes->m_nBreakBeforeType > 0)) { if (oPage.IsEmptyBody() && !lineBefore) { m_pBlockAttributes->m_nBreakBeforeType = 0; return false; } oRegion.SetComplete(); oRegion.BreakType(m_pBlockAttributes->m_nBreakBeforeType); m_pBlockAttributes->m_nBreakBeforeType *= -1; addCommandToPage(oPage, pageBreakCommand); return true; } else return false; } CAlignHorizontal GetTextAlign() { CAlignHorizontal eTextAlign = LeftAlign; switch (m_pBlockAttributes->m_nTextAlignment) { case 1: eTextAlign = CenterAlign; break; case 2: eTextAlign = RightAlign; break; case 3: if (!m_Items.AtEnd()) eTextAlign = WideAlign; break; } return eTextAlign; } inline void ApplySpaceBefore(RectF& oLineArea, CItemManager* pItemManager) { oLineArea.Y += pItemManager->GetPlcOrPxl(m_pBlockAttributes->m_nSpaceBefore, oLineArea.Height); } inline void ApplySpaceAfter(RectF& oLineArea, CItemManager* pItemManager) { oLineArea.Height += pItemManager->GetPlcOrPxl(m_pBlockAttributes->m_nSpaceAfter, oLineArea.Height); } inline void ApplyLineHeight(RectF& oLineArea, CLine *pLine, CItemManager* pItemManager) { if (m_pBlockAttributes->m_fLineHeight != 0) { if (pLine->IsContainsAlternate()) { REAL fSpaceAfter = pItemManager->GetPlcOrPxl(m_pBlockAttributes->m_fLineHeight, pLine->GetTextHeight()) - pLine->GetTextHeight(); oLineArea.Height += fSpaceAfter; } else { oLineArea.Height = pItemManager->GetPlcOrPxl(m_pBlockAttributes->m_fLineHeight, oLineArea.Height); } } else if ((m_pBlockAttributes->m_nLineSpacing != 0)) { oLineArea.Height = pItemManager->GetPlcOrPxl(m_pBlockAttributes->m_nLineSpacing, oLineArea.Height, 1); } } private: bool IgnoreNegativeWidth(const RectF& area) { if ((area.Width <= 0) && (!InTable())) m_Items.m_IgnoreNegativeWidth = true; else m_Items.m_IgnoreNegativeWidth = false; return true; } private: void initCommands() { _blockStartCommand = SharedPtr( new BlockStartRendererCommand( _blockPr.getHeadingLevel(), _blockPr.getNumberingLevel(), m_pBlockAttributes->m_nTextAlignment)); _blockEndCommand = SharedPtr( new BlockEndRendererCommand(_blockStartCommand)); pageBreakCommand = SharedPtr(new PageBreakRendererCommand()); } }; class CTable : public CCommonBlock, private CXmlAttributeReader { private: class CCell { public: CFlow *m_pFlow; INT m_iNumberColumnsSpanned; INT m_iNumberRowsSpanned; REAL m_fWidth; INT m_bCarring; bool _negativeRect; RectF m_oRectF; CPaddingProperties m_oPaddingProperties; CBorderProperties m_oBorderProperties; CBackgroundProperties m_oBackgroundProperties; private: float _widthMin; float _widthScore; public: CCell() : m_pFlow(NULL), m_iNumberColumnsSpanned(1), m_iNumberRowsSpanned(1), m_fWidth(0.0f), m_bCarring(0), _negativeRect(false), m_oRectF(), m_oPaddingProperties(), m_oBorderProperties(), m_oBackgroundProperties(), _widthMin(-1), _widthScore(-1) { } ~CCell() { Clear(); } void Clear() { RELEASEOBJECT(m_pFlow); m_iNumberColumnsSpanned = 1; m_iNumberRowsSpanned = 1; m_fWidth = 0.0f; m_bCarring = 0; m_oRectF = RectF(); m_oPaddingProperties.Clear(); m_oBackgroundProperties.Clear(); m_oBorderProperties.Clear(); _widthMin = -1; _widthScore = -1; } public: bool FromXmlNode(XmlUtils::CXmlNode &oXmlNode, CDocumentManager& documentManager) { CString strVMerge = oXmlNode.GetAttributeOrValue(_T("v-merge"), _T("reset")); if (strVMerge == _T("continue")) { Clear(); return false; } m_pFlow = new CFlow(); m_pFlow->FromXmlNode(oXmlNode, documentManager, TRUE); m_iNumberColumnsSpanned = oXmlNode.ReadAttributeOrValueInt(_T("number-columns-spanned"), 1); m_iNumberRowsSpanned = oXmlNode.ReadAttributeOrValueInt(_T("number-rows-spanned"), 1); m_oPaddingProperties.FromXmlNode(oXmlNode); m_oBorderProperties.FromXmlNode2(oXmlNode); m_oBackgroundProperties.FromXmlNode2(oXmlNode); return true; } public: bool Complete() { return m_pFlow->Complete() || _negativeRect; } bool IsEmpty() { return m_pFlow->Empty(); } void estimateWidth(CGrapher* grapher, float& widthMin, float& widthScore) { if ((_widthMin >= 0) || (_widthScore >= 0)) { widthMin = _widthMin; widthScore = _widthScore; } else if (m_pFlow) { m_pFlow->estimateWidth(grapher, widthMin, widthScore); } else { widthMin = _widthMin = 0; widthScore = _widthScore = 0; } } public: bool FillRegion(CRegion& region, CPage& page, const bool& isMustRenew, CGrapher* grapher) { float fSize = 0.0f; if (m_oBorderProperties.m_pLeftSide != NULL) fSize = (REAL)m_oBorderProperties.m_pLeftSide->m_oPen.m_oPen.Size; CBounds oPaddings; oPaddings.SetAsMarginPt(m_oPaddingProperties.m_fPaddingLeft + fSize, m_oPaddingProperties.m_fPaddingTop, m_oPaddingProperties.m_fPaddingRight, m_oPaddingProperties.m_fPaddingBottom); oPaddings.SetAsRectPt(region.GetRectPt()); RectF rect = oPaddings.GetRectPt(); region.SetRect(rect); page.beginCell(); bool result = true; if (rect.Width > 0) { region.SetReady(); result = m_pFlow->FillRegion(region, page, grapher); } else { _negativeRect = true; region.SetComplete(); } page.endCell(); return result; } void DrawBorder(CPage &oPage) { if (m_oBorderProperties.m_pLeftSide != NULL) { oPage.AddGraphicLine(m_oBorderProperties.m_pLeftSide->GetGraphicLine(m_oRectF.X, m_oRectF.Y, m_oRectF.X, m_oRectF.Y + m_oRectF.Height)); } if (m_oBorderProperties.m_pRightSide != NULL) { oPage.AddGraphicLine(m_oBorderProperties.m_pRightSide->GetGraphicLine(m_oRectF.X + m_oRectF.Width, m_oRectF.Y, m_oRectF.X + m_oRectF.Width, m_oRectF.Y + m_oRectF.Height)); } if ((m_oBorderProperties.m_pTopSide != NULL) ) { oPage.AddGraphicLine(m_oBorderProperties.m_pTopSide->GetGraphicLine(m_oRectF.X, m_oRectF.Y, m_oRectF.X + m_oRectF.Width, m_oRectF.Y)); } if (m_oBorderProperties.m_pBottomSide != NULL) { oPage.AddGraphicLine(m_oBorderProperties.m_pBottomSide->GetGraphicLine(m_oRectF.X, m_oRectF.Y + m_oRectF.Height, m_oRectF.X + m_oRectF.Width, m_oRectF.Y + m_oRectF.Height)); } /*/ oPage.AddGraphicLine(m_oBorderProperties.m_pBottomSide->GetGraphicLine(m_oRectF.X, m_oRectF.Y, m_oRectF.X + m_oRectF.Width, m_oRectF.Y + m_oRectF.Height)); //*/ --m_bCarring; } void DrawBackground(CPage &oPage) { if (m_oBackgroundProperties.m_pRect != NULL) { oPage.AddBackgroundRect(m_oBackgroundProperties.GetBackgroundRect(m_oRectF.X, m_oRectF.Y, m_oRectF.Width, m_oRectF.Height)); } } }; private: CAtlArray m_arrColumnWidth; bool _colsCalculated; CAtlArray m_arrRowHeight; INT m_iColumnCount; INT m_iRowCount; REAL m_fWidth; REAL m_fSummaryWidth; INT m_iCurrentRow; INT m_iPageStartRow; CAtlArray m_arrCells; CBlockAttributes _blockAttributes; RCommand _tableStartCommand; RCommand _tableEndCommand; public: CTable() : CCommonBlock() , _colsCalculated(false) , m_iColumnCount(0), m_iRowCount(0) , m_fWidth(0.0f), m_fSummaryWidth(0.0f) , m_iCurrentRow(-1), m_iPageStartRow(0) { } ~CTable() { Clear(); } void Clear() { m_arrColumnWidth.RemoveAll(); m_arrRowHeight.RemoveAll(); m_iColumnCount = 0; m_iRowCount = 0; m_fWidth = 0.0f; m_fSummaryWidth = 0.0f; m_iCurrentRow = -1; m_iPageStartRow = 0; for (size_t nIndex1 = 0; nIndex1 < m_arrCells.GetCount(); ++nIndex1) { if (m_arrCells[nIndex1] != NULL) { for (size_t nIndex2 = nIndex1 + 1; nIndex2 < m_arrCells.GetCount(); ++nIndex2) { if (m_arrCells[nIndex2] == m_arrCells[nIndex1]) { m_arrCells[nIndex2] = NULL; } } RELEASEOBJECT(m_arrCells[nIndex1]); } } m_arrCells.RemoveAll(); _blockAttributes.Clear(); initCommands(); } public: bool FromXmlNode(XmlUtils::CXmlNode &oXmlNode, CDocumentManager& documentManager) { Clear(); documentManager.BlockCreated(); documentManager.SetStaticProcessing(true); setCommands(oXmlNode.GetXml()); m_fWidth = FloatPtAttributeFromXml(oXmlNode, _T("width"), -1.0f); m_iCurrentRow = 0; _blockAttributes.FromXmlNode2(oXmlNode); if (!TryLoadCols(oXmlNode)) { m_iColumnCount = CalculateMaxCols(oXmlNode); if (m_iColumnCount > 0) m_arrColumnWidth.InsertAt(0, -1.0f, m_iColumnCount); } XmlUtils::CXmlNode oBodyNode; if (oXmlNode.GetNode(_T("fo:table-body"), oBodyNode)) { XmlUtils::CXmlNodes oRowNodes; if (oBodyNode.GetNodes(_T("fo:table-row"), oRowNodes)) { m_iRowCount = oRowNodes.GetCount(); if (m_iRowCount == 0) { documentManager.SetStaticProcessing(false); return false; } //m_arrCells.SetCount(m_iColumnCount * m_iRowCount); //for (int iIndex = 0; iIndex < (int)m_arrCells.GetCount(); ++iIndex) // m_arrCells[iIndex] = NULL; m_arrCells.InsertAt(0, NULL, m_iColumnCount * m_iRowCount); for (INT iIndex = 0; iIndex < m_iRowCount; ++iIndex) { XmlUtils::CXmlNode oRowNode; oRowNodes.GetAt(iIndex, oRowNode); LoadNewRow(oRowNode, documentManager); REAL fRowHeight = oRowNode.ReadAttributeOrValueFloat(_T("height"), 0); m_arrRowHeight.Add(fRowHeight); } } } m_iCurrentRow = 0; documentManager.SetStaticProcessing(false); return true; } public: bool Empty() const { return (m_iCurrentRow == -1); } bool Complete() const { return (m_iCurrentRow == -1); } bool UsualBlock() const { return false; } void estimateWidth(CGrapher* grapher, float& widthMin, float& widthScore) { widthMin = 0; widthScore = 0; int rowsCount = m_iRowCount; int colsCount = m_iColumnCount; int index = 0; for (int i = 0; i < rowsCount; ++i) { float rowWidthMin = 0; for (int j = 0; j < colsCount; ++j) { if (!m_arrCells[index]) continue; float cellWidthMin = 0; float cellWidthScore = 0; m_arrCells[index]->estimateWidth(grapher, cellWidthMin, cellWidthScore); rowWidthMin += cellWidthMin; widthScore += cellWidthScore; ++index; } } } public: void Renew(CGrapher* pGrapher, const bool& full = true) { _colsCalculated = false; m_iCurrentRow = 0; m_iPageStartRow = 0; for (size_t nIndex1 = 0; nIndex1 < m_arrCells.GetCount(); ++nIndex1) if ((m_arrCells[nIndex1] != NULL) && (m_arrCells[nIndex1]->m_pFlow != NULL)) m_arrCells[nIndex1]->m_pFlow->Static(true); initCommands(); } public: bool FillRegion(CRegion &oRegion, CPage &oPage, const bool& bIsMustRenew, CGrapher* pGrapher) { if (m_fWidth < 0) m_fWidth *= -oRegion.GetRectPt().Width; if (!InTable()) addCommandToPage(oPage, _tableStartCommand); normalizeWidth(); if (bIsMustRenew) Renew(pGrapher); CRegion oRegionWithMargins = makeRegionWithSettings(oRegion); bool bIsSomePrinted = false; if (!_colsCalculated) { calcColsWidths(m_arrColumnWidth, m_fWidth, *pGrapher); _colsCalculated = true; } pGrapher->m_DocumentManager->SetStaticProcessing(true); int iPreviousRow = 0; while (m_iCurrentRow != -1) { iPreviousRow = m_iCurrentRow; oRegion.SetProcessing(); if (!OutputRow(oRegionWithMargins, oPage, pGrapher)) { bIsSomePrinted = true; oRegion.SetComplete(); break; } } pGrapher->m_DocumentManager->SetStaticProcessing(false); if (!InTable() && m_iCurrentRow == -1) addCommandToPage(oPage, _tableEndCommand, true); m_iPageStartRow = iPreviousRow; oRegion.TrancateRectPt(oRegion.GetRegionHeightPt() - oRegionWithMargins.GetRegionHeightPt()); return bIsSomePrinted; } private: bool OutputRow(CRegion &oRegion, CPage &oPage, CGrapher* pGrapher) { bool bIsCompletePrinted = true; bool bIsSomePrinted = false; REAL fRowHeight = 0.0f; REAL fOffsetX = 0.0f; CAtlArray arrRowCells; CAtlArray arrUnrowCells; CAtlArray arrLastUnrowCells; INT iCurrentCellIndex = 0; INT iRawStartIndex = m_iCurrentRow * m_iColumnCount; CCell *pCell = NULL; while (iCurrentCellIndex < m_iColumnCount) { pCell = m_arrCells[iRawStartIndex + iCurrentCellIndex]; if (!pCell) { ++iCurrentCellIndex; continue; } if (m_arrColumnWidth[iCurrentCellIndex] == 0.0f) { ++iCurrentCellIndex; continue; } BOOL bIsLastRow = FALSE; if (m_iCurrentRow == m_iRowCount - 1) { bIsLastRow = TRUE; } else if (pCell != m_arrCells[iRawStartIndex + m_iColumnCount + iCurrentCellIndex]) { bIsLastRow = TRUE; } if (bIsLastRow == TRUE) { arrRowCells.Add(pCell); } else { arrUnrowCells.Add(pCell); } BOOL bIsDrawing = FALSE; if (m_iCurrentRow == m_iPageStartRow) { bIsDrawing = TRUE; } else if (pCell != m_arrCells[iRawStartIndex - m_iColumnCount + iCurrentCellIndex]) { bIsDrawing = TRUE; } else { arrLastUnrowCells.Add(pCell); if (!pCell->Complete()) { bIsDrawing = TRUE; } } REAL fCellHeight = 0.0f; if (bIsDrawing == TRUE) { RectF oCellRect = oRegion.GetRectPt(); oCellRect.X += fOffsetX; oCellRect.Width = 0.0f; while (pCell == m_arrCells[iRawStartIndex + iCurrentCellIndex]) { oCellRect.Width += m_arrColumnWidth[iCurrentCellIndex]; ++iCurrentCellIndex; if (iCurrentCellIndex == m_iColumnCount) { break; } } pCell->m_oRectF = oCellRect; CRegion oCellRegion; oCellRegion.SetReady(); oCellRegion.SetRect(oCellRect); if (pCell->FillRegion(oCellRegion, oPage, false, pGrapher)) { bIsSomePrinted = true; pCell->m_oRectF.Height = oRegion.GetRegionHeightPt() - oCellRegion.GetRegionHeightPt(); } else { pCell->m_oRectF.Height = 0.0f; } if (bIsLastRow == TRUE) { fCellHeight = pCell->m_oRectF.Height; } else { fCellHeight = 0.0f; } } else { iCurrentCellIndex += pCell->m_iNumberColumnsSpanned; if (bIsLastRow == TRUE) { fCellHeight = pCell->m_oRectF.Height; } } fOffsetX += pCell->m_oRectF.Width; if (fRowHeight < fCellHeight) { fRowHeight = fCellHeight; } if (!pCell->Complete()) { bIsCompletePrinted = FALSE; pCell->m_bCarring = 2; } } if (fRowHeight < m_arrRowHeight[m_iCurrentRow]) { fRowHeight = m_arrRowHeight[m_iCurrentRow]; } if (fRowHeight == 0) fRowHeight = 12; if (bIsSomePrinted == TRUE) { for (size_t nIndex = 0; nIndex < arrRowCells.GetCount(); ++nIndex) { if (bIsCompletePrinted == FALSE) { arrRowCells[nIndex]->m_bCarring = 2; } arrRowCells[nIndex]->m_oRectF.Height = fRowHeight + oRegion.GetRectPt().Y - arrRowCells[nIndex]->m_oRectF.Y; arrRowCells[nIndex]->DrawBorder(oPage); arrRowCells[nIndex]->DrawBackground(oPage); } } if (bIsCompletePrinted == FALSE) { for (size_t nIndex = 0; nIndex < arrUnrowCells.GetCount(); ++nIndex) { REAL fFullHeight = arrUnrowCells[nIndex]->m_oRectF.Height; arrUnrowCells[nIndex]->m_oRectF.Height = fRowHeight + oRegion.GetRectPt().Y - arrUnrowCells[nIndex]->m_oRectF.Y; arrUnrowCells[nIndex]->DrawBorder(oPage); arrUnrowCells[nIndex]->DrawBackground(oPage); arrUnrowCells[nIndex]->m_oRectF.Height = 0; } if (m_iCurrentRow != 0) { for (size_t nIndex = 0; nIndex < arrLastUnrowCells.GetCount(); ++nIndex) { arrLastUnrowCells[nIndex]->m_oRectF.Height = oRegion.GetRectPt().Y - arrLastUnrowCells[nIndex]->m_oRectF.Y; arrLastUnrowCells[nIndex]->DrawBorder(oPage); arrLastUnrowCells[nIndex]->DrawBackground(oPage); arrLastUnrowCells[nIndex]->m_oRectF.Height = 0; } } } else { for (size_t nIndex = 0; nIndex < arrUnrowCells.GetCount(); ++nIndex) { arrUnrowCells[nIndex]->m_oRectF.Height -= fRowHeight; } } oRegion.TrancateRectPt(fRowHeight); arrRowCells.RemoveAll(); arrUnrowCells.RemoveAll(); arrLastUnrowCells.RemoveAll(); if (bIsCompletePrinted == TRUE) { ++m_iCurrentRow; if (m_iCurrentRow == m_iRowCount) { m_iCurrentRow = -1; } } return bIsCompletePrinted; } private: bool TryLoadCols(XmlUtils::CXmlNode &oXmlNode) { XmlUtils::CXmlNodes oColumnNodes; if (oXmlNode.GetNodes(_T("fo:table-column"), oColumnNodes)) { m_iColumnCount = oColumnNodes.GetCount(); if (m_iColumnCount == 0) { return false; } for (INT nIndex = 0; nIndex < m_iColumnCount; ++nIndex) { XmlUtils::CXmlNode oNode; oColumnNodes.GetAt(nIndex, oNode); REAL fColumnWidth = FloatPtAttributeFromXml(oNode, _T("column-width"), -1.0f); m_fSummaryWidth += fColumnWidth; m_arrColumnWidth.Add(fColumnWidth); } m_fWidth = m_fSummaryWidth; return true; } return false; } INT CalculateMaxCols(XmlUtils::CXmlNode &oXmlNode) { XmlUtils::CXmlNode oBodyNode; if (oXmlNode.GetNode(_T("fo:table-body"), oBodyNode)) { XmlUtils::CXmlNodes oRowNodes; if (oBodyNode.GetNodes(_T("fo:table-row"), oRowNodes)) { INT iMaxColsCount = 0; INT iRowCount = oRowNodes.GetCount(); for (INT iRowIndex = 0; iRowIndex < iRowCount; ++iRowIndex) { INT iColsCount = 0; XmlUtils::CXmlNode oRowNode; oRowNodes.GetAt(iRowIndex, oRowNode); XmlUtils::CXmlNodes oCellNodes; if (oRowNode.GetNodes(_T("fo:table-cell"), oCellNodes)) { INT iCellCount = oCellNodes.GetCount(); for (INT iCellIndex = 0; iCellIndex < iCellCount; ++iCellIndex) { XmlUtils::CXmlNode oCellNode; oCellNodes.GetAt(iCellIndex, oCellNode); iColsCount += oCellNode.ReadAttributeOrValueInt(_T("number-columns-spanned"), 1); } } if (iColsCount > iMaxColsCount) { iMaxColsCount = iColsCount; } } return iMaxColsCount; } } return 0; } void LoadNewRow(XmlUtils::CXmlNode &oXmlNode, CDocumentManager& documentManager) { ++m_iCurrentRow; INT iCurrentCell = m_iColumnCount * (m_iCurrentRow - 1); int iFreeCellsCount = m_iColumnCount; XmlUtils::CXmlNodes oCellNodes; if (oXmlNode.GetNodes(_T("fo:table-cell"), oCellNodes)) { INT iCellCount = oCellNodes.GetCount(); iFreeCellsCount -= iCellCount; for (INT iIndex = 0; iIndex < iCellCount; ++iIndex) { XmlUtils::CXmlNode oCellNode; oCellNodes.GetAt(iIndex, oCellNode); CCell *pNewCell = new CCell(); pNewCell->m_oBorderProperties = _blockAttributes; if (pNewCell->FromXmlNode(oCellNode, documentManager)) { for (; iCurrentCell < m_iColumnCount * m_iCurrentRow; ++iCurrentCell) { if (m_arrCells[iCurrentCell] == NULL) break; } } else { if (iCurrentCell >= m_iColumnCount * m_iCurrentRow) { RELEASEOBJECT(pNewCell); return; } if ((m_arrCells[iCurrentCell] == NULL) && (m_iCurrentRow != 1)) { m_arrCells[iCurrentCell] = m_arrCells[iCurrentCell - m_iColumnCount]; } ++iCurrentCell; RELEASEOBJECT(pNewCell); continue; } if (iCurrentCell == m_iColumnCount * m_iCurrentRow) return; if (pNewCell->m_iNumberColumnsSpanned > iFreeCellsCount + 1) { pNewCell->m_iNumberColumnsSpanned = iFreeCellsCount + 1; iFreeCellsCount = 0; } INT iCellIndex = iCurrentCell; for (INT iSpanRowIndex = 0; iSpanRowIndex < pNewCell->m_iNumberRowsSpanned; ++iSpanRowIndex) { for (INT iSpanColIndex = 0; iSpanColIndex < pNewCell->m_iNumberColumnsSpanned; ++iSpanColIndex) { m_arrCells[iCellIndex] = pNewCell; iCellIndex++; } iCellIndex += m_iColumnCount - pNewCell->m_iNumberColumnsSpanned; } iCurrentCell += pNewCell->m_iNumberColumnsSpanned; } } } private: CRegion makeRegionWithSettings(const CRegion& region) { float widthDelta = region.GetRectPt().Width - m_fWidth; float offsetX = calcAlignOffset(widthDelta); CBounds bounds; bounds.SetAsMarginPt(_blockAttributes.m_fStartIndent + offsetX , _blockAttributes.m_nSpaceBefore, _blockAttributes.m_fEndIndent, 0.0f); CRegion regionWithSettings = region; regionWithSettings.ChangeRect(bounds); return regionWithSettings; } float calcAlignOffset(const float& widthDelta) { switch (_blockAttributes.m_nTextAlignment) { case 1: return widthDelta / 2; case 2: return widthDelta; } return 0; } private: void calcColsWidths(CAtlArray& colsWidths, const float& widthMax , CGrapher& grapher) { int& colsCount = m_iColumnCount; int& rowsCount = m_iRowCount; CAtlArray colsScores; colsScores.InsertAt(0, 1, colsCount); CAtlArray colsWidthsMin; colsWidthsMin.InsertAt(0, 0, colsCount); CAtlArray rowScores; rowScores.InsertAt(0, 0, colsCount); CAtlArray rowWidthsMin; rowWidthsMin.InsertAt(0, 0, colsCount); for (int row = 0; row < rowsCount; ++row) { calcRowWidths(rowWidthsMin, rowScores, row, widthMax,grapher); for (int col = 0; col < colsCount; ++col) { int colsSpanned = 1; while (isSpanned(row, col + colsSpanned, 1)) ++colsSpanned; float spanColsWidthMin = rowWidthsMin[col] / colsSpanned; float spanColsScore = rowScores[col] / colsSpanned; for (int i = col; i < col + colsSpanned; ++i) { if (colsWidthsMin[i] < spanColsWidthMin) colsWidthsMin[i] = spanColsWidthMin; colsScores[i] += spanColsScore; } col += colsSpanned - 1; } } float width = 0; float score = 0; int colsAutoCount = 0; for (int i = 0; i < colsCount; ++i) if (m_arrColumnWidth[i] > 0) { width += m_arrColumnWidth[i]; } else { width += colsWidthsMin[i]; score += colsScores[i]; ++colsAutoCount; } colsWidths.SetCount(colsCount); float widthDelta = widthMax - width; for (int i = 0; i < colsCount; ++i) if (m_arrColumnWidth[i] > 0) colsWidths[i] = m_arrColumnWidth[i]; else { colsWidths[i] = colsWidthsMin[i]; float coeff = colsScores[i] / score; colsWidths[i] += coeff * widthDelta; } } void calcRowWidths(CAtlArray& colsWidths, CAtlArray& colsScores , const int& row, const float& rowWidthMax, CGrapher& grapher) { int& colsCount = m_iColumnCount; float rowWidth = 0; int colsAutoCount = 0; for (int i = 0; i < colsCount; ++i) { float colWidth = m_arrColumnWidth[i]; if (colWidth > 0) { colsWidths[i] = colWidth; rowWidth += colWidth; } else { colsWidths[i] = -1; ++colsAutoCount; } colsScores[i] = 0; } for (int i = 0; i < colsCount; ++i) { if (colsWidths[i] != -1) continue; CCell* cell = m_arrCells[row * colsCount + i]; if (!cell || isSpanned(row, i)) { colsWidths[i] = 0; colsScores[i] = 0; continue; } float cellWidth = cell->m_fWidth; if (cellWidth > 0) { colsWidths[i] = cellWidth; rowWidth += cellWidth; --colsAutoCount; } else { float widthMin = 0; float widthScore = 0; cell->estimateWidth(&grapher, widthMin, widthScore); colsScores[i] = widthScore; cellWidth = widthMin; if (cellWidth >= 0) { colsWidths[i] = -cellWidth; rowWidth += cellWidth; } } } if (colsAutoCount > 0) { float colWidthReduction = (rowWidth - rowWidthMax) / colsAutoCount; for (int i = 0; i < colsCount; ++i) { if (colsWidths[i] < 0) colsWidths[i] = -colsWidths[i]; if (colWidthReduction > 0) colsWidths[i] -= colWidthReduction; } } } private: bool isSpanned(const int& row, const int& col, const char& type = 0) { if (row >= m_iRowCount || col >= m_iColumnCount) return false; bool spanned = false; CCell* cell = m_arrCells[row * m_iColumnCount + col]; if (!cell) return false; if (row > 0 && type != 1) if (cell == m_arrCells[(row - 1) * m_iColumnCount + col]) spanned = true; if (col > 0 && type != 2) if (cell == m_arrCells[row * m_iColumnCount + col - 1]) spanned = true; return spanned; } void normalizeWidth() { if (m_fWidth <= 0) return; if (m_fSummaryWidth > m_fWidth) { REAL fDeltaPct = m_fWidth / m_fSummaryWidth; for (INT iIndex = 0; iIndex < m_iColumnCount; ++iIndex) { m_arrColumnWidth[iIndex] *= fDeltaPct; } m_fSummaryWidth = m_fWidth; } } private: void initCommands() { if (!_tableStartCommand.isEmpty()) _tableStartCommand->setAdded(false); if (!_tableEndCommand.isEmpty()) _tableEndCommand->setAdded(false); } void setCommands(const CString& xml) { _tableStartCommand = SharedPtr(new TableStartRendererCommand(xml)); _tableEndCommand = SharedPtr(new TableEndRendererCommand()); } }; // ### ### ### class CFlow { public: enum EPosPageType { OddPageType = 0, EvenPageType, FirstPageType }; public: CFlow() : m_strName(_T("")), m_Static(false), m_Complete(false), m_arrBlocks(), m_nCurrentBlock(0), m_eTextAlignVertical(FarAlignVert) { } ~CFlow() { Clear(); } void Clear() { m_strName = _T(""); m_Static = false; m_Complete = false; for (size_t nIndex = 0; nIndex < m_arrBlocks.GetCount(); ++nIndex) RELEASEOBJECT(m_arrBlocks[nIndex]); m_arrBlocks.RemoveAll(); m_nCurrentBlock = 0; m_eTextAlignVertical = FarAlignVert; } public: void FromXmlNode(XmlUtils::CXmlNode &oXmlNode, CDocumentManager& documentManager, const bool& inTable = false) { m_strName = oXmlNode.GetAttributeOrValue(_T("flow-name"), _T("")); m_PageType = ReadPosPageType(oXmlNode); XmlUtils::CXmlNodes oNodes; if (oXmlNode.GetNodes(_T("*"), oNodes)) { INT iListLenght = oNodes.GetCount(); bool bIsFirst = true; bool inCommandField = false; CAtlArray curCommands; for (INT iIndexNode = 0; iIndexNode < iListLenght; ++iIndexNode) { XmlUtils::CXmlNode oBlockNode; oNodes.GetAt(iIndexNode, oBlockNode); CString strBlockName = oBlockNode.GetName(); if (strBlockName == _T("fo:block")) { CBlock *pBlock = new CBlock; pBlock->InTable(inTable); pBlock->FromXmlNode(oBlockNode, documentManager, bIsFirst, inCommandField, curCommands); m_arrBlocks.Add(pBlock); bIsFirst = false; } else if (strBlockName == _T("fo:table")) { CTable *pTable = new CTable(); pTable->InTable(inTable); if (pTable->FromXmlNode(oBlockNode, documentManager)) m_arrBlocks.Add(pTable); else RELEASEOBJECT(pTable); } } } } public: inline bool Empty() { return (m_arrBlocks.GetCount() == 0); } inline void Complete(const bool& complete) { m_Complete = complete; } inline bool Complete() const { return m_Complete; } inline void Static(const bool& staticFlow) { m_Static = staticFlow; } inline bool Static() const { return m_Static; } inline const CString& Name() const { return m_strName; } inline const EPosPageType PageType() const { return m_PageType; } public: void estimateWidth(CGrapher* grapher, float& widthMin, float& widthScore) const { widthMin = 0; widthScore = 0; int blocksCount = (int) m_arrBlocks.GetCount(); for (int i = 0; i < blocksCount; ++i) { float blockWidthMin = 0; float blockWidthScore = 0; m_arrBlocks[i]->estimateWidth(grapher, blockWidthMin, blockWidthScore); if (blockWidthMin > widthMin) widthMin = blockWidthMin; widthScore += blockWidthScore; } } inline size_t GetCurrentBlock() const { return m_nCurrentBlock; } inline void SetCurrentBlock(size_t currentBlock, CGrapher* grapher) { for (size_t nIndex = currentBlock; nIndex < m_arrBlocks.GetCount(); ++nIndex) m_arrBlocks[nIndex]->Renew(grapher, false); m_nCurrentBlock = currentBlock; } public: bool FillRegion(CRegion &oRegion, CPage &oPage, CGrapher* pGrapher, const bool& inColumn = false) { oPage.StartPrintingFlow(); if (Complete() && !Static()) return false; if (oRegion.IsComplete()) return false; if (Static() && !inColumn) m_nCurrentBlock = 0; pGrapher->m_DocumentManager->SetBorders(oRegion); Complete(true); bool somePrinted = false; CBlockInputParameters blockParams; for (size_t nIndex = m_nCurrentBlock; nIndex < m_arrBlocks.GetCount(); ++nIndex) { CCommonBlock *pBlock = m_arrBlocks[nIndex]; if (pBlock->UsualBlock()) { CCommonBlock *pPrevBlock; bool mergeWithPrev = false; bool removeSpaceBefore = false; if (nIndex != 0) { pPrevBlock = m_arrBlocks[nIndex - 1]; if (pPrevBlock->UsualBlock()) { mergeWithPrev = ((CBlock*)pPrevBlock)->m_mergeBordersWithNextBlock; removeSpaceBefore = ((CBlock*)pPrevBlock)->m_removeSpaceAfter; } } ((CBlock*)pBlock)->m_mergeBordersWithPrevBlock = mergeWithPrev; ((CBlock*)pBlock)->m_removeSpaceBefore = removeSpaceBefore; CCommonBlock *pNextBlock; bool mergeWithNext = false; bool removeSpaceAfter = false; if (nIndex != m_arrBlocks.GetCount() - 1) { pNextBlock = m_arrBlocks[nIndex + 1]; if (pNextBlock->UsualBlock()) { mergeWithNext = EqualsAreas(pBlock, pNextBlock); removeSpaceAfter = EqualsStyles(pBlock, pNextBlock); } } ((CBlock*)pBlock)->m_mergeBordersWithNextBlock = mergeWithNext; ((CBlock*)pBlock)->m_removeSpaceAfter = removeSpaceAfter; } bool blockSomePrinted = false; pBlock->InColumn(inColumn); pBlock->InputParams(blockParams, *pGrapher->m_DocumentManager); if (pBlock->FillRegion(oRegion, oPage, m_Static, pGrapher)) { blockSomePrinted = true; somePrinted = true; } pBlock->InputParams(blockParams, *pGrapher->m_DocumentManager, true); if (pBlock->Complete()) pGrapher->m_DocumentManager->BlockProcessed(); else Complete(false); if (oRegion.IsComplete()) { if (nIndex != m_nCurrentBlock) { if (!blockSomePrinted && (m_arrBlocks[nIndex - 1]->KeepNext()) && oRegion.BreakType() == 0) if (m_arrBlocks[nIndex - 1]->transferToNextPage(pGrapher)) { oPage.DeleteBlocks(2); --nIndex; } } m_nCurrentBlock = nIndex; if (pBlock->Complete()) ++m_nCurrentBlock; Complete(false); break; } if (nIndex == m_arrBlocks.GetCount() - 1) m_nCurrentBlock = nIndex; } AlignInRegion(oRegion, oPage, m_eTextAlignVertical); return somePrinted; } void AlignInRegion(CRegion &oRegion, CPage &oPage, CAlignVertical eTextAlignVertical) { REAL fOffsetPt = oRegion.GetRegionHeightPt(); switch(eTextAlignVertical) { case CenterAlignVert : fOffsetPt /= 2; break; case FarAlignVert : fOffsetPt = 0; break; } oPage.MoveFlowOn(0, fOffsetPt); } public: bool EqualsAreas(CCommonBlock* block1, CCommonBlock* block2) { CBlockAttributes* blockAttr1 = ((CBlock*)block1)->m_pBlockAttributes; CBlockAttributes* blockAttr2 = ((CBlock*)block2)->m_pBlockAttributes; if (blockAttr1->m_fStartIndent == ((CBlock*)block2)->m_pBlockAttributes->m_fStartIndent && blockAttr1->m_fEndIndent == blockAttr2->m_fEndIndent && ((blockAttr1->m_oBrush.m_oBrush.Alpha1 != 0 && blockAttr2->m_oBrush.m_oBrush.Alpha1 != 0) ||(blockAttr1->m_oBrush.m_oBrush.Alpha1 == 0 && blockAttr2->m_oBrush.m_oBrush.Alpha1 == 0)) && blockAttr2->GetBorderType() == blockAttr1->GetBorderType()) return true; return false; } bool EqualsStyles(CCommonBlock* block1, CCommonBlock* block2) { if (((CBlock*)block1)->m_pBlockAttributes->m_pStyle == ((CBlock*)block2)->m_pBlockAttributes->m_pStyle) return true; return false; } public: CAtlArray& GetBlocks() { return m_arrBlocks; } void SetAlignVertical(const CAlignVertical& alingVertical) { m_eTextAlignVertical = alingVertical; } private: CString m_strName; bool m_Static; bool m_Complete; EPosPageType m_PageType; CAtlArray m_arrBlocks; size_t m_nCurrentBlock; CAlignVertical m_eTextAlignVertical; private: EPosPageType ReadPosPageType(XmlUtils::CXmlNode& flow) { CString type = flow.GetAttribute(_T("type"), _T("odd")); EPosPageType pageType = OddPageType; if (type == _T("odd")) pageType = OddPageType; else if (type == _T("even")) pageType = EvenPageType; else if (type == _T("first")) pageType = FirstPageType; return pageType; } }; class CFootnote : public CFlow, public CItem { private: INT m_iInlinePosition; public: CFootnote() : CFlow(), CItem(), m_iInlinePosition(-1) { } ~CFootnote() { Clear(); } public: void Clear() { m_iInlinePosition = -1; CItem::Clear(); CFlow::Clear(); } void FromXmlNode(XmlUtils::CXmlNode& oXmlNode, CDocumentManager& documentManager) { CFlow::FromXmlNode(oXmlNode, documentManager); } CItemType GetType() { return Footnote; } INT GetInilinePosition() { return m_iInlinePosition; } void SetInlinePosition(const INT& iInlinePosition) { m_iInlinePosition = iInlinePosition; } void SetOnBaseline(const bool& bIsInit = true) { m_oRect = RectF(0.0f, 0.0f, 0.0f, 0.0f); } public: bool FillRegion(CRegion& oRegion, CPage &oPage, CGrapher* pGrapher) { return CFlow::FillRegion(oRegion, oPage, pGrapher); } void Draw(IAVSRenderer *pRenderer, CDocumentManager& documentManager, const float &fCompleteness) { } }; class CPageSequence { private: CLayoutMasterSet* m_pLayoutMasterSet; CFlowMap* m_pFlowMap; CPageSequenceMaster* m_pPageSequenceMaster; CPageSequence* _prev; CString m_strMasterReference; CAtlArray m_arrFlows; CAtlArray m_arrStaticContent; bool m_Complete; bool m_reWriteColumns; public: CPageSequence(CLayoutMasterSet *pLayoutMasterSet = NULL) : m_pLayoutMasterSet(pLayoutMasterSet), _prev(NULL), m_pFlowMap(NULL), m_pPageSequenceMaster(NULL), m_strMasterReference(_T("")), m_arrFlows(), m_arrStaticContent(), m_Complete(true), m_reWriteColumns(true) { } ~CPageSequence() { Clear(); } void Clear() { m_pLayoutMasterSet = NULL; m_pFlowMap = NULL; m_pPageSequenceMaster = NULL; m_strMasterReference = _T(""); m_arrFlows.RemoveAll(); m_arrStaticContent.RemoveAll(); m_Complete = true; m_reWriteColumns = true; _prev = NULL; } public: void loadFromXml(XmlUtils::CXmlNode& pageSequenceXml, CDocumentManager& documentManager) { CString strFlowMapName = pageSequenceXml.GetAttributeOrValue(_T("flow-map-reference"), _T("")); m_pFlowMap = m_pLayoutMasterSet->FindFlowMap(strFlowMapName); m_strMasterReference = pageSequenceXml.GetAttributeOrValue(_T("master-reference"), _T("")); m_pPageSequenceMaster = m_pLayoutMasterSet->FindPageSequenceMaster(m_strMasterReference); documentManager.SetStaticProcessing(true); XmlUtils::CXmlNodes oStaticContentNodes; if (pageSequenceXml.GetNodes(_T("fo:static-content"), oStaticContentNodes)) { INT iCount = oStaticContentNodes.GetCount(); for (INT iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oNode; oStaticContentNodes.GetAt(iIndex, oNode); m_arrStaticContent.Add(); m_arrStaticContent[iIndex].FromXmlNode(oNode, documentManager); m_arrStaticContent[iIndex].Static(true); } } documentManager.SetStaticProcessing(false); XmlUtils::CXmlNodes oFlowNodes; if (pageSequenceXml.GetNodes(_T("fo:flow"), oFlowNodes)) { INT iCount = oFlowNodes.GetCount(); for (INT iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oNode; oFlowNodes.GetAt(iIndex, oNode); m_arrFlows.Add(); m_arrFlows[iIndex].FromXmlNode(oNode, documentManager); } } } public: void SetLayoutMasterSet(CLayoutMasterSet* layoutMasterSet) { m_pLayoutMasterSet = layoutMasterSet; } bool Continuous() { CSimplePageMaster* simplePageMaster = m_pLayoutMasterSet->FindSimplePageMaster(GetPageMasterName()); assert(simplePageMaster != NULL); return simplePageMaster->Continuous(); } void Complete(const bool& complete) { m_Complete = complete; } bool Complete() { return m_Complete; } public: CPage* NewPage(CGrapher* grapher, const CPage* prevPage) { CSimplePageMaster* pageMaster = m_pLayoutMasterSet->FindSimplePageMaster(GetPageMasterName()); CPage *page = CPage::createNew(prevPage); page->SetPageMaster(pageMaster); CItemManager* itemManager = &grapher->m_DocumentManager->m_ItemManager; itemManager->SetWidthL(page->GetWidthL()); itemManager->SetHeightL(page->GetHeightL()); itemManager->SetMultiplierX(page->GetWidthPt()); itemManager->SetMultiplierY(page->GetHeightPt()); if (Complete()) grapher->m_DocumentManager->setPageNumbering(pageMaster->getPageNumbering()); grapher->m_DocumentManager->nextPage(); return page; } void ContinuePage(CPage& page) { page.SetPageMaster(m_pLayoutMasterSet->FindSimplePageMaster(GetPageMasterName())); page.Continuous(true); } bool FillPage(CPage& page, CGrapher* grapher) { grapher->m_DocumentManager->SetPage(page); if (!page.Continuous()) { #ifndef TME_DONT_OUTPUT_HEADER_FOOTER addHeaderCommandToPage(page); FillHeader(page, grapher); FillFooter(page, grapher); addHeaderCommandToPage(page, false); #endif TruncateBody(page); } else { float filledHeight = page.FilledHeight(); TruncateBodyTop(page, filledHeight); TruncateBodyBottom(page, page.getFootnoteHeight()); float footerHeight = page.FooterHeight(); } FillBody(page, grapher); CalculateFilledHeight(page); return Complete(); } void ReWriteColumns(bool flag) { m_reWriteColumns = flag; } public: CFlow* GetFirstFlow() { return &m_arrFlows[0]; } private: void FillBody(CPage& page, CGrapher* grapher) { Complete(true); page.StartBody(); for (int index = 0; index < (int)m_arrFlows.GetCount(); ++index) { CFlow& flow = m_arrFlows[index]; PrintFlow(page, &flow, grapher); } page.FinishBody(); } void FillHeader(CPage& page, CGrapher* grapher) { int pageIndex = grapher->m_DocumentManager->getPageIndex(); FillStatic(page, grapher, _T("xsl-region-before"), PageType(pageIndex)); } void FillFooter(CPage& page, CGrapher* grapher) { int pageIndex = grapher->m_DocumentManager->getPageIndex(); FillStatic(page, grapher, _T("xsl-region-after"), PageType(pageIndex)); } void FillStatic(CPage& page, CGrapher* grapher, const CString& name, const CFlow::EPosPageType& pageType) { grapher->m_DocumentManager->SetStaticProcessing(true); bool found = false; for (int index = 0; index < (int) m_arrStaticContent.GetCount(); ++index) { CFlow& flow = m_arrStaticContent[index]; if ((flow.Name() == name) && (flow.PageType() == pageType)) { PrintFlow(page, &flow, grapher); found = true; break; } } if (!found) { if (!FillStatic(page, grapher, name) && _prev != NULL) _prev->FillStatic(page, grapher, name, pageType); } grapher->m_DocumentManager->SetStaticProcessing(false); } bool FillStatic(CPage& page, CGrapher* grapher, const CString& name) { bool found = false; grapher->m_DocumentManager->SetStaticProcessing(true); for (int index = 0; index < (int) m_arrStaticContent.GetCount(); ++index) { CFlow& flow = m_arrStaticContent[index]; if ((flow.Name() == name) && (flow.PageType() == CFlow::OddPageType)) { found = true; PrintFlow(page, &flow, grapher); break; } } grapher->m_DocumentManager->SetStaticProcessing(false); return found; } private: void PrintFlow(CPage& oPage, CFlow* pFlow, CGrapher* pGrapher) { CAtlArray arrRegionNames; GetRegionNames(pFlow->Name(), arrRegionNames); for (size_t nRegionIndex = 0; nRegionIndex < arrRegionNames.GetCount(); ++nRegionIndex) { CString name = arrRegionNames[nRegionIndex]; if (name == _T("xsl-region-after")) pFlow->SetAlignVertical(NearAlignVert); size_t iLength; double dSizeBlocksInColumns = 0; double dWidthBlocksInColumns = 0; size_t sBlockInBeginColumns = 0; size_t sLineInBeginColumns = 0; size_t sFirstColumn; int footLineInBeginColumns = 0; int graphLineInBeginColumns = 0; int backgroundInBeginColumns = 0; bool completeRegions = false; CRegion **ppRegion = oPage.GetRegions(arrRegionNames[nRegionIndex], iLength); if (ppRegion != NULL) { addColumnCommandToPage(oPage, (int) iLength); size_t i = 0; for (size_t i = 0; i < iLength;i++) { CRegion *pRegion = ppRegion[i]; if (pRegion != NULL) { if (!pRegion->IsComplete()) { if (pRegion->IsColumn() && (i == 0 || !ppRegion[i -1]->IsColumn())) { sBlockInBeginColumns = pFlow->GetCurrentBlock(); sLineInBeginColumns = oPage.GetLastLine(); graphLineInBeginColumns = oPage.GetLastGraphLine(); backgroundInBeginColumns = oPage.GetLastBackground(); sFirstColumn = i; } if (!pRegion->IsColumn()) { pFlow->FillRegion(*pRegion, oPage, pGrapher); if (pRegion->BreakType() == 1) completeRegions = true; } else { if (completeRegions) continue; if (i == 0) pFlow->FillRegion(*pRegion, oPage, pGrapher, true); else pFlow->FillRegion(*pRegion, oPage, pGrapher); if (pRegion->BreakType() == 1) completeRegions = true; double dWidth = pRegion->GetFilledWidth(); float delta = 0; float filledHeight = oPage.FilledHeight(); float top = pRegion->GetOriginalRectPt().GetTop(); if (filledHeight > top) delta = filledHeight - top; dSizeBlocksInColumns += (pRegion->GetFilledHeight() - delta) * dWidth; dWidthBlocksInColumns += dWidth; if (pFlow->Complete() && m_reWriteColumns) { size_t sLastColumn; double dHeightRegion = pRegion->GetOriginalRectPt().GetBottom() - top - delta; dWidthBlocksInColumns += GetWidthNextColumns(ppRegion, iLength, i, sLastColumn); double dNewHeight = dSizeBlocksInColumns / dWidthBlocksInColumns; bool flowIsEmpty = false; int iStep = 5; do { pFlow->Complete(false); oPage.ClearDerivedLines((int) sLineInBeginColumns); oPage.ClearDerivedGraphLines(graphLineInBeginColumns); oPage.ClearDerivedBackgrounds(backgroundInBeginColumns); pFlow->SetCurrentBlock(sBlockInBeginColumns, pGrapher); ReWriteColumns(ppRegion, sFirstColumn, sLastColumn, dNewHeight, pFlow, oPage, pGrapher); flowIsEmpty = pFlow->Complete(); if (flowIsEmpty == false) dNewHeight += iStep; else break; } while (dNewHeight <= dHeightRegion); i = sLastColumn; } } } } else { break; } } if (!pFlow->Complete()) Complete(false); } RELEASEARRAYOBJECTS(ppRegion); } } double GetWidthNextColumns(CRegion **ppRegion, size_t iLength, size_t position, size_t& sLastColumn) { double dWidth = 0; size_t i; for(i = position + 1; i < iLength; i++) { CRegion *pRegion = ppRegion[i]; if (pRegion != NULL && pRegion->IsColumn()) { dWidth += pRegion->GetFilledWidth(); } else { sLastColumn = i - 1; break; } } if (i == iLength ) sLastColumn = iLength - 1; return dWidth; } void ReWriteColumns(CRegion **ppRegion, size_t sFirstColumn, size_t sLastColumn, double dNewHeight, CFlow* pFlow, CPage& oPage, CGrapher* pGrapher, const float& prevSectionBottom = 0.0f) { bool completeRegions = false; for (size_t i = sFirstColumn; i <= sLastColumn; i++) { CRegion *pRegion = ppRegion[i]; if (completeRegions) continue; if (pRegion != NULL) { pRegion->SetComplete(); pRegion->CheckRect(); float filledHeight = oPage.FilledHeight(); float deltaY = filledHeight - pRegion->GetRectPt().GetTop(); if (deltaY > 0) pRegion->TrancateRectPt(deltaY); pRegion->TruncateHeightPt(pRegion->GetRectPt().GetBottom() - pRegion->GetRectPt().GetTop() - dNewHeight); pFlow->FillRegion(*pRegion, oPage, pGrapher); if (pRegion->BreakType() == 1) completeRegions = true; } } } private: void TruncateBody(CPage& page) { CRegion* regionBefore = page.GetRegion(_T("xsl-region-before")); if ((regionBefore != NULL) && !regionBefore->IsReady()) { float headerBottom = regionBefore->GetRectPt().GetTop(); TruncateBodyTop(page, headerBottom); } CRegion* regionAfter = page.GetRegion(_T("xsl-region-after")); if ((regionAfter != NULL) && !regionAfter->IsReady()) { float footerHeightEmpty = regionAfter->GetRectPt().GetBottom() - regionAfter->GetRectPt().GetTop(); float footerTop = regionAfter->GetOriginalRectPt().GetTop() + footerHeightEmpty; TruncateBodyBottom(page, footerTop, true); } } void TruncateBodyTop(CPage& page, const float& y) { size_t count = 0; CRegion** bodyRegions = page.GetRegions(_T("xsl-region-body"), count); for (int i = 0; i < (int)count; ++i) if (bodyRegions[i]) { float bodyTop = bodyRegions[i]->GetRectPt().GetTop(); float deltaY = y - bodyTop; if (deltaY > 0) bodyRegions[i]->TrancateRectPt(deltaY); } delete[] bodyRegions; } void TruncateBodyBottom(CPage& page, const float& y, bool bSaveFooterPos = false) { size_t count = 0; CRegion** bodyRegions = page.GetRegions(_T("xsl-region-body"), count); for (int i = 0; i < (int) count; ++i) if (bodyRegions[i]) { float bodyBottom = bodyRegions[i]->GetRectPt().GetBottom(); float deltaY = bodyBottom - y; if (deltaY > 0) { bodyRegions[i]->TruncateHeightPt(deltaY); if (bSaveFooterPos == true) page.FooterHeight(y); } } delete[] bodyRegions; } void CalculateFilledHeight(CPage& page) { float filledHeight = page.FilledHeight(); size_t count = 0; CRegion** bodyRegions = page.GetRegions(_T("xsl-region-body"), count); for (int i = 0; i < (int) count; ++i) if (bodyRegions[i]) { float bodyTop = bodyRegions[i]->GetRectPt().GetTop(); if (bodyTop > filledHeight) filledHeight = bodyTop; } delete[] bodyRegions; page.FilledHeight(filledHeight); } private: void GetRegionNames(const CString &strFlowName, CAtlArray &arrRegionNames) { if (m_pFlowMap != NULL) { m_pFlowMap->GetRegionNames(strFlowName, arrRegionNames); } if (arrRegionNames.GetCount() == 0) { arrRegionNames.Add(strFlowName); } } CString GetPageMasterName() { if (m_pPageSequenceMaster != NULL) { return m_pPageSequenceMaster->GetPageMasterName(); } else { return m_strMasterReference; } } CFlow::EPosPageType PageType(const int& pageIndex) const { if (pageIndex % 2 == 0) return CFlow::EvenPageType; else if (pageIndex == 1) return CFlow::FirstPageType; else return CFlow::OddPageType; } public: void setPrev(CPageSequence* prev) { _prev = prev; } private: void addHeaderCommandToPage(CPage& page, const bool& beginCommand = true) { RCommand command; if (beginCommand) command = SharedPtr(new HeaderStartRendererCommand()); else command = SharedPtr(new HeaderEndRendererCommand()); page.addRendererCommand(command, !beginCommand); } void addColumnCommandToPage(CPage& page, const int columnCount) { page.addRendererCommand( SharedPtr(new ColumnCountRendererCommand(columnCount))); } }; class CPageMasterAlternatives { public: CString m_strOddPageMasterReference; CString m_strEvenPageMasterReference; public: // --- CPageMasterAlternatives() : m_strOddPageMasterReference(_T("")), m_strEvenPageMasterReference(_T("")) { } CPageMasterAlternatives(const CPageMasterAlternatives &oSrc) { m_strOddPageMasterReference = oSrc.m_strOddPageMasterReference; m_strEvenPageMasterReference = oSrc.m_strEvenPageMasterReference; } // --- ~CPageMasterAlternatives() { Clear(); } // --- void Clear() { m_strOddPageMasterReference = _T(""); m_strEvenPageMasterReference = _T(""); } // --- void FromXmlNode(XmlUtils::CXmlNode &oXmlNode) { XmlUtils::CXmlNodes oPageMasterReferenceNodes; if (oXmlNode.GetNodes(_T("fo:conditional-page-master-reference"), oPageMasterReferenceNodes)) { INT iCount = oPageMasterReferenceNodes.GetCount(); for (INT iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oPageMasterReferenceNode; oPageMasterReferenceNodes.GetAt(iIndex, oPageMasterReferenceNode); CString strOddOrEven = oPageMasterReferenceNode.GetAttributeOrValue(_T("odd-or-even"), _T("")); if (strOddOrEven == _T("odd")) { m_strOddPageMasterReference = oPageMasterReferenceNode.GetAttributeOrValue(_T("master-reference"), _T("")); } else if (strOddOrEven == _T("even")) { m_strEvenPageMasterReference = oPageMasterReferenceNode.GetAttributeOrValue(_T("master-reference"), _T("")); } } } } }; class CPageSequenceMaster { public: CString m_strName; CAtlArray m_arrPageMasterAlternatives; public: // --- CPageSequenceMaster() : m_strName(_T("")), m_arrPageMasterAlternatives() { } CPageSequenceMaster(const CPageSequenceMaster &oSrc) { m_strName = oSrc.m_strName; m_arrPageMasterAlternatives.Copy(oSrc.m_arrPageMasterAlternatives); } // --- ~CPageSequenceMaster() { Clear(); } // --- void Clear() { m_strName = _T(""); m_arrPageMasterAlternatives.RemoveAll(); } // --- void FromXmlNode(XmlUtils::CXmlNode& oXmlNode) { m_strName = oXmlNode.GetAttributeOrValue(_T("master-name"), _T("")); XmlUtils::CXmlNodes oPageMasterAlternativesNodes; if (oXmlNode.GetNodes(_T("fo:repeatable-page-master-alternatives"), oPageMasterAlternativesNodes)) { INT iCount = oPageMasterAlternativesNodes.GetCount(); for (INT iIndex = 0; iIndex < iCount; ++ iIndex) { XmlUtils::CXmlNode oPageMasterAlternativesNode; oPageMasterAlternativesNodes.GetAt(iIndex, oPageMasterAlternativesNode); m_arrPageMasterAlternatives.Add(); m_arrPageMasterAlternatives[iIndex].FromXmlNode(oPageMasterAlternativesNode); } } } // --- CString GetPageMasterName() { if (!m_arrPageMasterAlternatives.IsEmpty()) { return m_arrPageMasterAlternatives[0].m_strEvenPageMasterReference; } else { return _T(""); } } }; class CFlowAssignment { private: CAtlArray m_arrSources; CAtlArray m_arrTargets; public: // --- CFlowAssignment() : m_arrSources(), m_arrTargets() { } CFlowAssignment(const CFlowAssignment &oFlowAssignment) { m_arrSources.Copy(oFlowAssignment.m_arrSources); m_arrTargets.Copy(oFlowAssignment.m_arrTargets); } // --- ~CFlowAssignment() { Clear(); } // --- CFlowAssignment& operator=(const CFlowAssignment &oFlowAssignment) { m_arrSources.Copy(oFlowAssignment.m_arrSources); m_arrTargets.Copy(oFlowAssignment.m_arrTargets); return *this; } // --- void Clear() { m_arrSources.RemoveAll(); m_arrTargets.RemoveAll(); } // --- void FromXmlNode(XmlUtils::CXmlNode &oXmlNode) { XmlUtils::CXmlNode oSourceNode; oXmlNode.GetNode(_T("fo:flow-source-list"), oSourceNode); XmlUtils::CXmlNodes oSpecifierNodes; if (oSourceNode.GetNodes(_T("fo:flow-name-specifier"), oSpecifierNodes)) { int iCount = oSpecifierNodes.GetCount(); for (int iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oNode; oSpecifierNodes.GetAt(iIndex, oNode); CString strFlowNameReference = oNode.GetAttributeOrValue(_T("flow-name-reference"), _T("")); if (strFlowNameReference != _T("")) { m_arrSources.Add(strFlowNameReference); } } } XmlUtils::CXmlNode oTargetNode; oXmlNode.GetNode(_T("fo:flow-target-list"), oTargetNode); if (oTargetNode.GetNodes(_T("fo:region-name-specifier"), oSpecifierNodes)) { int iCount = oSpecifierNodes.GetCount(); for (int iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oNode; oSpecifierNodes.GetAt(iIndex, oNode); CString strRegionNameReference = oNode.GetAttributeOrValue(_T("region-name-reference"), _T("")); if (strRegionNameReference != _T("")) { m_arrTargets.Add(strRegionNameReference); } } } } // --- CAtlArray* Find(const CString& strSource) { for (size_t nIndex = 0; nIndex < m_arrSources.GetCount(); ++nIndex) { if (m_arrSources[nIndex] == strSource) { return &m_arrTargets; } } return NULL; } }; class CFlowMap { private: CString m_strName; CAtlArray m_arrAssignments; public: // --- CFlowMap() : m_strName(_T("")), m_arrAssignments() { } CFlowMap(const CFlowMap &oPageMap) { m_strName = oPageMap.m_strName; m_arrAssignments.Copy(oPageMap.m_arrAssignments); } // --- ~CFlowMap() { Clear(); } // --- void FromXmlNode(XmlUtils::CXmlNode &oXmlNode) { m_strName = oXmlNode.GetAttributeOrValue(_T("flow-map-name"), _T("")); if (m_strName != _T("")) { XmlUtils::CXmlNodes oAssignmentNodes; if (oXmlNode.GetNodes(_T("fo:flow-assignment"), oAssignmentNodes)) { INT iCount = oAssignmentNodes.GetCount(); for (INT iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oNode; oAssignmentNodes.GetAt(iIndex, oNode); CFlowAssignment oFlowAssignment; oFlowAssignment.FromXmlNode(oNode); m_arrAssignments.Add(oFlowAssignment); } } } } // --- void Clear() { m_strName = _T(""); m_arrAssignments.RemoveAll(); } // --- inline BOOL IsEqualName(const CString& strName) { return (m_strName == strName); } // --- void GetRegionNames(const CString& strFlowName, CAtlArray& arrRegionNames) { for (size_t nIndex = 0; nIndex < m_arrAssignments.GetCount(); ++nIndex) { CAtlArray* pArrTargets = m_arrAssignments[nIndex].Find(strFlowName); if (pArrTargets) { arrRegionNames.Copy(*pArrTargets); } } } }; class CSimplePageMaster : private CXmlAttributeReader { private: CString m_strName; REAL m_fWidthPt; REAL m_fHeightPt; REAL m_fWidthL; REAL m_fHeightL; CBounds m_oBounds; CBrush m_oBrush; CAtlArray m_arrRegions; PageNumbering _pageNum; bool m_Continuous; private: void LoadAttributesFromXml(XmlUtils::CXmlNode& attributes) { CString continuous = attributes.GetAttribute(_T("continuous"), _T("false")); if (continuous == _T("true")) m_Continuous = true; } public: CSimplePageMaster() : m_strName(_T("")), m_fWidthPt(0.0f), m_fHeightPt(0.0f), m_fWidthL(0.0f), m_fHeightL(0.0f), m_oBounds(), m_oBrush(), m_arrRegions(), m_Continuous(false) { } ~CSimplePageMaster() { Clear(); } public: void Clear() { m_strName = _T(""); m_fWidthPt = 0.0f; m_fHeightPt = 0.0f; m_fWidthL = 0.0f; m_fHeightL = 0.0f; m_oBounds.Clear(); m_arrRegions.RemoveAll(); m_Continuous = false; } void loadFromXml(XmlUtils::CXmlNode& oXmlNode, CDocumentManager& documentManager) { m_strName = oXmlNode.GetAttributeOrValue(_T("master-name"), _T("")); if (documentManager.m_ItemManager.IsFo()) { m_fWidthPt = FloatPtAttributeFromXml(oXmlNode, _T("page-width"), 612.0f); m_fHeightPt = FloatPtAttributeFromXml(oXmlNode, _T("page-height"), 792.0f); } else { m_fWidthPt = FloatPtAttributeFromXml(oXmlNode, _T("page-width")); m_fHeightPt = FloatPtAttributeFromXml(oXmlNode, _T("page-height")); } m_fWidthL = m_fWidthPt; m_fHeightL = m_fHeightPt; m_oBounds.FromXmlNodeFo2(oXmlNode); ReadRegions(oXmlNode); XmlUtils::CXmlNode pageNumberingXml; if (oXmlNode.GetNode(_T("pageNumbering"), pageNumberingXml)) _pageNum.loadFromXml(pageNumberingXml); LoadAttributesFromXml(oXmlNode); } public: inline REAL GetWidthPt() { return m_fWidthPt; } inline REAL GetHeightPt() { return m_fHeightPt; } inline REAL GetWidthL() { return m_fWidthL; } inline REAL GetHeightL() { return m_fHeightL; } inline RectF GetRectPt() { return m_oBounds.GetRectPt(); } const PageNumbering& getPageNumbering() const { return _pageNum; } inline bool Continuous() { return m_Continuous; } public: inline BOOL IsEqualName(const CString& strName) { return (m_strName == strName); } public: void ResetRegions() { for (size_t nIndex = 0; nIndex < m_arrRegions.GetCount(); ++nIndex) { m_arrRegions[nIndex].SetComplete(); m_arrRegions[nIndex].CheckRect(); } } CRegion* GetRegion(const CString& strRegionName) { CRegion *pRegion = NULL; for (size_t nIndex = 0; nIndex < m_arrRegions.GetCount(); ++nIndex) { if (m_arrRegions[nIndex].IsEqualName(strRegionName)) { pRegion = &m_arrRegions[nIndex]; break; } } return pRegion; } CRegion** GetRegions(const CString& strRegionName, size_t& length) { CRegion **ppRegion = new CRegion*[m_arrRegions.GetCount()]; size_t i = 0; for (size_t nIndex = 0; nIndex < m_arrRegions.GetCount(); ++nIndex) { if (m_arrRegions[nIndex].IsEqualName(strRegionName)) { ppRegion[i++] = &m_arrRegions[nIndex]; } } length = i; return ppRegion; } public: // --- non-fo void Init(const REAL& fWidthL, const REAL& fHeightL, const REAL& fWidthMm, const REAL& fHeightMm, const CBounds& oBounds, const CBrush& oBrush) { m_fWidthL = fWidthL; m_fHeightL = fHeightL; m_oBounds.SetAsRectMm(fWidthMm, fHeightMm); m_fWidthPt = m_oBounds.GetRectPt().Width; m_fHeightPt = m_oBounds.GetRectPt().Height; for (size_t nIndex = 0; nIndex < m_arrRegions.GetCount(); ++nIndex) { m_arrRegions[nIndex].SetBounds(oBounds); } m_oBrush = oBrush; } private: void ReadRegions(XmlUtils::CXmlNode &oXmlNode, const bool& bMustInitRegions = true) { bool bSkip = true; m_oBounds.SetAsRectPt(m_fWidthPt, m_fHeightPt); RectF oPrevRectPt = RectF(); XmlUtils::CXmlNodes oNodes; if (oXmlNode.GetNodes(_T("*"), oNodes)) { INT iListLength = oNodes.GetCount(); for (INT iIndex = 0; iIndex < iListLength; ++iIndex) { XmlUtils::CXmlNode oNode; oNodes.GetAt(iIndex, oNode); if (oNode.GetAttribute(_T("hasCols")) != _T("")) { XmlUtils::CXmlNode oNodeCols; oNode.GetNode(_T("w:cols"), oNodeCols); int iColsCount = oNodeCols.ReadAttributeInt(_T("w:num"), 1); BOOL bEqualWidth = XmlUtils::GetBoolean(oNodeCols.GetAttribute(_T("w:equalWidth"), _T("true"))); double dSpace = oNodeCols.ReadAttributeInt(_T("w:space"), 720) / 20; double* dWidthCols = new double[iColsCount]; double* dSpaceCols = new double[iColsCount]; if (iColsCount != 1) { if (bEqualWidth == FALSE) { XmlUtils::CXmlNodes oNodeColGroup; if (oNodeCols.GetNodes(_T("w:col"), oNodeColGroup)) { int iGroupLength = oNodeColGroup.GetCount(); double dMarginLeft = 0; for (int iInd = 0; iInd < iGroupLength; ++iInd) { XmlUtils::CXmlNode oNodeCol; oNodeColGroup.GetAt(iInd, oNodeCol); dWidthCols[iInd] = oNodeCol.ReadAttributeDouble(_T("w:w"), 0) / 20; dSpaceCols[iInd] = oNodeCol.ReadAttributeDouble(_T("w:space"), 0) / 20; } } } else { double dWidth = (m_oBounds.GetRectPt().GetRight() - m_oBounds.GetRectPt().GetLeft() - dSpace * (iColsCount - 1)) / iColsCount; for (int iInd = 0; iInd < iColsCount; ++iInd) { dWidthCols[iInd] = dWidth; dSpaceCols[iInd] = dSpace; } } double dMarginLeft = 0; for (int iInd = 0; iInd < iColsCount; ++iInd) { AddRegion(oNode, dMarginLeft, dWidthCols[iInd], oPrevRectPt); dMarginLeft += (dWidthCols[iInd] + dSpaceCols[iInd]); } } else { AddRegion(oNode, oPrevRectPt); } delete [] dWidthCols; delete [] dSpaceCols; } else { AddRegion(oNode, oPrevRectPt); } } } /*XmlUtils::CXmlReader oReader; if (oReader.SetXmlString(oXmlNode.GetXml()) && oReader.ReadNodeList(_T("*"))) { INT iListLength = oReader.GetLengthList(); for (INT iIndex = 0; iIndex < iListLength; ++iIndex) { XmlUtils::CXmlNode oNode; oNode.FromXmlString(oReader.ReadNodeXml(iIndex)); m_arrRegions.Add(); m_arrRegions[iIndex].FromXmlNodeFo(oNode); m_arrRegions[iIndex].SetBounds(m_oBounds); m_arrRegions[iIndex].ApplyDisplayAlign(oPrevRectPt); } }*/ } void AddRegion(XmlUtils::CXmlNode oNode, double dMarginLeft, double dWidth, RectF& oPrevRectPt) { size_t iCount = m_arrRegions.GetCount(); m_arrRegions.Add(); m_arrRegions[iCount].FromXmlNodeFo(oNode); m_arrRegions[iCount].SetIsColumn(); CBounds cBounds = m_arrRegions[iCount].GetBounds(); cBounds.SetAsRectPt(m_oBounds.GetRectPt()); m_arrRegions[iCount].AddBounds(dMarginLeft, 0, cBounds.GetRectPt().GetRight() - cBounds.GetRectPt().GetLeft()- dMarginLeft - dWidth, 0); m_arrRegions[iCount].SetBounds(m_oBounds); m_arrRegions[iCount].ApplyDisplayAlign(oPrevRectPt); } void AddRegion(XmlUtils::CXmlNode oNode, RectF& oPrevRectPt) { size_t iCount = m_arrRegions.GetCount(); m_arrRegions.Add(); #ifdef AVS_LOG_DEBUG CRegion *p1 = &m_arrRegions[iCount]; #endif m_arrRegions[iCount].FromXmlNodeFo(oNode, true); m_arrRegions[iCount].SetBounds(m_oBounds); //m_arrRegions[iCount].ApplyDisplayAlign(oPrevRectPt); } }; class CLayoutMasterSet { private: CAtlArray m_arrSimplePageMasters; CAtlArray m_arrFlowMaps; CAtlArray m_arrPageSequenceMasters; public: // --- CLayoutMasterSet() : m_arrSimplePageMasters(), m_arrFlowMaps(), m_arrPageSequenceMasters() { } // --- ~CLayoutMasterSet() { Clear(); } // --- void Clear() { m_arrSimplePageMasters.RemoveAll(); m_arrFlowMaps.RemoveAll(); m_arrPageSequenceMasters.RemoveAll(); } // --- void FromXmlNode(XmlUtils::CXmlNode& oXmlNode, CDocumentManager& documentManager) { XmlUtils::CXmlNodes oPageTypeNodes; if (oXmlNode.GetNodes(_T("fo:simple-page-master"), oPageTypeNodes)) { INT iCount = oPageTypeNodes.GetCount(); for (INT iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oNode; oPageTypeNodes.GetAt(iIndex, oNode); m_arrSimplePageMasters.Add(); m_arrSimplePageMasters[iIndex].loadFromXml(oNode, documentManager); } } XmlUtils::CXmlNodes oPageMapNodes; if (oXmlNode.GetNodes(_T("fo:flow-map"), oPageMapNodes)) { INT iCount = oPageMapNodes.GetCount(); for (INT iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oNode; oPageMapNodes.GetAt(iIndex, oNode); m_arrFlowMaps.Add(); m_arrFlowMaps[m_arrFlowMaps.GetCount() - 1].FromXmlNode(oNode); } } XmlUtils::CXmlNodes oPageSequenceMasterNodes; if (oXmlNode.GetNodes(_T("fo:page-sequence-master"), oPageSequenceMasterNodes)) { INT iCount = oPageSequenceMasterNodes.GetCount(); for (INT iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oNode; oPageSequenceMasterNodes.GetAt(iIndex, oNode); m_arrPageSequenceMasters.Add(); m_arrPageSequenceMasters[m_arrPageSequenceMasters.GetCount() - 1].FromXmlNode(oNode); } } } // --- CSimplePageMaster* FindSimplePageMaster(const CString& strName) { size_t nPageTypesCount = m_arrSimplePageMasters.GetCount(); for (size_t nIndex = 0; nIndex < nPageTypesCount; ++nIndex) { if (m_arrSimplePageMasters[nIndex].IsEqualName(strName)) { return &m_arrSimplePageMasters[nIndex]; } } return NULL; } CFlowMap* FindFlowMap(const CString& strName) { size_t nPageMapsCount = m_arrFlowMaps.GetCount(); for (size_t nIndex = 0; nIndex < nPageMapsCount; ++nIndex) { if (m_arrFlowMaps[nIndex].IsEqualName(strName)) { return &m_arrFlowMaps[nIndex]; } } return NULL; } CPageSequenceMaster* FindPageSequenceMaster(const CString& strName) { size_t nPageSequenceMastersCount = m_arrPageSequenceMasters.GetCount(); for (size_t nIndex = 0; nIndex < nPageSequenceMastersCount; ++nIndex) { if ( m_arrPageSequenceMasters[nIndex].m_strName == strName ) { return &m_arrPageSequenceMasters[nIndex]; } } return NULL; } }; class CPage { private: CSimplePageMaster* m_pSimplePageMaster; CAtlArray m_arrLines; CAtlArray m_arrBlockBeginIndexes; int m_nFlowBeginIndex; int m_nFlowEndIndex; CAtlArray m_arrFLines; CAtlArray m_arrBlockFBeginIndexes; REAL m_fFootnoteStart; int m_iCurrentFootnoteIndex; CAtlArray m_arrGraphicLinesBeginIndexes; CAtlArray m_arrGraphicLines; int m_nGraphicLinesBeginIndex; int m_nGraphicLinesEndIndex; CAtlArray m_arrBackgroundBeginIndexes; CAtlArray m_arrBackgroundsRects; int m_nBackgroundBeginIndex; int m_nBackgroundEndIndex; CAreaManager m_oAreaManager; CAtlArray m_arrAnchors; int m_AnchorFirst; int m_AnchorBlockFirst; int m_AnchorLast; bool m_bFootnoteProcessing; bool m_bBodyProcessing; bool m_bIsEmptyBody; bool _withNonDummyLines; bool m_Continuous; float m_FilledHeight; float m_FooterHeight; float _footnoteHeight; bool _beginCell; CArray _lineCommands; public: CPage() : m_pSimplePageMaster(NULL), m_arrLines(), m_arrBlockBeginIndexes(), m_nFlowBeginIndex(0), m_nFlowEndIndex(0), m_nGraphicLinesBeginIndex(0), m_nGraphicLinesEndIndex(0), m_nBackgroundBeginIndex(0), m_nBackgroundEndIndex(0), m_arrFLines(), m_arrBlockFBeginIndexes(), m_fFootnoteStart(0.0f), m_iCurrentFootnoteIndex(-1), m_arrGraphicLines(), m_arrBackgroundsRects(), m_oAreaManager(), m_arrAnchors(), m_AnchorFirst(0), m_AnchorLast(0), m_AnchorBlockFirst(0), m_bFootnoteProcessing(false), m_bBodyProcessing(false), m_bIsEmptyBody(true), _withNonDummyLines(false), m_Continuous(false), m_FilledHeight(0.0f), m_FooterHeight(-1), _footnoteHeight(0), _beginCell(false) { } ~CPage() { Clear(); } void Clear() { m_pSimplePageMaster = NULL; size_t nLinesCount = m_arrLines.GetCount(); for (size_t nIndex = 0; nIndex < nLinesCount; ++nIndex) { RELEASEOBJECT(m_arrLines[nIndex]); } m_arrLines.RemoveAll(); m_arrBlockBeginIndexes.RemoveAll(); m_nFlowBeginIndex = 0; m_nFlowEndIndex = 0; size_t nFLinesCount = m_arrFLines.GetCount(); for (size_t nIndex = 0; nIndex < nFLinesCount; ++nIndex) { RELEASEOBJECT(m_arrFLines[nIndex]); } m_arrFLines.RemoveAll(); m_arrBlockFBeginIndexes.RemoveAll(); m_fFootnoteStart = 0.0f; m_iCurrentFootnoteIndex = -1; size_t nGraphicLinesCount = m_arrGraphicLines.GetCount(); for (size_t nIndex = 0; nIndex < nGraphicLinesCount; ++nIndex) { RELEASEOBJECT(m_arrGraphicLines[nIndex]); } m_nGraphicLinesBeginIndex = 0; m_nGraphicLinesEndIndex = 0; m_arrGraphicLines.RemoveAll(); size_t nBackgroundsRectsCount = m_arrBackgroundsRects.GetCount(); for (size_t nIndex = 0; nIndex < nBackgroundsRectsCount; ++nIndex) { RELEASEOBJECT(m_arrBackgroundsRects[nIndex]); } m_nBackgroundBeginIndex = 0; m_nBackgroundEndIndex = 0; m_arrBackgroundsRects.RemoveAll(); m_oAreaManager.Clear(); m_arrAnchors.RemoveAll(); m_AnchorFirst = 0; m_AnchorLast = 0; m_AnchorBlockFirst = 0; m_bFootnoteProcessing = false; m_Continuous = false; m_FilledHeight = 0.0f; m_FooterHeight = -1; _footnoteHeight = 0; _beginCell = false; } public: void ClearDerivedLines(int from) { for (size_t i = m_nFlowEndIndex; i != from; i--) m_arrLines.RemoveAt(i - 1); m_nFlowEndIndex = from; } void ClearDerivedGraphLines(int startIndex) { for (int i = m_nGraphicLinesEndIndex; i != startIndex; --i) m_arrGraphicLines.RemoveAt(i - 1); m_nGraphicLinesEndIndex = startIndex; } void ClearDerivedBackgrounds(int startIndex) { for (int i = m_nBackgroundEndIndex; i != startIndex; --i) m_arrBackgroundsRects.RemoveAt(i - 1); m_nBackgroundEndIndex = startIndex; } inline size_t GetLastLine() { return m_nFlowEndIndex; } inline int GetLastGraphLine() const { return (int)m_nGraphicLinesEndIndex; } inline int GetLastBackground() const { return (int)m_nBackgroundEndIndex; } inline void SetPageMaster(CSimplePageMaster* pSimplePageMaster) { m_pSimplePageMaster = pSimplePageMaster; m_pSimplePageMaster->ResetRegions(); } inline REAL GetWidthPt() const { if (m_pSimplePageMaster) return m_pSimplePageMaster->GetWidthPt(); else return 0; } inline REAL GetHeightPt() const { if (m_pSimplePageMaster) return m_pSimplePageMaster->GetHeightPt(); else return 0; } inline REAL GetWidthL() { return m_pSimplePageMaster->GetWidthL(); } inline REAL GetHeightL() { return m_pSimplePageMaster->GetHeightL(); } inline REAL GetWidthMm() const { return GetWidthPt() * (25.4f / 72.0f); } inline REAL GetHeightMm() const { return GetHeightPt() * (25.4f / 72.0f); } inline CAreaManager* GetAreaManager() { return &m_oAreaManager; } inline CAtlArray& GetRefLines () { return m_arrLines; } int getBlockCount() const { return (int)m_arrBlockBeginIndexes.GetCount(); } void getBlockMetric(const int& block, float& height, float& offset) { height = 0; offset = 0; int blockCount = (int)m_arrBlockBeginIndexes.GetCount(); if (block < 0 || block >= blockCount) return; int firstLine = m_arrBlockBeginIndexes[block]; int lastLine = block + 1 == blockCount ? m_arrLines.GetCount() - 1 : m_arrBlockBeginIndexes[block + 1] - 1; if (firstLine >= (int)m_arrLines.GetCount()) return; float bottom = m_arrLines[lastLine]->GetRect().GetBottom(); offset = m_arrLines[firstLine]->GetRect().GetTop(); height = bottom - offset; } public: inline void StartFootnote() { m_bFootnoteProcessing = true; m_iCurrentFootnoteIndex = -1; if (m_arrFLines.GetCount() != 0) { m_iCurrentFootnoteIndex = (int)m_arrFLines.GetCount() - 1; } } inline void FinishFootnote() { m_bFootnoteProcessing = false; size_t nLastIndex = m_arrFLines.GetCount() - 1; if (nLastIndex - m_iCurrentFootnoteIndex > 0) { REAL fOffset = m_arrFLines[m_iCurrentFootnoteIndex + 1]->GetRect().Y - m_fFootnoteStart; for (size_t nIndex = m_iCurrentFootnoteIndex + 1; nIndex <= nLastIndex; ++nIndex) { m_arrFLines[nIndex]->MoveOn(0, -fOffset); } m_fFootnoteStart += m_arrFLines[nLastIndex]->GetRect().GetBottom() - m_arrFLines[m_iCurrentFootnoteIndex + 1]->GetRect().Y; } } inline void StartBlock() { if (!m_bFootnoteProcessing) { m_arrBlockBeginIndexes.Add((unsigned int)m_arrLines.GetCount()); m_arrBlockFBeginIndexes.Add((unsigned int)m_arrFLines.GetCount()); m_arrGraphicLinesBeginIndexes.Add((unsigned int)m_arrGraphicLines.GetCount()); m_arrBackgroundBeginIndexes.Add((unsigned int)m_arrBackgroundsRects.GetCount()); m_AnchorBlockFirst = m_AnchorLast; } } inline void FinishBlock() { } inline void StartBody() { m_bBodyProcessing = true; } inline void FinishBody() { m_bBodyProcessing = false; } inline bool IsEmptyBody() { return (m_bIsEmptyBody && !m_bFootnoteProcessing); } inline bool isWithNonDummyLines() const { return _withNonDummyLines; } inline void DeleteBlocks(int number) { while (number-- > 0) { int lastBlock = (int)m_arrBlockBeginIndexes.GetCount() - 1; if (lastBlock < 0) break; int blockFirstLine = (int)m_arrBlockBeginIndexes[lastBlock]; int lineCount = (int)m_arrLines.GetCount(); if (blockFirstLine < lineCount) { for (int index = blockFirstLine; index < (int)lineCount; ++index) RELEASEOBJECT(m_arrLines[index]); m_arrLines.RemoveAt(blockFirstLine, lineCount - blockFirstLine); m_nFlowEndIndex = blockFirstLine; } m_arrBlockBeginIndexes.RemoveAt(lastBlock); int blockFirstFootLine = (int)m_arrBlockFBeginIndexes[lastBlock]; int footLineCount = (int)m_arrFLines.GetCount(); if (blockFirstFootLine < footLineCount) { for (int index = blockFirstFootLine; index < footLineCount; ++index) RELEASEOBJECT(m_arrFLines[index]); m_arrFLines.RemoveAt(blockFirstFootLine, footLineCount - blockFirstFootLine); } m_arrBlockFBeginIndexes.RemoveAt(lastBlock); int blockFirstGraphLine = (int)m_arrGraphicLinesBeginIndexes[lastBlock]; int graphLineCount = (int)m_arrGraphicLines.GetCount(); if (blockFirstGraphLine < graphLineCount) { for (int index = blockFirstGraphLine; index < graphLineCount; ++index) RELEASEOBJECT(m_arrGraphicLines[index]); m_arrGraphicLines.RemoveAt(blockFirstGraphLine, graphLineCount - blockFirstGraphLine); m_nGraphicLinesEndIndex = blockFirstGraphLine; } int blockFirstBackground = (int)m_arrBackgroundBeginIndexes[lastBlock]; int backgroundCount = (int)m_arrBackgroundsRects.GetCount(); if (blockFirstBackground < backgroundCount) { for (int index = blockFirstBackground; index < backgroundCount; ++index) RELEASEOBJECT(m_arrBackgroundsRects[index]); m_arrBackgroundsRects.RemoveAt(blockFirstBackground, backgroundCount - blockFirstBackground); m_nBackgroundEndIndex = blockFirstBackground; } } } inline void AddLine(CLine* line) { if (m_bFootnoteProcessing) m_arrFLines.Add(line); else { if (_beginCell) { _beginCell = false; line->setStartCell(); } if (m_bBodyProcessing && !line->isDummy()) { m_bIsEmptyBody = false; _withNonDummyLines = true; } setRendererCommandsToLine(line); m_arrLines.Add(line); ++m_nFlowEndIndex; } } void AddAnchorContent(CAtlArray &arrAnchors) { size_t anchorCount = arrAnchors.GetCount(); if (anchorCount && !m_bFootnoteProcessing && m_bBodyProcessing) m_bIsEmptyBody = false; size_t nAnchorIndex = m_arrAnchors.GetCount(); RectF oPageRectPt = m_pSimplePageMaster->GetRectPt(); for (size_t nIndex = 0; nIndex < anchorCount; ++nIndex) { CAlternate2* anchor = arrAnchors[nIndex]; if (!arrAnchors[nIndex]->Related()) continue; float zIndex = arrAnchors[nIndex]->getZIndex(); int count = (int) m_arrAnchors.GetCount(); int insIndex = 0; for (; insIndex < count; ++insIndex) if (zIndex < m_arrAnchors[insIndex]->getZIndex()) break; if (insIndex == count) m_arrAnchors.Add(arrAnchors[nIndex]); else m_arrAnchors.InsertAt((size_t) insIndex, arrAnchors[nIndex]); arrAnchors[nIndex]->setInHeader(!m_bBodyProcessing); m_oAreaManager.AddWrapPolygon(arrAnchors[nIndex]->Points(), arrAnchors[nIndex]->DistanceLeft(), arrAnchors[nIndex]->DistanceRight()); arrAnchors[nIndex]->Placed(true); ++m_AnchorLast; } } void RemoveAnchorContent(int position) { if (m_AnchorBlockFirst == m_AnchorLast) return; int index = m_AnchorLast - 1; while (index >= m_AnchorBlockFirst) { if (m_arrAnchors[index]->InlinePosition() != position) break; m_arrAnchors[index]->Placed(false); --index; } ++index; if (index != m_AnchorLast) { m_arrAnchors.RemoveAt(index, m_AnchorLast - index); m_AnchorLast = (int)m_arrAnchors.GetCount(); } } void AddGraphicLine(CGraphicLine *pGraphicLine) { m_arrGraphicLines.Add(pGraphicLine); ++m_nGraphicLinesEndIndex; } void AddBackgroundRect(CBackgroundRect *pBackgroundRect) { m_arrBackgroundsRects.Add(pBackgroundRect); ++m_nBackgroundEndIndex; } // --- inline void StartPrintingFlow() { if (!m_bFootnoteProcessing) { m_nFlowBeginIndex = (int) m_arrLines.GetCount(); m_nFlowEndIndex = (int) m_arrLines.GetCount(); m_nGraphicLinesBeginIndex = (int) m_arrGraphicLines.GetCount(); m_nGraphicLinesEndIndex = (int) m_arrGraphicLines.GetCount(); m_nBackgroundBeginIndex = (int) m_arrBackgroundsRects.GetCount(); m_nBackgroundEndIndex = (int) m_arrBackgroundsRects.GetCount(); m_AnchorFirst = (int) m_arrAnchors.GetCount(); m_AnchorLast = (int) m_arrAnchors.GetCount(); } } inline void FinishPrintingFlow() { if (!m_bFootnoteProcessing) { m_nFlowBeginIndex = 0; m_nFlowEndIndex = 0; m_nGraphicLinesBeginIndex = 0; m_nGraphicLinesEndIndex = 0; m_nBackgroundBeginIndex = 0; m_nBackgroundEndIndex = 0; m_AnchorFirst = 0; m_AnchorLast = 0; } } void MoveFlowOn(const REAL &fDeltaX, const REAL &fDeltaY) { if (!m_bFootnoteProcessing) { for (int nIndex = m_nGraphicLinesBeginIndex; nIndex < (int) m_arrGraphicLines.GetCount(); ++nIndex) { m_arrGraphicLines[nIndex]->MoveOn(fDeltaX * 25.4 / 72, fDeltaY * 25.4 / 72); } for (int nIndex = m_nBackgroundBeginIndex; nIndex < (int) m_arrBackgroundsRects.GetCount(); ++nIndex) { m_arrBackgroundsRects[nIndex]->MoveOn(fDeltaX * 25.4 / 72, fDeltaY * 25.4 / 72); } for (int nIndex = m_nFlowBeginIndex; nIndex < m_nFlowEndIndex; ++nIndex) { m_arrLines[nIndex]->MoveOn(fDeltaX, fDeltaY); } for (int i = m_AnchorFirst; i < m_AnchorLast; ++i) if (m_arrAnchors[i]->AnchoredToRegion()) m_arrAnchors[i]->MoveOn(fDeltaX, fDeltaY); } } public: void beginCell() { _beginCell = true; } void endCell() { _beginCell = false; if (m_arrLines.GetCount() > 0) { int last = (int) m_arrLines.GetCount() - 1; m_arrLines[last]->setFinishCell(); } } // --- void Draw(IAVSRenderer* pRenderer, CDocumentManager& documentManager, const float& fCompleteness) { documentManager.SetPage(*this); for (size_t nIndex = 0; nIndex < m_arrBackgroundsRects.GetCount(); ++nIndex) m_arrBackgroundsRects[nIndex]->Draw(pRenderer, fCompleteness); for (size_t nIndex = 0; nIndex < m_arrAnchors.GetCount(); ++nIndex) { CAlternate2* anchor = m_arrAnchors[nIndex]; if (anchor->getZIndex() < 0) anchor->Draw(pRenderer, documentManager, fCompleteness); } DrawLines(pRenderer, documentManager, fCompleteness); drawFootnoteLines(pRenderer, documentManager, fCompleteness); for (size_t nIndex = 0; nIndex < m_arrAnchors.GetCount(); ++nIndex) { CAlternate2* anchor = m_arrAnchors[nIndex]; if (anchor->getZIndex() >= 0) anchor->Draw(pRenderer, documentManager, fCompleteness); } for (size_t nIndex = 0; nIndex < m_arrGraphicLines.GetCount(); ++nIndex) m_arrGraphicLines[nIndex]->Draw(pRenderer, fCompleteness); } void Draw(IAVSRenderer* renderer, CDocumentManager& documentManager, const int& block, const float& completeness) { int blockCount = (int)m_arrBlockBeginIndexes.GetCount(); if (block < 0 || block >= blockCount) return; int firstLine = m_arrBlockBeginIndexes[block]; int lastLine = block + 1 == blockCount ? m_arrLines.GetCount() - 1 : m_arrBlockBeginIndexes[block + 1] - 1; if (firstLine >= (int)m_arrLines.GetCount()) return; for (int i = firstLine; i <= lastLine; ++i) m_arrLines[i]->Draw(renderer, documentManager, completeness); } void DrawLines(IAVSRenderer* renderer, CDocumentManager& documentManager, const float& completeness) { for (size_t index = 0; index < m_arrLines.GetCount(); ++index) m_arrLines[index]->Draw(renderer, documentManager, completeness); } void drawFootnoteLines(IAVSRenderer* renderer, CDocumentManager& documentManager, const float& completeness) { IAVSRenderer2* renderer2 = NULL; if (!SUCCEEDED(renderer->QueryInterface(__UUIDOF__IAVSRENDERER2, (void**)&renderer2))) renderer2 = NULL; if (renderer2 != NULL) renderer->BeginCommand(c_nFootnote); if (m_fFootnoteStart != 0.0f) { CRegion* pRegionBody = GetRegion(_T("xsl-region-body")); RectF originalRect = pRegionBody->GetOriginalRectPt(); REAL fRegionBottom = originalRect.GetBottom(); if ((m_FooterHeight >= 0) && (m_FooterHeight < fRegionBottom)) fRegionBottom = m_FooterHeight; CGraphicLine* grL = new CGraphicLine(); double koef = 25.4f / 72.0f; //TODO grL->SetStartPoint( originalRect.GetLeft() * koef, (fRegionBottom - m_fFootnoteStart)*koef - 1); grL->SetFinishPoint( originalRect.GetLeft() * koef + 50, (fRegionBottom - m_fFootnoteStart)*koef - 1); CPen pen; pen.m_oPen.Size = 0.2; grL->SetPen(pen); AddGraphicLine(grL); for (size_t nIndex = 0; nIndex < m_arrFLines.GetCount(); ++nIndex) m_arrFLines[nIndex]->MoveOn(0, fRegionBottom - m_fFootnoteStart); m_fFootnoteStart = 0.0f; } for (size_t nIndex = 0; nIndex < m_arrFLines.GetCount(); ++nIndex) m_arrFLines[nIndex]->Draw(renderer, documentManager, completeness); if (renderer2 != NULL) renderer->EndCommand(c_nFootnote); RELEASEINTERFACE(renderer2); } // --- void GetLines(CAtlArray& lines) { lines.Copy(m_arrLines); m_arrLines.RemoveAll(); } inline CRegion* GetRegion(const CString& strRegionName) { return m_pSimplePageMaster->GetRegion(strRegionName); } inline CRegion** GetRegions(const CString& strRegionName, size_t& iLength) { return m_pSimplePageMaster->GetRegions(strRegionName, iLength); } public: bool Continuous() const { return m_Continuous; } void Continuous(const bool& continuous) { m_Continuous = continuous; } float FilledHeight() const { return m_FilledHeight; } void FilledHeight(const float& filledHeight) { m_FilledHeight = filledHeight; } float FooterHeight() { return m_FooterHeight; } void FooterHeight(const float& footerHeight) { m_FooterHeight = footerHeight; } void Merge(CPage* page) { m_arrLines.Append(page->m_arrLines); m_arrFLines.Append(page->m_arrFLines); m_arrGraphicLines.Append(page->m_arrGraphicLines); m_arrBackgroundsRects.Append(page->m_arrBackgroundsRects); m_arrAnchors.Append(page->m_arrAnchors); } void changeFootnoteHeight(const float& footnoteHeight) { _footnoteHeight += footnoteHeight; } float getFootnoteHeight() const { return _footnoteHeight; } public: bool InFootnoteProcess() { return m_bFootnoteProcessing; } public: void addRendererCommand(const SharedPtr& command , const bool& toLast = false) { if (toLast) if (removeEmptyCommands(command)) return; _lineCommands.Add(command); if (toLast) { int last = (int) m_arrLines.GetCount() - 1; if (last >= 0) setRendererCommandsToLine(m_arrLines[last]); } } bool removeEmptyCommands(const SharedPtr& command) { int commandCount = (int) _lineCommands.GetCount(); if (commandCount > 0 && command->getType() == RendererCommand::END && command->getName() != RendererCommand::COMMON) { RendererCommand::RendererCommandName name = command->getName(); for (int i = commandCount - 1; i >= 0; --i) if (_lineCommands[i]->getName() == name) if (_lineCommands[i]->getType() == RendererCommand::BEGIN) { _lineCommands.RemoveAt(i, commandCount - i); return true; } } return false; } void setRendererCommandsToLine(CLine* line) { if (_lineCommands.GetCount() != 0) { setAttrsOfRendererCommands(line); line->setRendererCommands(_lineCommands); _lineCommands.RemoveAll(); } } void setAttrsOfRendererCommands(CLine* line) { for (int i = 0; i < (int) _lineCommands.GetCount(); ++i) _lineCommands[i]->setRect(line->GetRect()); } public: static CPage* createNew(const CPage* prevPage = NULL) { CPage* page = new CPage(); if (prevPage != NULL) { page->_lineCommands.Copy(prevPage->_lineCommands); page->_footnoteHeight = prevPage->_footnoteHeight; } return page; } }; public: class TextMeasurer2 { CTextMeasurer* tm; int block; float height; float offset; public: TextMeasurer2(CTextMeasurer* tm = NULL, const int& block = 0, const float& height = 0, const float& offset = 0) : tm(tm), block(block) , height(height), offset(offset) {} void DrawFirstPage(IAVSRenderer* renderer, const float& completeness) { if (tm) tm->DrawFirstPage(renderer, completeness, block); } float GetHeight() const { return height; } float GetOffset() const { return offset; } }; CLayoutMasterSet m_oLayoutMasterSet; CArray m_arrPageSequence; INT m_iPageSequenceIndex; bool m_bIsFo; REAL m_fCompleteness; IAVSRenderer* m_pRenderer; CDocumentManager m_DocumentManager; IAVSFontManager* m_pFontManager; bool handlesFontManager; CAtlArray m_arrPages; size_t m_nCurrentPage; REAL m_fWidthMm; REAL m_fHeightMm; CString m_strText; bool m_bIsFormated; bool m_bVertical; bool m_bRightToLeft; double m_dAngle; long m_lFlags; RectF m_oLayoutRect; CBrush m_oBrush; CBackgroundProperties m_oBGPage; public: CTextMeasurer() : m_oLayoutMasterSet(), m_arrPageSequence(), m_iPageSequenceIndex(0), m_bIsFo(false), m_fCompleteness(1.0f), m_pRenderer(NULL), m_DocumentManager(), m_pFontManager(NULL), handlesFontManager(true), m_arrPages(), m_nCurrentPage(0), m_fWidthMm(0), m_fHeightMm(0), m_strText(_T("")), m_bIsFormated(false), m_bVertical(false), m_bRightToLeft(false), m_dAngle(0.0), m_lFlags(0), m_oBGPage(), m_oLayoutRect() { InitFontManager(); } CTextMeasurer(IAVSFontManager* fm) : m_oLayoutMasterSet(), m_arrPageSequence(), m_iPageSequenceIndex(0), m_bIsFo(false), m_fCompleteness(1.0f), m_pRenderer(NULL), m_DocumentManager(), m_pFontManager(fm), handlesFontManager(false), m_arrPages(), m_nCurrentPage(0), m_fWidthMm(0), m_fHeightMm(0), m_strText(_T("")), m_bIsFormated(false), m_bVertical(false), m_bRightToLeft(false), m_dAngle(0.0), m_lFlags(0), m_oBGPage(), m_oLayoutRect() {} ~CTextMeasurer() { InternalClear(); if (handlesFontManager) RELEASEINTERFACE(m_pFontManager); } public: virtual INT InternalGetRequiredStreamSize() { return 0; } virtual void InternalToXmlAttributes(XmlUtils::CXmlWriter& oXmlWriter) { } virtual void InternalFromXmlNode(XmlUtils::CXmlNode &oXmlNode) { InternalClear(); #ifdef TME_DEBUG CString strXml = oXmlNode.GetXml(); FILE *pDebugInfoFile; fopen_s(&pDebugInfoFile, "c:\\temp\\debug_fo_doc.xml", "w"); fwprintf_s(pDebugInfoFile, L"%s", strXml); fclose(pDebugInfoFile); #endif IWorker_OnProgress(0.0f); CItemManager *pItemManager = &m_DocumentManager.m_ItemManager; m_DocumentManager.m_FontManager = m_pFontManager; #ifdef TME_DEBUG_VSXML oXmlNode.FromXmlFile(_T("c:\\temp\\vs.xml")); #endif if (oXmlNode.GetAttributeOrValue(_T("xmlns:fo"), _T("")) == _T("http://www.w3.org/1999/XSL/Format")) { pItemManager->SetIsFo(TRUE); InternalFromFoXml(oXmlNode); } else { pItemManager->SetIsFo(FALSE); InternalFromNonFoXml(oXmlNode); } IWorker_OnProgress(0.1f); } void InternalFromNonFoXml2(XmlUtils::CXmlNode &oXmlNode, LONG& lMode, double dWidthMM, double dHeightMM) { InternalClear(); IWorker_OnProgress(0.0f); CItemManager *pItemManager = &m_DocumentManager.m_ItemManager; pItemManager->SetIsFo(FALSE); m_bIsFo = FALSE; SetDefaultLayoutMasterSet(m_oLayoutMasterSet); m_strText = oXmlNode.GetAttributeOrValueExt(_T("text"), _T("")); FromXmlString(m_strText); if (m_strText == _T("")) { m_bIsFormated = TRUE; return; } m_dAngle = 0; m_lFlags = 0; m_bVertical = 0; m_bRightToLeft = 0; REAL fWidthL = 1000; REAL fHeightL = 1000; m_fWidthMm = (REAL)dWidthMM; m_fHeightMm = (REAL)dHeightMM; pItemManager->SetWidthL(fWidthL); pItemManager->SetHeightL(fHeightL); REAL fMmToPt = 72.0f / 25.4f; pItemManager->SetMultiplierX(m_fWidthMm * fMmToPt); pItemManager->SetMultiplierY(m_fHeightMm * fMmToPt); CSimplePageMaster *pSimplePageMaster = m_oLayoutMasterSet.FindSimplePageMaster(_T("SPM")); m_oLayoutRect.X = (REAL)(dWidthMM / 2.0 - 10000); m_oLayoutRect.Width = (REAL)(20000); m_oLayoutRect.Y = (REAL)(dHeightMM / 2.0 - 10000); m_oLayoutRect.Height = (REAL)(20000); if ((m_oLayoutRect.Width == 0) || (m_oLayoutRect.Height == 0)) { InternalClear(); m_bIsFormated = TRUE; return; } CBounds oBounds; oBounds.SetAsRectMm(m_oLayoutRect); pSimplePageMaster->Init(fWidthL, fHeightL, m_fWidthMm, m_fHeightMm, oBounds, m_oBrush); CTextAttributes oAttributes; XmlUtils::CXmlNode oAttributeNode; if (oXmlNode.GetNode(_T("Attributes"), oAttributeNode)) oAttributes.FromXmlNode(oAttributeNode); CAtlArray arPFs; CBlockAttributes *pParagraph = new CBlockAttributes(); pParagraph->FromXmlNode(oAttributeNode, m_DocumentManager); pParagraph->m_lCount = m_strText.GetLength(); //pParagraph->m_nTextAlignment = oAttributes.m_nTextAlignmentHorizontal; arPFs.Add(pParagraph); arPFs[0]->m_bIsFirst = true; CAtlArray arCFs; CCharacter *pCharacter = new CCharacter(); pCharacter->FromXmlNode(oXmlNode); pCharacter->m_lCount = m_strText.GetLength(); pCharacter->m_oAttributes = oAttributes; arCFs.Add(pCharacter); m_arrPageSequence.Add(new CPageSequence()); SetDefaultPageSequence(*m_arrPageSequence[0]); CFlow* pFirstFlow = m_arrPageSequence[0]->GetFirstFlow(); pFirstFlow->SetAlignVertical((CAlignVertical)oAttributes.m_nTextAlignmentVertical); if (!Normalize(&arPFs, &arCFs, pFirstFlow->GetBlocks())) { InternalClear(); } m_arrPages.RemoveAll(); } virtual void InternalClear() { m_oLayoutMasterSet.Clear(); for (int i = 0; i < (int) m_arrPageSequence.GetCount(); ++i) if (m_arrPageSequence[i]) delete m_arrPageSequence[i]; m_arrPageSequence.RemoveAll(); m_iPageSequenceIndex = 0; m_bIsFo = false; m_fCompleteness = 1.0f; m_pRenderer = NULL; m_DocumentManager.Clear(); for (size_t nIndex = 0; nIndex < m_arrPages.GetCount(); ++nIndex) { RELEASEOBJECT(m_arrPages[nIndex]); } m_arrPages.RemoveAll(); m_nCurrentPage = 0; m_fWidthMm = 0; m_fHeightMm = 0; m_strText = _T(""); m_bIsFormated = FALSE; m_bVertical = FALSE; m_bRightToLeft = FALSE; m_dAngle = 0.0f; m_lFlags = 0; m_oLayoutRect = RectF(); } public: void IWorker_Resume() { } void IWorker_Pause() { } void IWorker_Stop() { } void IWorker_OnNewPage(double dWidthMm, double dHeightMm) { } void IWorker_OnCompletePage() { } void IWorker_OnProgress(double dCompleteness) { double d = dCompleteness; } public: void SetRenderer(IAVSRenderer *pRenderer) { m_pRenderer = pRenderer; } bool IsFormated() { return true; } void RotateRect(RectF& oRect) { REAL fWidth = oRect.Width; REAL fHeight = oRect.Height; REAL fCenterX = oRect.X + fWidth / 2; REAL fCenterY = oRect.Y + fHeight / 2; oRect.Width = fHeight; oRect.Height = fWidth; oRect.X = fCenterX - fHeight / 2; oRect.Y = fCenterY - fWidth / 2; } public: void InitDrawText(IAVSRenderer *pRenderer, REAL fWidhtPix, REAL fHeightPix) { } bool DrawText(IAVSRenderer* renderer, const float& completeness , const bool& transform = true, const bool& draw = true, const int& block = -1) { #ifdef TME_EMPTY_DRAWING return true; #endif if (m_bIsFormated && (m_arrPages.GetCount() <= 0)) return true; if (!m_bIsFormated) { m_DocumentManager.RendererType(renderer); CGrapher* grapher = new CGrapher(); grapher->DocumentManager(&m_DocumentManager); grapher->FontManager(m_pFontManager); int lastPage = (int) m_arrPages.GetCount() - 1; CPage* prevPage = (lastPage != -1) ? m_arrPages[lastPage] : NULL; CPage* newPage = (*m_arrPageSequence[m_iPageSequenceIndex]).NewPage(grapher, prevPage); if ((m_iPageSequenceIndex == (int)m_arrPageSequence.GetCount() - 1) || !(*m_arrPageSequence[m_iPageSequenceIndex + 1]).Continuous()) (*m_arrPageSequence[m_iPageSequenceIndex]).ReWriteColumns(false); bool complete = (*m_arrPageSequence[m_iPageSequenceIndex]).FillPage(*newPage, grapher); if (complete) { while (m_iPageSequenceIndex < (int)m_arrPageSequence.GetCount() - 1) { ++m_iPageSequenceIndex; if ((*m_arrPageSequence[m_iPageSequenceIndex]).Continuous()) { (*m_arrPageSequence[m_iPageSequenceIndex]).ContinuePage(*newPage); if ((m_iPageSequenceIndex == (int)m_arrPageSequence.GetCount() - 1) || !(*m_arrPageSequence[m_iPageSequenceIndex + 1]).Continuous()) (*m_arrPageSequence[m_iPageSequenceIndex]).ReWriteColumns(false); complete = (*m_arrPageSequence[m_iPageSequenceIndex]).FillPage(*newPage, grapher); if (!complete) break; } else { complete = false; break; } } } if (complete && (m_iPageSequenceIndex == (int)m_arrPageSequence.GetCount() - 1)) m_bIsFormated = true; RELEASEOBJECT(grapher); if (!newPage->IsEmptyBody()) { m_arrPages.Add(newPage); m_nCurrentPage = m_arrPages.GetCount() - 1; if (draw) DrawPage(newPage, renderer, completeness, transform, block); if (m_bIsFo) Progress(0.0f); else Progress(1.0f); } if (m_bIsFo && m_bIsFormated) { Progress(1.0f); SendLinkerXml(renderer); } } return m_bIsFormated; } void DrawTextInRect(BSTR bstrText, const RectF& textRect, IAVSRenderer* renderer, const NSStructures::CFont& font, const NSStructures::CBrush& brush, const NSStructures::CFormat& format, ITextPainter* textPainter) { CItemManager* itemManager = &m_DocumentManager.m_ItemManager; m_DocumentManager.m_FontManager = m_pFontManager; m_DocumentManager.m_TextPainter = textPainter; itemManager->SetWrapFlags(format.WordWrapBySymbol); CRegion textRegion; textRegion.FromRectMm(textRect); CPage page; CGrapher* grapher = new CGrapher(); grapher->FontManager(m_pFontManager); grapher->DocumentManager(&m_DocumentManager); CBlock block; CString text(bstrText); block.FromString(text, grapher, font, brush, format); page.StartPrintingFlow(); block.FillRegion(textRegion, page, false, grapher); float offset = textRegion.GetRegionHeightPt(); switch (format.StringAlignmentVertical) { case 1 : offset /= 2; break; case 0 : offset = 0; break; } page.MoveFlowOn(0, offset); page.Draw(renderer, m_DocumentManager, 1.0f); RELEASEOBJECT(grapher); } void DrawFirstPage(IAVSRenderer* renderer, const float& completeness, const int& block = -1) { if (m_arrPages.GetCount()) DrawPage(m_arrPages[0], renderer, completeness, false, block); else DrawText(renderer, completeness, false, true, block); } void PrepareFirstPage(IAVSRenderer* renderer) { DrawText(renderer, 0, false, false); } void TruncateByBlocks(CArray& blockMeasurers, const bool& removeEmpty = false) { blockMeasurers.RemoveAll(); if (m_arrPages.GetCount() == 0) return; CPage& page = *m_arrPages[0]; float height, offset; for (int i = 0; i < m_arrPages[0]->getBlockCount(); ++i) { page.getBlockMetric(i, height, offset); if (removeEmpty && height == 0) continue; blockMeasurers.Add(TextMeasurer2(this, i, height, offset)); } } private: void InternalFromFoXml(XmlUtils::CXmlNode &oXmlNode) { m_bIsFo = true; XmlUtils::CXmlNode oDocInfoNode; if (oXmlNode.GetNode(_T("fo:doc-info"), oDocInfoNode)) m_DocumentManager.loadFromXml(oDocInfoNode); //int iPageCount = oDocInfoNode.ReadAttributeInt(_T("pages"), 0); //m_DocumentManager.SetPageCount(iPageCount); XmlUtils::CXmlNode fontTable; if (oDocInfoNode.GetNode(_T("font-table"), fontTable)) m_DocumentManager.FontTableFromXml(fontTable); m_DocumentManager.UseHtmlSpacing(XmlUtils::GetBoolean(oDocInfoNode.GetAttribute(_T("useHtmlSpacing"), _T("true"))) == TRUE); XmlUtils::CXmlNode oBackgroundNode; oDocInfoNode.GetNode(_T("w:background"), oBackgroundNode); m_oBGPage.PageBGFromXml(oBackgroundNode); XmlUtils::CXmlNode oLayoutMasterSetNode; oXmlNode.GetNode(_T("fo:layout-master-set"), oLayoutMasterSetNode); m_oLayoutMasterSet.Clear(); m_oLayoutMasterSet.FromXmlNode(oLayoutMasterSetNode, m_DocumentManager); m_arrPageSequence.RemoveAll(); CPageSequence* prev = NULL; XmlUtils::CXmlNodes oPageSequenceNodes; oXmlNode.GetNodes(_T("fo:page-sequence"), oPageSequenceNodes); for (INT iIndex = 0; iIndex < oPageSequenceNodes.GetCount(); ++iIndex) { m_arrPageSequence.Add(new CPageSequence()); (*m_arrPageSequence[iIndex]).SetLayoutMasterSet(&m_oLayoutMasterSet); (*m_arrPageSequence[iIndex]).setPrev(prev); prev = m_arrPageSequence[iIndex]; XmlUtils::CXmlNode oPageSequenceNode; oPageSequenceNodes.GetAt(iIndex, oPageSequenceNode); (*m_arrPageSequence[iIndex]).loadFromXml(oPageSequenceNode, m_DocumentManager); } m_arrPages.RemoveAll(); } void InternalFromNonFoXml(XmlUtils::CXmlNode &oXmlNode) { m_bIsFo = FALSE; m_DocumentManager.UseHtmlSpacing(false); SetDefaultLayoutMasterSet(m_oLayoutMasterSet); m_strText = oXmlNode.GetAttributeOrValueExt(_T("text"), _T("")); FromXmlString(m_strText); if (m_strText == _T("")) { m_bIsFormated = TRUE; return; } m_dAngle = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("angle"), _T("0"))); m_lFlags = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("flags"), _T("0"))); m_bVertical = (0 != XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("vertical"), _T("0")))); m_bRightToLeft = (0 != XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("righttoleft"), _T("0")))); REAL fWidthL = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("widthl"), _T("0"))); REAL fHeightL = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("heightl"), _T("0"))); m_fWidthMm = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("widthmm"), _T("0"))); m_fHeightMm = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("heightmm"), _T("0"))); CItemManager *pItemManager = &m_DocumentManager.m_ItemManager; pItemManager->SetWidthL(fWidthL); pItemManager->SetHeightL(fHeightL); REAL fMmToPt = 72.0f / 25.4f; pItemManager->SetMultiplierX(m_fWidthMm * fMmToPt); pItemManager->SetMultiplierY(m_fHeightMm * fMmToPt); CSimplePageMaster *pSimplePageMaster = m_oLayoutMasterSet.FindSimplePageMaster(_T("SPM")); m_oLayoutRect.X = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("left"), _T("0"))); m_oLayoutRect.Width = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("right"), _T("0"))) - m_oLayoutRect.X; m_oLayoutRect.Y = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("top"), _T("0"))); m_oLayoutRect.Height = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("bottom"), _T("0"))) - m_oLayoutRect.Y; if ((m_oLayoutRect.Width == 0) || (m_oLayoutRect.Height == 0)) { InternalClear(); m_bIsFormated = TRUE; return; } if (m_bVertical == TRUE) { RotateRect(m_oLayoutRect); m_dAngle = 90.0f; m_lFlags = 0; } CBounds oBounds; oBounds.SetAsRectMm(m_oLayoutRect); pSimplePageMaster->Init(fWidthL, fHeightL, m_fWidthMm, m_fHeightMm, oBounds, m_oBrush); CTextAttributes oAttributes; XmlUtils::CXmlNode oAttributeNode; if (oXmlNode.GetNode(_T("Attributes"), oAttributeNode)) { oAttributes.FromXmlNode(oAttributeNode); } CAtlArray arPFs; XmlUtils::CXmlNodes oNodesPFs; if (oXmlNode.GetNodes(_T("Paragraph"), oNodesPFs)) { INT iCount = oNodesPFs.GetCount(); for (INT iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oNode; oNodesPFs.GetAt(iIndex, oNode); arPFs.Add(new CBlockAttributes()); arPFs[iIndex]->m_nTextAlignment = oAttributes.m_nTextAlignmentHorizontal; arPFs[iIndex]->FromXmlNode(oNode, m_DocumentManager); } if (iCount == 0) { CBlockAttributes *pParagraph = new CBlockAttributes(); pParagraph->FromXmlNode(oXmlNode, m_DocumentManager); pParagraph->m_lCount = m_strText.GetLength(); pParagraph->m_nTextAlignment = oAttributes.m_nTextAlignmentHorizontal; arPFs.Add(pParagraph); } arPFs[0]->m_bIsFirst = TRUE; } CAtlArray arCFs; XmlUtils::CXmlNodes oNodesCFs; if (oXmlNode.GetNodes(_T("Character"), oNodesCFs)) { INT iCount = oNodesCFs.GetCount(); for (INT iIndex = 0; iIndex < iCount; ++iIndex) { XmlUtils::CXmlNode oNode; oNodesCFs.GetAt(iIndex, oNode); arCFs.Add(new CCharacter()); arCFs[iIndex]->m_oAttributes = oAttributes; arCFs[iIndex]->FromXmlNode(oNode, m_DocumentManager); } if (iCount == 0) { CCharacter *pCharacter = new CCharacter(); pCharacter->FromXmlNode(oXmlNode, m_DocumentManager); pCharacter->m_lCount = m_strText.GetLength(); pCharacter->m_oAttributes = oAttributes; arCFs.Add(pCharacter); } } m_arrPageSequence.Add(new CPageSequence()); SetDefaultPageSequence(*m_arrPageSequence[0]); CFlow* pFirstFlow = (*m_arrPageSequence[0]).GetFirstFlow(); pFirstFlow->SetAlignVertical((CAlignVertical)oAttributes.m_nTextAlignmentVertical); if (!Normalize(&arPFs, &arCFs, pFirstFlow->GetBlocks())) InternalClear(); m_arrPages.RemoveAll(); } void SetDefaultLayoutMasterSet(CLayoutMasterSet &oLayoutMasterSet) { oLayoutMasterSet.Clear(); CString strXml = _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); XmlUtils::CXmlNode oNode; oNode.FromXmlString(strXml, _T("xmlns:fo='http://www.w3.org/1999/XSL/Format'")); oLayoutMasterSet.FromXmlNode(oNode, m_DocumentManager); } void SetDefaultPageSequence(CPageSequence &oPageSequence) { oPageSequence.Clear(); CString strXml = _T(""); strXml += _T(""); strXml += _T(""); strXml += _T(""); XmlUtils::CXmlNode oNode; oNode.FromXmlString(strXml, _T("xmlns:fo=\"http://www.w3.org/1999/XSL/Format\"")); oPageSequence.SetLayoutMasterSet(&m_oLayoutMasterSet); oPageSequence.loadFromXml(oNode, m_DocumentManager); } bool Normalize(CAtlArray *pArrayPFs, CAtlArray *pArrayCFs, CAtlArray &arrParagraphs) { size_t nParagraphsCount = pArrayPFs->GetCount(); size_t nCharactersCount = pArrayCFs->GetCount(); size_t nTextLength = m_strText.GetLength(); size_t nCurrentSymbolIndex = 0; size_t nIndex = 0; size_t nSymbolsCount = 0; for (; nIndex < nParagraphsCount; ++nIndex) { nSymbolsCount += (*pArrayPFs)[nIndex]->m_lCount; if (nSymbolsCount >= nTextLength) { break; } } if (nIndex < nParagraphsCount - 1) { for (size_t i = nIndex + 1; i < nParagraphsCount; ++i) { RELEASEOBJECT((*pArrayPFs)[i]); } pArrayPFs->RemoveAt(nIndex + 1, nParagraphsCount - nIndex - 1); nParagraphsCount = pArrayPFs->GetCount(); } if (nSymbolsCount != nTextLength) { CBlockAttributes *pParagraph = (*pArrayPFs)[nParagraphsCount - 1]; pParagraph->m_lCount += (LONG)(nTextLength - nSymbolsCount); } size_t nCurrentCharacter = 0; for (size_t nIndex = 0; nIndex < nParagraphsCount; ++ nIndex) { CBlockAttributes *pParagraph = (*pArrayPFs)[nIndex]; CBlock *pTextParagraph = new CBlock; arrParagraphs.Add(pTextParagraph); pTextParagraph->m_pBlockAttributes = pParagraph; size_t nSymbolsCount = 0; size_t nParagraphLen = pParagraph->m_lCount; for (; nCurrentCharacter < nCharactersCount; ++nCurrentCharacter) { if (nSymbolsCount >= nParagraphLen) { break; } CCharacter *pCharacter = (*pArrayCFs)[nCurrentCharacter]; size_t nCharacterLen = pCharacter->m_lCount; if (nCharacterLen == 0) { RELEASEOBJECT(pCharacter); continue; } if (nSymbolsCount + nCharacterLen <= nParagraphLen) { nSymbolsCount += nCharacterLen; pTextParagraph->m_Items.AddCharacter(pCharacter); } else { CCharacter *pNewCharacter = new CCharacter(); pNewCharacter->m_oAttributes = pCharacter->m_oAttributes; pNewCharacter->m_lCount = (LONG)(nParagraphLen - nSymbolsCount); pCharacter->m_lCount -= pNewCharacter->m_lCount; nSymbolsCount += pNewCharacter->m_lCount; pTextParagraph->m_Items.AddCharacter(pNewCharacter); break; } } if (nSymbolsCount < nParagraphLen) { if (pTextParagraph->m_Items.CountCharacters() != 0) { int nLastCharacterIndex = pTextParagraph->m_Items.CountCharacters() - 1; CCharacter *pLastCharacter = pTextParagraph->m_Items.GetCharacter(nLastCharacterIndex); pLastCharacter->m_lCount += (LONG)(nParagraphLen - nSymbolsCount); } else { CCharacter *pNewCharacter = new CCharacter(); size_t nLastCharacterIndex = nCharactersCount - 1; CCharacter *pLastCharacter = (*pArrayCFs)[nLastCharacterIndex]; pNewCharacter->m_oAttributes = pLastCharacter->m_oAttributes; pNewCharacter->m_lCount = pTextParagraph->m_pBlockAttributes->m_lCount; pTextParagraph->m_Items.AddCharacter(pNewCharacter); } } pTextParagraph->m_Items.Text(m_strText.Mid((int)nCurrentSymbolIndex, (int)pParagraph->m_lCount)); nCurrentSymbolIndex += pParagraph->m_lCount; } if (nCurrentCharacter < nCharactersCount) { for (size_t i = nCurrentCharacter; i < nCharactersCount; ++i) { RELEASEOBJECT((*pArrayCFs)[i]); } pArrayCFs->RemoveAt(nCurrentCharacter, nCharactersCount - nCurrentCharacter); } m_bIsFormated = false; return TRUE; } private: void DrawPage(CPage* page, IAVSRenderer* renderer, const float& completeness, const bool& transform = true, const int& block = -1) { if (m_bIsFo) { m_fWidthMm = page->GetWidthMm(); m_fHeightMm = page->GetHeightMm(); IWorker_OnNewPage(m_fWidthMm, m_fHeightMm); CBackgroundRect* pageRect = m_oBGPage.GetBackgroundRect2(0, 0, m_fWidthMm, m_fHeightMm); pageRect->Draw(renderer, completeness); RELEASEOBJECT(pageRect); if (block == -1) page->Draw(renderer, m_DocumentManager, completeness); else page->Draw(renderer, m_DocumentManager, block, completeness); IWorker_OnCompletePage(); } else { #ifdef TME_DEBUG_VSXML m_fWidthMm = page->GetWidthMm(); m_fHeightMm = page->GetHeightMm(); IWorker_OnNewPage(m_fWidthMm, m_fHeightMm); #endif SetRenderer(renderer); if (transform) renderer->SetCommandParams(m_dAngle, m_oLayoutRect.X, m_oLayoutRect.Y, m_oLayoutRect.Width, m_oLayoutRect.Height, m_lFlags); if (block == -1) page->Draw(renderer, m_DocumentManager, completeness); else page->Draw(renderer, m_DocumentManager, block, completeness); if (transform) renderer->SetCommandParams(0, -1, -1, -1, -1, 0); #ifdef TME_DEBUG_VSXML IWorker_OnCompletePage(); #endif } } void Progress(const float &fProgress) { if (fProgress > 0.0f) { IWorker_OnProgress(fProgress); } else { IWorker_OnProgress(m_DocumentManager.GetCompleteness()); } } void SendLinkerXml(IAVSRenderer *pRenderer) { BSTR bstrHyperlinkXml = m_DocumentManager.m_Linker.GenerateXml(); pRenderer->BeginCommand(c_nHyperlinkType); pRenderer->CommandDrawText(bstrHyperlinkXml, 0, 0, 0, 0, 0); pRenderer->EndCommand(c_nHyperlinkType); } protected: void InitFontManager() { m_pFontManager = CGrapher::GenerateFontManager(); //ADDREFINTERFACE(m_pFontManager); } }; } } } }