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