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