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