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 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 229 XMLBorderWidthHdl::~XMLBorderWidthHdl() 230 { 231 // nothing to do 232 } 233 234 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 284 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 310 XMLBorderHdl::~XMLBorderHdl() 311 { 312 // nothing to do 313 } 314 315 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 414 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