LibreOffice Module xmloff (master)  1
xexptran.cxx
Go to the documentation of this file.
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 #include <sal/config.h>
21 
22 #include <string_view>
23 
24 #include <xexptran.hxx>
25 #include <rtl/ustrbuf.hxx>
26 #include <osl/diagnose.h>
27 #include <sax/tools/converter.hxx>
28 #include <xmloff/xmluconv.hxx>
35 
36 using namespace ::com::sun::star;
37 
38 using std::make_unique;
39 
40 // parsing help functions for simple chars
41 static void Imp_SkipSpaces(std::u16string_view rStr, sal_Int32& rPos, const sal_Int32 nLen)
42 {
43  while(rPos < nLen
44  && ' ' == rStr[rPos])
45  rPos++;
46 }
47 
48 static void Imp_SkipSpacesAndOpeningBraces(std::u16string_view rStr, sal_Int32& rPos, const sal_Int32 nLen)
49 {
50  while(rPos < nLen
51  && (' ' == rStr[rPos] || '(' == rStr[rPos]))
52  rPos++;
53 }
54 
55 static void Imp_SkipSpacesAndCommas(std::u16string_view rStr, sal_Int32& rPos, const sal_Int32 nLen)
56 {
57  while(rPos < nLen
58  && (' ' == rStr[rPos] || ',' == rStr[rPos]))
59  rPos++;
60 }
61 
62 static void Imp_SkipSpacesAndClosingBraces(std::u16string_view rStr, sal_Int32& rPos, const sal_Int32 nLen)
63 {
64  while(rPos < nLen
65  && (' ' == rStr[rPos] || ')' == rStr[rPos]))
66  rPos++;
67 }
68 
69 // parsing help functions for integer numbers
70 
71 static bool Imp_IsOnUnitChar(std::u16string_view rStr, const sal_Int32 nPos)
72 {
73  sal_Unicode aChar(rStr[nPos]);
74 
75  return ('a' <= aChar && 'z' >= aChar)
76  || ('A' <= aChar && 'Z' >= aChar)
77  || '%' == aChar;
78 }
79 
80 static double Imp_GetDoubleChar(std::u16string_view rStr, sal_Int32& rPos, const sal_Int32 nLen,
81  const SvXMLUnitConverter& rConv, double fRetval, bool bLookForUnits = false)
82 {
83  sal_Unicode aChar(rStr[rPos]);
84  OUStringBuffer sNumberString(32);
85 
86  if('+' == aChar || '-' == aChar)
87  {
88  sNumberString.append(rStr[rPos]);
89  ++rPos;
90  aChar = rPos >= nLen ? 0 : rStr[rPos];
91  }
92 
93  while(('0' <= aChar && '9' >= aChar)
94  || '.' == aChar)
95  {
96  sNumberString.append(rStr[rPos]);
97  ++rPos;
98  aChar = rPos >= nLen ? 0 : rStr[rPos];
99  }
100 
101  if('e' == aChar || 'E' == aChar)
102  {
103  sNumberString.append(rStr[rPos]);
104  ++rPos;
105  aChar = rPos >= nLen ? 0 : rStr[rPos];
106 
107  if('+' == aChar || '-' == aChar)
108  {
109  sNumberString.append(rStr[rPos]);
110  ++rPos;
111  aChar = rPos >= nLen ? 0 : rStr[rPos];
112  }
113 
114  while('0' <= aChar && '9' >= aChar)
115  {
116  sNumberString.append(rStr[rPos]);
117  ++rPos;
118  aChar = rPos >= nLen ? 0 : rStr[rPos];
119  }
120  }
121 
122  if(bLookForUnits)
123  {
124  Imp_SkipSpaces(rStr, rPos, nLen);
125  while(rPos < nLen && Imp_IsOnUnitChar(rStr, rPos))
126  sNumberString.append(rStr[rPos++]);
127  }
128 
129  if(!sNumberString.isEmpty())
130  {
131  if(bLookForUnits)
132  rConv.convertDouble(fRetval, sNumberString.makeStringAndClear());
133  else
134  {
136  sNumberString.makeStringAndClear());
137  }
138  }
139 
140  return fRetval;
141 }
142 
143 static void Imp_PutDoubleChar(OUString& rStr, double fValue)
144 {
145  OUStringBuffer sStringBuffer;
146  ::sax::Converter::convertDouble(sStringBuffer, fValue);
147  rStr += sStringBuffer;
148 }
149 
150 static void Imp_PutDoubleChar(OUStringBuffer& rStr, const SvXMLUnitConverter& rConv, double fValue,
151  bool bConvertUnits = false)
152 {
153  OUStringBuffer sStringBuffer;
154 
155  if(bConvertUnits)
156  rConv.convertDouble(sStringBuffer, fValue);
157  else
158  {
159  ::sax::Converter::convertDouble(sStringBuffer, fValue);
160  }
161 
162  rStr.append(sStringBuffer);
163 }
164 
165 // base class of all 2D transform objects
166 
168 {
169  sal_uInt16 mnType;
170  explicit ImpSdXMLExpTransObj2DBase(sal_uInt16 nType)
171  : mnType(nType) {}
172 };
173 
174 // possible object types for 2D
175 
176 #define IMP_SDXMLEXP_TRANSOBJ2D_ROTATE 0x0000
177 #define IMP_SDXMLEXP_TRANSOBJ2D_SCALE 0x0001
178 #define IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE 0x0002
179 #define IMP_SDXMLEXP_TRANSOBJ2D_SKEWX 0x0003
180 #define IMP_SDXMLEXP_TRANSOBJ2D_SKEWY 0x0004
181 #define IMP_SDXMLEXP_TRANSOBJ2D_MATRIX 0x0005
182 
183 // classes of objects, different sizes
184 
185 namespace {
186 
187 struct ImpSdXMLExpTransObj2DRotate : public ImpSdXMLExpTransObj2DBase
188 {
189  double mfRotate;
190  explicit ImpSdXMLExpTransObj2DRotate(double fVal)
192 };
193 struct ImpSdXMLExpTransObj2DScale : public ImpSdXMLExpTransObj2DBase
194 {
195  ::basegfx::B2DTuple maScale;
196  explicit ImpSdXMLExpTransObj2DScale(const ::basegfx::B2DTuple& rNew)
198 };
199 struct ImpSdXMLExpTransObj2DTranslate : public ImpSdXMLExpTransObj2DBase
200 {
201  ::basegfx::B2DTuple maTranslate;
202  explicit ImpSdXMLExpTransObj2DTranslate(const ::basegfx::B2DTuple& rNew)
204 };
205 struct ImpSdXMLExpTransObj2DSkewX : public ImpSdXMLExpTransObj2DBase
206 {
207  double mfSkewX;
208  explicit ImpSdXMLExpTransObj2DSkewX(double fVal)
210 };
211 struct ImpSdXMLExpTransObj2DSkewY : public ImpSdXMLExpTransObj2DBase
212 {
213  double mfSkewY;
214  explicit ImpSdXMLExpTransObj2DSkewY(double fVal)
216 };
217 struct ImpSdXMLExpTransObj2DMatrix : public ImpSdXMLExpTransObj2DBase
218 {
220  explicit ImpSdXMLExpTransObj2DMatrix(const ::basegfx::B2DHomMatrix& rNew)
222 };
223 
224 }
225 
226 // add members
227 
229 {
230  if(fNew != 0.0)
231  maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DRotate>(fNew));
232 }
233 
234 void SdXMLImExTransform2D::AddTranslate(const ::basegfx::B2DTuple& rNew)
235 {
236  if(!rNew.equalZero())
237  maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DTranslate>(rNew));
238 }
239 
241 {
242  if(fNew != 0.0)
243  maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DSkewX>(fNew));
244 }
245 
246 // gen string for export
248 {
249  OUStringBuffer aNewString;
250  OUString aClosingBrace(")");
251  OUString aEmptySpace(" ");
252 
253  const sal_uInt32 nCount = maList.size();
254  for(sal_uInt32 a(0); a < nCount; a++)
255  {
256  ImpSdXMLExpTransObj2DBase* pObj = maList[a].get();
257  switch(pObj->mnType)
258  {
260  {
261  aNewString.append("rotate (");
262  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DRotate*>(pObj)->mfRotate);
263  aNewString.append(aClosingBrace);
264  break;
265  }
267  {
268  aNewString.append("scale (");
269  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DScale*>(pObj)->maScale.getX());
270  aNewString.append(aEmptySpace);
271  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DScale*>(pObj)->maScale.getY());
272  aNewString.append(aClosingBrace);
273  break;
274  }
276  {
277  aNewString.append("translate (");
278  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DTranslate*>(pObj)->maTranslate.getX(), true);
279  aNewString.append(aEmptySpace);
280  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DTranslate*>(pObj)->maTranslate.getY(), true);
281  aNewString.append(aClosingBrace);
282  break;
283  }
285  {
286  aNewString.append("skewX (");
287  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DSkewX*>(pObj)->mfSkewX);
288  aNewString.append(aClosingBrace);
289  break;
290  }
292  {
293  aNewString.append("skewY (");
294  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DSkewY*>(pObj)->mfSkewY);
295  aNewString.append(aClosingBrace);
296  break;
297  }
299  {
300  aNewString.append("matrix (");
301 
302  // a
303  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(0, 0));
304  aNewString.append(aEmptySpace);
305 
306  // b
307  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(1, 0));
308  aNewString.append(aEmptySpace);
309 
310  // c
311  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(0, 1));
312  aNewString.append(aEmptySpace);
313 
314  // d
315  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(1, 1));
316  aNewString.append(aEmptySpace);
317 
318  // e
319  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(0, 2), true);
320  aNewString.append(aEmptySpace);
321 
322  // f
323  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(1, 2), true);
324 
325  aNewString.append(aClosingBrace);
326  break;
327  }
328  default :
329  {
330  OSL_FAIL("SdXMLImExTransform2D: impossible entry!");
331  break;
332  }
333  }
334 
335  // if not the last entry, add one space to next tag
336  if(a + 1 != maList.size())
337  {
338  aNewString.append(aEmptySpace);
339  }
340  }
341 
342  // fill string form OUString
343  msString = aNewString.makeStringAndClear();
344 
345  return msString;
346 }
347 
348 // sets new string, parses it and generates entries
349 void SdXMLImExTransform2D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
350 {
351  msString = rNew;
352  maList.clear();
353 
354  if(msString.isEmpty())
355  return;
356 
357  const OUString aStr = msString;
358  const sal_Int32 nLen(aStr.getLength());
359 
360  const OUString aString_rotate( "rotate" );
361  const OUString aString_scale( "scale" );
362  const OUString aString_translate( "translate" );
363  const OUString aString_skewX( "skewX" );
364  const OUString aString_skewY( "skewY" );
365  const OUString aString_matrix( "matrix" );
366 
367  sal_Int32 nPos(0);
368 
369  while(nPos < nLen)
370  {
371  // skip spaces
372  Imp_SkipSpaces(aStr, nPos, nLen);
373 
374  // look for tag
375  if(nPos < nLen)
376  {
377  if(nPos == aStr.indexOf(aString_rotate, nPos))
378  {
379  double fValue(0.0);
380  nPos += 6;
381  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
382  fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
383  if(fValue != 0.0)
384  maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DRotate>(fValue));
385 
386  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
387  }
388  else if(nPos == aStr.indexOf(aString_scale, nPos))
389  {
390  ::basegfx::B2DTuple aValue(1.0, 1.0);
391  nPos += 5;
392  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
393  aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
394  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
395  aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
396 
397  if(aValue.getX() != 1.0 || aValue.getY() != 1.0)
398  maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DScale>(aValue));
399 
400  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
401  }
402  else if(nPos == aStr.indexOf(aString_translate, nPos))
403  {
404  ::basegfx::B2DTuple aValue;
405  nPos += 9;
406  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
407  aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
408  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
409  aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
410 
411  if(!aValue.equalZero())
412  maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DTranslate>(aValue));
413 
414  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
415  }
416  else if(nPos == aStr.indexOf(aString_skewX, nPos))
417  {
418  double fValue(0.0);
419  nPos += 5;
420  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
421  fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
422  if(fValue != 0.0)
423  maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DSkewX>(fValue));
424 
425  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
426  }
427  else if(nPos == aStr.indexOf(aString_skewY, nPos))
428  {
429  double fValue(0.0);
430  nPos += 5;
431  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
432  fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
433  if(fValue != 0.0)
434  maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DSkewY>(fValue));
435 
436  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
437  }
438  else if(nPos == aStr.indexOf(aString_matrix, nPos))
439  {
441 
442  nPos += 6;
443  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
444 
445  // a
446  aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
447  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
448 
449  // b
450  aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
451  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
452 
453  // c
454  aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
455  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
456 
457  // d
458  aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
459  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
460 
461  // e
462  aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2), true));
463  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
464 
465  // f
466  aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2), true));
467  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
468 
469  if(!aValue.isIdentity())
470  maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DMatrix>(aValue));
471 
472  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
473  }
474  else
475  {
476  nPos++;
477  }
478  }
479  }
480 }
481 
483 {
484  rFullTrans.identity();
485 
486  const sal_uInt32 nCount = maList.size();
487  for(sal_uInt32 a(0); a < nCount; a++)
488  {
489  ImpSdXMLExpTransObj2DBase* pObj = maList[a].get();
490  switch(pObj->mnType)
491  {
493  {
494  // #i78696#
495  // mfRotate is mathematically wrong oriented since we export/import the angle
496  // values mirrored. This error is fixed in the API, but not yet in the FileFormat.
497  // For the FileFormat there is a follow-up task (#i78698#) to fix this in the next
498  // ODF FileFormat version. For now - to emulate the old behaviour - it is necessary
499  // to mirror the value here
500  rFullTrans.rotate(static_cast<ImpSdXMLExpTransObj2DRotate*>(pObj)->mfRotate * -1.0);
501  break;
502  }
504  {
505  const ::basegfx::B2DTuple& rScale = static_cast<ImpSdXMLExpTransObj2DScale*>(pObj)->maScale;
506  rFullTrans.scale(rScale.getX(), rScale.getY());
507  break;
508  }
510  {
511  const ::basegfx::B2DTuple& rTranslate = static_cast<ImpSdXMLExpTransObj2DTranslate*>(pObj)->maTranslate;
512  rFullTrans.translate(rTranslate.getX(), rTranslate.getY());
513  break;
514  }
516  {
517  // For to get a mathematical correct matrix from already existing documents,
518  // mirror the value here. ODF spec is unclear about direction.
519  rFullTrans.shearX(-tan(static_cast<ImpSdXMLExpTransObj2DSkewX*>(pObj)->mfSkewX));
520  break;
521  }
523  {
524  // LibreOffice does not write skewY, OOo neither. Such files are foreign documents
525  // or manually set transformations. OOo had used the value as -tan(value) before
526  // errors were introduced, Scribus 1.5.4 uses it as -tan(value) too, MS Office does
527  // not shear at all. ODF spec is unclear about direction.
528  rFullTrans.shearY(-tan(static_cast<ImpSdXMLExpTransObj2DSkewY*>(pObj)->mfSkewY));
529  break;
530  }
532  {
533  rFullTrans *= static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix;
534  break;
535  }
536  default :
537  {
538  OSL_FAIL("SdXMLImExTransform2D: impossible entry!");
539  break;
540  }
541  }
542  }
543 }
544 
545 // base class of all 3D transform objects
546 
548 {
549  sal_uInt16 mnType;
550  explicit ImpSdXMLExpTransObj3DBase(sal_uInt16 nType)
551  : mnType(nType) {}
552 };
553 
554 // possible object types for 3D
555 
556 #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X 0x0000
557 #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y 0x0001
558 #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z 0x0002
559 #define IMP_SDXMLEXP_TRANSOBJ3D_SCALE 0x0003
560 #define IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE 0x0004
561 #define IMP_SDXMLEXP_TRANSOBJ3D_MATRIX 0x0005
562 
563 // classes of objects, different sizes
564 
565 namespace {
566 
567 struct ImpSdXMLExpTransObj3DRotateX : public ImpSdXMLExpTransObj3DBase
568 {
569  double mfRotateX;
570  explicit ImpSdXMLExpTransObj3DRotateX(double fVal)
572 };
573 struct ImpSdXMLExpTransObj3DRotateY : public ImpSdXMLExpTransObj3DBase
574 {
575  double mfRotateY;
576  explicit ImpSdXMLExpTransObj3DRotateY(double fVal)
578 };
579 struct ImpSdXMLExpTransObj3DRotateZ : public ImpSdXMLExpTransObj3DBase
580 {
581  double mfRotateZ;
582  explicit ImpSdXMLExpTransObj3DRotateZ(double fVal)
584 };
585 struct ImpSdXMLExpTransObj3DScale : public ImpSdXMLExpTransObj3DBase
586 {
587  ::basegfx::B3DTuple maScale;
588  explicit ImpSdXMLExpTransObj3DScale(const ::basegfx::B3DTuple& rNew)
590 };
591 struct ImpSdXMLExpTransObj3DTranslate : public ImpSdXMLExpTransObj3DBase
592 {
593  ::basegfx::B3DTuple maTranslate;
594  explicit ImpSdXMLExpTransObj3DTranslate(const ::basegfx::B3DTuple& rNew)
596 };
597 struct ImpSdXMLExpTransObj3DMatrix : public ImpSdXMLExpTransObj3DBase
598 {
600  explicit ImpSdXMLExpTransObj3DMatrix(const ::basegfx::B3DHomMatrix& rNew)
602 };
603 
604 }
605 
606 // add members
607 
608 void SdXMLImExTransform3D::AddMatrix(const ::basegfx::B3DHomMatrix& rNew)
609 {
610  if(!rNew.isIdentity())
611  maList.push_back(std::make_shared<ImpSdXMLExpTransObj3DMatrix>(rNew));
612 }
613 
614 void SdXMLImExTransform3D::AddHomogenMatrix(const drawing::HomogenMatrix& xHomMat)
615 {
617 }
618 
619 // gen string for export
621 {
622  OUStringBuffer aNewString;
623  OUString aClosingBrace(")");
624  OUString aEmptySpace(" ");
625 
626  const sal_uInt32 nCount = maList.size();
627  for(sal_uInt32 a(0); a < nCount; a++)
628  {
629  ImpSdXMLExpTransObj3DBase* pObj = maList[a].get();
630  switch(pObj->mnType)
631  {
633  {
634  aNewString.append("rotatex (");
635  Imp_PutDoubleChar(aNewString, rConv, basegfx::rad2deg( static_cast<ImpSdXMLExpTransObj3DRotateX*>(pObj)->mfRotateX) );
636  aNewString.append(aClosingBrace);
637  break;
638  }
640  {
641  aNewString.append("rotatey (");
642  Imp_PutDoubleChar(aNewString, rConv, basegfx::rad2deg( static_cast<ImpSdXMLExpTransObj3DRotateY*>(pObj)->mfRotateY) );
643  aNewString.append(aClosingBrace);
644  break;
645  }
647  {
648  aNewString.append("rotatez (");
649  Imp_PutDoubleChar(aNewString, rConv, basegfx::rad2deg( static_cast<ImpSdXMLExpTransObj3DRotateZ*>(pObj)->mfRotateZ) );
650  aNewString.append(aClosingBrace);
651  break;
652  }
654  {
655  aNewString.append("scale (");
656  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DScale*>(pObj)->maScale.getX());
657  aNewString.append(aEmptySpace);
658  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DScale*>(pObj)->maScale.getY());
659  aNewString.append(aEmptySpace);
660  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DScale*>(pObj)->maScale.getZ());
661  aNewString.append(aClosingBrace);
662  break;
663  }
665  {
666  aNewString.append("translate (");
667  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DTranslate*>(pObj)->maTranslate.getX(), true);
668  aNewString.append(aEmptySpace);
669  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DTranslate*>(pObj)->maTranslate.getY(), true);
670  aNewString.append(aEmptySpace);
671  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DTranslate*>(pObj)->maTranslate.getZ(), true);
672  aNewString.append(aClosingBrace);
673  break;
674  }
676  {
677  aNewString.append("matrix (");
678 
679  // a
680  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(0, 0));
681  aNewString.append(aEmptySpace);
682 
683  // b
684  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(1, 0));
685  aNewString.append(aEmptySpace);
686 
687  // c
688  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(2, 0));
689  aNewString.append(aEmptySpace);
690 
691  // d
692  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(0, 1));
693  aNewString.append(aEmptySpace);
694 
695  // e
696  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(1, 1));
697  aNewString.append(aEmptySpace);
698 
699  // f
700  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(2, 1));
701  aNewString.append(aEmptySpace);
702 
703  // g
704  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(0, 2));
705  aNewString.append(aEmptySpace);
706 
707  // h
708  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(1, 2));
709  aNewString.append(aEmptySpace);
710 
711  // i
712  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(2, 2));
713  aNewString.append(aEmptySpace);
714 
715  // j
716  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(0, 3), true);
717  aNewString.append(aEmptySpace);
718 
719  // k
720  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(1, 3), true);
721  aNewString.append(aEmptySpace);
722 
723  // l
724  Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(2, 3), true);
725 
726  aNewString.append(aClosingBrace);
727  break;
728  }
729  default :
730  {
731  OSL_FAIL("SdXMLImExTransform3D: impossible entry!");
732  break;
733  }
734  }
735 
736  // if not the last entry, add one space to next tag
737  if(a + 1 != maList.size())
738  {
739  aNewString.append(aEmptySpace);
740  }
741  }
742 
743  // fill string form OUString
744  msString = aNewString.makeStringAndClear();
745 
746  return msString;
747 }
748 
749 // for Import: constructor with string, parses it and generates entries
751 {
752  SetString(rNew, rConv);
753 }
754 
755 // sets new string, parses it and generates entries
756 void SdXMLImExTransform3D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
757 {
758  msString = rNew;
759  maList.clear();
760 
761  if(msString.isEmpty())
762  return;
763 
764  const OUString aStr = msString;
765  const sal_Int32 nLen(aStr.getLength());
766 
767  const OUString aString_rotatex( "rotatex" );
768  const OUString aString_rotatey( "rotatey" );
769  const OUString aString_rotatez( "rotatez" );
770  const OUString aString_scale( "scale" );
771  const OUString aString_translate( "translate" );
772  const OUString aString_matrix( "matrix" );
773 
774  sal_Int32 nPos(0);
775 
776  while(nPos < nLen)
777  {
778  // skip spaces
779  Imp_SkipSpaces(aStr, nPos, nLen);
780 
781  // look for tag
782  if(nPos < nLen)
783  {
784  if(nPos == aStr.indexOf(aString_rotatex, nPos))
785  {
786  double fValue(0.0);
787 
788  nPos += 7;
789  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
790  fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
791  if(fValue != 0.0)
792  maList.push_back(std::make_shared<ImpSdXMLExpTransObj3DRotateX>(basegfx::deg2rad(fValue)));
793 
794  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
795  }
796  else if(nPos == aStr.indexOf(aString_rotatey, nPos))
797  {
798  double fValue(0.0);
799 
800  nPos += 7;
801  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
802  fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
803  if(fValue != 0.0)
804  maList.push_back(std::make_shared<ImpSdXMLExpTransObj3DRotateY>(basegfx::deg2rad(fValue)));
805 
806  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
807  }
808  else if(nPos == aStr.indexOf(aString_rotatez, nPos))
809  {
810  double fValue(0.0);
811 
812  nPos += 7;
813  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
814  fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
815  if(fValue != 0.0)
816  maList.push_back(std::make_shared<ImpSdXMLExpTransObj3DRotateZ>(basegfx::deg2rad(fValue)));
817 
818  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
819  }
820  else if(nPos == aStr.indexOf(aString_scale, nPos))
821  {
822  ::basegfx::B3DTuple aValue(1.0, 1.0, 1.0);
823 
824  nPos += 5;
825  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
826  aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
827  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
828  aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
829  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
830  aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ()));
831 
832  if(1.0 != aValue.getX() || 1.0 != aValue.getY() || 1.0 != aValue.getZ())
833  maList.push_back(std::make_shared<ImpSdXMLExpTransObj3DScale>(aValue));
834 
835  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
836  }
837  else if(nPos == aStr.indexOf(aString_translate, nPos))
838  {
839  ::basegfx::B3DTuple aValue;
840 
841  nPos += 9;
842  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
843  aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
844  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
845  aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
846  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
847  aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ(), true));
848 
849  if(!aValue.equalZero())
850  maList.push_back(std::make_shared<ImpSdXMLExpTransObj3DTranslate>(aValue));
851 
852  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
853  }
854  else if(nPos == aStr.indexOf(aString_matrix, nPos))
855  {
857 
858  nPos += 6;
859  Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
860 
861  // a
862  aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
863  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
864 
865  // b
866  aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
867  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
868 
869  // c
870  aValue.set(2, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 0)));
871  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
872 
873  // d
874  aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
875  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
876 
877  // e
878  aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
879  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
880 
881  // f
882  aValue.set(2, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 1)));
883  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
884 
885  // g
886  aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2)));
887  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
888 
889  // h
890  aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2)));
891  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
892 
893  // i
894  aValue.set(2, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 2)));
895  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
896 
897  // j
898  aValue.set(0, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 3), true));
899  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
900 
901  // k
902  aValue.set(1, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 3), true));
903  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
904 
905  // l
906  aValue.set(2, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 3), true));
907  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
908 
909  if(!aValue.isIdentity())
910  maList.push_back(std::make_shared<ImpSdXMLExpTransObj3DMatrix>(aValue));
911 
912  Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
913  }
914  else
915  {
916  nPos++;
917  }
918  }
919  }
920 }
921 
922 bool SdXMLImExTransform3D::GetFullHomogenTransform(css::drawing::HomogenMatrix& xHomMat)
923 {
924  ::basegfx::B3DHomMatrix aFullTransform;
925  GetFullTransform(aFullTransform);
926 
927  if(!aFullTransform.isIdentity())
928  {
929  basegfx::utils::B3DHomMatrixToUnoHomogenMatrix(aFullTransform, xHomMat);
930  return true;
931  }
932 
933  return false;
934 }
935 
937 {
938  rFullTrans.identity();
939 
940  const sal_uInt32 nCount = maList.size();
941  for(sal_uInt32 a(0); a < nCount; a++)
942  {
943  ImpSdXMLExpTransObj3DBase* pObj = maList[a].get();
944  switch(pObj->mnType)
945  {
947  {
948  rFullTrans.rotate(static_cast<ImpSdXMLExpTransObj3DRotateX*>(pObj)->mfRotateX, 0.0, 0.0);
949  break;
950  }
952  {
953  rFullTrans.rotate(0.0, static_cast<ImpSdXMLExpTransObj3DRotateY*>(pObj)->mfRotateY, 0.0);
954  break;
955  }
957  {
958  rFullTrans.rotate(0.0, 0.0, static_cast<ImpSdXMLExpTransObj3DRotateZ*>(pObj)->mfRotateZ);
959  break;
960  }
962  {
963  const ::basegfx::B3DTuple& rScale = static_cast<ImpSdXMLExpTransObj3DScale*>(pObj)->maScale;
964  rFullTrans.scale(rScale.getX(), rScale.getY(), rScale.getZ());
965  break;
966  }
968  {
969  const ::basegfx::B3DTuple& rTranslate = static_cast<ImpSdXMLExpTransObj3DTranslate*>(pObj)->maTranslate;
970  rFullTrans.translate(rTranslate.getX(), rTranslate.getY(), rTranslate.getZ());
971  break;
972  }
974  {
975  rFullTrans *= static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix;
976  break;
977  }
978  default :
979  {
980  OSL_FAIL("SdXMLImExTransform3D: impossible entry!");
981  break;
982  }
983  }
984  }
985 }
986 
987 SdXMLImExViewBox::SdXMLImExViewBox(double fX, double fY, double fW, double fH)
988 : mfX( fX ),
989  mfY( fY ),
990  mfW( fW ),
991  mfH( fH )
992 {
993 }
994 
995 // #100617# Asked vincent hardy: svg:viewBox values may be double precision.
996 SdXMLImExViewBox::SdXMLImExViewBox(const OUString& rNew, const SvXMLUnitConverter& rConv)
997 : msString(rNew),
998  mfX( 0.0 ),
999  mfY( 0.0 ),
1000  mfW( 1000.0 ),
1001  mfH( 1000.0 )
1002 {
1003  if(msString.isEmpty())
1004  return;
1005 
1006  const OUString aStr = msString;
1007  const sal_Int32 nLen(aStr.getLength());
1008  sal_Int32 nPos(0);
1009 
1010  // skip starting spaces
1011  Imp_SkipSpaces(aStr, nPos, nLen);
1012 
1013  // get mX, #100617# be prepared for doubles
1014  mfX = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfX);
1015 
1016  // skip spaces and commas
1017  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1018 
1019  // get mY, #100617# be prepared for doubles
1020  mfY = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfY);
1021 
1022  // skip spaces and commas
1023  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1024 
1025  // get mW, #100617# be prepared for doubles
1026  mfW = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfW);
1027 
1028  // skip spaces and commas
1029  Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1030 
1031  // get mH, #100617# be prepared for doubles
1032  mfH = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfH);
1033 
1034 }
1035 
1037 {
1038  OUString aNewString;
1039  OUString aEmptySpace(" ");
1040 
1041  Imp_PutDoubleChar(aNewString, mfX);
1042  aNewString += aEmptySpace;
1043 
1044  Imp_PutDoubleChar(aNewString, mfY);
1045  aNewString += aEmptySpace;
1046 
1047  Imp_PutDoubleChar(aNewString, mfW);
1048  aNewString += aEmptySpace;
1049 
1050  Imp_PutDoubleChar(aNewString, mfH);
1051 
1052  // set new string
1053  msString = aNewString;
1054 
1055  return msString;
1056 }
1057 
1058 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void setX(double fX)
double mfX
void convertDouble(OUStringBuffer &rBuffer, double fNumber) const
convert double number to string (using ::rtl::math) and DO convert to export MapUnit using meCoreMeas...
Definition: xmluconv.cxx:286
void GetFullTransform(::basegfx::B3DHomMatrix &rFullTrans)
Definition: xexptran.cxx:936
void AddRotate(double fNew)
Definition: xexptran.cxx:228
void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
#define IMP_SDXMLEXP_TRANSOBJ2D_SKEWX
Definition: xexptran.cxx:179
OUString msString
Definition: xexptran.hxx:85
the SvXMLTypeConverter converts values of various types from their internal representation to the tex...
Definition: xmluconv.hxx:77
void B3DHomMatrixToUnoHomogenMatrix(const B3DHomMatrix &rMatrixIn, com::sun::star::drawing::HomogenMatrix &rMatrixOut)
std::vector< std::shared_ptr< ImpSdXMLExpTransObj3DBase > > maList
Definition: xexptran.hxx:66
#define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y
Definition: xexptran.cxx:557
double getX() const
double getY() const
void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
std::vector< std::shared_ptr< ImpSdXMLExpTransObj2DBase > > maList
Definition: xexptran.hxx:46
void shearY(double fSy)
void scale(double fX, double fY, double fZ)
#define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z
Definition: xexptran.cxx:558
constexpr double rad2deg(double v)
bool GetFullHomogenTransform(css::drawing::HomogenMatrix &xHomMat)
Definition: xexptran.cxx:922
double get(sal_uInt16 nRow, sal_uInt16 nColumn) const
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
static void Imp_SkipSpacesAndCommas(std::u16string_view rStr, sal_Int32 &rPos, const sal_Int32 nLen)
Definition: xexptran.cxx:55
#define IMP_SDXMLEXP_TRANSOBJ2D_MATRIX
Definition: xexptran.cxx:181
sal_uInt16 sal_Unicode
static void Imp_SkipSpacesAndClosingBraces(std::u16string_view rStr, sal_Int32 &rPos, const sal_Int32 nLen)
Definition: xexptran.cxx:62
#define IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE
Definition: xexptran.cxx:560
int nCount
const OUString & GetExportString()
Definition: xexptran.cxx:1036
void SetString(const OUString &rNew, const SvXMLUnitConverter &rConv)
Definition: xexptran.cxx:756
ImpSdXMLExpTransObj2DBase(sal_uInt16 nType)
Definition: xexptran.cxx:170
const OUString & GetExportString(const SvXMLUnitConverter &rConv)
Definition: xexptran.cxx:247
B3DHomMatrix UnoHomogenMatrixToB3DHomMatrix(const com::sun::star::drawing::HomogenMatrix &rMatrixIn)
void shearX(double fSx)
double mfY
const OUString & GetExportString(const SvXMLUnitConverter &rConv)
Definition: xexptran.cxx:620
uno_Any a
#define IMP_SDXMLEXP_TRANSOBJ3D_SCALE
Definition: xexptran.cxx:559
static void Imp_PutDoubleChar(OUString &rStr, double fValue)
Definition: xexptran.cxx:143
void SetString(const OUString &rNew, const SvXMLUnitConverter &rConv)
Definition: xexptran.cxx:349
#define IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE
Definition: xexptran.cxx:178
void rotate(double fRadiant)
static bool Imp_IsOnUnitChar(std::u16string_view rStr, const sal_Int32 nPos)
Definition: xexptran.cxx:71
void AddMatrix(const ::basegfx::B3DHomMatrix &rNew)
Definition: xexptran.cxx:608
#define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X
Definition: xexptran.cxx:556
void scale(double fX, double fY)
void AddTranslate(const ::basegfx::B2DTuple &rNew)
Definition: xexptran.cxx:234
constexpr double deg2rad(double v)
bool isIdentity() const
bool isIdentity() const
#define IMP_SDXMLEXP_TRANSOBJ2D_ROTATE
Definition: xexptran.cxx:176
void translate(double fX, double fY, double fZ)
#define IMP_SDXMLEXP_TRANSOBJ2D_SCALE
Definition: xexptran.cxx:177
SdXMLImExViewBox(double fX, double fY, double fW, double fH)
Definition: xexptran.cxx:987
void setY(double fY)
static void Imp_SkipSpacesAndOpeningBraces(std::u16string_view rStr, sal_Int32 &rPos, const sal_Int32 nLen)
Definition: xexptran.cxx:48
bool equalZero() const
void AddHomogenMatrix(const css::drawing::HomogenMatrix &xHomMat)
Definition: xexptran.cxx:614
static double Imp_GetDoubleChar(std::u16string_view rStr, sal_Int32 &rPos, const sal_Int32 nLen, const SvXMLUnitConverter &rConv, double fRetval, bool bLookForUnits=false)
Definition: xexptran.cxx:80
::basegfx::B2DHomMatrix maMatrix
void translate(double fX, double fY)
void GetFullTransform(::basegfx::B2DHomMatrix &rFullTrans)
Definition: xexptran.cxx:482
#define IMP_SDXMLEXP_TRANSOBJ2D_SKEWY
Definition: xexptran.cxx:180
void rotate(double fAngleX, double fAngleY, double fAngleZ)
ImpSdXMLExpTransObj3DBase(sal_uInt16 nType)
Definition: xexptran.cxx:550
void AddSkewX(double fNew)
Definition: xexptran.cxx:240
static void Imp_SkipSpaces(std::u16string_view rStr, sal_Int32 &rPos, const sal_Int32 nLen)
Definition: xexptran.cxx:41
aStr
#define IMP_SDXMLEXP_TRANSOBJ3D_MATRIX
Definition: xexptran.cxx:561
double get(sal_uInt16 nRow, sal_uInt16 nColumn) const
sal_uInt16 nPos