Line data Source code
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 :
21 : #include <string.h>
22 : #include <dxfreprd.hxx>
23 : #include "osl/nlsupport.h"
24 :
25 : //------------------DXFBoundingBox--------------------------------------------
26 :
27 :
28 0 : void DXFBoundingBox::Union(const DXFVector & rVector)
29 : {
30 0 : if (bEmpty) {
31 0 : fMinX=rVector.fx;
32 0 : fMinY=rVector.fy;
33 0 : fMinZ=rVector.fz;
34 0 : fMaxX=rVector.fx;
35 0 : fMaxY=rVector.fy;
36 0 : fMaxZ=rVector.fz;
37 0 : bEmpty=false;
38 : }
39 : else {
40 0 : if (fMinX>rVector.fx) fMinX=rVector.fx;
41 0 : if (fMinY>rVector.fy) fMinY=rVector.fy;
42 0 : if (fMinZ>rVector.fz) fMinZ=rVector.fz;
43 0 : if (fMaxX<rVector.fx) fMaxX=rVector.fx;
44 0 : if (fMaxY<rVector.fy) fMaxY=rVector.fy;
45 0 : if (fMaxZ<rVector.fz) fMaxZ=rVector.fz;
46 : }
47 0 : }
48 :
49 :
50 : //------------------DXFPalette------------------------------------------------
51 :
52 :
53 1 : DXFPalette::DXFPalette()
54 : {
55 : short i,j,nHue,nNSat,nVal,nC[3],nmax,nmed,nmin;
56 : sal_uInt8 nV;
57 :
58 1 : pRed =new sal_uInt8[256];
59 1 : pGreen=new sal_uInt8[256];
60 1 : pBlue =new sal_uInt8[256];
61 :
62 : // colors 0 - 9 (normal colors)
63 1 : SetColor(0, 0x00, 0x00, 0x00); // actually never being used
64 1 : SetColor(1, 0xff, 0x00, 0x00);
65 1 : SetColor(2, 0xff, 0xff, 0x00);
66 1 : SetColor(3, 0x00, 0xff, 0x00);
67 1 : SetColor(4, 0x00, 0xff, 0xff);
68 1 : SetColor(5, 0x00, 0x00, 0xff);
69 1 : SetColor(6, 0xff, 0x00, 0xff);
70 1 : SetColor(7, 0x0f, 0x0f, 0x0f); // actually white???
71 1 : SetColor(8, 0x80, 0x80, 0x80);
72 1 : SetColor(9, 0xc0, 0xc0, 0xc0);
73 :
74 : // colors 10 - 249
75 : // (Universal-Palette: 24 hues * 5 lightnesses * 2 saturations )
76 1 : i=10;
77 25 : for (nHue=0; nHue<24; nHue++) {
78 144 : for (nVal=5; nVal>=1; nVal--) {
79 360 : for (nNSat=0; nNSat<2; nNSat++) {
80 240 : nmax=((nHue+3)>>3)%3;
81 240 : j=nHue-(nmax<<3); if (j>4) j=j-24;
82 240 : if (j>=0) {
83 150 : nmed=(nmax+1)%3;
84 150 : nmin=(nmax+2)%3;
85 : }
86 : else {
87 90 : nmed=(nmax+2)%3;
88 90 : nmin=(nmax+1)%3;
89 90 : j=-j;
90 : }
91 240 : nC[nmin]=0;
92 240 : nC[nmed]=255*j/4;
93 240 : nC[nmax]=255;
94 240 : if (nNSat!=0) {
95 120 : for (j=0; j<3; j++) nC[j]=(nC[j]>>1)+128;
96 : }
97 240 : for (j=0; j<3; j++) nC[j]=nC[j]*nVal/5;
98 240 : SetColor((sal_uInt8)(i++),(sal_uInt8)nC[0],(sal_uInt8)nC[1],(sal_uInt8)nC[2]);
99 : }
100 : }
101 : }
102 :
103 : // Farben 250 - 255 (shades of gray)
104 7 : for (i=0; i<6; i++) {
105 6 : nV=(sal_uInt8)(i*38+65);
106 6 : SetColor((sal_uInt8)(250+i),nV,nV,nV);
107 : }
108 1 : }
109 :
110 :
111 1 : DXFPalette::~DXFPalette()
112 : {
113 1 : delete[] pBlue;
114 1 : delete[] pGreen;
115 1 : delete[] pRed;
116 1 : }
117 :
118 :
119 256 : void DXFPalette::SetColor(sal_uInt8 nIndex, sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue)
120 : {
121 256 : pRed[nIndex]=nRed;
122 256 : pGreen[nIndex]=nGreen;
123 256 : pBlue[nIndex]=nBlue;
124 256 : }
125 :
126 :
127 : //------------------DXFRepresentation-----------------------------------------
128 :
129 :
130 1 : DXFRepresentation::DXFRepresentation()
131 1 : : bUseUTF8(false)
132 : {
133 1 : setTextEncoding(osl_getTextEncodingFromLocale(nullptr)); // Use default encoding if none specified
134 1 : setGlobalLineTypeScale(1.0);
135 1 : }
136 :
137 :
138 1 : DXFRepresentation::~DXFRepresentation()
139 : {
140 1 : }
141 :
142 :
143 1 : bool DXFRepresentation::Read( SvStream & rIStream, sal_uInt16 /*nMinPercent*/, sal_uInt16 /*nMaxPercent*/)
144 : {
145 : bool bRes;
146 :
147 1 : aTables.Clear();
148 1 : aBlocks.Clear();
149 1 : aEntities.Clear();
150 :
151 1 : DXFGroupReader DGR( rIStream );
152 :
153 1 : DGR.Read();
154 4 : while (DGR.GetG()!=0 || (DGR.GetS() != "EOF")) {
155 2 : if (DGR.GetG()==0 && DGR.GetS() == "SECTION") {
156 1 : if (DGR.Read()!=2) {
157 0 : DGR.SetError();
158 0 : break;
159 : }
160 1 : if (DGR.GetS() == "HEADER") ReadHeader(DGR);
161 0 : else if (DGR.GetS() == "TABLES") aTables.Read(DGR);
162 0 : else if (DGR.GetS() == "BLOCKS") aBlocks.Read(DGR);
163 0 : else if (DGR.GetS() == "ENTITIES") aEntities.Read(DGR);
164 0 : else DGR.Read();
165 : }
166 1 : else DGR.Read();
167 : }
168 :
169 1 : bRes=DGR.GetStatus();
170 :
171 1 : if (bRes && aBoundingBox.bEmpty)
172 0 : CalcBoundingBox(aEntities,aBoundingBox);
173 :
174 1 : return bRes;
175 : }
176 :
177 1 : void DXFRepresentation::ReadHeader(DXFGroupReader & rDGR)
178 : {
179 199 : while (rDGR.GetG()!=0 || (rDGR.GetS() != "EOF" && rDGR.GetS() != "ENDSEC") )
180 : {
181 197 : if (rDGR.GetG()==9) {
182 0 : if (rDGR.GetS() == "$EXTMIN" ||
183 0 : rDGR.GetS() == "$EXTMAX")
184 : {
185 0 : DXFVector aVector;
186 0 : while (rDGR.Read()!=9 && rDGR.GetG()!=0) {
187 0 : switch (rDGR.GetG()) {
188 0 : case 10: aVector.fx = rDGR.GetF(); break;
189 0 : case 20: aVector.fy = rDGR.GetF(); break;
190 0 : case 30: aVector.fz = rDGR.GetF(); break;
191 : }
192 : }
193 0 : aBoundingBox.Union(aVector);
194 : }
195 0 : else if (rDGR.GetS() == "$ACADVER")
196 : {
197 0 : if (!rDGR.Read(1))
198 0 : continue;
199 0 : if (rDGR.GetS() >= "AC1021")
200 0 : bUseUTF8 = true;
201 : }
202 0 : else if (rDGR.GetS() == "$DWGCODEPAGE")
203 : {
204 0 : if (!rDGR.Read(3))
205 0 : continue;
206 :
207 : // FIXME: we really need a whole table of
208 : // $DWGCODEPAGE to encodings mappings
209 0 : if ( (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_932")) ||
210 0 : (rDGR.GetS().equalsIgnoreAsciiCase("DOS932")) )
211 : {
212 0 : setTextEncoding(RTL_TEXTENCODING_MS_932);
213 : }
214 0 : else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_936"))
215 : {
216 0 : setTextEncoding(RTL_TEXTENCODING_MS_936);
217 : }
218 0 : else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_949"))
219 : {
220 0 : setTextEncoding(RTL_TEXTENCODING_MS_949);
221 : }
222 0 : else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_950"))
223 : {
224 0 : setTextEncoding(RTL_TEXTENCODING_MS_950);
225 : }
226 0 : else if (rDGR.GetS().equalsIgnoreAsciiCase("ANSI_1251"))
227 : {
228 0 : setTextEncoding(RTL_TEXTENCODING_MS_1251);
229 : }
230 : }
231 0 : else if (rDGR.GetS() == "$LTSCALE")
232 : {
233 0 : if (!rDGR.Read(40))
234 0 : continue;
235 0 : setGlobalLineTypeScale(getGlobalLineTypeScale() * rDGR.GetF());
236 : }
237 0 : else rDGR.Read();
238 : }
239 197 : else rDGR.Read();
240 : }
241 1 : }
242 :
243 0 : void DXFRepresentation::CalcBoundingBox(const DXFEntities & rEntities,
244 : DXFBoundingBox & rBox)
245 : {
246 0 : DXFBasicEntity * pBE=rEntities.pFirst;
247 0 : while (pBE!=NULL) {
248 0 : switch (pBE->eType) {
249 : case DXF_LINE: {
250 0 : const DXFLineEntity * pE = static_cast<const DXFLineEntity*>(pBE);
251 0 : rBox.Union(pE->aP0);
252 0 : rBox.Union(pE->aP1);
253 0 : break;
254 : }
255 : case DXF_POINT: {
256 0 : const DXFPointEntity * pE = static_cast<const DXFPointEntity*>(pBE);
257 0 : rBox.Union(pE->aP0);
258 0 : break;
259 : }
260 : case DXF_CIRCLE: {
261 0 : const DXFCircleEntity * pE = static_cast<const DXFCircleEntity*>(pBE);
262 0 : DXFVector aP;
263 0 : aP=pE->aP0;
264 0 : aP.fx-=pE->fRadius;
265 0 : aP.fy-=pE->fRadius;
266 0 : rBox.Union(aP);
267 0 : aP=pE->aP0;
268 0 : aP.fx+=pE->fRadius;
269 0 : aP.fy+=pE->fRadius;
270 0 : rBox.Union(aP);
271 0 : break;
272 : }
273 : case DXF_ARC: {
274 0 : const DXFArcEntity * pE = static_cast<const DXFArcEntity*>(pBE);
275 0 : DXFVector aP;
276 0 : aP=pE->aP0;
277 0 : aP.fx-=pE->fRadius;
278 0 : aP.fy-=pE->fRadius;
279 0 : rBox.Union(aP);
280 0 : aP=pE->aP0;
281 0 : aP.fx+=pE->fRadius;
282 0 : aP.fy+=pE->fRadius;
283 0 : rBox.Union(aP);
284 0 : break;
285 : }
286 : case DXF_TRACE: {
287 0 : const DXFTraceEntity * pE = static_cast<const DXFTraceEntity*>(pBE);
288 0 : rBox.Union(pE->aP0);
289 0 : rBox.Union(pE->aP1);
290 0 : rBox.Union(pE->aP2);
291 0 : rBox.Union(pE->aP3);
292 0 : break;
293 : }
294 : case DXF_SOLID: {
295 0 : const DXFSolidEntity * pE = static_cast<const DXFSolidEntity*>(pBE);
296 0 : rBox.Union(pE->aP0);
297 0 : rBox.Union(pE->aP1);
298 0 : rBox.Union(pE->aP2);
299 0 : rBox.Union(pE->aP3);
300 0 : break;
301 : }
302 : case DXF_TEXT: {
303 : //const DXFTextEntity * pE = (DXFTextEntity*)pBE;
304 : //???
305 0 : break;
306 : }
307 : case DXF_SHAPE: {
308 : //const DXFShapeEntity * pE = (DXFShapeEntity*)pBE;
309 : //???
310 0 : break;
311 : }
312 : case DXF_INSERT: {
313 0 : const DXFInsertEntity * pE = static_cast<const DXFInsertEntity*>(pBE);
314 : DXFBlock * pB;
315 0 : DXFBoundingBox aBox;
316 0 : DXFVector aP;
317 0 : pB=aBlocks.Search(pE->m_sName);
318 0 : if (pB==NULL) break;
319 0 : CalcBoundingBox(*pB,aBox);
320 0 : if (aBox.bEmpty) break;
321 0 : aP.fx=(aBox.fMinX-pB->aBasePoint.fx)*pE->fXScale+pE->aP0.fx;
322 0 : aP.fy=(aBox.fMinY-pB->aBasePoint.fy)*pE->fYScale+pE->aP0.fy;
323 0 : aP.fz=(aBox.fMinZ-pB->aBasePoint.fz)*pE->fZScale+pE->aP0.fz;
324 0 : rBox.Union(aP);
325 0 : aP.fx=(aBox.fMaxX-pB->aBasePoint.fx)*pE->fXScale+pE->aP0.fx;
326 0 : aP.fy=(aBox.fMaxY-pB->aBasePoint.fy)*pE->fYScale+pE->aP0.fy;
327 0 : aP.fz=(aBox.fMaxZ-pB->aBasePoint.fz)*pE->fZScale+pE->aP0.fz;
328 0 : rBox.Union(aP);
329 0 : break;
330 : }
331 : case DXF_ATTDEF: {
332 : //const DXFAttDefEntity * pE = (DXFAttDefEntity*)pBE;
333 : //???
334 0 : break;
335 : }
336 : case DXF_ATTRIB: {
337 : //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE;
338 : //???
339 0 : break;
340 : }
341 : case DXF_VERTEX: {
342 0 : const DXFVertexEntity * pE = static_cast<const DXFVertexEntity*>(pBE);
343 0 : rBox.Union(pE->aP0);
344 0 : break;
345 : }
346 : case DXF_3DFACE: {
347 0 : const DXF3DFaceEntity * pE = static_cast<const DXF3DFaceEntity*>(pBE);
348 0 : rBox.Union(pE->aP0);
349 0 : rBox.Union(pE->aP1);
350 0 : rBox.Union(pE->aP2);
351 0 : rBox.Union(pE->aP3);
352 0 : break;
353 : }
354 : case DXF_DIMENSION: {
355 0 : const DXFDimensionEntity * pE = static_cast<const DXFDimensionEntity*>(pBE);
356 : DXFBlock * pB;
357 0 : DXFBoundingBox aBox;
358 0 : DXFVector aP;
359 0 : pB = aBlocks.Search(pE->m_sPseudoBlock);
360 0 : if (pB==NULL) break;
361 0 : CalcBoundingBox(*pB,aBox);
362 0 : if (aBox.bEmpty) break;
363 0 : aP.fx=aBox.fMinX-pB->aBasePoint.fx;
364 0 : aP.fy=aBox.fMinY-pB->aBasePoint.fy;
365 0 : aP.fz=aBox.fMinZ-pB->aBasePoint.fz;
366 0 : rBox.Union(aP);
367 0 : aP.fx=aBox.fMaxX-pB->aBasePoint.fx;
368 0 : aP.fy=aBox.fMaxY-pB->aBasePoint.fy;
369 0 : aP.fz=aBox.fMaxZ-pB->aBasePoint.fz;
370 0 : rBox.Union(aP);
371 0 : break;
372 : }
373 : case DXF_POLYLINE: {
374 : //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE;
375 : //???
376 0 : break;
377 : }
378 : case DXF_SEQEND: {
379 : //const DXFAttribEntity * pE = (DXFAttribEntity*)pBE;
380 : //???
381 0 : break;
382 : }
383 : case DXF_HATCH :
384 0 : break;
385 : case DXF_LWPOLYLINE :
386 0 : break;
387 : }
388 0 : pBE=pBE->pSucc;
389 : }
390 0 : }
391 :
392 : namespace {
393 0 : inline bool lcl_isDec(sal_Unicode ch)
394 : {
395 0 : return ch >= L'0' && ch <= L'9';
396 : }
397 0 : inline bool lcl_isHex(sal_Unicode ch)
398 : {
399 0 : return lcl_isDec(ch) || (ch >= L'A' && ch <= L'F') || (ch >= L'a' && ch <= L'f');
400 : }
401 : }
402 :
403 0 : OUString DXFRepresentation::ToOUString(const OString& s, bool bSpecials) const
404 : {
405 0 : OUString result = OStringToOUString(s, getTextEncoding());
406 0 : if (bSpecials) {
407 0 : result = result.replaceAll("%%o", "") // Overscore - simply remove
408 : .replaceAll("%%u", "") // Underscore - simply remove
409 : .replaceAll("%%d", OUString(sal_Unicode(L'\u00B0'))) // Degrees symbol (°)
410 : .replaceAll("%%p", OUString(sal_Unicode(L'\u00B1'))) // Tolerance symbol (±)
411 : .replaceAll("%%c", OUString(sal_Unicode(L'\u2205'))) // Diameter symbol
412 0 : .replaceAll("%%%", "%"); // Percent symbol
413 :
414 0 : sal_Int32 pos = result.indexOf("%%"); // %%nnn, where nnn - 3-digit decimal ASCII code
415 0 : while (pos != -1 && pos <= result.getLength() - 5) {
416 0 : OUString asciiNum = result.copy(pos + 2, 3);
417 0 : if (lcl_isDec(asciiNum[0]) &&
418 0 : lcl_isDec(asciiNum[1]) &&
419 0 : lcl_isDec(asciiNum[2]))
420 : {
421 0 : char ch = static_cast<char>(asciiNum.toUInt32());
422 0 : OUString codePt(&ch, 1, mEnc);
423 0 : result = result.replaceAll(result.copy(pos, 5), codePt, pos);
424 : }
425 0 : pos = result.indexOf("%%", pos + 1);
426 0 : }
427 :
428 0 : pos = result.indexOf("\\U+"); // \U+XXXX, where XXXX - 4-digit hex unicode
429 0 : while (pos != -1 && pos <= result.getLength() - 7) {
430 0 : OUString codePtNum = result.copy(pos + 3, 4);
431 0 : if (lcl_isHex(codePtNum[0]) &&
432 0 : lcl_isHex(codePtNum[1]) &&
433 0 : lcl_isHex(codePtNum[2]) &&
434 0 : lcl_isHex(codePtNum[3]))
435 : {
436 0 : OUString codePt(static_cast<sal_Unicode>(codePtNum.toUInt32(16)));
437 0 : result = result.replaceAll(result.copy(pos, 7), codePt, pos);
438 : }
439 0 : pos = result.indexOf("\\U+", pos + 1);
440 0 : }
441 : }
442 0 : return result;
443 : }
444 :
445 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|