1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <string_view>
24 #include "dxfreprd.hxx"
25 #include <osl/nlsupport.h>
26 #include <unotools/defaultencoding.hxx>
27 #include <unotools/wincodepage.hxx>
29 //------------------DXFBoundingBox--------------------------------------------
32 void DXFBoundingBox::Union(const DXFVector
& rVector
)
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
;
54 //------------------DXFPalette------------------------------------------------
57 DXFPalette::DXFPalette()
59 short i
,j
,nHue
,nNSat
,nVal
,nC
[3],nmax
,nmed
,nmin
;
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);
75 // (Universal-Palette: 24 hues * 5 lightnesses * 2 saturations )
77 for (nHue
=0; nHue
<24; nHue
++) {
78 for (nVal
=5; nVal
>=1; nVal
--) {
79 for (nNSat
=0; nNSat
<2; nNSat
++) {
81 j
=nHue
-(nmax
<<3); if (j
>4) j
=j
-24;
95 for (j
=0; j
<3; j
++) nC
[j
]=(nC
[j
]>>1)+128;
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]));
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
);
111 void DXFPalette::SetColor(sal_uInt8 nIndex
, sal_uInt8 nRed
, sal_uInt8 nGreen
, sal_uInt8 nBlue
)
114 pGreen
[nIndex
]=nGreen
;
119 //------------------DXFRepresentation-----------------------------------------
122 DXFRepresentation::DXFRepresentation()
123 : mEnc(RTL_TEXTENCODING_DONTKNOW
)
126 setGlobalLineTypeScale(1.0);
129 DXFRepresentation::~DXFRepresentation()
133 rtl_TextEncoding
DXFRepresentation::getTextEncoding() const
135 return (isTextEncodingSet()) ?
137 osl_getTextEncodingFromLocale(nullptr); // Use default encoding if none specified
140 bool DXFRepresentation::Read( SvStream
& rIStream
)
148 DXFGroupReader
DGR( rIStream
);
151 while (DGR
.GetG()!=0 || (DGR
.GetS() != "EOF")) {
152 if (DGR
.GetG()==0 && DGR
.GetS() == "SECTION") {
157 if (DGR
.GetS() == "HEADER") ReadHeader(DGR
);
158 else if (DGR
.GetS() == "TABLES") aTables
.Read(DGR
);
159 else if (DGR
.GetS() == "BLOCKS") aBlocks
.Read(DGR
);
160 else if (DGR
.GetS() == "ENTITIES") aEntities
.Read(DGR
);
166 bRes
=DGR
.GetStatus();
168 if (bRes
&& aBoundingBox
.bEmpty
)
169 CalcBoundingBox(aEntities
,aBoundingBox
);
174 void DXFRepresentation::ReadHeader(DXFGroupReader
& rDGR
)
176 while (rDGR
.GetG()!=0 || (rDGR
.GetS() != "EOF" && rDGR
.GetS() != "ENDSEC") )
178 if (rDGR
.GetG()==9) {
179 if (rDGR
.GetS() == "$EXTMIN" ||
180 rDGR
.GetS() == "$EXTMAX")
183 while (rDGR
.Read()!=9 && rDGR
.GetG()!=0) {
184 switch (rDGR
.GetG()) {
185 case 10: aVector
.fx
= rDGR
.GetF(); break;
186 case 20: aVector
.fy
= rDGR
.GetF(); break;
187 case 30: aVector
.fz
= rDGR
.GetF(); break;
190 aBoundingBox
.Union(aVector
);
192 else if (rDGR
.GetS() == "$ACADVER")
196 // Versions of AutoCAD up to Release 12 (inclusive, AC1009)
197 // were DOS software and used OEM encoding for storing strings.
198 // Release 13 (AC1012) had both DOS and Windows variants.
199 // Its Windows variant, and later releases used ANSI encodings for
200 // strings (up to version 2006, which was the last one to do so).
201 // Later versions (2007+, AC1021+) use UTF-8 for that.
202 // Other (non-Autodesk) implementations may have used different
203 // encodings for storing to corresponding formats, but there's
204 // no way to know that.
205 // See http://autodesk.blogs.com/between_the_lines/autocad-release-history.html
206 if ((rDGR
.GetS() <= std::string_view("AC1009")) || (rDGR
.GetS() == "AC2.22") || (rDGR
.GetS() == "AC2.21") || (rDGR
.GetS() == "AC2.10") ||
207 (rDGR
.GetS() == "AC1.50") || (rDGR
.GetS() == "AC1.40") || (rDGR
.GetS() == "AC1.2") || (rDGR
.GetS() == "MC0.0"))
209 // Set OEM encoding for old DOS formats
210 // only if the encoding is not set yet
211 // e.g. by previous $DWGCODEPAGE
212 if (!isTextEncodingSet())
213 setTextEncoding(utl_getWinTextEncodingFromLangStr(
214 utl_getLocaleForGlobalDefaultEncoding(), true));
216 else if (rDGR
.GetS() >= std::string_view("AC1021"))
217 setTextEncoding(RTL_TEXTENCODING_UTF8
);
220 // Set ANSI encoding for old Windows formats
221 // only if the encoding is not set yet
222 // e.g. by previous $DWGCODEPAGE
223 if (!isTextEncodingSet())
224 setTextEncoding(utl_getWinTextEncodingFromLangStr(
225 utl_getLocaleForGlobalDefaultEncoding()));
228 else if (rDGR
.GetS() == "$DWGCODEPAGE")
233 // If we already use UTF8, then don't update encoding anymore
234 if (mEnc
== RTL_TEXTENCODING_UTF8
)
236 // FIXME: we really need a whole table of
237 // $DWGCODEPAGE to encodings mappings
238 else if ( (rDGR
.GetS().equalsIgnoreAsciiCase("ANSI_932")) ||
239 (rDGR
.GetS().equalsIgnoreAsciiCase("DOS932")) )
241 setTextEncoding(RTL_TEXTENCODING_MS_932
);
243 else if (rDGR
.GetS().equalsIgnoreAsciiCase("ANSI_936"))
245 setTextEncoding(RTL_TEXTENCODING_MS_936
);
247 else if (rDGR
.GetS().equalsIgnoreAsciiCase("ANSI_949"))
249 setTextEncoding(RTL_TEXTENCODING_MS_949
);
251 else if (rDGR
.GetS().equalsIgnoreAsciiCase("ANSI_950"))
253 setTextEncoding(RTL_TEXTENCODING_MS_950
);
255 else if (rDGR
.GetS().equalsIgnoreAsciiCase("ANSI_1251"))
257 setTextEncoding(RTL_TEXTENCODING_MS_1251
);
260 else if (rDGR
.GetS() == "$LTSCALE")
264 setGlobalLineTypeScale(getGlobalLineTypeScale() * rDGR
.GetF());
272 void DXFRepresentation::CalcBoundingBox(const DXFEntities
& rEntities
,
273 DXFBoundingBox
& rBox
)
279 DXFBasicEntity
* pBE
=rEntities
.pFirst
;
280 while (pBE
!=nullptr) {
281 switch (pBE
->eType
) {
283 const DXFLineEntity
* pE
= static_cast<const DXFLineEntity
*>(pBE
);
289 const DXFPointEntity
* pE
= static_cast<const DXFPointEntity
*>(pBE
);
294 const DXFCircleEntity
* pE
= static_cast<const DXFCircleEntity
*>(pBE
);
307 const DXFArcEntity
* pE
= static_cast<const DXFArcEntity
*>(pBE
);
320 const DXFTraceEntity
* pE
= static_cast<const DXFTraceEntity
*>(pBE
);
328 const DXFSolidEntity
* pE
= static_cast<const DXFSolidEntity
*>(pBE
);
336 //const DXFTextEntity * pE = (DXFTextEntity*)pBE;
341 //const DXFShapeEntity * pE = (DXFShapeEntity*)pBE;
346 const DXFInsertEntity
* pE
= static_cast<const DXFInsertEntity
*>(pBE
);
350 pB
=aBlocks
.Search(pE
->m_sName
);
351 if (pB
==nullptr) break;
352 CalcBoundingBox(*pB
,aBox
);
353 if (aBox
.bEmpty
) break;
354 aP
.fx
=(aBox
.fMinX
-pB
->aBasePoint
.fx
)*pE
->fXScale
+pE
->aP0
.fx
;
355 aP
.fy
=(aBox
.fMinY
-pB
->aBasePoint
.fy
)*pE
->fYScale
+pE
->aP0
.fy
;
356 aP
.fz
=(aBox
.fMinZ
-pB
->aBasePoint
.fz
)*pE
->fZScale
+pE
->aP0
.fz
;
358 aP
.fx
=(aBox
.fMaxX
-pB
->aBasePoint
.fx
)*pE
->fXScale
+pE
->aP0
.fx
;
359 aP
.fy
=(aBox
.fMaxY
-pB
->aBasePoint
.fy
)*pE
->fYScale
+pE
->aP0
.fy
;
360 aP
.fz
=(aBox
.fMaxZ
-pB
->aBasePoint
.fz
)*pE
->fZScale
+pE
->aP0
.fz
;
365 //const DXFAttDefEntity * pE = (DXFAttDefEntity*)pBE;
370 //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE;
375 const DXFVertexEntity
* pE
= static_cast<const DXFVertexEntity
*>(pBE
);
380 const DXF3DFaceEntity
* pE
= static_cast<const DXF3DFaceEntity
*>(pBE
);
387 case DXF_DIMENSION
: {
388 const DXFDimensionEntity
* pE
= static_cast<const DXFDimensionEntity
*>(pBE
);
392 pB
= aBlocks
.Search(pE
->m_sPseudoBlock
);
393 if (pB
==nullptr) break;
394 CalcBoundingBox(*pB
,aBox
);
395 if (aBox
.bEmpty
) break;
396 aP
.fx
=aBox
.fMinX
-pB
->aBasePoint
.fx
;
397 aP
.fy
=aBox
.fMinY
-pB
->aBasePoint
.fy
;
398 aP
.fz
=aBox
.fMinZ
-pB
->aBasePoint
.fz
;
400 aP
.fx
=aBox
.fMaxX
-pB
->aBasePoint
.fx
;
401 aP
.fy
=aBox
.fMaxY
-pB
->aBasePoint
.fy
;
402 aP
.fz
=aBox
.fMaxZ
-pB
->aBasePoint
.fz
;
407 //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE;
412 //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE;
418 case DXF_LWPOLYLINE
:
427 bool lcl_isDec(sal_Unicode ch
)
429 return ch
>= L
'0' && ch
<= L
'9';
431 bool lcl_isHex(sal_Unicode ch
)
433 return lcl_isDec(ch
) || (ch
>= L
'A' && ch
<= L
'F') || (ch
>= L
'a' && ch
<= L
'f');
437 OUString
DXFRepresentation::ToOUString(std::string_view s
) const
439 OUString result
= OStringToOUString(s
, getTextEncoding(),
440 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
441 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
442 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR
);
443 result
= result
.replaceAll("%%o", "") // Overscore - simply remove
444 .replaceAll("%%u", "") // Underscore - simply remove
445 .replaceAll("%%d", u
"\u00B0") // Degrees symbol (°)
446 .replaceAll("%%p", u
"\u00B1") // Tolerance symbol (±)
447 .replaceAll("%%c", u
"\u2205") // Diameter symbol
448 .replaceAll("%%%", "%"); // Percent symbol
450 sal_Int32 pos
= result
.indexOf("%%"); // %%nnn, where nnn - 3-digit decimal ASCII code
451 while (pos
!= -1 && pos
<= result
.getLength() - 5) {
452 OUString asciiNum
= result
.copy(pos
+ 2, 3);
453 if (lcl_isDec(asciiNum
[0]) &&
454 lcl_isDec(asciiNum
[1]) &&
455 lcl_isDec(asciiNum
[2]))
457 char ch
= static_cast<char>(asciiNum
.toUInt32());
458 OUString
codePt(&ch
, 1, mEnc
);
459 result
= result
.replaceAll(result
.subView(pos
, 5), codePt
, pos
);
461 pos
= result
.indexOf("%%", pos
+ 1);
464 pos
= result
.indexOf("\\U+"); // \U+XXXX, where XXXX - 4-digit hex unicode
465 while (pos
!= -1 && pos
<= result
.getLength() - 7) {
466 OUString codePtNum
= result
.copy(pos
+ 3, 4);
467 if (lcl_isHex(codePtNum
[0]) &&
468 lcl_isHex(codePtNum
[1]) &&
469 lcl_isHex(codePtNum
[2]) &&
470 lcl_isHex(codePtNum
[3]))
472 OUString
codePt(static_cast<sal_Unicode
>(codePtNum
.toUInt32(16)));
473 result
= result
.replaceAll(result
.subView(pos
, 7), codePt
, pos
);
475 pos
= result
.indexOf("\\U+", pos
+ 1);
480 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */