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 #include <limits.h> 27 #include <tools/debug.hxx> 28 #include <tools/bigint.hxx> 29 #include <rtl/ustrbuf.hxx> 30 #include "xmlehelp.hxx" 31 32 #ifndef _XMLOFF_XMTOKEN_HXX 33 #include <xmloff/xmltoken.hxx> 34 #endif 35 36 using ::rtl::OUString; 37 using ::rtl::OUStringBuffer; 38 39 using namespace ::xmloff::token; 40 41 void SvXMLExportHelper::AddLength( sal_Int32 nValue, MapUnit eValueUnit, 42 OUStringBuffer& rOut, 43 MapUnit eOutUnit ) 44 { 45 // the sign is processed seperatly 46 if( nValue < 0 ) 47 { 48 nValue = -nValue; 49 rOut.append( sal_Unicode('-') ); 50 } 51 52 // The new length is (nVal * nMul)/(nDiv*nFac*10) 53 sal_Int32 nMul = 1000; 54 sal_Int32 nDiv = 1; 55 sal_Int32 nFac = 100; 56 enum XMLTokenEnum eUnit = XML_TOKEN_INVALID; 57 switch( eValueUnit ) 58 { 59 case MAP_TWIP: 60 switch( eOutUnit ) 61 { 62 case MAP_100TH_MM: 63 case MAP_10TH_MM: 64 DBG_ASSERT( MAP_INCH == eOutUnit, 65 "output unit not supported for twip values" ); 66 case MAP_MM: 67 // 0.01mm = 0.57twip (exactly) 68 nMul = 25400; // 25.4 * 1000 69 nDiv = 1440; // 72 * 20; 70 nFac = 100; 71 eUnit = XML_UNIT_MM; 72 break; 73 74 case MAP_CM: 75 // 0.001cm = 0.57twip (exactly) 76 nMul = 25400; // 2.54 * 10000 77 nDiv = 1440; // 72 * 20; 78 nFac = 1000; 79 eUnit = XML_UNIT_CM; 80 break; 81 82 case MAP_POINT: 83 // 0.01pt = 0.2twip (exactly) 84 nMul = 1000; 85 nDiv = 20; 86 nFac = 100; 87 eUnit = XML_UNIT_PT; 88 break; 89 90 case MAP_INCH: 91 default: 92 DBG_ASSERT( MAP_INCH == eOutUnit, 93 "output unit not supported for twip values" ); 94 // 0.0001in = 0.144twip (exactly) 95 nMul = 100000; 96 nDiv = 1440; // 72 * 20; 97 nFac = 10000; 98 eUnit = XML_UNIT_INCH; 99 break; 100 } 101 break; 102 103 case MAP_POINT: 104 // 1pt = 1pt (exactly) 105 DBG_ASSERT( MAP_POINT == eOutUnit, 106 "output unit not supported for pt values" ); 107 nMul = 10; 108 nDiv = 1; 109 nFac = 1; 110 eUnit = XML_UNIT_PT; 111 break; 112 case MAP_10TH_MM: 113 case MAP_100TH_MM: 114 { 115 long nFac2 = (MAP_100TH_MM == eValueUnit) ? 100 : 10; 116 switch( eOutUnit ) 117 { 118 case MAP_100TH_MM: 119 case MAP_10TH_MM: 120 DBG_ASSERT( MAP_INCH == eOutUnit, 121 "output unit not supported for 1/100mm values" ); 122 case MAP_MM: 123 // 0.01mm = 1 mm/100 (exactly) 124 nMul = 10; 125 nDiv = 1; 126 nFac = nFac2; 127 eUnit = XML_UNIT_MM; 128 break; 129 130 case MAP_CM: 131 // 0.001mm = 1 mm/100 (exactly) 132 nMul = 10; 133 nDiv = 1; // 72 * 20; 134 nFac = 10*nFac2; 135 eUnit = XML_UNIT_CM; 136 break; 137 138 case MAP_POINT: 139 // 0.01pt = 0.35 mm/100 (exactly) 140 nMul = 72000; 141 nDiv = 2540; 142 nFac = nFac2; 143 eUnit = XML_UNIT_PT; 144 break; 145 146 case MAP_INCH: 147 default: 148 DBG_ASSERT( MAP_INCH == eOutUnit, 149 "output unit not supported for 1/100mm values" ); 150 // 0.0001in = 0.254 mm/100 (exactly) 151 nMul = 100000; 152 nDiv = 2540; 153 nFac = 100*nFac2; 154 eUnit = XML_UNIT_INCH; 155 break; 156 } 157 break; 158 } 159 default: 160 DBG_ASSERT( 0, "input unit not handled" ); 161 break; 162 } 163 164 165 sal_Int32 nLongVal = 0; 166 sal_Bool bOutLongVal = sal_True; 167 if( nValue > SAL_MAX_INT32 / nMul ) 168 { 169 // A big int is required for calculation 170 BigInt nBigVal( nValue ); 171 nBigVal *= nMul; 172 nBigVal /= nDiv; 173 nBigVal += 5; 174 nBigVal /= 10; 175 176 if( nBigVal.IsLong() ) 177 { 178 // To convert the value into a string a sal_Int32 is sufficient 179 nLongVal = sal_Int32( nBigVal ); 180 } 181 else 182 { 183 BigInt nBigFac( nFac ); 184 BigInt nBig10( 10 ); 185 rOut.append( (sal_Int32)(nBigVal / nBigFac) ); 186 if( !(nBigVal % nBigFac).IsZero() ) 187 { 188 rOut.append( sal_Unicode('.') ); 189 while( nFac > 1 && !(nBigVal % nBigFac).IsZero() ) 190 { 191 nFac /= 10; 192 nBigFac = nFac; 193 rOut.append( (sal_Int32)((nBigVal / nBigFac) % nBig10 ) ); 194 } 195 } 196 bOutLongVal = sal_False; 197 } 198 } 199 else 200 { 201 nLongVal = nValue * nMul; 202 nLongVal /= nDiv; 203 nLongVal += 5; 204 nLongVal /= 10; 205 } 206 207 if( bOutLongVal ) 208 { 209 rOut.append( (sal_Int32)(nLongVal / nFac) ); 210 if( nFac > 1 && (nLongVal % nFac) != 0 ) 211 { 212 rOut.append( sal_Unicode('.') ); 213 while( nFac > 1 && (nLongVal % nFac) != 0 ) 214 { 215 nFac /= 10; 216 rOut.append( (sal_Int32)((nLongVal / nFac) % 10) ); 217 } 218 } 219 } 220 221 if( eUnit != XML_TOKEN_INVALID ) 222 rOut.append( GetXMLToken(eUnit) ); 223 } 224 225 void SvXMLExportHelper::AddPercentage( sal_Int32 nValue, OUStringBuffer& rOut ) 226 { 227 rOut.append( nValue ); 228 rOut.append( sal_Unicode('%' ) ); 229 } 230 231 double SvXMLExportHelper::GetConversionFactor(::rtl::OUStringBuffer& rUnit, 232 const MapUnit eCoreUnit, const MapUnit eDestUnit) 233 { 234 double fRetval(1.0); 235 rUnit.setLength(0L); 236 237 if(eCoreUnit != eDestUnit) 238 { 239 enum XMLTokenEnum eUnit = XML_TOKEN_INVALID; 240 241 switch(eCoreUnit) 242 { 243 case MAP_TWIP: 244 { 245 switch(eDestUnit) 246 { 247 case MAP_100TH_MM: 248 case MAP_10TH_MM: 249 { 250 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for twip values"); 251 } 252 case MAP_MM: 253 { 254 // 0.01mm = 0.57twip (exactly) 255 fRetval = ((25400.0 / 1440.0) / 1000.0); 256 eUnit = XML_UNIT_MM; 257 break; 258 } 259 case MAP_CM: 260 { 261 // 0.001cm = 0.57twip (exactly) 262 fRetval = ((25400.0 / 1440.0) / 10000.0); 263 eUnit = XML_UNIT_CM; 264 break; 265 } 266 case MAP_POINT: 267 { 268 // 0.01pt = 0.2twip (exactly) 269 fRetval = ((1000.0 / 20.0) / 1000.0); 270 eUnit = XML_UNIT_PT; 271 break; 272 } 273 case MAP_INCH: 274 default: 275 { 276 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for twip values"); 277 // 0.0001in = 0.144twip (exactly) 278 fRetval = ((100000.0 / 1440.0) / 100000.0); 279 eUnit = XML_UNIT_INCH; 280 break; 281 } 282 } 283 break; 284 } 285 case MAP_POINT: 286 { 287 switch(eDestUnit) 288 { 289 case MAP_MM: 290 // 1mm = 72 / 25.4 pt (exactly) 291 fRetval = ( 25.4 / 72.0 ); 292 eUnit = XML_UNIT_MM; 293 break; 294 295 case MAP_CM: 296 // 1cm = 72 / 2.54 pt (exactly) 297 fRetval = ( 2.54 / 72.0 ); 298 eUnit = XML_UNIT_CM; 299 break; 300 301 case MAP_TWIP: 302 // 1twip = 72 / 1440 pt (exactly) 303 fRetval = 20.0; // 1440.0 / 72.0 304 eUnit = XML_UNIT_PC; 305 break; 306 307 case MAP_INCH: 308 default: 309 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for pt values"); 310 // 1in = 72 pt (exactly) 311 fRetval = ( 1.0 / 72.0 ); 312 eUnit = XML_UNIT_INCH; 313 break; 314 } 315 break; 316 } 317 case MAP_10TH_MM: 318 { 319 switch(eDestUnit) 320 { 321 case MAP_100TH_MM: 322 case MAP_10TH_MM: 323 { 324 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for 1/100mm values"); 325 } 326 case MAP_MM: 327 { 328 // 0.01mm = 1 mm/100 (exactly) 329 fRetval = ((10.0 / 1.0) / 100.0); 330 eUnit = XML_UNIT_MM; 331 break; 332 } 333 case MAP_CM: 334 { 335 // 0.001mm = 1 mm/100 (exactly) 336 fRetval = ((10.0 / 1.0) / 1000.0); 337 eUnit = XML_UNIT_CM; 338 break; 339 } 340 case MAP_POINT: 341 { 342 // 0.01pt = 0.35 mm/100 (exactly) 343 fRetval = ((72000.0 / 2540.0) / 100.0); 344 eUnit = XML_UNIT_PT; 345 break; 346 } 347 case MAP_INCH: 348 default: 349 { 350 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for 1/100mm values"); 351 // 0.0001in = 0.254 mm/100 (exactly) 352 fRetval = ((100000.0 / 2540.0) / 10000.0); 353 eUnit = XML_UNIT_INCH; 354 break; 355 } 356 } 357 break; 358 } 359 case MAP_100TH_MM: 360 { 361 switch(eDestUnit) 362 { 363 case MAP_100TH_MM: 364 case MAP_10TH_MM: 365 { 366 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for 1/100mm values"); 367 } 368 case MAP_MM: 369 { 370 // 0.01mm = 1 mm/100 (exactly) 371 fRetval = ((10.0 / 1.0) / 1000.0); 372 eUnit = XML_UNIT_MM; 373 break; 374 } 375 case MAP_CM: 376 { 377 // 0.001mm = 1 mm/100 (exactly) 378 fRetval = ((10.0 / 1.0) / 10000.0); 379 eUnit = XML_UNIT_CM; 380 break; 381 } 382 case MAP_POINT: 383 { 384 // 0.01pt = 0.35 mm/100 (exactly) 385 fRetval = ((72000.0 / 2540.0) / 1000.0); 386 eUnit = XML_UNIT_PT; 387 break; 388 } 389 case MAP_INCH: 390 default: 391 { 392 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for 1/100mm values"); 393 // 0.0001in = 0.254 mm/100 (exactly) 394 fRetval = ((100000.0 / 2540.0) / 100000.0); 395 eUnit = XML_UNIT_INCH; 396 break; 397 } 398 } 399 break; 400 } 401 default: 402 DBG_ERROR("xmloff::SvXMLExportHelper::GetConversionFactor(), illegal eCoreUnit value!"); 403 break; 404 } 405 406 if(eUnit != XML_TOKEN_INVALID) 407 rUnit.append(GetXMLToken(eUnit)); 408 } 409 410 return fRetval; 411 } 412 413 MapUnit SvXMLExportHelper::GetUnitFromString(const ::rtl::OUString& rString, MapUnit eDefaultUnit) 414 { 415 sal_Int32 nPos = 0; 416 sal_Int32 nLen = rString.getLength(); 417 MapUnit eRetUnit = eDefaultUnit; 418 419 // skip white space 420 while( nPos < nLen && sal_Unicode(' ') == rString[nPos] ) 421 nPos++; 422 423 // skip negative 424 if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) 425 nPos++; 426 427 // skip number 428 while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] ) 429 nPos++; 430 431 if( nPos < nLen && sal_Unicode('.') == rString[nPos] ) 432 { 433 nPos++; 434 while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] ) 435 nPos++; 436 } 437 438 // skip white space 439 while( nPos < nLen && sal_Unicode(' ') == rString[nPos] ) 440 nPos++; 441 442 if( nPos < nLen ) 443 { 444 switch(rString[nPos]) 445 { 446 case sal_Unicode('%') : 447 { 448 eRetUnit = MAP_RELATIVE; 449 break; 450 } 451 case sal_Unicode('c'): 452 case sal_Unicode('C'): 453 { 454 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m') 455 || rString[nPos+1] == sal_Unicode('M'))) 456 eRetUnit = MAP_CM; 457 break; 458 } 459 case sal_Unicode('e'): 460 case sal_Unicode('E'): 461 { 462 // CSS1_EMS or CSS1_EMX later 463 break; 464 } 465 case sal_Unicode('i'): 466 case sal_Unicode('I'): 467 { 468 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('n') 469 || rString[nPos+1] == sal_Unicode('n'))) 470 eRetUnit = MAP_INCH; 471 break; 472 } 473 case sal_Unicode('m'): 474 case sal_Unicode('M'): 475 { 476 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m') 477 || rString[nPos+1] == sal_Unicode('M'))) 478 eRetUnit = MAP_MM; 479 break; 480 } 481 case sal_Unicode('p'): 482 case sal_Unicode('P'): 483 { 484 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('t') 485 || rString[nPos+1] == sal_Unicode('T'))) 486 eRetUnit = MAP_POINT; 487 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('c') 488 || rString[nPos+1] == sal_Unicode('C'))) 489 eRetUnit = MAP_TWIP; 490 break; 491 } 492 } 493 } 494 495 return eRetUnit; 496 } 497