mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-04-07 13:55:33 +08:00
2106 lines
63 KiB
C++
2106 lines
63 KiB
C++
/*
|
||
* (c) Copyright Ascensio System SIA 2010-2016
|
||
*
|
||
* 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 Lubanas st. 125a-25, Riga, Latvia,
|
||
* EU, LV-1021.
|
||
*
|
||
* 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 "OfficeDrawing/DiagramBooleanProperties.h"
|
||
#include "OfficeDrawing/GeometryBooleanProperties.h"
|
||
#include "OfficeDrawing/ShadowStyleBooleanProperties.h"
|
||
#include "OfficeDrawing/GeometryBooleanProperties.h"
|
||
#include "OfficeDrawing/FillStyleBooleanProperties.h"
|
||
#include "OfficeDrawing/GeometryBooleanProperties.h"
|
||
#include "OfficeDrawing/FillStyleBooleanProperties.h"
|
||
#include "OfficeDrawing/LineStyleBooleanProperties.h"
|
||
#include "OfficeDrawing/GeometryTextBooleanProperties.h"
|
||
#include "OfficeDrawing/GroupShapeBooleanProperties.h"
|
||
#include "OfficeDrawing/ProtectionBooleanProperties.h"
|
||
|
||
#include "DrawingPrimitives.h"
|
||
|
||
#include "../../DesktopEditor/common/String.h"
|
||
|
||
#include "../Common/FormatUtils.h"
|
||
|
||
namespace DocFileFormat
|
||
{
|
||
VMLShapeMapping::VMLShapeMapping (ConversionContext* pConv, XMLTools::CStringXmlWriter* pWriter, Spa* pSpa, PictureDescriptor* pPicture, IMapping* pCaller, bool isInlineShape) : PropertiesMapping(pWriter)
|
||
{
|
||
m_isInlineShape = isInlineShape;
|
||
m_isBullete = false;
|
||
|
||
m_pSpa = pSpa;
|
||
m_pCaller = pCaller;
|
||
m_pBlipStore = NULL;
|
||
|
||
m_context = pConv;
|
||
m_pict = pPicture;
|
||
m_nImageId = 0;
|
||
|
||
m_imagedata = XMLTools::XMLElement<wchar_t>(L"v:imagedata");
|
||
m_fill = XMLTools::XMLElement<wchar_t>(L"v:fill");
|
||
m_stroke = XMLTools::XMLElement<wchar_t>(L"v:stroke");
|
||
m_shadow = XMLTools::XMLElement<wchar_t>(L"v:shadow");
|
||
m_3dstyle = XMLTools::XMLElement<wchar_t>(L"o:extrusion");
|
||
m_textpath = XMLTools::XMLElement<wchar_t>(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);
|
||
}
|
||
}
|
||
|
||
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]);
|
||
std::list<OptionEntry> options = groupShape->ExtractOptions();
|
||
ChildAnchor* anchor = groupShape->FirstChildWithType<ChildAnchor>();
|
||
|
||
m_shapeId = GetShapeID(shape);
|
||
|
||
m_pXmlWriter->WriteNodeBegin( L"v:group", true );
|
||
m_pXmlWriter->WriteAttribute( L"id", m_shapeId .c_str());
|
||
m_pXmlWriter->WriteAttribute( L"style", FormatUtils::XmlEncode(buildStyle(shape, anchor, options, container->Index)).c_str() );
|
||
m_pXmlWriter->WriteAttribute( L"coordorigin", ( FormatUtils::IntToWideString(gsr->rcgBounds.topLeftAngle.x) + L"," + FormatUtils::IntToWideString( gsr->rcgBounds.topLeftAngle.y)).c_str() );
|
||
m_pXmlWriter->WriteAttribute( L"coordsize", ( FormatUtils::IntToWideString(gsr->rcgBounds.size.cx) + L"," + FormatUtils::IntToWideString(gsr->rcgBounds.size.cy)).c_str() );
|
||
|
||
// Write wrap coords
|
||
std::list<OptionEntry>::const_iterator end = options.end();
|
||
for (std::list<OptionEntry>::const_iterator iter = options.begin(); iter != end; ++iter)
|
||
{
|
||
switch (iter->pid)
|
||
{
|
||
case pWrapPolygonVertices:
|
||
{
|
||
std::wstring wrapCoords = getWrapCoords(*iter);
|
||
if (wrapCoords.length())
|
||
m_pXmlWriter->WriteAttribute(L"wrapcoords", wrapCoords.c_str());
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
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);
|
||
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.c_str() );
|
||
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::list<OptionEntry> options = pContainer->ExtractOptions();
|
||
ChildAnchor* pAnchor = pContainer->FirstChildWithType<ChildAnchor>();
|
||
ClientAnchor* clientAnchor = pContainer->FirstChildWithType<ClientAnchor>();
|
||
|
||
WriteBeginShapeNode (pShape);
|
||
|
||
m_shapeId = GetShapeID(pShape);
|
||
|
||
count_vml_objects++;
|
||
|
||
if (m_shapeId.empty())
|
||
m_shapeId = std::wstring(L"_x0000_s") + FormatUtils::IntToWideString(1024 + count_vml_objects);
|
||
|
||
m_pXmlWriter->WriteAttribute ( L"id", m_shapeId );
|
||
|
||
if ( !pShape->fBackground )
|
||
{
|
||
if (pShape->GetShapeType())
|
||
{
|
||
freeform = false;
|
||
m_pXmlWriter->WriteAttribute( L"type", (std::wstring(L"#") + VMLShapeTypeMapping::GenerateTypeId(pShape->GetShapeType())).c_str());
|
||
|
||
m_pXmlWriter->WriteAttribute( L"style", FormatUtils::XmlEncode(buildStyle(pShape, pAnchor, options, pContainer->Index)).c_str());
|
||
}
|
||
|
||
if (pShape->is<LineType>())
|
||
{
|
||
//append "from" and "to" attributes
|
||
m_pXmlWriter->WriteAttribute(L"from", GetLineFrom(pAnchor).c_str());
|
||
m_pXmlWriter->WriteAttribute(L"to", GetLineTo(pAnchor).c_str());
|
||
}
|
||
|
||
if (m_isBullete)
|
||
{
|
||
m_pXmlWriter->WriteAttribute(L"o:bullet", L"t");
|
||
}
|
||
}
|
||
|
||
EmuValue ShadowOffsetX;
|
||
EmuValue ShadowOffsetY;
|
||
EmuValue SecondShadowOffsetX;
|
||
EmuValue SecondShadowOffsetY;
|
||
EmuValue ViewPointX;
|
||
EmuValue ViewPointY;
|
||
EmuValue ViewPointZ;
|
||
|
||
double viewPointOriginX = 0;
|
||
double viewPointOriginY = 0;
|
||
double ShadowOriginX = 0;
|
||
double ShadowOriginY = 0;
|
||
unsigned int xCoord = 0;
|
||
unsigned int yCoord = 0;
|
||
bool stroked = true;
|
||
bool filled = true;
|
||
bool hasTextbox = false;
|
||
bool layoutInCell = true; //anmeldebogenfos.doc
|
||
|
||
int ndxTextLeft = -1;
|
||
int ndyTextTop = -1;
|
||
int ndxTextRight = -1;
|
||
int ndyTextBottom = -1;
|
||
|
||
bool bHavePath = false;
|
||
int nAdjValues = 0;
|
||
int nLTxID = -1;
|
||
|
||
std::wstring sTextboxStyle;
|
||
|
||
std::wstring adjValues[8];
|
||
ShadowStyleBooleanProperties shadowBoolean(0);
|
||
std::vector<std::wstring> arrInscribe;
|
||
|
||
std::list<OptionEntry>::const_iterator end = options.end();
|
||
for (std::list<OptionEntry>::const_iterator iter = options.begin(); iter != end; ++iter)
|
||
{
|
||
switch (iter->pid)
|
||
{
|
||
//BOOLEANS
|
||
case geometryBooleans:
|
||
{
|
||
GeometryBooleanProperties booleans(iter->op);
|
||
if (booleans.fUsefLineOK && !booleans.fLineOK)
|
||
{
|
||
stroked = false;
|
||
}
|
||
|
||
if (booleans.fUsefFillOK && !booleans.fFillOK)
|
||
{
|
||
filled = false;
|
||
}
|
||
}
|
||
break;
|
||
case fillStyleBooleanProperties:
|
||
{
|
||
FillStyleBooleanProperties booleans(iter->op);
|
||
if (booleans.fUsefFilled && !booleans.fFilled)
|
||
{
|
||
filled = false;
|
||
}
|
||
}break;
|
||
case lineStyleBooleans:
|
||
{
|
||
LineStyleBooleanProperties booleans(iter->op);
|
||
if (booleans.fUsefLine && !booleans.fLine)
|
||
{
|
||
stroked = false;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case protectionBooleans:
|
||
{
|
||
ProtectionBooleanProperties booleans(iter->op);
|
||
}
|
||
break;
|
||
|
||
case diagramBooleans:
|
||
{
|
||
DiagramBooleanProperties booleans(iter->op);
|
||
}
|
||
break;
|
||
|
||
case groupShapeBooleans:
|
||
{
|
||
GroupShapeBooleanProperties booleans(iter->op);
|
||
if (booleans.fUsefLayoutInCell)
|
||
{
|
||
layoutInCell = booleans.fLayoutInCell;
|
||
}
|
||
}
|
||
break;
|
||
|
||
// GEOMETRY
|
||
|
||
case adjustValue:
|
||
{
|
||
adjValues[0] = FormatUtils::IntToWideString( (int)iter->op );
|
||
nAdjValues = (std::max)(nAdjValues,1);
|
||
}
|
||
break;
|
||
|
||
case adjust2Value:
|
||
{
|
||
adjValues[1] = FormatUtils::IntToWideString( (int)iter->op );
|
||
nAdjValues = (std::max)(nAdjValues,2);
|
||
}
|
||
break;
|
||
|
||
case adjust3Value:
|
||
{
|
||
adjValues[2] = FormatUtils::IntToWideString( (int)iter->op );
|
||
nAdjValues = (std::max)(nAdjValues,3);
|
||
}break;
|
||
case adjust4Value:
|
||
{
|
||
adjValues[3] = FormatUtils::IntToWideString( (int)iter->op );
|
||
nAdjValues = (std::max)(nAdjValues,4);
|
||
}break;
|
||
case adjust5Value:
|
||
{
|
||
adjValues[4] = FormatUtils::IntToWideString( (int)iter->op );
|
||
nAdjValues = (std::max)(nAdjValues,5);
|
||
}break;
|
||
case adjust6Value:
|
||
{
|
||
adjValues[5] = FormatUtils::IntToWideString( (int)iter->op );
|
||
nAdjValues = (std::max)(nAdjValues,6);
|
||
}break;
|
||
case adjust7Value:
|
||
{
|
||
adjValues[6] = FormatUtils::IntToWideString( (int)iter->op );
|
||
nAdjValues = (std::max)(nAdjValues,7);
|
||
}break;
|
||
case adjust8Value:
|
||
{
|
||
adjValues[7] = FormatUtils::IntToWideString( (int)iter->op );
|
||
nAdjValues = (std::max)(nAdjValues,8);
|
||
}break;
|
||
case pWrapPolygonVertices:
|
||
{
|
||
std::wstring wrapCoords = getWrapCoords(*iter);
|
||
|
||
if (!wrapCoords.empty())
|
||
{
|
||
m_pXmlWriter->WriteAttribute( L"wrapcoords", wrapCoords.c_str() );
|
||
}
|
||
}break;
|
||
case geoRight:
|
||
{
|
||
xCoord = iter->op;
|
||
}break;
|
||
case geoBottom:
|
||
{
|
||
yCoord = iter->op;
|
||
}break;
|
||
case pGuides:
|
||
{
|
||
}break;
|
||
case pInscribe:
|
||
{
|
||
arrInscribe = GetTextRectangles(*iter);
|
||
}break;
|
||
// OUTLINE
|
||
case lineColor:
|
||
{
|
||
RGBColor lineColor((int)iter->op, RedFirst);
|
||
if ( !pShape->fBackground )
|
||
m_pXmlWriter->WriteAttribute( L"strokecolor", (std::wstring(L"#") + lineColor.SixDigitHexCode).c_str());
|
||
}break;
|
||
case lineWidth:
|
||
{
|
||
if (iter->op > 0)
|
||
{
|
||
EmuValue eLineWidth ((int)iter->op );
|
||
m_pXmlWriter->WriteAttribute(L"strokeweight", FormatUtils::DoubleToWideString(eLineWidth.ToPoints()) + L"pt");
|
||
}
|
||
}break;
|
||
case lineDashing:
|
||
{
|
||
appendValueAttribute(&m_stroke, L"dashstyle", FormatUtils::MapValueToWideString( iter->op, &Global::DashStyleMap[0][0], 11, 16 ).c_str() );
|
||
}break;
|
||
case lineStyle:
|
||
{
|
||
appendValueAttribute(&m_stroke, L"linestyle", getLineStyle( iter->op ).c_str());
|
||
}break;
|
||
case lineEndArrowhead:
|
||
{
|
||
appendValueAttribute(&m_stroke, L"endarrow", getArrowStyle( iter->op ).c_str());
|
||
}break;
|
||
case lineEndArrowLength:
|
||
{
|
||
appendValueAttribute(&m_stroke, L"endarrowlength", getArrowLength( iter->op ).c_str());
|
||
}break;
|
||
case lineEndArrowWidth:
|
||
{
|
||
appendValueAttribute(&m_stroke, L"endarrowwidth", getArrowWidth( iter->op ).c_str());
|
||
}break;
|
||
case lineStartArrowhead:
|
||
{
|
||
appendValueAttribute(&m_stroke, L"startarrow", getArrowStyle( iter->op ).c_str());
|
||
}break;
|
||
case lineStartArrowLength:
|
||
{
|
||
appendValueAttribute(&m_stroke, L"startarrowlength", getArrowLength( iter->op ).c_str());
|
||
}break;
|
||
case lineStartArrowWidth:
|
||
{
|
||
appendValueAttribute(&m_stroke, L"startarrowwidth", getArrowWidth( iter->op ).c_str());
|
||
}break;
|
||
// FILL
|
||
case fillColor:
|
||
{
|
||
RGBColor fillColor((int)iter->op, RedFirst);
|
||
m_pXmlWriter->WriteAttribute(L"fillcolor", ( std::wstring( L"#" ) + fillColor.SixDigitHexCode ).c_str());
|
||
}break;
|
||
case fillBackColor:
|
||
{
|
||
RGBColor fillBackColor( (int)iter->op, RedFirst );
|
||
appendValueAttribute(&m_fill, L"color2", ( std::wstring( L"#" ) + fillBackColor.SixDigitHexCode ).c_str());
|
||
}break;
|
||
case fillAngle:
|
||
{
|
||
FixedPointNumber fllAngl( iter->op );
|
||
appendValueAttribute(&m_fill, L"angle", FormatUtils::DoubleToWideString( fllAngl.ToAngle() ).c_str());
|
||
}break;
|
||
case fillShadeType:
|
||
{
|
||
appendValueAttribute(&m_fill, L"method", getFillMethod( iter->op ).c_str());
|
||
}break;
|
||
case fillShadeColors:
|
||
{
|
||
appendValueAttribute(&m_fill, L"colors", getFillColorString( iter->opComplex, iter->op ).c_str());
|
||
}break;
|
||
case fillFocus:
|
||
{
|
||
appendValueAttribute(&m_fill, L"focus", ( FormatUtils::IntToWideString( iter->op ) + L"%" ).c_str());
|
||
}break;
|
||
case fillType:
|
||
{
|
||
appendValueAttribute(&m_fill, L"type", getFillType( iter->op ).c_str());
|
||
}break;
|
||
case 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" ) + FormatUtils::IntToWideString(m_nImageId) ).c_str());
|
||
}
|
||
}break;
|
||
case fillOpacity:
|
||
{
|
||
appendValueAttribute(&m_fill, L"opacity", ( FormatUtils::IntToWideString( iter->op ) + L"f" ).c_str());
|
||
}
|
||
break;
|
||
case fillBackOpacity:
|
||
{
|
||
appendValueAttribute(&m_fill, L"opacity2", (FormatUtils::IntToWideString(iter->op) + L"f").c_str());
|
||
}break;
|
||
// SHADOW
|
||
case shadowType:
|
||
{
|
||
appendValueAttribute(&m_shadow, L"type", getShadowType(iter->op).c_str());
|
||
}break;
|
||
|
||
case shadowColor:
|
||
{
|
||
RGBColor shadowColor((int)iter->op, RedFirst);
|
||
appendValueAttribute(&m_shadow, L"color", ( std::wstring( L"#" ) + shadowColor.SixDigitHexCode ).c_str());
|
||
}break;
|
||
case shadowOffsetX:
|
||
{
|
||
ShadowOffsetX = EmuValue( (int)iter->op );
|
||
}break;
|
||
case shadowSecondOffsetX:
|
||
{
|
||
SecondShadowOffsetX = EmuValue( (int)iter->op );
|
||
}break;
|
||
case shadowOffsetY:
|
||
{
|
||
ShadowOffsetY = EmuValue( (int)iter->op );
|
||
}break;
|
||
case shadowSecondOffsetY:
|
||
{
|
||
SecondShadowOffsetY = EmuValue( (int)iter->op );
|
||
}break;
|
||
case shadowOriginX:
|
||
{
|
||
ShadowOriginX = ( iter->op / pow( (double)2, (double)16 ) );
|
||
}break;
|
||
case shadowOriginY:
|
||
{
|
||
ShadowOriginY = (iter->op / pow( (double)2, (double)16));
|
||
}break;
|
||
case shadowOpacity:
|
||
{
|
||
double shadowOpa = (iter->op / pow( (double)2, (double)16));
|
||
|
||
appendValueAttribute(&m_shadow, L"opacity", FormatUtils::DoubleToFormattedWideString( shadowOpa, L"%.2f" ).c_str());
|
||
}break;
|
||
case shadowStyleBooleanProperties:
|
||
{
|
||
shadowBoolean = ShadowStyleBooleanProperties(iter->op);
|
||
}break;
|
||
// OLE
|
||
case pictureId:
|
||
{
|
||
indexOLE = iter->op;
|
||
}break;
|
||
// PICTURE
|
||
case 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" ) + FormatUtils::IntToWideString(m_nImageId) ).c_str());
|
||
}
|
||
}
|
||
}break;
|
||
case pibName:
|
||
{
|
||
std::wstring name;
|
||
FormatUtils::GetSTLCollectionFromBytes<std::wstring>(&name, iter->opComplex, iter->op, ENCODING_UTF16);
|
||
if (!name.empty())
|
||
appendValueAttribute(&m_imagedata, L"o:title", FormatUtils::XmlEncode(name).c_str());
|
||
}break;
|
||
// 3D STYLE
|
||
case f3D:
|
||
case threeDStyleBooleanProperties:
|
||
case threeDObjectBooleanProperties:
|
||
break;
|
||
|
||
case c3DExtrudeBackward:
|
||
{
|
||
EmuValue backwardValue( (int)iter->op );
|
||
std::wstring depth = FormatUtils::DoubleToWideString( backwardValue.ToPoints() ) + L"pt";
|
||
appendValueAttribute(&m_3dstyle, L"backdepth", depth.c_str());
|
||
}break;
|
||
case c3DAmbientIntensity:
|
||
{
|
||
std::wstring intens = FormatUtils::IntToWideString((int)iter->op) + L"f";
|
||
appendValueAttribute(&m_3dstyle, L"brightness", intens.c_str());
|
||
}break;
|
||
case c3DSpecularAmt:
|
||
{
|
||
std::wstring amt = FormatUtils::IntToWideString((int)iter->op) + L"f";
|
||
appendValueAttribute(&m_3dstyle, L"specularity", amt.c_str());
|
||
}break;
|
||
case c3DDiffuseAmt:
|
||
{
|
||
std::wstring amt = FormatUtils::IntToWideString((int)iter->op) + L"f";
|
||
appendValueAttribute(&m_3dstyle, L"diffusity", amt.c_str());
|
||
}break;
|
||
case c3DKeyIntensity:
|
||
{
|
||
std::wstring amt = FormatUtils::IntToWideString((int)iter->op);
|
||
appendValueAttribute(&m_3dstyle, L"lightlevel", amt.c_str());
|
||
}break;
|
||
case c3DExtrusionColor:
|
||
{
|
||
std::wstring color = FormatUtils::IntToFormattedWideString(iter->op, L"#%06x");
|
||
appendValueAttribute(&m_3dstyle, L"color", color.c_str());
|
||
}break;
|
||
case c3DSkewAngle:
|
||
{
|
||
FixedPointNumber skewAngle( iter->op );
|
||
appendValueAttribute(&m_3dstyle, L"skewangle", FormatUtils::DoubleToWideString( skewAngle.ToAngle() ).c_str());
|
||
}break;
|
||
case c3DXViewpoint:
|
||
{
|
||
ViewPointX = EmuValue( FixedPointNumber( iter->op ).Integral );
|
||
}break;
|
||
case c3DYViewpoint:
|
||
{
|
||
ViewPointY = EmuValue( FixedPointNumber( iter->op ).Integral );
|
||
}break;
|
||
case c3DZViewpoint:
|
||
{
|
||
ViewPointZ = EmuValue( FixedPointNumber( iter->op ).Integral );
|
||
}break;
|
||
case c3DOriginX:
|
||
{
|
||
FixedPointNumber dOriginX( iter->op );
|
||
viewPointOriginX = ( dOriginX.Integral / 65536.0 );
|
||
}break;
|
||
case c3DOriginY:
|
||
{
|
||
FixedPointNumber dOriginY( iter->op );
|
||
viewPointOriginY = (dOriginY.Integral / 65536.0 );
|
||
}break;
|
||
// TEXTBOX
|
||
case lTxid:
|
||
{
|
||
hasTextbox = true;
|
||
nLTxID = (((iter->op) >> 16) & 0xFFFF);
|
||
}break;
|
||
case dxTextLeft: {ndxTextLeft = (int)iter->op;break;}
|
||
case dyTextTop: {ndyTextTop = (int)iter->op;break;}
|
||
case dxTextRight: {ndxTextRight = (int)iter->op;break;}
|
||
case dyTextBottom: {ndyTextBottom = (int)iter->op;break;}
|
||
case txflTextFlow:
|
||
{
|
||
switch(iter->op)
|
||
{
|
||
case 0:
|
||
case 4://обычный
|
||
break;
|
||
case 1:
|
||
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;
|
||
// Word Art
|
||
case gtextUNICODE:
|
||
{
|
||
std::wstring text = NSStringExt::CConverter::GetUnicodeFromUTF16((unsigned short*)iter->opComplex, (iter->op)/2);
|
||
|
||
text = FormatUtils::XmlEncode(text);
|
||
|
||
if (0 <= text.find(L"\n"))
|
||
{
|
||
m_textpath.AppendText(text.c_str());
|
||
}
|
||
text = ReplaceString(text, L"\n", L"
");
|
||
appendValueAttribute(&m_textpath, L"string", text.c_str());
|
||
}break;
|
||
case gtextFont:
|
||
{
|
||
std::wstring font = NSStringExt::CConverter::GetUnicodeFromUTF16((unsigned short*)iter->opComplex, (iter->op)/2);
|
||
int i = font.size();
|
||
while (i > 0)
|
||
{
|
||
if (font[i-1] != 0) break;
|
||
i--;
|
||
}
|
||
if (i < font.size()) font.erase(font.begin() + i, font.end());
|
||
|
||
font = std::wstring(L"\"") + font + std::wstring(L"\"");
|
||
appendStyleProperty(&m_textPathStyle, L"font-family", font);
|
||
}break;
|
||
case gtextSize:
|
||
{
|
||
std::wstring fontSize = FormatUtils::IntToWideString(iter->op/65535);
|
||
appendStyleProperty(&m_textPathStyle, L"font-size", fontSize + L"pt");
|
||
}break;
|
||
case gtextSpacing:
|
||
{
|
||
std::wstring spacing = FormatUtils::IntToWideString(iter->op);
|
||
appendStyleProperty(&m_textPathStyle, L"v-text-spacing", spacing + L"f");
|
||
}break;
|
||
case geometryTextBooleanProperties:
|
||
{
|
||
GeometryTextBooleanProperties props(iter->op);
|
||
if (props.fUsegtextFBestFit && props.gtextFBestFit)
|
||
{
|
||
appendValueAttribute(&m_textpath, L"fitshape", L"t");
|
||
}
|
||
if (props.fUsegtextFShrinkFit && props.gtextFShrinkFit)
|
||
{
|
||
appendValueAttribute(&m_textpath, L"trim", L"t");
|
||
}
|
||
if (props.fUsegtextFVertical && props.gtextFVertical)
|
||
{
|
||
appendStyleProperty(&m_textPathStyle, L"v-rotate-letters", L"t");
|
||
//_twistDimension = true;
|
||
}
|
||
if (props.fUsegtextFKern && props.gtextFKern)
|
||
{
|
||
appendStyleProperty(&m_textPathStyle, L"v-text-kern", L"t");
|
||
}
|
||
if (props.fUsegtextFItalic && props.gtextFItalic)
|
||
{
|
||
appendStyleProperty(&m_textPathStyle, L"font-style", L"italic");
|
||
}
|
||
if (props.fUsegtextFBold && props.gtextFBold)
|
||
{
|
||
appendStyleProperty(&m_textPathStyle, L"font-weight", L"bold");
|
||
}
|
||
}break;
|
||
// PATH
|
||
case shapePath :
|
||
{
|
||
bHavePath = true;
|
||
|
||
std::wstring path = ParsePath(options);
|
||
|
||
if (false == path.empty())
|
||
m_pXmlWriter->WriteAttribute (L"path", path.c_str());
|
||
}break;
|
||
default:
|
||
{
|
||
int val = iter->op;
|
||
}break;
|
||
}
|
||
}
|
||
|
||
if (false == bHavePath) // фигура может быть задана только наборами вершин и индексов
|
||
{
|
||
std::wstring path = ParsePath(options);
|
||
|
||
if (false == path.empty())
|
||
m_pXmlWriter->WriteAttribute (L"path", path.c_str());
|
||
}
|
||
|
||
if ( !filled )
|
||
{
|
||
m_pXmlWriter->WriteAttribute( L"filled", L"f" );
|
||
}
|
||
|
||
if ( !stroked )
|
||
{
|
||
m_pXmlWriter->WriteAttribute( L"stroked", L"f" );
|
||
}
|
||
|
||
if (!layoutInCell)
|
||
{
|
||
m_pXmlWriter->WriteAttribute(L"o:allowincell", L"f");
|
||
}
|
||
|
||
if ( ( xCoord > 0 ) && ( yCoord > 0 ) )
|
||
{
|
||
m_pXmlWriter->WriteAttribute( L"coordsize", ( FormatUtils::IntToWideString( xCoord ) + L"," + FormatUtils::IntToWideString( yCoord ) ).c_str() );
|
||
}
|
||
|
||
int nCode = 0;
|
||
if (pShape->GetShapeType())
|
||
{
|
||
nCode = pShape->GetShapeType()->GetTypeCode();
|
||
}
|
||
|
||
if (DocFileFormat::msosptRoundRectangle == nCode)
|
||
{
|
||
if (nAdjValues)
|
||
{
|
||
m_pXmlWriter->WriteAttribute(L"arcsize", adjValues[0].c_str());
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (nAdjValues)
|
||
{
|
||
std::wstring adjTag = adjValues[0];
|
||
|
||
for (int i = 1; i < nAdjValues; ++i)
|
||
adjTag += std::wstring(L",") + adjValues[i];
|
||
|
||
m_pXmlWriter->WriteAttribute(L"adj", adjTag.c_str());
|
||
}
|
||
}
|
||
|
||
m_pXmlWriter->WriteNodeEnd( L"", true, false );
|
||
|
||
//build shadow offsets
|
||
std::wstring offset;
|
||
|
||
if ( ShadowOffsetX != 0 )
|
||
{
|
||
offset += FormatUtils::DoubleToWideString( ShadowOffsetX.ToPoints() );
|
||
offset += L"pt";
|
||
}
|
||
if ( ShadowOffsetY != 0 )
|
||
{
|
||
offset += L",";
|
||
offset += FormatUtils::DoubleToWideString( ShadowOffsetY.ToPoints() );
|
||
offset += L"pt";
|
||
}
|
||
if ( !offset.empty() )
|
||
{
|
||
appendValueAttribute(&m_shadow, L"offset", offset.c_str());
|
||
}
|
||
|
||
std::wstring offset2;
|
||
|
||
if ( SecondShadowOffsetX != 0 )
|
||
{
|
||
offset2 += FormatUtils::DoubleToWideString( SecondShadowOffsetX.ToPoints() );
|
||
offset2 += L"pt";
|
||
}
|
||
|
||
if ( SecondShadowOffsetY != 0 )
|
||
{
|
||
offset2 += L",";
|
||
offset2 += FormatUtils::DoubleToWideString(SecondShadowOffsetY.ToPoints());
|
||
offset2 += L"pt";
|
||
}
|
||
|
||
if (!offset2.empty())
|
||
{
|
||
appendValueAttribute(&m_shadow, L"offset2", offset2.c_str());
|
||
}
|
||
|
||
//build shadow origin
|
||
if ( ( ShadowOriginX != 0 ) && ( ShadowOriginY != 0 ) )
|
||
{
|
||
appendValueAttribute(&m_shadow, L"origin", (FormatUtils::DoubleToWideString(shadowOriginX) + std::wstring(L"," ) + FormatUtils::DoubleToWideString(shadowOriginY)).c_str());
|
||
}
|
||
|
||
// write shadow
|
||
if (m_shadow.GetAttributeCount() > 0)
|
||
{
|
||
if (shadowBoolean.fShadow)
|
||
{
|
||
appendValueAttribute(&m_shadow, L"on", L"t" );
|
||
}
|
||
|
||
m_pXmlWriter->WriteString(m_shadow.GetXMLString().c_str());
|
||
}
|
||
//write 3d style
|
||
if (m_3dstyle.GetAttributeCount() > 0)
|
||
{
|
||
appendValueAttribute(&m_3dstyle, L"v:ext", L"view" );
|
||
appendValueAttribute(&m_3dstyle, L"on", L"t" );
|
||
|
||
//write the viewpoint
|
||
if ( ( ViewPointX != 0 ) || ( ViewPointY != 0 ) || ( ViewPointZ != 0 ) )
|
||
{
|
||
std::wstring viewPoint;
|
||
|
||
if ( ViewPointX != 0 )
|
||
{
|
||
viewPoint += FormatUtils::IntToWideString( ViewPointX ) + L"pt";
|
||
}
|
||
viewPoint += L",";
|
||
if ( ViewPointY != 0 )
|
||
{
|
||
viewPoint += FormatUtils::IntToWideString( ViewPointY ) + L"pt";
|
||
}
|
||
viewPoint += L",";
|
||
if ( ViewPointZ != 0 )
|
||
{
|
||
viewPoint += FormatUtils::IntToWideString( ViewPointZ ) + L"pt";
|
||
}
|
||
|
||
appendValueAttribute(&m_3dstyle, L"viewpoint", viewPoint.c_str());
|
||
}
|
||
// write the viewpointorigin
|
||
if ( ( viewPointOriginX != 0 ) || ( viewPointOriginY != 0 ) )
|
||
{
|
||
std::wstring viewPointOrigin;
|
||
|
||
if ( viewPointOriginX != 0 )
|
||
{
|
||
viewPointOrigin += FormatUtils::DoubleToFormattedWideString( viewPointOriginX, L"%.2f" );
|
||
}
|
||
|
||
if ( viewPointOriginY != 0 )
|
||
{
|
||
viewPointOrigin += L",";
|
||
viewPointOrigin += FormatUtils::DoubleToFormattedWideString( viewPointOriginY, L"%.2f" );
|
||
}
|
||
|
||
appendValueAttribute(&m_3dstyle, L"viewpointorigin", viewPointOrigin.c_str());
|
||
}
|
||
|
||
m_pXmlWriter->WriteString(m_3dstyle.GetXMLString().c_str());
|
||
}
|
||
// 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.c_str() );
|
||
m_pXmlWriter->WriteNodeEnd ( L"w10:wrap", true );
|
||
}
|
||
}
|
||
// write fill
|
||
if (m_fill.GetAttributeCount())
|
||
{
|
||
m_pXmlWriter->WriteString(m_fill.GetXMLString().c_str());
|
||
}
|
||
// write imagedata
|
||
if (m_imagedata.GetAttributeCount())
|
||
{
|
||
m_pXmlWriter->WriteString(m_imagedata.GetXMLString().c_str());
|
||
}
|
||
|
||
if ( pShape->fBackground )
|
||
{
|
||
WriteEndShapeNode(pShape);
|
||
return;
|
||
}
|
||
// write stroke
|
||
if (m_stroke.GetAttributeCount())
|
||
{
|
||
m_pXmlWriter->WriteString(m_stroke.GetXMLString().c_str());
|
||
}
|
||
// text path
|
||
if (m_textpath.GetAttributeCount())
|
||
{
|
||
appendValueAttribute(&m_textpath, L"style", FormatUtils::XmlEncode(m_textPathStyle).c_str());
|
||
m_pXmlWriter->WriteString(m_textpath.GetXMLString().c_str());
|
||
}
|
||
if (freeform)
|
||
{
|
||
if (arrInscribe.size())
|
||
{
|
||
m_pXmlWriter->WriteNodeBegin(L"v:path", true);
|
||
m_pXmlWriter->WriteAttribute(L"textboxrect", arrInscribe[0]);
|
||
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->GetIndex();
|
||
if (nIndex)
|
||
{
|
||
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 )
|
||
{
|
||
//Open Office textbox
|
||
|
||
//Open Office doesn't append a OfficeArtClientTextbox record to the container.
|
||
//We don't know how Word gets the relation to the text, but we assume that the first textbox in the document
|
||
//get the index 0, the second textbox gets the index 1 (and so on).
|
||
|
||
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;
|
||
|
||
m_context->_doc->Convert(&textboxMapping);
|
||
|
||
m_pXmlWriter->WriteString(textboxMapping.getOLEObject());
|
||
}
|
||
|
||
//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 += FormatUtils::IntToWideString(pShape->GetShapeID());
|
||
}
|
||
|
||
return strXmlAttr;
|
||
}
|
||
|
||
std::wstring VMLShapeMapping::GetLineFrom(const ChildAnchor* pAnchor) const
|
||
{
|
||
//Если линия находится в группе, то координаты должны быть в Twips
|
||
//Если линия находится в группе, то координаты должны быть в других единицах измерения (например в twips)
|
||
|
||
std::wstring strXmlFrom;
|
||
|
||
if (NULL != pAnchor)
|
||
{
|
||
strXmlFrom += FormatUtils::IntToWideString(pAnchor->rcgBounds.topLeftAngle.x);
|
||
strXmlFrom += L",";
|
||
strXmlFrom += FormatUtils::IntToWideString(pAnchor->rcgBounds.topLeftAngle.y);
|
||
}
|
||
else if (m_pSpa)
|
||
{
|
||
TwipsValue oLeft(m_pSpa->xaLeft);
|
||
TwipsValue oTop(m_pSpa->yaTop);
|
||
|
||
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) const
|
||
{
|
||
//Если линия находится в группе, то координаты должны быть в других единицах измерения (например в twips)
|
||
|
||
std::wstring strXmlTo;
|
||
|
||
if (NULL != pAnchor)
|
||
{
|
||
strXmlTo += FormatUtils::IntToWideString(pAnchor->rcgBounds.topLeftAngle.x + pAnchor->rcgBounds.size.cx);
|
||
strXmlTo += L",";
|
||
strXmlTo += FormatUtils::IntToWideString(pAnchor->rcgBounds.topLeftAngle.y + pAnchor->rcgBounds.size.cy);
|
||
}
|
||
else if (m_pSpa)
|
||
{
|
||
TwipsValue oRight (m_pSpa->xaRight);
|
||
TwipsValue oBottom (m_pSpa->yaBottom);
|
||
|
||
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 OptionEntry& pWrapPolygonVertices) const
|
||
{
|
||
std::wstring coords;
|
||
|
||
MemoryStream oStream(pWrapPolygonVertices.opComplex, pWrapPolygonVertices.op);
|
||
std::list<int> arrVertices;
|
||
|
||
unsigned short nElems = oStream.ReadUInt16();
|
||
unsigned short nElemsAlloc = oStream.ReadUInt16();
|
||
unsigned short cbElem = oStream.ReadUInt16();
|
||
|
||
if ( ( nElems > 0 ) && ( cbElem > 0 ) && ( nElems <= nElemsAlloc ) )
|
||
{
|
||
//!!!TODO: read the Int32 coordinates!!!
|
||
while (oStream.GetPosition() < oStream.GetSize())
|
||
{
|
||
arrVertices.push_back(oStream.ReadInt32());
|
||
}
|
||
|
||
std::list<int>::const_iterator end = arrVertices.end();
|
||
for (std::list<int>::const_iterator iter = arrVertices.begin(); iter != end; ++iter)
|
||
{
|
||
coords += FormatUtils::IntToWideString(*iter);
|
||
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(const BlipStoreEntry* oBlip)
|
||
{
|
||
bool result = false;
|
||
|
||
//write the blip
|
||
if (oBlip)
|
||
{
|
||
VirtualStreamReader reader(m_context->_doc->WordDocumentStream, oBlip->foDelay, m_context->_doc->FIB->m_bOlderVersion);
|
||
|
||
switch (oBlip->btWin32)
|
||
{
|
||
case Global::msoblipEMF:
|
||
case Global::msoblipWMF:
|
||
{
|
||
//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;
|
||
int decompressedSize = 0;
|
||
|
||
decompressedSize = metaBlip->Decompress(&decompressed);
|
||
if (0 != decompressedSize && NULL != decompressed)
|
||
{
|
||
m_context->_docx->ImagesList.push_back(ImageFileStructure(GetTargetExt(oBlip->btWin32), std::vector<unsigned char>(decompressed, (decompressed + decompressedSize))));
|
||
RELEASEARRAYOBJECTS(decompressed);
|
||
}
|
||
|
||
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))
|
||
{
|
||
m_context->_docx->ImagesList.push_back(ImageFileStructure(GetTargetExt(oBlip->btWin32),
|
||
std::vector<unsigned char>(bitBlip->m_pvBits, (bitBlip->m_pvBits + bitBlip->pvBitsSize)), oBlip->btWin32));
|
||
RELEASEOBJECT (bitBlip);
|
||
}
|
||
}
|
||
break;
|
||
|
||
default:
|
||
{
|
||
result = false;
|
||
return result;
|
||
}
|
||
break;
|
||
}
|
||
|
||
m_nImageId = m_context->_docx->RegisterImage (m_pCaller, oBlip->btWin32);
|
||
|
||
result = true;
|
||
}
|
||
|
||
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" );
|
||
|
||
default:
|
||
return std::wstring( L".png" );
|
||
}
|
||
}
|
||
|
||
void VMLShapeMapping::AppendDimensionToStyle(std::wstring* style, const PictureDescriptor* pict, bool twistDimensions) const
|
||
{
|
||
if ( ( style != NULL ) && ( 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->operator += ( std::wstring( L"width:" ) + widthString + std::wstring( L"pt;" ) );
|
||
style->operator += ( std::wstring( L"height:" ) + heightString + std::wstring( L"pt;" ) );
|
||
}
|
||
}
|
||
|
||
void VMLShapeMapping::AppendDimensionToStyle(std::wstring* style, const Spa* pSpa, bool twistDimensions) const
|
||
{
|
||
if ( ( style != NULL ) && (pSpa != NULL ) )
|
||
{
|
||
//append size and position ...
|
||
|
||
//if (pSpa->fAnchorLock )
|
||
//if (pSpa->bx == TEXT && pSpa->by == TEXT)
|
||
//{
|
||
// appendStyleProperty( style, L"position", L"static" );
|
||
//}
|
||
//else
|
||
//{
|
||
appendStyleProperty( 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 ((style != NULL) && (anchor != NULL))
|
||
{
|
||
DocFormatUtils::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));
|
||
}
|
||
|
||
appendStyleProperty(style, L"position", L"absolute");
|
||
appendStyleProperty(style, L"left", FormatUtils::IntToWideString(bounds.topLeftAngle.x));
|
||
appendStyleProperty(style, L"top", FormatUtils::IntToWideString(bounds.topLeftAngle.y));
|
||
|
||
if (twistDimensions)
|
||
{
|
||
appendStyleProperty(style, L"width", FormatUtils::IntToWideString(bounds.size.cy));
|
||
appendStyleProperty(style, L"height", FormatUtils::IntToWideString(bounds.size.cx));
|
||
}
|
||
else
|
||
{
|
||
appendStyleProperty(style, L"width", FormatUtils::IntToWideString(bounds.size.cx));
|
||
appendStyleProperty(style, L"height", FormatUtils::IntToWideString(bounds.size.cy));
|
||
}
|
||
}
|
||
}
|
||
|
||
void VMLShapeMapping::appendStyleProperty(std::wstring* b, const std::wstring& propName, const std::wstring& propValue) const
|
||
{
|
||
if ( b != NULL )
|
||
{
|
||
b->operator += ( propName );
|
||
b->operator += ( L":" );
|
||
b->operator += ( propValue );
|
||
b->operator +=( L";" );
|
||
}
|
||
}
|
||
|
||
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";
|
||
case msoprhPage: return L"page";
|
||
case msoprhText: return L"text";
|
||
case msoprhChar: return L"char";
|
||
default:
|
||
return L"margin";
|
||
}
|
||
}
|
||
|
||
void VMLShapeMapping::AppendOptionsToStyle (std::wstring* oStyle, const std::list<OptionEntry>& options, int zIndex) const
|
||
{
|
||
bool bRelH = false;
|
||
bool bRelV = false;
|
||
|
||
bool bPosH = false;
|
||
bool bPosV = false;
|
||
|
||
bool bZIndex = false;
|
||
|
||
std::list<OptionEntry>::const_iterator end = options.end();
|
||
for (std::list<OptionEntry>::const_iterator iter = options.begin(); iter != end; ++iter)
|
||
{
|
||
switch (iter->pid)
|
||
{
|
||
// POSITIONING
|
||
case posh:
|
||
{
|
||
appendStyleProperty(oStyle, L"mso-position-horizontal", mapHorizontalPosition((PositionHorizontal)iter->op));
|
||
bPosH = true;
|
||
}break;
|
||
case posrelh:
|
||
{
|
||
appendStyleProperty(oStyle, L"mso-position-horizontal-relative", mapHorizontalPositionRelative((PositionHorizontalRelative)iter->op));
|
||
bRelH = true;
|
||
}break;
|
||
case posv:
|
||
{
|
||
appendStyleProperty(oStyle, L"mso-position-vertical", mapVerticalPosition((PositionVertical)iter->op));
|
||
bPosV = true;
|
||
}break;
|
||
case posrelv:
|
||
{
|
||
appendStyleProperty(oStyle, L"mso-position-vertical-relative", mapVerticalPositionRelative((PositionVerticalRelative)iter->op));
|
||
bRelV = true;
|
||
}break;
|
||
// BOOLEANS
|
||
case groupShapeBooleans:
|
||
{
|
||
GroupShapeBooleanProperties groupShapeBooleans(iter->op);
|
||
|
||
if (groupShapeBooleans.fUsefBehindDocument && groupShapeBooleans.fBehindDocument && !bZIndex)
|
||
{
|
||
//The shape is behind the text, so the z-index must be negative.
|
||
appendStyleProperty(oStyle, L"z-index", L"-1" );
|
||
bZIndex = true;
|
||
}
|
||
else if (!m_isInlineShape && !bZIndex)
|
||
{
|
||
appendStyleProperty( oStyle, L"z-index", FormatUtils::IntToWideString(zIndex + 0x7ffff));
|
||
bZIndex = true;
|
||
}
|
||
|
||
if (groupShapeBooleans.fHidden && groupShapeBooleans.fUsefHidden)
|
||
{
|
||
appendStyleProperty(oStyle, L"visibility", L"hidden" );
|
||
}
|
||
}break;
|
||
// GEOMETRY
|
||
case PropertyId_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 anchorText:
|
||
{
|
||
appendStyleProperty(oStyle, L"v-text-anchor", getTextboxAnchor(iter->op));
|
||
}break;
|
||
// WRAP DISTANCE
|
||
case dxWrapDistLeft:
|
||
{
|
||
appendStyleProperty(oStyle, L"mso-wrap-distance-left", (FormatUtils::DoubleToWideString(EmuValue((int)iter->op).ToPoints()) + std::wstring(L"pt")));
|
||
}break;
|
||
case dxWrapDistRight:
|
||
{
|
||
appendStyleProperty(oStyle, L"mso-wrap-distance-right", (FormatUtils::DoubleToWideString(EmuValue((int)iter->op).ToPoints()) + std::wstring(L"pt")));
|
||
}break;
|
||
case dyWrapDistBottom:
|
||
{
|
||
appendStyleProperty(oStyle, L"mso-wrap-distance-bottom", (FormatUtils::DoubleToWideString(EmuValue((int)iter->op).ToPoints()) + std::wstring(L"pt")));
|
||
}break;
|
||
case dyWrapDistTop:
|
||
{
|
||
appendStyleProperty(oStyle, L"mso-wrap-distance-top", (FormatUtils::DoubleToWideString(EmuValue((int)iter->op).ToPoints()) + std::wstring(L"pt")));
|
||
}break;
|
||
}
|
||
}
|
||
|
||
if (!bRelH && m_pSpa)
|
||
{
|
||
appendStyleProperty(oStyle, L"mso-position-horizontal-relative", mapHorizontalPositionRelative(m_pSpa->bx));
|
||
}
|
||
if (!bRelV && m_pSpa)
|
||
{
|
||
appendStyleProperty(oStyle, L"mso-position-vertical-relative", mapVerticalPositionRelative(m_pSpa->bx));
|
||
}
|
||
if (!m_isInlineShape && !bZIndex)
|
||
{
|
||
appendStyleProperty( oStyle, L"z-index", FormatUtils::IntToWideString(zIndex + 0x7ffff));
|
||
bZIndex = true;
|
||
}
|
||
|
||
//if (!bPosH)
|
||
//{
|
||
// appendStyleProperty(oStyle, L"mso-position-horizontal", L"absolute" );
|
||
//}
|
||
//if (!bPosV)
|
||
//{
|
||
// appendStyleProperty(oStyle, L"mso-position-vertical", L"absolute" );
|
||
//}
|
||
}
|
||
|
||
//
|
||
std::wstring VMLShapeMapping::buildStyle (const Shape* shape, const ChildAnchor* anchor, const std::list<OptionEntry>& options, int zIndex) const
|
||
{
|
||
std::wstring style;
|
||
|
||
// Check if some properties are set that cause the dimensions to be twisted
|
||
bool twistDimensions = false;
|
||
std::list<OptionEntry>::const_iterator end = options.end();
|
||
for (std::list<OptionEntry>::const_iterator iter = options.begin(); iter != end; ++iter)
|
||
{
|
||
if (geometryTextBooleanProperties == iter->pid)
|
||
{
|
||
GeometryTextBooleanProperties props(iter->op);
|
||
|
||
if (props.fUsegtextFVertical && props.gtextFVertical)
|
||
{
|
||
twistDimensions = true;
|
||
}
|
||
}
|
||
|
||
if (PropertyId_rotation == iter->pid)
|
||
{
|
||
double dAngle = (double)((int)iter->op) / 65535.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;
|
||
}
|
||
}
|
||
|
||
//don't append the dimension info to lines,
|
||
// because they have "from" and "to" attributes to decline the dimension
|
||
if(!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 )
|
||
{
|
||
appendStyleProperty( &style, L"position", L"absolute" );
|
||
}
|
||
else if (m_pSpa)
|
||
{
|
||
//append size and position ...
|
||
//if (m_pSpa->fAnchorLock)//это возможность смены привязки , а не ее тип
|
||
|
||
//if (m_pSpa->bx == TEXT && m_pSpa->by == TEXT)
|
||
//{
|
||
// appendStyleProperty( &style, L"position", L"static" );
|
||
//}
|
||
//else
|
||
{
|
||
appendStyleProperty( &style, L"position", L"absolute" );
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( shape->fFlipH )
|
||
{
|
||
appendStyleProperty( &style, L"flip", L"x" );
|
||
}
|
||
|
||
if ( shape->fFlipV )
|
||
{
|
||
appendStyleProperty( &style, L"flip", L"y" );
|
||
}
|
||
|
||
AppendOptionsToStyle( &style, options, zIndex );
|
||
|
||
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 )
|
||
{
|
||
default: return L"none";
|
||
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";
|
||
}
|
||
}
|
||
|
||
std::wstring VMLShapeMapping::getArrowLength(unsigned int op) const
|
||
{
|
||
switch ( op )
|
||
{
|
||
default: return L"short";
|
||
case 1: return L"medium";
|
||
case 2: return L"long";
|
||
}
|
||
}
|
||
|
||
std::wstring VMLShapeMapping::getArrowWidth(unsigned int op) const
|
||
{
|
||
switch ( op )
|
||
{
|
||
default: return L"narrow";
|
||
case 1: return L"medium";
|
||
case 2: return L"wide";
|
||
}
|
||
}
|
||
|
||
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 unsigned char* p, unsigned int size) const
|
||
{
|
||
std::wstring result;
|
||
|
||
if ( ( p != NULL ) && ( size > 0 ) )
|
||
{
|
||
// parse the IMsoArray
|
||
unsigned short nElems = FormatUtils::BytesToUInt16(p, 0, size);
|
||
unsigned short nElemsAlloc = FormatUtils::BytesToUInt16(p, 2, size);
|
||
unsigned short cb = FormatUtils::BytesToUInt16(p, 4, size);
|
||
|
||
for ( unsigned short i = 0; i < nElems; i++ )
|
||
{
|
||
int pos = ( 6 + ( i * cb ) );
|
||
|
||
RGBColor color(FormatUtils::BytesToInt32(p, pos, size ), RedFirst);
|
||
int colorPos = FormatUtils::BytesToInt32(p, ( pos + 4 ), size);
|
||
|
||
result += FormatUtils::IntToWideString(colorPos);
|
||
result += L"f #";
|
||
result += color.SixDigitHexCode;
|
||
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";
|
||
case 1: wrapType = L"topAndBottom";
|
||
case 3: wrapType = L"through";
|
||
case 4:
|
||
case 5: wrapType = L"tight";
|
||
default:
|
||
wrapType = L"none";
|
||
}
|
||
}
|
||
|
||
return wrapType;
|
||
}
|
||
|
||
std::wstring VMLShapeMapping::ParsePath (const std::list<OptionEntry>& options) const
|
||
{
|
||
const unsigned char* pVP = NULL;
|
||
unsigned int nVP = 0;
|
||
const unsigned char* pSI = NULL;
|
||
unsigned int nSI = 0;
|
||
|
||
std::list<OptionEntry>::const_iterator end = options.end();
|
||
for (std::list<OptionEntry>::const_iterator iter = options.begin(); iter != end; ++iter)
|
||
{
|
||
if (iter->pid == pVertices)
|
||
{
|
||
pVP = iter->opComplex;
|
||
nVP = iter->op;
|
||
}
|
||
|
||
if (iter->pid == pSegmentInfo)
|
||
{
|
||
pSI = iter->opComplex;
|
||
nSI = iter->op;
|
||
}
|
||
}
|
||
|
||
PathParser oParser (pSI, nSI, pVP, nVP);
|
||
return oParser.GetVmlPath();
|
||
}
|
||
|
||
//
|
||
std::vector<std::wstring> VMLShapeMapping::GetTextRectangles(const OptionEntry& inscribe) const
|
||
{
|
||
MemoryStream reader(inscribe.opComplex, inscribe.op + 6);
|
||
|
||
unsigned short elems = reader.ReadUInt16();
|
||
unsigned short allocElems = reader.ReadUInt16();
|
||
unsigned short cb = reader.ReadUInt16();
|
||
|
||
std::vector<std::wstring> rectangles;
|
||
|
||
if (16 != cb) return rectangles; // TODO: доделать
|
||
|
||
int count = (inscribe.op) / 16;
|
||
|
||
for (int i = 0; i < count; ++i)
|
||
{
|
||
RECT rc;
|
||
|
||
rc.top = reader.ReadInt32();
|
||
rc.left = reader.ReadInt32();
|
||
rc.right = reader.ReadInt32();
|
||
rc.bottom = reader.ReadInt32();
|
||
|
||
std::wstringstream sstream;
|
||
sstream << boost::wformat(L"%d,%d,%d,%d") % rc.top % rc.left % rc.right % rc.bottom;
|
||
rectangles.push_back(sstream.str());
|
||
}
|
||
|
||
return rectangles;
|
||
}
|
||
//------------------------------------------------------------------------------------------------------
|
||
|
||
void VMLShapeMapping::ApplyPrimitives(DrawingPrimitives * primitives)
|
||
{
|
||
int index = 0;
|
||
|
||
while(true)
|
||
{
|
||
index = ApplyPrimitive(primitives, index);
|
||
if (index > primitives->size() - 1)
|
||
break;
|
||
}
|
||
}
|
||
|
||
static int currentTextBoxIndex = 1;
|
||
|
||
int VMLShapeMapping::ApplyPrimitive(DrawingPrimitives * primitives, int index)
|
||
{
|
||
if (!primitives) return index++;
|
||
if (index >= primitives->size()) return index++;
|
||
|
||
DrawingPrimitive *primitive = dynamic_cast<DrawingPrimitive *>(primitives->at(index));
|
||
|
||
m_pXmlWriter->WriteNodeBegin(primitive->strVmlType.c_str(), 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.c_str() );
|
||
|
||
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 );
|
||
|
||
std::wstring strId = std::wstring(L"_x0000_s") + FormatUtils::IntToWideString(1024 + count_vml_objects);
|
||
|
||
count_vml_objects++;
|
||
//m_pXmlWriter->WriteAttribute ( L"id") , strId.c_str());
|
||
m_pXmlWriter->WriteAttribute ( L"o:spid", strId.c_str());
|
||
|
||
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 = FormatUtils::IntToWideString(line->xaStart + primitive->xa) + L"," + FormatUtils::IntToWideString(line->yaStart + primitive->ya);
|
||
std::wstring strEnd = FormatUtils::IntToWideString(line->xaEnd + primitive->xa) + L"," + FormatUtils::IntToWideString(line->yaEnd + primitive->ya);
|
||
|
||
m_pXmlWriter->WriteAttribute(L"from", strStart.c_str() );
|
||
m_pXmlWriter->WriteAttribute(L"to", strEnd.c_str());
|
||
}
|
||
else
|
||
{
|
||
if (root)
|
||
{
|
||
//strStyle += L"left:" + FormatUtils::IntToWideString( x.ToPoints()) + L"pt;";
|
||
//strStyle += L"top:" + FormatUtils::IntToWideString( y.ToPoints()) + L"pt;";
|
||
strStyle += L"width:" + FormatUtils::IntToWideString( w.ToPoints()) + L"pt;";
|
||
strStyle += L"height:" + FormatUtils::IntToWideString( h.ToPoints()) + L"pt;";
|
||
|
||
strStyle += L"margin-left:" + FormatUtils::IntToWideString( x.ToPoints()) + L"pt;";
|
||
strStyle += L"margin-top:" + FormatUtils::IntToWideString( y.ToPoints()) + L"pt;";
|
||
|
||
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 = FormatUtils::IntToWideString(primitive->dxa) + L"," + FormatUtils::IntToWideString(primitive->dya);
|
||
std::wstring strOrigin = FormatUtils::IntToWideString(primitive->xa) + L"," + FormatUtils::IntToWideString(primitive->ya);
|
||
|
||
m_pXmlWriter->WriteAttribute( L"coordsize", strSize.c_str());
|
||
//m_pXmlWriter->WriteAttribute( L"coordorigin"), strOrigin.c_str());
|
||
}
|
||
else
|
||
{
|
||
strStyle += L"left:" + FormatUtils::IntToWideString( primitive->xa) + L";";
|
||
strStyle += L"top:" + FormatUtils::IntToWideString( primitive->ya) + L";";
|
||
strStyle += L"width:" + FormatUtils::IntToWideString( primitive->dxa) + L";";
|
||
strStyle += L"height:" + FormatUtils::IntToWideString( 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").c_str());
|
||
}
|
||
m_pXmlWriter->WriteAttribute( L"style", strStyle.c_str());
|
||
|
||
std::wstring strStrokeWeight = FormatUtils::IntToWideString(primitive->lineWeight / 20) + L"pt";
|
||
if (primitive->lineWeight > 20)
|
||
m_pXmlWriter->WriteAttribute( L"strokeweight", strStrokeWeight.c_str());
|
||
|
||
if (primitive->type > 0)
|
||
m_pXmlWriter->WriteAttribute( L"strokecolor", FormatUtils::IntToFormattedWideString(primitive->lineColor, L"#%06x").c_str());
|
||
|
||
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").c_str());
|
||
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 = FormatUtils::IntToWideString(primitive->lineStyle) + L" 1";
|
||
m_pXmlWriter->WriteAttribute( L"dashstyle", strDashStyle.c_str());
|
||
m_pXmlWriter->WriteNodeEnd( L"", true, false );
|
||
m_pXmlWriter->WriteNodeEnd( L"v:stroke" );
|
||
}
|
||
}
|
||
|
||
}
|