xref: /trunk/main/xmloff/source/style/bordrhdl.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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