From 1e0f4d6fdbbb98501d1167b829c2fc89205d38e6 Mon Sep 17 00:00:00 2001 From: ElenaSubbotina Date: Thu, 19 Oct 2017 17:39:00 +0300 Subject: [PATCH] XlsFormat - developers controls (buttons, options, ....), fix vba stream --- .../source/XlsFormat/Binary/CompoundFile.cpp | 29 +- .../source/XlsFormat/Binary/CompoundFile.h | 2 +- .../XlsFormat/Logic/Biff_records/Font.h | 6 +- .../XlsFormat/Logic/Biff_records/Note.cpp | 2 - .../XlsFormat/Logic/Biff_records/Note.h | 11 +- .../XlsFormat/Logic/Biff_records/TxO.cpp | 79 ++- .../source/XlsFormat/Logic/Biff_records/TxO.h | 15 +- .../Logic/Biff_structures/NoteSh.cpp | 3 - .../XlsFormat/Logic/Biff_structures/NoteSh.h | 1 - .../ConvertShapes/GraphicsPath.h | 84 +--- .../source/XlsXlsxConverter/XlsConverter.cpp | 28 +- .../source/XlsXlsxConverter/external_items.h | 19 +- .../XlsXlsxConverter/xlsx_drawing_context.cpp | 456 +++++++++++++++--- .../XlsXlsxConverter/xlsx_drawing_context.h | 42 +- .../XlsXlsxConverter/xlsx_output_xml.cpp | 18 +- .../source/XlsXlsxConverter/xlsx_output_xml.h | 2 +- .../XlsXlsxConverter/xlsx_tablecontext.cpp | 18 +- Common/3dParty/pole/pole.cpp | 135 ++++-- Common/3dParty/pole/pole.h | 1 + XlsxSerializerCom/Reader/BinaryWriter.h | 2 + 20 files changed, 662 insertions(+), 291 deletions(-) diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CompoundFile.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CompoundFile.cpp index 64aaea520c..50c0056f55 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CompoundFile.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CompoundFile.cpp @@ -97,9 +97,9 @@ CompoundFile::CompoundFile(const std::wstring & file_path, const ReadWriteMode m Open(file_path, mode); } -void CompoundFile::copy_stream(std::string streamName, POLE::Storage * storageOut, bool bWithRoot) +void CompoundFile::copy_stream(std::string streamNameOpen, std::string streamNameCreate, POLE::Storage * storageOut, bool bWithRoot) { - POLE::Stream *stream = new POLE::Stream(storage_, streamName); + POLE::Stream *stream = new POLE::Stream(storage_, streamNameOpen); if (!stream) return; stream->seek(0); @@ -107,12 +107,12 @@ void CompoundFile::copy_stream(std::string streamName, POLE::Storage * storageOu if (bWithRoot == false) { - int pos = streamName.find("/"); + int pos = streamNameCreate.find("/"); if (pos >= 0) - streamName = streamName.substr(pos + 1); + streamNameCreate = streamNameCreate.substr(pos + 1); } - POLE::Stream *streamNew = new POLE::Stream(storageOut, streamName, true, size_stream); + POLE::Stream *streamNew = new POLE::Stream(storageOut, streamNameCreate, true, size_stream); if (!streamNew) return; unsigned char* data_stream = new unsigned char[size_stream]; @@ -135,7 +135,8 @@ void CompoundFile::copy_stream(std::string streamName, POLE::Storage * storageOu void CompoundFile::copy( int indent, std::string path, POLE::Storage * storageOut, bool bWithRoot, bool bSortFiles) { std::list entries, entries_files, entries_dir; - entries = storage_->entries( path ); + + entries = storage_->entries_with_prefix( path ); for( std::list::iterator it = entries.begin(); it != entries.end(); it++ ) { @@ -157,16 +158,18 @@ void CompoundFile::copy( int indent, std::string path, POLE::Storage * storageOu copy( indent + 1, fullname + "/", storageOut, bWithRoot, bSortFiles ); } - if (bSortFiles) - { - entries_files.sort(); - //todooo ??? со спецсимволами выше - } + + entries_files.sort(); + for( std::list::iterator it = entries_files.begin(); it != entries_files.end(); it++ ) { - std::string fullname = path + *it; + std::string createName = path + *it; + std::string openName; + + if (it->at(0) < 32) openName = path + it->substr(1); + else openName = path + *it; - copy_stream(fullname, storageOut, bWithRoot); + copy_stream(openName, createName, storageOut, bWithRoot); } } CFStreamPtr CompoundFile::getWorkbookStream() diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CompoundFile.h b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CompoundFile.h index 13487e49bd..e235a5de0c 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CompoundFile.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CompoundFile.h @@ -65,7 +65,7 @@ public: POLE::Storage *storage_; private: - void copy_stream(std::string streamName, POLE::Storage * storageOut, bool bWithRoot = true); + void copy_stream(std::string streamNameOpen, std::string streamNameCreate, POLE::Storage * storageOut, bool bWithRoot = true); POLE::Stream* openStream (const std::string & stream_name); // Opens a stream in the storage (shall be called not more than once per stream) POLE::Stream* createStream (const std::string & stream_name); // Creates a new stream in the storage diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Font.h b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Font.h index 522c13250a..fe7cbe5535 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Font.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Font.h @@ -32,14 +32,12 @@ #pragma once #include "BiffRecord.h" -#include -#include +#include "../Biff_structures/BiffString.h" +#include "../Biff_structures/BorderFillInfo.h" namespace XLS { - -// Logical representation of Font record in BIFF8 class Font: public BiffRecord { BIFF_RECORD_DEFINE_TYPE_INFO(Font) diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Note.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Note.cpp index 4c5f812050..a87b51193b 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Note.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Note.cpp @@ -39,12 +39,10 @@ Note::Note() { } - Note::~Note() { } - BaseObjectPtr Note::clone() { return BaseObjectPtr(new Note(*this)); diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Note.h b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Note.h index 5853039d3d..2e27ad68e6 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Note.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/Note.h @@ -32,13 +32,11 @@ #pragma once #include "BiffRecord.h" -#include -#include +#include "../Biff_structures/NoteSh.h" +#include "../Biff_structures/NoteRR.h" namespace XLS { - -// Logical representation of Note record in BIFF8 class Note: public BiffRecord { BIFF_RECORD_DEFINE_TYPE_INFO(Note) @@ -49,15 +47,12 @@ public: BaseObjectPtr clone(); - void readFields(CFRecord& record); - static const ElementType type = typeNote; + static const ElementType type = typeNote; NoteSh note_sh; // NoteRR note_rr; - - }; } // namespace XLS diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/TxO.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/TxO.cpp index 944f691064..85a6f5445f 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/TxO.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/TxO.cpp @@ -56,11 +56,11 @@ BaseObjectPtr TxO::clone() void TxO::readFields(CFRecord& record) { - pGlobalWorkbookInfoPtr = record.getGlobalWorkbookInfo(); + global_info = record.getGlobalWorkbookInfo(); unsigned short flags; - if (pGlobalWorkbookInfoPtr->Version < 0x0600) + if (global_info->Version < 0x0600) { short mnLinkSize; short mnButtonFlags; @@ -154,6 +154,71 @@ void TxO::readFields(CFRecord& record) fSecretEdit = GETBIT(flags, 15); } +int TxO::serialize_vml (std::wostream & _stream) +{ + std::wstring str_ = rawText.value(); + int str_size = str_.size(); + + int iFmt = 0; + + CP_XML_WRITER(_stream) + { + for (size_t i = 0; i < TxOruns.rgTxoRuns.size(); i++) + { + Run *run = dynamic_cast(TxOruns.rgTxoRuns[i].get()); + if (run == NULL) continue; + + int end_string = str_size; + + if ( i < TxOruns.rgTxoRuns.size() - 1) + { + Run *run_next = dynamic_cast(TxOruns.rgTxoRuns[i+1].get()); + if (run_next) + end_string = run_next->formatRun.ich; + } + + CP_XML_NODE(L"div") + { + //style='text-align:left' + CP_XML_NODE(L"font") + { + iFmt = run->formatRun.ifnt; + Font *font = NULL; + if ((global_info->m_arFonts) && (iFmt >=0 && iFmt < global_info->m_arFonts->size())) + { + font = dynamic_cast(global_info->m_arFonts->at(iFmt).get()); + } + if (font) + { + if (font->dyHeight > 0) CP_XML_ATTR(L"size", font->dyHeight); + if (font->bls == 700) CP_XML_ATTR(L"bold", true); + if (font->fItalic) CP_XML_ATTR(L"italic", true); + if (!font->fontName.value().empty()) + { + CP_XML_ATTR(L"face", font->fontName.value()); + } + if ( font->icv < 0x7fff ) + { + } + else CP_XML_ATTR(L"color", L"auto"); + + } + + if (run->formatRun.ich > str_.length()) + { + //ошибка + run->formatRun.ich = 0; + } + + std::wstring str_part = str_.substr( run->formatRun.ich, end_string - run->formatRun.ich); + + CP_XML_STREAM() << xml::utils::replace_text_to_xml(str_part); + } + } + } + } + return 0; +} int TxO::serialize (std::wostream & _stream) { @@ -163,7 +228,7 @@ int TxO::serialize (std::wostream & _stream) int Fmt = 0; std::wstring namespace_ = L"a:"; - oox::external_items::Type type = pGlobalWorkbookInfoPtr->xls_converter->xlsx_context->get_drawing_context().getType(); + oox::external_items::Type type = global_info->xls_converter->xlsx_context->get_drawing_context().getType(); if (type == oox::external_items::typeComment) namespace_.clear(); @@ -215,13 +280,13 @@ int TxO::serialize (std::wostream & _stream) } int TxO::serialize_rPr (std::wostream & _stream, int iFmt, std::wstring namespace_) { - if (!pGlobalWorkbookInfoPtr) return 0; - if (!pGlobalWorkbookInfoPtr->m_arFonts) return 0; + if (!global_info) return 0; + if (!global_info->m_arFonts) return 0; - int sz = pGlobalWorkbookInfoPtr->m_arFonts->size(); + int sz = global_info->m_arFonts->size(); if (iFmt - 1 >= sz || iFmt < 1) return 0; - Font * font = dynamic_cast(pGlobalWorkbookInfoPtr->m_arFonts->at(iFmt-1).get()); + Font * font = dynamic_cast(global_info->m_arFonts->at(iFmt-1).get()); if (!font) return 0; diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/TxO.h b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/TxO.h index 493200e351..90dc128bf9 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/TxO.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/TxO.h @@ -32,17 +32,15 @@ #pragma once #include "BiffRecordContinued.h" -#include -#include -#include -#include -#include +#include "MsoDrawing.h" +#include "../Biff_structures/ControlInfo.h" +#include "../Biff_structures/FontIndex.h" +#include "../Biff_structures/ObjFmla.h" +#include "../Biff_structures/TxORuns.h" namespace XLS { - -// Logical representation of TxO record in BIFF8 class TxO: public BiffRecordContinued { BIFF_RECORD_DEFINE_TYPE_INFO(TxO) @@ -68,8 +66,9 @@ public: int serialize (std::wostream & _stream); int serialize_rPr (std::wostream & _stream, int iFmt, std::wstring namespace_= L"a:"); + int serialize_vml (std::wostream & _stream); - GlobalWorkbookInfoPtr pGlobalWorkbookInfoPtr; + GlobalWorkbookInfoPtr global_info; unsigned char hAlignment; unsigned char vAlignment; diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/NoteSh.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/NoteSh.cpp index 6a6098a2f5..f95a645404 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/NoteSh.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/NoteSh.cpp @@ -37,7 +37,6 @@ namespace XLS { - NoteSh::NoteSh() { x_ = y_ = 0; @@ -47,14 +46,12 @@ NoteSh::NoteSh() fColHidden = false; } - NoteSh::NoteSh(CFRecord& record) { x_ = y_ = 0; load(record); } - BiffStructurePtr NoteSh::clone() { return BiffStructurePtr(new NoteSh(*this)); diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/NoteSh.h b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/NoteSh.h index 1ac130ce84..4baeb30289 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/NoteSh.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/NoteSh.h @@ -52,7 +52,6 @@ public: virtual void load(CFRecord& record); - Rw row; Col col; bool fShow; diff --git a/ASCOfficeXlsFile2/source/XlsXlsxConverter/ConvertShapes/GraphicsPath.h b/ASCOfficeXlsFile2/source/XlsXlsxConverter/ConvertShapes/GraphicsPath.h index 0552de391a..e3b7cf621d 100644 --- a/ASCOfficeXlsFile2/source/XlsXlsxConverter/ConvertShapes/GraphicsPath.h +++ b/ASCOfficeXlsFile2/source/XlsXlsxConverter/ConvertShapes/GraphicsPath.h @@ -137,41 +137,6 @@ namespace NSCustomShapesConvert } }; - //class CRectF - //{ - //public: - // float X; - // float Y; - // float Width; - // float Height; - - //public: - // CRectF() - // { - // X = 0; - // Y = 0; - // Width = 0; - // Height = 0; - // } - // CRectF(const CRectF& oSrc) - // { - // *this = oSrc; - // } - // CRectF& operator=(const CRectF& oSrc) - // { - // X = oSrc.X; - // Y = oSrc.Y; - // Width = oSrc.Width; - // Height = oSrc.Height; - - // return *this; - // } - // bool Equals(const CRect& oSrc) - // { - // return ((X == oSrc.X) && (Y == oSrc.Y) && (Width == oSrc.Width) && (Height == oSrc.Height)); - // } - //}; - class CGeomShapeInfo { public: @@ -314,7 +279,7 @@ namespace NSCustomShapesConvert enum RulesType { - // VML +// VML rtLineTo = 0, // 2* rtCurveTo = 1, // 6* rtMoveTo = 2, // 2 @@ -360,58 +325,14 @@ namespace NSCustomShapesConvert class CGraphicPath { public: - //virtual void InternalFromXmlNode(XmlUtils::CXmlNode& oXmlNode) - //{ - // Metric = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("metric"), _T("0"))); - // m_bStroke = (1 == XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("stroke"), _T("0")))); - // m_bFill = (1 == XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("fill"), _T("0")))); - - // m_dWidthMM = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("widthmm"), _T("210"))); - // m_dHeightMM = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("heightmm"), _T("190"))); - - // m_dAngle = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("angle"), _T("0"))); - // m_lFlags = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("flags"), _T("0"))); - - // m_oBounds.left = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("bounds-left"), _T("0"))); - // m_oBounds.top = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("bounds-top"), _T("0"))); - // m_oBounds.right = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("bounds-right"), _T("0"))); - // m_oBounds.bottom = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("bounds-bottom"), _T("0"))); - - // XmlUtils::CXmlNodes oNodes; - // oXmlNode.GetNodes(_T("part"), oNodes); - // for (int nIndex = 0; nIndex < oNodes.GetCount(); ++nIndex) - // { - // CPart oPart; - // XmlUtils::CXmlNode oNode; - // oNodes.GetAt(nIndex, oNode); - // oPart.FromXmlNode(oNode); - // m_arParts.push_back(oPart); - // } - - // //XmlUtils::CXmlNode oPenNode; - // //if (oXmlNode.GetNode(_T("pen"), oPenNode)) - // //{ - // // Pen.FromXmlNode(oPenNode); - // //} - // //XmlUtils::CXmlNode oBrushNode; - // //if (oXmlNode.GetNode(_T("brush"), oBrushNode)) - // //{ - // // Brush.FromXmlNode(oBrushNode); - // //} - //} virtual void InternalClear() { m_lFlags = 0; } - - public: - CGraphicPath() { InternalClear(); } - public: - class CPart { public: @@ -1028,9 +949,6 @@ namespace NSCustomShapesConvert { m_arParts.clear(); } - - public: - std::vector m_arParts; int m_lFlags; diff --git a/ASCOfficeXlsFile2/source/XlsXlsxConverter/XlsConverter.cpp b/ASCOfficeXlsFile2/source/XlsXlsxConverter/XlsConverter.cpp index 0d69bb4fb3..1866a7bd12 100644 --- a/ASCOfficeXlsFile2/source/XlsXlsxConverter/XlsConverter.cpp +++ b/ASCOfficeXlsFile2/source/XlsXlsxConverter/XlsConverter.cpp @@ -1040,7 +1040,7 @@ void XlsConverter::convert(XLS::OBJECTS* objects, XLS::WorksheetSubstream * shee if (text_obj) { - if (type_object <0) type_object = 0x0006; + if (type_object < 0) type_object = 0x0006; } //----------------------------------------------------------------------------- @@ -1115,7 +1115,7 @@ void XlsConverter::convert(XLS::OBJECTS* objects, XLS::WorksheetSubstream * shee void XlsConverter::convert(ODRAW::OfficeArtSpgrContainer * spgr) { if (spgr == NULL) return; - if (spgr->anchor_type_ != ODRAW::OfficeArtRecord::CA_HF) return; //todooo проверить что тока для header/footer это нужно + if (spgr->anchor_type_ != ODRAW::OfficeArtRecord::CA_HF) return; for (size_t i = 0; i < spgr->child_records.size(); i++) { @@ -1123,7 +1123,7 @@ void XlsConverter::convert(ODRAW::OfficeArtSpgrContainer * spgr) if (xlsx_context->get_drawing_context().start_drawing(type_object)) { - xlsx_context->get_drawing_context().set_mode_vmlwrite(true); + xlsx_context->get_drawing_context().set_mode_HF(true); convert(spgr->child_records[i].get()); xlsx_context->get_drawing_context().end_drawing(); @@ -1515,7 +1515,7 @@ void XlsConverter::convert_blip(std::vector & props) std::wstring target; int id = props[i]->op; - if (xlsx_context->get_drawing_context().get_mode_vmlwrite()) + if (xlsx_context->get_drawing_context().get_mode_HF()) id += 3000; std::wstring rId = xlsx_context->get_mediaitems().find_image(id , target, isIternal); @@ -1894,9 +1894,6 @@ void XlsConverter::convert(XLS::TxO * text_obj) { if (text_obj == NULL) return; - std::wstringstream strm; - text_obj->serialize(strm); - int rot = text_obj->rot; if (rot > 0) @@ -1928,7 +1925,14 @@ void XlsConverter::convert(XLS::TxO * text_obj) xlsx_context->get_drawing_context().set_text_align (text_obj->hAlignment); xlsx_context->get_drawing_context().set_text_vert_align (text_obj->vAlignment); + std::wstringstream strm, strm_vml; + + text_obj->serialize(strm); xlsx_context->get_drawing_context().set_text(strm.str()); + + text_obj->serialize_vml(strm_vml); + xlsx_context->get_drawing_context().set_text_vml(strm_vml.str()); + } void XlsConverter::convert(XLS::Obj * obj) @@ -1991,9 +1995,17 @@ void XlsConverter::convert(XLS::Obj * obj) if (obj->list.fExist) { } + bool full_ref = false; + if (obj->cmo.ot > 0x06) full_ref = true; + + if (obj->linkFmla.fExist && obj->linkFmla.fmla.bFmlaExist) + { + std::wstring link = obj->linkFmla.fmla.fmla.getAssembledFormula(full_ref); + xlsx_context->get_drawing_context().set_object_link(link); + } if (obj->macro.fExist && obj->macro.fmla.bFmlaExist) { - std::wstring macro = obj->macro.fmla.fmla.getAssembledFormula(); + std::wstring macro = obj->macro.fmla.fmla.getAssembledFormula(full_ref); xlsx_context->get_drawing_context().set_macro(macro); } } diff --git a/ASCOfficeXlsFile2/source/XlsXlsxConverter/external_items.h b/ASCOfficeXlsFile2/source/XlsXlsxConverter/external_items.h index 83cdad9ebe..d2a6ebbaef 100644 --- a/ASCOfficeXlsFile2/source/XlsXlsxConverter/external_items.h +++ b/ASCOfficeXlsFile2/source/XlsXlsxConverter/external_items.h @@ -41,7 +41,22 @@ class rels; class external_items { public: - enum Type { typeUnknown = 0, typeImage, typeChart, typeShape, typeTable, typeHyperlink, typeComment, typeMedia, typeGroup, typeExternalLink, typeOleObject, typeActiveX}; + enum Type + { + typeUnknown = 0, + typeImage, + typeChart, + typeShape, + typeTable, + typeHyperlink, + typeComment, + typeMedia, + typeGroup, + typeExternalLink, + typeOleObject, + typeActiveX, + typeControl + }; external_items() { @@ -52,6 +67,7 @@ public: count_media = 0; count_activeX = 0; count_embeddings= 0; + count_controls = 0; } struct item @@ -79,6 +95,7 @@ public: size_t count_tables; size_t count_activeX; size_t count_embeddings; + size_t count_controls; //std::wstring add_or_find(const std::wstring & href, Type type, bool & isInternal);//возможны ссылки на один и тот же объект std::wstring add_image (const std::wstring & file_name, int bin_id); diff --git a/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_drawing_context.cpp b/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_drawing_context.cpp index b598c2c6ef..d44d84b596 100644 --- a/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_drawing_context.cpp +++ b/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_drawing_context.cpp @@ -46,6 +46,155 @@ namespace oox { + class PathParser + { + public: + + PathParser (std::vector &arSegments, std::vector& arPoints, std::vector & arGuides) + : m_arSegments(arSegments) + { + LONG lMinF = (_INT32)0x80000000; + POINT point; + for (size_t i = 0; i < arPoints.size(); i++) + { + point.x = arPoints[i].x; + point.y = arPoints[i].y; + + if (lMinF <= point.x) + { + int index = (_UINT32)point.x - 0x80000000; + if (index >= 0 && index < arGuides.size()) + { + point.x = arGuides[index].m_param_value3; + } + } + if (lMinF <= point.y) + { + int index = (_UINT32)point.y - 0x80000000; + if (index >= 0 && index < arGuides.size()) + { + point.y = arGuides[index].m_param_value3; + } + } + if ((size_t)point.y > 0xffff) point.y &= 0xffff; + if ((size_t)point.x > 0xffff) point.x &= 0xffff; + + m_arPoints.push_back(point); + } + } + + inline std::wstring GetVmlPath () const + { + if (m_arSegments.empty() && m_arPoints.empty()) + return std::wstring(L""); + + std::wstring strVmlPath; + size_t valuePointer = 0; + + if (m_arSegments.empty()) + { + for (size_t i = 0; i < m_arPoints.size(); ++i) + { + strVmlPath += L"l"; + strVmlPath += std::to_wstring(m_arPoints[i].x); + strVmlPath += L","; + strVmlPath += std::to_wstring(m_arPoints[i].y); + + ++valuePointer; + } + + strVmlPath += L"xe"; + + return strVmlPath; + } + + for (size_t i = 0; i < m_arSegments.size(); i++) + { + switch (m_arSegments[i].m_eRuler) + { + case NSCustomShapesConvert::rtLineTo: + { + for (_UINT16 i = 0; i < m_arSegments[i].m_nCount; ++i) + { + if (valuePointer + 1 > m_arPoints.size()) + { + break; + + strVmlPath += L"l"; + strVmlPath += std::to_wstring(m_arPoints[0].x); + strVmlPath += L","; + strVmlPath += std::to_wstring(m_arPoints[0].y); + + ++valuePointer; + } + else + { + strVmlPath += L"l"; + strVmlPath += std::to_wstring(m_arPoints[valuePointer].x ); + strVmlPath += L","; + strVmlPath += std::to_wstring(m_arPoints[valuePointer].y ); + + ++valuePointer; + } + } + }break; + case NSCustomShapesConvert::rtCurveTo: + { + for (_UINT16 i = 0; i < m_arSegments[i].m_nCount; ++i) + { + if (valuePointer + 3 > m_arPoints.size()) + break; + strVmlPath += L"c"; + strVmlPath += std::to_wstring(m_arPoints[valuePointer].x ); + strVmlPath += L","; + strVmlPath += std::to_wstring(m_arPoints[valuePointer].y ); + strVmlPath += L","; + strVmlPath += std::to_wstring(m_arPoints[valuePointer + 1].x ); + strVmlPath += L","; + strVmlPath += std::to_wstring(m_arPoints[valuePointer + 1].y ); + strVmlPath += L","; + strVmlPath += std::to_wstring(m_arPoints[valuePointer + 2].x ); + strVmlPath += L","; + strVmlPath += std::to_wstring(m_arPoints[valuePointer + 2].y ); + valuePointer += 3; + } + }break; + case NSCustomShapesConvert::rtMoveTo: + { + if (valuePointer < m_arPoints.size()) + { + strVmlPath += L"m"; + strVmlPath += std::to_wstring(m_arPoints[valuePointer].x ); + strVmlPath += L","; + strVmlPath += std::to_wstring(m_arPoints[valuePointer].y ); + + ++valuePointer; + } + } + break; + case NSCustomShapesConvert::rtClose: + { + strVmlPath += L"x"; + } + break; + case NSCustomShapesConvert::rtEnd: + { + strVmlPath += L"e"; + }break; + } + } + + if ( !strVmlPath.empty() && ( strVmlPath[strVmlPath.size() - 1] != L'e' ) ) + strVmlPath +=L"e"; + + return strVmlPath; + } + + private: + std::vector &m_arSegments; + std::vector m_arPoints; + }; +//----------------------------------------------------------------------------------------------------------- const static std::wstring shemeColor[18] = {L"accent1",L"accent2",L"accent3",L"accent4",L"accent5",L"accent6",L"bk1",L"bk2",L"dk1",L"dk2",L"folHlink",L"hlink",L"lt1",L"lt2",L"none", L"tx1",L"tx2",L"phClr"}; @@ -284,11 +433,11 @@ _color xlsx_drawing_context::CorrectSysColor(int nColorCode, _drawing_state_ptr //} return color; } - +//----------------------------------------------------------------------------------------------------------- xlsx_drawing_context::xlsx_drawing_context(xlsx_conversion_context & Context) : context_(Context), handle_(Context.get_drawing_context_handle()) , rels_ (xlsx_drawings_rels::create()) , vml_HF_rels_ (xlsx_drawings_rels::create()) - , vml_comments_rels_(xlsx_drawings_rels::create()) + , vml_rels_(xlsx_drawings_rels::create()) , sheet_rels_ (xlsx_drawings_rels::create()) { in_chart_ = false; @@ -326,10 +475,9 @@ bool xlsx_drawing_context::start_drawing(int type) case 0x0010: // Spin control case 0x0012: // List case 0x0013: // Group box - start_shape(0x0002); return true; case 0x0011: // Scrollbar case 0x0014: // Dropdown list - break; + start_control(type); return true; case 0x0019: // Note start_comment(); return true; break; @@ -357,6 +505,7 @@ void xlsx_drawing_context::start_image() current_drawing_states->push_back(create_drawing_state()); current_drawing_states->back()->type = external_items::typeImage; + current_drawing_states->back()->type_control = 0x0008; count_object++; } @@ -367,9 +516,12 @@ void xlsx_drawing_context::start_comment() current_drawing_states->push_back(create_drawing_state()); - current_drawing_states->back()->type = external_items::typeComment; - //current_drawing_states->back()->vmlwrite_mode_ = true; это только для HF !!! + current_drawing_states->back()->type = external_items::typeComment; + current_drawing_states->back()->shape_id = MSOSPT::msosptRectangle; + current_drawing_states->back()->type_control = 0x0019; + current_drawing_states->back()->object.visible = false; + count_object++; context_.get_comments_context().start_comment(); @@ -389,6 +541,7 @@ void xlsx_drawing_context::start_group() current_drawing_states->push_back(newState); current_drawing_states->back()->type = external_items::typeGroup; + current_drawing_states->back()->type_control = 0x0000; } void xlsx_drawing_context::end_group() { @@ -412,7 +565,19 @@ void xlsx_drawing_context::start_chart() in_chart_ = true; count_object++; } +void xlsx_drawing_context::start_control(int type) +{ + if (current_drawing_states == NULL) return; + current_drawing_states->push_back(create_drawing_state()); + + current_drawing_states->back()->type = external_items::typeControl; + + current_drawing_states->back()->shape_id = MSOSPT::msosptRectangle; + current_drawing_states->back()->type_control = type; + + count_object++; +} void xlsx_drawing_context::start_shape(int type) { if (current_drawing_states == NULL) return; @@ -420,6 +585,7 @@ void xlsx_drawing_context::start_shape(int type) current_drawing_states->push_back(create_drawing_state()); current_drawing_states->back()->type = external_items::typeShape; + current_drawing_states->back()->type_control = type; switch(type) { @@ -465,14 +631,14 @@ void xlsx_drawing_context::set_shape_id(int id) current_drawing_states->back()->shape_id = (MSOSPT)id; } -void xlsx_drawing_context::set_object_visible (bool val) +void xlsx_drawing_context::set_object_visible(bool val) { if (current_drawing_states == NULL) return; if (current_drawing_states->empty()) return; current_drawing_states->back()->object.visible = val; } -void xlsx_drawing_context::set_object_anchor (int col, int row) +void xlsx_drawing_context::set_object_anchor(int col, int row) { if (current_drawing_states == NULL) return; if (current_drawing_states->empty()) return; @@ -484,7 +650,13 @@ void xlsx_drawing_context::set_object_anchor (int col, int row) void xlsx_drawing_context::set_object_id(int val) { } +void xlsx_drawing_context::set_object_link(const std::wstring & formula) +{ + if (current_drawing_states == NULL) return; + if (current_drawing_states->empty()) return; + current_drawing_states->back()->object.link = formula; +} void xlsx_drawing_context::end_drawing() { @@ -495,17 +667,19 @@ void xlsx_drawing_context::end_drawing() end_drawing(current_drawing_states->back()); - if ( current_drawing_states->back()->type == external_items::typeComment ) + if ( current_drawing_states->back()->type == external_items::typeComment || + current_drawing_states->back()->type == external_items::typeControl ) { - drawing_states_vml_comments.push_back(current_drawing_states->back()); + drawing_states_vml.push_back(current_drawing_states->back()); + + if (current_drawing_states->back()->type == external_items::typeComment) + current_drawing_states->pop_back(); + } + else if (!current_drawing_states->back()->vml_shape.empty()) + { // && current_drawing_states->back()->vml_HF_mode_ + drawing_states_vml_HF.push_back(current_drawing_states->back()); current_drawing_states->pop_back(); } - else - if (current_drawing_states->back()->vmlwrite_mode_) - { - drawing_states_vml_HF.push_back(current_drawing_states->back()); - current_drawing_states->pop_back(); - } } void xlsx_drawing_context::end_drawing(_drawing_state_ptr & drawing_state) @@ -527,10 +701,14 @@ void xlsx_drawing_context::end_drawing(_drawing_state_ptr & drawing_state) serialize_pic(drawing_state, rId); - if (drawing_state->vmlwrite_mode_) + if (drawing_state->vml_HF_mode_) + { vml_HF_rels_->add(isIternal, rId , drawing_state->fill.texture_target, drawing_state->type); + } else + { rels_->add(isIternal, rId , drawing_state->fill.texture_target, drawing_state->type); + } } else drawing_state->type = external_items::typeShape; @@ -561,15 +739,18 @@ void xlsx_drawing_context::end_drawing(_drawing_state_ptr & drawing_state) { context_.get_comments_context().set_content(drawing_state->text.content); - serialize_shape_comment(drawing_state); + serialize_vml_shape(drawing_state); - //context_.get_comments_context().set_shape_drawing(drawing_state->shape); context_.get_comments_context().end_comment(); } if ( drawing_state->type == external_items::typeShape) { serialize_shape(drawing_state); } + if ( drawing_state->type == external_items::typeControl) + { + serialize_control(drawing_state); + } } void xlsx_drawing_context::serialize_group() @@ -640,7 +821,7 @@ void xlsx_drawing_context::serialize_group() drawing_state->shape = strm.str(); } -void xlsx_drawing_context::serialize_shape_comment(_drawing_state_ptr & drawing_state) +void xlsx_drawing_context::serialize_vml_shape(_drawing_state_ptr & drawing_state) { std::wstringstream strm; @@ -651,18 +832,23 @@ void xlsx_drawing_context::serialize_shape_comment(_drawing_state_ptr & drawing_ strmStyle << L"position:absolute;"; strmStyle << L"margin-left:" << std::to_wstring(drawing_state->child_anchor.x / 12700.) << L"pt;"; //in pt (1 pt = 12700 emu) strmStyle << L"margin-top:" << std::to_wstring(drawing_state->child_anchor.y / 12700.) << L"pt;"; - strmStyle << L"width:" << std::to_wstring(drawing_state->child_anchor.cx / 12700.) << L"pt;"; - strmStyle << L"height:" << std::to_wstring(drawing_state->child_anchor.cy / 12700.) << L"pt;"; - strmStyle << L"z-index:" << std::to_wstring(drawing_state->id) << L";"; + strmStyle << L"width:" << std::to_wstring(drawing_state->child_anchor.cx / 12700.) << L"pt;"; + strmStyle << L"height:" << std::to_wstring(drawing_state->child_anchor.cy / 12700.) << L"pt;"; + strmStyle << L"z-index:" << std::to_wstring(drawing_state->id) << L";"; if (drawing_state->object.visible == false) strmStyle << L"visibility:hidden;"; CP_XML_NODE(L"v:shape") { - //CP_XML_ATTR(L"id" , std::to_wstring(drawing_state->object.id)); - CP_XML_ATTR(L"type" , L"_x0000_t202"); - CP_XML_ATTR(L"fillcolor" , L"#" + drawing_state->fill.color.sRGB); + CP_XML_ATTR(L"id", L"_x0000_s" + std::to_wstring(drawing_state->id)); + + if (drawing_state->shape_id != msosptNotPrimitive) + { + CP_XML_ATTR(L"type", L"#_x0000_t" + std::to_wstring(drawing_state->shape_id)); + CP_XML_ATTR(L"o:spt", drawing_state->shape_id); + } + CP_XML_ATTR(L"fillcolor", L"#" + drawing_state->fill.color.sRGB); if (drawing_state->line.width > 0) { @@ -670,6 +856,32 @@ void xlsx_drawing_context::serialize_shape_comment(_drawing_state_ptr & drawing_ } CP_XML_ATTR(L"style", strmStyle.str()); + if (!current_drawing_states->back()->custom_verticles.empty() && + !current_drawing_states->back()->custom_segments.empty()) + { + PathParser oParser (current_drawing_states->back()->custom_segments, current_drawing_states->back()->custom_verticles, current_drawing_states->back()->custom_guides); + std::wstring path = oParser.GetVmlPath(); + + if (false == path.empty()) + CP_XML_ATTR(L"path", path); + } + if (drawing_state->type == external_items::typeControl) + { + CP_XML_ATTR(L"o:button", L"t"); + } + if (drawing_state->line.fill.type == fillNone) + { + CP_XML_ATTR(L"stroked", L"f"); + } + if (drawing_state->line.fill.type == fillNone) + { + CP_XML_ATTR(L"stroked", L"f"); + } + if (drawing_state->fill.type == fillNone) + { + CP_XML_ATTR(L"filled", L"f"); + } +//---------------------------------------------------------------------------------------------- CP_XML_NODE(L"v:shadow") { CP_XML_ATTR(L"color", L"black"); @@ -696,7 +908,14 @@ void xlsx_drawing_context::serialize_shape_comment(_drawing_state_ptr & drawing_ CP_XML_ATTR(L"o:relid" , rId); CP_XML_ATTR(L"type" , L"tile"); - vml_comments_rels_->add(isIternal, rId , drawing_state->fill.texture_target, external_items::typeImage); + if (current_drawing_states->back()->vml_HF_mode_ ) + { + vml_HF_rels_->add(isIternal, rId , drawing_state->fill.texture_target, external_items::typeImage); + } + else + { + vml_rels_->add(isIternal, rId , drawing_state->fill.texture_target, external_items::typeImage); + } } else if (drawing_state->fill.type == fillGradient || drawing_state->fill.type == fillGradientOne) { @@ -725,10 +944,43 @@ void xlsx_drawing_context::serialize_shape_comment(_drawing_state_ptr & drawing_ case lineDashDot: CP_XML_ATTR(L"dashstyle", L"dashDot"); break; case lineDashDotDot:CP_XML_ATTR(L"dashstyle", L"lgDashDotDot"); break; } - } + } + if (!drawing_state->text.vml_content.empty()) + { + CP_XML_NODE(L"v:textbox") + { + //style='mso-direction-alt:auto' + //o:singleclick="f" + CP_XML_STREAM() << drawing_state->text.vml_content; + } + } CP_XML_NODE(L"x:ClientData") { - CP_XML_ATTR(L"ObjectType", L"Note"); + switch(drawing_state->type_control) + { + case 0x0000: CP_XML_ATTR(L"ObjectType", L"Group"); break; + case 0x0001: CP_XML_ATTR(L"ObjectType", L"Shape"); break; // Line + case 0x0002: CP_XML_ATTR(L"ObjectType", L"Rect"); break; + case 0x0003: CP_XML_ATTR(L"ObjectType", L"Shape"); break; // Oval + case 0x0004: CP_XML_ATTR(L"ObjectType", L"Shape"); break; // Arc + case 0x0006: CP_XML_ATTR(L"ObjectType", L"Shape"); break; // Text + case 0x0007: CP_XML_ATTR(L"ObjectType", L"Button"); break; + case 0x0008: CP_XML_ATTR(L"ObjectType", L"Pict"); break; + case 0x0009: CP_XML_ATTR(L"ObjectType", L"Shape"); break; // Polygon: + case 0x000B: CP_XML_ATTR(L"ObjectType", L"Checkbox"); break; + case 0x000C: CP_XML_ATTR(L"ObjectType", L"Radio"); break; + case 0x000D: CP_XML_ATTR(L"ObjectType", L"Edit"); break; + case 0x000E: CP_XML_ATTR(L"ObjectType", L"Label"); break; + case 0x000F: CP_XML_ATTR(L"ObjectType", L"Dialog"); break; + case 0x0010: CP_XML_ATTR(L"ObjectType", L"Spin"); break; + case 0x0012: CP_XML_ATTR(L"ObjectType", L"List"); break; + case 0x0013: CP_XML_ATTR(L"ObjectType", L"GBox"); break; + case 0x0011: CP_XML_ATTR(L"ObjectType", L"Scroll"); break; + case 0x0014: CP_XML_ATTR(L"ObjectType", L"Drop"); break; + case 0x001E: CP_XML_ATTR(L"ObjectType", L"Shape"); break; // OfficeArt object + case 0x0019: CP_XML_ATTR(L"ObjectType", L"Note"); break; + default: break; + } CP_XML_NODE(L"x:MoveWithCells"){} CP_XML_NODE(L"x:SizeWithCells"){} @@ -748,16 +1000,22 @@ void xlsx_drawing_context::serialize_shape_comment(_drawing_state_ptr & drawing_ CP_XML_NODE(L"x:AutoFill") {CP_XML_CONTENT("False");} CP_XML_NODE(L"x:Row") {CP_XML_CONTENT(drawing_state->object.row);} CP_XML_NODE(L"x:Column") {CP_XML_CONTENT(drawing_state->object.col);} - + if (drawing_state->object.visible) CP_XML_NODE(L"x:Visible"); + + if (!drawing_state->object.macro.empty()) + { + CP_XML_NODE(L"x:FmlaMacro"){CP_XML_CONTENT(drawing_state->object.macro);} + } + if (!drawing_state->object.link.empty() ) + { + CP_XML_NODE(L"x:FmlaLink"){CP_XML_CONTENT(drawing_state->object.link);} + } } } } - drawing_state->shape = strm.str(); -} -void xlsx_drawing_context::serialize_vml_shape(_drawing_state_ptr & drawing_state) -{ + drawing_state->vml_shape = strm.str(); } void xlsx_drawing_context::serialize_vml_pic(_drawing_state_ptr & drawing_state, std::wstring rId) { @@ -790,12 +1048,12 @@ void xlsx_drawing_context::serialize_vml_pic(_drawing_state_ptr & drawing_state, } } } - drawing_state->shape = strm.str(); + drawing_state->vml_shape = strm.str(); } void xlsx_drawing_context::serialize_pic(_drawing_state_ptr & drawing_state, std::wstring rId) { - if (drawing_state->vmlwrite_mode_) + if (drawing_state->vml_HF_mode_) return serialize_vml_pic(drawing_state, rId); std::wstringstream strm; @@ -804,7 +1062,7 @@ void xlsx_drawing_context::serialize_pic(_drawing_state_ptr & drawing_state, std { CP_XML_NODE(L"xdr:pic") { - CP_XML_ATTR(L"macro", drawing_state->macro); + CP_XML_ATTR(L"macro", drawing_state->object.macro); CP_XML_NODE(L"xdr:nvPicPr") { @@ -914,10 +1172,73 @@ void xlsx_drawing_context::serialize_chart(_drawing_state_ptr & drawing_state, s } drawing_state->shape = strm.str(); } +void xlsx_drawing_context::serialize_control(_drawing_state_ptr & drawing_state) +{ + std::wstringstream strm; + CP_XML_WRITER(strm) + { + CP_XML_NODE(L"xdr:sp") + { + CP_XML_NODE(L"xdr:nvSpPr") + { + CP_XML_NODE(L"xdr:cNvPr") + { + CP_XML_ATTR(L"id", drawing_state->id); + + if (drawing_state->name.empty()) + { + drawing_state->name = L"Control_" + std::to_wstring(count_object); + } + CP_XML_ATTR(L"name", drawing_state->name); + + if (!drawing_state->description.empty()) + { + CP_XML_ATTR(L"descr", drawing_state->description); + } + CP_XML_ATTR(L"hidden", 1); + CP_XML_NODE(L"a:extLst") + { + CP_XML_NODE(L"a:ext") + { + CP_XML_ATTR(L"uri", L"{63B3BB69-23CF-44E3-9099-C40C66FF867C}"); + CP_XML_ATTR(L"xmlns:a14", L"http://schemas.microsoft.com/office/drawing/2010/main"); + + CP_XML_NODE(L"a14:compatExt") + { + CP_XML_ATTR(L"spid", L"_x0000_s" + std::to_wstring(drawing_state->id)); + } + } + } + } + CP_XML_NODE(L"xdr:cNvSpPr"); + } + + CP_XML_NODE(L"xdr:spPr") + { + serialize_xfrm(CP_XML_STREAM(), drawing_state); + + CP_XML_NODE(L"a:prstGeom") + { + CP_XML_ATTR(L"prst", L"rect"); + if (!drawing_state->wordart.is) CP_XML_NODE(L"a:avLst"); + } + CP_XML_NODE(L"a:noFill"); + CP_XML_NODE(L"a:ln") + { + CP_XML_NODE(L"a:noFill"); + } + } + serialize_text(CP_XML_STREAM(), drawing_state); + } + } + drawing_state->shape = strm.str(); + + serialize_vml_shape(drawing_state); +} void xlsx_drawing_context::serialize_shape(_drawing_state_ptr & drawing_state) { - if (drawing_state->vmlwrite_mode_) + if (drawing_state->vml_HF_mode_) return serialize_vml_shape(drawing_state); std::wstringstream strm; @@ -949,7 +1270,7 @@ void xlsx_drawing_context::serialize_shape(_drawing_state_ptr & drawing_state) { CP_XML_NODE(L"xdr:sp") { - CP_XML_ATTR(L"macro", drawing_state->macro); + CP_XML_ATTR(L"macro", drawing_state->object.macro); CP_XML_NODE(L"xdr:nvSpPr") { @@ -1748,11 +2069,6 @@ void xlsx_drawing_context::serialize_bitmap_fill(std::wostream & stream, _drawin } } -void xlsx_drawing_context::serialize_vml(std::wostream & stream, _drawing_state_ptr & drawing_state) -{ - stream << drawing_state->shape; -} - void xlsx_drawing_context::serialize(std::wostream & stream, _drawing_state_ptr & drawing_state) { if (drawing_state->type_anchor == 0) return; @@ -1836,7 +2152,7 @@ void xlsx_drawing_context::set_macro(const std::wstring & str) { if (current_drawing_states == NULL) return; - current_drawing_states->back()->macro = str; + current_drawing_states->back()->object.macro = str; } void xlsx_drawing_context::set_ole_object(const std::wstring & id, const std::wstring & info) { @@ -2446,6 +2762,13 @@ void xlsx_drawing_context::set_text (const std::wstring & text) current_drawing_states->back()->text.content = text; } +void xlsx_drawing_context::set_text_vml (const std::wstring & text) +{ + if (current_drawing_states == NULL) return; + if (current_drawing_states->empty()) return; + + current_drawing_states->back()->text.vml_content = text; +} void xlsx_drawing_context::set_text_wrap (int val) { if (current_drawing_states == NULL) return; @@ -2547,25 +2870,29 @@ void xlsx_drawing_context::set_custom_y_limo(int val) current_drawing_states->back()->custom_y_limo = val; } //---------------------------------------------------------------------------------------------------------- -bool xlsx_drawing_context::get_mode_vmlwrite () +bool xlsx_drawing_context::get_mode_HF () {//comment, shapes in header/footer, .... if (current_drawing_states == NULL) return false; if (current_drawing_states->empty()) return false; - return current_drawing_states->back()->vmlwrite_mode_; + return current_drawing_states->back()->vml_HF_mode_; } -void xlsx_drawing_context::set_mode_vmlwrite (bool val) +void xlsx_drawing_context::set_mode_HF (bool val) {//comment, shapes in header/footer, .... if (current_drawing_states == NULL) return; if (current_drawing_states->empty()) return; - current_drawing_states->back()->vmlwrite_mode_ = val; + current_drawing_states->back()->vml_HF_mode_ = val; } //---------------------------------------------------------------------------------------------------------- bool xlsx_drawing_context::empty() { return drawing_states.empty(); } +bool xlsx_drawing_context::empty_vml() +{ + return drawing_states_vml.empty(); +} bool xlsx_drawing_context::empty_vml_HF() { return drawing_states_vml_HF.empty(); @@ -2578,9 +2905,9 @@ xlsx_drawings_rels_ptr xlsx_drawing_context::get_vml_HF_rels() { return vml_HF_rels_; } -xlsx_drawings_rels_ptr xlsx_drawing_context::get_vml_comments_rels() +xlsx_drawings_rels_ptr xlsx_drawing_context::get_vml_rels() { - return vml_comments_rels_; + return vml_rels_; } xlsx_drawings_rels_ptr xlsx_drawing_context::get_sheet_rels() { @@ -2608,6 +2935,7 @@ void xlsx_drawing_context::serialize_objects(std::wostream & strm) serialize_object(strm, drawing_states[i]); } } +//------------------------------------------------------------------------------------------------------------------- void xlsx_drawing_context::serialize_vml_HF(std::wostream & strm) { CP_XML_WRITER(strm) @@ -2620,13 +2948,13 @@ void xlsx_drawing_context::serialize_vml_HF(std::wostream & strm) for (size_t i = 0 ; i < drawing_states_vml_HF.size(); i++) { - serialize_vml(CP_XML_STREAM(), drawing_states_vml_HF[i]); + CP_XML_STREAM() << drawing_states_vml_HF[i]->vml_shape; } } } } -void xlsx_drawing_context::serialize_vml_comments(std::wostream & strm) +void xlsx_drawing_context::serialize_vml(std::wostream & strm) { CP_XML_WRITER(strm) { @@ -2636,27 +2964,9 @@ void xlsx_drawing_context::serialize_vml_comments(std::wostream & strm) CP_XML_ATTR(L"xmlns:o" , L"urn:schemas-microsoft-com:office:office"); CP_XML_ATTR(L"xmlns:x" , L"urn:schemas-microsoft-com:office:excel"); - CP_XML_NODE(L"v:shapetype") + for (size_t i = 0 ; i < drawing_states_vml.size(); i++) { - CP_XML_ATTR(L"id" , L"_x0000_t202"); - CP_XML_ATTR(L"coordsize", L"21600,21600"); - CP_XML_ATTR(L"o:spt" , L"202"); - CP_XML_ATTR(L"path" , L"m,l,21600r21600,l21600,xe"); - - CP_XML_NODE(L"v:stroke") - { - CP_XML_ATTR(L"joinstyle", L"miter"); - } - CP_XML_NODE(L"v:path") - { - CP_XML_ATTR(L"gradientshapeok", L"t"); - CP_XML_ATTR(L"o:connecttype", L"rect"); - } - } - - for (size_t i = 0 ; i < drawing_states_vml_comments.size(); i++) - { - serialize_vml(CP_XML_STREAM(), drawing_states_vml_comments[i]); + CP_XML_STREAM() << drawing_states_vml[i]->vml_shape; } } diff --git a/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_drawing_context.h b/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_drawing_context.h index de3dba368a..b3539c02e2 100644 --- a/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_drawing_context.h +++ b/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_drawing_context.h @@ -135,7 +135,7 @@ public: flipH(false), flipV(false), bTextBox(false), type_anchor(0), - vmlwrite_mode_(false), + vml_HF_mode_(false), hidden(false) { id = -1; @@ -143,18 +143,21 @@ public: parent_drawing_states = NULL; custom_path = -1; custom_x_limo = 0x80000000; - custom_y_limo = 0x80000000; + custom_y_limo = 0x80000000; + + type_control = -1; } external_items::Type type; bool hidden; std::wstring name; std::wstring description; - std::wstring macro; std::wstring objectId; std::wstring objectProgId; + int type_control; + struct _anchor { int colFrom = -1; @@ -172,8 +175,10 @@ public: int type_anchor; - bool vmlwrite_mode_; + bool vml_HF_mode_; + std::wstring shape; + std::wstring vml_shape; int id; MSOSPT shape_id; @@ -204,7 +209,8 @@ public: margins.left = margins.right = 0x00016530; margins.top = margins.bottom = 0x0000b298; } - std::wstring content; //c форматированием + std::wstring content; //c форматированием oox + std::wstring vml_content; //c форматированием vml int wrap; int align; int vert_align; @@ -289,11 +295,13 @@ public: }line; struct _object { - _object() {visible = false; col = row = 0; id = 0;} + _object() {visible = true; col = row = 0; id = 0;} int id; bool visible; int col; int row; + std::wstring macro; + std::wstring link; }object; //for group std::vector<_drawing_state_ptr> drawing_states; @@ -317,10 +325,11 @@ public: xlsx_drawings_rels_ptr get_rels(); xlsx_drawings_rels_ptr get_vml_HF_rels(); - xlsx_drawings_rels_ptr get_vml_comments_rels(); + xlsx_drawings_rels_ptr get_vml_rels(); xlsx_drawings_rels_ptr get_sheet_rels(); bool empty(); + bool empty_vml(); bool empty_vml_HF(); void start_group(); @@ -330,14 +339,15 @@ public: void start_shape(int type); void start_chart(); void start_comment(); + void start_control(int type); void set_id (int id); void set_FlipH (); void set_FlipV (); void set_shape_id (int id); //-------------------------------------------------------------------------------------- - void set_mode_vmlwrite (bool val); - bool get_mode_vmlwrite (); + void set_mode_HF (bool val); + bool get_mode_HF (); //-------------------------------------------------------------------------------------- void set_name (const std::wstring & str); void set_description (const std::wstring & str); @@ -392,6 +402,7 @@ public: void set_hyperlink (const std::wstring & link, const std::wstring & display, bool is_external); void set_text (const std::wstring & text); + void set_text_vml (const std::wstring & text); void set_text_wrap (int val); void set_text_align (int val); void set_text_vert_align (int val); @@ -412,6 +423,7 @@ public: void set_object_id (int val); void set_object_visible (bool val); void set_object_anchor (int col, int row); + void set_object_link (const std::wstring & text); //--------------------------------------------------------------------------------------------- void set_custom_rect (_rect & rect); void set_custom_verticles (std::vector & points); @@ -431,8 +443,7 @@ public: void serialize_chart (_drawing_state_ptr & drawing_state, std::wstring rId ); void serialize_pic (_drawing_state_ptr & drawing_state, std::wstring rId ); void serialize_object (_drawing_state_ptr & drawing_state, std::wstring rId ); - - void serialize_shape_comment(_drawing_state_ptr & drawing_state); //part of vml shape + void serialize_control (_drawing_state_ptr & drawing_state); //----------------------------------------------------------------------------------- void serialize_vml_shape (_drawing_state_ptr & drawing_state); void serialize_vml_pic (_drawing_state_ptr & drawing_state, std::wstring rId ); @@ -441,12 +452,11 @@ public: void serialize_fill (std::wostream & stream); //----------------------------------------------------------------------------------- void serialize (std::wostream & stream, _drawing_state_ptr & drawing_state); - void serialize_vml (std::wostream & stream, _drawing_state_ptr & drawing_state); void serialize_object (std::wostream & stream, _drawing_state_ptr & drawing_state); + void serialize_objects (std::wostream & stream); //----------------------------------------------------------------------------------- void serialize_vml_HF (std::wostream & stream); - void serialize_vml_comments (std::wostream & stream); - void serialize_objects (std::wostream & stream); + void serialize_vml (std::wostream & stream); void serialize (std::wostream & stream); //----------------------------------------------------------------------------------- bool is_lined_shape (_drawing_state_ptr & drawing_state); @@ -459,7 +469,7 @@ private: xlsx_drawing_context_handle & handle_; xlsx_drawings_rels_ptr rels_; - xlsx_drawings_rels_ptr vml_comments_rels_; + xlsx_drawings_rels_ptr vml_rels_; xlsx_drawings_rels_ptr vml_HF_rels_; xlsx_drawings_rels_ptr sheet_rels_; @@ -469,7 +479,7 @@ private: std::vector<_hlink_desc> hlinks_; std::vector<_drawing_state_ptr> drawing_states_vml_HF; - std::vector<_drawing_state_ptr> drawing_states_vml_comments; + std::vector<_drawing_state_ptr> drawing_states_vml; std::vector<_drawing_state_ptr> drawing_states; std::vector<_drawing_state_ptr>* current_drawing_states; diff --git a/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_output_xml.cpp b/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_output_xml.cpp index 6eb6b38b69..23079487d4 100644 --- a/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_output_xml.cpp +++ b/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_output_xml.cpp @@ -78,8 +78,8 @@ public: std::wstring vml_drawingName_; std::wstring vml_drawingId_; - std::wstring vml_drawingName_HF_; - std::wstring vml_drawingId_HF_; + std::wstring vml_HF_drawingName_; + std::wstring vml_HF_drawingId_; }; std::wstring xlsx_xml_worksheet::name() const @@ -223,18 +223,18 @@ void xlsx_xml_worksheet::write_to(std::wostream & strm) CP_XML_STREAM() << impl_->drawing_.str(); - if (!impl_->commentsId_.empty() && !impl_->vml_drawingId_.empty()) + if (!impl_->vml_drawingId_.empty()) { CP_XML_NODE(L"legacyDrawing") { CP_XML_ATTR(L"r:id", impl_->vml_drawingId_); } } - if (!impl_->vml_drawingId_HF_.empty()) + if (!impl_->vml_HF_drawingId_.empty()) { CP_XML_NODE(L"legacyDrawingHF") { - CP_XML_ATTR(L"r:id", impl_->vml_drawingId_HF_); + CP_XML_ATTR(L"r:id", impl_->vml_HF_drawingId_); } } if (!impl_->ole_objects_.str().empty()) @@ -271,10 +271,10 @@ void xlsx_xml_worksheet::set_vml_drawing_link(std::wstring const & fileName, std impl_->vml_drawingName_ = fileName; impl_->vml_drawingId_ = id; } -void xlsx_xml_worksheet::set_vml_drawing_link_HF(std::wstring const & fileName, std::wstring const & id) +void xlsx_xml_worksheet::set_vml_HF_drawing_link(std::wstring const & fileName, std::wstring const & id) { - impl_->vml_drawingName_HF_ = fileName; - impl_->vml_drawingId_HF_ = id; + impl_->vml_HF_drawingName_ = fileName; + impl_->vml_HF_drawingId_ = id; } std::pair xlsx_xml_worksheet::get_drawing_link() const { @@ -290,7 +290,7 @@ std::pair xlsx_xml_worksheet::get_vml_drawing_link() } std::pair xlsx_xml_worksheet::get_vml_drawing_HF_link() const { - return std::pair(impl_->vml_drawingName_HF_, impl_->vml_drawingId_HF_); + return std::pair(impl_->vml_HF_drawingName_, impl_->vml_HF_drawingId_); } } diff --git a/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_output_xml.h b/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_output_xml.h index ec7a6d5f9e..2a02935003 100644 --- a/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_output_xml.h +++ b/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_output_xml.h @@ -77,7 +77,7 @@ public: void set_vml_drawing_link (std::wstring const & fileName, std::wstring const & id); void set_comments_link (std::wstring const & fileName, std::wstring const & id); void set_state (std::wstring const & state); - void set_vml_drawing_link_HF(std::wstring const & fileName, std::wstring const & id); + void set_vml_HF_drawing_link(std::wstring const & fileName, std::wstring const & id); std::pair get_drawing_link() const; std::pair get_vml_drawing_link() const; diff --git a/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_tablecontext.cpp b/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_tablecontext.cpp index 99db2f8bd9..5d2cda10c1 100644 --- a/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_tablecontext.cpp +++ b/ASCOfficeXlsFile2/source/XlsXlsxConverter/xlsx_tablecontext.cpp @@ -104,25 +104,27 @@ void xlsx_table_context::end_table() const std::pair vmlDrawingName = context_.get_drawing_context_handle().add_drawing_vml(strm.str(), get_drawing_context().get_vml_HF_rels()); - context_.current_sheet().set_vml_drawing_link_HF(vmlDrawingName.first, vmlDrawingName.second); + context_.current_sheet().set_vml_HF_drawing_link(vmlDrawingName.first, vmlDrawingName.second); + } + if (!get_drawing_context().empty_vml()) + { + std::wstringstream strm; + get_drawing_context().serialize_vml(strm); + + const std::pair vmlDrawingName = + context_.get_drawing_context_handle().add_drawing_vml(strm.str(), get_drawing_context().get_vml_rels()); + context_.current_sheet().set_vml_drawing_link(vmlDrawingName.first, vmlDrawingName.second); } if (!get_comments_context().empty()) { std::wstringstream strm; get_comments_context().write_comments(strm); - std::wstringstream vml_strm; - get_drawing_context().serialize_vml_comments(vml_strm); - const std::pair commentsName = context_.get_comments_context_handle().add_comments_xml(strm.str(), context_.get_comments_context().get_comments()); - const std::pair vmlDrawingName = - context_.get_drawing_context_handle().add_drawing_vml(vml_strm.str(), get_drawing_context().get_vml_comments_rels()); - context_.current_sheet().set_comments_link (commentsName.first, commentsName.second); - context_.current_sheet().set_vml_drawing_link (vmlDrawingName.first, vmlDrawingName.second); } } diff --git a/Common/3dParty/pole/pole.cpp b/Common/3dParty/pole/pole.cpp index 7951b9da89..760602ab48 100644 --- a/Common/3dParty/pole/pole.cpp +++ b/Common/3dParty/pole/pole.cpp @@ -125,6 +125,7 @@ class DirEntry public: DirEntry(): valid(), name(), dir(), size(), start(), prev(), next(), child() {} bool valid; // false if invalid (should be skipped) + unsigned char prefix; std::string name; // the name, not in unicode anymore bool dir; // true if directory uint64 size; // size (not valid if directory) @@ -805,49 +806,67 @@ DirEntry* DirTree::entry( const std::string& name, bool create, int64 bigBlockSi } else { - // not found among children - if( !create || !io->writeable) + std::vector chi = children( index ); + for( unsigned i = 0; i < chi.size(); i++ ) + { + DirEntry* ce = entry( chi[i] ); + if( ce ) + if( ce->valid && ( ce->name.length()>1 ) ) + if( ce->name == *it ) + { + child = chi[i]; + break; + } + } + } + if( child > 0 ) + { + index = child; + } + else + { + // not found among children ..wrong header??? + if( !create || !io->writeable) + { + return (DirEntry*)0; + } + // create a new entry + uint64 parent2 = index; + index = unused(); + DirEntry* e = entry( index ); + e->valid = true; + e->name = *it; + e->dir = (levelsLeft > 0); + if (!e->dir) + e->size = streamSize; + else + e->size = 0; + e->start = AllocTable::Eof; + e->child = End; + if (closest == End) { - return (DirEntry*)0; + e->prev = End; + e->next = entry(parent2)->child; + entry(parent2)->child = index; + markAsDirty(parent2, bigBlockSize); + } + else + { + DirEntry* closeE = entry( closest ); + if (closeE->compare(*e) < 0) + { + e->prev = closeE->next; + e->next = End; + closeE->next = index; + } + else + { + e->next = closeE->prev; + e->prev = End; + closeE->prev = index; + } + markAsDirty(closest, bigBlockSize); } - - // create a new entry - uint64 parent2 = index; - index = unused(); - DirEntry* e = entry( index ); - e->valid = true; - e->name = *it; - e->dir = (levelsLeft > 0); - if (!e->dir) - e->size = streamSize; - else - e->size = 0; - e->start = AllocTable::Eof; - e->child = End; - if (closest == End) - { - e->prev = End; - e->next = entry(parent2)->child; - entry(parent2)->child = index; - markAsDirty(parent2, bigBlockSize); - } - else - { - DirEntry* closeE = entry( closest ); - if (closeE->compare(*e) < 0) - { - e->prev = closeE->next; - e->next = End; - closeE->next = index; - } - else - { - e->next = closeE->prev; - e->prev = End; - closeE->prev = index; - } - markAsDirty(closest, bigBlockSize); - } markAsDirty(index, bigBlockSize); uint64 bbidx = index / (bigBlockSize / 128); std::vector blocks = io->bbat->follow(io->header->dirent_start); @@ -937,7 +956,7 @@ void DirTree::load( unsigned char* buffer, uint64 size ) uint64 p = i * 128; // would be < 32 if first char in the name isn't printable - unsigned prefix = 32; + unsigned char prefix = 32; // parse name of this entry, which stored as Unicode 16-bit std::string name; @@ -949,7 +968,7 @@ void DirTree::load( unsigned char* buffer, uint64 size ) // first char isn't printable ? remove it... if( buffer[p] < 32 ) { - prefix = buffer[0]; + prefix = name[0]; name.erase( 0,1 ); } @@ -959,6 +978,7 @@ void DirTree::load( unsigned char* buffer, uint64 size ) DirEntry e; e.valid = ( type != 0 ); e.name = name; + e.prefix = prefix; e.start = readU32( buffer + 0x74+p ); e.size = readU32( buffer + 0x78+p ); e.prev = readU32( buffer + 0x44+p ); @@ -2225,12 +2245,35 @@ std::list Storage::entries( const std::string& path ) uint64 parent = dt->indexOf( e ); std::vector children = dt->children( parent ); for( uint64 i = 0; i < children.size(); i++ ) - localResult.push_back( dt->entry( children[i] )->name ); + { + localResult.push_back( dt->entry( children[i] )->name ); + } } return localResult; } +std::list Storage::entries_with_prefix( const std::string& path ) +{ + std::list localResult; + DirTree* dt = io->dirtree; + DirEntry* e = dt->entry( path, false ); + if( e && e->dir ) + { + uint64 parent = dt->indexOf( e ); + std::vector children = dt->children( parent ); + for( uint64 i = 0; i < children.size(); i++ ) + { + std::string val; + if (dt->entry( children[i] )->prefix != 32) + val = (char) dt->entry( children[i] )->prefix; + val += dt->entry( children[i] )->name; + localResult.push_back(val); + } + } + + return localResult; +} bool Storage::isDirectory( const std::string& name ) { DirEntry* e = io->dirtree->entry( name, false ); @@ -2271,7 +2314,9 @@ void CollectStreams( std::list& result, DirTree* tree, DirEntry* pa DirEntry* c = tree->entry( parent->child ); std::queue queue; if ( c ) queue.push( c ); - while ( !queue.empty() ) { + + while ( !queue.empty() ) + { DirEntry* e = queue.front(); queue.pop(); if ( e->dir ) diff --git a/Common/3dParty/pole/pole.h b/Common/3dParty/pole/pole.h index d3b3381f51..effa2b9508 100644 --- a/Common/3dParty/pole/pole.h +++ b/Common/3dParty/pole/pole.h @@ -124,6 +124,7 @@ public: * Finds all stream and directories in given path. **/ std::list entries( const std::string& path = "/" ); + std::list entries_with_prefix( const std::string& path = "/" ); /** * Returns true if specified entry name is a directory. diff --git a/XlsxSerializerCom/Reader/BinaryWriter.h b/XlsxSerializerCom/Reader/BinaryWriter.h index 760279f3e1..54b0e54567 100644 --- a/XlsxSerializerCom/Reader/BinaryWriter.h +++ b/XlsxSerializerCom/Reader/BinaryWriter.h @@ -3019,6 +3019,8 @@ namespace BinXlsxRW else pCellAnchor = new OOX::Spreadsheet::CCellAnchor(eAnchorType); + pCellAnchor->m_bShapeOle= true; + PPTX::Logic::Pic *olePic = new PPTX::Logic::Pic; olePic->oleObject.Init();