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
AddLength(sal_Int32 nValue,MapUnit eValueUnit,OUStringBuffer & rOut,MapUnit eOutUnit)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
AddPercentage(sal_Int32 nValue,OUStringBuffer & rOut)225 void SvXMLExportHelper::AddPercentage( sal_Int32 nValue, OUStringBuffer& rOut )
226 {
227 rOut.append( nValue );
228 rOut.append( sal_Unicode('%' ) );
229 }
230
GetConversionFactor(::rtl::OUStringBuffer & rUnit,const MapUnit eCoreUnit,const MapUnit eDestUnit)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
GetUnitFromString(const::rtl::OUString & rString,MapUnit eDefaultUnit)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