xref: /trunk/main/xmloff/source/style/bordrhdl.cxx (revision 63bba73c)
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 
27 
28 #include <bordrhdl.hxx>
29 #include <xmloff/xmltoken.hxx>
30 #include <xmloff/xmluconv.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <com/sun/star/uno/Any.hxx>
33 #include <com/sun/star/table/BorderLine.hpp>
34 
35 using ::rtl::OUString;
36 using ::rtl::OUStringBuffer;
37 
38 using namespace ::com::sun::star;
39 using namespace ::xmloff::token;
40 
41 // copied from svx/boxitem.hxx
42 #define DEF_LINE_WIDTH_0        1
43 #define DEF_LINE_WIDTH_1        35
44 #define DEF_LINE_WIDTH_2        88
45 #define DEF_LINE_WIDTH_3        141
46 #define DEF_LINE_WIDTH_4        176
47 
48 #define DEF_MAX_LINE_WIDHT      DEF_LINE_WIDTH_4
49 #define DEF_MAX_LINE_DIST       DEF_LINE_WIDTH_2
50 
51 #define DEF_DOUBLE_LINE0_OUT    DEF_LINE_WIDTH_0
52 #define DEF_DOUBLE_LINE0_IN     DEF_LINE_WIDTH_0
53 #define DEF_DOUBLE_LINE0_DIST   DEF_LINE_WIDTH_1
54 
55 #define DEF_DOUBLE_LINE1_OUT    DEF_LINE_WIDTH_1
56 #define DEF_DOUBLE_LINE1_IN     DEF_LINE_WIDTH_1
57 #define DEF_DOUBLE_LINE1_DIST   DEF_LINE_WIDTH_1
58 
59 #define DEF_DOUBLE_LINE2_OUT    DEF_LINE_WIDTH_2
60 #define DEF_DOUBLE_LINE2_IN     DEF_LINE_WIDTH_2
61 #define DEF_DOUBLE_LINE2_DIST   DEF_LINE_WIDTH_2
62 
63 #define DEF_DOUBLE_LINE3_OUT    DEF_LINE_WIDTH_2
64 #define DEF_DOUBLE_LINE3_IN     DEF_LINE_WIDTH_1
65 #define DEF_DOUBLE_LINE3_DIST   DEF_LINE_WIDTH_2
66 
67 #define DEF_DOUBLE_LINE4_OUT    DEF_LINE_WIDTH_1
68 #define DEF_DOUBLE_LINE4_IN     DEF_LINE_WIDTH_2
69 #define DEF_DOUBLE_LINE4_DIST   DEF_LINE_WIDTH_1
70 
71 #define DEF_DOUBLE_LINE5_OUT    DEF_LINE_WIDTH_3
72 #define DEF_DOUBLE_LINE5_IN     DEF_LINE_WIDTH_2
73 #define DEF_DOUBLE_LINE5_DIST   DEF_LINE_WIDTH_2
74 
75 #define DEF_DOUBLE_LINE6_OUT    DEF_LINE_WIDTH_2
76 #define DEF_DOUBLE_LINE6_IN     DEF_LINE_WIDTH_3
77 #define DEF_DOUBLE_LINE6_DIST   DEF_LINE_WIDTH_2
78 
79 #define DEF_DOUBLE_LINE7_OUT    DEF_LINE_WIDTH_0
80 #define DEF_DOUBLE_LINE7_IN     DEF_LINE_WIDTH_0
81 #define DEF_DOUBLE_LINE7_DIST   DEF_LINE_WIDTH_2
82 
83 #define DEF_DOUBLE_LINE8_OUT    DEF_LINE_WIDTH_1
84 #define DEF_DOUBLE_LINE8_IN     DEF_LINE_WIDTH_0
85 #define DEF_DOUBLE_LINE8_DIST   DEF_LINE_WIDTH_2
86 
87 #define DEF_DOUBLE_LINE9_OUT    DEF_LINE_WIDTH_2
88 #define DEF_DOUBLE_LINE9_IN     DEF_LINE_WIDTH_0
89 #define DEF_DOUBLE_LINE9_DIST   DEF_LINE_WIDTH_2
90 
91 #define DEF_DOUBLE_LINE10_OUT	DEF_LINE_WIDTH_3
92 #define DEF_DOUBLE_LINE10_IN	DEF_LINE_WIDTH_0
93 #define DEF_DOUBLE_LINE10_DIST	DEF_LINE_WIDTH_2
94 
95 // finished copy
96 
97 #define SVX_XML_BORDER_STYLE_NONE 0
98 #define SVX_XML_BORDER_STYLE_SOLID 1
99 #define SVX_XML_BORDER_STYLE_DOUBLE 2
100 
101 #define SVX_XML_BORDER_WIDTH_THIN 0
102 #define SVX_XML_BORDER_WIDTH_MIDDLE 1
103 #define SVX_XML_BORDER_WIDTH_THICK 2
104 
105 SvXMLEnumMapEntry pXML_BorderStyles[] =
106 {
107 	{ XML_NONE,				    SVX_XML_BORDER_STYLE_NONE	},
108 	{ XML_HIDDEN, 				SVX_XML_BORDER_STYLE_NONE	},
109 	{ XML_SOLID, 				SVX_XML_BORDER_STYLE_SOLID	},
110 	{ XML_DOUBLE,				SVX_XML_BORDER_STYLE_DOUBLE	},
111 	{ XML_DOTTED, 				SVX_XML_BORDER_STYLE_SOLID  },
112 	{ XML_DASHED, 				SVX_XML_BORDER_STYLE_SOLID	},
113 	{ XML_GROOVE, 				SVX_XML_BORDER_STYLE_SOLID	},
114 	{ XML_RIDGE,  				SVX_XML_BORDER_STYLE_SOLID  },
115 	{ XML_INSET,  				SVX_XML_BORDER_STYLE_SOLID  },
116 	{ XML_OUTSET, 				SVX_XML_BORDER_STYLE_SOLID	},
117 	{ XML_TOKEN_INVALID,        0 }
118 };
119 
120 SvXMLEnumMapEntry pXML_NamedBorderWidths[] =
121 {
122 	{ XML_THIN,	            SVX_XML_BORDER_WIDTH_THIN	},
123 	{ XML_MIDDLE,	        SVX_XML_BORDER_WIDTH_MIDDLE	},
124 	{ XML_THICK,	        SVX_XML_BORDER_WIDTH_THICK	},
125 	{ XML_TOKEN_INVALID,    0 }
126 };
127 // mapping tables to map external xml input to intarnal box line widths
128 
129 // Ein Eintrag besteht aus vier USHORTs. Der erste ist die Gesamtbreite,
130 // die anderen sind die 3 Einzelbreiten
131 
132 #define SBORDER_ENTRY( n ) \
133 	DEF_LINE_WIDTH_##n, DEF_LINE_WIDTH_##n, 0, 0
134 
135 #define DBORDER_ENTRY( n ) \
136 	DEF_DOUBLE_LINE##n##_OUT + DEF_DOUBLE_LINE##n##_IN + \
137 	DEF_DOUBLE_LINE##n##_DIST, \
138 	DEF_DOUBLE_LINE##n##_OUT, \
139 	DEF_DOUBLE_LINE##n##_IN, \
140 	DEF_DOUBLE_LINE##n##_DIST
141 
142 #define TDBORDER_ENTRY( n ) \
143 	DEF_DOUBLE_LINE##n##_OUT, \
144 	DEF_DOUBLE_LINE##n##_OUT, \
145 	DEF_DOUBLE_LINE##n##_IN, \
146 	DEF_DOUBLE_LINE##n##_DIST
147 
148 
149 static sal_uInt16 __READONLY_DATA aSBorderWidths[] =
150 {
151 	SBORDER_ENTRY( 0 ), SBORDER_ENTRY( 1 ), SBORDER_ENTRY( 2 ),
152 	SBORDER_ENTRY( 3 ), SBORDER_ENTRY( 4 )
153 };
154 
155 static sal_uInt16 __READONLY_DATA aDBorderWidths[] =
156 {
157 	DBORDER_ENTRY( 0 ),
158 	DBORDER_ENTRY( 7 ),
159 	DBORDER_ENTRY( 1 ),
160 	DBORDER_ENTRY( 8 ),
161 	DBORDER_ENTRY( 4 ),
162 	DBORDER_ENTRY( 9 ),
163 	DBORDER_ENTRY( 3 ),
164 	DBORDER_ENTRY( 10 ),
165 	DBORDER_ENTRY( 2 ),
166 	DBORDER_ENTRY( 6 ),
167 	DBORDER_ENTRY( 5 )
168 };
169 
lcl_frmitems_setXMLBorderWidth(table::BorderLine & rBorderLine,sal_uInt16 nWidth,sal_Bool bDouble)170 void lcl_frmitems_setXMLBorderWidth( table::BorderLine &rBorderLine,
171 									 sal_uInt16 nWidth, sal_Bool bDouble )
172 {
173 #ifdef XML_CHECK_UI_CONTSTRAINS
174 	const sal_uInt16 *aWidths;
175 	sal_uInt16 nSize;
176 	if( !bDouble )
177 	{
178 		aWidths = aSBorderWidths;
179 		nSize = sizeof( aSBorderWidths );
180 	}
181 	else
182 	{
183 		aWidths = aDBorderWidths;
184 		nSize = sizeof( aDBorderWidths );
185 	}
186 
187 	sal_uInt16 i = (nSize / sizeof(sal_uInt16)) - 4;
188 	while( i>0 &&
189 		   nWidth <= ((aWidths[i] + aWidths[i-4]) / 2)	)
190 	{
191 		i -= 4;
192 	}
193 
194 	rBorderLine.OuterLineWidth = aWidths[i+1];
195 	rBorderLine.InnerLineWidth = aWidths[i+2];
196 	rBorderLine.LineDistance = aWidths[i+3];
197 #else
198 	if( bDouble )
199 	{
200 		const sal_uInt16 *aWidths = aDBorderWidths;
201 		sal_uInt16 nSize = sizeof( aDBorderWidths );
202 		sal_uInt16 i = (nSize / sizeof(sal_uInt16)) - 4;
203 		while( i>0 &&
204 			   nWidth <= ((aWidths[i] + aWidths[i-4]) / 2)	)
205 		{
206 			i -= 4;
207 		}
208 
209 		rBorderLine.OuterLineWidth = aWidths[i+1];
210 		rBorderLine.InnerLineWidth = aWidths[i+2];
211 		rBorderLine.LineDistance = aWidths[i+3];
212 	}
213 	else
214 	{
215 		rBorderLine.OuterLineWidth = 0 == nWidth ? DEF_LINE_WIDTH_0 : nWidth;
216 		rBorderLine.InnerLineWidth = 0;
217 		rBorderLine.LineDistance = 0;
218 
219 	}
220 #endif
221 }
222 
223 
224 ///////////////////////////////////////////////////////////////////////////////
225 //
226 // class XMLEscapementPropHdl
227 //
228 
~XMLBorderWidthHdl()229 XMLBorderWidthHdl::~XMLBorderWidthHdl()
230 {
231 	// nothing to do
232 }
233 
importXML(const OUString & rStrImpValue,uno::Any & rValue,const SvXMLUnitConverter & rUnitConverter) const234 sal_Bool XMLBorderWidthHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
235 {
236 	SvXMLTokenEnumerator aTokenEnum( rStrImpValue );
237 
238 	sal_Int32 nInWidth, nDistance, nOutWidth;
239 
240 	OUString aToken;
241 	if( !aTokenEnum.getNextToken( aToken ) )
242 		return sal_False;
243 
244 	if( !rUnitConverter.convertMeasure( nInWidth, aToken, 0, 500 ) )
245 		return sal_False;
246 
247 	if( !aTokenEnum.getNextToken( aToken ) )
248 		return sal_False;
249 
250 	if( !rUnitConverter.convertMeasure( nDistance, aToken, 0, 500 ) )
251 		return sal_False;
252 
253 	if( !aTokenEnum.getNextToken( aToken ) )
254 		return sal_False;
255 
256 	if( !rUnitConverter.convertMeasure( nOutWidth, aToken, 0, 500 ) )
257 		return sal_False;
258 
259 #ifdef XML_CHECK_UI_CONSTRAINS
260 	sal_uInt16 nSize = sizeof( aDBorderWidths );
261 	for( sal_uInt16 i=0; i < nSize; i += 4 )
262 	{
263 		if( aDBorderWidths[i+1] == nOutWidth &&
264 			aDBorderWidths[i+2] == nInWidth &&
265 			aDBorderWidths[i+3] == nDistance )
266 			break;
267 	}
268 
269 	sal_uInt16 nWidth = i < nSize ? 0 : nOutWidth + nInWidth + nDistance;
270 #endif
271 
272 	table::BorderLine aBorderLine;
273 	if(!(rValue >>= aBorderLine))
274 		aBorderLine.Color = 0;
275 
276 	aBorderLine.InnerLineWidth = sal::static_int_cast< sal_Int16 >(nInWidth);
277 	aBorderLine.OuterLineWidth = sal::static_int_cast< sal_Int16 >(nOutWidth);
278 	aBorderLine.LineDistance   = sal::static_int_cast< sal_Int16 >(nDistance);
279 
280 	rValue <<= aBorderLine;
281 	return sal_True;
282 }
283 
exportXML(OUString & rStrExpValue,const uno::Any & rValue,const SvXMLUnitConverter & rUnitConverter) const284 sal_Bool XMLBorderWidthHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
285 {
286 	OUStringBuffer aOut;
287 
288 	table::BorderLine aBorderLine;
289 	if(!(rValue >>= aBorderLine))
290 		return sal_False;
291 
292 	if( aBorderLine.LineDistance == 0 && aBorderLine.InnerLineWidth == 0)
293 		return sal_False;
294 
295 	rUnitConverter.convertMeasure( aOut, aBorderLine.InnerLineWidth );
296 	aOut.append( sal_Unicode( ' ' ) );
297 	rUnitConverter.convertMeasure( aOut, aBorderLine.LineDistance );
298 	aOut.append( sal_Unicode( ' ' ) );
299 	rUnitConverter.convertMeasure( aOut, aBorderLine.OuterLineWidth );
300 
301 	rStrExpValue = aOut.makeStringAndClear();
302 	return sal_True;
303 }
304 
305 ///////////////////////////////////////////////////////////////////////////////
306 //
307 // class XMLEscapementHeightPropHdl
308 //
309 
~XMLBorderHdl()310 XMLBorderHdl::~XMLBorderHdl()
311 {
312 	// nothing to do
313 }
314 
importXML(const OUString & rStrImpValue,uno::Any & rValue,const SvXMLUnitConverter & rUnitConverter) const315 sal_Bool XMLBorderHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
316 {
317 	OUString aToken;
318 	SvXMLTokenEnumerator aTokens( rStrImpValue );
319 
320 	sal_Bool bHasStyle = sal_False;
321 	sal_Bool bHasWidth = sal_False;
322 	sal_Bool bHasColor = sal_False;
323 
324 	sal_uInt16 nStyle = USHRT_MAX;
325 	sal_uInt16 nWidth = 0;
326 	sal_uInt16 nNamedWidth = USHRT_MAX;
327 	Color aColor;
328 
329 	sal_Int32 nTemp;
330 	while( aTokens.getNextToken( aToken ) && aToken.getLength() != 0 )
331 	{
332 		if( !bHasWidth &&
333 			rUnitConverter.convertEnum( nNamedWidth, aToken,
334 										pXML_NamedBorderWidths ) )
335 		{
336 			bHasWidth = sal_True;
337 		}
338 		else if( !bHasStyle &&
339 			     rUnitConverter.convertEnum( nStyle, aToken,
340 						 					 pXML_BorderStyles ) )
341 		{
342 			bHasStyle = sal_True;
343 		}
344 		else if( !bHasColor && rUnitConverter.convertColor( aColor, aToken ) )
345 		{
346 			bHasColor = sal_True;
347 		}
348 		else if( !bHasWidth &&
349 				 rUnitConverter.convertMeasure( nTemp, aToken, 0,
350 						 						USHRT_MAX ) )
351 		{
352 			nWidth = (sal_uInt16)nTemp;
353 			bHasWidth = sal_True;
354 		}
355 		else
356 		{
357 			// missformed
358 			return sal_False;
359 		}
360 	}
361 
362 	// if there is no style or a different style than none but no width,
363    	// then the declaration is not valid.
364 	if( !bHasStyle || (SVX_XML_BORDER_STYLE_NONE != nStyle && !bHasWidth) )
365 		return sal_False;
366 
367 	table::BorderLine aBorderLine;
368 	if(!(rValue >>= aBorderLine))
369 	{
370 		aBorderLine.Color = 0;
371 		aBorderLine.InnerLineWidth = 0;
372 		aBorderLine.OuterLineWidth = 0;
373 		aBorderLine.LineDistance   = 0;
374 	}
375 
376 	// first of all, delete an empty line
377 	sal_Bool bDouble = SVX_XML_BORDER_STYLE_DOUBLE == nStyle;
378 	if( (bHasStyle && SVX_XML_BORDER_STYLE_NONE == nStyle) ||
379 		(bHasWidth && USHRT_MAX == nNamedWidth && 0 == nWidth) )
380 	{
381 		aBorderLine.InnerLineWidth = 0;
382 		aBorderLine.OuterLineWidth = 0;
383 		aBorderLine.LineDistance   = 0;
384 	}
385 	else if( bHasWidth )
386 	{
387 		if( USHRT_MAX != nNamedWidth )
388 		{
389 			const sal_uInt16 *aWidths = bDouble ? aDBorderWidths
390 										    : aSBorderWidths;
391 			sal_uInt16 nNWidth = nNamedWidth * 4;
392 			aBorderLine.OuterLineWidth = aWidths[nNWidth+1];
393 			aBorderLine.InnerLineWidth = aWidths[nNWidth+2];
394 			aBorderLine.LineDistance = aWidths[nNWidth+3];
395 		}
396 		else
397 		{
398 			lcl_frmitems_setXMLBorderWidth( aBorderLine, nWidth, bDouble );
399 		}
400 	}
401 	else
402 	{
403 		lcl_frmitems_setXMLBorderWidth( aBorderLine, 0, bDouble );
404 	}
405 
406 	// set color
407 	if( bHasColor )
408 		aBorderLine.Color = (sal_Int32)aColor.GetRGBColor();
409 
410 	rValue <<= aBorderLine;
411 	return sal_True;
412 }
413 
exportXML(OUString & rStrExpValue,const uno::Any & rValue,const SvXMLUnitConverter & rUnitConverter) const414 sal_Bool XMLBorderHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
415 {
416 	OUStringBuffer aOut;
417 
418 	table::BorderLine aBorderLine;
419 	if(!(rValue >>= aBorderLine))
420 		return sal_False;
421 
422 	sal_Int32 nWidth = aBorderLine.OuterLineWidth;
423 	const sal_uInt16 nDistance = aBorderLine.LineDistance;
424 	if( 0 != nDistance )
425 	{
426 		nWidth += nDistance;
427 		nWidth += aBorderLine.InnerLineWidth;
428 	}
429 
430 	if( nWidth == 0 )
431 	{
432 		aOut.append( GetXMLToken( XML_NONE ) );
433 	}
434 	else
435 	{
436 		rUnitConverter.convertMeasure( aOut, nWidth );
437 
438 		aOut.append( sal_Unicode( ' ' ) );
439 
440 		aOut.append( GetXMLToken((0 == nDistance) ? XML_SOLID : XML_DOUBLE) );
441 
442 		aOut.append( sal_Unicode( ' ' ) );
443 
444 		rUnitConverter.convertColor( aOut, aBorderLine.Color );
445 	}
446 
447 	rStrExpValue = aOut.makeStringAndClear();
448 
449 	return sal_True;
450 }
451