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