LibreOffice Module vcl (master)  1
dxfreprd.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 "dxfreprd.hxx"
25 #include <osl/nlsupport.h>
27 #include <unotools/wincodepage.hxx>
28 
29 //------------------DXFBoundingBox--------------------------------------------
30 
31 
32 void DXFBoundingBox::Union(const DXFVector & rVector)
33 {
34  if (bEmpty) {
35  fMinX=rVector.fx;
36  fMinY=rVector.fy;
37  fMinZ=rVector.fz;
38  fMaxX=rVector.fx;
39  fMaxY=rVector.fy;
40  fMaxZ=rVector.fz;
41  bEmpty=false;
42  }
43  else {
44  if (fMinX>rVector.fx) fMinX=rVector.fx;
45  if (fMinY>rVector.fy) fMinY=rVector.fy;
46  if (fMinZ>rVector.fz) fMinZ=rVector.fz;
47  if (fMaxX<rVector.fx) fMaxX=rVector.fx;
48  if (fMaxY<rVector.fy) fMaxY=rVector.fy;
49  if (fMaxZ<rVector.fz) fMaxZ=rVector.fz;
50  }
51 }
52 
53 
54 //------------------DXFPalette------------------------------------------------
55 
56 
58 {
59  short i,j,nHue,nNSat,nVal,nC[3],nmax,nmed,nmin;
60  sal_uInt8 nV;
61 
62  // colors 0 - 9 (normal colors)
63  SetColor(0, 0x00, 0x00, 0x00); // actually never being used
64  SetColor(1, 0xff, 0x00, 0x00);
65  SetColor(2, 0xff, 0xff, 0x00);
66  SetColor(3, 0x00, 0xff, 0x00);
67  SetColor(4, 0x00, 0xff, 0xff);
68  SetColor(5, 0x00, 0x00, 0xff);
69  SetColor(6, 0xff, 0x00, 0xff);
70  SetColor(7, 0x0f, 0x0f, 0x0f); // actually white???
71  SetColor(8, 0x80, 0x80, 0x80);
72  SetColor(9, 0xc0, 0xc0, 0xc0);
73 
74  // colors 10 - 249
75  // (Universal-Palette: 24 hues * 5 lightnesses * 2 saturations )
76  i=10;
77  for (nHue=0; nHue<24; nHue++) {
78  for (nVal=5; nVal>=1; nVal--) {
79  for (nNSat=0; nNSat<2; nNSat++) {
80  nmax=((nHue+3)>>3)%3;
81  j=nHue-(nmax<<3); if (j>4) j=j-24;
82  if (j>=0) {
83  nmed=(nmax+1)%3;
84  nmin=(nmax+2)%3;
85  }
86  else {
87  nmed=(nmax+2)%3;
88  nmin=(nmax+1)%3;
89  j=-j;
90  }
91  nC[nmin]=0;
92  nC[nmed]=255*j/4;
93  nC[nmax]=255;
94  if (nNSat!=0) {
95  for (j=0; j<3; j++) nC[j]=(nC[j]>>1)+128;
96  }
97  for (j=0; j<3; j++) nC[j]=nC[j]*nVal/5;
98  SetColor(static_cast<sal_uInt8>(i++),static_cast<sal_uInt8>(nC[0]),static_cast<sal_uInt8>(nC[1]),static_cast<sal_uInt8>(nC[2]));
99  }
100  }
101  }
102 
103  // Farben 250 - 255 (shades of gray)
104  for (i=0; i<6; i++) {
105  nV=static_cast<sal_uInt8>(i*38+65);
106  SetColor(static_cast<sal_uInt8>(250+i),nV,nV,nV);
107  }
108 }
109 
110 
112 {
113 }
114 
115 
116 void DXFPalette::SetColor(sal_uInt8 nIndex, sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue)
117 {
118  pRed[nIndex]=nRed;
119  pGreen[nIndex]=nGreen;
120  pBlue[nIndex]=nBlue;
121 }
122 
123 
124 //------------------DXFRepresentation-----------------------------------------
125 
126 
128  : mEnc(RTL_TEXTENCODING_DONTKNOW)
129  , mbInCalc(false)
130 {
132 }
133 
135 {
136 }
137 
138 rtl_TextEncoding DXFRepresentation::getTextEncoding() const
139 {
140  return (isTextEncodingSet()) ?
141  mEnc :
142  osl_getTextEncodingFromLocale(nullptr); // Use default encoding if none specified
143 }
144 
146 {
147  bool bRes;
148 
149  aTables.Clear();
150  aBlocks.Clear();
151  aEntities.Clear();
152 
153  DXFGroupReader DGR( rIStream );
154 
155  DGR.Read();
156  while (DGR.GetG()!=0 || (DGR.GetS() != "EOF")) {
157  if (DGR.GetG()==0 && DGR.GetS() == "SECTION") {
158  if (DGR.Read()!=2) {
159  DGR.SetError();
160  break;
161  }
162  if (DGR.GetS() == "HEADER") ReadHeader(DGR);
163  else if (DGR.GetS() == "TABLES") aTables.Read(DGR);
164  else if (DGR.GetS() == "BLOCKS") aBlocks.Read(DGR);
165  else if (DGR.GetS() == "ENTITIES") aEntities.Read(DGR);
166  else DGR.Read();
167  }
168  else DGR.Read();
169  }
170 
171  bRes=DGR.GetStatus();
172 
173  if (bRes && aBoundingBox.bEmpty)
175 
176  return bRes;
177 }
178 
180 {
181  while (rDGR.GetG()!=0 || (rDGR.GetS() != "EOF" && rDGR.GetS() != "ENDSEC") )
182  {
183  if (rDGR.GetG()==9) {
184  if (rDGR.GetS() == "$EXTMIN" ||
185  rDGR.GetS() == "$EXTMAX")
186  {
187  DXFVector aVector;
188  while (rDGR.Read()!=9 && rDGR.GetG()!=0) {
189  switch (rDGR.GetG()) {
190  case 10: aVector.fx = rDGR.GetF(); break;
191  case 20: aVector.fy = rDGR.GetF(); break;
192  case 30: aVector.fz = rDGR.GetF(); break;
193  }
194  }
195  aBoundingBox.Union(aVector);
196  }
197  else if (rDGR.GetS() == "$ACADVER")
198  {
199  if (!rDGR.Read(1))
200  continue;
201  // Versions of AutoCAD up to Release 12 (inclusive, AC1009)
202  // were DOS software and used OEM encoding for storing strings.
203  // Release 13 (AC1012) had both DOS and Windows variants.
204  // Its Windows variant, and later releases used ANSI encodings for
205  // strings (up to version 2006, which was the last one to do so).
206  // Later versions (2007+, AC1021+) use UTF-8 for that.
207  // Other (non-Autodesk) implementations may have used different
208  // encodings for storing to corresponding formats, but there's
209  // no way to know that.
210  // See http://autodesk.blogs.com/between_the_lines/autocad-release-history.html
211  if ((rDGR.GetS() <= std::string_view("AC1009")) || (rDGR.GetS() == "AC2.22") || (rDGR.GetS() == "AC2.21") || (rDGR.GetS() == "AC2.10") ||
212  (rDGR.GetS() == "AC1.50") || (rDGR.GetS() == "AC1.40") || (rDGR.GetS() == "AC1.2") || (rDGR.GetS() == "MC0.0"))
213  {
214  // Set OEM encoding for old DOS formats
215  // only if the encoding is not set yet
216  // e.g. by previous $DWGCODEPAGE
217  if (!isTextEncodingSet())
220  }
221  else if (rDGR.GetS() >= std::string_view("AC1021"))
222  setTextEncoding(RTL_TEXTENCODING_UTF8);
223  else
224  {
225  // Set ANSI encoding for old Windows formats
226  // only if the encoding is not set yet
227  // e.g. by previous $DWGCODEPAGE
228  if (!isTextEncodingSet())
231  }
232  }
233  else if (rDGR.GetS() == "$DWGCODEPAGE")
234  {
235  if (!rDGR.Read(3))
236  continue;
237 
238  // If we already use UTF8, then don't update encoding anymore
239  if (mEnc == RTL_TEXTENCODING_UTF8)
240  continue;
241  // FIXME: we really need a whole table of
242  // $DWGCODEPAGE to encodings mappings
243  else if ( (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_932")) ||
244  (rDGR.GetS().equalsIgnoreAsciiCase("DOS932")) )
245  {
246  setTextEncoding(RTL_TEXTENCODING_MS_932);
247  }
248  else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_936"))
249  {
250  setTextEncoding(RTL_TEXTENCODING_MS_936);
251  }
252  else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_949"))
253  {
254  setTextEncoding(RTL_TEXTENCODING_MS_949);
255  }
256  else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_950"))
257  {
258  setTextEncoding(RTL_TEXTENCODING_MS_950);
259  }
260  else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_1251"))
261  {
262  setTextEncoding(RTL_TEXTENCODING_MS_1251);
263  }
264  }
265  else if (rDGR.GetS() == "$LTSCALE")
266  {
267  if (!rDGR.Read(40))
268  continue;
270  }
271  else rDGR.Read();
272  }
273  else rDGR.Read();
274  }
275 }
276 
278  DXFBoundingBox & rBox)
279 {
280  if (mbInCalc)
281  return;
282  mbInCalc = true;
283 
284  DXFBasicEntity * pBE=rEntities.pFirst;
285  while (pBE!=nullptr) {
286  switch (pBE->eType) {
287  case DXF_LINE: {
288  const DXFLineEntity * pE = static_cast<const DXFLineEntity*>(pBE);
289  rBox.Union(pE->aP0);
290  rBox.Union(pE->aP1);
291  break;
292  }
293  case DXF_POINT: {
294  const DXFPointEntity * pE = static_cast<const DXFPointEntity*>(pBE);
295  rBox.Union(pE->aP0);
296  break;
297  }
298  case DXF_CIRCLE: {
299  const DXFCircleEntity * pE = static_cast<const DXFCircleEntity*>(pBE);
300  DXFVector aP;
301  aP=pE->aP0;
302  aP.fx-=pE->fRadius;
303  aP.fy-=pE->fRadius;
304  rBox.Union(aP);
305  aP=pE->aP0;
306  aP.fx+=pE->fRadius;
307  aP.fy+=pE->fRadius;
308  rBox.Union(aP);
309  break;
310  }
311  case DXF_ARC: {
312  const DXFArcEntity * pE = static_cast<const DXFArcEntity*>(pBE);
313  DXFVector aP;
314  aP=pE->aP0;
315  aP.fx-=pE->fRadius;
316  aP.fy-=pE->fRadius;
317  rBox.Union(aP);
318  aP=pE->aP0;
319  aP.fx+=pE->fRadius;
320  aP.fy+=pE->fRadius;
321  rBox.Union(aP);
322  break;
323  }
324  case DXF_TRACE: {
325  const DXFTraceEntity * pE = static_cast<const DXFTraceEntity*>(pBE);
326  rBox.Union(pE->aP0);
327  rBox.Union(pE->aP1);
328  rBox.Union(pE->aP2);
329  rBox.Union(pE->aP3);
330  break;
331  }
332  case DXF_SOLID: {
333  const DXFSolidEntity * pE = static_cast<const DXFSolidEntity*>(pBE);
334  rBox.Union(pE->aP0);
335  rBox.Union(pE->aP1);
336  rBox.Union(pE->aP2);
337  rBox.Union(pE->aP3);
338  break;
339  }
340  case DXF_TEXT: {
341  //const DXFTextEntity * pE = (DXFTextEntity*)pBE;
342  //???
343  break;
344  }
345  case DXF_SHAPE: {
346  //const DXFShapeEntity * pE = (DXFShapeEntity*)pBE;
347  //???
348  break;
349  }
350  case DXF_INSERT: {
351  const DXFInsertEntity * pE = static_cast<const DXFInsertEntity*>(pBE);
352  DXFBlock * pB;
353  DXFBoundingBox aBox;
354  DXFVector aP;
355  pB=aBlocks.Search(pE->m_sName);
356  if (pB==nullptr) break;
357  CalcBoundingBox(*pB,aBox);
358  if (aBox.bEmpty) break;
359  aP.fx=(aBox.fMinX-pB->aBasePoint.fx)*pE->fXScale+pE->aP0.fx;
360  aP.fy=(aBox.fMinY-pB->aBasePoint.fy)*pE->fYScale+pE->aP0.fy;
361  aP.fz=(aBox.fMinZ-pB->aBasePoint.fz)*pE->fZScale+pE->aP0.fz;
362  rBox.Union(aP);
363  aP.fx=(aBox.fMaxX-pB->aBasePoint.fx)*pE->fXScale+pE->aP0.fx;
364  aP.fy=(aBox.fMaxY-pB->aBasePoint.fy)*pE->fYScale+pE->aP0.fy;
365  aP.fz=(aBox.fMaxZ-pB->aBasePoint.fz)*pE->fZScale+pE->aP0.fz;
366  rBox.Union(aP);
367  break;
368  }
369  case DXF_ATTDEF: {
370  //const DXFAttDefEntity * pE = (DXFAttDefEntity*)pBE;
371  //???
372  break;
373  }
374  case DXF_ATTRIB: {
375  //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE;
376  //???
377  break;
378  }
379  case DXF_VERTEX: {
380  const DXFVertexEntity * pE = static_cast<const DXFVertexEntity*>(pBE);
381  rBox.Union(pE->aP0);
382  break;
383  }
384  case DXF_3DFACE: {
385  const DXF3DFaceEntity * pE = static_cast<const DXF3DFaceEntity*>(pBE);
386  rBox.Union(pE->aP0);
387  rBox.Union(pE->aP1);
388  rBox.Union(pE->aP2);
389  rBox.Union(pE->aP3);
390  break;
391  }
392  case DXF_DIMENSION: {
393  const DXFDimensionEntity * pE = static_cast<const DXFDimensionEntity*>(pBE);
394  DXFBlock * pB;
395  DXFBoundingBox aBox;
396  DXFVector aP;
397  pB = aBlocks.Search(pE->m_sPseudoBlock);
398  if (pB==nullptr) break;
399  CalcBoundingBox(*pB,aBox);
400  if (aBox.bEmpty) break;
401  aP.fx=aBox.fMinX-pB->aBasePoint.fx;
402  aP.fy=aBox.fMinY-pB->aBasePoint.fy;
403  aP.fz=aBox.fMinZ-pB->aBasePoint.fz;
404  rBox.Union(aP);
405  aP.fx=aBox.fMaxX-pB->aBasePoint.fx;
406  aP.fy=aBox.fMaxY-pB->aBasePoint.fy;
407  aP.fz=aBox.fMaxZ-pB->aBasePoint.fz;
408  rBox.Union(aP);
409  break;
410  }
411  case DXF_POLYLINE: {
412  //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE;
413  //???
414  break;
415  }
416  case DXF_SEQEND: {
417  //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE;
418  //???
419  break;
420  }
421  case DXF_HATCH :
422  break;
423  case DXF_LWPOLYLINE :
424  break;
425  }
426  pBE=pBE->pSucc;
427  }
428  mbInCalc = false;
429 }
430 
431 namespace {
432  bool lcl_isDec(sal_Unicode ch)
433  {
434  return ch >= L'0' && ch <= L'9';
435  }
436  bool lcl_isHex(sal_Unicode ch)
437  {
438  return lcl_isDec(ch) || (ch >= L'A' && ch <= L'F') || (ch >= L'a' && ch <= L'f');
439  }
440 }
441 
442 OUString DXFRepresentation::ToOUString(std::string_view s) const
443 {
444  OUString result = OStringToOUString(s, getTextEncoding(),
445  RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
446  | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
447  | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR);
448  result = result.replaceAll("%%o", "") // Overscore - simply remove
449  .replaceAll("%%u", "") // Underscore - simply remove
450  .replaceAll("%%d", u"\u00B0") // Degrees symbol (°)
451  .replaceAll("%%p", u"\u00B1") // Tolerance symbol (±)
452  .replaceAll("%%c", u"\u2205") // Diameter symbol
453  .replaceAll("%%%", "%"); // Percent symbol
454 
455  sal_Int32 pos = result.indexOf("%%"); // %%nnn, where nnn - 3-digit decimal ASCII code
456  while (pos != -1 && pos <= result.getLength() - 5) {
457  OUString asciiNum = result.copy(pos + 2, 3);
458  if (lcl_isDec(asciiNum[0]) &&
459  lcl_isDec(asciiNum[1]) &&
460  lcl_isDec(asciiNum[2]))
461  {
462  char ch = static_cast<char>(asciiNum.toUInt32());
463  OUString codePt(&ch, 1, mEnc);
464  result = result.replaceAll(result.subView(pos, 5), codePt, pos);
465  }
466  pos = result.indexOf("%%", pos + 1);
467  }
468 
469  pos = result.indexOf("\\U+"); // \U+XXXX, where XXXX - 4-digit hex unicode
470  while (pos != -1 && pos <= result.getLength() - 7) {
471  OUString codePtNum = result.copy(pos + 3, 4);
472  if (lcl_isHex(codePtNum[0]) &&
473  lcl_isHex(codePtNum[1]) &&
474  lcl_isHex(codePtNum[2]) &&
475  lcl_isHex(codePtNum[3]))
476  {
477  OUString codePt(static_cast<sal_Unicode>(codePtNum.toUInt32(16)));
478  result = result.replaceAll(result.subView(pos, 7), codePt, pos);
479  }
480  pos = result.indexOf("\\U+", pos + 1);
481  }
482  return result;
483 }
484 
485 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void Read(DXFGroupReader &rDGR)
Definition: dxftblrd.cxx:269
DXFEntityType eType
Definition: dxfentrd.hxx:60
DXFVector aP0
Definition: dxfentrd.hxx:114
std::array< sal_uInt8, 256 > pGreen
Definition: dxfreprd.hxx:63
double fx
Definition: dxfvec.hxx:55
double GetF() const
Definition: dxfgrprd.hxx:102
DXFVector aP3
Definition: dxfentrd.hxx:176
DXFBlocks aBlocks
Definition: dxfreprd.hxx:86
DXFVector aP0
Definition: dxfentrd.hxx:481
double fMinZ
Definition: dxfreprd.hxx:38
void CalcBoundingBox(const DXFEntities &rEntities, DXFBoundingBox &rBox)
Definition: dxfreprd.cxx:277
FormulaCommand pE
OUString ToOUString(std::string_view s) const
Definition: dxfreprd.cxx:442
std::array< sal_uInt8, 256 > pBlue
Definition: dxfreprd.hxx:64
DXFVector aP0
Definition: dxfentrd.hxx:141
DXFVector aP1
Definition: dxfentrd.hxx:101
void Clear()
Definition: dxfblkrd.cxx:113
void Read(DXFGroupReader &rDGR)
Definition: dxfblkrd.cxx:81
DXFVector aP0
Definition: dxfentrd.hxx:157
double fMinX
Definition: dxfreprd.hxx:36
double fMaxY
Definition: dxfreprd.hxx:40
double fMaxX
Definition: dxfreprd.hxx:39
void setTextEncoding(rtl_TextEncoding aEnc)
Definition: dxfreprd.hxx:102
DXFVector aP1
Definition: dxfentrd.hxx:482
DXFVector aP0
Definition: dxfentrd.hxx:100
sal_uInt16 sal_Unicode
rtl_TextEncoding getTextEncoding() const
Definition: dxfreprd.cxx:138
DXFBlock * Search(std::string_view rName) const
Definition: dxfblkrd.cxx:103
double fz
Definition: dxfvec.hxx:55
size_t pos
rtl_TextEncoding utl_getWinTextEncodingFromLangStr(const OUString &sLanguage, bool bOEM)
void Clear()
Definition: dxftblrd.cxx:321
OString m_sName
Definition: dxfentrd.hxx:231
DXFVector aP3
Definition: dxfentrd.hxx:484
sal_uInt16 Read()
Definition: dxfgrprd.cxx:117
double fMaxZ
Definition: dxfreprd.hxx:41
void Union(const DXFVector &rVector)
Definition: dxfreprd.cxx:32
bool isTextEncodingSet() const
Definition: dxfreprd.hxx:116
int i
DXFVector aP0
Definition: dxfentrd.hxx:232
DXFVector aP2
Definition: dxfentrd.hxx:175
DXFVector aP2
Definition: dxfentrd.hxx:159
DXFVector aBasePoint
Definition: dxfblkrd.hxx:44
double fy
Definition: dxfvec.hxx:55
DXFVector aP2
Definition: dxfentrd.hxx:483
bool GetStatus() const
Definition: dxfgrprd.hxx:81
float u
DXFVector aP0
Definition: dxfentrd.hxx:456
DXFTables aTables
Definition: dxfreprd.hxx:83
void setGlobalLineTypeScale(double fGlobalLineTypeScale)
Definition: dxfreprd.hxx:106
double fMinY
Definition: dxfreprd.hxx:37
double getGlobalLineTypeScale() const
Definition: dxfreprd.hxx:105
sal_uInt16 GetG() const
Definition: dxfgrprd.hxx:92
DXFBoundingBox aBoundingBox
Definition: dxfreprd.hxx:79
void Read(DXFGroupReader &rDGR)
Definition: dxfentrd.cxx:794
DXFBasicEntity * pSucc
Definition: dxfentrd.hxx:57
void SetError()
Definition: dxfgrprd.hxx:87
DXFVector aP0
Definition: dxfentrd.hxx:173
unsigned char sal_uInt8
const OString & GetS() const
Definition: dxfgrprd.hxx:107
DXFVector aP3
Definition: dxfentrd.hxx:160
DXFEntities aEntities
Definition: dxfreprd.hxx:89
Any result
DXFVector aP0
Definition: dxfentrd.hxx:127
DXFVector aP1
Definition: dxfentrd.hxx:174
bool Read(SvStream &rIStream)
Definition: dxfreprd.cxx:145
void SetColor(sal_uInt8 nIndex, sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue)
Definition: dxfreprd.cxx:116
void Clear()
Definition: dxfentrd.cxx:839
rtl_TextEncoding mEnc
Definition: dxfreprd.hxx:92
OUString utl_getLocaleForGlobalDefaultEncoding()
DXFBasicEntity * pFirst
Definition: dxfentrd.hxx:524
double fRadius
Definition: dxfentrd.hxx:142
OString m_sPseudoBlock
Definition: dxfentrd.hxx:498
DXFVector aP1
Definition: dxfentrd.hxx:158
void ReadHeader(DXFGroupReader &rDGR)
Definition: dxfreprd.cxx:179
std::array< sal_uInt8, 256 > pRed
Definition: dxfreprd.hxx:62