/* * (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(); } } } if (recBs) { m_pBlipStore = static_cast(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(visited); if ( primitives ) return ApplyPrimitives(primitives); //---------------------------------------------------------------------------------------------- ShapeContainer* pContainer = dynamic_cast(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(pContainer->_ParentRecord)); } } } } /// Converts a group of shapes void VMLShapeMapping::WriteGroup (const GroupContainer* container) { if ((container != NULL) && (!container->Children.empty())) { ShapeContainer* groupShape = static_cast(container->Children[0]); GroupShapeRecord* gsr = static_cast(groupShape->Children[0]); Shape* shape = static_cast(groupShape->Children[1]); ChildAnchor* anchor = groupShape->FirstChildWithType(); std::vector 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(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(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(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(pContainer->Children[0]); if (!pShape) return; int indexOLE = -1; bool freeform = true; std::wstring sShapeId; std::vector options = pContainer->ExtractOptions(); ChildAnchor* pAnchor = pContainer->FirstChildWithType(); ClientAnchor* clientAnchor = pContainer->FirstChildWithType(); 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()) { //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 ShadowOffsetX; boost::optional ShadowOffsetY; boost::optional SecondShadowOffsetX; boost::optional SecondShadowOffsetY; boost::optional ViewPointX; boost::optional ViewPointY; boost::optional ViewPointZ; boost::optional viewPointOriginX; boost::optional viewPointOriginY; boost::optional ShadowOriginX; boost::optional ShadowOriginY; boost::optional xCoord; boost::optional yCoord; boost::optional xCoord2; boost::optional yCoord2; boost::optional 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 fill_left; boost::optional fill_top; boost::optional fill_right; boost::optional 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(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(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(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(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(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(iter.get()); if (point) fill_left = point->dVal; }break; case ODRAW::fillToTop: { ODRAW::FixedPoint* point = dynamic_cast(iter.get()); if (point) fill_top = point->dVal; }break; case ODRAW::fillToRight: { ODRAW::FixedPoint* point = dynamic_cast(iter.get()); if (point) fill_right = point->dVal; }break; case ODRAW::fillToBottom: { ODRAW::FixedPoint* point = dynamic_cast(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(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(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(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(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(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(iter.get()); }break; case ODRAW::threeDObjectBooleanProperties: { ODRAW::ThreeDObjectBooleanProperties* booleans = dynamic_cast(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(iter.get()); if (point) appendValueAttribute(&m_3dstyle, L"skewangle", FormatUtils::DoubleToWideString(point->dVal)); }break; case ODRAW::c3DXViewpoint: { ODRAW::FixedPoint* point = dynamic_cast(iter.get()); if (point) ViewPointX = EmuValue((int)point->dVal); }break; case ODRAW::c3DYViewpoint: { ODRAW::FixedPoint* point = dynamic_cast(iter.get()); if (point) ViewPointY = EmuValue((int)point->dVal); }break; case ODRAW::c3DZViewpoint: { ODRAW::FixedPoint* point = dynamic_cast(iter.get()); if (point) ViewPointZ = EmuValue((int)point->dVal); }break; case ODRAW::c3DOriginX: { ODRAW::FixedPoint* point = dynamic_cast(iter.get()); if (point) viewPointOriginX = point->dVal; }break; case ODRAW::c3DOriginY: { ODRAW::FixedPoint* point = dynamic_cast(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(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(iter.get()); if ((str) && (!str->string_.empty())) { appendValueAttribute(&m_textpath, L"string", str->string_); } }break; case ODRAW::gtextFont: { ODRAW::AnyString* str = dynamic_cast(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(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(opVerticles.get()); ODRAW::PSegmentInfo* pSI = dynamic_cast(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 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(); 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()) { m_pXmlWriter->WriteNodeBegin( L"v:oval", true ); } else if (pShape->is()) { m_pXmlWriter->WriteNodeBegin( L"v:roundrect", true ); } else if (pShape->is()) { m_pXmlWriter->WriteNodeBegin( L"v:rect", true ); } else if (pShape->is()) { 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()) { m_pXmlWriter->WriteNodeEnd( L"v:oval" ); } else if (pShape->is()) { m_pXmlWriter->WriteNodeEnd( L"v:roundrect" ); } else if (pShape->is()) { m_pXmlWriter->WriteNodeEnd( L"v:rect" ); } else if (pShape->is()) { 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(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(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 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(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(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(((anchor->Right + anchor->Left) * 0.5 - (anchor->Bottom - anchor->Top) * 0.5)); bounds.topLeftAngle.y = static_cast(((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& 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(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& 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(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()) { 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(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(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(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(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 VMLShapeMapping::GetTextRectangles( const ODRAW::OfficeArtFOPTEPtr& pOpt ) const { std::vector rectangles; ODRAW::PInscribe* pInscribe = dynamic_cast(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(primitives->at(index)); m_pXmlWriter->WriteNodeBegin(primitive->strVmlType, true ); if (primitive->type == 0x0007) { DrawingPrimitiveCTextBox * callout = dynamic_cast(primitive); if ((callout) && (callout->txbx)) { //временно обычный текстбокс callout->txbx->xa += callout->xa; callout->txbx->ya += callout->ya; WritePrimitiveProps(dynamic_cast(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(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(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" ); } } }