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