Line data Source code
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 :
21 : #include <xmloff/xmluconv.hxx>
22 :
23 : #include <com/sun/star/util/DateTime.hpp>
24 : #include <com/sun/star/util/Date.hpp>
25 : #include <tools/debug.hxx>
26 : #include <rtl/ustrbuf.hxx>
27 : #include <xmloff/xmlement.hxx>
28 : #include <xmloff/xmltoken.hxx>
29 : #include <rtl/math.hxx>
30 :
31 : #include <tools/date.hxx>
32 : #include <tools/time.hxx>
33 : #include <tools/fldunit.hxx>
34 :
35 : #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
36 : #include <com/sun/star/style/NumberingType.hpp>
37 : #include <com/sun/star/text/DefaultNumberingProvider.hpp>
38 : #include <com/sun/star/text/XDefaultNumberingProvider.hpp>
39 : #include <com/sun/star/text/XNumberingTypeInfo.hpp>
40 : #include <com/sun/star/i18n/CharacterClassification.hpp>
41 : #include <com/sun/star/i18n/UnicodeType.hpp>
42 : #include <basegfx/vector/b3dvector.hxx>
43 : #include <comphelper/processfactory.hxx>
44 :
45 : #include <sax/tools/converter.hxx>
46 :
47 :
48 : using namespace com::sun::star;
49 : using namespace com::sun::star::uno;
50 : using namespace com::sun::star::lang;
51 : using namespace com::sun::star::text;
52 : using namespace com::sun::star::style;
53 : using namespace ::com::sun::star::i18n;
54 : using namespace ::xmloff::token;
55 :
56 :
57 : const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 11;
58 : #define XML_NULLDATE "NullDate"
59 :
60 10620 : struct SvXMLUnitConverter::Impl
61 : {
62 : sal_Int16 m_eCoreMeasureUnit; /*css::util::MeasureUnit*/
63 : sal_Int16 m_eXMLMeasureUnit; /*css::util::MeasureUnit*/
64 : util::Date m_aNullDate;
65 : mutable uno::Reference< text::XNumberingTypeInfo > m_xNumTypeInfo;
66 : mutable uno::Reference< i18n::XCharacterClassification > m_xCharClass;
67 : uno::Reference< uno::XComponentContext > m_xContext;
68 :
69 10620 : Impl(uno::Reference<uno::XComponentContext> const& xContext,
70 : sal_Int16 const eCoreMeasureUnit,
71 : sal_Int16 const eXMLMeasureUnit)
72 : : m_eCoreMeasureUnit(eCoreMeasureUnit)
73 : , m_eXMLMeasureUnit(eXMLMeasureUnit)
74 : , m_aNullDate(30, 12, 1899)
75 10620 : , m_xContext(xContext)
76 : {
77 : OSL_ENSURE( m_xContext.is(), "got no service manager" );
78 10620 : }
79 :
80 : void createNumTypeInfo() const;
81 : };
82 :
83 :
84 0 : void SvXMLUnitConverter::Impl::createNumTypeInfo() const
85 : {
86 0 : Reference<XDefaultNumberingProvider> xDefNum = DefaultNumberingProvider::create(m_xContext);
87 0 : m_xNumTypeInfo = Reference<XNumberingTypeInfo>(xDefNum, uno::UNO_QUERY);
88 0 : }
89 :
90 : const uno::Reference< text::XNumberingTypeInfo >&
91 0 : SvXMLUnitConverter::getNumTypeInfo() const
92 : {
93 0 : if (!m_pImpl->m_xNumTypeInfo.is())
94 : {
95 0 : m_pImpl->createNumTypeInfo();
96 : }
97 0 : return m_pImpl->m_xNumTypeInfo;
98 : }
99 :
100 402 : void SvXMLUnitConverter::SetCoreMeasureUnit(sal_Int16 const eCoreMeasureUnit/*css::util::MeasureUnit*/)
101 : {
102 402 : m_pImpl->m_eCoreMeasureUnit = eCoreMeasureUnit;
103 402 : }
104 :
105 402 : void SvXMLUnitConverter::SetXMLMeasureUnit(sal_Int16 const eXMLMeasureUnit/*css::util::MeasureUnit*/)
106 : {
107 402 : m_pImpl->m_eXMLMeasureUnit = eXMLMeasureUnit;
108 402 : }
109 :
110 472 : sal_Int16 SvXMLUnitConverter::GetXMLMeasureUnit() const
111 : {
112 472 : return m_pImpl->m_eXMLMeasureUnit;
113 : }
114 :
115 : /** constructs a SvXMLUnitConverter. The core measure unit is the
116 : default unit for numerical measures, the XML measure unit is
117 : the default unit for textual measures
118 : */
119 :
120 10620 : SvXMLUnitConverter::SvXMLUnitConverter(
121 : const uno::Reference<uno::XComponentContext>& xContext,
122 : sal_Int16 const eCoreMeasureUnit,
123 : sal_Int16 const eXMLMeasureUnit)
124 10620 : : m_pImpl(new Impl(xContext, eCoreMeasureUnit, eXMLMeasureUnit))
125 : {
126 10620 : }
127 :
128 21240 : SvXMLUnitConverter::~SvXMLUnitConverter()
129 : {
130 21240 : }
131 :
132 230 : sal_Int16 SvXMLUnitConverter::GetMeasureUnit(FieldUnit const nFieldUnit)
133 : {
134 230 : sal_Int16 eUnit = util::MeasureUnit::INCH;
135 230 : switch( nFieldUnit )
136 : {
137 : case FUNIT_MM:
138 0 : eUnit = util::MeasureUnit::MM;
139 0 : break;
140 : case FUNIT_CM:
141 : case FUNIT_M:
142 : case FUNIT_KM:
143 0 : eUnit = util::MeasureUnit::CM;
144 0 : break;
145 : case FUNIT_TWIP:
146 0 : eUnit = util::MeasureUnit::TWIP;
147 0 : break;
148 : case FUNIT_POINT:
149 : case FUNIT_PICA:
150 0 : eUnit = util::MeasureUnit::POINT;
151 0 : break;
152 : case FUNIT_100TH_MM:
153 0 : eUnit = util::MeasureUnit::MM_100TH;
154 0 : break;
155 : case FUNIT_INCH:
156 230 : eUnit = util::MeasureUnit::INCH;
157 230 : break;
158 : default:
159 : assert(false);
160 0 : break;
161 : }
162 230 : return eUnit;
163 : }
164 :
165 : /** convert string to measure using optional min and max values*/
166 86166 : bool SvXMLUnitConverter::convertMeasureToCore( sal_Int32& nValue,
167 : const OUString& rString,
168 : sal_Int32 nMin, sal_Int32 nMax ) const
169 : {
170 : return ::sax::Converter::convertMeasure( nValue, rString,
171 86166 : m_pImpl->m_eCoreMeasureUnit,
172 86166 : nMin, nMax );
173 : }
174 :
175 : /** convert measure to string */
176 22092 : void SvXMLUnitConverter::convertMeasureToXML( OUStringBuffer& rString,
177 : sal_Int32 nMeasure ) const
178 : {
179 : ::sax::Converter::convertMeasure( rString, nMeasure,
180 22092 : m_pImpl->m_eCoreMeasureUnit,
181 44184 : m_pImpl->m_eXMLMeasureUnit );
182 22092 : }
183 :
184 : /** convert string to enum using given enum map, if the enum is
185 : not found in the map, this method will return false
186 : */
187 3314 : bool SvXMLUnitConverter::convertEnum( sal_uInt16& rEnum,
188 : const OUString& rValue,
189 : const SvXMLEnumStringMapEntry *pMap )
190 : {
191 43206 : while( pMap->pName )
192 : {
193 39892 : if( rValue.equalsAsciiL( pMap->pName, pMap->nNameLength ) )
194 : {
195 3314 : rEnum = pMap->nValue;
196 3314 : return true;
197 : }
198 36578 : ++pMap;
199 : }
200 :
201 0 : return false;
202 : }
203 :
204 : /** convert string to enum using given token map, if the enum is
205 : not found in the map, this method will return false */
206 62345 : bool SvXMLUnitConverter::convertEnum(
207 : sal_uInt16& rEnum,
208 : const OUString& rValue,
209 : const SvXMLEnumMapEntry *pMap )
210 : {
211 308168 : while( pMap->eToken != XML_TOKEN_INVALID )
212 : {
213 238719 : if( IsXMLToken( rValue, pMap->eToken ) )
214 : {
215 55241 : rEnum = pMap->nValue;
216 55241 : return true;
217 : }
218 183478 : ++pMap;
219 : }
220 7104 : return false;
221 : }
222 :
223 : /** convert enum to string using given token map with an optional
224 : default token. If the enum is not found in the map,
225 : this method will either use the given default or return
226 : false if no default is set */
227 34566 : bool SvXMLUnitConverter::convertEnum(
228 : OUStringBuffer& rBuffer,
229 : unsigned int nValue,
230 : const SvXMLEnumMapEntry *pMap,
231 : enum XMLTokenEnum eDefault)
232 : {
233 34566 : enum XMLTokenEnum eTok = eDefault;
234 :
235 101088 : while( pMap->eToken != XML_TOKEN_INVALID )
236 : {
237 66506 : if( pMap->nValue == nValue )
238 : {
239 34550 : eTok = pMap->eToken;
240 34550 : break;
241 : }
242 31956 : ++pMap;
243 : }
244 :
245 : // the map may have contained XML_TOKEN_INVALID
246 34566 : if( eTok == XML_TOKEN_INVALID )
247 4 : eTok = eDefault;
248 :
249 34566 : if( eTok != XML_TOKEN_INVALID )
250 34562 : rBuffer.append( GetXMLToken(eTok) );
251 :
252 34566 : return (eTok != XML_TOKEN_INVALID);
253 : }
254 :
255 5408 : static int lcl_gethex( int nChar )
256 : {
257 5408 : if( nChar >= '0' && nChar <= '9' )
258 3998 : return nChar - '0';
259 1410 : else if( nChar >= 'a' && nChar <= 'f' )
260 1410 : return nChar - 'a' + 10;
261 0 : else if( nChar >= 'A' && nChar <= 'F' )
262 0 : return nChar - 'A' + 10;
263 : else
264 0 : return 0;
265 : }
266 :
267 : static sal_Char aHexTab[] = "0123456789abcdef";
268 :
269 :
270 : /** convert double number to string (using ::rtl::math) */
271 620 : void SvXMLUnitConverter::convertDouble(OUStringBuffer& rBuffer,
272 : double fNumber, bool bWriteUnits) const
273 : {
274 : ::sax::Converter::convertDouble(rBuffer, fNumber,
275 620 : bWriteUnits, m_pImpl->m_eCoreMeasureUnit, m_pImpl->m_eXMLMeasureUnit);
276 620 : }
277 :
278 : /** convert string to double number (using ::rtl::math) */
279 306 : bool SvXMLUnitConverter::convertDouble(double& rValue,
280 : const OUString& rString, bool bLookForUnits) const
281 : {
282 306 : if(bLookForUnits)
283 : {
284 : sal_Int16 const eSrcUnit = ::sax::Converter::GetUnitFromString(
285 306 : rString, m_pImpl->m_eCoreMeasureUnit);
286 :
287 : return ::sax::Converter::convertDouble(rValue, rString,
288 306 : eSrcUnit, m_pImpl->m_eCoreMeasureUnit);
289 : }
290 : else
291 : {
292 0 : return ::sax::Converter::convertDouble(rValue, rString);
293 : }
294 : }
295 :
296 : /** get the Null Date of the XModel and set it to the UnitConverter */
297 60 : bool SvXMLUnitConverter::setNullDate(const com::sun::star::uno::Reference <com::sun::star::frame::XModel>& xModel)
298 : {
299 60 : com::sun::star::uno::Reference <com::sun::star::util::XNumberFormatsSupplier> xNumberFormatsSupplier (xModel, com::sun::star::uno::UNO_QUERY);
300 60 : if (xNumberFormatsSupplier.is())
301 : {
302 60 : const com::sun::star::uno::Reference <com::sun::star::beans::XPropertySet> xPropertySet = xNumberFormatsSupplier->getNumberFormatSettings();
303 60 : return xPropertySet.is() && (xPropertySet->getPropertyValue(OUString(XML_NULLDATE)) >>= m_pImpl->m_aNullDate);
304 : }
305 0 : return false;
306 : }
307 :
308 : /** convert double to ISO Date Time String */
309 4 : void SvXMLUnitConverter::convertDateTime(OUStringBuffer& rBuffer,
310 : const double& fDateTime, bool const bAddTimeIf0AM)
311 : {
312 4 : convertDateTime(rBuffer, fDateTime, m_pImpl->m_aNullDate, bAddTimeIf0AM);
313 4 : }
314 :
315 : /** convert ISO Date Time String to double */
316 532 : bool SvXMLUnitConverter::convertDateTime(double& fDateTime,
317 : const OUString& rString)
318 : {
319 532 : return convertDateTime(fDateTime, rString, m_pImpl->m_aNullDate);
320 : }
321 :
322 : /** convert double to ISO Date Time String */
323 12 : void SvXMLUnitConverter::convertDateTime( OUStringBuffer& rBuffer,
324 : const double& fDateTime,
325 : const com::sun::star::util::Date& aTempNullDate,
326 : bool bAddTimeIf0AM )
327 : {
328 12 : double fValue = fDateTime;
329 12 : sal_Int32 nValue = static_cast <sal_Int32> (::rtl::math::approxFloor (fValue));
330 12 : Date aDate (aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
331 12 : aDate += nValue;
332 12 : fValue -= nValue;
333 : double fCount;
334 12 : if (nValue > 0)
335 4 : fCount = ::rtl::math::approxFloor (log10((double)nValue)) + 1;
336 8 : else if (nValue < 0)
337 0 : fCount = ::rtl::math::approxFloor (log10((double)(nValue * -1))) + 1;
338 : else
339 8 : fCount = 0.0;
340 12 : sal_Int16 nCount = sal_Int16(fCount);
341 12 : bool bHasTime(false);
342 12 : double fHoursValue = 0;
343 12 : double fMinsValue = 0;
344 12 : double fSecsValue = 0;
345 12 : double f100SecsValue = 0;
346 12 : if (fValue > 0.0)
347 : {
348 0 : bHasTime = true;
349 0 : fValue *= 24;
350 0 : fHoursValue = ::rtl::math::approxFloor (fValue);
351 0 : fValue -= fHoursValue;
352 0 : fValue *= 60;
353 0 : fMinsValue = ::rtl::math::approxFloor (fValue);
354 0 : fValue -= fMinsValue;
355 0 : fValue *= 60;
356 0 : fSecsValue = ::rtl::math::approxFloor (fValue);
357 0 : fValue -= fSecsValue;
358 0 : if (fValue > 0.0)
359 0 : f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - nCount);
360 : else
361 0 : f100SecsValue = 0.0;
362 :
363 0 : if (f100SecsValue == 1.0)
364 : {
365 0 : f100SecsValue = 0.0;
366 0 : fSecsValue += 1.0;
367 : }
368 0 : if (fSecsValue >= 60.0)
369 : {
370 0 : fSecsValue -= 60.0;
371 0 : fMinsValue += 1.0;
372 : }
373 0 : if (fMinsValue >= 60.0)
374 : {
375 0 : fMinsValue -= 60.0;
376 0 : fHoursValue += 1.0;
377 : }
378 0 : if (fHoursValue >= 24.0)
379 : {
380 0 : fHoursValue -= 24.0;
381 0 : aDate += 1;
382 : }
383 : }
384 12 : sal_uInt16 nTemp = aDate.GetYear();
385 12 : if (nTemp < 1000)
386 0 : rBuffer.append( '0');
387 12 : if (nTemp < 100)
388 0 : rBuffer.append( '0');
389 12 : if (nTemp < 10)
390 0 : rBuffer.append( '0');
391 12 : rBuffer.append( sal_Int32( nTemp));
392 12 : rBuffer.append( '-');
393 12 : nTemp = aDate.GetMonth();
394 12 : if (nTemp < 10)
395 10 : rBuffer.append( '0');
396 12 : rBuffer.append( sal_Int32( nTemp));
397 12 : rBuffer.append( '-');
398 12 : nTemp = aDate.GetDay();
399 12 : if (nTemp < 10)
400 12 : rBuffer.append( '0');
401 12 : rBuffer.append( sal_Int32( nTemp));
402 12 : if(bHasTime || bAddTimeIf0AM)
403 : {
404 4 : rBuffer.append( 'T');
405 4 : if (fHoursValue < 10)
406 4 : rBuffer.append( '0');
407 4 : rBuffer.append( sal_Int32( fHoursValue));
408 4 : rBuffer.append( ':');
409 4 : if (fMinsValue < 10)
410 4 : rBuffer.append( '0');
411 4 : rBuffer.append( sal_Int32( fMinsValue));
412 4 : rBuffer.append( ':');
413 4 : if (fSecsValue < 10)
414 4 : rBuffer.append( '0');
415 4 : rBuffer.append( sal_Int32( fSecsValue));
416 4 : if (f100SecsValue > 0.0)
417 : {
418 : OUString a100th( ::rtl::math::doubleToUString( fValue,
419 : rtl_math_StringFormat_F,
420 0 : XML_MAXDIGITSCOUNT_TIME - nCount, '.', true));
421 0 : if ( a100th.getLength() > 2 )
422 : {
423 0 : rBuffer.append( '.');
424 0 : rBuffer.append( a100th.copy( 2 ) ); // strip 0.
425 0 : }
426 : }
427 : }
428 12 : }
429 :
430 : /** convert ISO Date Time String to double */
431 532 : bool SvXMLUnitConverter::convertDateTime( double& fDateTime,
432 : const OUString& rString, const com::sun::star::util::Date& aTempNullDate)
433 : {
434 532 : com::sun::star::util::DateTime aDateTime;
435 532 : bool bSuccess = ::sax::Converter::parseDateTime(aDateTime, 0, rString);
436 :
437 532 : if (bSuccess)
438 : {
439 530 : const Date aTmpNullDate(aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
440 530 : const Date aTempDate((sal_uInt16)aDateTime.Day, (sal_uInt16)aDateTime.Month, (sal_uInt16)aDateTime.Year);
441 530 : const sal_Int32 nTage = aTempDate - aTmpNullDate;
442 530 : double fTempDateTime = nTage;
443 530 : double Hour = aDateTime.Hours;
444 530 : double Min = aDateTime.Minutes;
445 530 : double Sec = aDateTime.Seconds;
446 530 : double NanoSec = aDateTime.NanoSeconds;
447 530 : fTempDateTime += Hour / ::tools::Time::hourPerDay;
448 530 : fTempDateTime += Min / ::tools::Time::minutePerDay;
449 530 : fTempDateTime += Sec / ::tools::Time::secondPerDay;
450 530 : fTempDateTime += NanoSec / ::tools::Time::nanoSecPerDay;
451 530 : fDateTime = fTempDateTime;
452 : }
453 532 : return bSuccess;
454 : }
455 :
456 :
457 8484 : SvXMLTokenEnumerator::SvXMLTokenEnumerator( const OUString& rString, sal_Unicode cSeparator /* = ' ' */ )
458 8484 : : maTokenString( rString ), mnNextTokenPos(0), mcSeparator( cSeparator )
459 : {
460 8484 : }
461 :
462 20970 : bool SvXMLTokenEnumerator::getNextToken( OUString& rToken )
463 : {
464 20970 : if( -1 == mnNextTokenPos )
465 4148 : return false;
466 :
467 16822 : int nTokenEndPos = maTokenString.indexOf( mcSeparator, mnNextTokenPos );
468 16822 : if( nTokenEndPos != -1 )
469 : {
470 20712 : rToken = maTokenString.copy( mnNextTokenPos,
471 10356 : nTokenEndPos - mnNextTokenPos );
472 10356 : mnNextTokenPos = nTokenEndPos + 1;
473 :
474 : // if the mnNextTokenPos is at the end of the string, we have
475 : // to deliver an empty token
476 10356 : if( mnNextTokenPos > maTokenString.getLength() )
477 0 : mnNextTokenPos = -1;
478 : }
479 : else
480 : {
481 6466 : rToken = maTokenString.copy( mnNextTokenPos );
482 6466 : mnNextTokenPos = -1;
483 : }
484 :
485 16822 : return true;
486 : }
487 :
488 706 : static bool lcl_getPositions(const OUString& _sValue,OUString& _rContentX,OUString& _rContentY,OUString& _rContentZ)
489 : {
490 706 : if(_sValue.isEmpty() || _sValue[0] != '(')
491 0 : return false;
492 :
493 706 : sal_Int32 nPos(1L);
494 706 : sal_Int32 nFound = _sValue.indexOf(' ', nPos);
495 :
496 706 : if(nFound == -1 || nFound <= nPos)
497 0 : return false;
498 :
499 706 : _rContentX = _sValue.copy(nPos, nFound - nPos);
500 :
501 706 : nPos = nFound + 1;
502 706 : nFound = _sValue.indexOf(' ', nPos);
503 :
504 706 : if(nFound == -1 || nFound <= nPos)
505 0 : return false;
506 :
507 706 : _rContentY = _sValue.copy(nPos, nFound - nPos);
508 :
509 706 : nPos = nFound + 1;
510 706 : nFound = _sValue.indexOf(')', nPos);
511 :
512 706 : if(nFound == -1 || nFound <= nPos)
513 0 : return false;
514 :
515 706 : _rContentZ = _sValue.copy(nPos, nFound - nPos);
516 706 : return true;
517 :
518 : }
519 : /** convert string to ::basegfx::B3DVector */
520 704 : bool SvXMLUnitConverter::convertB3DVector( ::basegfx::B3DVector& rVector, const OUString& rValue )
521 : {
522 1408 : OUString aContentX,aContentY,aContentZ;
523 704 : if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) )
524 0 : return false;
525 :
526 : rtl_math_ConversionStatus eStatus;
527 :
528 : rVector.setX(::rtl::math::stringToDouble(aContentX, '.',
529 704 : ',', &eStatus, NULL));
530 :
531 704 : if( eStatus != rtl_math_ConversionStatus_Ok )
532 0 : return false;
533 :
534 : rVector.setY(::rtl::math::stringToDouble(aContentY, '.',
535 704 : ',', &eStatus, NULL));
536 :
537 704 : if( eStatus != rtl_math_ConversionStatus_Ok )
538 0 : return false;
539 :
540 : rVector.setZ(::rtl::math::stringToDouble(aContentZ, '.',
541 704 : ',', &eStatus, NULL));
542 :
543 :
544 1408 : return ( eStatus == rtl_math_ConversionStatus_Ok );
545 : }
546 :
547 : /** convert ::basegfx::B3DVector to string */
548 2244 : void SvXMLUnitConverter::convertB3DVector( OUStringBuffer &rBuffer, const ::basegfx::B3DVector& rVector )
549 : {
550 2244 : rBuffer.append('(');
551 2244 : ::sax::Converter::convertDouble(rBuffer, rVector.getX());
552 2244 : rBuffer.append(' ');
553 2244 : ::sax::Converter::convertDouble(rBuffer, rVector.getY());
554 2244 : rBuffer.append(' ');
555 2244 : ::sax::Converter::convertDouble(rBuffer, rVector.getZ());
556 2244 : rBuffer.append(')');
557 2244 : }
558 :
559 : /** convert string to Position3D */
560 2 : bool SvXMLUnitConverter::convertPosition3D( drawing::Position3D& rPosition,
561 : const OUString& rValue )
562 : {
563 4 : OUString aContentX,aContentY,aContentZ;
564 2 : if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) )
565 0 : return false;
566 :
567 2 : if ( !convertDouble( rPosition.PositionX, aContentX, true ) )
568 0 : return false;
569 2 : if ( !convertDouble( rPosition.PositionY, aContentY, true ) )
570 0 : return false;
571 4 : return convertDouble( rPosition.PositionZ, aContentZ, true );
572 : }
573 :
574 : /** convert Position3D to string */
575 0 : void SvXMLUnitConverter::convertPosition3D( OUStringBuffer &rBuffer,
576 : const drawing::Position3D& rPosition )
577 : {
578 0 : rBuffer.append( '(' );
579 0 : convertDouble( rBuffer, rPosition.PositionX, true );
580 0 : rBuffer.append( ' ' );
581 0 : convertDouble( rBuffer, rPosition.PositionY, true );
582 0 : rBuffer.append( ' ' );
583 0 : convertDouble( rBuffer, rPosition.PositionZ, true );
584 0 : rBuffer.append( ')' );
585 0 : }
586 :
587 5948 : bool SvXMLUnitConverter::convertNumFormat(
588 : sal_Int16& rType,
589 : const OUString& rNumFmt,
590 : const OUString& rNumLetterSync,
591 : bool bNumberNone ) const
592 : {
593 5948 : bool bRet = true;
594 5948 : bool bExt = false;
595 :
596 5948 : sal_Int32 nLen = rNumFmt.getLength();
597 5948 : if( 0 == nLen )
598 : {
599 3594 : if( bNumberNone )
600 3594 : rType = NumberingType::NUMBER_NONE;
601 : else
602 0 : bRet = false;
603 : }
604 2354 : else if( 1 == nLen )
605 : {
606 2354 : switch( rNumFmt[0] )
607 : {
608 1816 : case '1': rType = NumberingType::ARABIC; break;
609 114 : case 'a': rType = NumberingType::CHARS_LOWER_LETTER; break;
610 10 : case 'A': rType = NumberingType::CHARS_UPPER_LETTER; break;
611 412 : case 'i': rType = NumberingType::ROMAN_LOWER; break;
612 2 : case 'I': rType = NumberingType::ROMAN_UPPER; break;
613 0 : default: bExt = true; break;
614 : }
615 2354 : if( !bExt && IsXMLToken( rNumLetterSync, XML_TRUE ) )
616 : {
617 0 : switch( rType )
618 : {
619 : case NumberingType::CHARS_LOWER_LETTER:
620 0 : rType = NumberingType::CHARS_LOWER_LETTER_N;
621 0 : break;
622 : case NumberingType::CHARS_UPPER_LETTER:
623 0 : rType = NumberingType::CHARS_UPPER_LETTER_N;
624 0 : break;
625 : }
626 : }
627 : }
628 : else
629 : {
630 0 : bExt = true;
631 : }
632 5948 : if( bExt )
633 : {
634 0 : Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo();
635 0 : if( xInfo.is() && xInfo->hasNumberingType( rNumFmt ) )
636 : {
637 0 : rType = xInfo->getNumberingType( rNumFmt );
638 : }
639 : else
640 : {
641 0 : rType = NumberingType::ARABIC;
642 0 : }
643 : }
644 :
645 5948 : return bRet;
646 : }
647 :
648 2652 : void SvXMLUnitConverter::convertNumFormat( OUStringBuffer& rBuffer,
649 : sal_Int16 nType ) const
650 : {
651 2652 : enum XMLTokenEnum eFormat = XML_TOKEN_INVALID;
652 2652 : switch( nType )
653 : {
654 1020 : case NumberingType::CHARS_UPPER_LETTER: eFormat = XML_A_UPCASE; break;
655 192 : case NumberingType::CHARS_LOWER_LETTER: eFormat = XML_A; break;
656 0 : case NumberingType::ROMAN_UPPER: eFormat = XML_I_UPCASE; break;
657 250 : case NumberingType::ROMAN_LOWER: eFormat = XML_I; break;
658 486 : case NumberingType::ARABIC: eFormat = XML_1; break;
659 0 : case NumberingType::CHARS_UPPER_LETTER_N: eFormat = XML_A_UPCASE; break;
660 0 : case NumberingType::CHARS_LOWER_LETTER_N: eFormat = XML_A; break;
661 704 : case NumberingType::NUMBER_NONE: eFormat = XML__EMPTY; break;
662 :
663 : case NumberingType::CHAR_SPECIAL:
664 : case NumberingType::PAGE_DESCRIPTOR:
665 : case NumberingType::BITMAP:
666 : DBG_ASSERT( eFormat != XML_TOKEN_INVALID, "invalid number format" );
667 0 : break;
668 : default:
669 0 : break;
670 : }
671 :
672 2652 : if( eFormat != XML_TOKEN_INVALID )
673 : {
674 2652 : rBuffer.append( GetXMLToken(eFormat) );
675 : }
676 : else
677 : {
678 0 : Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo();
679 0 : if( xInfo.is() )
680 0 : rBuffer.append( xInfo->getNumberingIdentifier( nType ) );
681 : }
682 2652 : }
683 :
684 2652 : void SvXMLUnitConverter::convertNumLetterSync( OUStringBuffer& rBuffer,
685 : sal_Int16 nType ) const
686 : {
687 2652 : enum XMLTokenEnum eSync = XML_TOKEN_INVALID;
688 2652 : switch( nType )
689 : {
690 : case NumberingType::CHARS_UPPER_LETTER:
691 : case NumberingType::CHARS_LOWER_LETTER:
692 : case NumberingType::ROMAN_UPPER:
693 : case NumberingType::ROMAN_LOWER:
694 : case NumberingType::ARABIC:
695 : case NumberingType::NUMBER_NONE:
696 2652 : break;
697 :
698 : case NumberingType::CHARS_UPPER_LETTER_N:
699 : case NumberingType::CHARS_LOWER_LETTER_N:
700 0 : eSync = XML_TRUE;
701 0 : break;
702 :
703 : case NumberingType::CHAR_SPECIAL:
704 : case NumberingType::PAGE_DESCRIPTOR:
705 : case NumberingType::BITMAP:
706 : DBG_ASSERT( eSync != XML_TOKEN_INVALID, "invalid number format" );
707 0 : break;
708 : }
709 2652 : if( eSync != XML_TOKEN_INVALID )
710 0 : rBuffer.append( GetXMLToken(eSync) );
711 2652 : }
712 :
713 128 : void SvXMLUnitConverter::convertPropertySet(uno::Sequence<beans::PropertyValue>& rProps,
714 : const uno::Reference<beans::XPropertySet>& aProperties)
715 : {
716 128 : uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = aProperties->getPropertySetInfo();
717 128 : if (xPropertySetInfo.is())
718 : {
719 128 : uno::Sequence< beans::Property > aProps = xPropertySetInfo->getProperties();
720 128 : const sal_Int32 nCount(aProps.getLength());
721 128 : if (nCount)
722 : {
723 128 : rProps.realloc(nCount);
724 128 : beans::PropertyValue* pProps = rProps.getArray();
725 7032 : for (sal_Int32 i = 0; i < nCount; i++, ++pProps)
726 : {
727 6904 : pProps->Name = aProps[i].Name;
728 6904 : pProps->Value = aProperties->getPropertyValue(aProps[i].Name);
729 : }
730 128 : }
731 128 : }
732 128 : }
733 :
734 266 : void SvXMLUnitConverter::convertPropertySet(uno::Reference<beans::XPropertySet>& rProperties,
735 : const uno::Sequence<beans::PropertyValue>& aProps)
736 : {
737 266 : sal_Int32 nCount(aProps.getLength());
738 266 : if (nCount)
739 : {
740 266 : uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = rProperties->getPropertySetInfo();
741 266 : if (xPropertySetInfo.is())
742 : {
743 7576 : for (sal_Int32 i = 0; i < nCount; i++)
744 : {
745 7310 : if (xPropertySetInfo->hasPropertyByName(aProps[i].Name))
746 7310 : rProperties->setPropertyValue(aProps[i].Name, aProps[i].Value);
747 : }
748 266 : }
749 : }
750 266 : }
751 :
752 :
753 5114 : OUString SvXMLUnitConverter::encodeStyleName(
754 : const OUString& rName,
755 : bool *pEncoded ) const
756 : {
757 5114 : if( pEncoded )
758 1930 : *pEncoded = false;
759 :
760 5114 : sal_Int32 nLen = rName.getLength();
761 5114 : OUStringBuffer aBuffer( nLen );
762 :
763 47022 : for( sal_Int32 i = 0; i < nLen; i++ )
764 : {
765 41908 : sal_Unicode c = rName[i];
766 41908 : bool bValidChar = false;
767 41908 : if( c < 0x00ffU )
768 : {
769 : bValidChar =
770 36830 : (c >= 0x0041 && c <= 0x005a) ||
771 31432 : (c >= 0x0061 && c <= 0x007a) ||
772 22 : (c >= 0x00c0 && c <= 0x00d6) ||
773 22 : (c >= 0x00d8 && c <= 0x00f6) ||
774 80986 : (c >= 0x00f8 && c <= 0x00ff) ||
775 4374 : ( i > 0 && ( (c >= 0x0030 && c <= 0x0039) ||
776 43002 : c == 0x00b7 || c == '-' || c == '.') );
777 : }
778 : else
779 : {
780 600 : if( (c >= 0xf900U && c <= 0xfffeU) ||
781 0 : (c >= 0x20ddU && c <= 0x20e0U))
782 : {
783 0 : bValidChar = false;
784 : }
785 600 : else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 ||
786 600 : c == 0x06e5 || c == 0x06e6 )
787 : {
788 0 : bValidChar = true;
789 : }
790 600 : else if( c == 0x0387 )
791 : {
792 0 : bValidChar = i > 0;
793 : }
794 : else
795 : {
796 600 : if (!m_pImpl->m_xCharClass.is())
797 : {
798 4 : this->m_pImpl->m_xCharClass = CharacterClassification::create( m_pImpl->m_xContext );
799 : }
800 600 : sal_Int16 nType = m_pImpl->m_xCharClass->getType(rName, i);
801 :
802 600 : switch( nType )
803 : {
804 : case UnicodeType::UPPERCASE_LETTER: // Lu
805 : case UnicodeType::LOWERCASE_LETTER: // Ll
806 : case UnicodeType::TITLECASE_LETTER: // Lt
807 : case UnicodeType::OTHER_LETTER: // Lo
808 : case UnicodeType::LETTER_NUMBER: // Nl
809 600 : bValidChar = true;
810 600 : break;
811 : case UnicodeType::NON_SPACING_MARK: // Ms
812 : case UnicodeType::ENCLOSING_MARK: // Me
813 : case UnicodeType::COMBINING_SPACING_MARK: //Mc
814 : case UnicodeType::MODIFIER_LETTER: // Lm
815 : case UnicodeType::DECIMAL_DIGIT_NUMBER: // Nd
816 0 : bValidChar = i > 0;
817 0 : break;
818 : }
819 : }
820 : }
821 41908 : if( bValidChar )
822 : {
823 40278 : aBuffer.append( c );
824 : }
825 : else
826 : {
827 1630 : aBuffer.append( '_' );
828 1630 : if( c > 0x0fff )
829 : aBuffer.append( static_cast< sal_Unicode >(
830 0 : aHexTab[ (c >> 12) & 0x0f ] ) );
831 1630 : if( c > 0x00ff )
832 : aBuffer.append( static_cast< sal_Unicode >(
833 0 : aHexTab[ (c >> 8) & 0x0f ] ) );
834 1630 : if( c > 0x000f )
835 : aBuffer.append( static_cast< sal_Unicode >(
836 1630 : aHexTab[ (c >> 4) & 0x0f ] ) );
837 : aBuffer.append( static_cast< sal_Unicode >(
838 1630 : aHexTab[ c & 0x0f ] ) );
839 1630 : aBuffer.append( '_' );
840 1630 : if( pEncoded )
841 578 : *pEncoded = true;
842 : }
843 : }
844 :
845 : // check for length
846 5114 : if( aBuffer.getLength() > ((1<<15)-1) )
847 : {
848 0 : aBuffer = rName;
849 0 : if( pEncoded )
850 0 : *pEncoded = false;
851 : }
852 :
853 :
854 5114 : return aBuffer.makeStringAndClear();
855 : }
856 :
857 : /** convert string (hex) to number (sal_uInt32) */
858 676 : bool SvXMLUnitConverter::convertHex( sal_uInt32& nVal,
859 : const OUString& rValue )
860 : {
861 676 : if( rValue.getLength() != 8 )
862 0 : return false;
863 :
864 676 : nVal = 0;
865 6084 : for ( int i = 0; i < 8; i++ )
866 : {
867 5408 : nVal = ( nVal << 4 )
868 5408 : | sal::static_int_cast< sal_uInt32 >( lcl_gethex( rValue[i] ) );
869 : }
870 :
871 676 : return true;
872 : }
873 :
874 : /** convert number (sal_uInt32) to string (hex) */
875 34 : void SvXMLUnitConverter::convertHex( OUStringBuffer& rBuffer,
876 : sal_uInt32 nVal )
877 : {
878 306 : for ( int i = 0; i < 8; i++ )
879 : {
880 272 : rBuffer.append( sal_Unicode( aHexTab[ nVal >> 28 ] ) );
881 272 : nVal <<= 4;
882 : }
883 34 : }
884 :
885 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|