1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 #include "xmloff/MarkerStyle.hxx"
31 #include "xexptran.hxx"
32 #include <xmloff/attrlist.hxx>
33 #include <xmloff/nmspmap.hxx>
34 #include <xmloff/xmluconv.hxx>
35 #include "xmloff/xmlnmspe.hxx"
36 #include <xmloff/xmltoken.hxx>
37 #include <xmloff/xmlexp.hxx>
38 #include <xmloff/xmlimp.hxx>
39 #include <rtl/ustrbuf.hxx>
40 #include <rtl/ustring.hxx>
41 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
42 
43 using namespace ::com::sun::star;
44 using ::rtl::OUString;
45 using ::rtl::OUStringBuffer;
46 
47 using namespace ::xmloff::token;
48 
49 
50 //-------------------------------------------------------------
51 // Import
52 //-------------------------------------------------------------
53 
54 XMLMarkerStyleImport::XMLMarkerStyleImport( SvXMLImport& rImp )
55     : rImport( rImp )
56 {
57 }
58 
59 XMLMarkerStyleImport::~XMLMarkerStyleImport()
60 {
61 }
62 
63 sal_Bool XMLMarkerStyleImport::importXML(
64     const uno::Reference< xml::sax::XAttributeList >& xAttrList,
65     uno::Any& rValue,
66     OUString& rStrName )
67 {
68 	sal_Bool bHasViewBox    = sal_False;
69 	sal_Bool bHasPathData   = sal_False;
70 	OUString aDisplayName;
71 
72 	SdXMLImExViewBox* pViewBox = NULL;
73 
74     SvXMLNamespaceMap& rNamespaceMap = rImport.GetNamespaceMap();
75     SvXMLUnitConverter& rUnitConverter = rImport.GetMM100UnitConverter();
76 
77 	OUString strPathData;
78 
79 	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
80 	for( sal_Int16 i = 0; i < nAttrCount; i++ )
81 	{
82 		OUString aStrFullAttrName = xAttrList->getNameByIndex( i );
83 		OUString aStrAttrName;
84 		rNamespaceMap.GetKeyByAttrName( aStrFullAttrName, &aStrAttrName );
85 		OUString aStrValue = xAttrList->getValueByIndex( i );
86 
87 		if( IsXMLToken( aStrAttrName, XML_NAME ) )
88 		{
89 			rStrName = aStrValue;
90 		}
91 		else if( IsXMLToken( aStrAttrName, XML_DISPLAY_NAME ) )
92 		{
93 			aDisplayName = aStrValue;
94 		}
95 		else if( IsXMLToken( aStrAttrName, XML_VIEWBOX ) )
96 		{
97 			pViewBox = new SdXMLImExViewBox( aStrValue, rUnitConverter );
98 			bHasViewBox = sal_True;
99 
100 		}
101 		else if( IsXMLToken( aStrAttrName, XML_D ) )
102 		{
103 			strPathData = aStrValue;
104 			bHasPathData = sal_True;
105 		}
106 	}
107 
108 	if( bHasViewBox && bHasPathData )
109 	{
110 		SdXMLImExSvgDElement aPoints(strPathData, *pViewBox, awt::Point( 0, 0 ),
111 			awt::Size( pViewBox->GetWidth(), pViewBox->GetHeight() ),
112 			rUnitConverter );
113 
114 		if(aPoints.IsCurve())
115 		{
116 			drawing::PolyPolygonBezierCoords aSourcePolyPolygon(
117 				aPoints.GetPointSequenceSequence(),
118 				aPoints.GetFlagSequenceSequence());
119 			rValue <<= aSourcePolyPolygon;
120 		}
121 		else
122 		{
123 			drawing::PolyPolygonBezierCoords aSourcePolyPolygon;
124 			aSourcePolyPolygon.Coordinates = aPoints.GetPointSequenceSequence();
125 			aSourcePolyPolygon.Flags.realloc(aSourcePolyPolygon.Coordinates.getLength());
126 
127 			// Zeiger auf innere sequences holen
128 			const drawing::PointSequence* pInnerSequence = aSourcePolyPolygon.Coordinates.getConstArray();
129 			drawing::FlagSequence* pInnerSequenceFlags = aSourcePolyPolygon.Flags.getArray();
130 
131 			for(sal_Int32 a(0); a < aSourcePolyPolygon.Coordinates.getLength(); a++)
132 			{
133 				pInnerSequenceFlags->realloc(pInnerSequence->getLength());
134 				drawing::PolygonFlags* pPolyFlags = pInnerSequenceFlags->getArray();
135 
136 				for(sal_Int32 b(0); b < pInnerSequence->getLength(); b++)
137 					*pPolyFlags++ = drawing::PolygonFlags_NORMAL;
138 
139 				// next run
140 				pInnerSequence++;
141 				pInnerSequenceFlags++;
142 			}
143 
144 			rValue <<= aSourcePolyPolygon;
145 		}
146 
147 		if( aDisplayName.getLength() )
148 		{
149 			rImport.AddStyleDisplayName( XML_STYLE_FAMILY_SD_MARKER_ID, rStrName,
150 										aDisplayName );
151 			rStrName = aDisplayName;
152 		}
153 
154 	}
155 
156 	if( pViewBox )
157 		delete pViewBox;
158 
159 	return bHasViewBox && bHasPathData;
160 }
161 
162 
163 //-------------------------------------------------------------
164 // Export
165 //-------------------------------------------------------------
166 
167 #ifndef SVX_LIGHT
168 
169 XMLMarkerStyleExport::XMLMarkerStyleExport( SvXMLExport& rExp )
170     : rExport( rExp )
171 {
172 }
173 
174 XMLMarkerStyleExport::~XMLMarkerStyleExport()
175 {
176 }
177 
178 sal_Bool XMLMarkerStyleExport::exportXML(
179     const OUString& rStrName,
180     const uno::Any& rValue )
181 {
182 	sal_Bool bRet(sal_False);
183 
184 	if(rStrName.getLength())
185 	{
186 		drawing::PolyPolygonBezierCoords aBezier;
187 
188 		if(rValue >>= aBezier)
189 		{
190 			OUString aStrValue;
191 			OUStringBuffer aOut;
192 
193 			/////////////////
194 			// Name
195 			sal_Bool bEncoded = sal_False;
196 			OUString aStrName( rStrName );
197 			rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
198 								  rExport.EncodeStyleName( aStrName,
199 														   &bEncoded ) );
200 			if( bEncoded )
201 				rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DISPLAY_NAME,
202 									  aStrName );
203 
204 			/////////////////
205 			// Viewbox (viewBox="0 0 1500 1000")
206 			sal_Int32 nMinX(0x7fffffff);
207 			sal_Int32 nMaxX(0x80000000);
208 			sal_Int32 nMinY(0x7fffffff);
209 			sal_Int32 nMaxY(0x80000000);
210 			sal_Int32 nOuterCnt(aBezier.Coordinates.getLength());
211 			drawing::PointSequence* pOuterSequence = aBezier.Coordinates.getArray();
212 			sal_Int32 a, b;
213 			sal_Bool bClosed(sal_False);
214 
215             for (a = 0; a < nOuterCnt; a++)
216 			{
217 				drawing::PointSequence* pSequence = pOuterSequence++;
218 				const awt::Point *pPoints = pSequence->getConstArray();
219 				sal_Int32 nPointCount(pSequence->getLength());
220 
221 				if(nPointCount)
222 				{
223 					const awt::Point aStart = pPoints[0];
224 					const awt::Point aEnd = pPoints[nPointCount - 1];
225 
226 					if(aStart.X == aEnd.X && aStart.Y == aEnd.Y)
227 					{
228 						bClosed = sal_True;
229 					}
230 				}
231 
232                 for (b = 0; b < nPointCount; b++)
233 				{
234 					const awt::Point aPoint = pPoints[b];
235 
236 					if( aPoint.X < nMinX )
237 						nMinX = aPoint.X;
238 
239 					if( aPoint.X > nMaxX )
240 						nMaxX = aPoint.X;
241 
242 					if( aPoint.Y < nMinY )
243 						nMinY = aPoint.Y;
244 
245 					if( aPoint.Y > nMaxY )
246 						nMaxY = aPoint.Y;
247 				}
248 			}
249 
250 			sal_Int32 nDifX(nMaxX - nMinX);
251 			sal_Int32 nDifY(nMaxY - nMinY);
252 
253 			SdXMLImExViewBox aViewBox( 0, 0, nDifX, nDifY );
254 			rExport.AddAttribute( XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString() );
255 
256 			/////////////////
257 			// Pathdata
258 			pOuterSequence = aBezier.Coordinates.getArray();
259 			drawing::FlagSequence*  pOuterFlags = aBezier.Flags.getArray();
260 			SdXMLImExSvgDElement aSvgDElement(aViewBox);
261 
262             for (a = 0; a < nOuterCnt; a++)
263 			{
264 				drawing::PointSequence* pSequence = pOuterSequence++;
265 				drawing::FlagSequence* pFlags = pOuterFlags++;
266 
267 				aSvgDElement.AddPolygon(pSequence, pFlags,
268 					awt::Point( 0, 0 ),
269 					awt::Size( aViewBox.GetWidth(), aViewBox.GetHeight() ),
270 					bClosed);
271 			}
272 
273 			// write point array
274 			rExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aSvgDElement.GetExportString());
275 
276 			/////////////////
277 			// Do Write
278             SvXMLElementExport rElem( rExport, XML_NAMESPACE_DRAW, XML_MARKER,
279                                       sal_True, sal_False );
280 		}
281 	}
282 
283 	return bRet;
284 }
285 
286 #endif // #ifndef SVX_LIGHT
287