/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include "dxfreprd.hxx" #include "osl/nlsupport.h" #include "officecfg/Setup.hxx" #include "officecfg/Office/Linguistic.hxx" #include #include //------------------DXFBoundingBox-------------------------------------------- void DXFBoundingBox::Union(const DXFVector & rVector) { if (bEmpty) { fMinX=rVector.fx; fMinY=rVector.fy; fMinZ=rVector.fz; fMaxX=rVector.fx; fMaxY=rVector.fy; fMaxZ=rVector.fz; bEmpty=false; } else { if (fMinX>rVector.fx) fMinX=rVector.fx; if (fMinY>rVector.fy) fMinY=rVector.fy; if (fMinZ>rVector.fz) fMinZ=rVector.fz; if (fMaxX=1; nVal--) { for (nNSat=0; nNSat<2; nNSat++) { nmax=((nHue+3)>>3)%3; j=nHue-(nmax<<3); if (j>4) j=j-24; if (j>=0) { nmed=(nmax+1)%3; nmin=(nmax+2)%3; } else { nmed=(nmax+2)%3; nmin=(nmax+1)%3; j=-j; } nC[nmin]=0; nC[nmed]=255*j/4; nC[nmax]=255; if (nNSat!=0) { for (j=0; j<3; j++) nC[j]=(nC[j]>>1)+128; } for (j=0; j<3; j++) nC[j]=nC[j]*nVal/5; SetColor((sal_uInt8)(i++),(sal_uInt8)nC[0],(sal_uInt8)nC[1],(sal_uInt8)nC[2]); } } } // Farben 250 - 255 (shades of gray) for (i=0; i<6; i++) { nV=(sal_uInt8)(i*38+65); SetColor((sal_uInt8)(250+i),nV,nV,nV); } } DXFPalette::~DXFPalette() { delete[] pBlue; delete[] pGreen; delete[] pRed; } void DXFPalette::SetColor(sal_uInt8 nIndex, sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue) { pRed[nIndex]=nRed; pGreen[nIndex]=nGreen; pBlue[nIndex]=nBlue; } //------------------DXFRepresentation----------------------------------------- DXFRepresentation::DXFRepresentation() : mEnc(RTL_TEXTENCODING_DONTKNOW) , mbInCalc(false) { setGlobalLineTypeScale(1.0); } DXFRepresentation::~DXFRepresentation() { } namespace { OUString getLODefaultLanguage() { if (utl::ConfigManager::IsAvoidConfig()) return OUString("en-US"); OUString result(officecfg::Office::Linguistic::General::DefaultLocale::get()); if (result.isEmpty()) result = officecfg::Setup::L10N::ooSetupSystemLocale::get(); return result; } } rtl_TextEncoding DXFRepresentation::getTextEncoding() const { return (isTextEncodingSet()) ? mEnc : osl_getTextEncodingFromLocale(nullptr); // Use default encoding if none specified } bool DXFRepresentation::Read( SvStream & rIStream, sal_uInt16 /*nMinPercent*/, sal_uInt16 /*nMaxPercent*/) { bool bRes; aTables.Clear(); aBlocks.Clear(); aEntities.Clear(); DXFGroupReader DGR( rIStream ); DGR.Read(); while (DGR.GetG()!=0 || (DGR.GetS() != "EOF")) { if (DGR.GetG()==0 && DGR.GetS() == "SECTION") { if (DGR.Read()!=2) { DGR.SetError(); break; } if (DGR.GetS() == "HEADER") ReadHeader(DGR); else if (DGR.GetS() == "TABLES") aTables.Read(DGR); else if (DGR.GetS() == "BLOCKS") aBlocks.Read(DGR); else if (DGR.GetS() == "ENTITIES") aEntities.Read(DGR); else DGR.Read(); } else DGR.Read(); } bRes=DGR.GetStatus(); if (bRes && aBoundingBox.bEmpty) CalcBoundingBox(aEntities,aBoundingBox); return bRes; } void DXFRepresentation::ReadHeader(DXFGroupReader & rDGR) { while (rDGR.GetG()!=0 || (rDGR.GetS() != "EOF" && rDGR.GetS() != "ENDSEC") ) { if (rDGR.GetG()==9) { if (rDGR.GetS() == "$EXTMIN" || rDGR.GetS() == "$EXTMAX") { DXFVector aVector; while (rDGR.Read()!=9 && rDGR.GetG()!=0) { switch (rDGR.GetG()) { case 10: aVector.fx = rDGR.GetF(); break; case 20: aVector.fy = rDGR.GetF(); break; case 30: aVector.fz = rDGR.GetF(); break; } } aBoundingBox.Union(aVector); } else if (rDGR.GetS() == "$ACADVER") { if (!rDGR.Read(1)) continue; // Versions of AutoCAD up to Release 12 (inclusive, AC1009) // were DOS software and used OEM encoding for storing strings. // Release 13 (AC1012) had both DOS and Windows variants. // Its Windows variant, and later releases used ANSI encodings for // strings (up to version 2006, which was the last one to do so). // Later versions (2007+, AC1021+) use UTF-8 for that. // Other (non-Autodesk) implementations may have used different // encodings for storing to corresponding formats, but there's // no way to know that. // See http://autodesk.blogs.com/between_the_lines/autocad-release-history.html if ((rDGR.GetS() <= "AC1009") || (rDGR.GetS() == "AC2.22") || (rDGR.GetS() == "AC2.21") || (rDGR.GetS() == "AC2.10") || (rDGR.GetS() == "AC1.50") || (rDGR.GetS() == "AC1.40") || (rDGR.GetS() == "AC1.2") || (rDGR.GetS() == "MC0.0")) { // Set OEM encoding for old DOS formats // only if the encoding is not set yet // e.g. by previous $DWGCODEPAGE if (!isTextEncodingSet()) setTextEncoding(utl_getWinTextEncodingFromLangStr(getLODefaultLanguage().toUtf8().getStr(), true)); } else if (rDGR.GetS() >= "AC1021") setTextEncoding(RTL_TEXTENCODING_UTF8); else { // Set ANSI encoding for old Windows formats // only if the encoding is not set yet // e.g. by previous $DWGCODEPAGE if (!isTextEncodingSet()) setTextEncoding(utl_getWinTextEncodingFromLangStr(getLODefaultLanguage().toUtf8().getStr())); } } else if (rDGR.GetS() == "$DWGCODEPAGE") { if (!rDGR.Read(3)) continue; // If we already use UTF8, then don't update encoding anymore if (mEnc == RTL_TEXTENCODING_UTF8) continue; // FIXME: we really need a whole table of // $DWGCODEPAGE to encodings mappings else if ( (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_932")) || (rDGR.GetS().equalsIgnoreAsciiCase("DOS932")) ) { setTextEncoding(RTL_TEXTENCODING_MS_932); } else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_936")) { setTextEncoding(RTL_TEXTENCODING_MS_936); } else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_949")) { setTextEncoding(RTL_TEXTENCODING_MS_949); } else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_950")) { setTextEncoding(RTL_TEXTENCODING_MS_950); } else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_1251")) { setTextEncoding(RTL_TEXTENCODING_MS_1251); } } else if (rDGR.GetS() == "$LTSCALE") { if (!rDGR.Read(40)) continue; setGlobalLineTypeScale(getGlobalLineTypeScale() * rDGR.GetF()); } else rDGR.Read(); } else rDGR.Read(); } } void DXFRepresentation::CalcBoundingBox(const DXFEntities & rEntities, DXFBoundingBox & rBox) { if (mbInCalc) return; mbInCalc = true; DXFBasicEntity * pBE=rEntities.pFirst; while (pBE!=nullptr) { switch (pBE->eType) { case DXF_LINE: { const DXFLineEntity * pE = static_cast(pBE); rBox.Union(pE->aP0); rBox.Union(pE->aP1); break; } case DXF_POINT: { const DXFPointEntity * pE = static_cast(pBE); rBox.Union(pE->aP0); break; } case DXF_CIRCLE: { const DXFCircleEntity * pE = static_cast(pBE); DXFVector aP; aP=pE->aP0; aP.fx-=pE->fRadius; aP.fy-=pE->fRadius; rBox.Union(aP); aP=pE->aP0; aP.fx+=pE->fRadius; aP.fy+=pE->fRadius; rBox.Union(aP); break; } case DXF_ARC: { const DXFArcEntity * pE = static_cast(pBE); DXFVector aP; aP=pE->aP0; aP.fx-=pE->fRadius; aP.fy-=pE->fRadius; rBox.Union(aP); aP=pE->aP0; aP.fx+=pE->fRadius; aP.fy+=pE->fRadius; rBox.Union(aP); break; } case DXF_TRACE: { const DXFTraceEntity * pE = static_cast(pBE); rBox.Union(pE->aP0); rBox.Union(pE->aP1); rBox.Union(pE->aP2); rBox.Union(pE->aP3); break; } case DXF_SOLID: { const DXFSolidEntity * pE = static_cast(pBE); rBox.Union(pE->aP0); rBox.Union(pE->aP1); rBox.Union(pE->aP2); rBox.Union(pE->aP3); break; } case DXF_TEXT: { //const DXFTextEntity * pE = (DXFTextEntity*)pBE; //??? break; } case DXF_SHAPE: { //const DXFShapeEntity * pE = (DXFShapeEntity*)pBE; //??? break; } case DXF_INSERT: { const DXFInsertEntity * pE = static_cast(pBE); DXFBlock * pB; DXFBoundingBox aBox; DXFVector aP; pB=aBlocks.Search(pE->m_sName); if (pB==nullptr) break; CalcBoundingBox(*pB,aBox); if (aBox.bEmpty) break; aP.fx=(aBox.fMinX-pB->aBasePoint.fx)*pE->fXScale+pE->aP0.fx; aP.fy=(aBox.fMinY-pB->aBasePoint.fy)*pE->fYScale+pE->aP0.fy; aP.fz=(aBox.fMinZ-pB->aBasePoint.fz)*pE->fZScale+pE->aP0.fz; rBox.Union(aP); aP.fx=(aBox.fMaxX-pB->aBasePoint.fx)*pE->fXScale+pE->aP0.fx; aP.fy=(aBox.fMaxY-pB->aBasePoint.fy)*pE->fYScale+pE->aP0.fy; aP.fz=(aBox.fMaxZ-pB->aBasePoint.fz)*pE->fZScale+pE->aP0.fz; rBox.Union(aP); break; } case DXF_ATTDEF: { //const DXFAttDefEntity * pE = (DXFAttDefEntity*)pBE; //??? break; } case DXF_ATTRIB: { //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE; //??? break; } case DXF_VERTEX: { const DXFVertexEntity * pE = static_cast(pBE); rBox.Union(pE->aP0); break; } case DXF_3DFACE: { const DXF3DFaceEntity * pE = static_cast(pBE); rBox.Union(pE->aP0); rBox.Union(pE->aP1); rBox.Union(pE->aP2); rBox.Union(pE->aP3); break; } case DXF_DIMENSION: { const DXFDimensionEntity * pE = static_cast(pBE); DXFBlock * pB; DXFBoundingBox aBox; DXFVector aP; pB = aBlocks.Search(pE->m_sPseudoBlock); if (pB==nullptr) break; CalcBoundingBox(*pB,aBox); if (aBox.bEmpty) break; aP.fx=aBox.fMinX-pB->aBasePoint.fx; aP.fy=aBox.fMinY-pB->aBasePoint.fy; aP.fz=aBox.fMinZ-pB->aBasePoint.fz; rBox.Union(aP); aP.fx=aBox.fMaxX-pB->aBasePoint.fx; aP.fy=aBox.fMaxY-pB->aBasePoint.fy; aP.fz=aBox.fMaxZ-pB->aBasePoint.fz; rBox.Union(aP); break; } case DXF_POLYLINE: { //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE; //??? break; } case DXF_SEQEND: { //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE; //??? break; } case DXF_HATCH : break; case DXF_LWPOLYLINE : break; } pBE=pBE->pSucc; } mbInCalc = false; } namespace { inline bool lcl_isDec(sal_Unicode ch) { return ch >= L'0' && ch <= L'9'; } inline bool lcl_isHex(sal_Unicode ch) { return lcl_isDec(ch) || (ch >= L'A' && ch <= L'F') || (ch >= L'a' && ch <= L'f'); } } OUString DXFRepresentation::ToOUString(const OString& s) const { OUString result = OStringToOUString(s, getTextEncoding()); result = result.replaceAll("%%o", "") // Overscore - simply remove .replaceAll("%%u", "") // Underscore - simply remove .replaceAll("%%d", OUStringLiteral1(0x00B0)) // Degrees symbol (°) .replaceAll("%%p", OUStringLiteral1(0x00B1)) // Tolerance symbol (±) .replaceAll("%%c", OUStringLiteral1(0x2205)) // Diameter symbol .replaceAll("%%%", "%"); // Percent symbol sal_Int32 pos = result.indexOf("%%"); // %%nnn, where nnn - 3-digit decimal ASCII code while (pos != -1 && pos <= result.getLength() - 5) { OUString asciiNum = result.copy(pos + 2, 3); if (lcl_isDec(asciiNum[0]) && lcl_isDec(asciiNum[1]) && lcl_isDec(asciiNum[2])) { char ch = static_cast(asciiNum.toUInt32()); OUString codePt(&ch, 1, mEnc); result = result.replaceAll(result.copy(pos, 5), codePt, pos); } pos = result.indexOf("%%", pos + 1); } pos = result.indexOf("\\U+"); // \U+XXXX, where XXXX - 4-digit hex unicode while (pos != -1 && pos <= result.getLength() - 7) { OUString codePtNum = result.copy(pos + 3, 4); if (lcl_isHex(codePtNum[0]) && lcl_isHex(codePtNum[1]) && lcl_isHex(codePtNum[2]) && lcl_isHex(codePtNum[3])) { OUString codePt(static_cast(codePtNum.toUInt32(16))); result = result.replaceAll(result.copy(pos, 7), codePt, pos); } pos = result.indexOf("\\U+", pos + 1); } return result; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */