1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <svtools/unitconv.hxx> 21 #include <tools/debug.hxx> 22 #include <vcl/outdev.hxx> 23 #include <vcl/weld.hxx> 24 25 void SetFieldUnit(weld::MetricSpinButton& rField, FieldUnit eUnit, bool bAll) 26 { 27 int nMin, nMax; 28 rField.get_range(nMin, nMax, FieldUnit::TWIP); 29 int nValue = rField.get_value(FieldUnit::TWIP); 30 nMin = rField.denormalize(nMin); 31 nMax = rField.denormalize(nMax); 32 nValue = rField.denormalize(nValue); 33 34 if (!bAll) 35 { 36 switch (eUnit) 37 { 38 case FieldUnit::M: 39 case FieldUnit::KM: 40 eUnit = FieldUnit::CM; 41 break; 42 case FieldUnit::FOOT: 43 case FieldUnit::MILE: 44 eUnit = FieldUnit::INCH; 45 break; 46 default: //prevent warning 47 break; 48 } 49 } 50 51 rField.set_unit(eUnit); 52 53 if (FieldUnit::POINT == eUnit) 54 { 55 if (rField.get_digits() > 1) 56 rField.set_digits(1); 57 } 58 else 59 rField.set_digits(2); 60 61 switch (eUnit) 62 { 63 // _CHAR and _LINE sets the step of "char" and "line" unit, they are same as FieldUnit::MM 64 case FieldUnit::CHAR: 65 case FieldUnit::LINE: 66 case FieldUnit::MM: 67 rField.set_increments(50, 500, eUnit); 68 break; 69 case FieldUnit::INCH: 70 rField.set_increments(2, 20, eUnit); 71 break; 72 default: 73 rField.set_increments(10, 100, eUnit); 74 break; 75 } 76 77 if (!bAll) 78 { 79 nMin = rField.normalize(nMin); 80 nMax = rField.normalize(nMax); 81 rField.set_range(nMin, nMax, FieldUnit::TWIP); 82 } 83 84 rField.set_value(rField.normalize(nValue), FieldUnit::TWIP); 85 } 86 87 void SetMetricValue(weld::MetricSpinButton& rField, int nCoreValue, MapUnit eUnit) 88 { 89 auto nVal = OutputDevice::LogicToLogic(nCoreValue, eUnit, MapUnit::Map100thMM); 90 nVal = rField.normalize(nVal); 91 rField.set_value(nVal, FieldUnit::MM_100TH); 92 } 93 94 int GetCoreValue(const weld::MetricSpinButton& rField, MapUnit eUnit) 95 { 96 int nVal = rField.get_value(FieldUnit::MM_100TH); 97 // avoid rounding issues 98 const int nSizeMask = 0xff000000; 99 bool bRoundBefore = true; 100 if( nVal >= 0 ) 101 { 102 if( (nVal & nSizeMask) == 0 ) 103 bRoundBefore = false; 104 } 105 else 106 { 107 if( ((-nVal) & nSizeMask ) == 0 ) 108 bRoundBefore = false; 109 } 110 if( bRoundBefore ) 111 nVal = rField.denormalize( nVal ); 112 auto nUnitVal = OutputDevice::LogicToLogic(nVal, MapUnit::Map100thMM, eUnit); 113 if (!bRoundBefore) 114 nUnitVal = rField.denormalize(nUnitVal); 115 return nUnitVal; 116 } 117 118 long CalcToUnit( float nIn, MapUnit eUnit ) 119 { 120 // nIn is in Points 121 122 DBG_ASSERT( eUnit == MapUnit::MapTwip || 123 eUnit == MapUnit::Map100thMM || 124 eUnit == MapUnit::Map10thMM || 125 eUnit == MapUnit::MapMM || 126 eUnit == MapUnit::MapCM, "this unit is not implemented" ); 127 128 float nTmp = nIn; 129 130 if ( MapUnit::MapTwip != eUnit ) 131 nTmp = nIn * 10 / 567; 132 133 switch ( eUnit ) 134 { 135 case MapUnit::Map100thMM: nTmp *= 100; break; 136 case MapUnit::Map10thMM: nTmp *= 10; break; 137 case MapUnit::MapMM: break; 138 case MapUnit::MapCM: nTmp /= 10; break; 139 default: ;//prevent warning 140 } 141 142 nTmp *= 20; 143 long nRet = static_cast<long>(nTmp); 144 return nRet; 145 //! return (long)(nTmp * 20); 146 } 147 148 149 long ItemToControl( long nIn, MapUnit eItem, FieldUnit eCtrl ) 150 { 151 long nOut = 0; 152 153 switch ( eItem ) 154 { 155 case MapUnit::Map100thMM: 156 case MapUnit::Map10thMM: 157 case MapUnit::MapMM: 158 { 159 if ( eItem == MapUnit::Map10thMM ) 160 nIn /= 10; 161 else if ( eItem == MapUnit::Map100thMM ) 162 nIn /= 100; 163 nOut = TransformMetric( nIn, FieldUnit::MM, eCtrl ); 164 } 165 break; 166 167 case MapUnit::MapCM: 168 { 169 nOut = TransformMetric( nIn, FieldUnit::CM, eCtrl ); 170 } 171 break; 172 173 case MapUnit::Map1000thInch: 174 case MapUnit::Map100thInch: 175 case MapUnit::Map10thInch: 176 case MapUnit::MapInch: 177 { 178 if ( eItem == MapUnit::Map10thInch ) 179 nIn /= 10; 180 else if ( eItem == MapUnit::Map100thInch ) 181 nIn /= 100; 182 else if ( eItem == MapUnit::Map1000thInch ) 183 nIn /= 1000; 184 nOut = TransformMetric( nIn, FieldUnit::INCH, eCtrl ); 185 } 186 break; 187 188 case MapUnit::MapPoint: 189 { 190 nOut = TransformMetric( nIn, FieldUnit::POINT, eCtrl ); 191 } 192 break; 193 194 case MapUnit::MapTwip: 195 { 196 nOut = TransformMetric( nIn, FieldUnit::TWIP, eCtrl ); 197 } 198 break; 199 default: ;//prevent warning 200 } 201 return nOut; 202 } 203 204 205 long ControlToItem( long nIn, FieldUnit eCtrl, MapUnit eItem ) 206 { 207 return ItemToControl( nIn, eItem, eCtrl ); 208 } 209 210 211 FieldUnit MapToFieldUnit( const MapUnit eUnit ) 212 { 213 switch ( eUnit ) 214 { 215 case MapUnit::Map100thMM: 216 case MapUnit::Map10thMM: 217 case MapUnit::MapMM: 218 return FieldUnit::MM; 219 220 case MapUnit::MapCM: 221 return FieldUnit::CM; 222 223 case MapUnit::Map1000thInch: 224 case MapUnit::Map100thInch: 225 case MapUnit::Map10thInch: 226 case MapUnit::MapInch: 227 return FieldUnit::INCH; 228 229 case MapUnit::MapPoint: 230 return FieldUnit::POINT; 231 232 case MapUnit::MapTwip: 233 return FieldUnit::TWIP; 234 default: ;//prevent warning 235 } 236 return FieldUnit::NONE; 237 } 238 239 240 long CalcToPoint( long nIn, MapUnit eUnit, sal_uInt16 nFactor ) 241 { 242 DBG_ASSERT( eUnit == MapUnit::MapTwip || 243 eUnit == MapUnit::Map100thMM || 244 eUnit == MapUnit::Map10thMM || 245 eUnit == MapUnit::MapMM || 246 eUnit == MapUnit::MapCM, "this unit is not implemented" ); 247 248 long nRet = 0; 249 250 if ( MapUnit::MapTwip == eUnit ) 251 nRet = nIn; 252 else 253 nRet = nIn * 567; 254 255 switch ( eUnit ) 256 { 257 case MapUnit::Map100thMM: nRet /= 100; break; 258 case MapUnit::Map10thMM: nRet /= 10; break; 259 case MapUnit::MapMM: break; 260 case MapUnit::MapCM: nRet *= 10; break; 261 default: ;//prevent warning 262 } 263 264 // round up if necessary 265 if ( MapUnit::MapTwip != eUnit ) 266 { 267 long nTmp = nRet % 10; 268 269 if ( nTmp >= 4 ) 270 nRet += 10 - nTmp; 271 nRet /= 10; 272 } 273 return nRet * nFactor / 20; 274 } 275 276 277 static long CMToTwips( long nIn ) 278 { 279 long nRet = 0; 280 281 if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) 282 nRet = nIn * 567; 283 return nRet; 284 } 285 286 287 static long MMToTwips( long nIn ) 288 { 289 long nRet = 0; 290 291 if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) 292 nRet = nIn * 567 / 10; 293 return nRet; 294 } 295 296 297 static long InchToTwips( long nIn ) 298 { 299 long nRet = 0; 300 301 if ( nIn <= ( LONG_MAX / 1440 ) && nIn >= ( LONG_MIN / 1440 ) ) 302 nRet = nIn * 1440; 303 return nRet; 304 } 305 306 307 long PointToTwips( long nIn ) 308 { 309 long nRet = 0; 310 311 if ( nIn <= ( LONG_MAX / 20 ) && nIn >= ( LONG_MIN / 20 ) ) 312 nRet = nIn * 20; 313 return nRet; 314 } 315 316 317 static long PicaToTwips( long nIn ) 318 { 319 long nRet = 0; 320 321 if ( nIn <= ( LONG_MAX / 240 ) && nIn >= ( LONG_MIN / 240 ) ) 322 nRet = nIn * 240; 323 return nRet; 324 } 325 326 327 static long TwipsToCM( long nIn ) 328 { 329 long nRet = nIn / 567; 330 return nRet; 331 } 332 333 334 static long InchToCM( long nIn ) 335 { 336 long nRet = 0; 337 338 if ( nIn <= ( LONG_MAX / 254 ) && nIn >= ( LONG_MIN / 254 ) ) 339 nRet = nIn * 254 / 100; 340 return nRet; 341 } 342 343 344 static long MMToCM( long nIn ) 345 { 346 long nRet = nIn / 10; 347 return nRet; 348 } 349 350 351 static long PointToCM( long nIn ) 352 { 353 long nRet = 0; 354 355 if ( nIn <= ( LONG_MAX / 20 ) && nIn >= ( LONG_MIN / 20 ) ) 356 nRet = nIn * 20 / 567; 357 return nRet; 358 } 359 360 361 static long PicaToCM( long nIn) 362 { 363 long nRet = 0; 364 365 if ( nIn <= ( LONG_MAX / 12 / 20 ) && nIn >= ( LONG_MIN / 12 / 20 ) ) 366 nRet = nIn * 12 * 20 / 567; 367 return nRet; 368 } 369 370 371 static long TwipsToMM( long nIn ) 372 { 373 long nRet = 0; 374 375 if ( nIn <= ( LONG_MAX / 10 ) && nIn >= ( LONG_MIN / 10 ) ) 376 nRet = nIn * 10 / 566; 377 return nRet; 378 } 379 380 381 static long CMToMM( long nIn ) 382 { 383 long nRet = 0; 384 385 if ( nIn <= ( LONG_MAX / 10 ) && nIn >= ( LONG_MIN / 10 ) ) 386 nRet = nIn * 10; 387 return nRet; 388 } 389 390 391 static long InchToMM( long nIn ) 392 { 393 long nRet = 0; 394 395 if ( nIn <= ( LONG_MAX / 254 ) && nIn >= ( LONG_MIN / 254 ) ) 396 nRet = nIn * 254 / 10; 397 return nRet; 398 } 399 400 401 static long PointToMM( long nIn ) 402 { 403 long nRet = 0; 404 405 if ( nIn <= ( LONG_MAX / 200 ) && nIn >= ( LONG_MIN / 200 ) ) 406 nRet = nIn * 200 / 567; 407 return nRet; 408 } 409 410 411 static long PicaToMM( long nIn ) 412 { 413 long nRet = 0; 414 415 if ( nIn <= ( LONG_MAX / 12 / 200 ) && nIn >= ( LONG_MIN / 12 / 200 ) ) 416 nRet = nIn * 12 * 200 / 567; 417 return nRet; 418 } 419 420 421 static long TwipsToInch( long nIn ) 422 { 423 long nRet = nIn / 1440; 424 return nRet; 425 } 426 427 428 static long CMToInch( long nIn ) 429 { 430 long nRet = 0; 431 432 if ( nIn <= ( LONG_MAX / 100 ) && nIn >= ( LONG_MIN / 100 ) ) 433 nRet = nIn * 100 / 254; 434 return nRet; 435 } 436 437 438 static long MMToInch( long nIn ) 439 { 440 long nRet = 0; 441 442 if ( nIn <= ( LONG_MAX / 10 ) && nIn >= ( LONG_MIN / 10 ) ) 443 nRet = nIn * 10 / 254; 444 return nRet; 445 } 446 447 448 static long PointToInch( long nIn ) 449 { 450 long nRet = nIn / 72; 451 return nRet; 452 } 453 454 455 static long PicaToInch( long nIn ) 456 { 457 long nRet = nIn / 6; 458 return nRet; 459 } 460 461 462 static long TwipsToPoint( long nIn ) 463 { 464 long nRet = nIn / 20; 465 return nRet; 466 } 467 468 469 static long InchToPoint( long nIn ) 470 { 471 long nRet = 0; 472 473 if ( nIn <= ( LONG_MAX / 72 ) && nIn >= ( LONG_MIN / 72 ) ) 474 nRet = nIn * 72; 475 return nRet; 476 } 477 478 479 static long CMToPoint( long nIn ) 480 { 481 long nRet = 0; 482 483 if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) 484 nRet = nIn * 567 / 20; 485 return nRet; 486 } 487 488 489 static long MMToPoint( long nIn ) 490 { 491 long nRet = 0; 492 493 if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) 494 nRet = nIn * 567 / 200; 495 return nRet; 496 } 497 498 499 static long PicaToPoint( long nIn ) 500 { 501 long nRet = nIn / 12; 502 return nRet; 503 } 504 505 506 static long TwipsToPica( long nIn ) 507 { 508 long nRet = nIn / 240; 509 return nRet; 510 } 511 512 513 static long InchToPica( long nIn ) 514 { 515 long nRet = 0; 516 517 if ( nIn <= ( LONG_MAX / 6 ) && nIn >= ( LONG_MIN / 6 ) ) 518 nRet = nIn * 6; 519 return nRet; 520 } 521 522 523 static long PointToPica( long nIn ) 524 { 525 long nRet = 0; 526 527 if ( nIn <= ( LONG_MAX / 12 ) && nIn >= ( LONG_MIN / 12 ) ) 528 nRet = nIn * 12; 529 return nRet; 530 } 531 532 533 static long CMToPica( long nIn ) 534 { 535 long nRet = 0; 536 537 if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) 538 nRet = nIn * 567 / 20 / 12; 539 return nRet; 540 } 541 542 543 static long MMToPica( long nIn ) 544 { 545 long nRet = 0; 546 547 if ( nIn <= ( LONG_MAX / 567 ) && nIn >= ( LONG_MIN / 567 ) ) 548 nRet = nIn * 567 / 200 / 12; 549 return nRet; 550 } 551 552 553 static long Nothing( long nIn ) 554 { 555 long nRet = nIn; 556 return nRet; 557 } 558 559 FUNC_CONVERT const ConvertTable[6][6] = 560 { 561 // CM, MM INCH POINT PICAS=32 TWIPS 562 { Nothing, CMToMM, CMToInch, CMToPoint, CMToPica, CMToTwips }, 563 { MMToCM, Nothing, MMToInch, MMToPoint, MMToPica, MMToTwips }, 564 { InchToCM, InchToMM, Nothing, InchToPoint, InchToPica, InchToTwips }, 565 { PointToCM, PointToMM, PointToInch, Nothing, PointToPica, PointToTwips }, 566 { PicaToCM, PicaToMM, PicaToInch, PicaToPoint, Nothing, PicaToTwips }, 567 { TwipsToCM, TwipsToMM, TwipsToInch, TwipsToPoint,TwipsToPica, Nothing } 568 }; 569 570 571 long TransformMetric( long nVal, FieldUnit aOld, FieldUnit aNew ) 572 { 573 if ( aOld == FieldUnit::NONE || aNew == FieldUnit::NONE || 574 aOld == FieldUnit::CUSTOM || aNew == FieldUnit::CUSTOM ) 575 { 576 return nVal; 577 } 578 579 sal_uInt16 nOld = 0; 580 sal_uInt16 nNew = 0; 581 582 switch ( aOld ) 583 { 584 case FieldUnit::CM: 585 nOld = 0; break; 586 case FieldUnit::MM: 587 nOld = 1; break; 588 case FieldUnit::INCH: 589 nOld = 2; break; 590 case FieldUnit::POINT: 591 nOld = 3; break; 592 case FieldUnit::PICA: 593 nOld = 4; break; 594 case FieldUnit::TWIP: 595 nOld = 5; break; 596 default: ;//prevent warning 597 } 598 599 switch ( aNew ) 600 { 601 case FieldUnit::CM: 602 nNew = 0; break; 603 case FieldUnit::MM: 604 nNew = 1; break; 605 case FieldUnit::INCH: 606 nNew = 2; break; 607 case FieldUnit::POINT: 608 nNew = 3; break; 609 case FieldUnit::PICA: 610 nNew = 4; break; 611 case FieldUnit::TWIP: 612 nNew = 5; break; 613 default: ;//prevent warning 614 } 615 return ConvertTable[nOld][nNew]( nVal ); 616 } 617 618 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 619
