Files
DocumentServer-v-9.2.0/core/MsBinaryFile/DocFile/VMLShapeMapping.cpp
T
Yajbir Singh f1b860b25c
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

2512 lines
73 KiB
C++

/*
* (c) Copyright Ascensio System SIA 2010-2023
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "VMLShapeMapping.h"
#include "TextboxMapping.h"
#include "OfficeDrawing/Shapetypes/LineType.h"
#include "OfficeDrawing/Shapetypes/OvalType.h"
#include "OfficeDrawing/Shapetypes/RectangleType.h"
#include "OfficeDrawing/Shapetypes/RoundedRectangleType.h"
#include "OfficeDrawing/OfficeArtClientTextbox.h"
#include "DrawingPrimitives.h"
#include "../../DesktopEditor/common/StringExt.h"
#include "../Common/Base/FormatUtils.h"
#include "../XlsFile/Format/Logic/Biff_structures/ODRAW/OfficeArtFOPTE.h"
namespace DocFileFormat
{
VMLShapeMapping::VMLShapeMapping (ConversionContext* pConv, XMLTools::CStringXmlWriter* pWriter, Spa* pSpa, PictureDescriptor* pPicture, IMapping* pCaller, bool isInlineShape, bool inGroup) : PropertiesMapping(pWriter)
{
m_inGroup = inGroup;
m_isInlineShape = isInlineShape;
m_isBullete = false;
m_isPictureBroken = false;
m_pSpa = pSpa;
m_pCaller = pCaller;
m_pBlipStore = NULL;
m_context = pConv;
m_pict = pPicture;
m_nImageId = 0;
m_imagedata = XMLTools::XMLElement(L"v:imagedata");
m_fill = XMLTools::XMLElement(L"v:fill");
m_stroke = XMLTools::XMLElement(L"v:stroke");
m_shadow = XMLTools::XMLElement(L"v:shadow");
m_3dstyle = XMLTools::XMLElement(L"o:extrusion");
m_textpath = XMLTools::XMLElement(L"v:textpath");
Record* recBs = NULL;
if ((m_context) && (m_context->_doc))
{
OfficeArtContent* officeArt = m_context->_doc->GetOfficeArt();
if (officeArt)
{
const DrawingGroup* group = officeArt->GetDrawingGroup();
if (group)
{
recBs = group->FirstChildWithType<BlipStoreContainer>();
}
}
}
if (recBs)
{
m_pBlipStore = static_cast<BlipStoreContainer*>(recBs);
}
for (int i = 0; i < 8; ++i)
{
m_nAdjValues[i] = 0x7fffffff;
}
}
VMLShapeMapping::~VMLShapeMapping()
{
}
}
namespace DocFileFormat
{
void VMLShapeMapping::Apply(IVisitable* visited)
{
DrawingPrimitives * primitives = dynamic_cast<DrawingPrimitives *>(visited);
if ( primitives ) return ApplyPrimitives(primitives);
//----------------------------------------------------------------------------------------------
ShapeContainer* pContainer = dynamic_cast<ShapeContainer*>(visited);
if ((pContainer != NULL) && (!pContainer->Children.empty()))
{
Record* firstRecord = pContainer->Children[0];
if (firstRecord != NULL)
{
if (typeid(*firstRecord) == typeid(Shape))
{
// It's a single shape
WriteShape(pContainer);
}
else if (typeid(*firstRecord) == typeid(GroupShapeRecord))
{
// Its a group of shapes
WriteGroup(static_cast<GroupContainer*>(pContainer->_ParentRecord));
}
}
}
}
/// Converts a group of shapes
void VMLShapeMapping::WriteGroup (const GroupContainer* container)
{
if ((container != NULL) && (!container->Children.empty()))
{
ShapeContainer* groupShape = static_cast<ShapeContainer*>(container->Children[0]);
GroupShapeRecord* gsr = static_cast<GroupShapeRecord*>(groupShape->Children[0]);
Shape* shape = static_cast<Shape*>(groupShape->Children[1]);
ChildAnchor* anchor = groupShape->FirstChildWithType<ChildAnchor>();
std::vector<ODRAW::OfficeArtFOPTEPtr> options = groupShape->ExtractOptions();
m_shapeId = GetShapeID(shape);
m_pXmlWriter->WriteNodeBegin( L"v:group", true );
m_pXmlWriter->WriteAttribute( L"id", m_shapeId);
bool layoutInCell = true;
bool twistDimensions = false;
m_pXmlWriter->WriteAttribute( L"style", FormatUtils::XmlEncode(buildStyle(shape, anchor, options, container->Index, twistDimensions)));
m_pXmlWriter->WriteAttribute( L"coordorigin", ( std::to_wstring(gsr->rcgBounds.topLeftAngle.x) + L"," + std::to_wstring( gsr->rcgBounds.topLeftAngle.y)));
m_pXmlWriter->WriteAttribute( L"coordsize", ( std::to_wstring(gsr->rcgBounds.size.cx) + L"," + std::to_wstring(gsr->rcgBounds.size.cy)));
// Write wrap coords
for (size_t i = 0; i < options.size(); i++)
{
switch (options[i]->opid)
{
case ODRAW::pWrapPolygonVertices:
{
std::wstring wrapCoords = GetWrapCoords(options[i]);
if (!wrapCoords.empty())
m_pXmlWriter->WriteAttribute(L"wrapcoords", wrapCoords);
}break;
case ODRAW::groupShapeBooleanProperties:
{
ODRAW::GroupShapeBooleanProperties *booleans = dynamic_cast<ODRAW::GroupShapeBooleanProperties *>(options[i].get());
if (booleans && booleans->fUsefLayoutInCell)
{
layoutInCell = booleans->fLayoutInCell;
}
}
break;
default:
break;
}
}
if (!layoutInCell)
{
m_pXmlWriter->WriteAttribute(L"o:allowincell", L"f");
}
m_pXmlWriter->WriteNodeEnd(L"", true, false);
// Convert the shapes/groups in the group
size_t count = container->Children.size();
for (size_t i = 1; i < count; ++i)
{
if (container->Children[i])
{
if (typeid(*container->Children[i]) == typeid(ShapeContainer))
{
ShapeContainer* pChildShape = static_cast<ShapeContainer*>(container->Children[i]);
if (pChildShape)
{
VMLShapeMapping vmlShapeMapping(m_context, m_pXmlWriter, m_pSpa, NULL, m_pCaller, false, true);
pChildShape->Convert(&vmlShapeMapping);
}
}
else if (typeid(*container->Children[i]) == typeid(GroupContainer))
{
GroupContainer* pChildGroup = static_cast<GroupContainer*>(container->Children[i]);
m_pSpa = NULL;
WriteGroup(pChildGroup);
}
}
}
// Write wrap
if (m_pSpa)
{
std::wstring wrap = getWrapType(m_pSpa);
if (wrap != L"through")
{
m_pXmlWriter->WriteNodeBegin( L"w10:wrap", true );
m_pXmlWriter->WriteAttribute( L"type", wrap);
m_pXmlWriter->WriteNodeEnd ( L"w10:wrap", true );
}
}
m_pXmlWriter->WriteNodeEnd( L"v:group" );
}
}
/// Converts a single shape
void VMLShapeMapping::WriteShape(const ShapeContainer* pContainer)
{
if ((NULL == pContainer) || (pContainer->Children.empty())) return;
Shape* pShape = static_cast<Shape*>(pContainer->Children[0]);
if (!pShape) return;
int indexOLE = -1;
bool freeform = true;
std::wstring sShapeId;
std::vector<ODRAW::OfficeArtFOPTEPtr> options = pContainer->ExtractOptions();
ChildAnchor* pAnchor = pContainer->FirstChildWithType<ChildAnchor>();
ClientAnchor* clientAnchor = pContainer->FirstChildWithType<ClientAnchor>();
WriteBeginShapeNode(pShape);
m_shapeId = GetShapeID(pShape);
if (m_shapeId.empty())
{
m_context->_doc->GetOfficeArt()->m_uLastShapeId++;
m_shapeId = std::wstring(L"_x0000_s") + std::to_wstring(m_context->_doc->GetOfficeArt()->m_uLastShapeId);
}
m_pXmlWriter->WriteAttribute(L"id", m_shapeId);
if (!pShape->fBackground)
{
bool twistDimensions = false;
if (pShape->GetShapeType())
{
freeform = false;
m_pXmlWriter->WriteAttribute(L"type", (std::wstring(L"#") + VMLShapeTypeMapping::GenerateTypeId(pShape->GetShapeType())));
}
m_pXmlWriter->WriteAttribute(L"style", FormatUtils::XmlEncode(buildStyle(pShape, pAnchor, options, pContainer->m_nIndex, twistDimensions)));
if (pShape->is<LineType>())
{
//append "from" and "to" attributes
m_pXmlWriter->WriteAttribute(L"from", GetLineFrom(pAnchor, twistDimensions));
m_pXmlWriter->WriteAttribute(L"to", GetLineTo(pAnchor, twistDimensions));
}
if (m_isBullete)
{
m_pXmlWriter->WriteAttribute(L"o:bullet", L"t");
}
}
boost::optional<EmuValue> ShadowOffsetX;
boost::optional<EmuValue> ShadowOffsetY;
boost::optional<EmuValue> SecondShadowOffsetX;
boost::optional<EmuValue> SecondShadowOffsetY;
boost::optional<EmuValue> ViewPointX;
boost::optional<EmuValue> ViewPointY;
boost::optional<EmuValue> ViewPointZ;
boost::optional<double> viewPointOriginX;
boost::optional<double> viewPointOriginY;
boost::optional<double> ShadowOriginX;
boost::optional<double> ShadowOriginY;
boost::optional<size_t> xCoord;
boost::optional<size_t> yCoord;
boost::optional<size_t> xCoord2;
boost::optional<size_t> yCoord2;
boost::optional<int> matrix[4];
bool bStroked = true;
bool bFilled = true;
bool hasTextbox = false;
bool layoutInCell = true; //anmeldebogenfos.doc
bool b3D = false;
bool bShadow = false;
bool bPicturePresent = false;
int ndxTextLeft = -1;
int ndyTextTop = -1;
int ndxTextRight = -1;
int ndyTextBottom = -1;
bool bHavePath = false;
int nShapePath = -1;
int nAdjValues = 0;
int nLTxID = -1;
int nProperty = 0;
std::wstring sTextboxStyle;
ODRAW::OfficeArtFOPTEPtr opSegmentInfo;
ODRAW::OfficeArtFOPTEPtr opVerticles;
ODRAW::OfficeArtFOPTEPtr opInscribe;
ODRAW::OfficeArtFOPTEPtr opConnectAngles;
ODRAW::OfficeArtFOPTEPtr opConnectLocs;
int nColorRGBBase = 0xffffff, nFillType = 0;
bool bFlipColors = false;
boost::optional<double> fill_left;
boost::optional<double> fill_top;
boost::optional<double> fill_right;
boost::optional<double> fill_bottom;
for (size_t i = 0; i < options.size(); i++)
{
ODRAW::OfficeArtFOPTEPtr& iter = options[i];
switch (iter->opid)
{
//BOOLEANS
case ODRAW::geometryBooleanProperties:
{
ODRAW::GeometryBooleanProperties* booleans = dynamic_cast<ODRAW::GeometryBooleanProperties*>(iter.get());
if (booleans->fUsefLineOK && !booleans->fLineOK)
{
bStroked = false;
}
if (booleans->fUsefFillOK && !booleans->fFillOK)
{
bFilled = false;
}
if (booleans->fUsef3DOK && booleans->f3DOK)
{
b3D = true;
}
if (booleans->fUsefShadowOK && booleans->fShadowOK)
{
bShadow = true;
}
}
break;
case ODRAW::fillStyleBooleanProperties:
{
ODRAW::FillStyleBooleanProperties* booleans = dynamic_cast<ODRAW::FillStyleBooleanProperties*>(iter.get());
if (booleans->fUsefFilled && !booleans->fFilled)
{
bFilled = false;
}
if (booleans->fUsefUseShapeAnchor && booleans->fUseShapeAnchor)
{
appendValueAttribute(&m_fill, L"rotate", L"t");
}
}break;
case ODRAW::lineStyleBooleanProperties:
{
ODRAW::LineStyleBooleanProperties* booleans = dynamic_cast<ODRAW::LineStyleBooleanProperties*>(iter.get());
if (booleans->fUsefLine && !booleans->fLine)
{
bStroked = false;
}
}
break;
case ODRAW::protectionBooleanProperties:
{
//ProtectionBooleanProperties booleans(iter->op);
}
break;
case ODRAW::diagramBooleanProperties:
{
}
break;
case ODRAW::groupShapeBooleanProperties:
{
ODRAW::GroupShapeBooleanProperties* booleans = dynamic_cast<ODRAW::GroupShapeBooleanProperties*>(iter.get());
if (booleans->fUsefLayoutInCell)
{
layoutInCell = booleans->fLayoutInCell;
}
}
break;
// GEOMETRY
case ODRAW::shapePath:
{
bHavePath = true;
nShapePath = iter->op;
}break;
case ODRAW::pVertices:
{
opVerticles = iter;
}break;
case ODRAW::pSegmentInfo:
{
opSegmentInfo = iter;
}break;
case ODRAW::pGuides:
{
GetGuides(iter);
}break;
case ODRAW::pConnectionSites:
{
opConnectLocs = iter;
}break;
case ODRAW::pConnectionSitesDir:
{
opConnectAngles = iter;
}break;
case ODRAW::pInscribe:
{
opInscribe = iter;
}break;
case ODRAW::adjustValue:
{
m_nAdjValues[0] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 1);
}
break;
case ODRAW::adjust2Value:
{
m_nAdjValues[1] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 2);
}
break;
case ODRAW::adjust3Value:
{
m_nAdjValues[2] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 3);
}break;
case ODRAW::adjust4Value:
{
m_nAdjValues[3] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 4);
}break;
case ODRAW::adjust5Value:
{
m_nAdjValues[4] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 5);
}break;
case ODRAW::adjust6Value:
{
m_nAdjValues[5] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 6);
}break;
case ODRAW::adjust7Value:
{
m_nAdjValues[6] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 7);
}break;
case ODRAW::adjust8Value:
{
m_nAdjValues[7] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 8);
}break;
case ODRAW::pWrapPolygonVertices:
{
std::wstring wrapCoords = GetWrapCoords(iter);
if (!wrapCoords.empty())
{
m_pXmlWriter->WriteAttribute(L"wrapcoords", wrapCoords);
}
}break;
case ODRAW::geoLeft:
{
xCoord2 = iter->op;
}break;
case ODRAW::geoTop:
{
yCoord2 = iter->op;
}break;
case ODRAW::geoRight:
{
xCoord = iter->op;
}break;
case ODRAW::geoBottom:
{
yCoord = iter->op;
}break;
// LINE
case ODRAW::lineColor:
{
ODRAW::OfficeArtCOLORREF lineColor((_UINT32)iter->op);
m_context->_doc->CorrectColor(lineColor, nColorRGBBase, 5);
if (false == lineColor.sColorRGB.empty() && !pShape->fBackground)
m_pXmlWriter->WriteAttribute(L"strokecolor", (std::wstring(L"#") + lineColor.sColorRGB));
}break;
case ODRAW::lineWidth:
{
if (iter->op > 0)
{
EmuValue eLineWidth((int)iter->op);
m_pXmlWriter->WriteAttribute(L"strokeweight", FormatUtils::DoubleToWideString(eLineWidth.ToPoints()) + L"pt");
}
}break;
case ODRAW::lineDashing:
{
appendValueAttribute(&m_stroke, L"dashstyle", FormatUtils::MapValueToWideString(iter->op, &Global::DashStyleMap[0][0], 11, 16));
}break;
case ODRAW::lineStyle:
{
appendValueAttribute(&m_stroke, L"linestyle", getLineStyle(iter->op));
}break;
case ODRAW::lineEndArrowhead:
{
appendValueAttribute(&m_stroke, L"endarrow", getArrowStyle(iter->op));
}break;
case ODRAW::lineEndArrowLength:
{
appendValueAttribute(&m_stroke, L"endarrowlength", getArrowLength(iter->op));
}break;
case ODRAW::lineEndArrowWidth:
{
appendValueAttribute(&m_stroke, L"endarrowwidth", getArrowWidth(iter->op));
}break;
case ODRAW::lineStartArrowhead:
{
appendValueAttribute(&m_stroke, L"startarrow", getArrowStyle(iter->op));
}break;
case ODRAW::lineStartArrowLength:
{
appendValueAttribute(&m_stroke, L"startarrowlength", getArrowLength(iter->op));
}break;
case ODRAW::lineStartArrowWidth:
{
appendValueAttribute(&m_stroke, L"startarrowwidth", getArrowWidth(iter->op));
}break;
case ODRAW::cxstyle:
{
if (pShape->GetShapeType() == NULL)
{
freeform = false;
m_pXmlWriter->WriteAttribute(L"type", L"#_x0000_t32");
}
switch (iter->op)
{
case 0: m_pXmlWriter->WriteAttribute(L"o:connectortype", L"straight"); break;
case 1: m_pXmlWriter->WriteAttribute(L"o:connectortype", L"elbow"); break;
case 2: m_pXmlWriter->WriteAttribute(L"o:connectortype", L"curved"); break;
case 3: m_pXmlWriter->WriteAttribute(L"o:connectortype", L"none"); break;
}
}break;
// FILL
case ODRAW::fillColor:
{
ODRAW::OfficeArtCOLORREF fillColor((_UINT32)iter->op);
m_context->_doc->CorrectColor(fillColor, nColorRGBBase, 1);
if (false == fillColor.sColorRGB.empty())
m_pXmlWriter->WriteAttribute(L"fillcolor", (std::wstring(L"#") + fillColor.sColorRGB));
nColorRGBBase = fillColor.nColorRGB;
}break;
case ODRAW::fillBackColor:
{
ODRAW::OfficeArtCOLORREF fillBackColor((_UINT32)iter->op);
m_context->_doc->CorrectColor(fillBackColor, nColorRGBBase, 2);
if (false == fillBackColor.sColorRGB.empty())
appendValueAttribute(&m_fill, L"color2", (std::wstring(L"#") + fillBackColor.sColorRGB));
}break;
case ODRAW::fillAngle:
{
ODRAW::FixedPoint* point = dynamic_cast<ODRAW::FixedPoint*>(iter.get());
if (point) appendValueAttribute(&m_fill, L"angle", FormatUtils::DoubleToWideString(point->dVal));
}break;
case ODRAW::fillShadeType:
{
appendValueAttribute(&m_fill, L"method", getFillMethod(iter->op));
}break;
case ODRAW::fillShadeColors:
{
appendValueAttribute(&m_fill, L"colors", getFillColorString(iter));
}break;
case ODRAW::fillFocus:
{
appendValueAttribute(&m_fill, L"focus", (std::to_wstring(iter->op) + L"%"));
appendValueAttribute(&m_fill, L"focussize", L"");
}break;
case ODRAW::fillType:
{
nFillType = iter->op;
appendValueAttribute(&m_fill, L"type", getFillType(nFillType));
if (nFillType == 6)
{
fill_top = 0.5;
fill_left = 0.5;
}
//if (nFillType == 7) bFlipColors = true;
}break;
case ODRAW::fillToLeft:
{
ODRAW::FixedPoint* point = dynamic_cast<ODRAW::FixedPoint*>(iter.get());
if (point) fill_left = point->dVal;
}break;
case ODRAW::fillToTop:
{
ODRAW::FixedPoint* point = dynamic_cast<ODRAW::FixedPoint*>(iter.get());
if (point) fill_top = point->dVal;
}break;
case ODRAW::fillToRight:
{
ODRAW::FixedPoint* point = dynamic_cast<ODRAW::FixedPoint*>(iter.get());
if (point) fill_right = point->dVal;
}break;
case ODRAW::fillToBottom:
{
ODRAW::FixedPoint* point = dynamic_cast<ODRAW::FixedPoint*>(iter.get());
if (point) fill_bottom = point->dVal;
}break;
case ODRAW::fillRectLeft:
case ODRAW::fillRectTop:
case ODRAW::fillRectRight:
case ODRAW::fillRectBottom:
{
}break;
case ODRAW::fillBlip:
{
BlipStoreEntry* pFillBlip = NULL;
if ((m_pict != NULL) && (m_pict->blipStoreEntry != NULL))
{
// Word Art Texture
//fillBlip = this->_pict->BlipStoreEntry;
}
else if ((m_pBlipStore != NULL) && ((iter->op - 1) < m_pBlipStore->Children.size()))
{
pFillBlip = static_cast<BlipStoreEntry*>(m_pBlipStore->Children[iter->op - 1]);
}
if ((pFillBlip != NULL) && copyPicture(pFillBlip))
{
appendValueAttribute(&m_fill, L"r:id", std::wstring((L"rId") + std::to_wstring(m_nImageId)));
}
bPicturePresent = true;
}break;
case ODRAW::fillBlipName:
{
ODRAW::AnyString* str = dynamic_cast<ODRAW::AnyString*>(iter.get());
if ((str) && (!str->string_.empty()))
{
appendValueAttribute(&m_fill, L"o:title", str->string_);
}
}break;
case ODRAW::fillOpacity:
{
double opa = (iter->op / pow((double)2, (double)16));
appendValueAttribute(&m_fill, L"opacity", FormatUtils::DoubleToFormattedWideString(opa, L"%.2f"));
}
break;
case ODRAW::fillBackOpacity:
{
double opa = (iter->op / pow((double)2, (double)16));
appendValueAttribute(&m_fill, L"o:opacity2", FormatUtils::DoubleToFormattedWideString(opa, L"%.2f"));
}break;
// SHADOW
case ODRAW::shadowType:
{
appendValueAttribute(&m_shadow, L"type", getShadowType(iter->op));
}break;
case ODRAW::shadowColor:
{
ODRAW::OfficeArtCOLORREF shadowColor((_UINT32)iter->op);
m_context->_doc->CorrectColor(shadowColor, nColorRGBBase, 3);
if (false == shadowColor.sColorRGB.empty())
appendValueAttribute(&m_shadow, L"color", (std::wstring(L"#") + shadowColor.sColorRGB));
}break;
case ODRAW::shadowOffsetX:
{
ShadowOffsetX = EmuValue((int)iter->op);
}break;
case ODRAW::shadowSecondOffsetX:
{
SecondShadowOffsetX = EmuValue((int)iter->op);
}break;
case ODRAW::shadowOffsetY:
{
ShadowOffsetY = EmuValue((int)iter->op);
}break;
case ODRAW::shadowSecondOffsetY:
{
SecondShadowOffsetY = EmuValue((int)iter->op);
}break;
case ODRAW::shadowOriginX:
{
ShadowOriginX = (iter->op / pow((double)2, (double)16));
}break;
case ODRAW::shadowOriginY:
{
ShadowOriginY = (iter->op / pow((double)2, (double)16));
}break;
case ODRAW::shadowScaleXToX:
{
matrix[0] = iter->op;
}break;
case ODRAW::shadowScaleYToX:
{
matrix[1] = iter->op;
}break;
case ODRAW::shadowScaleXToY:
{
matrix[2] = iter->op;
}break;
case ODRAW::shadowScaleYToY:
{
matrix[3] = iter->op;
}break;
case ODRAW::shadowOpacity:
{
double shadowOpa = (iter->op / pow((double)2, (double)16));
appendValueAttribute(&m_shadow, L"opacity", FormatUtils::DoubleToFormattedWideString(shadowOpa, L"%.2f"));
}break;
case ODRAW::shadowStyleBooleanProperties:
{
ODRAW::ShadowStyleBooleanProperties* booleans = dynamic_cast<ODRAW::ShadowStyleBooleanProperties*>(iter.get());
if (booleans)
{
if (booleans->fUsefShadow && booleans->fShadow)
{
bShadow = true;
}
}
}break;
// OLE
case ODRAW::pictureId:
{
indexOLE = iter->op;
}break;
// PICTURE
case ODRAW::pib:
{
int index = (int)(iter->op - 1);
if ((m_pBlipStore != NULL) && (index < (int)m_pBlipStore->Children.size()))
{
BlipStoreEntry* oBlip = static_cast<BlipStoreEntry*>(m_pBlipStore->Children[index]);
if (copyPicture(oBlip))
{
appendValueAttribute(&m_imagedata, L"r:id", (std::wstring(L"rId") + std::to_wstring(m_nImageId)));
}
}
bPicturePresent = true;
}break;
case ODRAW::pibName:
{
ODRAW::AnyString* str = dynamic_cast<ODRAW::AnyString*>(iter.get());
if ((str) && (!str->string_.empty()))
{
appendValueAttribute(&m_imagedata, L"o:title", str->string_);
}
}break;
case ODRAW::pictureTransparent:
{
}break;
case ODRAW::pictureContrast:
{
appendValueAttribute(&m_imagedata, L"gain", (std::to_wstring(iter->op) + L"f"));
}break;
case ODRAW::pictureBrightness:
{
appendValueAttribute(&m_imagedata, L"blacklevel", (std::to_wstring(iter->op) + L"f"));
}break;
case ODRAW::pictureGamma:
{
appendValueAttribute(&m_imagedata, L"gamma", (std::to_wstring(iter->op) + L"f"));
}break;
//CROPPING
case ODRAW::cropFromBottom:
{
//cast to signed integer
int cropBottom = (int)iter->op;
appendValueAttribute(&m_imagedata, L"cropbottom", std::to_wstring(cropBottom) + L"f");
}
break;
case ODRAW::cropFromLeft:
{
//cast to signed integer
int cropLeft = (int)iter->op;
appendValueAttribute(&m_imagedata, L"cropleft", std::to_wstring(cropLeft) + L"f");
}
break;
case ODRAW::cropFromRight:
{
//cast to signed integer
int cropRight = (int)iter->op;
appendValueAttribute(&m_imagedata, L"cropright", std::to_wstring(cropRight) + L"f");
}
break;
case ODRAW::cropFromTop:
{
//cast to signed integer
int cropTop = (int)iter->op;
appendValueAttribute(&m_imagedata, L"croptop", std::to_wstring(cropTop) + L"f");
}
break;
// 3D STYLE
case ODRAW::threeDStyleBooleanProperties:
{
ODRAW::ThreeDStyleBooleanProperties* booleans = dynamic_cast<ODRAW::ThreeDStyleBooleanProperties*>(iter.get());
}break;
case ODRAW::threeDObjectBooleanProperties:
{
ODRAW::ThreeDObjectBooleanProperties* booleans = dynamic_cast<ODRAW::ThreeDObjectBooleanProperties*>(iter.get());
if ((booleans) && (booleans->fUsef3D && !booleans->f3D))
b3D = false;
}break;
case ODRAW::c3DRenderMode:
{
}break;
case ODRAW::c3DExtrudeBackward:
{
EmuValue backwardValue((int)iter->op);
std::wstring depth = FormatUtils::DoubleToWideString(backwardValue.ToPoints()) + L"pt";
appendValueAttribute(&m_3dstyle, L"backdepth", depth);
}break;
case ODRAW::c3DAmbientIntensity:
{
std::wstring intens = std::to_wstring((int)iter->op) + L"f";
appendValueAttribute(&m_3dstyle, L"brightness", intens);
}break;
case ODRAW::c3DSpecularAmt:
{
std::wstring amt = std::to_wstring((int)iter->op) + L"f";
appendValueAttribute(&m_3dstyle, L"specularity", amt);
}break;
case ODRAW::c3DDiffuseAmt:
{
std::wstring amt = std::to_wstring((int)iter->op) + L"f";
appendValueAttribute(&m_3dstyle, L"diffusity", amt);
}break;
case ODRAW::c3DKeyIntensity:
{
std::wstring amt = std::to_wstring((int)iter->op);
appendValueAttribute(&m_3dstyle, L"lightlevel", amt);
}break;
case ODRAW::c3DExtrusionColor:
{
std::wstring color = FormatUtils::IntToFormattedWideString(iter->op, L"#%06x");
appendValueAttribute(&m_3dstyle, L"color", color);
}break;
case ODRAW::c3DSkewAngle:
{
ODRAW::FixedPoint* point = dynamic_cast<ODRAW::FixedPoint*>(iter.get());
if (point) appendValueAttribute(&m_3dstyle, L"skewangle", FormatUtils::DoubleToWideString(point->dVal));
}break;
case ODRAW::c3DXViewpoint:
{
ODRAW::FixedPoint* point = dynamic_cast<ODRAW::FixedPoint*>(iter.get());
if (point) ViewPointX = EmuValue((int)point->dVal);
}break;
case ODRAW::c3DYViewpoint:
{
ODRAW::FixedPoint* point = dynamic_cast<ODRAW::FixedPoint*>(iter.get());
if (point) ViewPointY = EmuValue((int)point->dVal);
}break;
case ODRAW::c3DZViewpoint:
{
ODRAW::FixedPoint* point = dynamic_cast<ODRAW::FixedPoint*>(iter.get());
if (point) ViewPointZ = EmuValue((int)point->dVal);
}break;
case ODRAW::c3DOriginX:
{
ODRAW::FixedPoint* point = dynamic_cast<ODRAW::FixedPoint*>(iter.get());
if (point) viewPointOriginX = point->dVal;
}break;
case ODRAW::c3DOriginY:
{
ODRAW::FixedPoint* point = dynamic_cast<ODRAW::FixedPoint*>(iter.get());
if (point) viewPointOriginY = point->dVal;
}break;
// TEXTBOX
case ODRAW::lTxid:
{
hasTextbox = true;
nLTxID = (((iter->op) >> 16) & 0xFFFF);
}break;
case ODRAW::dxTextLeft: {ndxTextLeft = (int)iter->op; break; }
case ODRAW::dyTextTop: {ndyTextTop = (int)iter->op; break; }
case ODRAW::dxTextRight: {ndxTextRight = (int)iter->op; break; }
case ODRAW::dyTextBottom: {ndyTextBottom = (int)iter->op; break; }
case ODRAW::txflTextFlow:
{
switch (iter->op)
{
case 0:
case 4://обычный
break;
case 1:
case 3:
case 5://верт (склони голову направо)
appendStyleProperty(sTextboxStyle, L"layout-flow", L"vertical");
break;
case 2://верт (склони голову налево)
appendStyleProperty(sTextboxStyle, L"layout-flow", L"vertical");
appendStyleProperty(sTextboxStyle, L"mso-layout-flow-alt", L"bottom-to-top");
break;
}
}break;
case ODRAW::hspNext:
{
appendStyleProperty(sTextboxStyle, L"mso-next-textbox", std::wstring(L"_x0000_s") + std::to_wstring((unsigned int)iter->op));
}break;
case ODRAW::textBooleanProperties:
{
ODRAW::TextBooleanProperties* props = dynamic_cast<ODRAW::TextBooleanProperties*>(iter.get());
if (props->fUsefFitShapeToText && props->fFitShapeToText)
{
appendStyleProperty(sTextboxStyle, L"mso-fit-shape-to-text", L"t");
}
}break;
// Word Art
case ODRAW::gtextUNICODE:
{
ODRAW::AnyString* str = dynamic_cast<ODRAW::AnyString*>(iter.get());
if ((str) && (!str->string_.empty()))
{
appendValueAttribute(&m_textpath, L"string", str->string_);
}
}break;
case ODRAW::gtextFont:
{
ODRAW::AnyString* str = dynamic_cast<ODRAW::AnyString*>(iter.get());
if (str)
{
appendStyleProperty(m_textPathStyle, L"font-family", str->string_);
}
}break;
case ODRAW::gtextSize:
{
std::wstring fontSize = std::to_wstring(iter->op / 65535);
appendStyleProperty(m_textPathStyle, L"font-size", fontSize + L"pt");
}break;
case ODRAW::gtextSpacing:
{
std::wstring spacing = std::to_wstring(iter->op);
appendStyleProperty(m_textPathStyle, L"v-text-spacing", spacing + L"f");
}break;
case ODRAW::geometryTextBooleanProperties:
{
ODRAW::GeometryTextBooleanProperties* props = dynamic_cast<ODRAW::GeometryTextBooleanProperties*>(iter.get());
if (props->fUsegFShrinkFit && props->fShrinkFit && (props->fStretch || props->fUsegFStretch))
{
appendValueAttribute(&m_textpath, L"fitshape", L"t");
}
if (props->fUsegFBestFit && props->fBestFit && (!props->fStretch || !props->fUsegFStretch))
{
appendValueAttribute(&m_textpath, L"fitshape", L"t");
}
if (props->fUsegFShrinkFit && props->fShrinkFit)
{
appendValueAttribute(&m_textpath, L"trim", L"t");
}
if (props->fUsegFVertical && props->fVertical)
{
appendStyleProperty(m_textPathStyle, L"v-rotate-letters", L"t");
//_twistDimension = true;
}
if (props->fUsegFKern && props->fKern)
{
appendStyleProperty(m_textPathStyle, L"v-text-kern", L"t");
}
if (props->fUsegFItalic && props->fItalic)
{
appendStyleProperty(m_textPathStyle, L"font-style", L"italic");
}
if (props->fUsegFBold && props->fBold)
{
appendStyleProperty(m_textPathStyle, L"font-weight", L"bold");
}
}break;
default:
{
nProperty = iter->op;
}break;
}
}
if (fill_top || fill_left)
{
std::wstring focusposition;
if (fill_left) focusposition += FormatUtils::DoubleToFormattedWideString(*fill_left, L"%.2f");
if (fill_top)
{
focusposition += L",";
focusposition += FormatUtils::DoubleToFormattedWideString(*fill_top, L"%.2f");
}
appendValueAttribute(&m_fill, L"focusposition", focusposition);
}
ODRAW::PVertices* pVP = dynamic_cast<ODRAW::PVertices*>(opVerticles.get());
ODRAW::PSegmentInfo* pSI = dynamic_cast<ODRAW::PSegmentInfo*>(opSegmentInfo.get());
if (pVP && pSI)
{
ODRAW::PathParser oParser(pSI->complex.data, pVP->complex.data, m_arrGuides, xCoord, yCoord);
std::wstring path = oParser.GetVmlPath();
if (false == path.empty())
m_pXmlWriter->WriteAttribute(L"path", path);
}
if (freeform && (!xCoord || !yCoord))
{
xCoord = 21600;
yCoord = 21600;
}
if (!bFilled)
{
m_pXmlWriter->WriteAttribute(L"filled", L"f");
}
if (!bStroked)
{
m_pXmlWriter->WriteAttribute(L"stroked", L"f");
}
if (!layoutInCell)
{
m_pXmlWriter->WriteAttribute(L"o:allowincell", L"f");
}
if (xCoord && yCoord)
{
if (xCoord2 && yCoord2)
{
m_pXmlWriter->WriteAttribute(L"coordorigin", (FormatUtils::SizeTToWideString(*xCoord2) + L"," + FormatUtils::SizeTToWideString(*yCoord2)));
m_pXmlWriter->WriteAttribute(L"coordsize", (FormatUtils::SizeTToWideString(*xCoord - *xCoord2) + L"," + FormatUtils::SizeTToWideString(*yCoord - *yCoord2)));
}
else
{
m_pXmlWriter->WriteAttribute(L"coordsize", (FormatUtils::SizeTToWideString(*xCoord) + L"," + FormatUtils::SizeTToWideString(*yCoord)));
}
}
int nCode = 0;
if (pShape->GetShapeType())
{
nCode = pShape->GetShapeType()->GetTypeCode();
}
if (DocFileFormat::msosptRoundRectangle == nCode)
{
if (nAdjValues)
{
double dArcsize = m_nAdjValues[0] / 21600.;
m_pXmlWriter->WriteAttribute(L"arcsize", dArcsize);
}
}
else if (DocFileFormat::msosptPictureFrame == nCode)
{
if (bPicturePresent == false)
m_isPictureBroken = true;
}
else
{
if (nAdjValues > 0)
{
std::wstring adjTag;
for (int i = 0; i < nAdjValues; ++i)
{
adjTag += L"," + (m_nAdjValues[i] != 0x7fffffff ? std::to_wstring(m_nAdjValues[i]) : L"");
}
m_pXmlWriter->WriteAttribute(L"adj", adjTag.substr(1));
}
}
m_pXmlWriter->WriteNodeEnd(L"", true, false);
//build shadow offsets
std::wstring offset;
if (ShadowOffsetX)
{
offset += FormatUtils::DoubleToWideString(ShadowOffsetX->ToPoints());
offset += L"pt";
}
if (ShadowOffsetY)
{
offset += L",";
offset += FormatUtils::DoubleToWideString(ShadowOffsetY->ToPoints());
offset += L"pt";
}
if (!offset.empty())
{
appendValueAttribute(&m_shadow, L"offset", offset);
}
std::wstring offset2;
if (SecondShadowOffsetX)
{
offset2 += FormatUtils::DoubleToWideString(SecondShadowOffsetX->ToPoints());
offset2 += L"pt";
}
if (SecondShadowOffsetY)
{
offset2 += L",";
offset2 += FormatUtils::DoubleToWideString(SecondShadowOffsetY->ToPoints());
offset2 += L"pt";
}
if (!offset2.empty())
{
appendValueAttribute(&m_shadow, L"offset2", offset2);
}
//build shadow origin
if (ShadowOriginX && ShadowOriginY)
{
appendValueAttribute(&m_shadow, L"origin", FormatUtils::DoubleToWideString(*ShadowOriginX) + std::wstring(L",") + FormatUtils::DoubleToWideString(*ShadowOriginY));
}
//build shadow matrix scale
if (matrix[0] || matrix[1] || matrix[2] || matrix[3])
{
std::wstring matrix_str;
for (auto m : matrix)
{
matrix_str += L",";
if (m) matrix_str += std::to_wstring(*m) + L"f";
}
appendValueAttribute(&m_shadow, L"matrix", matrix_str.substr(1));
}
//write the viewpoint
if ( ViewPointX || ViewPointY || ViewPointZ )
{
std::wstring viewPoint;
if ( ViewPointX )
{
viewPoint += std::to_wstring( *ViewPointX ) + L"pt";
}
viewPoint += L",";
if ( ViewPointY)
{
viewPoint += std::to_wstring( *ViewPointY ) + L"pt";
}
viewPoint += L",";
if ( ViewPointZ)
{
viewPoint += std::to_wstring( *ViewPointZ ) + L"pt";
}
appendValueAttribute(&m_3dstyle, L"viewpoint", viewPoint);
}
// write the viewpointorigin
if ( viewPointOriginX || viewPointOriginY)
{
std::wstring viewPointOrigin;
if ( viewPointOriginX )
{
viewPointOrigin += FormatUtils::DoubleToFormattedWideString( *viewPointOriginX, L"%.2f" );
}
if ( viewPointOriginY )
{
viewPointOrigin += L",";
viewPointOrigin += FormatUtils::DoubleToFormattedWideString( *viewPointOriginY, L"%.2f" );
}
appendValueAttribute(&m_3dstyle, L"viewpointorigin", viewPointOrigin);
}
//write 3d style
if (m_3dstyle.GetAttributeCount() > 0)
{
if (b3D)
{
appendValueAttribute(&m_3dstyle, L"v:ext", L"view" ); //??? вытащить
}
appendValueAttribute(&m_3dstyle, L"on", b3D ? L"t" : L"f" );
m_pXmlWriter->WriteString(m_3dstyle.GetXMLString());
}
// write wrap
if (m_pSpa)
{
std::wstring wrap = getWrapType(m_pSpa);
if (wrap != L"through")
{
m_pXmlWriter->WriteNodeBegin( L"w10:wrap", true );
m_pXmlWriter->WriteAttribute( L"type", wrap );
m_pXmlWriter->WriteNodeEnd ( L"w10:wrap", true );
}
}
// write fill
if (m_fill.GetAttributeCount())
{
m_pXmlWriter->WriteString(m_fill.GetXMLString());
}
// write shadow
if (m_shadow.GetAttributeCount() > 0)
{
appendValueAttribute(&m_shadow, L"on", bShadow ? L"t" : L"f");
m_pXmlWriter->WriteString(m_shadow.GetXMLString());
}
// write imagedata
if (m_imagedata.GetAttributeCount())
{
m_pXmlWriter->WriteString(m_imagedata.GetXMLString());
}
if ( pShape->fBackground )
{
WriteEndShapeNode(pShape);
return;
}
// write stroke
if (m_stroke.GetAttributeCount())
{
m_pXmlWriter->WriteString(m_stroke.GetXMLString());
}
// text path
if (m_textpath.GetAttributeCount())
{
appendValueAttribute(&m_textpath, L"style", FormatUtils::XmlEncode(m_textPathStyle));
m_pXmlWriter->WriteString(m_textpath.GetXMLString());
}
if (freeform)
{
if (opInscribe || opConnectAngles || opConnectLocs)
{
std::vector<std::wstring> arrInscribe = GetTextRectangles(opInscribe);
std::wstring strConnectAngles = GetConnectAngles(opConnectAngles);
std::wstring strConnectLocs = GetConnectLocs(opConnectLocs);
m_pXmlWriter->WriteNodeBegin(L"v:path", true);
if (!arrInscribe.empty())
m_pXmlWriter->WriteAttribute(L"textboxrect", arrInscribe[0]);
if (!strConnectAngles.empty() || !strConnectLocs.empty())
{
m_pXmlWriter->WriteAttribute(L"o:connecttype", L"custom");
if (!strConnectLocs.empty())
m_pXmlWriter->WriteAttribute(L"o:connectlocs", strConnectLocs);
if (!strConnectAngles.empty())
m_pXmlWriter->WriteAttribute(L"o:connectangles", strConnectAngles);
}
m_pXmlWriter->WriteNodeEnd(L"", true);
}
}
// TEXTBOX
OfficeArtClientTextbox* pTextBox = pContainer->FirstChildWithType<OfficeArtClientTextbox>();
if (pTextBox)
{
// Word text box
//Word appends a OfficeArtClientTextbox record to the container.
//This record stores the index of the textbox.
int nIndex = pTextBox->m_nIndex;
if (nIndex > 0)
{
TextboxMapping textboxMapping(m_context, nIndex - 1, m_pXmlWriter, m_pCaller);
textboxMapping.SetInset(ndxTextLeft, ndyTextTop, ndxTextRight, ndyTextBottom);
textboxMapping.SetTextboxStyle(sTextboxStyle);
m_context->_doc->Convert(&textboxMapping);
}
}
else if( hasTextbox )
{
if (-1 != nLTxID)
{
TextboxMapping textboxMapping(m_context, nLTxID - 1, m_pXmlWriter, m_pCaller);
textboxMapping.SetInset(ndxTextLeft, ndyTextTop, ndxTextRight, ndyTextBottom);
m_context->_doc->Convert(&textboxMapping);
}
else
{
TextboxMapping textboxMapping(m_context, m_pXmlWriter, m_pCaller);
textboxMapping.SetInset(ndxTextLeft, ndyTextTop, ndxTextRight, ndyTextBottom);
m_context->_doc->Convert(&textboxMapping);
}
}
WriteEndShapeNode(pShape);
// OLE
if (indexOLE >= 0 && pShape->fOleShape) //4571833.doc
{
XMLTools::CStringXmlWriter txtBoxWrapper;
TextboxMapping textboxMapping(m_context, (indexOLE >> 16) - 1, &txtBoxWrapper, m_pCaller);
textboxMapping.m_shapeIdOwner = m_shapeId;
textboxMapping.m_bOleInPicture = pContainer->m_bOleInPicture;
m_context->_doc->Convert(&textboxMapping);
std::wstring sOleXml = textboxMapping.getOLEObject();
if (false == sOleXml.empty())
m_pXmlWriter->WriteString(sOleXml);
else
{
m_pXmlWriter->WriteString(txtBoxWrapper.GetXmlString());
}
}
//ShapeType
if (NULL != pShape->GetShapeType() /* && !m_isInlineShape*/) //bullete only???
{
VMLShapeTypeMapping oXmlMapper(m_pXmlWriter, m_isInlineShape);
pShape->GetShapeType()->Convert(&oXmlMapper);
}
}
//
void VMLShapeMapping::WriteBeginShapeNode (const Shape* pShape)
{
if (NULL != pShape)
{
if (pShape->fBackground)
{
m_pXmlWriter->WriteNodeBegin( L"v:background", true );
}
else if (pShape->is<OvalType>())
{
m_pXmlWriter->WriteNodeBegin( L"v:oval", true );
}
else if (pShape->is<RoundedRectangleType>())
{
m_pXmlWriter->WriteNodeBegin( L"v:roundrect", true );
}
else if (pShape->is<RectangleType>())
{
m_pXmlWriter->WriteNodeBegin( L"v:rect", true );
}
else if (pShape->is<LineType>())
{
m_pXmlWriter->WriteNodeBegin(L"v:line", true);
}
else
{
m_pXmlWriter->WriteNodeBegin(L"v:shape", true);
}
}
}
void VMLShapeMapping::WriteEndShapeNode (const Shape* pShape)
{
if (NULL != pShape)
{
if (pShape->fBackground)
{
m_pXmlWriter->WriteNodeEnd( L"v:background" );
}
else if (pShape->is<OvalType>())
{
m_pXmlWriter->WriteNodeEnd( L"v:oval" );
}
else if (pShape->is<RoundedRectangleType>())
{
m_pXmlWriter->WriteNodeEnd( L"v:roundrect" );
}
else if (pShape->is<RectangleType>())
{
m_pXmlWriter->WriteNodeEnd( L"v:rect" );
}
else if (pShape->is<LineType>())
{
m_pXmlWriter->WriteNodeEnd( L"v:line" );
}
else
{
m_pXmlWriter->WriteNodeEnd( L"v:shape" );
}
}
}
std::wstring VMLShapeMapping::GetShapeID(const Shape* pShape) const
{
std::wstring strXmlAttr;
if (NULL != pShape)
{
strXmlAttr += std::wstring(L"_x0000_s");
strXmlAttr += std::to_wstring(pShape->GetShapeID());
}
return strXmlAttr;
}
std::wstring VMLShapeMapping::GetLineFrom(const ChildAnchor* pAnchor, bool twistDimensions) const
{
//Если линия находится в группе, то координаты должны быть в Twips
//Если линия находится в группе, то координаты должны быть в других единицах измерения (например в twips)
std::wstring strXmlFrom;
if (NULL != pAnchor)
{
int left = pAnchor->rcgBounds.topLeftAngle.x;
int top = pAnchor->rcgBounds.topLeftAngle.y;
if (twistDimensions)
{
int right = pAnchor->rcgBounds.topLeftAngle.x + pAnchor->rcgBounds.size.cx;
int bottom = pAnchor->rcgBounds.topLeftAngle.y + pAnchor->rcgBounds.size.cy;
left = (right + pAnchor->rcgBounds.topLeftAngle.x) * 0.5 - (bottom - pAnchor->rcgBounds.topLeftAngle.y) * 0.5;
top = (bottom + pAnchor->rcgBounds.topLeftAngle.y) * 0.5 - (right - pAnchor->rcgBounds.topLeftAngle.x) * 0.5;
}
strXmlFrom += std::to_wstring(left);
strXmlFrom += L",";
strXmlFrom += std::to_wstring(top);
}
else if (m_pSpa)
{
TwipsValue oLeft(m_pSpa->xaLeft);
TwipsValue oTop(m_pSpa->yaTop);
if (twistDimensions)
{
oLeft = TwipsValue((m_pSpa->xaRight + m_pSpa->xaLeft) * 0.5 - (m_pSpa->yaBottom - m_pSpa->yaTop) * 0.5);
oTop = TwipsValue((m_pSpa->yaBottom + m_pSpa->yaTop) * 0.5 - (m_pSpa->xaRight - m_pSpa->xaLeft) * 0.5);
}
strXmlFrom += FormatUtils::DoubleToWideString(oLeft.ToPoints());
strXmlFrom += L"pt,";
strXmlFrom += FormatUtils::DoubleToWideString(oTop.ToPoints());
strXmlFrom += L"pt";
}
return strXmlFrom;
}
std::wstring VMLShapeMapping::GetLineTo(const ChildAnchor* pAnchor, bool twistDimensions) const
{
//Если линия находится в группе, то координаты должны быть в других единицах измерения (например в twips)
std::wstring strXmlTo;
if (NULL != pAnchor)
{
int right = pAnchor->rcgBounds.topLeftAngle.x + pAnchor->rcgBounds.size.cx;
int bottom = pAnchor->rcgBounds.topLeftAngle.y + pAnchor->rcgBounds.size.cy;
if (twistDimensions)
{
int left = (right + pAnchor->rcgBounds.topLeftAngle.x) * 0.5 - (bottom - pAnchor->rcgBounds.topLeftAngle.y) * 0.5;
int top = (bottom + pAnchor->rcgBounds.topLeftAngle.y) * 0.5 - (right - pAnchor->rcgBounds.topLeftAngle.x) * 0.5;
right = left + pAnchor->rcgBounds.size.cy;
bottom = top + pAnchor->rcgBounds.size.cx;
}
strXmlTo += std::to_wstring(right);
strXmlTo += L",";
strXmlTo += std::to_wstring(bottom);
}
else if (m_pSpa)
{
TwipsValue oRight (m_pSpa->xaRight);
TwipsValue oBottom (m_pSpa->yaBottom);
if (twistDimensions)
{
oRight = TwipsValue((m_pSpa->yaBottom - m_pSpa->yaTop) + (m_pSpa->xaRight + m_pSpa->xaLeft) * 0.5 - (m_pSpa->yaBottom - m_pSpa->yaTop) * 0.5);
oBottom = TwipsValue((m_pSpa->xaRight - m_pSpa->xaLeft) + (m_pSpa->yaBottom + m_pSpa->yaTop) * 0.5 - (m_pSpa->xaRight - m_pSpa->xaLeft) * 0.5);
}
strXmlTo += FormatUtils::DoubleToWideString(oRight.ToPoints());
strXmlTo += L"pt,";
strXmlTo += FormatUtils::DoubleToWideString(oBottom.ToPoints());
strXmlTo += L"pt";
}
return strXmlTo;
}
/// Build the VML wrapcoords string for a given pWrapPolygonVertices
std::wstring VMLShapeMapping::GetWrapCoords(const ODRAW::OfficeArtFOPTEPtr& pOpt) const
{
ODRAW::PWrapPolygonVertices* pWrapPolygonVertices = dynamic_cast<ODRAW::PWrapPolygonVertices*>(pOpt.get());
if (!pWrapPolygonVertices) return L"";
if (pWrapPolygonVertices->complex.data.empty()) return L"";
std::wstring coords;
for (size_t i = 0; i < pWrapPolygonVertices->complex.data.size(); ++i)
{
coords += std::to_wstring(pWrapPolygonVertices->complex.data[i].x);
coords += L",";
coords += FormatUtils::IntToWideString(pWrapPolygonVertices->complex.data[i].y);
coords += L",";
}
coords.erase(coords.size() - 1);
return coords;
}
/// Copies the picture from the binary stream to the zip archive
/// and creates the relationships for the image.
bool VMLShapeMapping::copyPicture(BlipStoreEntry* oBlip)
{
bool result = false;
//write the blip
if (oBlip)
{
VirtualStreamReader reader(m_context->_doc->WordDocumentStream, oBlip->foDelay, m_context->_doc->nWordVersion);
switch (oBlip->btWin32)
{
case Global::msoblipEMF:
case Global::msoblipWMF:
case Global::msoblipPICT:
{
//it's a meta image
MetafilePictBlip* metaBlip = static_cast<MetafilePictBlip*>(RecordFactory::ReadRecord(&reader, 0));
if (metaBlip)
{
//meta images can be compressed
unsigned char* decompressed = NULL;
unsigned int decompressedSize = 0;
decompressedSize = metaBlip->Decompress(&decompressed);
if (0 != decompressedSize && NULL != decompressed)
{
boost::shared_array<unsigned char> arDecompressed(decompressed);
m_context->_docx->ImagesList.push_back(ImageFileStructure(GetTargetExt(oBlip->btWin32), arDecompressed, decompressedSize));
result = true;
}
RELEASEOBJECT(metaBlip);
}
}break;
case Global::msoblipJPEG:
case Global::msoblipCMYKJPEG:
case Global::msoblipPNG:
case Global::msoblipTIFF:
case Global::msoblipDIB:
{//it's a bitmap image
BitmapBlip* bitBlip = static_cast<BitmapBlip*>(RecordFactory::ReadRecord(&reader, 0));
if ((bitBlip) && (bitBlip->m_pvBits))
{
if (oBlip->btWin32 == Global::msoblipDIB)
{
std::wstring file_name = m_context->_doc->m_sTempFolder + FILE_SEPARATOR_STR + L"tmp_image";
oBlip->btWin32 = ImageHelper::SaveImageToFileFromDIB(bitBlip->m_pvBits, bitBlip->pvBitsSize, file_name);
unsigned char* pData = NULL;
DWORD nData = 0;
if (NSFile::CFileBinary::ReadAllBytes(file_name, &pData, nData))
{
m_context->_docx->ImagesList.push_back(ImageFileStructure(GetTargetExt(oBlip->btWin32),
boost::shared_array<unsigned char>(pData), nData, oBlip->btWin32));
result = true;
break;
}//в случае ошибки конвертации -храним оригинальный dib
}
m_context->_docx->ImagesList.push_back(ImageFileStructure(GetTargetExt(oBlip->btWin32),
bitBlip->m_pvBits, bitBlip->pvBitsSize, oBlip->btWin32));
RELEASEOBJECT (bitBlip);
result = true;
}break;
}
default:
{
result = false;
}
break;
}
}
if (result)
{
m_nImageId = m_context->_docx->RegisterImage (m_pCaller, oBlip->btWin32);
}
return result;
}
std::wstring VMLShapeMapping::GetTargetExt(Global::BlipType _type) const
{
switch ( _type )
{
case Global::msoblipDIB:
return std::wstring( L".bmp" );
case Global::msoblipEMF:
return std::wstring( L".emf" );
//case msoblipGIF:
// return std::wstring( L".gif" );
//case msoblipICON:
// return std::wstring( L".ico" );
case Global::msoblipJPEG:
case Global::msoblipCMYKJPEG:
return std::wstring( L".jpg" );
//case msoblipPCX:
// return std::wstring( L".pcx" );
case Global::msoblipPNG:
return std::wstring( L".png" );
case Global::msoblipTIFF:
return std::wstring( L".tif" );
case Global::msoblipWMF:
return std::wstring( L".wmf" );
case Global::msoblipPICT:
return std::wstring( L".pcz" );
default:
return std::wstring( L".png" );
}
}
void VMLShapeMapping::AppendDimensionToStyle(std::wstring& style, const PictureDescriptor* pict, bool twistDimensions) const
{
if ( pict != NULL )
{
double xScaling = pict->mx / 1000.0;
double yScaling = pict->my / 1000.0;
TwipsValue width( ( pict->dxaGoal - ( pict->dxaCropLeft + pict->dxaCropRight ) ) * xScaling );
TwipsValue height( ( pict->dyaGoal - ( pict->dyaCropTop + pict->dyaCropBottom ) ) * yScaling );
if ( twistDimensions )
{
width = TwipsValue( ( pict->dyaGoal - ( pict->dyaCropTop + pict->dyaCropBottom ) ) * yScaling );
height = TwipsValue( ( pict->dxaGoal - ( pict->dxaCropLeft + pict->dxaCropRight ) ) * xScaling );
}
std::wstring widthString = FormatUtils::DoubleToWideString( width.ToPoints() );
std::wstring heightString = FormatUtils::DoubleToWideString( height.ToPoints() );
style += L"width:" + widthString + L"pt;" ;
style += L"height:" + heightString + L"pt;";
}
}
void VMLShapeMapping::AppendDimensionToStyle(std::wstring& style, const Spa* pSpa, bool twistDimensions) const
{
if (pSpa != NULL )
{
//append size and position ...
if (m_isInlineShape)
{
// appendStyleProperty( style, L"position", L"static" );
}
else
appendStylePropertyFirst( style, L"position", L"absolute" );
TwipsValue left (pSpa->xaLeft);
TwipsValue top (pSpa->yaTop);
TwipsValue width (pSpa->xaRight - pSpa->xaLeft);
TwipsValue height(pSpa->yaBottom - pSpa->yaTop);
if (twistDimensions)
{
width = TwipsValue(pSpa->yaBottom - pSpa->yaTop);
height = TwipsValue(pSpa->xaRight - pSpa->xaLeft);
left = TwipsValue((pSpa->xaRight + pSpa->xaLeft) * 0.5 - (pSpa->yaBottom - pSpa->yaTop) * 0.5);
top = TwipsValue((pSpa->yaBottom + pSpa->yaTop) * 0.5 - (pSpa->xaRight - pSpa->xaLeft) * 0.5);
}
appendStyleProperty (style, L"margin-left", ( FormatUtils::DoubleToWideString(left.ToPoints()) + std::wstring( L"pt" ) ));
appendStyleProperty (style, L"margin-top", ( FormatUtils::DoubleToWideString(top.ToPoints()) + std::wstring( L"pt" ) ));
appendStyleProperty (style, L"width", ( FormatUtils::DoubleToWideString(width.ToPoints()) + std::wstring( L"pt" ) ));
appendStyleProperty (style, L"height", ( FormatUtils::DoubleToWideString(height.ToPoints()) + std::wstring( L"pt" ) ));
}
}
void VMLShapeMapping::AppendDimensionToStyle(std::wstring& style, const ChildAnchor* anchor, bool twistDimensions) const
{
if (anchor != NULL)
{
DocFileFormat::Rectangle bounds = anchor->rcgBounds;
if (twistDimensions)
{
bounds.topLeftAngle.x = static_cast<LONG>(((anchor->Right + anchor->Left) * 0.5 - (anchor->Bottom - anchor->Top) * 0.5));
bounds.topLeftAngle.y = static_cast<LONG>(((anchor->Bottom + anchor->Top) * 0.5 - (anchor->Right - anchor->Left) * 0.5));
}
appendStylePropertyFirst(style, L"top", std::to_wstring(bounds.topLeftAngle.y));
appendStylePropertyFirst(style, L"left", std::to_wstring(bounds.topLeftAngle.x));
appendStylePropertyFirst(style, L"position", L"absolute");
if (twistDimensions)
{
appendStylePropertyFirst(style, L"width", std::to_wstring(bounds.size.cy));
appendStylePropertyFirst(style, L"height", std::to_wstring(bounds.size.cx));
}
else
{
appendStylePropertyFirst(style, L"width", std::to_wstring(bounds.size.cx));
appendStylePropertyFirst(style, L"height", std::to_wstring(bounds.size.cy));
}
}
}
void VMLShapeMapping::appendStyleProperty(std::wstring& style, const std::wstring& propName, const std::wstring& propValue) const
{
style += ( propName );
style += ( L":" );
style += ( propValue );
style +=( L";" );
}
void VMLShapeMapping::appendStylePropertyFirst(std::wstring& style, const std::wstring& propName, const std::wstring& propValue) const
{
std::wstring s;
s += ( propName );
s += ( L":" );
s += ( propValue );
s +=( L";" );
style = s + style;
}
std::wstring VMLShapeMapping::getTextboxAnchor(unsigned int anchor) const
{
switch ( anchor )
{
case 0: return L"top";
case 1: return L"middle";
case 2: return L"bottom";
case 3: return L"top-center";
case 4: return L"middle-center";
case 5: return L"bottom-center";
case 6: return L"top-baseline";
case 7: return L"bottom-baseline";
case 8: return L"top-center-baseline";
case 9: return L"bottom-center-baseline";
default:
return L"top";
}
}
std::wstring VMLShapeMapping::mapVerticalPosition(PositionVertical vPos)
{
switch ( vPos )
{
/*case msopvAbs: return L"absolute" );*/
case msopvTop: return L"top";
case msopvCenter: return L"center";
case msopvBottom: return L"bottom";
case msopvInside: return L"inside";
case msopvOutside: return L"outside";
default:
return L"absolute";
}
}
std::wstring VMLShapeMapping::mapVerticalPositionRelative(int vRel_)
{
PositionVerticalRelative vRel = (PositionVerticalRelative)vRel_;
switch ( vRel )
{
case msoprvMargin: return L"margin";
case msoprvPage: return L"page";
case msoprvText: return L"text";
case msoprvLine: return L"line";
default:
return L"margin";
}
}
std::wstring VMLShapeMapping::mapHorizontalPosition(PositionHorizontal hPos)
{
switch ( hPos )
{
/*case msophAbs: return L"absolute";*/
case msophLeft: return L"left";
case msophCenter: return L"center";
case msophRight: return L"right";
case msophInside: return L"inside";
case msophOutside: return L"outside";
default:
return L"absolute";
}
}
std::wstring VMLShapeMapping::mapHorizontalPositionRelative(int hRel_ )
{
PositionHorizontalRelative hRel = (PositionHorizontalRelative )hRel_;
switch ( hRel )
{
case msoprhMargin: return L"margin"; //0 //MARGIN = anchor
case msoprhPage: return L"page"; //1 //PAGE
case msoprhText: return L"text"; //2 //TEXT
case msoprhChar: return L"char"; //3
default:
return L"margin";
}
}
std::wstring VMLShapeMapping::mapWrapText(int val)
{
switch (val)
{
case 0: return L"square";
case 1: return L"tight";
case 2: return L"none";
//case 3: return L"TopBottom";
//case 3: return L"Through";
default:
return L"square";
}
}
void VMLShapeMapping::AppendOptionsToStyle (std::wstring& oStyle, const std::vector<ODRAW::OfficeArtFOPTEPtr>& options, int zIndex) const
{
int nRelH = -1;
int nRelV = -1;
int nPosH = -1;
int nPosV = -1;
bool bZIndex = false;
for (size_t i = 0; i < options.size(); i++)
{
const ODRAW::OfficeArtFOPTEPtr & iter = options[i];
switch (iter->opid)
{
case ODRAW::WrapText:
{
appendStyleProperty(oStyle, L"mso-wrap-style", mapWrapText(iter->op));
}break;
// POSITIONING
case ODRAW::posh:
{
nPosH = iter->op;
}break;
case ODRAW::posrelh:
{
nRelH = iter->op;
if (false == m_inGroup)
appendStyleProperty(oStyle, L"mso-position-horizontal-relative", mapHorizontalPositionRelative((PositionHorizontalRelative)iter->op));
}break;
case ODRAW::posv:
{
nPosV = iter->op;
}break;
case ODRAW::posrelv:
{
nRelV = iter->op;
if (false == m_inGroup)
appendStyleProperty(oStyle, L"mso-position-vertical-relative", mapVerticalPositionRelative((PositionVerticalRelative)iter->op));
}break;
// BOOLEANS
case ODRAW::groupShapeBooleanProperties:
{
ODRAW::GroupShapeBooleanProperties* booleans = dynamic_cast<ODRAW::GroupShapeBooleanProperties*>(iter.get());
if (booleans->fUsefBehindDocument && booleans->fBehindDocument)
{
//за текстом (The shape is behind the text, so the z-index must be negative.)
m_isInlineShape = false;
if (false == bZIndex/* && false == m_inGroup*/) // Пример.doc
{
appendStyleProperty(oStyle, L"z-index", FormatUtils::IntToWideString(-zIndex - 0x7ffff));
bZIndex = true;
}
}
//if (!m_isInlineShape && !bZIndex)
//{
// appendStyleProperty( oStyle, L"z-index", FormatUtils::IntToWideString(zIndex + 0x7ffff));
// bZIndex = true;
//}
if (booleans->fHidden && booleans->fUsefHidden)
{
appendStyleProperty(oStyle, L"visibility", L"hidden" );
}
}break;
// GEOMETRY
case ODRAW::ePropertyId_rotation:
{
double dAngle = (double)((int)iter->op) / 65535.0;
if (dAngle < -360.0)
dAngle += 360.0;
appendStyleProperty(oStyle, L"rotation", FormatUtils::DoubleToWideString(dAngle));
}break;
// TEXTBOX
case ODRAW::anchorText:
{
appendStyleProperty(oStyle, L"v-text-anchor", getTextboxAnchor(iter->op));
}break;
// WRAP DISTANCE
case ODRAW::dxWrapDistLeft:
{
appendStyleProperty(oStyle, L"mso-wrap-distance-left", (FormatUtils::DoubleToWideString(EmuValue((int)iter->op).ToPoints()) + std::wstring(L"pt")));
}break;
case ODRAW::dxWrapDistRight:
{
appendStyleProperty(oStyle, L"mso-wrap-distance-right", (FormatUtils::DoubleToWideString(EmuValue((int)iter->op).ToPoints()) + std::wstring(L"pt")));
}break;
case ODRAW::dyWrapDistBottom:
{
appendStyleProperty(oStyle, L"mso-wrap-distance-bottom", (FormatUtils::DoubleToWideString(EmuValue((int)iter->op).ToPoints()) + std::wstring(L"pt")));
}break;
case ODRAW::dyWrapDistTop:
{
appendStyleProperty(oStyle, L"mso-wrap-distance-top", (FormatUtils::DoubleToWideString(EmuValue((int)iter->op).ToPoints()) + std::wstring(L"pt")));
}break;
default:
break;
}
}
if (nRelH < 0 && m_pSpa && false == m_inGroup)
{
//if (m_pSpa->bx == TEXT && bZIndex)
//{
// m_pSpa->bx = PAGE;
//}04012010post.doc
if (m_pSpa->bx == MARGIN)
appendStyleProperty(oStyle, L"mso-position-horizontal-relative", mapHorizontalPositionRelative(msoprhMargin));
else if (m_pSpa->bx == PAGE)
appendStyleProperty(oStyle, L"mso-position-horizontal-relative", mapHorizontalPositionRelative(msoprhPage));
else if (m_pSpa->bx == TEXT)
appendStyleProperty(oStyle, L"mso-position-horizontal-relative", mapHorizontalPositionRelative(msoprhText));
}
if (nRelV < 0 && m_pSpa && false == m_inGroup)
{
//if (m_pSpa->by == TEXT && bZIndex)
//{
// m_pSpa->by = PAGE;
//}04012010post.doc
if (m_pSpa->by == MARGIN)
appendStyleProperty(oStyle, L"mso-position-vertical-relative", mapHorizontalPositionRelative(msoprvMargin));
else if (m_pSpa->by == PAGE)
appendStyleProperty(oStyle, L"mso-position-vertical-relative", mapHorizontalPositionRelative(msoprvPage));
else if (m_pSpa->by == TEXT)
appendStyleProperty(oStyle, L"mso-position-vertical-relative", mapHorizontalPositionRelative(msoprvText));
}
if (nRelH == 3 && nRelV == 3)
{
m_isInlineShape = true;
}
if (false == m_isInlineShape && false == bZIndex && false == m_inGroup)
{
appendStyleProperty( oStyle, L"z-index", FormatUtils::IntToWideString(zIndex + 0x7ffff));
bZIndex = true;
}
if (false == m_isInlineShape && false == m_inGroup)
{
if (nPosH >= 0)
{
appendStyleProperty(oStyle, L"mso-position-horizontal", mapHorizontalPosition((PositionHorizontal)nPosH));
}
if (nPosV >= 0)
{
appendStyleProperty(oStyle, L"mso-position-vertical", mapVerticalPosition((PositionVertical)nPosV));
}
}
}
//
std::wstring VMLShapeMapping::buildStyle (const Shape* shape, const ChildAnchor* anchor, const std::vector<ODRAW::OfficeArtFOPTEPtr>& options, int zIndex, bool &twistDimensions) const
{
std::wstring style;
twistDimensions = false;
for (size_t i = 0; i < options.size(); i++)
{
const ODRAW::OfficeArtFOPTEPtr & iter = options[i];
if (ODRAW::geometryTextBooleanProperties == iter->opid)
{
ODRAW::GeometryTextBooleanProperties* booleans = dynamic_cast<ODRAW::GeometryTextBooleanProperties*>(iter.get());
if (booleans->fUsegFVertical && booleans->fVertical)
{
twistDimensions = true;
}
}
else if (ODRAW::ePropertyId_rotation == iter->opid)
{
double dAngle = (double)((int)iter->op) / 65535.0;
if (dAngle < -360.0)
dAngle += 360.0;
if (dAngle > 360.0)
dAngle -= 360.0;
if ((dAngle >= 45.0 && dAngle <= 135.0) || (dAngle >= 225.0 && dAngle <= 315.0) || (dAngle <= -45.0 && dAngle >= -135.0) || (dAngle <= -225.0 && dAngle >= -315.0))
twistDimensions = true;
}
}
if ( shape->fFlipH )
{
appendStyleProperty( style, L"flip", L"x" );
}
if ( shape->fFlipV )
{
appendStyleProperty( style, L"flip", L"y" );
}
AppendOptionsToStyle( style, options, zIndex );
//don't append the dimension info to lines,
// because they have "from" and "to" attributes to decline the dimension
if (false == shape->is<LineType>())
{
if ( (m_pSpa != NULL) && ( anchor == NULL ) )
{
//this shape is placed directly in the document,
//so use the FSPA to build the style
AppendDimensionToStyle( style, m_pSpa, twistDimensions);
}
else if (anchor)
{
//the style is part of a group,
//so use the anchor
AppendDimensionToStyle( style, anchor, twistDimensions);
}
else if (m_pict)
{
// it is some kind of PICT shape (e.g. WordArt)
AppendDimensionToStyle( style, m_pict, twistDimensions);
}
}
else
{
//если не написать тип позиции, то будет inline
if ( anchor != NULL )
{
appendStylePropertyFirst( style, L"position", L"absolute" );
}
else if (m_pSpa)
{
//append size and position ...
//if (m_pSpa->fAnchorLock)//это возможность смены привязки , а не ее тип
if (m_isInlineShape)/*m_pSpa->bx == TEXT && m_pSpa->by == TEXT*/
{
// appendStyleProperty( style, L"position", L"static" );
}
else
{
appendStylePropertyFirst( style, L"position", L"absolute" );
}
}
}
return style;
}
std::wstring VMLShapeMapping::getLineStyle(unsigned int p) const
{
switch (p)
{
case 0: return L"single";
case 1: return L"thinThin";
case 2: return L"thinThick";
case 3: return L"thickThin";
case 4: return L"thickBetweenThin";
default: return L"single";
}
}
std::wstring VMLShapeMapping::getArrowStyle(unsigned int op) const
{
switch ( op )
{
case 1: return L"block";
case 2: return L"classic";
case 3: return L"diamond";
case 4: return L"oval";
case 5: return L"open";
default: return L"none";
}
}
std::wstring VMLShapeMapping::getArrowLength(unsigned int op) const
{
switch ( op )
{
case 1: return L"medium";
case 2: return L"long";
default: return L"short";
}
}
std::wstring VMLShapeMapping::getArrowWidth(unsigned int op) const
{
switch ( op )
{
case 1: return L"medium";
case 2: return L"wide";
default: return L"narrow";
}
}
std::wstring VMLShapeMapping::getFillMethod(unsigned int p) const
{
short val = (short)( ( p & 0xFFFF0000 ) >> 28 );
switch ( val )
{
case 0: return L"none";
case 1: return L"any";
case 2: return L"linear";
case 4: return L"linear sigma";
default:
return L"any";
}
}
std::wstring VMLShapeMapping::getFillColorString(const ODRAW::OfficeArtFOPTEPtr& pOpt) const
{
ODRAW::FillShadeColors* pColors = dynamic_cast<ODRAW::FillShadeColors*>(pOpt.get());
if (!pColors) return L"";
std::wstring result;
for (size_t i = 0; i < pColors->complex.data.size(); ++i)
{
if (pColors->complex.data[i].position.Fractional == 0)
result += std::to_wstring(pColors->complex.data[i].position.Integral);
else
result += std::to_wstring(pColors->complex.data[i].position.Fractional) +L"f";
result += L" #";
result += pColors->complex.data[i].color.sColorRGB;
result += L";";
}
return result;
}
/// Returns the OpenXML fill type of a fill effect
std::wstring VMLShapeMapping::getFillType(unsigned int p) const
{
switch ( p )
{
case 0: return L"solid";
case 1: return L"pattern";
case 2: return L"tile";
case 3: return L"frame";
case 4: return L"gradient";
case 5: return L"gradientRadial";
case 6: return L"gradientRadial";
case 7: return L"gradient";
case 9:
default:
return L"solid";
}
}
std::wstring VMLShapeMapping::getShadowType(unsigned int p) const
{
switch ( p )
{
case 0: return L"single";
case 1: return L"double";
case 2: return L"perspective";
case 3: return L"shaperelative";
case 4: return L"drawingrelative";
case 5: return L"emboss";
default:
return L"single";
}
}
/// Returns the OpenXML wrap type of the shape
std::wstring VMLShapeMapping::getWrapType (const Spa* pSpa) const
{
// spec values
// 0 = like 2 but doesn't equire absolute object
// 1 = no text next to shape
// 2 = wrap around absolute object
// 3 = wrap as if no object present
// 4 = wrap tightly areound object
// 5 = wrap tightly but allow holes
std::wstring wrapType = L"none";
if (pSpa != NULL)
{
switch (pSpa->wr)
{
case 0:
case 2: wrapType = L"square"; break;
case 1: wrapType = L"topAndBottom"; break;
case 3: wrapType = L"through"; break;
case 4:
case 5: wrapType = L"tight"; break;
default:
wrapType = L"none"; break;
}
}
return wrapType;
}
std::wstring VMLShapeMapping::GetConnectAngles(const ODRAW::OfficeArtFOPTEPtr& pOpt) const
{
ODRAW::PConnectionSitesDir* pAngles = dynamic_cast<ODRAW::PConnectionSitesDir*>(pOpt.get());
if (!pAngles) return L"";
std::wstring angles;
for (size_t i = 0; i < pAngles->complex.data.size(); ++i)
{
angles += std::to_wstring((int)pAngles->complex.data[i].dVal) + (i < (pAngles->complex.data.size() - 1) ? L"," : L"");
}
return angles;
}
int VMLShapeMapping::UpdateFromGuides(const int val) const
{
int new_val = val;
LONG lMinF = (LONG)0x80000000;
if (lMinF <= val)
{
int index = (DWORD)val - 0x80000000;
if (index >= 0 && index < (int)m_arrGuides.size())
{
new_val = m_arrGuides[index].m_param_value3;
}
}
return new_val;
}
void VMLShapeMapping::GetGuides( const ODRAW::OfficeArtFOPTEPtr& pOpt )
{
ODRAW::PGuides* pGuides = dynamic_cast<ODRAW::PGuides*>(pOpt.get());
if (!pGuides) return;
m_arrGuides = pGuides->complex.data;
//for (size_t i = 0; i < pGuides->complex.data.size(); ++i)
//{
// _guides g;
// g.type = pGuides->complex.data[i].type;
// g.param_type1 = pGuides->complex.data[i].param_type1;
// g.param_type2 = pGuides->complex.data[i].param_type2;
// g.param_type3 = pGuides->complex.data[i].param_type3;
// g.param1 = pGuides->complex.data[i].param1;
// g.param2 = pGuides->complex.data[i].param2;
// g.param3 = pGuides->complex.data[i].param3;
// m_arrGuides.push_back(g);
//}
}
std::wstring VMLShapeMapping::GetConnectLocs( const ODRAW::OfficeArtFOPTEPtr& pOpt ) const
{
ODRAW::PConnectionSites* pConnection = dynamic_cast<ODRAW::PConnectionSites*>(pOpt.get());
if (!pConnection) return L"";
std::wstring locs;
for (size_t i = 0; i < pConnection->complex.data.size(); ++i)
{
POINT pt;
pt.x = UpdateFromGuides(pConnection->complex.data[i].x);
pt.y = UpdateFromGuides(pConnection->complex.data[i].y);
locs += std::to_wstring(pt.x) + L"," + std::to_wstring(pt.y) + (i < (pConnection->complex.data.size() - 1) ? L";" : L"");
}
return locs;
}
std::vector<std::wstring> VMLShapeMapping::GetTextRectangles( const ODRAW::OfficeArtFOPTEPtr& pOpt ) const
{
std::vector<std::wstring> rectangles;
ODRAW::PInscribe* pInscribe = dynamic_cast<ODRAW::PInscribe*>(pOpt.get());
if (!pInscribe) return rectangles;
for (size_t i = 0; i < pInscribe->complex.data.size(); ++i)
{
RECT rc;
rc.top = UpdateFromGuides(pInscribe->complex.data[i].t);
rc.left = UpdateFromGuides(pInscribe->complex.data[i].l);
rc.right = UpdateFromGuides(pInscribe->complex.data[i].r);
rc.bottom = UpdateFromGuides(pInscribe->complex.data[i].b);
rectangles.push_back( std::to_wstring(rc.top) + L"," + std::to_wstring(rc.left) + L"," +
std::to_wstring(rc.right) + L"," + std::to_wstring(rc.bottom));
}
return rectangles;
}
//------------------------------------------------------------------------------------------------------
void VMLShapeMapping::ApplyPrimitives(DrawingPrimitives * primitives)
{
size_t index = 0;
while(true)
{
index = ApplyPrimitive(primitives, index);
if (index > primitives->size() - 1)
break;
}
}
static int currentTextBoxIndex = 1;
size_t VMLShapeMapping::ApplyPrimitive(DrawingPrimitives * primitives, size_t index)
{
if (!primitives) return index++;
if (index >= primitives->size()) return index++;
DrawingPrimitive *primitive = dynamic_cast<DrawingPrimitive *>(primitives->at(index));
m_pXmlWriter->WriteNodeBegin(primitive->strVmlType, true );
if (primitive->type == 0x0007)
{
DrawingPrimitiveCTextBox * callout = dynamic_cast<DrawingPrimitiveCTextBox *>(primitive);
if ((callout) && (callout->txbx))
{
//временно обычный текстбокс
callout->txbx->xa += callout->xa;
callout->txbx->ya += callout->ya;
WritePrimitiveProps(dynamic_cast<DrawingPrimitive*>(callout->txbx), (index==0?true:false));
}
//todooo нарисовать кастомный шейп
}
else
WritePrimitiveProps(primitive, (index==0?true:false));
if (primitive->type == 0x0000)
{
index++;
while(true)
{
if (index > primitives->size() - 1)
break;
primitive = dynamic_cast<DrawingPrimitive *>(primitives->at(index));
if (primitive->type == 0x0008)
{
break;
}
index = ApplyPrimitive(primitives, index);
}
}
if (primitive->type == 0x0002 || primitive->type == 0x0007)
{
int nLTxID = currentTextBoxIndex++;;
if (-1 != nLTxID)
{
TextboxMapping textboxMapping(m_context, nLTxID - 1, m_pXmlWriter, m_pCaller);
//textboxMapping.SetInset(ndxTextLeft, ndyTextTop, ndxTextRight, ndyTextBottom);
m_context->_doc->Convert(&textboxMapping);
}
}
m_pXmlWriter->WriteNodeEnd( primitive->strVmlType );
index++;
return index;
}
void VMLShapeMapping::WritePrimitiveProps (DrawingPrimitive * primitive, bool root)
{
TwipsValue x( primitive->xa );
TwipsValue y( primitive->ya );
TwipsValue w( primitive->dxa );
TwipsValue h( primitive->dya );
m_context->_doc->GetOfficeArt()->m_uLastShapeId++;
std::wstring strId = std::wstring(L"_x0000_s") + std::to_wstring(m_context->_doc->GetOfficeArt()->m_uLastShapeId);
//m_pXmlWriter->WriteAttribute ( L"id") , strId);
m_pXmlWriter->WriteAttribute ( L"o:spid", strId);
std::wstring strStyle = L"position:absolute;visibility:visible;mso-wrap-style:square;";
DrawingPrimitiveLine * line = dynamic_cast<DrawingPrimitiveLine *>(primitive);
if (line)
{
TwipsValue x1( line->xaStart );
TwipsValue y1( line->yaStart );
TwipsValue x2( line->xaEnd );
TwipsValue y2( line->yaEnd );
std::wstring strStart = std::to_wstring(line->xaStart + primitive->xa) + L"," + std::to_wstring(line->yaStart + primitive->ya);
std::wstring strEnd = std::to_wstring(line->xaEnd + primitive->xa) + L"," + std::to_wstring(line->yaEnd + primitive->ya);
m_pXmlWriter->WriteAttribute(L"from", strStart);
m_pXmlWriter->WriteAttribute(L"to", strEnd);
}
else
{
if (root)
{
//strStyle += L"left:" + std::to_wstring( x.ToPoints()) + L"pt;";
//strStyle += L"top:" + std::to_wstring( y.ToPoints()) + L"pt;";
strStyle += L"width:" + std::to_wstring( (int)w.ToPoints()) + L"pt;";
strStyle += L"height:" + std::to_wstring( (int)h.ToPoints()) + L"pt;";
strStyle += L"margin-left:" + std::to_wstring( (int)x.ToPoints()) + L"pt;";
strStyle += L"margin-top:" + std::to_wstring( (int)y.ToPoints()) + L"pt;";
if (false == m_inGroup)
{
std::wstring xMargin;
std::wstring yMargin;
if (m_pSpa->bx == PAGE) xMargin = L"page;";
if (m_pSpa->by == PAGE) yMargin = L"page;";
if (m_pSpa->bx == MARGIN) xMargin = L"margin;";
if (m_pSpa->by == MARGIN) yMargin = L"margin;";
if (!xMargin.empty()) strStyle += L"mso-position-horizontal-relative:" + xMargin;
if (!yMargin.empty()) strStyle += L"mso-position-vertical-relative:" + yMargin;
}
std::wstring strSize = std::to_wstring(primitive->dxa) + L"," + std::to_wstring(primitive->dya);
std::wstring strOrigin = std::to_wstring(primitive->xa) + L"," + std::to_wstring(primitive->ya);
m_pXmlWriter->WriteAttribute( L"coordsize", strSize);
//m_pXmlWriter->WriteAttribute( L"coordorigin"), strOrigin);
}
else
{
strStyle += L"left:" + std::to_wstring( primitive->xa) + L";";
strStyle += L"top:" + std::to_wstring( primitive->ya) + L";";
strStyle += L"width:" + std::to_wstring( primitive->dxa) + L";";
strStyle += L"height:" + std::to_wstring( primitive->dya) + L";";
}
}
if (primitive->fillPattern == 0)
m_pXmlWriter->WriteAttribute( L"filled", L"f");
if (primitive->type > 1)
{
m_pXmlWriter->WriteAttribute( L"fillColor", FormatUtils::IntToFormattedWideString(primitive->fillFore, L"#%06x"));
}
m_pXmlWriter->WriteAttribute( L"style", strStyle);
std::wstring strStrokeWeight = std::to_wstring(primitive->lineWeight / 20) + L"pt";
if (primitive->lineWeight > 20)
m_pXmlWriter->WriteAttribute( L"strokeweight", strStrokeWeight);
if (primitive->type > 0)
m_pXmlWriter->WriteAttribute( L"strokecolor", FormatUtils::IntToFormattedWideString(primitive->lineColor, L"#%06x"));
m_pXmlWriter->WriteNodeEnd( L"", true, false );
if (primitive->type > 1 && primitive->fillPattern > 1)
{
m_pXmlWriter->WriteNodeBegin(L"v:fill", true );
m_pXmlWriter->WriteAttribute( L"color2", FormatUtils::IntToFormattedWideString(primitive->fillBack, L"#%06x"));
m_pXmlWriter->WriteAttribute( L"type", L"pattern");
m_pXmlWriter->WriteNodeEnd( L"", true, false );
m_pXmlWriter->WriteNodeEnd( L"v:fill" );
}
if (primitive->lineStyle > 1)
{
m_pXmlWriter->WriteNodeBegin(L"v:stroke", true );
std::wstring strDashStyle = std::to_wstring(primitive->lineStyle) + L" 1";
m_pXmlWriter->WriteAttribute( L"dashstyle", strDashStyle);
m_pXmlWriter->WriteNodeEnd( L"", true, false );
m_pXmlWriter->WriteNodeEnd( L"v:stroke" );
}
}
}