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