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