xref: /AOO41X/main/xmloff/source/style/bordrhdl.cxx (revision 63bba73cc51e0afb45f8a8d578158724bb5afee8)
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