Update ooo320-m1
[ooovba.git] / xmloff / source / core / xmlehelp.cxx
blobaabd4b21f0c6fd2d5d4dd01a63cece50edaec007
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xmlehelp.cxx,v $
10 * $Revision: 1.17 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
33 #include <limits.h>
34 #include <tools/debug.hxx>
35 #include <tools/bigint.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <vcl/outdev.hxx>
38 #include "xmlehelp.hxx"
40 #ifndef _XMLOFF_XMTOKEN_HXX
41 #include <xmloff/xmltoken.hxx>
42 #endif
44 using ::rtl::OUString;
45 using ::rtl::OUStringBuffer;
47 using namespace ::xmloff::token;
49 void SvXMLExportHelper::AddLength( sal_Int32 nValue, MapUnit eValueUnit,
50 OUStringBuffer& rOut,
51 MapUnit eOutUnit )
53 // the sign is processed seperatly
54 if( nValue < 0 )
56 nValue = -nValue;
57 rOut.append( sal_Unicode('-') );
60 // The new length is (nVal * nMul)/(nDiv*nFac*10)
61 sal_Int32 nMul = 1000;
62 sal_Int32 nDiv = 1;
63 sal_Int32 nFac = 100;
64 enum XMLTokenEnum eUnit = XML_TOKEN_INVALID;
65 switch( eValueUnit )
67 case MAP_TWIP:
68 switch( eOutUnit )
70 case MAP_100TH_MM:
71 case MAP_10TH_MM:
72 DBG_ASSERT( MAP_INCH == eOutUnit,
73 "output unit not supported for twip values" );
74 case MAP_MM:
75 // 0.01mm = 0.57twip (exactly)
76 nMul = 25400; // 25.4 * 1000
77 nDiv = 1440; // 72 * 20;
78 nFac = 100;
79 eUnit = XML_UNIT_MM;
80 break;
82 case MAP_CM:
83 // 0.001cm = 0.57twip (exactly)
84 nMul = 25400; // 2.54 * 10000
85 nDiv = 1440; // 72 * 20;
86 nFac = 1000;
87 eUnit = XML_UNIT_CM;
88 break;
90 case MAP_POINT:
91 // 0.01pt = 0.2twip (exactly)
92 nMul = 1000;
93 nDiv = 20;
94 nFac = 100;
95 eUnit = XML_UNIT_PT;
96 break;
98 case MAP_INCH:
99 default:
100 DBG_ASSERT( MAP_INCH == eOutUnit,
101 "output unit not supported for twip values" );
102 // 0.0001in = 0.144twip (exactly)
103 nMul = 100000;
104 nDiv = 1440; // 72 * 20;
105 nFac = 10000;
106 eUnit = XML_UNIT_INCH;
107 break;
109 break;
111 case MAP_POINT:
112 // 1pt = 1pt (exactly)
113 DBG_ASSERT( MAP_POINT == eOutUnit,
114 "output unit not supported for pt values" );
115 nMul = 10;
116 nDiv = 1;
117 nFac = 1;
118 eUnit = XML_UNIT_PT;
119 break;
120 case MAP_10TH_MM:
121 case MAP_100TH_MM:
123 long nFac2 = (MAP_100TH_MM == eValueUnit) ? 100 : 10;
124 switch( eOutUnit )
126 case MAP_100TH_MM:
127 case MAP_10TH_MM:
128 DBG_ASSERT( MAP_INCH == eOutUnit,
129 "output unit not supported for 1/100mm values" );
130 case MAP_MM:
131 // 0.01mm = 1 mm/100 (exactly)
132 nMul = 10;
133 nDiv = 1;
134 nFac = nFac2;
135 eUnit = XML_UNIT_MM;
136 break;
138 case MAP_CM:
139 // 0.001mm = 1 mm/100 (exactly)
140 nMul = 10;
141 nDiv = 1; // 72 * 20;
142 nFac = 10*nFac2;
143 eUnit = XML_UNIT_CM;
144 break;
146 case MAP_POINT:
147 // 0.01pt = 0.35 mm/100 (exactly)
148 nMul = 72000;
149 nDiv = 2540;
150 nFac = nFac2;
151 eUnit = XML_UNIT_PT;
152 break;
154 case MAP_INCH:
155 default:
156 DBG_ASSERT( MAP_INCH == eOutUnit,
157 "output unit not supported for 1/100mm values" );
158 // 0.0001in = 0.254 mm/100 (exactly)
159 nMul = 100000;
160 nDiv = 2540;
161 nFac = 100*nFac2;
162 eUnit = XML_UNIT_INCH;
163 break;
165 break;
167 default:
168 DBG_ASSERT( 0, "input unit not handled" );
169 break;
173 sal_Int32 nLongVal = 0;
174 BOOL bOutLongVal = TRUE;
175 if( nValue > SAL_MAX_INT32 / nMul )
177 // A big int is required for calculation
178 BigInt nBigVal( nValue );
179 nBigVal *= nMul;
180 nBigVal /= nDiv;
181 nBigVal += 5;
182 nBigVal /= 10;
184 if( nBigVal.IsLong() )
186 // To convert the value into a string a sal_Int32 is sufficient
187 nLongVal = sal_Int32( nBigVal );
189 else
191 BigInt nBigFac( nFac );
192 BigInt nBig10( 10 );
193 rOut.append( (sal_Int32)(nBigVal / nBigFac) );
194 if( !(nBigVal % nBigFac).IsZero() )
196 rOut.append( sal_Unicode('.') );
197 while( nFac > 1 && !(nBigVal % nBigFac).IsZero() )
199 nFac /= 10;
200 nBigFac = nFac;
201 rOut.append( (sal_Int32)((nBigVal / nBigFac) % nBig10 ) );
204 bOutLongVal = FALSE;
207 else
209 nLongVal = nValue * nMul;
210 nLongVal /= nDiv;
211 nLongVal += 5;
212 nLongVal /= 10;
215 if( bOutLongVal )
217 rOut.append( (sal_Int32)(nLongVal / nFac) );
218 if( nFac > 1 && (nLongVal % nFac) != 0 )
220 rOut.append( sal_Unicode('.') );
221 while( nFac > 1 && (nLongVal % nFac) != 0 )
223 nFac /= 10;
224 rOut.append( (sal_Int32)((nLongVal / nFac) % 10) );
229 if( eUnit != XML_TOKEN_INVALID )
230 rOut.append( GetXMLToken(eUnit) );
231 #if 0
232 enum XMLTokenEnum eUnit;
233 sal_Int32 nFac = 1;
234 switch( eOutUnit )
236 case MAP_100TH_MM:
237 nFac *= 10L;
238 case MAP_10TH_MM:
239 nFac *= 10L;
240 eOutUnit = MAP_MM;
241 case MAP_MM:
242 // 0.01mm
243 nFac *= 100L;
244 eUnit = XML_UNIT_MM;
245 break;
247 case MAP_CM:
248 #ifdef EXACT_VALUES
249 // 0.001cm
250 nFac *= 1000L;
251 #else
252 // 0.01cm
253 nFac *= 100L;
254 #endif
255 eUnit = XML_UNIT_CM;
256 break;
258 case MAP_TWIP:
259 case MAP_POINT:
260 #ifdef EXACT_VALUES
261 // 0.01pt
262 nFac *= 100L;
263 #else
264 // 0.1pt
265 nFac *= 10L;
266 #endif
267 eUnit = XML_UNIT_PT;
268 break;
270 case MAP_1000TH_INCH:
271 nFac *= 10L;
272 case MAP_100TH_INCH:
273 nFac *= 10L;
274 case MAP_10TH_INCH:
275 nFac *= 10L;
276 case MAP_INCH:
277 default:
278 eOutUnit = MAP_INCH;
279 #ifdef EXACT_VALUES
280 // 0.0001in
281 nFac *= 10000L;
282 #else
283 // 0.01in
284 nFac *= 100L;
285 #endif
286 eUnit = XML_UNIT_INCH;
287 break;
290 if( eValueUnit != eOutUnit )
291 nValue = OutputDevice::LogicToLogic( nValue, eValueUnit, eOutUnit );
293 rOut.append( nValue / nFac );
294 if( nFac > 1 && (nValue % nFac) != 0 )
296 rOut.append( sal_Unicode('.') );
297 while( nFac > 1 && (nValue % nFac) != 0 )
299 nFac /= 10L;
300 rOut.append( (nValue / nFac) % 10L );
304 rOut.append( GetXMLToken(eUnit) );
305 #endif
309 void SvXMLExportHelper::AddPercentage( sal_Int32 nValue, OUStringBuffer& rOut )
311 rOut.append( nValue );
312 rOut.append( sal_Unicode('%' ) );
315 double SvXMLExportHelper::GetConversionFactor(::rtl::OUStringBuffer& rUnit,
316 const MapUnit eCoreUnit, const MapUnit eDestUnit)
318 double fRetval(1.0);
319 rUnit.setLength(0L);
321 if(eCoreUnit != eDestUnit)
323 enum XMLTokenEnum eUnit = XML_TOKEN_INVALID;
325 switch(eCoreUnit)
327 case MAP_TWIP:
329 switch(eDestUnit)
331 case MAP_100TH_MM:
332 case MAP_10TH_MM:
334 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for twip values");
336 case MAP_MM:
338 // 0.01mm = 0.57twip (exactly)
339 fRetval = ((25400.0 / 1440.0) / 1000.0);
340 eUnit = XML_UNIT_MM;
341 break;
343 case MAP_CM:
345 // 0.001cm = 0.57twip (exactly)
346 fRetval = ((25400.0 / 1440.0) / 10000.0);
347 eUnit = XML_UNIT_CM;
348 break;
350 case MAP_POINT:
352 // 0.01pt = 0.2twip (exactly)
353 fRetval = ((1000.0 / 20.0) / 1000.0);
354 eUnit = XML_UNIT_PT;
355 break;
357 case MAP_INCH:
358 default:
360 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for twip values");
361 // 0.0001in = 0.144twip (exactly)
362 fRetval = ((100000.0 / 1440.0) / 100000.0);
363 eUnit = XML_UNIT_INCH;
364 break;
367 break;
369 case MAP_POINT:
371 switch(eDestUnit)
373 case MAP_MM:
374 // 1mm = 72 / 25.4 pt (exactly)
375 fRetval = ( 25.4 / 72.0 );
376 eUnit = XML_UNIT_MM;
377 break;
379 case MAP_CM:
380 // 1cm = 72 / 2.54 pt (exactly)
381 fRetval = ( 2.54 / 72.0 );
382 eUnit = XML_UNIT_CM;
383 break;
385 case MAP_TWIP:
386 // 1twip = 72 / 1440 pt (exactly)
387 fRetval = 20.0; // 1440.0 / 72.0
388 eUnit = XML_UNIT_PC;
389 break;
391 case MAP_INCH:
392 default:
393 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for pt values");
394 // 1in = 72 pt (exactly)
395 fRetval = ( 1.0 / 72.0 );
396 eUnit = XML_UNIT_INCH;
397 break;
399 break;
401 case MAP_10TH_MM:
403 switch(eDestUnit)
405 case MAP_100TH_MM:
406 case MAP_10TH_MM:
408 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for 1/100mm values");
410 case MAP_MM:
412 // 0.01mm = 1 mm/100 (exactly)
413 fRetval = ((10.0 / 1.0) / 100.0);
414 eUnit = XML_UNIT_MM;
415 break;
417 case MAP_CM:
419 // 0.001mm = 1 mm/100 (exactly)
420 fRetval = ((10.0 / 1.0) / 1000.0);
421 eUnit = XML_UNIT_CM;
422 break;
424 case MAP_POINT:
426 // 0.01pt = 0.35 mm/100 (exactly)
427 fRetval = ((72000.0 / 2540.0) / 100.0);
428 eUnit = XML_UNIT_PT;
429 break;
431 case MAP_INCH:
432 default:
434 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for 1/100mm values");
435 // 0.0001in = 0.254 mm/100 (exactly)
436 fRetval = ((100000.0 / 2540.0) / 10000.0);
437 eUnit = XML_UNIT_INCH;
438 break;
441 break;
443 case MAP_100TH_MM:
445 switch(eDestUnit)
447 case MAP_100TH_MM:
448 case MAP_10TH_MM:
450 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for 1/100mm values");
452 case MAP_MM:
454 // 0.01mm = 1 mm/100 (exactly)
455 fRetval = ((10.0 / 1.0) / 1000.0);
456 eUnit = XML_UNIT_MM;
457 break;
459 case MAP_CM:
461 // 0.001mm = 1 mm/100 (exactly)
462 fRetval = ((10.0 / 1.0) / 10000.0);
463 eUnit = XML_UNIT_CM;
464 break;
466 case MAP_POINT:
468 // 0.01pt = 0.35 mm/100 (exactly)
469 fRetval = ((72000.0 / 2540.0) / 1000.0);
470 eUnit = XML_UNIT_PT;
471 break;
473 case MAP_INCH:
474 default:
476 DBG_ASSERT(MAP_INCH == eDestUnit, "output unit not supported for 1/100mm values");
477 // 0.0001in = 0.254 mm/100 (exactly)
478 fRetval = ((100000.0 / 2540.0) / 100000.0);
479 eUnit = XML_UNIT_INCH;
480 break;
483 break;
485 default:
486 DBG_ERROR("xmloff::SvXMLExportHelper::GetConversionFactor(), illegal eCoreUnit value!");
487 break;
490 if(eUnit != XML_TOKEN_INVALID)
491 rUnit.append(GetXMLToken(eUnit));
494 return fRetval;
497 MapUnit SvXMLExportHelper::GetUnitFromString(const ::rtl::OUString& rString, MapUnit eDefaultUnit)
499 sal_Int32 nPos = 0L;
500 sal_Int32 nLen = rString.getLength();
501 MapUnit eRetUnit = eDefaultUnit;
503 // skip white space
504 while( nPos < nLen && sal_Unicode(' ') == rString[nPos] )
505 nPos++;
507 // skip negative
508 if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
509 nPos++;
511 // skip number
512 while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] )
513 nPos++;
515 if( nPos < nLen && sal_Unicode('.') == rString[nPos] )
517 nPos++;
518 while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] )
519 nPos++;
522 // skip white space
523 while( nPos < nLen && sal_Unicode(' ') == rString[nPos] )
524 nPos++;
526 if( nPos < nLen )
528 switch(rString[nPos])
530 case sal_Unicode('%') :
532 eRetUnit = MAP_RELATIVE;
533 break;
535 case sal_Unicode('c'):
536 case sal_Unicode('C'):
538 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m')
539 || rString[nPos+1] == sal_Unicode('M')))
540 eRetUnit = MAP_CM;
541 break;
543 case sal_Unicode('e'):
544 case sal_Unicode('E'):
546 // CSS1_EMS or CSS1_EMX later
547 break;
549 case sal_Unicode('i'):
550 case sal_Unicode('I'):
552 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('n')
553 || rString[nPos+1] == sal_Unicode('n')))
554 eRetUnit = MAP_INCH;
555 break;
557 case sal_Unicode('m'):
558 case sal_Unicode('M'):
560 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m')
561 || rString[nPos+1] == sal_Unicode('M')))
562 eRetUnit = MAP_MM;
563 break;
565 case sal_Unicode('p'):
566 case sal_Unicode('P'):
568 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('t')
569 || rString[nPos+1] == sal_Unicode('T')))
570 eRetUnit = MAP_POINT;
571 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('c')
572 || rString[nPos+1] == sal_Unicode('C')))
573 eRetUnit = MAP_TWIP;
574 break;
579 return eRetUnit;